syms_t* syms_new(bin_obj_t* obj) { elfobj_t* elfobj = NULL; char* sections[] = { ".symtab", ".dynsym" , NULL }; int i; Elf_Shdr* section; Elf_Sym* start, * end; syms_t* list = NULL; sym_t* sym; elfobj = (elfobj_t*) obj->luse; for (i = 0; sections[i]; i++) { section = get_elfsection(obj, sections[i]); if (!section) continue; start = (Elf_Sym *) ((char*) elfobj->header + section->sh_offset); end = (Elf_Sym *) ((char*) elfobj->header + section->sh_offset + section->sh_size); /* ** Add every symbol to the list. */ for (; start < end; start++) { /* ** J'ai virer le alloc ?! (TODO) */ if (ELF_ST_TYPE(start->st_info) != STT_FUNC && ELF_ST_TYPE(start->st_info) != STT_NOTYPE) continue; /* ** Skip unusable symbol. */ if (start->st_value == 0x0) continue; sym = malloc(sizeof(sym_t)); if (sym == NULL) goto syms_new_failed; sym->addr = start->st_value + elfobj->base; sym->size = start->st_size; sym->name = (char*) ((char*) elfobj->header + elfobj->section_headers[section->sh_link]->sh_offset + start->st_name); /* printf("Add Sym 0x%x size: %d name: %s\n", sym->addr, sym->size, sym->name); */ list = list_add(list, sym); if (list == NULL) goto syms_new_failed; } } return (list); syms_new_failed: for (; list; ) { sym = (sym_t*) list->value; list = list_del(list, sym); free(sym); } return (NULL); }
bool ElfSymbolTable::lookup(address addr, int* stringtableIndex, int* posIndex, int* offset) { assert(stringtableIndex, "null string table index pointer"); assert(posIndex, "null string table offset pointer"); assert(offset, "null offset pointer"); if (NullDecoder::is_error(m_status)) { return false; } address pc = 0; size_t sym_size = sizeof(Elf_Sym); assert((m_shdr.sh_size % sym_size) == 0, "check size"); int count = m_shdr.sh_size / sym_size; if (m_symbols != NULL) { for (int index = 0; index < count; index ++) { if (STT_FUNC == ELF_ST_TYPE(m_symbols[index].st_info)) { address sym_addr = (address)m_symbols[index].st_value; if (sym_addr < addr && (addr - sym_addr) < *offset) { pc = (address)m_symbols[index].st_value; *offset = (int)(addr - pc); *posIndex = m_symbols[index].st_name; *stringtableIndex = m_shdr.sh_link; } } } } else { long cur_pos; if ((cur_pos = ftell(m_file)) == -1 || fseek(m_file, m_shdr.sh_offset, SEEK_SET)) { m_status = NullDecoder::file_invalid; return false; } Elf_Sym sym; for (int index = 0; index < count; index ++) { if (fread(&sym, sym_size, 1, m_file) == 1) { if (STT_FUNC == ELF_ST_TYPE(sym.st_info)) { address sym_addr = (address)sym.st_value; if (sym_addr < addr && (addr - sym_addr) < *offset) { pc = (address)sym.st_value; *offset = (int)(addr - pc); *posIndex = sym.st_name; *stringtableIndex = m_shdr.sh_link; } } } else { m_status = NullDecoder::file_invalid; return false; } } fseek(m_file, cur_pos, SEEK_SET); } return true; }
static inline int _rtld_relocate_plt_object(const Obj_Entry *obj, Elf_Word sym, Elf_Addr *tp) { Elf_Addr *got = obj->pltgot; const Elf_Sym *def; const Obj_Entry *defobj; Elf_Addr new_value; def = _rtld_find_plt_symdef(sym, obj, &defobj, tp != NULL); if (__predict_false(def == NULL)) return -1; if (__predict_false(def == &_rtld_sym_zero)) return 0; if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { if (tp == NULL) return 0; new_value = _rtld_resolve_ifunc(defobj, def); } else { new_value = (Elf_Addr)(defobj->relocbase + def->st_value); } rdbg(("bind now/fixup in %s --> new=%p", defobj->strtab + def->st_name, (void *)new_value)); got[obj->local_gotno + sym - obj->gotsym] = new_value; if (tp) *tp = new_value; return 0; }
bool generic_get_symbol( Elf_Xword index, std::string& name, Elf64_Addr& value, Elf_Xword& size, unsigned char& bind, unsigned char& type, Elf_Half& section_index, unsigned char& other ) const { bool ret = false; if ( index < get_symbols_num() ) { const T* pSym = reinterpret_cast<const T*>( symbol_section->get_data() + index * symbol_section->get_entry_size() ); const endianess_convertor& convertor = elf_file.get_convertor(); section* string_section = elf_file.sections[get_string_table_index()]; string_section_accessor str_reader( string_section ); const char* pStr = str_reader.get_string( convertor( pSym->st_name ) ); if ( 0 != pStr ) { name = pStr; } value = convertor( pSym->st_value ); size = convertor( pSym->st_size ); bind = ELF_ST_BIND( pSym->st_info ); type = ELF_ST_TYPE( pSym->st_info ); section_index = convertor( pSym->st_shndx ); other = pSym->st_other; ret = true; } return ret; }
static __init void reloc_symtab(Elf32_Ehdr *ehdr, unsigned offset, unsigned size) { Elf32_Sym *sym = (void *)ehdr + offset; unsigned nsym = size / sizeof(*sym); unsigned i; for(i = 0; i < nsym; i++, sym++) { if (sym->st_shndx == SHN_UNDEF || sym->st_shndx == SHN_ABS) continue; /* skip */ if (sym->st_shndx > SHN_LORESERVE) { printk(KERN_INFO "VDSO: unexpected st_shndx %x\n", sym->st_shndx); continue; } switch(ELF_ST_TYPE(sym->st_info)) { case STT_OBJECT: case STT_FUNC: case STT_SECTION: case STT_FILE: sym->st_value += VDSO_ADDR_ADJUST; } } }
static int _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rel *rel, Elf_Addr *tp) { Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rel->r_offset); Elf_Addr new_value; const Elf_Sym *def; const Obj_Entry *defobj; unsigned long info = rel->r_info; assert(ELF_R_TYPE(info) == R_TYPE(JUMP_SLOT)); def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL); if (__predict_false(def == NULL)) return -1; if (__predict_false(def == &_rtld_sym_zero)) return 0; if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { if (tp == NULL) return 0; new_value = _rtld_resolve_ifunc(defobj, def); } else { new_value = (Elf_Addr)(defobj->relocbase + def->st_value); } rdbg(("bind now/fixup in %s --> old=%p new=%p", defobj->strtab + def->st_name, (void *)*where, (void *)new_value)); if (*where != new_value) *where = new_value; if (tp) *tp = new_value; return 0; }
int reloc_gnu_ifunc(Obj_Entry *obj, int flags, RtldLockState *lockstate) { const Elf_Rela *relalim; const Elf_Rela *rela; if (!obj->gnu_ifunc) return (0); relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize); for (rela = obj->pltrela; rela < relalim; rela++) { Elf_Addr *where, target; const Elf_Sym *def; const Obj_Entry *defobj; switch (ELF_R_TYPE(rela->r_info)) { case R_X86_64_JMP_SLOT: where = (Elf_Addr *)(obj->relocbase + rela->r_offset); def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, SYMLOOK_IN_PLT | flags, NULL, lockstate); if (def == NULL) return (-1); if (ELF_ST_TYPE(def->st_info) != STT_GNU_IFUNC) continue; lock_release(rtld_bind_lock, lockstate); target = (Elf_Addr)rtld_resolve_ifunc(defobj, def); wlock_acquire(rtld_bind_lock, lockstate); reloc_jmpslot(where, target, defobj, obj, (const Elf_Rel *)rela); break; } } obj->gnu_ifunc = false; return (0); }
static bool wantsym(const Elf_Sym *sym, const char *strtab) { int type; int bind; type = ELF_ST_TYPE(sym->st_info); bind = ELF_ST_BIND(sym->st_info); if (type != STT_FUNC || (aflag && bind == STB_LOCAL)) #if 0 || (uflag && strchr(strtab + sym->st_name, '.') != NULL)) #endif return 0; #ifdef __arm__ /* ignore what gas calls "mapping symbols" */ { const char *c = strtab + sym->st_name; if (c[0] == '$') return 0; } #endif return 1; }
int sym7(void) { if(ELF_ST_TYPE(orcSYM->st_info) != STT_FILE) return 0; if(mode & REL) if(rand() % 2) return 0; unsigned char st_info = orcSYM->st_info; Elf_Section st_shndx; if(rand() % 2) do st_info = ELF_ST_INFO(rand() & 0x0f, STT_FILE); while(ELF_ST_BIND(st_info) == STB_LOCAL); if(rand() % 4 < 3){ while((st_shndx = rand() % orcHDR->e_shnum)) if(st_shndx != SHN_ABS) break; } else while((st_shndx = getElf_Section())) if(st_shndx != SHN_ABS) break; orcSYM->st_info = st_info; orcSYM->st_shndx = st_shndx; fprintf(logfp, "(SYM[%d]->st_info = 0x%.2x,", entry, orcSYM->st_info); fprintf(logfp, " st_shndx = 0x%x)", orcSYM->st_shndx); return 1; }
/* * Convert an Elf_Sym into an nlist structure. This fills in only the * n_value and n_type members. */ static void elf_sym_to_nlist(struct nlist *nl, Elf_Sym *s, Elf_Shdr *shdr, int shnum) { nl->n_value = s->st_value; switch (s->st_shndx) { case SHN_UNDEF: case SHN_COMMON: nl->n_type = N_UNDF; break; case SHN_ABS: nl->n_type = ELF_ST_TYPE(s->st_info) == STT_FILE ? N_FN : N_ABS; break; default: if (s->st_shndx >= shnum) nl->n_type = N_UNDF; else { Elf_Shdr *sh = shdr + s->st_shndx; nl->n_type = sh->sh_type == SHT_PROGBITS ? (sh->sh_flags & SHF_WRITE ? N_DATA : N_TEXT) : (sh->sh_type == SHT_NOBITS ? N_BSS : N_UNDF); } break; } if (ELF_ST_BIND(s->st_info) == STB_GLOBAL || ELF_ST_BIND(s->st_info) == STB_WEAK) nl->n_type |= N_EXT; }
//-------------------------------------------------------------------------- //lint -e{1764} could be declared const ref static int handle_symbol( reader_t &reader, int shndx, int _info, uint32 st_name, uval_t st_value, int namsec, symbol_visitor_t &sv) { if ( shndx == SHN_UNDEF || shndx == SHN_LOPROC || shndx == SHN_HIPROC || shndx == SHN_ABS ) { return 0; } int type = ELF_ST_TYPE(_info); if ( type != STT_OBJECT && type != STT_FUNC ) return 0; if ( st_name == 0 ) return 0; if ( imagebase != uval_t(-1) ) st_value -= imagebase; qstring name; reader.sections.get_name(&name, namsec, st_name); return sv.visit_symbol(st_value, name.c_str()); }
Elf32_Sym *mips_elf_find_address(struct mips_cpu *pcpu, Elf32_Addr addr) { Elf32_Shdr *shsymtab = pcpu->shsymtab; unsigned n = shsymtab->sh_size / shsymtab->sh_entsize; Elf32_Addr min = (unsigned)-1; Elf32_Sym *ret = NULL; unsigned i; if((shsymtab->sh_offset + shsymtab->sh_size > pcpu->elfsz) || (addr >= pcpu->memsz)) return NULL; for(i = 0; i < n; i++) { Elf32_Sym *sym = get_sym(pcpu->elf, pcpu->elfsz, shsymtab, i); if(!sym) return NULL; if((ELF_ST_BIND(sym->st_info) != STB_GLOBAL) || (ELF_ST_TYPE(sym->st_info) >= STT_SECTION)) continue; if(sym->st_value <= addr) { Elf32_Addr diff = addr - sym->st_value; if(diff < min) { min = diff; ret = sym; if(diff == 0) break; } } } return ret; }
void dump_info(struct elf_object *object) { int numrel, numrela, i; const Elf_Sym *symt; const char *strt; Elf_Word *needed_list; symt = object->dyn.symtab; strt = object->dyn.strtab; for (i = 0; i < object->nchains; i++) { const Elf_Sym *sym = symt + i; char *type; switch (ELF_ST_TYPE(sym->st_info)) { case STT_FUNC: type = "func"; break; case STT_OBJECT: type = "object"; break; case STT_NOTYPE: type = "notype"; break; default: type = "UNKNOWN"; } printf("symbol %d [%s] type %s value %x\n", i, strt + sym->st_name, type, sym->st_value); } numrel = object->dyn.relsz / sizeof(Elf_Rel); numrela = object->dyn.relasz / sizeof(Elf_RelA); printf("numrel %d numrela %d\n", numrel, numrela); printf("rel relocations:\n"); for (i = 0; i < numrel ; i++) { Elf_Rel *rel = object->dyn.rel; printf("%d: %x sym %x type %d\n", i, rel[i].r_offset, ELF_R_SYM(rel[i].r_info), ELF_R_TYPE(rel[i].r_info)); } printf("rela relocations:\n"); for (i = 0; i < numrela ; i++) { Elf_RelA *rela = object->dyn.rela; printf("%d: %x sym %x type %d\n", i, rela[i].r_offset, ELF_R_SYM(rela[i].r_info), ELF_R_TYPE(rela[i].r_info)); } needed_list = (Elf_Addr *)object->dyn.needed; for (i = 0; needed_list[i] != NULL; i++) printf("NEEDED %s\n", needed_list[i] + strt); }
static void parse_elf_symbols(uintptr_t mem, size_t size, Phdr_t *load, struct vdso_symtable *t, uintptr_t dynsymbol_names, Hash_t *hash, Dyn_t *dyn_symtab) { const char *vdso_symbols[VDSO_SYMBOL_MAX] = { ARCH_VDSO_SYMBOLS }; const size_t vdso_symbol_length = sizeof(t->symbols[0].name); Hash_t nbucket, nchain; Hash_t *bucket, *chain; unsigned int i, j, k; uintptr_t addr; nbucket = hash[0]; nchain = hash[1]; bucket = &hash[2]; chain = &hash[nbucket + 2]; pr_debug("nbucket %lx nchain %lx bucket %lx chain %lx\n", (long)nbucket, (long)nchain, (unsigned long)bucket, (unsigned long)chain); for (i = 0; i < VDSO_SYMBOL_MAX; i++) { const char * symbol = vdso_symbols[i]; k = elf_hash((const unsigned char *)symbol); for (j = bucket[k % nbucket]; j < nchain && chain[j] != STN_UNDEF; j = chain[j]) { addr = mem + dyn_symtab->d_un.d_ptr - load->p_vaddr; Sym_t *sym; char *name; addr += sizeof(Sym_t)*j; if (__ptr_struct_oob(addr, sizeof(Sym_t), mem, size)) continue; sym = (void *)addr; if (ELF_ST_TYPE(sym->st_info) != STT_FUNC && ELF_ST_BIND(sym->st_info) != STB_GLOBAL) continue; addr = dynsymbol_names + sym->st_name; if (__ptr_struct_oob(addr, vdso_symbol_length, mem, size)) continue; name = (void *)addr; if (std_strncmp(name, symbol, vdso_symbol_length)) continue; memcpy(t->symbols[i].name, name, vdso_symbol_length); t->symbols[i].offset = (unsigned long)sym->st_value - load->p_vaddr; break; } } }
int _rtld_relocate_plt_objects(const Obj_Entry *obj) { const Elf_Sym *sym = obj->symtab + obj->gotsym; Elf_Word i; for (i = obj->gotsym; i < obj->symtabno; i++, sym++) { if (ELF_ST_TYPE(sym->st_info) == STT_FUNC) if (_rtld_relocate_plt_object(obj, i, NULL) < 0) return -1; } return 0; }
const char *arch_loader_symbol_lookup(addr_t addr, struct section_data *sd) { elf64_symtab_entry_t *symtab = (elf64_symtab_entry_t *)(sd->vbase[sd->symtab]); addr_t strtab = sd->vbase[sd->strtab]; if(!symtab || !strtab) return NULL; for(unsigned i=0;i<(sd->symlen / sizeof(elf64_symtab_entry_t));i++) { if(ELF_ST_TYPE(symtab[i].info) == ELF_ST_TYPE_FUNCTION) { if(addr >= symtab[i].address && addr < (symtab[i].address + symtab[i].size)) { return (const char *)(strtab + symtab[i].name); } } } return NULL; }
static void * _sym_lookup(DL * dl, Elf_Shdr * shdr, char const * name, char const * strtab, size_t strtab_cnt) { size_t i; Elf_Sym * sym; char const * p; for(i = 0; i < dl->symtab_cnt; i++) { sym = &dl->symtab[i]; if((p = _dl_strtab_string(strtab, strtab_cnt, sym->st_name)) == NULL) return NULL; if(strcmp(p, name) != 0) continue; /* found the symbol */ if(sym->st_shndx >= dl->ehdr.e_shnum) { _dl_error_set(DE_INVALID_FORMAT, 0); return NULL; } #ifdef DEBUG fprintf(stderr, "DEBUG: %s() symbol: %s, section: %u, type=%x" ", value: 0x%x, size: 0x%x\n", __func__, &strtab[sym->st_name], sym->st_shndx, ELF_ST_TYPE(sym->st_info), sym->st_value, sym->st_size); #endif /* FIXME handle only known types */ if(ELF_ST_TYPE(sym->st_info) == STT_FUNC) return (void*)(sym->st_value + dl->text_addr); return (void*)(sym->st_value + dl->data_addr); } _dl_error_set(DE_SYMBOL_NOT_FOUND, 0); return NULL; }
static bool wantsym(const Elf_Sym *sym, const char *strtab) { int type; int bind; type = ELF_ST_TYPE(sym->st_info); bind = ELF_ST_BIND(sym->st_info); if (type != STT_FUNC || (aflag && bind == STB_LOCAL) || (uflag && strchr(strtab + sym->st_name, '.') != NULL)) return 0; return 1; }
static int link_elf_each_function_name(linker_file_t file, int (*callback)(const char *, void *), void *opaque) { elf_file_t ef = (elf_file_t)file; const Elf_Sym *symp; int i, error; /* Exhaustive search */ for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) { if (symp->st_value != 0 && ELF_ST_TYPE(symp->st_info) == STT_FUNC) { error = callback(ef->ddbstrtab + symp->st_name, opaque); if (error) return (error); } } return (0); }
bool ElfSymbolTable::compare(const Elf_Sym* sym, address addr, int* stringtableIndex, int* posIndex, int* offset, ElfFuncDescTable* funcDescTable) { if (STT_FUNC == ELF_ST_TYPE(sym->st_info)) { Elf_Word st_size = sym->st_size; address sym_addr; if (funcDescTable != NULL && funcDescTable->get_index() == sym->st_shndx) { // We need to go another step trough the function descriptor table (currently PPC64 only) sym_addr = funcDescTable->lookup(sym->st_value); } else { sym_addr = (address)sym->st_value; } if (sym_addr <= addr && (Elf_Word)(addr - sym_addr) < st_size) { *offset = (int)(addr - sym_addr); *posIndex = sym->st_name; *stringtableIndex = m_shdr.sh_link; return true; } } return false; }
/* ** ** Get symbol from section. ** */ Elf_Sym* get_elfsym_frm_section(elfobj* obj, Elf_Addr addr, Elf_Shdr* section, int type) { Elf_Sym* start, * end, * ret = NULL; int stop = 0; start = (Elf_Sym *) ((char*) obj->header + section->sh_offset); end = (Elf_Sym *) ((char*) obj->header + section->sh_offset + section->sh_size); /* ** Try to find a symbol whose virtual range includes the target address ** else take a symbol with the highest address less than or equal to the ** target */ for (; !stop && start < end; start++) { /* ** SHF_ALLOC from the man: If the file has a loadable segment that includes ** the symbol table, the section's attributes will include the SHF_ALLOC bit; ** otherwise, that bit will be off. */ if (!( (type == STT_NOTYPE || ELF_ST_TYPE(start->st_info) == type) && start->st_value <= addr && (obj->section_headers[start->st_shndx]->sh_flags & SHF_ALLOC)) ) continue; if (start->st_size) { if (start->st_size + start->st_value > addr) { ret = start; stop = 1; } } else { if (ret == NULL || ret->st_value < start->st_value) ret = start; } } return (ret); }
/* Relocate the jump slots in an object. */ int reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate) { const Elf_Rel *rellim; const Elf_Rel *rel; if (obj->jmpslots_done) return 0; rellim = (const Elf_Rel *)((char *)obj->pltrel + obj->pltrelsize); for (rel = obj->pltrel; rel < rellim; rel++) { Elf_Addr *where, target; const Elf_Sym *def; const Obj_Entry *defobj; switch (ELF_R_TYPE(rel->r_info)) { case R_386_JMP_SLOT: where = (Elf_Addr *)(obj->relocbase + rel->r_offset); def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, SYMLOOK_IN_PLT | flags, NULL, lockstate); if (def == NULL) return (-1); if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { obj->gnu_ifunc = true; continue; } target = (Elf_Addr)(defobj->relocbase + def->st_value); reloc_jmpslot(where, target, defobj, obj, rel); break; case R_386_IRELATIVE: break; default: _rtld_error("Unknown relocation type %x in PLT", ELF_R_TYPE(rel->r_info)); return (-1); } } obj->jmpslots_done = true; return 0; }
const char *arch_loader_lookup_module_symbol(struct module *mq, addr_t addr, char **modname) { /* okay, look up the symbol */ for (unsigned int i = 0; i < (mq->sd.symlen/sizeof (elf64_symtab_entry_t)); i++) { elf64_symtab_entry_t *st; st = &((elf64_symtab_entry_t *)mq->sd.vbase[mq->sd.symtab])[i]; if (ELF_ST_TYPE(st->info) != 0x2) continue; if ( (addr >= st->address) && (addr < (st->address + st->size)) ) { const char *name = (const char *) ((uint64_t)(mq->sd.vbase[mq->sd.strtab]) + st->name); *modname = mq->name; return name; } } return 0; }
/** Convert symbol address to name. * * This function finds the symbol which starts at the highest address * less than or equal to @a addr. * * @param st Symbol table. * @param addr Address for lookup. * @param name Place to store pointer name of symbol, if found. * This is valid while @a st exists. * * @return EOK on success or ENOENT if no matching symbol was found. */ int symtab_addr_to_name(symtab_t *st, uintptr_t addr, char **name, size_t *offs) { size_t i; uintptr_t saddr, best_addr; char *sname, *best_name; unsigned stype; best_name = NULL; best_addr = 0; for (i = 0; i < st->sym_size / sizeof(elf_symbol_t); ++i) { if (st->sym[i].st_name == 0) continue; stype = ELF_ST_TYPE(st->sym[i].st_info); if (stype != STT_OBJECT && stype != STT_FUNC && stype != STT_NOTYPE) { continue; } saddr = st->sym[i].st_value; sname = st->strtab + st->sym[i].st_name; /* An ugly hack to filter out some special ARM symbols. */ if (sname[0] == '$') continue; if (best_name == NULL || (saddr <= addr && saddr > best_addr)) { best_name = sname; best_addr = saddr; } } if (best_name == NULL) return ENOENT; *name = best_name; *offs = addr - best_addr; return EOK; }
int sym6(void) { if(ELF_ST_TYPE(orcSYM->st_info) != STT_SECTION) return 0; if(mode & REL) if(rand() % 2) return 0; unsigned char st_info; do st_info = ELF_ST_INFO(rand() & 0x0f, STT_SECTION); while(ELF_ST_BIND(st_info) == STB_LOCAL); orcSYM->st_info = st_info; fprintf(logfp, "(SYM[%d]->st_info = 0x%.2x)", entry, orcSYM->st_info); return 1; }
int __elfN(lookup_symbol)(struct preloaded_file *fp, elf_file_t ef, const char* name, Elf_Sym *symp) { Elf_Hashelt symnum; Elf_Sym sym; char *strp; unsigned long hash; hash = elf_hash(name); COPYOUT(&ef->buckets[hash % ef->nbuckets], &symnum, sizeof(symnum)); while (symnum != STN_UNDEF) { if (symnum >= ef->nchains) { printf(__elfN(bad_symtable)); return ENOENT; } COPYOUT(ef->symtab + symnum, &sym, sizeof(sym)); if (sym.st_name == 0) { printf(__elfN(bad_symtable)); return ENOENT; } strp = strdupout((vm_offset_t)(ef->strtab + sym.st_name)); if (strcmp(name, strp) == 0) { free(strp); if (sym.st_shndx != SHN_UNDEF || (sym.st_value != 0 && ELF_ST_TYPE(sym.st_info) == STT_FUNC)) { *symp = sym; return 0; } return ENOENT; } free(strp); COPYOUT(&ef->chains[symnum], &symnum, sizeof(symnum)); } return ENOENT; }
static int link_elf_each_function_nameval(linker_file_t file, linker_function_nameval_callback_t callback, void *opaque) { linker_symval_t symval; elf_file_t ef = (elf_file_t)file; const Elf_Sym* symp; int i, error; /* Exhaustive search */ for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) { if (symp->st_value != 0 && ELF_ST_TYPE(symp->st_info) == STT_FUNC) { error = link_elf_symbol_values(file, (c_linker_sym_t) symp, &symval); if (error) return (error); error = callback(file, i, &symval, opaque); if (error) return (error); } } return (0); }
static Elf_Addr SUFFIX (count_funcs) (Elf_Ehdr *e, Elf_Shdr *symtab_section, struct image_target_desc *image_target) { Elf_Word symtab_size, sym_size, num_syms; Elf_Off symtab_offset; Elf_Sym *sym; Elf_Word i; int ret = 0; symtab_size = grub_target_to_host (symtab_section->sh_size); sym_size = grub_target_to_host (symtab_section->sh_entsize); symtab_offset = grub_target_to_host (symtab_section->sh_offset); num_syms = symtab_size / sym_size; for (i = 0, sym = (Elf_Sym *) ((char *) e + symtab_offset); i < num_syms; i++, sym = (Elf_Sym *) ((char *) sym + sym_size)) if (ELF_ST_TYPE (sym->st_info) == STT_FUNC) ret++; return ret; }
/* * LD_BIND_NOW was set - force relocation for all jump slots */ int reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate) { const Obj_Entry *defobj; const Elf_Rela *relalim; const Elf_Rela *rela; const Elf_Sym *def; if (obj->jmpslots_done) return (0); relalim = (const Elf_Rela *)((const char *)obj->pltrela + obj->pltrelasize); for (rela = obj->pltrela; rela < relalim; rela++) { Elf_Addr *where, target; where = (Elf_Addr *)(obj->relocbase + rela->r_offset); switch(ELF_R_TYPE(rela->r_info)) { case R_AARCH64_JUMP_SLOT: def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, SYMLOOK_IN_PLT | flags, NULL, lockstate); if (def == NULL) return (-1); if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { obj->gnu_ifunc = true; continue; } target = (Elf_Addr)(defobj->relocbase + def->st_value); reloc_jmpslot(where, target, defobj, obj, (const Elf_Rel *)rela); break; } } obj->jmpslots_done = true; return (0); }
/** Convert symbol name to address. * * @param st Symbol table. * @param name Name of the symbol. * @param addr Place to store address for symbol, if found. * * @return EOK on success, ENOENT if no such symbol was found. */ int symtab_name_to_addr(symtab_t *st, char *name, uintptr_t *addr) { size_t i; char *sname; unsigned stype; for (i = 0; i < st->sym_size / sizeof(elf_symbol_t); ++i) { if (st->sym[i].st_name == 0) continue; stype = ELF_ST_TYPE(st->sym[i].st_info); if (stype != STT_OBJECT && stype != STT_FUNC) continue; sname = st->strtab + st->sym[i].st_name; if (str_cmp(sname, name) == 0) { *addr = st->sym[i].st_value; return EOK; } } return ENOENT; }