1 /* This file is part of centaur.
3 * centaur is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License 2 as
5 * published by the Free Software Foundation.
7 * centaur is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with centaur. If not, see <http://www.gnu.org/licenses/>.
19 #include <libelfu/libelfu.h>
22 int elfu_mSymtabLookupSymToAddr(ElfuElf *me, ElfuScn *msst, ElfuSym *sym, GElf_Addr *result)
24 char *symname = ELFU_SYMSTR(msst, sym->name);
30 if (sym->shndx == SHN_UNDEF) {
32 } else if (sym->shndx == SHN_ABS) {
35 } else if (sym->shndx == SHN_COMMON) {
41 newscn = elfu_mScnByOldscn(me, sym->scnptr);
43 *result = newscn->shdr.sh_addr + sym->value;
49 assert(elfu_mScnByOldscn(me, sym->scnptr));
50 *result = elfu_mScnByOldscn(me, sym->scnptr)->shdr.sh_addr;
53 ELFU_WARN("elfu_mSymtabLookupSymToAddr: Symbol type FILE is not supported.\n");
56 ELFU_WARN("elfu_mSymtabLookupSymToAddr: Unknown symbol type %d for %s.\n", sym->type, symname);
63 char* elfu_mSymtabSymToName(ElfuScn *msst, ElfuSym *sym)
68 return ELFU_SYMSTR(msst, sym->name);
73 ElfuSym* elfu_mSymtabIndexToSym(ElfuScn *msst, GElf_Word entry)
80 assert(!CIRCLEQ_EMPTY(&msst->symtab.syms));
82 sym = CIRCLEQ_FIRST(&msst->symtab.syms);
83 for (i = 1; i < entry; i++) {
84 sym = CIRCLEQ_NEXT(sym, elem);
92 /* Look up a value in the symbol table section *msst which is in *me. */
93 GElf_Addr elfu_mSymtabLookupAddrByName(ElfuElf *me, ElfuScn *msst, char *name)
100 assert(strlen(name) > 0);
101 assert(!CIRCLEQ_EMPTY(&msst->symtab.syms));
103 CIRCLEQ_FOREACH(sym, &msst->symtab.syms, elem) {
104 char *symname = ELFU_SYMSTR(msst, sym->name);
106 if (!strcmp(symname, name)) {
120 GElf_Addr a = sym->value;
121 a += me->ehdr.e_type == ET_REL ? sym->scnptr->shdr.sh_addr : 0;
123 } else if (sym->shndx == SHN_UNDEF) {
125 } else if (sym->shndx == SHN_ABS) {
128 ELFU_WARN("elfu_mSymtabLookupAddrByName: Symbol binding COMMON is not supported, using 0.\n");
139 /* Convert symtab from memory model to elfclass specific format */
140 void elfu_mSymtabFlatten(ElfuElf *me)
145 elfu_mLayoutAuto(me);
147 /* Update section indexes and count symbols */
148 CIRCLEQ_FOREACH(sym, &me->symtab->symtab.syms, elem) {
150 sym->shndx = elfu_mScnIndex(me, sym->scnptr);
156 /* Copy symbols to elfclass-specific format */
157 if (me->elfclass == ELFCLASS32) {
158 size_t newsize = (numsyms + 1) * sizeof(Elf32_Sym);
161 if (me->symtab->databuf) {
162 free(me->symtab->databuf);
164 me->symtab->databuf = malloc(newsize);
165 assert(me->symtab->databuf);
167 me->symtab->shdr.sh_size = newsize;
168 memset(me->symtab->databuf, 0, newsize);
171 CIRCLEQ_FOREACH(sym, &me->symtab->symtab.syms, elem) {
172 Elf32_Sym *es = ((Elf32_Sym*)me->symtab->databuf) + i;
174 es->st_name = sym->name;
175 es->st_value = sym->value;
176 es->st_size = sym->size;
177 es->st_info = ELF32_ST_INFO(sym->bind, sym->type);
178 es->st_other = sym->other;
179 es->st_shndx = sym->shndx;
183 } else if (me->elfclass == ELFCLASS64) {
184 size_t newsize = (numsyms + 1) * sizeof(Elf64_Sym);
187 if (me->symtab->databuf) {
188 free(me->symtab->databuf);
190 me->symtab->databuf = malloc(newsize);
191 assert(me->symtab->databuf);
193 me->symtab->shdr.sh_size = newsize;
194 memset(me->symtab->databuf, 0, newsize);
197 CIRCLEQ_FOREACH(sym, &me->symtab->symtab.syms, elem) {
198 Elf64_Sym *es = ((Elf64_Sym*)me->symtab->databuf) + i;
200 es->st_name = sym->name;
201 es->st_value = sym->value;
202 es->st_size = sym->size;
203 es->st_info = ELF64_ST_INFO(sym->bind, sym->type);
204 es->st_other = sym->other;
205 es->st_shndx = sym->shndx;
210 /* Unknown elfclass */
214 elfu_mLayoutAuto(me);
219 void elfu_mSymtabAddGlobalDymtabIfNotPresent(ElfuElf *me)
227 symtab = elfu_mScnAlloc();
229 strtab = elfu_mScnAlloc();
232 symtab->linkptr = strtab;
233 symtab->shdr.sh_entsize = me->elfclass == ELFCLASS32 ? sizeof(Elf32_Sym) : sizeof(Elf64_Sym);
234 symtab->shdr.sh_addralign = 4;
235 strtab->shdr.sh_addralign = 1;
236 symtab->shdr.sh_type = SHT_SYMTAB;
237 strtab->shdr.sh_type = SHT_STRTAB;
239 strtab->databuf = malloc(1);
240 assert(strtab->databuf);
241 strtab->databuf[0] = 0;
243 CIRCLEQ_INSERT_TAIL(&me->orphanScnList, symtab, elemChildScn);
244 CIRCLEQ_INSERT_TAIL(&me->orphanScnList, strtab, elemChildScn);
249 symtab->shdr.sh_name = me->shstrtab->shdr.sh_size;
250 if (elfu_mScnAppendData(me->shstrtab, ".symtab", 8)) {
251 symtab->shdr.sh_name = 0;
254 strtab->shdr.sh_name = me->shstrtab->shdr.sh_size;
255 if (elfu_mScnAppendData(me->shstrtab, ".strtab", 8)) {
256 strtab->shdr.sh_name = 0;