Page 1 of 1

Combining two executables in one ELF file

Posted: Thu Jul 02, 2009 8:26 pm
by NickJohnson
My OS has a somewhat complex booting process, involving the kernel loading a small usermode program (called "libsys") from the initrd, executing it, removing it's own execution code, remapping the initrd to userspace, jumping to libsys, and letting libsys then execute init from the initrd. It would be easier and less redundant for me if I could have GRUB do the actual loading of libsys (no parsing the initrd or ELF file). Let's say the kernel is to be mapped at 0x100000 physical and 0xFF100000 virtual; libsys would be mapped at 0x110000 physical and 0xF8000000 virtual. GRUB would load it into physical memory and then the kernel would move it to 0xF8000000 at the end of the booting process. Could I do this without changing the names of all the ELF segments in libsys and without sharing any symbols between the two programs, but still having both in one executable file? (If so, I would be able to cut out ~300 lines from my kernel, shrinking it down to a total of ~500!)

Here's what I would like:

readelf -l kernel:

Code: Select all

Elf file type is EXEC (Executable file)
Entry point 0xff10000c
There is 1 program header, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x001000 0xff100000 0x00100000 0x08000 0x31740 RWE 0x1000

 Section to Segment mapping:
  Segment Sections...
   00     .text .data .pdata .tdata .ttext .bss 
readelf -l libsys:

Code: Select all

Elf file type is EXEC (Executable file)
Entry point 0xf8000000
There is 1 program header, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x001000 0xf8000000 0x00110000 0x01195 0x01220 RWE 0x1000

 Section to Segment mapping:
  Segment Sections...
   00     .text .data .bss 
and in the end, it should be something like this:

Code: Select all

Elf file type is EXEC (Executable file)
Entry point 0xff10000c
There are 2 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x001000 0xff100000 0x00100000 0x08000 0x31740 RWE 0x1000
  LOAD           0x001000 0xf8000000 0x00110000 0x01195 0x01220 RWE 0x1000

Impossible, or no?

Re: Combining two executables in one ELF file

Posted: Fri Jul 03, 2009 9:10 am
by gravaera
I haven't finished reading the ELF spec PDF fully yet, (I'm on page 19 or so), but from what I've read so far, you could very well split the Program header however you like, as multiple indexes into the Program header. ELF seems, so far, to be EXTREMELY versatile.

For my OS, I intend to do something similar: the file that GRUB currently loads is nothing more than a Kernel Loader, and not the Kernel itself. In fact, my Kernel will be nothing more than a series of linked Executables and Shared objects in memory that can be loaded and unloaded as deemed necessary by an algorithm I'm working on.

But instead of loading a Multi-Program Header file, I'm thinking of just having the modules loaded from the HDD into the memory space. It makes life at least ten times easier.

But yes, I DO believe that ELF supports multiple PHeader index entries.

Re: Combining two executables in one ELF file

Posted: Fri Jul 03, 2009 11:47 am
by salil_bhagurkar
Firstly your 'executing libsys' and 'jumping to it' are the same, but you mention them at different stages.

Second, Grub has built in support of loading modules, using 'module' command.

Re: Combining two executables in one ELF file

Posted: Fri Jul 03, 2009 12:38 pm
by NickJohnson
salil_bhagurkar wrote:Firstly your 'executing libsys' and 'jumping to it' are the same, but you mention them at different stages.

Second, Grub has built in support of loading modules, using 'module' command.
By executing, I mean loading from an ELF file into the proper place in memory *and* jumping to it. The loading part is the more complex by far. If I don't have to deal with loading libsys, I can omit the initrd handling code altogether. I also want to try and eliminate the ELF loading code from the kernel, both for simplicity and to decouple the binary format from the kernel.

I'm already using the module feature to load the initrd. My current mechanism works, but I'm just trying to find a way to do it more easily.

So, as far as I can tell, there isn't any sort of feature in a normal ELF linker that would allow this, but it's possible to *have* an ELF file that does this. I might just postpone this idea until I have time to modify my linker (probably when I'm writing my native toolchain, sometime next year).