Compilation Problem

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
morphycs

Compilation Problem

Post by morphycs »

I have compiled my kernel succesfully, at this stage kernel is just doing an endless loop, kernel binary is 8 KB and booted.
When I made a call to puts() and compiled, the kernel binary became 1 MB and Grub say 'invaled or unsupported executable format'.

Do you think that it is a linking problem?
Shold I post more detailed information?
Midas
Member
Member
Posts: 140
Joined: Sat Jun 24, 2006 4:40 pm
Location: Falkirk, Scotland
Contact:

Re:Compilation Problem

Post by Midas »

More detail would be good. What format are you linking to - ELF?

What's your linker command (and script)?
Also, which toolchain are you using - GCC/binutils' LD?
Regards,
Angus [Óengus] 'Midas' Lepper
User avatar
Brynet-Inc
Member
Member
Posts: 2426
Joined: Tue Oct 17, 2006 9:29 pm
Libera.chat IRC: brynet
Location: Canada
Contact:

Re:Compilation Problem

Post by Brynet-Inc »

Are you using your compilers puts function or did you write your own?

If your writing your kernel in C, you'll need to link with an asm stub..

NASM example..

Code: Select all

[BITS 32]
[global start]
[extern _main] ; Or without the forward slash...depending

start:
   call _main ; Call the main function in your C kernel..
   jmp $ ; Hang the kernel..
You have to write your own C library/functions (Or port existing ones..), You can't link to your compilers C libraries or includes.

You would get more responses if you mention the C compiler your using and your host Operating System.

If you use gcc, Make sure when your compiling the C kernel use the flags -c and -ffreestanding to be sure your not linking with any external libraries.

(And look over the Wiki http://www.osdev.org/osfaq2/)
Image
Twitter: @canadianbryan. Award by smcerm, I stole it. Original was larger.
nick8325
Member
Member
Posts: 200
Joined: Wed Oct 18, 2006 5:49 am

Re:Compilation Problem

Post by nick8325 »

Are you using a linker script? If so, make sure you have a .rodata section in it (this stores constant global variables, e.g. strings like "Hello world" :))

If you don't have it in the linker script, if I remember correctly, ld decides to put it at virtual address 0. So .rodata will be loaded at address 0, and .text will be loaded at ~1MB, and to fit both of those in ld has to make a ~1MB output file...

In the linker, where you have something like

Code: Select all

.text : {
    *(.text)
}
you should replace it with

Code: Select all

.text : {
    *(.text)
    *(.rodata)
}
p.s. If you start getting 1MB files, it might be useful to run objdump -h *.o to see if there are sections in the .o files that are missing from the linker script.
morphycs

Re:Compilation Problem

Post by morphycs »

I wrote all the functions and didn't import them.
I'm using this linker script:
OUTPUT_FORMAT("binary")
ENTRY(start)
phys = 0x00100000;
SECTIONS
{
.text phys : AT(phys) {
code = .;
*(.text)
. = ALIGN(4096);
}
.data : AT(phys + (data - code))
{
data = .;
*(.data)
. = ALIGN(4096);
}
.bss : AT(phys + (bss - code))
{
bss = .;
*(.bss)
. = ALIGN(4096);
}
end = .;
}
and when I added:
*(.rodata)
. = ALIGN(4096);
nothing changed.

