loading an ELF kernel

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
aladdin

loading an ELF kernel

Post by aladdin »

I'm using a plain binary kernel, end now I want to use an elf kernel.
I replaced this line in my makefile

Code: Select all

kernel:$(KERNOBJS)
ld --oformat binary -Ttext 100000 $^ -o xosker32.xss

by this one

Code: Select all

kernel:$(KERNOBJS)
ld $^ -T kernel.ld -o xosker32.xss
and the content of kernel.ld file is

Code: Select all

OUTPUT_FORMAT("elf32-i386")
ENTRY(start)
   SECTIONS {
      .text 0x100000 : {
         *(.text)
            _etext = .;
         etext = _etext;
      }
      .data : {
         *(.data)
            _edata = .;
         edata = _edata;
      }
      .bss : {
         *(.bss)
            *(COMMON)
            _end = .;
         end = _end;
      }
   }


I'm using a bootloader that loads both kernel and setup codes then jump to setup code
the setup code do some tests switch to pmode, move the kernel to 0x100000 then do a far jump to 0x8:0x100000 where a plain binary copy of the kernel is
supposed to be.

but with the elf kernel (without modifing setup code) the system crash after loading doing the jump,
soafter reading some elf documentations I found where is the entry point (in my case its at offset 0x1000) so I did a far jump to 0x8:0x101000, now the kernel seems to run correctly but it dont print what it must print to the screen, it seems that data are in an incorrect place

so what is the solution tomake all this working correctly ?
must I dosome changes on loaded file (elf kernel) befor the far jump ?
mystran

Re:loading an ELF kernel

Post by mystran »

Does your bootloader understand ELF? If not, and it jumps to simply the begin of the kernel, what happens is that it jump directly into the sequence { \0, 'E', 'L', 'F' } which idenfies ELF binaries. Clearly this is not what you want.

You should try booting it with GRUB, which understands ELF. If that works, you can either start using GRUB permanently, or modify your bootloader to understand ELF.

Btw, if you compile with GCC, you probably want to include .rodata into your .text segment too. GCC uses .rodata for stuff like string constants and such.

ELF is not just a flat binary. It is a format which contains headers and several sections. The headers contain information including the addresses where each of the sections is supposed to be loaded. So if you simply load it as a flat binary, the sections end up into wrong places.
aladdin

Re:loading an ELF kernel

Post by aladdin »

FIXED ;D


after some documentation about plain binary format, elf format and ld scripts I changed my ld script to this :

Code: Select all

OUTPUT_FORMAT("elf32-i386")
ENTRY(start)
   SECTIONS {
       .= 0x101000;
      .text : {
         *(.text)
            _etext = .;
         etext = _etext;
      }
      .rodata : {
         *(.data)
            _edata = .;
         edata = _edata;
      }
      .data : {
         *(.data)
            _edata = .;
         edata = _edata;
      }
      .bss : {
         *(.bss)
            _ebss = .;
         end = _ebss;
      }
   }
All what I had to do is to jump to 0x8:0x101000 addresse from my 2nd stage loader (the program entry point).

Btw, if you compile with GCC, you probably want to include .rodata into your .text segment too. GCC uses .rodata for stuff like string constants and such.
this helped me a lot, thank u mystran ;)


now I have a working ELF kernel, that can be loaded using grub or using my bootloader "XOLO", and I'm very happy :D
mystran

Re:loading an ELF kernel

Post by mystran »

But you didn't get it correct :)

You don't want to create an .rodata section in the binary, (especially not for duplicating the .data section), instead you want to include GCC's .rodata in your .text section...

Something like this:

Code: Select all

SECTIONS
{
    . = 0x101000;
    .text : {
        *(.text)
        *(.rodata*)
    }
    .data : {
        *(.data)
    }
    .bss : {
        *(.bss)
        *(COMMON)
    }
}
Add whatever labels you want (like the end labels). I can't possibly remember right now why the COMMON was there but it seems to be in my ld script so I assume there is a reason of some kind.

Anyway: in LD scripts, the sections you define, are sections included in the final binary. Within the {} of those sections, you tell which sections from the object files go into which sections of the binary.

You don't need a separate .rodata section in your binary (although one won't hurt), but you want to include the .rodata produced by the compiler into one of you sections.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:loading an ELF kernel

Post by Solar »

mystran wrote: I can't possibly remember right now why the COMMON was there but it seems to be in my ld script so I assume there is a reason of some kind.
COMMON holds "common" symbols, like e.g. created with the GAS directive "COMM". (Think globals for ASM.) Those are canonically initialized somewhere in the code, so it makes sense to reserve space for them in .bss (where they don't take up space in the executable binary).

HTH.
Every good solution is obvious once you've found it.
Post Reply