diff --git a/sys/boot/common/load_elf.c b/sys/boot/common/load_elf.c index 057e76fcb223..c8c1ede95fba 100644 --- a/sys/boot/common/load_elf.c +++ b/sys/boot/common/load_elf.c @@ -24,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: load_elf.c,v 1.2 1998/10/02 08:04:56 peter Exp $ + * $Id: load_elf.c,v 1.3 1998/10/09 23:18:43 peter Exp $ */ #include @@ -155,7 +155,8 @@ elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result) mp->m_name = strdup(filename); mp->m_type = strdup(kernel ? elf_kerneltype : elf_moduletype); - printf("%s entry at %p\n", filename, (void *) dest); + if (kernel) + printf("%s entry at %p\n", filename, (void *) dest); mp->m_size = elf_loadimage(mp, fd, dest, &ehdr, kernel); if (mp->m_size == 0 || mp->m_addr == 0) @@ -189,15 +190,12 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off, int i, j; Elf_Phdr *phdr; Elf_Shdr *shdr; - Elf_Ehdr local_ehdr; int ret; vm_offset_t firstaddr; vm_offset_t lastaddr; void *buf; size_t resid, chunk; vm_offset_t dest; - char *secname; - vm_offset_t shdrpos; vm_offset_t ssym, esym; Elf_Dyn *dp; int ndp; @@ -207,6 +205,9 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off, int len; char *strtab; size_t strsz; + int symstrindex; + int symtabindex; + long size; dp = NULL; shdr = NULL; @@ -239,10 +240,17 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off, if (phdr[i].p_type != PT_LOAD) continue; +#ifdef ELF_VERBOSE printf("Segment: 0x%lx@0x%lx -> 0x%lx-0x%lx", (long)phdr[i].p_filesz, (long)phdr[i].p_offset, (long)(phdr[i].p_vaddr + off), (long)(phdr[i].p_vaddr + off + phdr[i].p_memsz - 1)); +#else + if ((phdr[i].p_flags & PF_W) == 0) + printf(" text=0x%lx", (long)phdr[i].p_filesz); + else + printf(" data=0x%lx", (long)phdr[i].p_filesz); +#endif if (lseek(fd, phdr[i].p_offset, SEEK_SET) == -1) { printf("\nelf_loadexec: cannot seek\n"); @@ -255,9 +263,13 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off, } /* clear space from oversized segments; eg: bss */ if (phdr[i].p_filesz < phdr[i].p_memsz) { +#ifdef ELF_VERBOSE printf(" (bss: 0x%lx-0x%lx)", (long)(phdr[i].p_vaddr + off + phdr[i].p_filesz), (long)(phdr[i].p_vaddr + off + phdr[i].p_memsz - 1)); +#else + printf(" bss=0x%lx", (long)(phdr[i].p_memsz -phdr[i].p_filesz)); +#endif /* no archsw.arch_bzero */ buf = malloc(PAGE_SIZE); @@ -272,79 +284,40 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off, } free(buf); } +#ifdef ELF_VERBOSE printf("\n"); +#endif if (firstaddr == 0 || firstaddr > (phdr[i].p_vaddr + off)) firstaddr = phdr[i].p_vaddr + off; if (lastaddr == 0 || lastaddr < (phdr[i].p_vaddr + off + phdr[i].p_memsz)) lastaddr = phdr[i].p_vaddr + off + phdr[i].p_memsz; } + lastaddr = roundup(lastaddr, sizeof(long)); /* * Now grab the symbol tables. This isn't easy if we're reading a * .gz file. I think the rule is going to have to be that you must * strip a file to remove symbols before gzipping it so that we do not - * try to lseek() on it. The layout is a bit wierd, but it's what - * the NetBSD-derived ddb/db_elf.c wants. + * try to lseek() on it. */ - lastaddr = roundup(lastaddr, sizeof(long)); chunk = ehdr->e_shnum * ehdr->e_shentsize; shdr = malloc(chunk); if (shdr == NULL) goto nosyms; - ssym = lastaddr; - printf("Symbols: ELF Ehdr @ 0x%x; ", lastaddr); - lastaddr += sizeof(*ehdr); - lastaddr = roundup(lastaddr, sizeof(long)); - /* Copy out executable header modified for base offsets */ - local_ehdr = *ehdr; - local_ehdr.e_phoff = 0; - local_ehdr.e_phentsize = 0; - local_ehdr.e_phnum = 0; - local_ehdr.e_shoff = lastaddr - ssym; - archsw.arch_copyin(&local_ehdr, ssym, sizeof(*ehdr)); if (lseek(fd, ehdr->e_shoff, SEEK_SET) == -1) { - printf("elf_loadimage: cannot lseek() to section headers\n"); - lastaddr = ssym; /* wind back */ - ssym = 0; + printf("\nelf_loadimage: cannot lseek() to section headers\n"); goto nosyms; } if (read(fd, shdr, chunk) != chunk) { - printf("elf_loadimage: read section headers failed\n"); - lastaddr = ssym; /* wind back */ - ssym = 0; + printf("\nelf_loadimage: read section headers failed\n"); goto nosyms; } - shdrpos = lastaddr; - printf("Section table: 0x%x@0x%x\n", chunk, shdrpos); - lastaddr += chunk; - lastaddr = roundup(lastaddr, sizeof(long)); + symtabindex = -1; + symstrindex = -1; for (i = 0; i < ehdr->e_shnum; i++) { - /* Explicitly skip string table for section names */ - if (i == ehdr->e_shstrndx) + if (shdr[i].sh_type != SHT_SYMTAB) continue; - switch(shdr[i].sh_type) { - /* - * These are the symbol tables. Their names are relative to - * an arbitary string table. - */ - case SHT_SYMTAB: /* Symbol table */ - secname = "symtab"; - break; - case SHT_DYNSYM: /* Dynamic linking symbol table */ - secname = "dynsym"; - break; - /* - * And here are the string tables. These can be referred to from - * a number of sources, including the dynsym, the section table - * names itself, etc. - */ - case SHT_STRTAB: /* String table */ - secname = "strtab"; - break; - default: /* Skip it */ - continue; - } for (j = 0; j < ehdr->e_phnum; j++) { if (phdr[j].p_type != PT_LOAD) continue; @@ -358,31 +331,72 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off, } if (shdr[i].sh_offset == 0 || shdr[i].sh_size == 0) continue; /* alread loaded in a PT_LOAD above */ + /* Save it for loading below */ + symtabindex = i; + symstrindex = shdr[i].sh_link; + } + if (symtabindex < 0 || symstrindex < 0) + goto nosyms; + /* Ok, committed to a load. */ +#ifndef ELF_VERBOSE + printf(" symbols=["); +#endif + ssym = lastaddr; + for (i = symtabindex; i >= 0; i = symstrindex) { +#ifdef ELF_VERBOSE + char *secname; + + switch(shdr[i].sh_type) { + case SHT_SYMTAB: /* Symbol table */ + secname = "symtab"; + break; + case SHT_STRTAB: /* String table */ + secname = "strtab"; + break; + default: + secname = "WHOA!!"; + break; + } +#endif + + size = shdr[i].sh_size; + archsw.arch_copyin(&size, lastaddr, sizeof(size)); + lastaddr += sizeof(long); + +#ifdef ELF_VERBOSE printf("%s: 0x%x@0x%x -> 0x%x-0x%x\n", secname, shdr[i].sh_size, shdr[i].sh_offset, lastaddr, lastaddr + shdr[i].sh_size); - +#else + printf("0x%x+0x%lx", sizeof(size), size); +#endif + if (lseek(fd, shdr[i].sh_offset, SEEK_SET) == -1) { printf("\nelf_loadimage: could not seek for symbols - skipped!\n"); - shdr[i].sh_offset = 0; - shdr[i].sh_size = 0; - continue; + lastaddr = ssym; + ssym = 0; + goto nosyms; } if (archsw.arch_readin(fd, lastaddr, shdr[i].sh_size) != shdr[i].sh_size) { printf("\nelf_loadimage: could not read symbols - skipped!\n"); - shdr[i].sh_offset = 0; - shdr[i].sh_size = 0; - continue; + lastaddr = ssym; + ssym = 0; + goto nosyms; } /* Reset offsets relative to ssym */ - shdr[i].sh_offset = lastaddr - ssym; lastaddr += shdr[i].sh_size; lastaddr = roundup(lastaddr, sizeof(long)); + if (i == symtabindex) + symtabindex = -1; + else if (i == symstrindex) + symstrindex = -1; } - archsw.arch_copyin(shdr, lastaddr, sizeof(*ehdr)); esym = lastaddr; +#ifndef ELF_VERBOSE + printf("]\n"); +#endif mod_addmetadata(mp, MODINFOMD_SSYM, sizeof(ssym), &ssym); mod_addmetadata(mp, MODINFOMD_ESYM, sizeof(esym), &esym); diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c index 2fbc3e7607c0..1a1266b58d1d 100644 --- a/sys/kern/link_elf.c +++ b/sys/kern/link_elf.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: link_elf.c,v 1.2 1998/09/11 08:46:15 dfr Exp $ + * $Id: link_elf.c,v 1.3 1998/10/09 23:55:31 peter Exp $ */ #include @@ -94,6 +94,7 @@ typedef struct elf_file { const Elf_Off* chains; caddr_t hash; caddr_t strtab; /* DT_STRTAB */ + int strsz; /* DT_STRSZ */ const Elf_Sym* symtab; /* DT_SYMTAB */ Elf_Addr* got; /* DT_PLTGOT */ const Elf_Rel* pltrel; /* DT_JMPREL */ @@ -104,11 +105,17 @@ typedef struct elf_file { int relsize; /* DT_RELSZ */ const Elf_Rela* rela; /* DT_RELA */ int relasize; /* DT_RELASZ */ + caddr_t modptr; + const Elf_Sym* ddbsymtab; /* The symbol table we are using */ + long ddbsymcnt; /* Number of symbols */ + caddr_t ddbstrtab; /* String table */ + long ddbstrcnt; /* number of bytes in string table */ } *elf_file_t; static int parse_dynamic(linker_file_t lf); static int load_dependancies(linker_file_t lf); static int relocate_file(linker_file_t lf); +static int parse_module_symbols(linker_file_t lf); /* * The kernel symbol table starts here. @@ -162,6 +169,7 @@ link_elf_init(void* arg) linker_kernel_file->size = -(long)linker_kernel_file->address; if (modptr) { + ef->modptr = modptr; baseptr = preload_search_info(modptr, MODINFO_ADDR); if (baseptr) linker_kernel_file->address = *(caddr_t *)baseptr; @@ -169,6 +177,7 @@ link_elf_init(void* arg) if (sizeptr) linker_kernel_file->size = *(size_t *)sizeptr; } + (void)parse_module_symbols(linker_kernel_file); linker_current_file = linker_kernel_file; } #endif @@ -176,6 +185,56 @@ link_elf_init(void* arg) SYSINIT(link_elf, SI_SUB_KLD, SI_ORDER_SECOND, link_elf_init, 0); +static int +parse_module_symbols(linker_file_t lf) +{ + elf_file_t ef = lf->priv; + caddr_t pointer; + caddr_t ssym, esym, base; + caddr_t strtab; + int strcnt; + Elf_Sym* symtab; + int symcnt; + + pointer = preload_search_info(ef->modptr, MODINFO_METADATA|MODINFOMD_SSYM); + if (pointer == NULL) + return 0; + ssym = *(caddr_t *)pointer; + pointer = preload_search_info(ef->modptr, MODINFO_METADATA|MODINFOMD_ESYM); + if (pointer == NULL) + return 0; + esym = *(caddr_t *)pointer; + + base = ssym; + + symcnt = *(long *)base; + base += sizeof(long); + symtab = (Elf_Sym *)base; + base += roundup(symcnt, sizeof(long)); + + if (base > esym || base < ssym) { + printf("Symbols are corrupt!\n"); + return EINVAL; + } + + strcnt = *(long *)base; + base += sizeof(long); + strtab = base; + base += roundup(strcnt, sizeof(long)); + + if (base > esym || base < ssym) { + printf("Symbols are corrupt!\n"); + return EINVAL; + } + + ef->ddbsymtab = symtab; + ef->ddbsymcnt = symcnt / sizeof(Elf_Sym); + ef->ddbstrtab = strtab; + ef->ddbstrcnt = strcnt; + + return 0; +} + static int parse_dynamic(linker_file_t lf) { @@ -199,6 +258,9 @@ parse_dynamic(linker_file_t lf) case DT_STRTAB: ef->strtab = (caddr_t) (ef->address + dp->d_un.d_ptr); break; + case DT_STRSZ: + ef->strsz = dp->d_un.d_val; + break; case DT_SYMTAB: ef->symtab = (Elf_Sym*) (ef->address + dp->d_un.d_ptr); break; @@ -250,6 +312,11 @@ parse_dynamic(linker_file_t lf) ef->pltrelsize = 0; } + ef->ddbsymtab = ef->symtab; + ef->ddbsymcnt = ef->nchains; + ef->ddbstrtab = ef->strtab; + ef->ddbstrcnt = ef->strsz; + return 0; } @@ -306,8 +373,6 @@ link_elf_load_module(const char *filename, linker_file_t *result) linker_file_unload(lf); return error; } - - /* Try to load dependencies */ error = load_dependancies(lf); if (error) { linker_file_unload(lf); @@ -318,6 +383,7 @@ link_elf_load_module(const char *filename, linker_file_t *result) linker_file_unload(lf); return error; } + (void)parse_module_symbols(lf); *result = lf; return (0); } @@ -548,7 +614,6 @@ link_elf_load_file(const char* filename, linker_file_t* result) linker_file_unload(lf); goto out; } - error = load_dependancies(lf); if (error) { linker_file_unload(lf); @@ -642,8 +707,8 @@ symbol_name(elf_file_t ef, const Elf_Rela *rela) const Elf_Sym *ref; if (ELF_R_SYM(rela->r_info)) { - ref = ef->symtab + ELF_R_SYM(rela->r_info); - return ef->strtab + ref->st_name; + ref = ef->ddbsymtab + ELF_R_SYM(rela->r_info); + return ef->ddbstrtab + ref->st_name; } else return NULL; } @@ -723,17 +788,16 @@ link_elf_lookup_symbol(linker_file_t lf, const char* name, linker_sym_t* sym) { elf_file_t ef = lf->priv; unsigned long symnum; - const Elf_Sym* es; + const Elf_Sym* symp; + const char *strp; unsigned long hash; int i; + /* First, search hashed global symbols */ hash = elf_hash(name); symnum = ef->buckets[hash % ef->nbuckets]; while (symnum != STN_UNDEF) { - const Elf_Sym *symp; - const char *strp; - if (symnum >= ef->nchains) { printf("link_elf_lookup_symbol: corrupt symbol table\n"); return ENOENT; @@ -760,6 +824,24 @@ link_elf_lookup_symbol(linker_file_t lf, const char* name, linker_sym_t* sym) symnum = ef->chains[symnum]; } + /* If we have not found it, look at the full table (if loaded) */ + if (ef->symtab == ef->ddbsymtab) + return ENOENT; + + /* Exhaustive search */ + for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) { + strp = ef->ddbstrtab + symp->st_name; + if (strcmp(name, strp) == 0) { + if (symp->st_shndx != SHN_UNDEF || + (symp->st_value != 0 && + ELF_ST_TYPE(symp->st_info) == STT_FUNC)) { + *sym = (linker_sym_t) symp; + return 0; + } else + return ENOENT; + } + } + return ENOENT; } @@ -768,16 +850,22 @@ link_elf_symbol_values(linker_file_t lf, linker_sym_t sym, linker_symval_t* symv { elf_file_t ef = lf->priv; Elf_Sym* es = (Elf_Sym*) sym; - int symcount = ef->nchains; - if (es < ef->symtab) - return ENOENT; - if ((es - ef->symtab) > symcount) - return ENOENT; - symval->name = ef->strtab + es->st_name; - symval->value = (caddr_t) ef->address + es->st_value; - symval->size = es->st_size; - return 0; + if (es >= ef->symtab && ((es - ef->symtab) < ef->nchains)) { + symval->name = ef->strtab + es->st_name; + symval->value = (caddr_t) ef->address + es->st_value; + symval->size = es->st_size; + return 0; + } + if (ef->symtab == ef->ddbsymtab) + return ENOENT; + if (es >= ef->ddbsymtab && ((es - ef->ddbsymtab) < ef->ddbsymcnt)) { + symval->name = ef->ddbstrtab + es->st_name; + symval->value = (caddr_t) ef->address + es->st_value; + symval->size = es->st_size; + return 0; + } + return ENOENT; } static int @@ -787,12 +875,11 @@ link_elf_search_symbol(linker_file_t lf, caddr_t value, elf_file_t ef = lf->priv; u_long off = (u_long) value; u_long diff = off; - int symcount = ef->nchains; const Elf_Sym* es; const Elf_Sym* best = 0; int i; - for (i = 0, es = ef->symtab; i < symcount; i++, es++) { + for (i = 0, es = ef->ddbsymtab; i < ef->ddbsymcnt; i++, es++) { if (es->st_name == 0) continue; if (off >= es->st_value) { diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c index 2fbc3e7607c0..1a1266b58d1d 100644 --- a/sys/kern/link_elf_obj.c +++ b/sys/kern/link_elf_obj.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: link_elf.c,v 1.2 1998/09/11 08:46:15 dfr Exp $ + * $Id: link_elf.c,v 1.3 1998/10/09 23:55:31 peter Exp $ */ #include @@ -94,6 +94,7 @@ typedef struct elf_file { const Elf_Off* chains; caddr_t hash; caddr_t strtab; /* DT_STRTAB */ + int strsz; /* DT_STRSZ */ const Elf_Sym* symtab; /* DT_SYMTAB */ Elf_Addr* got; /* DT_PLTGOT */ const Elf_Rel* pltrel; /* DT_JMPREL */ @@ -104,11 +105,17 @@ typedef struct elf_file { int relsize; /* DT_RELSZ */ const Elf_Rela* rela; /* DT_RELA */ int relasize; /* DT_RELASZ */ + caddr_t modptr; + const Elf_Sym* ddbsymtab; /* The symbol table we are using */ + long ddbsymcnt; /* Number of symbols */ + caddr_t ddbstrtab; /* String table */ + long ddbstrcnt; /* number of bytes in string table */ } *elf_file_t; static int parse_dynamic(linker_file_t lf); static int load_dependancies(linker_file_t lf); static int relocate_file(linker_file_t lf); +static int parse_module_symbols(linker_file_t lf); /* * The kernel symbol table starts here. @@ -162,6 +169,7 @@ link_elf_init(void* arg) linker_kernel_file->size = -(long)linker_kernel_file->address; if (modptr) { + ef->modptr = modptr; baseptr = preload_search_info(modptr, MODINFO_ADDR); if (baseptr) linker_kernel_file->address = *(caddr_t *)baseptr; @@ -169,6 +177,7 @@ link_elf_init(void* arg) if (sizeptr) linker_kernel_file->size = *(size_t *)sizeptr; } + (void)parse_module_symbols(linker_kernel_file); linker_current_file = linker_kernel_file; } #endif @@ -176,6 +185,56 @@ link_elf_init(void* arg) SYSINIT(link_elf, SI_SUB_KLD, SI_ORDER_SECOND, link_elf_init, 0); +static int +parse_module_symbols(linker_file_t lf) +{ + elf_file_t ef = lf->priv; + caddr_t pointer; + caddr_t ssym, esym, base; + caddr_t strtab; + int strcnt; + Elf_Sym* symtab; + int symcnt; + + pointer = preload_search_info(ef->modptr, MODINFO_METADATA|MODINFOMD_SSYM); + if (pointer == NULL) + return 0; + ssym = *(caddr_t *)pointer; + pointer = preload_search_info(ef->modptr, MODINFO_METADATA|MODINFOMD_ESYM); + if (pointer == NULL) + return 0; + esym = *(caddr_t *)pointer; + + base = ssym; + + symcnt = *(long *)base; + base += sizeof(long); + symtab = (Elf_Sym *)base; + base += roundup(symcnt, sizeof(long)); + + if (base > esym || base < ssym) { + printf("Symbols are corrupt!\n"); + return EINVAL; + } + + strcnt = *(long *)base; + base += sizeof(long); + strtab = base; + base += roundup(strcnt, sizeof(long)); + + if (base > esym || base < ssym) { + printf("Symbols are corrupt!\n"); + return EINVAL; + } + + ef->ddbsymtab = symtab; + ef->ddbsymcnt = symcnt / sizeof(Elf_Sym); + ef->ddbstrtab = strtab; + ef->ddbstrcnt = strcnt; + + return 0; +} + static int parse_dynamic(linker_file_t lf) { @@ -199,6 +258,9 @@ parse_dynamic(linker_file_t lf) case DT_STRTAB: ef->strtab = (caddr_t) (ef->address + dp->d_un.d_ptr); break; + case DT_STRSZ: + ef->strsz = dp->d_un.d_val; + break; case DT_SYMTAB: ef->symtab = (Elf_Sym*) (ef->address + dp->d_un.d_ptr); break; @@ -250,6 +312,11 @@ parse_dynamic(linker_file_t lf) ef->pltrelsize = 0; } + ef->ddbsymtab = ef->symtab; + ef->ddbsymcnt = ef->nchains; + ef->ddbstrtab = ef->strtab; + ef->ddbstrcnt = ef->strsz; + return 0; } @@ -306,8 +373,6 @@ link_elf_load_module(const char *filename, linker_file_t *result) linker_file_unload(lf); return error; } - - /* Try to load dependencies */ error = load_dependancies(lf); if (error) { linker_file_unload(lf); @@ -318,6 +383,7 @@ link_elf_load_module(const char *filename, linker_file_t *result) linker_file_unload(lf); return error; } + (void)parse_module_symbols(lf); *result = lf; return (0); } @@ -548,7 +614,6 @@ link_elf_load_file(const char* filename, linker_file_t* result) linker_file_unload(lf); goto out; } - error = load_dependancies(lf); if (error) { linker_file_unload(lf); @@ -642,8 +707,8 @@ symbol_name(elf_file_t ef, const Elf_Rela *rela) const Elf_Sym *ref; if (ELF_R_SYM(rela->r_info)) { - ref = ef->symtab + ELF_R_SYM(rela->r_info); - return ef->strtab + ref->st_name; + ref = ef->ddbsymtab + ELF_R_SYM(rela->r_info); + return ef->ddbstrtab + ref->st_name; } else return NULL; } @@ -723,17 +788,16 @@ link_elf_lookup_symbol(linker_file_t lf, const char* name, linker_sym_t* sym) { elf_file_t ef = lf->priv; unsigned long symnum; - const Elf_Sym* es; + const Elf_Sym* symp; + const char *strp; unsigned long hash; int i; + /* First, search hashed global symbols */ hash = elf_hash(name); symnum = ef->buckets[hash % ef->nbuckets]; while (symnum != STN_UNDEF) { - const Elf_Sym *symp; - const char *strp; - if (symnum >= ef->nchains) { printf("link_elf_lookup_symbol: corrupt symbol table\n"); return ENOENT; @@ -760,6 +824,24 @@ link_elf_lookup_symbol(linker_file_t lf, const char* name, linker_sym_t* sym) symnum = ef->chains[symnum]; } + /* If we have not found it, look at the full table (if loaded) */ + if (ef->symtab == ef->ddbsymtab) + return ENOENT; + + /* Exhaustive search */ + for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) { + strp = ef->ddbstrtab + symp->st_name; + if (strcmp(name, strp) == 0) { + if (symp->st_shndx != SHN_UNDEF || + (symp->st_value != 0 && + ELF_ST_TYPE(symp->st_info) == STT_FUNC)) { + *sym = (linker_sym_t) symp; + return 0; + } else + return ENOENT; + } + } + return ENOENT; } @@ -768,16 +850,22 @@ link_elf_symbol_values(linker_file_t lf, linker_sym_t sym, linker_symval_t* symv { elf_file_t ef = lf->priv; Elf_Sym* es = (Elf_Sym*) sym; - int symcount = ef->nchains; - if (es < ef->symtab) - return ENOENT; - if ((es - ef->symtab) > symcount) - return ENOENT; - symval->name = ef->strtab + es->st_name; - symval->value = (caddr_t) ef->address + es->st_value; - symval->size = es->st_size; - return 0; + if (es >= ef->symtab && ((es - ef->symtab) < ef->nchains)) { + symval->name = ef->strtab + es->st_name; + symval->value = (caddr_t) ef->address + es->st_value; + symval->size = es->st_size; + return 0; + } + if (ef->symtab == ef->ddbsymtab) + return ENOENT; + if (es >= ef->ddbsymtab && ((es - ef->ddbsymtab) < ef->ddbsymcnt)) { + symval->name = ef->ddbstrtab + es->st_name; + symval->value = (caddr_t) ef->address + es->st_value; + symval->size = es->st_size; + return 0; + } + return ENOENT; } static int @@ -787,12 +875,11 @@ link_elf_search_symbol(linker_file_t lf, caddr_t value, elf_file_t ef = lf->priv; u_long off = (u_long) value; u_long diff = off; - int symcount = ef->nchains; const Elf_Sym* es; const Elf_Sym* best = 0; int i; - for (i = 0, es = ef->symtab; i < symcount; i++, es++) { + for (i = 0, es = ef->ddbsymtab; i < ef->ddbsymcnt; i++, es++) { if (es->st_name == 0) continue; if (off >= es->st_value) {