19c6f9240SPeter Wemm /* 29c6f9240SPeter Wemm * Copyright (c) 2000, Boris Popov 39c6f9240SPeter Wemm * All rights reserved. 49c6f9240SPeter Wemm * 59c6f9240SPeter Wemm * Redistribution and use in source and binary forms, with or without 69c6f9240SPeter Wemm * modification, are permitted provided that the following conditions 79c6f9240SPeter Wemm * are met: 89c6f9240SPeter Wemm * 1. Redistributions of source code must retain the above copyright 99c6f9240SPeter Wemm * notice, this list of conditions and the following disclaimer. 109c6f9240SPeter Wemm * 2. Redistributions in binary form must reproduce the above copyright 119c6f9240SPeter Wemm * notice, this list of conditions and the following disclaimer in the 129c6f9240SPeter Wemm * documentation and/or other materials provided with the distribution. 139c6f9240SPeter Wemm * 3. All advertising materials mentioning features or use of this software 149c6f9240SPeter Wemm * must display the following acknowledgement: 159c6f9240SPeter Wemm * This product includes software developed by Boris Popov. 169c6f9240SPeter Wemm * 4. Neither the name of the author nor the names of any co-contributors 179c6f9240SPeter Wemm * may be used to endorse or promote products derived from this software 189c6f9240SPeter Wemm * without specific prior written permission. 199c6f9240SPeter Wemm * 209c6f9240SPeter Wemm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 219c6f9240SPeter Wemm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 229c6f9240SPeter Wemm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 239c6f9240SPeter Wemm * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 249c6f9240SPeter Wemm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 259c6f9240SPeter Wemm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 269c6f9240SPeter Wemm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 279c6f9240SPeter Wemm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 289c6f9240SPeter Wemm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 299c6f9240SPeter Wemm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 309c6f9240SPeter Wemm * SUCH DAMAGE. 319c6f9240SPeter Wemm * 329c6f9240SPeter Wemm * $FreeBSD$ 339c6f9240SPeter Wemm */ 349c6f9240SPeter Wemm 359c6f9240SPeter Wemm #include <sys/param.h> 369c6f9240SPeter Wemm #include <sys/linker.h> 379c6f9240SPeter Wemm #include <string.h> 38754a3615SPeter Wemm #include <stdio.h> 39754a3615SPeter Wemm #include <stdlib.h> 40754a3615SPeter Wemm #include <unistd.h> 41754a3615SPeter Wemm #include <errno.h> 42754a3615SPeter Wemm #include <fcntl.h> 439c6f9240SPeter Wemm #include <machine/elf.h> 449c6f9240SPeter Wemm #define FREEBSD_ELF 459c6f9240SPeter Wemm #include <link.h> 469c6f9240SPeter Wemm 479c6f9240SPeter Wemm #include <err.h> 489c6f9240SPeter Wemm 499c6f9240SPeter Wemm #include "ef.h" 509c6f9240SPeter Wemm 5187e5cd7cSMike Heffner static void ef_print_phdr(Elf_Phdr *); 5287e5cd7cSMike Heffner static u_long ef_get_offset(elf_file_t, Elf_Off); 5387e5cd7cSMike Heffner static int ef_parse_dynamic(elf_file_t); 5487e5cd7cSMike Heffner 559c6f9240SPeter Wemm void 569c6f9240SPeter Wemm ef_print_phdr(Elf_Phdr *phdr) 579c6f9240SPeter Wemm { 589c6f9240SPeter Wemm 599c6f9240SPeter Wemm if ((phdr->p_flags & PF_W) == 0) { 609c6f9240SPeter Wemm printf("text=0x%lx ", (long)phdr->p_filesz); 619c6f9240SPeter Wemm } else { 629c6f9240SPeter Wemm printf("data=0x%lx", (long)phdr->p_filesz); 639c6f9240SPeter Wemm if (phdr->p_filesz < phdr->p_memsz) 649c6f9240SPeter Wemm printf("+0x%lx", (long)(phdr->p_memsz - phdr->p_filesz)); 659c6f9240SPeter Wemm printf(" "); 669c6f9240SPeter Wemm } 679c6f9240SPeter Wemm } 689c6f9240SPeter Wemm 699c6f9240SPeter Wemm u_long 709c6f9240SPeter Wemm ef_get_offset(elf_file_t ef, Elf_Off off) 719c6f9240SPeter Wemm { 729c6f9240SPeter Wemm Elf_Phdr *ph; 739c6f9240SPeter Wemm int i; 749c6f9240SPeter Wemm 759c6f9240SPeter Wemm for (i = 0; i < ef->ef_nsegs; i++) { 769c6f9240SPeter Wemm ph = ef->ef_segs[i]; 779c6f9240SPeter Wemm if (off >= ph->p_vaddr && off < ph->p_vaddr + ph->p_memsz) { 789c6f9240SPeter Wemm return ph->p_offset + (off - ph->p_vaddr); 799c6f9240SPeter Wemm } 809c6f9240SPeter Wemm } 819c6f9240SPeter Wemm return 0; 829c6f9240SPeter Wemm } 839c6f9240SPeter Wemm 849c6f9240SPeter Wemm /* 859c6f9240SPeter Wemm * next three functions copied from link_elf.c 869c6f9240SPeter Wemm */ 879c6f9240SPeter Wemm static unsigned long 889c6f9240SPeter Wemm elf_hash(const char *name) 899c6f9240SPeter Wemm { 909c6f9240SPeter Wemm const unsigned char *p = (const unsigned char *) name; 919c6f9240SPeter Wemm unsigned long h = 0; 929c6f9240SPeter Wemm unsigned long g; 939c6f9240SPeter Wemm 949c6f9240SPeter Wemm while (*p != '\0') { 959c6f9240SPeter Wemm h = (h << 4) + *p++; 969c6f9240SPeter Wemm if ((g = h & 0xf0000000) != 0) 979c6f9240SPeter Wemm h ^= g >> 24; 989c6f9240SPeter Wemm h &= ~g; 999c6f9240SPeter Wemm } 1009c6f9240SPeter Wemm return h; 1019c6f9240SPeter Wemm } 1029c6f9240SPeter Wemm 1039c6f9240SPeter Wemm int 1049c6f9240SPeter Wemm ef_lookup_symbol(elf_file_t ef, const char* name, Elf_Sym** sym) 1059c6f9240SPeter Wemm { 1069c6f9240SPeter Wemm unsigned long symnum; 1079c6f9240SPeter Wemm Elf_Sym* symp; 1089c6f9240SPeter Wemm char *strp; 1099c6f9240SPeter Wemm unsigned long hash; 1109c6f9240SPeter Wemm 1119c6f9240SPeter Wemm /* First, search hashed global symbols */ 1129c6f9240SPeter Wemm hash = elf_hash(name); 1139c6f9240SPeter Wemm symnum = ef->ef_buckets[hash % ef->ef_nbuckets]; 1149c6f9240SPeter Wemm 1159c6f9240SPeter Wemm while (symnum != STN_UNDEF) { 1169c6f9240SPeter Wemm if (symnum >= ef->ef_nchains) { 1179c6f9240SPeter Wemm warnx("ef_lookup_symbol: file %s have corrupted symbol table\n", 1189c6f9240SPeter Wemm ef->ef_name); 1199c6f9240SPeter Wemm return ENOENT; 1209c6f9240SPeter Wemm } 1219c6f9240SPeter Wemm 1229c6f9240SPeter Wemm symp = ef->ef_symtab + symnum; 1239c6f9240SPeter Wemm if (symp->st_name == 0) { 1249c6f9240SPeter Wemm warnx("ef_lookup_symbol: file %s have corrupted symbol table\n", 1259c6f9240SPeter Wemm ef->ef_name); 1269c6f9240SPeter Wemm return ENOENT; 1279c6f9240SPeter Wemm } 1289c6f9240SPeter Wemm 1299c6f9240SPeter Wemm strp = ef->ef_strtab + symp->st_name; 1309c6f9240SPeter Wemm 1319c6f9240SPeter Wemm if (strcmp(name, strp) == 0) { 1329c6f9240SPeter Wemm if (symp->st_shndx != SHN_UNDEF || 1339c6f9240SPeter Wemm (symp->st_value != 0 && 1349c6f9240SPeter Wemm ELF_ST_TYPE(symp->st_info) == STT_FUNC)) { 1359c6f9240SPeter Wemm *sym = symp; 1369c6f9240SPeter Wemm return 0; 1379c6f9240SPeter Wemm } else 1389c6f9240SPeter Wemm return ENOENT; 1399c6f9240SPeter Wemm } 1409c6f9240SPeter Wemm 1419c6f9240SPeter Wemm symnum = ef->ef_chains[symnum]; 1429c6f9240SPeter Wemm } 1439c6f9240SPeter Wemm 1449c6f9240SPeter Wemm return ENOENT; 1459c6f9240SPeter Wemm } 1469c6f9240SPeter Wemm 1479c6f9240SPeter Wemm int 1489c6f9240SPeter Wemm ef_parse_dynamic(elf_file_t ef) 1499c6f9240SPeter Wemm { 1509c6f9240SPeter Wemm Elf_Dyn *dp; 151f23aa297SPeter Wemm Elf_Hashelt hashhdr[2]; 1529c6f9240SPeter Wemm /* int plttype = DT_REL;*/ 1539c6f9240SPeter Wemm int error; 1541eed250aSJake Burkholder Elf_Off rel_off; 1551eed250aSJake Burkholder Elf_Off rela_off; 1561eed250aSJake Burkholder int rel_sz; 1571eed250aSJake Burkholder int rela_sz; 1581eed250aSJake Burkholder int rel_entry; 1591eed250aSJake Burkholder int rela_entry; 1609c6f9240SPeter Wemm 1611eed250aSJake Burkholder rel_off = rela_off = 0; 1621eed250aSJake Burkholder rel_sz = rela_sz = 0; 1631eed250aSJake Burkholder rel_entry = rela_entry = 0; 1649c6f9240SPeter Wemm for (dp = ef->ef_dyn; dp->d_tag != DT_NULL; dp++) { 1659c6f9240SPeter Wemm switch (dp->d_tag) { 1669c6f9240SPeter Wemm case DT_HASH: 1679c6f9240SPeter Wemm error = ef_read(ef, ef_get_offset(ef, dp->d_un.d_ptr), 1689c6f9240SPeter Wemm sizeof(hashhdr), hashhdr); 1699c6f9240SPeter Wemm if (error) { 1709c6f9240SPeter Wemm warnx("can't read hash header (%lx)", 1719c6f9240SPeter Wemm ef_get_offset(ef, dp->d_un.d_ptr)); 1729c6f9240SPeter Wemm return error; 1739c6f9240SPeter Wemm } 1749c6f9240SPeter Wemm ef->ef_nbuckets = hashhdr[0]; 1759c6f9240SPeter Wemm ef->ef_nchains = hashhdr[1]; 1769c6f9240SPeter Wemm error = ef_read_entry(ef, -1, 177f23aa297SPeter Wemm (hashhdr[0] + hashhdr[1]) * sizeof(Elf_Hashelt), 1789c6f9240SPeter Wemm (void**)&ef->ef_hashtab); 1799c6f9240SPeter Wemm if (error) { 1809c6f9240SPeter Wemm warnx("can't read hash table"); 1819c6f9240SPeter Wemm return error; 1829c6f9240SPeter Wemm } 1839c6f9240SPeter Wemm ef->ef_buckets = ef->ef_hashtab; 1849c6f9240SPeter Wemm ef->ef_chains = ef->ef_buckets + ef->ef_nbuckets; 1859c6f9240SPeter Wemm break; 1869c6f9240SPeter Wemm case DT_STRTAB: 1879c6f9240SPeter Wemm ef->ef_stroff = dp->d_un.d_ptr; 1889c6f9240SPeter Wemm break; 1899c6f9240SPeter Wemm case DT_STRSZ: 1909c6f9240SPeter Wemm ef->ef_strsz = dp->d_un.d_val; 1919c6f9240SPeter Wemm break; 1929c6f9240SPeter Wemm case DT_SYMTAB: 1939c6f9240SPeter Wemm ef->ef_symoff = dp->d_un.d_ptr; 1949c6f9240SPeter Wemm break; 1959c6f9240SPeter Wemm case DT_SYMENT: 1969c6f9240SPeter Wemm if (dp->d_un.d_val != sizeof(Elf_Sym)) 1979c6f9240SPeter Wemm return EFTYPE; 1989c6f9240SPeter Wemm break; 1991eed250aSJake Burkholder case DT_REL: 2001eed250aSJake Burkholder if (rel_off != 0) 2011eed250aSJake Burkholder warnx("second DT_REL entry ignored"); 2021eed250aSJake Burkholder rel_off = dp->d_un.d_ptr; 2031eed250aSJake Burkholder break; 2041eed250aSJake Burkholder case DT_RELSZ: 2051eed250aSJake Burkholder if (rel_sz != 0) 2061eed250aSJake Burkholder warnx("second DT_RELSZ entry ignored"); 2071eed250aSJake Burkholder rel_sz = dp->d_un.d_val; 2081eed250aSJake Burkholder break; 2091eed250aSJake Burkholder case DT_RELENT: 2101eed250aSJake Burkholder if (rel_entry != 0) 2111eed250aSJake Burkholder warnx("second DT_RELENT entry ignored"); 2121eed250aSJake Burkholder rel_entry = dp->d_un.d_val; 2131eed250aSJake Burkholder break; 2141eed250aSJake Burkholder case DT_RELA: 2151eed250aSJake Burkholder if (rela_off != 0) 2161eed250aSJake Burkholder warnx("second DT_RELA entry ignored"); 2171eed250aSJake Burkholder rela_off = dp->d_un.d_ptr; 2181eed250aSJake Burkholder break; 2191eed250aSJake Burkholder case DT_RELASZ: 2201eed250aSJake Burkholder if (rela_sz != 0) 2211eed250aSJake Burkholder warnx("second DT_RELASZ entry ignored"); 2221eed250aSJake Burkholder rela_sz = dp->d_un.d_val; 2231eed250aSJake Burkholder break; 2241eed250aSJake Burkholder case DT_RELAENT: 2251eed250aSJake Burkholder if (rela_entry != 0) 2261eed250aSJake Burkholder warnx("second DT_RELAENT entry ignored"); 2271eed250aSJake Burkholder rela_entry = dp->d_un.d_val; 2281eed250aSJake Burkholder break; 2299c6f9240SPeter Wemm } 2309c6f9240SPeter Wemm } 2319c6f9240SPeter Wemm if (ef->ef_symoff == 0) { 2329c6f9240SPeter Wemm warnx("%s: no .dynsym section found\n", ef->ef_name); 2339c6f9240SPeter Wemm return EFTYPE; 2349c6f9240SPeter Wemm } 2359c6f9240SPeter Wemm if (ef->ef_stroff == 0) { 2369c6f9240SPeter Wemm warnx("%s: no .dynstr section found\n", ef->ef_name); 2379c6f9240SPeter Wemm return EFTYPE; 2389c6f9240SPeter Wemm } 2399c6f9240SPeter Wemm if (ef_read_entry(ef, ef_get_offset(ef, ef->ef_symoff), 2409c6f9240SPeter Wemm ef->ef_nchains * sizeof(Elf_Sym), 2419c6f9240SPeter Wemm (void**)&ef->ef_symtab) != 0) { 2429c6f9240SPeter Wemm if (ef->ef_verbose) 2439c6f9240SPeter Wemm warnx("%s: can't load .dynsym section (0x%lx)", 2449c6f9240SPeter Wemm ef->ef_name, (long)ef->ef_symoff); 2459c6f9240SPeter Wemm return EIO; 2469c6f9240SPeter Wemm } 2479c6f9240SPeter Wemm if (ef_read_entry(ef, ef_get_offset(ef, ef->ef_stroff), ef->ef_strsz, 2489c6f9240SPeter Wemm (void**)&ef->ef_strtab) != 0) { 2499c6f9240SPeter Wemm warnx("can't load .dynstr section"); 2509c6f9240SPeter Wemm return EIO; 2519c6f9240SPeter Wemm } 2521eed250aSJake Burkholder if (rel_off != 0) { 2531eed250aSJake Burkholder if (rel_entry == 0) { 2541eed250aSJake Burkholder warnx("%s: no DT_RELENT for DT_REL", ef->ef_name); 2551eed250aSJake Burkholder return (EFTYPE); 2561eed250aSJake Burkholder } 2571eed250aSJake Burkholder if (rel_entry != sizeof(Elf_Rel)) { 2581eed250aSJake Burkholder warnx("%s: inconsistent DT_RELENT value", 2591eed250aSJake Burkholder ef->ef_name); 2601eed250aSJake Burkholder return (EFTYPE); 2611eed250aSJake Burkholder } 2621eed250aSJake Burkholder if (rel_sz % rel_entry != 0) { 2631eed250aSJake Burkholder warnx("%s: inconsistent values for DT_RELSZ and " 2641eed250aSJake Burkholder "DT_RELENT", ef->ef_name); 2651eed250aSJake Burkholder return (EFTYPE); 2661eed250aSJake Burkholder } 2671eed250aSJake Burkholder if (ef_read_entry(ef, ef_get_offset(ef, rel_off), rel_sz, 2681eed250aSJake Burkholder (void **)&ef->ef_rel) != 0) { 2691eed250aSJake Burkholder warnx("%s: cannot load DT_REL section", ef->ef_name); 2701eed250aSJake Burkholder return (EIO); 2711eed250aSJake Burkholder } 2721eed250aSJake Burkholder ef->ef_relsz = rel_sz / rel_entry; 2731eed250aSJake Burkholder if (ef->ef_verbose) 2741eed250aSJake Burkholder warnx("%s: %d REL entries", ef->ef_name, 2751eed250aSJake Burkholder ef->ef_relsz); 2761eed250aSJake Burkholder } 2771eed250aSJake Burkholder if (rela_off != 0) { 2781eed250aSJake Burkholder if (rela_entry == 0) { 2791eed250aSJake Burkholder warnx("%s: no DT_RELAENT for DT_RELA", ef->ef_name); 2801eed250aSJake Burkholder return (EFTYPE); 2811eed250aSJake Burkholder } 2821eed250aSJake Burkholder if (rela_entry != sizeof(Elf_Rela)) { 2831eed250aSJake Burkholder warnx("%s: inconsistent DT_RELAENT value", 2841eed250aSJake Burkholder ef->ef_name); 2851eed250aSJake Burkholder return (EFTYPE); 2861eed250aSJake Burkholder } 2871eed250aSJake Burkholder if (rela_sz % rela_entry != 0) { 2881eed250aSJake Burkholder warnx("%s: inconsistent values for DT_RELASZ and " 2891eed250aSJake Burkholder "DT_RELAENT", ef->ef_name); 2901eed250aSJake Burkholder return (EFTYPE); 2911eed250aSJake Burkholder } 2921eed250aSJake Burkholder if (ef_read_entry(ef, ef_get_offset(ef, rela_off), rela_sz, 2931eed250aSJake Burkholder (void **)&ef->ef_rela) != 0) { 2941eed250aSJake Burkholder warnx("%s: cannot load DT_RELA section", ef->ef_name); 2951eed250aSJake Burkholder return (EIO); 2961eed250aSJake Burkholder } 2971eed250aSJake Burkholder ef->ef_relasz = rela_sz / rela_entry; 2981eed250aSJake Burkholder if (ef->ef_verbose) 2991eed250aSJake Burkholder warnx("%s: %d RELA entries", ef->ef_name, 3001eed250aSJake Burkholder ef->ef_relasz); 3011eed250aSJake Burkholder } 3029c6f9240SPeter Wemm return 0; 3039c6f9240SPeter Wemm } 3049c6f9240SPeter Wemm 3059c6f9240SPeter Wemm int 3069c6f9240SPeter Wemm ef_read(elf_file_t ef, Elf_Off offset, size_t len, void*dest) 3079c6f9240SPeter Wemm { 30887e5cd7cSMike Heffner ssize_t r; 3099c6f9240SPeter Wemm 31087e5cd7cSMike Heffner if (offset != (Elf_Off)-1) { 3119c6f9240SPeter Wemm if (lseek(ef->ef_fd, offset, SEEK_SET) == -1) 3129c6f9240SPeter Wemm return EIO; 3139c6f9240SPeter Wemm } 31487e5cd7cSMike Heffner 31587e5cd7cSMike Heffner r = read(ef->ef_fd, dest, len); 31687e5cd7cSMike Heffner if (r != -1 && (size_t)r == len) 31787e5cd7cSMike Heffner return 0; 31887e5cd7cSMike Heffner else 31987e5cd7cSMike Heffner return EIO; 3209c6f9240SPeter Wemm } 3219c6f9240SPeter Wemm 3229c6f9240SPeter Wemm int 3239c6f9240SPeter Wemm ef_read_entry(elf_file_t ef, Elf_Off offset, size_t len, void**ptr) 3249c6f9240SPeter Wemm { 3259c6f9240SPeter Wemm int error; 3269c6f9240SPeter Wemm 3279c6f9240SPeter Wemm *ptr = malloc(len); 3289c6f9240SPeter Wemm if (*ptr == NULL) 3299c6f9240SPeter Wemm return ENOMEM; 3309c6f9240SPeter Wemm error = ef_read(ef, offset, len, *ptr); 3319c6f9240SPeter Wemm if (error) 3329c6f9240SPeter Wemm free(*ptr); 3339c6f9240SPeter Wemm return error; 3349c6f9240SPeter Wemm } 3359c6f9240SPeter Wemm 3369c6f9240SPeter Wemm int 3379c6f9240SPeter Wemm ef_seg_read(elf_file_t ef, Elf_Off offset, size_t len, void*dest) 3389c6f9240SPeter Wemm { 3399c6f9240SPeter Wemm u_long ofs = ef_get_offset(ef, offset); 3409c6f9240SPeter Wemm 3419c6f9240SPeter Wemm if (ofs == 0) { 3429c6f9240SPeter Wemm if (ef->ef_verbose) 3439c6f9240SPeter Wemm warnx("ef_seg_read(%s): zero offset (%lx:%ld)", 3449c6f9240SPeter Wemm ef->ef_name, (long)offset, ofs); 3459c6f9240SPeter Wemm return EFAULT; 3469c6f9240SPeter Wemm } 3479c6f9240SPeter Wemm return ef_read(ef, ofs, len, dest); 3489c6f9240SPeter Wemm } 3499c6f9240SPeter Wemm 3509c6f9240SPeter Wemm int 3511eed250aSJake Burkholder ef_seg_read_rel(elf_file_t ef, Elf_Off offset, size_t len, void*dest) 3521eed250aSJake Burkholder { 3531eed250aSJake Burkholder u_long ofs = ef_get_offset(ef, offset); 3541eed250aSJake Burkholder int error; 3551eed250aSJake Burkholder 3561eed250aSJake Burkholder if (ofs == 0) { 3571eed250aSJake Burkholder if (ef->ef_verbose) 3581eed250aSJake Burkholder warnx("ef_seg_read(%s): zero offset (%lx:%ld)", 3591eed250aSJake Burkholder ef->ef_name, (long)offset, ofs); 3601eed250aSJake Burkholder return EFAULT; 3611eed250aSJake Burkholder } 3621eed250aSJake Burkholder if ((error = ef_read(ef, ofs, len, dest)) != 0) 3631eed250aSJake Burkholder return (error); 3641eed250aSJake Burkholder return (ef_reloc(ef, offset, len, dest)); 3651eed250aSJake Burkholder } 3661eed250aSJake Burkholder 3671eed250aSJake Burkholder int 3689c6f9240SPeter Wemm ef_seg_read_entry(elf_file_t ef, Elf_Off offset, size_t len, void**ptr) 3699c6f9240SPeter Wemm { 3709c6f9240SPeter Wemm int error; 3719c6f9240SPeter Wemm 3729c6f9240SPeter Wemm *ptr = malloc(len); 3739c6f9240SPeter Wemm if (*ptr == NULL) 3749c6f9240SPeter Wemm return ENOMEM; 3759c6f9240SPeter Wemm error = ef_seg_read(ef, offset, len, *ptr); 3769c6f9240SPeter Wemm if (error) 3779c6f9240SPeter Wemm free(*ptr); 3789c6f9240SPeter Wemm return error; 3799c6f9240SPeter Wemm } 3809c6f9240SPeter Wemm 3819c6f9240SPeter Wemm int 3821eed250aSJake Burkholder ef_seg_read_entry_rel(elf_file_t ef, Elf_Off offset, size_t len, void**ptr) 3831eed250aSJake Burkholder { 3841eed250aSJake Burkholder int error; 3851eed250aSJake Burkholder 3861eed250aSJake Burkholder *ptr = malloc(len); 3871eed250aSJake Burkholder if (*ptr == NULL) 3881eed250aSJake Burkholder return ENOMEM; 3891eed250aSJake Burkholder error = ef_seg_read_rel(ef, offset, len, *ptr); 3901eed250aSJake Burkholder if (error) 3911eed250aSJake Burkholder free(*ptr); 3921eed250aSJake Burkholder return error; 3931eed250aSJake Burkholder } 3941eed250aSJake Burkholder 3951eed250aSJake Burkholder int 3969c6f9240SPeter Wemm ef_open(const char *filename, elf_file_t ef, int verbose) 3979c6f9240SPeter Wemm { 3989c6f9240SPeter Wemm Elf_Ehdr *hdr; 3999c6f9240SPeter Wemm int fd; 4009c6f9240SPeter Wemm int error; 4019c6f9240SPeter Wemm int phlen, res; 4029c6f9240SPeter Wemm int nsegs; 4039c6f9240SPeter Wemm Elf_Phdr *phdr, *phdyn, *phphdr, *phlimit; 4049c6f9240SPeter Wemm 4059c6f9240SPeter Wemm bzero(ef, sizeof(*ef)); 4069c6f9240SPeter Wemm if (filename == NULL) 4079c6f9240SPeter Wemm return EFTYPE; 4089c6f9240SPeter Wemm ef->ef_verbose = verbose; 4099c6f9240SPeter Wemm if ((fd = open(filename, O_RDONLY)) == -1) 4109c6f9240SPeter Wemm return errno; 4119c6f9240SPeter Wemm ef->ef_fd = fd; 4129c6f9240SPeter Wemm ef->ef_name = strdup(filename); 4139c6f9240SPeter Wemm hdr = (Elf_Ehdr *)&ef->ef_hdr; 4149c6f9240SPeter Wemm do { 4159c6f9240SPeter Wemm res = read(fd, hdr, sizeof(*hdr)); 4169c6f9240SPeter Wemm error = EFTYPE; 4179c6f9240SPeter Wemm if (res != sizeof(*hdr)) 4189c6f9240SPeter Wemm break; 4199c6f9240SPeter Wemm if (!IS_ELF(*hdr)) 4209c6f9240SPeter Wemm break; 4219c6f9240SPeter Wemm if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS || 4229c6f9240SPeter Wemm hdr->e_ident[EI_DATA] != ELF_TARG_DATA || 4239c6f9240SPeter Wemm hdr->e_ident[EI_VERSION] != EV_CURRENT || 4249c6f9240SPeter Wemm hdr->e_version != EV_CURRENT || 4259c6f9240SPeter Wemm hdr->e_machine != ELF_TARG_MACH || 4269c6f9240SPeter Wemm hdr->e_phentsize != sizeof(Elf_Phdr)) 4279c6f9240SPeter Wemm break; 4289c6f9240SPeter Wemm phlen = hdr->e_phnum * sizeof(Elf_Phdr); 4299c6f9240SPeter Wemm if (ef_read_entry(ef, hdr->e_phoff, phlen, 4309c6f9240SPeter Wemm (void**)&ef->ef_ph) != 0) 4319c6f9240SPeter Wemm break; 4329c6f9240SPeter Wemm phdr = ef->ef_ph; 4339c6f9240SPeter Wemm phlimit = phdr + hdr->e_phnum; 4349c6f9240SPeter Wemm nsegs = 0; 4359c6f9240SPeter Wemm phdyn = NULL; 4369c6f9240SPeter Wemm phphdr = NULL; 4379c6f9240SPeter Wemm while (phdr < phlimit) { 4389c6f9240SPeter Wemm if (verbose > 1) 4399c6f9240SPeter Wemm ef_print_phdr(phdr); 4409c6f9240SPeter Wemm switch (phdr->p_type) { 4419c6f9240SPeter Wemm case PT_LOAD: 4429c6f9240SPeter Wemm if (nsegs == 2) { 4439c6f9240SPeter Wemm warnx("%s: too many sections", 4449c6f9240SPeter Wemm filename); 4459c6f9240SPeter Wemm break; 4469c6f9240SPeter Wemm } 4479c6f9240SPeter Wemm ef->ef_segs[nsegs++] = phdr; 4489c6f9240SPeter Wemm break; 4499c6f9240SPeter Wemm case PT_PHDR: 4509c6f9240SPeter Wemm phphdr = phdr; 4519c6f9240SPeter Wemm break; 4529c6f9240SPeter Wemm case PT_DYNAMIC: 4539c6f9240SPeter Wemm phdyn = phdr; 4549c6f9240SPeter Wemm break; 4559c6f9240SPeter Wemm } 4569c6f9240SPeter Wemm phdr++; 4579c6f9240SPeter Wemm } 4589c6f9240SPeter Wemm if (verbose > 1) 4599c6f9240SPeter Wemm printf("\n"); 4609c6f9240SPeter Wemm ef->ef_nsegs = nsegs; 4619c6f9240SPeter Wemm if (phdyn == NULL) { 4629c6f9240SPeter Wemm warnx("file isn't dynamically-linked"); 4639c6f9240SPeter Wemm break; 4649c6f9240SPeter Wemm } 4659c6f9240SPeter Wemm if (ef_read_entry(ef, phdyn->p_offset, 4669c6f9240SPeter Wemm phdyn->p_filesz, (void**)&ef->ef_dyn) != 0) { 4679c6f9240SPeter Wemm printf("ef_read_entry failed\n"); 4689c6f9240SPeter Wemm break; 4699c6f9240SPeter Wemm } 4709c6f9240SPeter Wemm error = ef_parse_dynamic(ef); 4719c6f9240SPeter Wemm if (error) 4729c6f9240SPeter Wemm break; 4739c6f9240SPeter Wemm if (hdr->e_type == ET_DYN) { 4749c6f9240SPeter Wemm ef->ef_type = EFT_KLD; 4759c6f9240SPeter Wemm /* pad = (u_int)dest & PAGE_MASK; 4769c6f9240SPeter Wemm if (pad) 4779c6f9240SPeter Wemm dest += PAGE_SIZE - pad;*/ 4789c6f9240SPeter Wemm error = 0; 4799c6f9240SPeter Wemm } else if (hdr->e_type == ET_EXEC) { 4809c6f9240SPeter Wemm /* dest = hdr->e_entry; 4819c6f9240SPeter Wemm if (dest == 0) 4829c6f9240SPeter Wemm break;*/ 4839c6f9240SPeter Wemm ef->ef_type = EFT_KERNEL; 4849c6f9240SPeter Wemm error = 0; 4859c6f9240SPeter Wemm } else 4869c6f9240SPeter Wemm break; 4879c6f9240SPeter Wemm } while(0); 4889c6f9240SPeter Wemm if (error) { 4899c6f9240SPeter Wemm ef_close(ef); 4909c6f9240SPeter Wemm if (ef->ef_verbose) 4919c6f9240SPeter Wemm warnc(error, "elf_open(%s)", filename); 4929c6f9240SPeter Wemm } 4939c6f9240SPeter Wemm return error; 4949c6f9240SPeter Wemm } 4959c6f9240SPeter Wemm 4969c6f9240SPeter Wemm int 4979c6f9240SPeter Wemm ef_close(elf_file_t ef) 4989c6f9240SPeter Wemm { 4999c6f9240SPeter Wemm close(ef->ef_fd); 5009c6f9240SPeter Wemm /* if (ef->ef_fpage) 5019c6f9240SPeter Wemm free(ef->ef_fpage);*/ 5029c6f9240SPeter Wemm if (ef->ef_name) 5039c6f9240SPeter Wemm free(ef->ef_name); 5049c6f9240SPeter Wemm return 0; 5059c6f9240SPeter Wemm } 506