In the asm stub, adding underscore infront of main gives this error:
kernel_entry.o:kernel_entry.o:(.text+0x2d): undefined reference to `_main'
I removed it and it compiled fine.

objdump -h *.o:
console.o: file format elf32-i386

Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000371 00000000 00000000 00000040 2**4
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data 00000004 00000000 00000000 000003b4 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000008 00000000 00000000 000003b8 2**2
ALLOC
3 .comment 0000002a 00000000 00000000 000003b8 2**0
CONTENTS, READONLY
4 .note.GNU-stack 00000000 00000000 00000000 000003e2 2**0
CONTENTS, READONLY

kernel_entry.o: file format a.out-i386-linux

Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000034 0000000000000000 0000000000000000 00000020 2**2
CONTENTS, ALLOC, LOAD, RELOC, CODE
1 .data 00000000 0000000000000034 0000000000000034 00000054 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00002000 0000000000000034 0000000000000034 00000000 2**2
ALLOC

kernel.o: file format elf32-i386

Sections:
Idx Name Size VMA LMA File off Algn
0 .text 000000d2 00000000 00000000 00000034 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data 00000000 00000000 00000000 00000108 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 00000108 2**2
ALLOC
3 .rodata.str1.1 00000006 00000000 00000000 00000108 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .comment 0000002a 00000000 00000000 0000010e 2**0
CONTENTS, READONLY
5 .note.GNU-stack 00000000 00000000 00000000 00000138 2**0
CONTENTS, READONLY

stdio.o: file format elf32-i386

Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000071 00000000 00000000 00000034 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data 00000004 00000000 00000000 000000a8 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 000000ac 2**2
ALLOC
3 .comment 0000002a 00000000 00000000 000000ac 2**0
CONTENTS, READONLY
4 .note.GNU-stack 00000000 00000000 00000000 000000d6 2**0
CONTENTS, READONLY
Finally, I'm using gcc, nasm, ld, bochs on Linux.
nick8325
Member
Member
Posts: 200
Joined: Wed Oct 18, 2006 5:49 am

Re:Compilation Problem

Post by nick8325 »

morphycs wrote: 3 .rodata.str1.1 00000006 00000000 00000000 00000108 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
Ah! Sorry. You should put *(.rodata*) instead of *(.rodata). That will match any section name that begins with .rodata. You might want to do the same for .text, .data and .bss as well, I'm not sure.
morphycs

Re:Compilation Problem

Post by morphycs »

Your idea solved the problem and I used it 3 different ways and it succeeded but which one is right.
OUTPUT_FORMAT("binary")
ENTRY(start)
phys = 0x00100000;
SECTIONS
{
.text phys : AT(phys) {
code = .;
*(.text)
. = ALIGN(4096);
}
.rodata phys : AT(phys + (rodata - code))
{
   rodata = .;
   *(.rodata)
   . = ALIGN(4096);
}
.data : AT(phys + (data - code))
{
data = .;
*(.data)
. = ALIGN(4096);
   
}
.bss : AT(phys + (bss - code))
{
bss = .;
*(.bss)
. = ALIGN(4096);
   
}
end = .;
}
OUTPUT_FORMAT("binary")
ENTRY(start)
phys = 0x00100000;
SECTIONS
{
.text phys : AT(phys) {
code = .;
*(.text)
. = ALIGN(4096);
   *(.rodata*)
   . = ALIGN(4096);
}
.data : AT(phys + (data - code))
{
data = .;
*(.data)
. = ALIGN(4096);
   *(.rodata*)
   . = ALIGN(4096);
}
.bss : AT(phys + (bss - code))
{
bss = .;
*(.bss)
. = ALIGN(4096);
   *(.rodata*)
   . = ALIGN(4096);
}
end = .;
}
OUTPUT_FORMAT("binary")
ENTRY(start)
phys = 0x00100000;
SECTIONS
{
.text phys : AT(phys) {
code = .;
*(.text)
*(.rodata*)
. = ALIGN(4096);
}
.data : AT(phys + (data - code))
{
data = .;
*(.data)
*(.rodata*)
. = ALIGN(4096);
}
.bss : AT(phys + (bss - code))
{
bss = .;
*(.bss)
*(.rodata*)
. = ALIGN(4096);
}
end = .;
}
nick8325
Member
Member
Posts: 200
Joined: Wed Oct 18, 2006 5:49 am

Re:Compilation Problem

Post by nick8325 »

All of the ways should work. I'd use the last way (.text and .rodata in the same section), because it doesn't matter if you put them in the same page - it only matters if you put code and writable data in the same page.

(That's because the processor has a cache - it reads the instructions it's going to execute from memory, in advance. If you write to an address that's near to a piece of code, some processors will empty the cache and read all the instructions again, in case the write modified some code. So you shouldn't have writable data near to code, but read-only data doesn't matter.)

Also, I'd remove the ALIGN(4096) at the end of .data - I don't think you need it (I could be wrong, though), and removing it will make the kernel a little bit smaller.
Post Reply