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?
Compilation Problem
Re:Compilation Problem
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?
What's your linker command (and script)?
Also, which toolchain are you using - GCC/binutils' LD?
Regards,
Angus [Óengus] 'Midas' Lepper
Angus [Óengus] 'Midas' Lepper
- Brynet-Inc
- Member
- Posts: 2426
- Joined: Tue Oct 17, 2006 9:29 pm
- Libera.chat IRC: brynet
- Location: Canada
- Contact:
Re:Compilation Problem
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..
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/)
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 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
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 likeyou should replace it with
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.
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)
}
Code: Select all
.text : {
*(.text)
*(.rodata)
}
Re:Compilation Problem
I wrote all the functions and didn't import them.
I'm using this linker script:
*(.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:
I'm using this linker script:
and when I added: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 = .;
}
*(.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:
Finally, I'm using gcc, nasm, ld, bochs on Linux.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
Re:Compilation Problem
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 wrote: 3 .rodata.str1.1 00000006 00000000 00000000 00000108 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
Re:Compilation Problem
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
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.
(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.