Jump to content
  • Sky
  • Blueberry
  • Slate
  • Blackcurrant
  • Watermelon
  • Strawberry
  • Orange
  • Banana
  • Apple
  • Emerald
  • Chocolate
  • Charcoal
GreaseMonkey

How to load a simple ELF file

Recommended Posts

Here's some definitions from the OCMIPS ELF bootloader which you can use for whatever the hell you like:

static const uint8_t e_ident_match[16+8] = 
	"\x7F" "ELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00"
	"\x02\x00"
	"\x08\x00" // Change this to match your architecture
	"\x01\x00\x00\x00";

struct ElfHeader
{
	uint8_t e_ident[16];
	uint16_t e_type, e_machine;
	uint32_t e_version;
	uint32_t e_entry, e_phoff, e_shoff, e_flags;
	uint16_t e_ehsize;
	uint16_t e_phentsize, e_phnum;
	uint16_t e_shentsize, e_shnum;
	uint16_t e_shstrndx;
};

struct ProgHeader
{
	uint32_t p_type;
	uint32_t p_offset;
	uint32_t p_vaddr;
	uint32_t p_paddr;
	uint32_t p_filesz;
	uint32_t p_memsz;
	uint32_t p_flags;
	uint32_t p_align;
};

#define PT_LOAD 0x00000001
It's only for 32-bit ELF files - 64-bit ELF files have differently-sized fields.

For e_ident_match you'll want to change it to match the first 24 bytes of the ELF you're trying to load, assuming you compiled it correctly.

Here's how I build mocha (note the text-segment bit - this is where your ELF will be loaded):

 

mipsel-none-elf-gcc -nostdlib -fno-builtin-headers -fno-builtin -Os -G0 -msoft-float -Wl,-Ttext-segment=0xA0005000 -o init.elf ${CSRCS} -lc -lgcc && \
cp init.elf "${OUTDIR}/" && \
mipsel-none-elf-strip "${OUTDIR}/init.elf" && \
mipsel-none-elf-objdump -p init.elf && \
ls -l init.elf "${OUTDIR}/init.elf" && \
true
Do not use dynamic linking. Just statically link it at the address you want it. If you want dynamic linking, do that in your main kernel, not in your bootloader. (It's hard. You normally go through the PT_DYNAMIC section and read your processor-specific ELF supplement to help you with the relocation types.)

The general loading process goes like this:

1. Load the header. (Verify the things you want in there.)

2. Use e_phoff to find the program header list, and e_phnum to find out how many program headers there are in the list.

3. Seek to e_phoff, and read e_phnum program header entries.

4. For every program header with a p_type of 1 (PT_LOAD), allocate + zerofill p_memsz bytes at p_vaddr, and if p_filesz is nonzero, read p_filesz bytes from p_offset in the file into p_vaddr in memory.

5. Jump to e_entry... That is:

 

((void (*)(void))(ehdr.e_entry))();
That should be enough to boot a simple ELF from a bootloader. If you want the actual ELF docs, Google is your friend.

Actually building the bootloader typically involves writing a GNU linker script and is outside of the scope of this document.

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use and Privacy Policy.