Elf loader implementation weird bug

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
chickendinner
Posts: 11
Joined: Thu Aug 01, 2013 9:47 am

Elf loader implementation weird bug

Post by chickendinner »

I'm working on a simple flat binary stub that loads my kernel file into it's upper half memory and runs. I've managed to get this to work (kind of) but with a very odd bug.

The entry point point appears to be wrong and i have to minus 0x120 from it to get the thing to run. This i found out after hours with a hex editor and searching through the binary in memory finding out where the first opcode is. However this doesn't seem to be due to me loading the program segment to the wrong location, if I load the program segment 0x120 bytes earlier, the entry point is in the right place now but the code seems to be written to be in the former location so no longer works. So essentially the symbols seem to be 0x120 out and may have nothing to do with the loading of elf file at all but rather the linker.

Elf-loader (i'm aware that it might not work with multiple program section atm, but there's only one in my test kernel so that case hasn't been tested yet):

Code: Select all

uint32_t _loader_parse_elf() {
	
	//Header information
	Elf32_Ehdr *elf_header = (Elf32_Ehdr*) KERNEL_ELF;	
	
	//Loop through each program segment
	Elf32_Phdr *program_header = (Elf32_Phdr*) (KERNEL_ELF + (elf_header->e_phoff/4));
	for(uint_fast16_t i = 0; i < elf_header->e_phnum; i++) {
	
		//Only parse loadable ones
		if(program_header->p_type == 1) {
	
			//Get info
			uint8_t *src = (uint8_t*) (KERNEL_ELF + program_header->p_offset);
			static uint8_t *dst = (uint8_t*) KERNEL_BUILT;
			for(uint32_t i = 0; i < program_header->p_filesz; i++) *dst++ = *src++; 
		
			//TODO zero out BSS
			
			//Page in the memory
			_loader_page_memory((uint32_t*) KERNEL_BUILT, program_header->p_vaddr, program_header->p_memsz);		
			
		}
		
		//Jump to next entry
		program_header += elf_header->e_phentsize;
		
	}
	
	//Return entry point
	return elf_header->e_entry;
}
The file that i use for testing this is extremely simple:

Linker:

Code: Select all

/* link-arm-eabi.ld - linker script for arm eabi */
ENTRY(main)
 
SECTIONS
{
	. = 0x80000000;
	
	/* text */
    .text : {*(.text)}
	
	/* Read only data */
    .rodata : {*(.rodata)}
 
	/* Data */ 
	.data : {*(.data)}
 
	/* BSS */
    .bss : {*(.bss)}
	
}
code:

Code: Select all

void main() {
	//light LED
	*LED_SELECT = 1 << 18;
	*LED_ON = 1 << 16;	
	while(1);
}
It's for a raspberry pi so the main code simply lights one of the LED's on the board to confirm it works.

I think i'm missing obvious but i have some theories to test when i get back home.

1. See if all symbols are 0x120 out or just the entrypoint. Have main call another method to turn on the LED and see if variables can be accessed.
2. (EDIT: Nope) I think i might need to map my kernel entrypoint into the .text.startup section that the elf file creates before the .text. I think the e_entrypoint simply points to the start of the that code section and i was supposed to put my main in there.
3. I'll see if the elf file is actually bootable by U-boot bootelf to see if that is the problem (it only works with identity paging though so i'll have to move the load address lower). Then i'll know for sure it's my elf loader code or the symbols being wrong.
User avatar
dozniak
Member
Member
Posts: 723
Joined: Thu Jul 12, 2012 7:29 am
Location: Tallinn, Estonia

Re: Elf loader implementation weird bug

Post by dozniak »

Code: Select all

Elf32_Phdr *program_header = (Elf32_Phdr*) (KERNEL_ELF + (elf_header->e_phoff/4));
This /4 looks very suspicious.
Learn to read.
Post Reply