|
|
1.1 ! root 1: /****************************************************************************** ! 2: * Copyright (c) 2004, 2011 IBM Corporation ! 3: * All rights reserved. ! 4: * This program and the accompanying materials ! 5: * are made available under the terms of the BSD License ! 6: * which accompanies this distribution, and is available at ! 7: * http://www.opensource.org/licenses/bsd-license.php ! 8: * ! 9: * Contributors: ! 10: * IBM Corporation - initial implementation ! 11: *****************************************************************************/ ! 12: ! 13: /* ! 14: * 32-bit ELF loader ! 15: */ ! 16: ! 17: #include <string.h> ! 18: #include <libelf.h> ! 19: ! 20: struct ehdr32 { ! 21: uint32_t ei_ident; ! 22: uint8_t ei_class; ! 23: uint8_t ei_data; ! 24: uint8_t ei_version; ! 25: uint8_t ei_pad[9]; ! 26: uint16_t e_type; ! 27: uint16_t e_machine; ! 28: uint32_t e_version; ! 29: uint32_t e_entry; ! 30: uint32_t e_phoff; ! 31: uint32_t e_shoff; ! 32: uint32_t e_flags; ! 33: uint16_t e_ehsize; ! 34: uint16_t e_phentsize; ! 35: uint16_t e_phnum; ! 36: uint16_t e_shentsize; ! 37: uint16_t e_shnum; ! 38: uint16_t e_shstrndx; ! 39: }; ! 40: ! 41: struct phdr32 { ! 42: uint32_t p_type; ! 43: uint32_t p_offset; ! 44: uint32_t p_vaddr; ! 45: uint32_t p_paddr; ! 46: uint32_t p_filesz; ! 47: uint32_t p_memsz; ! 48: uint32_t p_flags; ! 49: uint32_t p_align; ! 50: }; ! 51: ! 52: ! 53: static struct phdr32* ! 54: get_phdr32(void *file_addr) ! 55: { ! 56: return (struct phdr32 *) (((unsigned char *)file_addr) ! 57: + ((struct ehdr32 *)file_addr)->e_phoff); ! 58: } ! 59: ! 60: static void ! 61: load_segment(void *file_addr, struct phdr32 *phdr, signed long offset, ! 62: int (*pre_load)(void*, long), ! 63: void (*post_load)(void*, long)) ! 64: { ! 65: unsigned long src = phdr->p_offset + (unsigned long) file_addr; ! 66: unsigned long destaddr; ! 67: ! 68: destaddr = (unsigned long)phdr->p_paddr; ! 69: destaddr = destaddr + offset; ! 70: ! 71: /* check if we're allowed to copy */ ! 72: if (pre_load != NULL) { ! 73: if (pre_load((void*)destaddr, phdr->p_memsz) != 0) ! 74: return; ! 75: } ! 76: ! 77: /* copy into storage */ ! 78: memmove((void *)destaddr, (void *)src, phdr->p_filesz); ! 79: ! 80: /* clear bss */ ! 81: memset((void *)(destaddr + phdr->p_filesz), 0, ! 82: phdr->p_memsz - phdr->p_filesz); ! 83: ! 84: if (phdr->p_memsz && post_load) { ! 85: post_load((void*)destaddr, phdr->p_memsz); ! 86: } ! 87: } ! 88: ! 89: unsigned int ! 90: elf_load_segments32(void *file_addr, signed long offset, ! 91: int (*pre_load)(void*, long), ! 92: void (*post_load)(void*, long)) ! 93: { ! 94: struct ehdr32 *ehdr = (struct ehdr32 *) file_addr; ! 95: /* Calculate program header address */ ! 96: struct phdr32 *phdr = get_phdr32(file_addr); ! 97: int i; ! 98: signed int virt2phys = 0; /* Offset between virtual and physical */ ! 99: ! 100: /* loop e_phnum times */ ! 101: for (i = 0; i <= ehdr->e_phnum; i++) { ! 102: /* PT_LOAD ? */ ! 103: if (phdr->p_type == 1) { ! 104: if (!virt2phys) { ! 105: virt2phys = phdr->p_paddr - phdr->p_vaddr; ! 106: } ! 107: /* copy segment */ ! 108: load_segment(file_addr, phdr, offset, pre_load, ! 109: post_load); ! 110: } ! 111: /* step to next header */ ! 112: phdr = (struct phdr32 *)(((uint8_t *)phdr) + ehdr->e_phentsize); ! 113: } ! 114: ! 115: /* Entry point is always a virtual address, so translate it ! 116: * to physical before returning it */ ! 117: return ehdr->e_entry + virt2phys; ! 118: } ! 119: ! 120: /** ! 121: * Return the base address for loading (i.e. the address of the first PT_LOAD ! 122: * segment) ! 123: * @param file_addr pointer to the ELF file in memory ! 124: * @return the base address ! 125: */ ! 126: long ! 127: elf_get_base_addr32(void *file_addr) ! 128: { ! 129: struct ehdr32 *ehdr = (struct ehdr32 *) file_addr; ! 130: struct phdr32 *phdr = get_phdr32(file_addr); ! 131: int i; ! 132: ! 133: /* loop e_phnum times */ ! 134: for (i = 0; i <= ehdr->e_phnum; i++) { ! 135: /* PT_LOAD ? */ ! 136: if (phdr->p_type == 1) { ! 137: return phdr->p_paddr; ! 138: } ! 139: /* step to next header */ ! 140: phdr = (struct phdr32 *)(((uint8_t *)phdr) + ehdr->e_phentsize); ! 141: } ! 142: ! 143: return 0; ! 144: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.