Page 1 of 1

Compilation Problem

Posted: Thu Oct 12, 2006 3:14 pm
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?

Re:Compilation Problem

Posted: Thu Oct 12, 2006 3:43 pm
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?

Re:Compilation Problem

Posted: Thu Oct 12, 2006 3:55 pm
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/)

Re:Compilation Problem

Posted: Thu Oct 12, 2006 5:34 pm
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.

Re:Compilation Problem

Posted: Fri Oct 13, 2006 9:14 am
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.

Re:Compilation Problem

Posted: Fri Oct 13, 2006 10:29 am
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.

Re:Compilation Problem

Posted: Sat Oct 14, 2006 4:49 pm
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 = .;
}

Re:Compilation Problem

Posted: Sat Oct 14, 2006 5:46 pm
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.