static BOOL DLSYM_lookup_symtab(const char *sym_name, struct Elf32_Sym *symtab, Elf32_Word symnum, Elf32_Addr *sym_value, BOOL require_local_binding) { Elf32_Addr sym_idx; for (sym_idx = 0; sym_idx < symnum; sym_idx++) { #if LOADER_DEBUG if (debugging_on) DLIF_trace("DLSYM_lookup_symtab %s\n", (char *)symtab[sym_idx].st_name); #endif if ((symtab[sym_idx].st_shndx != SHN_UNDEF) && ((require_local_binding && (ELF32_ST_BIND(symtab[sym_idx].st_info) == STB_LOCAL)) || (!require_local_binding && (ELF32_ST_BIND(symtab[sym_idx].st_info) != STB_LOCAL))) && !strcmp(sym_name,(char*)(symtab[sym_idx].st_name))) { if (sym_value) *sym_value = symtab[sym_idx].st_value; return TRUE; } } if (sym_value) *sym_value = 0; return FALSE; }
void dump_SHT_SYMTAB_section(void* data, size_t length, int i) { Elf32_Ehdr* ehdr = (Elf32_Ehdr*)data; Elf32_Shdr* shdrs = (Elf32_Shdr*)((char*)data + ehdr->e_shoff); Elf32_Sym* symbols = (Elf32_Sym*)((char*)data + shdrs[i].sh_offset); int shnum = ehdr->e_shnum; int shentsize = ehdr->e_shentsize; int entnum; unsigned char st_info; char info[3]; /* local/global/weak, data/function/section/file */ int j; assert(sizeof(Elf32_Shdr) == ehdr->e_shentsize && sizeof(Elf32_Sym) == shdrs[i].sh_entsize); entnum = shdrs[i].sh_size / shdrs[i].sh_entsize; assert(entnum > 0); info[2] = '\0'; printf("entnum=%d\n", entnum); puts(" [ Nr] value size info other shndx name"); for (j = 0; j < entnum; ++j) { st_info = symbols[j].st_info; if (ELF32_ST_BIND(st_info) == STB_LOCAL) info[0] = 'l'; else if (ELF32_ST_BIND(st_info) == STB_GLOBAL) info[0] = 'g'; else if (ELF32_ST_BIND(st_info) == STB_WEAK) info[0] = 'w'; else info[0] = '?'; if (ELF32_ST_TYPE(st_info) == STT_OBJECT) info[1] = 'd'; else if (ELF32_ST_TYPE(st_info) == STT_FUNC) info[1] = 'F'; else if (ELF32_ST_TYPE(st_info) == STT_SECTION) info[1] = 's'; else if (ELF32_ST_TYPE(st_info) == STT_FILE) info[1] = 'f'; else if (ELF32_ST_TYPE(st_info) == STT_NOTYPE) info[1] = ' '; else info[1] = '?'; printf(" [%3d] %6d %4d [%2s] %2d %6d %-12s\n", j, symbols[j].st_value, symbols[j].st_size, info, symbols[j].st_other, symbols[j].st_shndx, (symbols[j].st_name == 0) ? "<UNNAMED>" : get_str(data, shdrs[i].sh_link, symbols[j].st_name)); } }
/** * Get the binding of a symbol. * @param infos Information about the symbol. * @return Binding as a string. */ const char *get_binding(const gel_sym_info_t *infos) { static char buf[32]; switch(ELF32_ST_BIND(infos->info)) { case STB_LOCAL: return "local"; case STB_GLOBAL: return "global"; case STB_WEAK: return "weak"; default: sprintf(buf, "%d", ELF32_ST_BIND(infos->info)); return buf; } }
int add_global( char *name, Elf32_Sym *sym, object *parent ) { DEBUG(( stderr, "add_global(%s, %p, %p): ", name, sym, parent )); global *g = root_global; while( g ) { if( strcmp( name, g->name ) == 0 ) break; g = g->next; } if( !g ) { // such global does not yet exists, add to list g = new global; g->next = root_global; root_global = g; g->name = name; g->sym = sym; g->parent = parent; DEBUG(( stderr, "created global definition of '%s' at %p [weak: %d, value: %d]\n", name, g, ELF32_ST_BIND(sym->st_info) == STB_WEAK, sym->st_value )); } else { if( ELF32_ST_BIND(g->sym->st_info) == ELF32_ST_BIND(sym->st_info) ) // equal binding { if( ELF32_ST_BIND(sym->st_info) == STB_WEAK ) { DEBUG(( stderr, "duplicate weak symbol, discarding\n" )); return 0; } if( g->sym->st_value == sym->st_value ) { warning( "global symbol '%s' is redefined in '%s'", name, parent->filename ); return 0; } error( "global symbol '%s' defined in '%s' conflicts with global symbol already defined in '%s'", name, parent->filename, g->parent->filename ); return 1; } if( ELF32_ST_BIND(sym->st_info) == STB_GLOBAL ) { g->sym = sym; g->parent = parent; DEBUG(( stderr, "replacing old weak definition of '%s' at %p\n", name, g )); } } return 0; }
static int relocate_section_rel(Elf32_Sym *sym_table, Elf32_Rel *rel, char *target_sect, int nr_reloc, char *strtab) { Elf32_Sym *sym; Elf32_Addr sym_val; int i; for (i = 0; i < nr_reloc; i++) { sym = &sym_table[ELF32_R_SYM(rel->r_info)]; ELFDBG(("%s\n", strtab + sym->st_name)); if (sym->st_shndx != STN_UNDEF) { sym_val = (Elf32_Addr)sect_addr[sym->st_shndx] + sym->st_value; if (relocate_rel(rel, sym_val, target_sect) != 0) return -1; } else if (ELF32_ST_BIND(sym->st_info) != STB_WEAK) { DPRINTF(("Undefined symbol for rel[%x] sym=%lx\n", i, (long)sym)); return -1; } else { DPRINTF(("Undefined weak symbol for rel[%x]\n", i)); } rel++; } return 0; }
int pmelf_getsym32(Elf_Stream s, Elf32_Sym *psym) { if ( 1 != SREAD(psym, sizeof(*psym), 1, s) ) { return -1; } if ( s->needswap ) { #ifdef PMELF_CONFIG_NO_SWAPSUPPORT return -2; #else elf_swap32( &psym->st_name); elf_swap32( &psym->st_value); elf_swap32( &psym->st_size); elf_swap16( &psym->st_shndx); #endif } #ifdef PARANOIA_ON { int x; if ( (x = ELF32_ST_TYPE( psym->st_info )) > STT_MAXSUP ) { PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_getsym - paranoia: unsupported type %i\n", x); return -1; } if ( (x = ELF32_ST_BIND( psym->st_info )) > STB_MAXSUP ) { PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_getsym - paranoia: unsupported binding %i\n", x); return -1; } } #endif return 0; }
/** * Get information about a symbol. * @param loader Current loader. * @param sym Symbol index. * @param data Dat structure to store information in. */ void gliss_loader_sym(gliss_loader_t *loader, int sym, gliss_loader_sym_t *data) { assert(sym < gliss_loader_count_syms(loader)); Elf32_Sym *s; /* get the descriptor */ assert(sym < gliss_loader_count_syms(loader)); s = &loader->Tables.sym_tbl[sym]; /* get name */ data->name = loader->Tables.symstr_tbl + loader->Tables.sym_tbl[sym].st_name; /* get value and section */ data->value = s->st_value; data->sect = s->st_shndx; data->size = s->st_size; /* get the binding */ switch(ELF32_ST_BIND(s->st_info)) { case STB_LOCAL: data->bind = GLISS_LOADER_LOCAL; break; case STB_GLOBAL: data->bind = GLISS_LOADER_GLOBAL; break; case STB_WEAK: data->bind = GLISS_LOADER_WEAK; break; default: data->bind = GLISS_LOADER_NO_BINDING; break; } /* get the type */ switch(ELF32_ST_TYPE(s->st_info)) { case STT_FUNC: data->type = GLISS_LOADER_SYM_CODE; break; case STT_OBJECT: data->type = GLISS_LOADER_SYM_DATA; break; default: data->type = GLISS_LOADER_SYM_NO_TYPE; break; } }
GElf_Sym * gelf_getsym(Elf_Data *d, int ndx, GElf_Sym *dst) { int ec; Elf *e; Elf_Scn *scn; Elf32_Sym *sym32; Elf64_Sym *sym64; size_t msz; uint32_t sh_type; if (d == NULL || ndx < 0 || dst == NULL || (scn = d->d_scn) == NULL || (e = scn->s_elf) == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } ec = e->e_class; assert(ec == ELFCLASS32 || ec == ELFCLASS64); if (ec == ELFCLASS32) sh_type = scn->s_shdr.s_shdr32.sh_type; else sh_type = scn->s_shdr.s_shdr64.sh_type; if (_libelf_xlate_shtype(sh_type) != ELF_T_SYM) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } msz = _libelf_msize(ELF_T_SYM, ec, e->e_version); assert(msz > 0); if (msz * ndx >= d->d_size) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } if (ec == ELFCLASS32) { sym32 = (Elf32_Sym *) d->d_buf + ndx; dst->st_name = sym32->st_name; dst->st_value = (Elf64_Addr) sym32->st_value; dst->st_size = (Elf64_Xword) sym32->st_size; dst->st_info = ELF64_ST_INFO(ELF32_ST_BIND(sym32->st_info), ELF32_ST_TYPE(sym32->st_info)); dst->st_other = sym32->st_other; dst->st_shndx = sym32->st_shndx; } else { sym64 = (Elf64_Sym *) d->d_buf + ndx; *dst = *sym64; } return (dst); }
static uint_t dt_module_syminit32(dt_module_t *dmp) { const Elf32_Sym *sym = dmp->dm_symtab.cts_data; const char *base = dmp->dm_strtab.cts_data; size_t ss_size = dmp->dm_strtab.cts_size; uint_t i, n = dmp->dm_nsymelems; uint_t asrsv = 0; for (i = 0; i < n; i++, sym++) { const char *name = base + sym->st_name; uchar_t type = ELF32_ST_TYPE(sym->st_info); if (type >= STT_NUM || type == STT_SECTION) continue; /* skip sections and unknown types */ if (sym->st_name == 0 || sym->st_name >= ss_size) continue; /* skip null or invalid names */ if (sym->st_value != 0 && (ELF32_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size)) asrsv++; /* reserve space in the address map */ dt_module_symhash_insert(dmp, name, i); } return (asrsv); }
static int _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, Elf32_Rela *rpnt, Elf32_Sym *symtab, char *strtab) { int reloc_type; int symtab_index; char *symname; unsigned long *reloc_addr; unsigned long symbol_addr; #if defined(__SUPPORT_LD_DEBUG__) unsigned long old_val; #endif reloc_addr = (unsigned long *)(tpnt->loadaddr + rpnt->r_offset); reloc_type = ELF32_R_TYPE(rpnt->r_info); symtab_index = ELF32_R_SYM(rpnt->r_info); symbol_addr = 0; symname = strtab + symtab[symtab_index].st_name; if (symtab_index) { symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name, tpnt->symbol_scope, tpnt, elf_machine_type_class(reloc_type)); /* Allow undefined references to weak symbols */ if (!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK) { _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); return 0; } } #if defined(__SUPPORT_LD_DEBUG__) old_val = *reloc_addr; #endif switch (reloc_type) { case R_AVR32_NONE: break; case R_AVR32_GLOB_DAT: case R_AVR32_JMP_SLOT: *reloc_addr = symbol_addr + rpnt->r_addend; break; case R_AVR32_RELATIVE: *reloc_addr = (unsigned long)tpnt->loadaddr + rpnt->r_addend; break; default: return -1; } #if defined(__SUPPORT_LD_DEBUG__) if (_dl_debug_reloc && _dl_debug_detail) _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", old_val, *reloc_addr); #endif return 0; }
/* * ======== print_symbol_info ======== */ static void print_symbol_info(struct Elf32_Sym *sym) { DEBUG_PRINT("Name-Offset = 0x%.8x Value = 0x%.8x Size = 0x%.8x " "Bind = %d Type = %d Visibility = %d Index = %d\n", sym->st_name, sym->st_value, sym->st_size, ELF32_ST_BIND(sym->st_info), ELF32_ST_TYPE(sym->st_info), sym->st_other, sym->st_shndx); }
// this function first tries to see if the first image and it's already resolved symbol is okay, otherwise // it tries to link against the shared_image // XXX gross hack and needs to be done better int elf_resolve_symbol(struct elf_image_info *image, struct Elf32_Sym *sym, struct elf_image_info *shared_image, const char *sym_prepend,addr_t *sym_addr) { struct Elf32_Sym *sym2; char new_symname[512]; switch(sym->st_shndx) { case SHN_UNDEF: // patch the symbol name strlcpy(new_symname, sym_prepend, sizeof(new_symname)); strlcat(new_symname, SYMNAME(image, sym), sizeof(new_symname)); // it's undefined, must be outside this image, try the other image sym2 = elf_find_symbol(shared_image, new_symname); if(!sym2) { dprintf("elf_resolve_symbol: could not resolve symbol '%s'\n", new_symname); return ERR_ELF_RESOLVING_SYMBOL; } // make sure they're the same type if(ELF32_ST_TYPE(sym->st_info) != ELF32_ST_TYPE(sym2->st_info)) { dprintf("elf_resolve_symbol: found symbol '%s' in shared image but wrong type\n", new_symname); return ERR_ELF_RESOLVING_SYMBOL; } if(ELF32_ST_BIND(sym2->st_info) != STB_GLOBAL && ELF32_ST_BIND(sym2->st_info) != STB_WEAK) { dprintf("elf_resolve_symbol: found symbol '%s' but not exported\n", new_symname); return ERR_ELF_RESOLVING_SYMBOL; } *sym_addr = sym2->st_value + shared_image->regions[0].delta; return NO_ERROR; case SHN_ABS: *sym_addr = sym->st_value; return NO_ERROR; case SHN_COMMON: // XXX finish this dprintf("elf_resolve_symbol: COMMON symbol, finish me!\n"); return ERR_NOT_IMPLEMENTED; default: // standard symbol *sym_addr = sym->st_value + image->regions[0].delta; return NO_ERROR; } }
BOOL DLSYM_canonical_lookup(DLOAD_HANDLE handle, int sym_index, DLIMP_Dynamic_Module *dyn_module, Elf32_Addr *sym_value) { /*------------------------------------------------------------------------*/ /* Lookup the symbol table to get the symbol characteristics. */ /*------------------------------------------------------------------------*/ struct Elf32_Sym *sym = &dyn_module->symtab[sym_index]; int32_t st_bind = ELF32_ST_BIND(sym->st_info); int32_t st_vis = ELF32_ST_VISIBILITY(sym->st_other); BOOL is_def = (sym->st_shndx != SHN_UNDEF && (sym->st_shndx < SHN_LORESERVE || sym->st_shndx == SHN_ABS || sym->st_shndx == SHN_COMMON || sym->st_shndx == SHN_XINDEX)); const char *sym_name = (char *)sym->st_name; #if LOADER_DEBUG if (debugging_on) DLIF_trace("DLSYM_canonical_lookup: %d, %s\n", sym_index, sym_name); #endif /*------------------------------------------------------------------------*/ /* Local symbols and symbol definitions that cannot be pre-empted */ /* are resolved by the definition in the same module. */ /*------------------------------------------------------------------------*/ if (st_bind == STB_LOCAL || st_vis != STV_DEFAULT) { /*---------------------------------------------------------------------*/ /* If it is a local symbol or non-local that cannot be preempted, */ /* the definition should be found in the same module. If we don't */ /* find the definition it is an error. */ /*---------------------------------------------------------------------*/ if (!is_def) { DLIF_error(DLET_SYMBOL, "Local/non-imported symbol %s definition is not found " "in module %s!\n", sym_name, dyn_module->name); return FALSE; } else { if (sym_value) *sym_value = sym->st_value; return TRUE; } } /*------------------------------------------------------------------------*/ /* Else we have either pre-emptable defintion or undef symbol. We need */ /* to do global look up. */ /*------------------------------------------------------------------------*/ else { return DLSYM_global_lookup(handle, sym_name, dyn_module->loaded_module, sym_value); } }
db_sym_t elf_db_search_symbol (db_symtab_t *stab, db_addr_t off, db_strategy_t strategy, db_expr_t *diffp) /* in/out */ { struct db_symtab_elf *self = (struct db_symtab_elf *) stab; unsigned long diff = *diffp; Elf32_Sym *s, *symp = NULL; for (s = self->start; s < self->end; s++) { if (s->st_name == 0) continue; if (strategy == DB_STGY_XTRN && (ELF32_ST_BIND(s->st_info) != STB_GLOBAL)) continue; if (off >= s->st_value) { if (ELF32_ST_TYPE(s->st_info) == STT_FUNC) continue; if (off - s->st_value < diff) { diff = off - s->st_value; symp = s; if (diff == 0 && (ELF32_ST_BIND(s->st_info) == STB_GLOBAL)) break; } else if (off - s->st_value == diff) { if (symp == NULL) symp = s; else if ((ELF32_ST_BIND(symp->st_info) != STB_GLOBAL) && (ELF32_ST_BIND(s->st_info) == STB_GLOBAL)) symp = s; /* pick the external symbol */ } } } if (symp == NULL) *diffp = off; else *diffp = diff; return (db_sym_t) symp; }
static int elf_search_section_sym(WadFrame *f, char *secname, char *strname) { int nsymtab; int nstrtab; int symtab_size; Elf32_Sym *sym; int nsym; char *str; int i; unsigned long vaddr, base; char *name; char *localfile = 0; vaddr = (unsigned long) f->pc; base = (unsigned long) f->segment->base; nsymtab = wad_elf_section_byname(f->object,secname); if (nsymtab < 0) return 0; nstrtab = wad_elf_section_byname(f->object,strname); if (nstrtab < 0) return 0; symtab_size = wad_elf_section_size(f->object,nsymtab); sym = (Elf32_Sym *) wad_elf_section_data(f->object,nsymtab); str = (char *) wad_elf_section_data(f->object,nstrtab); nsym = (symtab_size/sizeof(Elf32_Sym)); for (i = 0; i < nsym; i++) { name = str + sym[i].st_name; /* Look for filename in case the symbol maps to a local symbol */ if (ELF32_ST_TYPE(sym[i].st_info) == STT_FILE) { localfile = name; } if (wad_debug_mode & DEBUG_SYMBOL_SEARCH) { wad_printf("%x(%x): %s %x + %x, %x, %x\n", base, vaddr, name, sym[i].st_value, sym[i].st_size, sym[i].st_info, sym[i].st_shndx); } if (((base + sym[i].st_value) <= vaddr) && (vaddr <= (base+sym[i].st_value + sym[i].st_size))) { #ifdef WAD_LINUX /* If the section index is 0, the symbol is undefined */ if (sym[i].st_shndx == 0) continue; #endif f->sym_name = name; f->sym_nlen = strlen(name); f->sym_base = base + sym[i].st_value; f->sym_size = sym[i].st_size; if (ELF32_ST_BIND(sym[i].st_info) == STB_LOCAL) { f->sym_file = localfile; f->sym_bind = SYM_LOCAL; } else { f->sym_bind = SYM_GLOBAL; } return 1; } } return 0; }
void *__wrap_dlsym(void *handle, const char *symbol) { if (extractLibs) return dlsym(handle, symbol); soinfo *found; Elf32_Sym *sym; unsigned bind; pthread_mutex_lock(&dl_lock); if(unlikely(handle == 0)) { set_dlerror(DL_ERR_INVALID_LIBRARY_HANDLE); goto err; } if(unlikely(symbol == 0)) { set_dlerror(DL_ERR_BAD_SYMBOL_NAME); goto err; } if(handle == RTLD_DEFAULT) { sym = lookup(symbol, &found, NULL); } else if(handle == RTLD_NEXT) { void *ret_addr = __builtin_return_address(0); soinfo *si = find_containing_library(ret_addr); sym = NULL; if(si && si->next) { sym = lookup(symbol, &found, si->next); } } else { found = (soinfo*)handle; sym = lookup_in_library(found, symbol); } if(likely(sym != 0)) { bind = ELF32_ST_BIND(sym->st_info); if(likely((bind == STB_GLOBAL) && (sym->st_shndx != 0))) { unsigned ret = sym->st_value + found->base; pthread_mutex_unlock(&dl_lock); return (void*)ret; } set_dlerror(DL_ERR_SYMBOL_NOT_GLOBAL); } else set_dlerror(DL_ERR_SYMBOL_NOT_FOUND); err: pthread_mutex_unlock(&dl_lock); return 0; }
/* Change all symbols so that sh_value encodes the pointer directly. */ static int simplify_symbols(Elf32_Shdr *sechdrs, unsigned int symindex, const char *strtab) { Elf32_Sym *sym = (void *)sechdrs[symindex].sh_addr; unsigned long secbase; unsigned int i, n = sechdrs[symindex].sh_size / sizeof(Elf32_Sym); int ret = 0; for (i = 1; i < n; i++) { switch (sym[i].st_shndx) { case SHN_COMMON: /* We compiled with -fno-common. These are not supposed to happen. */ printf("Common symbol: %s\n", strtab + sym[i].st_name); printf("please compile with -fno-common\n"); ret = -1; break; case SHN_ABS: /* Don't need to do anything */ debug("Absolute symbol: 0x%08lx\n", (long)sym[i].st_value); break; case SHN_UNDEF: sym[i].st_value = resolve_symbol(sechdrs, strtab + sym[i].st_name); debug("undef : %20s 0x%08x 0x%08lx\n", strtab + sym[i].st_name, sym[i].st_value); /* Ok if resolved. */ if (sym[i].st_value != 0) break; /* Ok if weak. */ if (ELF32_ST_BIND(sym[i].st_info) == STB_WEAK) break; printf("Unknown symbol %s\n", strtab + sym[i].st_name); ret = -1; break; default: secbase = sechdrs[sym[i].st_shndx].sh_addr; debug("default: %20s 0x%08x 0x%08lx\n", strtab + sym[i].st_name, sym[i].st_value, secbase); sym[i].st_value += secbase; break; } } return ret; }
/* * Sort comparison function for 32-bit symbol address-to-name lookups. We sort * symbols by value. If values are equal, we prefer the symbol that is * non-zero sized, typed, not weak, or lexically first, in that order. */ static int dt_module_symcomp32(const void *lp, const void *rp) { Elf32_Sym *lhs = *((Elf32_Sym **)lp); Elf32_Sym *rhs = *((Elf32_Sym **)rp); if (lhs->st_value != rhs->st_value) return (lhs->st_value > rhs->st_value ? 1 : -1); if ((lhs->st_size == 0) != (rhs->st_size == 0)) return (lhs->st_size == 0 ? 1 : -1); if ((ELF32_ST_TYPE(lhs->st_info) == STT_NOTYPE) != (ELF32_ST_TYPE(rhs->st_info) == STT_NOTYPE)) return (ELF32_ST_TYPE(lhs->st_info) == STT_NOTYPE ? 1 : -1); if ((ELF32_ST_BIND(lhs->st_info) == STB_WEAK) != (ELF32_ST_BIND(rhs->st_info) == STB_WEAK)) return (ELF32_ST_BIND(lhs->st_info) == STB_WEAK ? 1 : -1); return (strcmp(dt_module_strtab + lhs->st_name, dt_module_strtab + rhs->st_name)); }
int elf_rel_find_symbol(struct mem_ehdr *ehdr, const char *name, struct mem_sym *ret_sym) { struct mem_shdr *shdr, *shdr_end; if (!ehdr->e_shdr) { /* "No section header? */ return -1; } /* Walk through the sections and find the symbol table */ shdr_end = &ehdr->e_shdr[ehdr->e_shnum]; for (shdr = ehdr->e_shdr; shdr != shdr_end; shdr++) { const char *strtab; size_t sym_size; const unsigned char *ptr, *sym_end; if (shdr->sh_type != SHT_SYMTAB) { continue; } if (shdr->sh_link > ehdr->e_shnum) { /* Invalid strtab section number? */ continue; } strtab = (char *)ehdr->e_shdr[shdr->sh_link].sh_data; /* Walk through the symbol table and find the symbol */ sym_size = elf_sym_size(ehdr); sym_end = shdr->sh_data + shdr->sh_size; for(ptr = shdr->sh_data; ptr < sym_end; ptr += sym_size) { struct mem_sym sym; sym = elf_sym(ehdr, ptr); if (ELF32_ST_BIND(sym.st_info) != STB_GLOBAL) { continue; } if (strcmp(strtab + sym.st_name, name) != 0) { continue; } if ((sym.st_shndx == STN_UNDEF) || (sym.st_shndx > ehdr->e_shnum)) { die("Symbol: %s has Bad section index %d\n", name, sym.st_shndx); } *ret_sym = sym; return 0; } } /* I did not find it :( */ return -1; }
static uint_t dt_module_syminit32(dt_module_t *dmp) { #if STT_NUM != (STT_TLS + 1) #error "STT_NUM has grown. update dt_module_syminit32()" #endif Elf32_Sym *sym = dmp->dm_symtab.cts_data; const char *base = dmp->dm_strtab.cts_data; size_t ss_size = dmp->dm_strtab.cts_size; uint_t i, n = dmp->dm_nsymelems; uint_t asrsv = 0; #if defined(__FreeBSD__) GElf_Ehdr ehdr; int is_elf_obj; gelf_getehdr(dmp->dm_elf, &ehdr); is_elf_obj = (ehdr.e_type == ET_REL); #endif for (i = 0; i < n; i++, sym++) { const char *name = base + sym->st_name; uchar_t type = ELF32_ST_TYPE(sym->st_info); if (type >= STT_NUM || type == STT_SECTION) continue; /* skip sections and unknown types */ if (sym->st_name == 0 || sym->st_name >= ss_size) continue; /* skip null or invalid names */ if (sym->st_value != 0 && (ELF32_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size)) { asrsv++; /* reserve space in the address map */ #if defined(__FreeBSD__) sym->st_value += (Elf_Addr) dmp->dm_reloc_offset; if (is_elf_obj && sym->st_shndx != SHN_UNDEF && sym->st_shndx < ehdr.e_shnum) sym->st_value += dmp->dm_sec_offsets[sym->st_shndx]; #endif } dt_module_symhash_insert(dmp, name, i); } return (asrsv); }
char * symbol_bind2str( Elf32_Sym * sym ) { char * ret; if( ! sym ) error_ret("null arg",NULL); switch( ELF32_ST_BIND( sym->st_info ) ) { case STB_LOCAL : ret = "STB_LOCAL "; break; case STB_GLOBAL : ret = "STB_GLOBAL"; break; case STB_WEAK : ret = "STB_WEAK "; break; case STB_LOPROC : ret = "STB_LOPROC"; break; case STB_HIPROC : ret = "STB_HIPROC"; break; default : ret = "unknown "; break; } return( ret ); }
Elf32_Sym elflink_getsym( const char *name, elfinfo_t *elf, int elfcount ) { int n, has_weak = 0, weak_n, bind, weak_s; Elf32_Sym *weak; Elf32_Word sym; Elf32_Sym *sym_p; Elf32_Sym notfound; for ( n = 0; n < elfcount; n++ ) { sym = elf_findsym( elf[n].hash_p, elf[n].symtab_p, elf[n].strtab_p, name ); if ( sym == STN_UNDEF ) continue; sym_p = ( Elf32_Sym *) (((uintptr_t)elf[n].symtab_p) + ( elf[n].syment * sym )); if ( sym_p->st_shndx == SHN_UNDEF ) continue; bind = ELF32_ST_BIND( sym_p->st_info ); if ( bind == STB_GLOBAL ) { printf("Bound symbol %s to image %i symbol %i\n", name, n, sym ); return *sym_p; } else if ( bind == STB_WEAK ) { weak = sym_p; weak_n = n; weak_s = sym; has_weak = 1; } } if ( has_weak ) { printf("Weakly bound symbol %s to image %i symbol %i\n", name, weak_n, weak_s); return *weak; } notfound.st_shndx = SHN_UNDEF; printf("Unresolved symbol %s\n", name); return notfound; }
static Elf32_Sym *elf_find_func(struct elf_obj *obj, unsigned int func) { int i, j; Elf32_Sym *cur; for(i = 0, j = 0, cur = obj->e_syms; i < obj->e_sym_num; i++, cur++) { if(ELF32_ST_BIND(cur->st_info) != STB_GLOBAL) continue; if(ELF32_ST_TYPE(cur->st_info) != STT_FUNC) continue; if(j == func) return cur; j++; } return NULL; }
static void assign32(void *symp, CexpSym cesp, void *closure) { Elf32_Sym *sp=symp; CexpType t; int s=sp->st_size; cesp->size = s; t=TVoid; switch (ELF32_ST_TYPE(sp->st_info)) { case STT_OBJECT: /* determine the type of variable */ t = cexpTypeGuessFromSize(s); break; case STT_FUNC: t=TFuncP; break; case STT_NOTYPE: t=TVoid; break; case STT_SECTION: t=TVoid; cesp->flags|=CEXP_SYMFLG_SECT; break; default: break; } cesp->value.type = t; switch(ELF32_ST_BIND(sp->st_info)) { case STB_GLOBAL: cesp->flags|=CEXP_SYMFLG_GLBL; break; case STB_WEAK : cesp->flags|=CEXP_SYMFLG_WEAK; break; default: break; } cesp->value.ptv = (CexpVal)(uintptr_t)sp->st_value; }
void StELFFile::dumpSymbolTable() { const char *symbolTypes[5] = { "NOTYPE", "OBJECT", "FUNC", "SECTION", "FILE" }; const char *symbolBinding[3] = { "LOCAL", "GLOBAL", "WEAK" }; unsigned count = getSymbolCount(); unsigned i = 0; for (; i < count; ++i) { const Elf32_Sym &symbol = getSymbolAtIndex(i); std::string name = getSymbolName(symbol); printf("'%s': %s, %s, 0x%08x, 0x%08x, %d. 0x%08x\n", name.c_str(), symbolTypes[ELF32_ST_TYPE(symbol.st_info)], symbolBinding[ELF32_ST_BIND(symbol.st_info)], symbol.st_value, symbol.st_size, symbol.st_shndx, symbol.st_other); } }
/* Finds a defined version of the symbol looking through all loaded libraries. If exclude_root is true, skips root file symbols when looking for the symbol. */ Elf32_Sym * link_node::find_symbol(unsigned char *name, char *vername, Elf32_Word verhash, bool exclude_root) { link_node *p = root; unsigned int symhash = dyn_table.elf_hash(name); Elf32_Sym *the_symbol = NULL, *weak_sym = NULL; symbol_wrapper *symbol; if (exclude_root == true) p = p->get_next(); while (p != NULL) { the_symbol = p->lookup_local_symbol(symhash, name, vername, verhash); if (the_symbol != NULL) { symbol = new symbol_wrapper(the_symbol, match_endian); if (ELF32_ST_BIND(symbol->read_info()) == STB_WEAK) { if (weak_sym == NULL) weak_sym = the_symbol; the_symbol = NULL; } delete symbol; } if (the_symbol != NULL) break; p = p->get_next(); } /* Hook for special symbols */ if (the_symbol != NULL) { symbol = new symbol_wrapper(the_symbol, match_endian); if(strcmp("_rtld_global", (char*)name)==0) { patch_rtld_global(symbol); } delete symbol; } if (the_symbol == NULL && weak_sym != NULL) return weak_sym; return the_symbol; }
void *dlsym(void *handle, const char *symbol) { soinfo *found; Elf32_Sym *sym; unsigned bind; pthread_mutex_lock(&dl_lock); if(unlikely(handle == 0)) { set_dlerror(DL_ERR_INVALID_LIBRARY_HANDLE); goto err; } if(unlikely(symbol == 0)) { set_dlerror(DL_ERR_BAD_SYMBOL_NAME); goto err; } if(handle == RTLD_DEFAULT) { sym = lookup(symbol, &found); } else if(handle == RTLD_NEXT) { sym = lookup(symbol, &found); } else { found = (soinfo*)handle; sym = lookup_in_library(found, symbol); } if(likely(sym != 0)) { bind = ELF32_ST_BIND(sym->st_info); if(likely((bind == STB_GLOBAL) && (sym->st_shndx != 0))) { unsigned ret = sym->st_value + found->base; pthread_mutex_unlock(&dl_lock); return (void*)ret; } set_dlerror(DL_ERR_SYMBOL_NOT_GLOBAL); } else set_dlerror(DL_ERR_SYMBOL_NOT_FOUND); err: pthread_mutex_unlock(&dl_lock); return 0; }
void* dlsym(void* handle, const char* symbol) { ScopedPthreadMutexLocker locker(&gDlMutex); if (handle == NULL) { __bionic_format_dlerror("dlsym library handle is null", NULL); return NULL; } if (symbol == NULL) { __bionic_format_dlerror("dlsym symbol name is null", NULL); return NULL; } soinfo* found = NULL; Elf32_Sym* sym = NULL; if (handle == RTLD_DEFAULT) { sym = lookup(symbol, &found, NULL); } else if (handle == RTLD_NEXT) { void* ret_addr = __builtin_return_address(0); soinfo* si = find_containing_library(ret_addr); sym = NULL; if (si && si->next) { sym = lookup(symbol, &found, si->next); } } else { found = (soinfo*) handle; sym = soinfo_lookup(found, symbol); } if (sym != NULL) { unsigned bind = ELF32_ST_BIND(sym->st_info); if (bind == STB_GLOBAL && sym->st_shndx != 0) { unsigned ret = sym->st_value + found->load_bias; return (void*) ret; } __bionic_format_dlerror("symbol found but not global", symbol); return NULL; } else { __bionic_format_dlerror("undefined symbol", symbol); return NULL; } }
/* changesymbols() finds all symbols in a given symbol table that * appear in the namelist with the specified binding and alters their * binding strength. */ static int changesymbols(Elf32_Sym *symtab, char const *strtab, int count) { Elf32_Sym *sym; char const *name; int touched; int i; touched = FALSE; for (i = 0, sym = symtab ; i < count ; ++i, ++sym) { if (ELF32_ST_BIND(sym->st_info) != fromstrength) continue; name = strtab + sym->st_name; if (!bsearch(&name, namelist, namecount, sizeof *namelist, qstrcmp)) continue; sym->st_info = ELF32_ST_INFO(tostrength, ELF32_ST_TYPE(sym->st_info)); printf("%s \"%s\".\n", tostrengthtext, name); touched = TRUE; } return touched; }
static SYM * readsyms(Elf32_Sym *data, size_t num, Elf *elf, Elf32_Word link) { SYM *s, *buf; size_t i; if((buf = (SYM *)calloc(num, sizeof(SYM)) ) == NULL) { return NULL; } s = buf; /* save pointer to head of array */ for(i=1; i<num; i++,data++,buf++) { buf->indx = i; buf->name = (char *)elf_strptr(elf, link, data->st_name); buf->value = data->st_value; buf->size = data->st_size; buf->type = ELF32_ST_TYPE(data->st_info); buf->bind = ELF32_ST_BIND(data->st_info); buf->other = data->st_other; buf->shndx = data->st_shndx; } /* end for loop */ return(s); }