/** * Load ELF image into memory * * @v image ELF file * @ret rc Return status code */ int elf_load ( struct image *image ) { Elf_Ehdr ehdr; Elf_Phdr phdr; Elf_Off phoff; unsigned int phnum; int rc; /* Image type must already have been set by caller */ assert ( image->type != NULL ); /* Read ELF header */ copy_from_user ( &ehdr, image->data, 0, sizeof ( ehdr ) ); if ( memcmp ( &ehdr.e_ident[EI_MAG0], ELFMAG, SELFMAG ) != 0 ) { DBG ( "Invalid ELF signature\n" ); return -ENOEXEC; } /* Read ELF program headers */ for ( phoff = ehdr.e_phoff , phnum = ehdr.e_phnum ; phnum ; phoff += ehdr.e_phentsize, phnum-- ) { if ( phoff > image->len ) { DBG ( "ELF program header %d outside ELF image\n", phnum ); return -ENOEXEC; } copy_from_user ( &phdr, image->data, phoff, sizeof ( phdr ) ); if ( ( rc = elf_load_segment ( image, &phdr ) ) != 0 ) return rc; } /* Record execution entry point in image private data field */ image->priv.phys = ehdr.e_entry; return 0; }
int load_elf(char *image, UINT *entry, int pretend) { if (!image || !entry) return LOAD_ELF_INVARG; elf32_ehdr* hdr=(elf32_ehdr *)image; elf32_phdr* seg; UINT i; if (hdr->ei_magic!=ELF_MAGIC) return LOAD_ELF_NOELF; if (hdr->ei_version!=EV_CURRENT || hdr->e_version!=EV_CURRENT) return LOAD_ELF_SUPPORT; if (hdr->ei_class!=ELFCLASS32 || hdr->ei_data!=ELFDATA2LSB || hdr->e_machine!=EM_386) return LOAD_ELF_MACHINE; if (hdr->ei_version!=EV_CURRENT || hdr->e_version!=EV_CURRENT || hdr->e_type!=ET_EXEC) return LOAD_ELF_SUPPORT; *entry=hdr->e_entry; for (i=0;i<hdr->e_phnum;i++) { seg=(elf32_phdr* )((UINT)image+hdr->e_phoff+i*(UINT)hdr->e_phentsize); switch (seg->p_type) { case PT_DYNAMIC: case PT_SHLIB: return LOAD_ELF_DYNAMIC; break; case PT_LOAD: if (!pretend) if (elf_load_segment(image,seg)) return LOAD_ELF_LOAD; break; default: break; } } return 0; }
uint32_t elf_load_small(page_directory_t* new_dir, unsigned char* src) { elf_header* hdr = (elf_header*)src; uintptr_t phdr_table_addr = (uint32_t)hdr + hdr->phoff; int segcount = hdr->phnum; if (!segcount) return 0; bool found_loadable_seg = false; //load each segment for (int i = 0; i < segcount; i++) { elf_phdr* segment = (elf_phdr*)(phdr_table_addr + (i * hdr->phentsize)); if (elf_load_segment(new_dir, src, segment)) { found_loadable_seg = true; } } //return entry point if (found_loadable_seg) { return hdr->entry; } return 0; }