4 #include <libelfu/libelfu.h>
7 int elfu_mSymtabLookupSymToAddr(ElfuElf *me, ElfuScn *msst, ElfuSym *sym, GElf_Addr *result)
9 char *symname = ELFU_SYMSTR(msst, sym->name);
15 if (sym->shndx == SHN_UNDEF) {
17 } else if (sym->shndx == SHN_ABS) {
20 } else if (sym->shndx == SHN_COMMON) {
26 newscn = elfu_mScnByOldscn(me, sym->scnptr);
28 *result = newscn->shdr.sh_addr + sym->value;
34 assert(elfu_mScnByOldscn(me, sym->scnptr));
35 *result = elfu_mScnByOldscn(me, sym->scnptr)->shdr.sh_addr;
38 ELFU_WARN("elfu_mSymtabLookupSymToAddr: Symbol type FILE is not supported.\n");
41 ELFU_WARN("elfu_mSymtabLookupSymToAddr: Unknown symbol type %d for %s.\n", sym->type, symname);
48 char* elfu_mSymtabSymToName(ElfuScn *msst, ElfuSym *sym)
53 return ELFU_SYMSTR(msst, sym->name);
58 ElfuSym* elfu_mSymtabIndexToSym(ElfuScn *msst, GElf_Word entry)
65 assert(!CIRCLEQ_EMPTY(&msst->symtab.syms));
67 sym = CIRCLEQ_FIRST(&msst->symtab.syms);
68 for (i = 1; i < entry; i++) {
69 sym = CIRCLEQ_NEXT(sym, elem);
77 /* Look up a value in the symbol table section *msst which is in *me. */
78 GElf_Addr elfu_mSymtabLookupAddrByName(ElfuElf *me, ElfuScn *msst, char *name)
85 assert(strlen(name) > 0);
86 assert(!CIRCLEQ_EMPTY(&msst->symtab.syms));
88 CIRCLEQ_FOREACH(sym, &msst->symtab.syms, elem) {
89 char *symname = ELFU_SYMSTR(msst, sym->name);
91 if (!strcmp(symname, name)) {
105 GElf_Addr a = sym->value;
106 a += me->ehdr.e_type == ET_REL ? sym->scnptr->shdr.sh_addr : 0;
108 } else if (sym->shndx == SHN_UNDEF) {
110 } else if (sym->shndx == SHN_ABS) {
113 ELFU_WARN("elfu_mSymtabLookupAddrByName: Symbol binding COMMON is not supported, using 0.\n");
124 /* Convert symtab from memory model to elfclass specific format */
125 void elfu_mSymtabFlatten(ElfuElf *me)
130 elfu_mLayoutAuto(me);
132 /* Update section indexes and count symbols */
133 CIRCLEQ_FOREACH(sym, &me->symtab->symtab.syms, elem) {
135 sym->shndx = elfu_mScnIndex(me, sym->scnptr);
141 /* Copy symbols to elfclass-specific format */
142 if (me->elfclass == ELFCLASS32) {
143 size_t newsize = (numsyms + 1) * sizeof(Elf32_Sym);
146 if (me->symtab->databuf) {
147 free(me->symtab->databuf);
149 me->symtab->databuf = malloc(newsize);
150 assert(me->symtab->databuf);
152 me->symtab->shdr.sh_size = newsize;
153 memset(me->symtab->databuf, 0, newsize);
156 CIRCLEQ_FOREACH(sym, &me->symtab->symtab.syms, elem) {
157 Elf32_Sym *es = ((Elf32_Sym*)me->symtab->databuf) + i;
159 es->st_name = sym->name;
160 es->st_value = sym->value;
161 es->st_size = sym->size;
162 es->st_info = ELF32_ST_INFO(sym->bind, sym->type);
163 es->st_other = sym->other;
164 es->st_shndx = sym->shndx;
168 } else if (me->elfclass == ELFCLASS64) {
169 size_t newsize = (numsyms + 1) * sizeof(Elf64_Sym);
172 if (me->symtab->databuf) {
173 free(me->symtab->databuf);
175 me->symtab->databuf = malloc(newsize);
176 assert(me->symtab->databuf);
178 me->symtab->shdr.sh_size = newsize;
179 memset(me->symtab->databuf, 0, newsize);
182 CIRCLEQ_FOREACH(sym, &me->symtab->symtab.syms, elem) {
183 Elf64_Sym *es = ((Elf64_Sym*)me->symtab->databuf) + i;
185 es->st_name = sym->name;
186 es->st_value = sym->value;
187 es->st_size = sym->size;
188 es->st_info = ELF64_ST_INFO(sym->bind, sym->type);
189 es->st_other = sym->other;
190 es->st_shndx = sym->shndx;
195 /* Unknown elfclass */
199 elfu_mLayoutAuto(me);
204 void elfu_mSymtabAddGlobalDymtabIfNotPresent(ElfuElf *me)
212 symtab = elfu_mScnAlloc();
214 strtab = elfu_mScnAlloc();
217 symtab->linkptr = strtab;
218 symtab->shdr.sh_entsize = me->elfclass == ELFCLASS32 ? sizeof(Elf32_Sym) : sizeof(Elf64_Sym);
219 symtab->shdr.sh_addralign = 4;
220 strtab->shdr.sh_addralign = 1;
221 symtab->shdr.sh_type = SHT_SYMTAB;
222 strtab->shdr.sh_type = SHT_STRTAB;
224 strtab->databuf = malloc(1);
225 assert(strtab->databuf);
226 strtab->databuf[0] = 0;
228 CIRCLEQ_INSERT_TAIL(&me->orphanScnList, symtab, elemChildScn);
229 CIRCLEQ_INSERT_TAIL(&me->orphanScnList, strtab, elemChildScn);
234 symtab->shdr.sh_name = me->shstrtab->shdr.sh_size;
235 if (elfu_mScnAppendData(me->shstrtab, ".symtab", 8)) {
236 symtab->shdr.sh_name = 0;
239 strtab->shdr.sh_name = me->shstrtab->shdr.sh_size;
240 if (elfu_mScnAppendData(me->shstrtab, ".strtab", 8)) {
241 strtab->shdr.sh_name = 0;