1da0c48c4Sopenharmony_ci/* Copyright (C) 2005, 2007, 2008 Red Hat, Inc. 2da0c48c4Sopenharmony_ci This file is part of elfutils. 3da0c48c4Sopenharmony_ci Written by Ulrich Drepper <drepper@redhat.com>, 2005. 4da0c48c4Sopenharmony_ci 5da0c48c4Sopenharmony_ci This file is free software; you can redistribute it and/or modify 6da0c48c4Sopenharmony_ci it under the terms of either 7da0c48c4Sopenharmony_ci 8da0c48c4Sopenharmony_ci * the GNU Lesser General Public License as published by the Free 9da0c48c4Sopenharmony_ci Software Foundation; either version 3 of the License, or (at 10da0c48c4Sopenharmony_ci your option) any later version 11da0c48c4Sopenharmony_ci 12da0c48c4Sopenharmony_ci or 13da0c48c4Sopenharmony_ci 14da0c48c4Sopenharmony_ci * the GNU General Public License as published by the Free 15da0c48c4Sopenharmony_ci Software Foundation; either version 2 of the License, or (at 16da0c48c4Sopenharmony_ci your option) any later version 17da0c48c4Sopenharmony_ci 18da0c48c4Sopenharmony_ci or both in parallel, as here. 19da0c48c4Sopenharmony_ci 20da0c48c4Sopenharmony_ci elfutils is distributed in the hope that it will be useful, but 21da0c48c4Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 22da0c48c4Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23da0c48c4Sopenharmony_ci General Public License for more details. 24da0c48c4Sopenharmony_ci 25da0c48c4Sopenharmony_ci You should have received copies of the GNU General Public License and 26da0c48c4Sopenharmony_ci the GNU Lesser General Public License along with this program. If 27da0c48c4Sopenharmony_ci not, see <http://www.gnu.org/licenses/>. */ 28da0c48c4Sopenharmony_ci 29da0c48c4Sopenharmony_ci#ifdef HAVE_CONFIG_H 30da0c48c4Sopenharmony_ci# include <config.h> 31da0c48c4Sopenharmony_ci#endif 32da0c48c4Sopenharmony_ci 33da0c48c4Sopenharmony_ci#include <string.h> 34da0c48c4Sopenharmony_ci 35da0c48c4Sopenharmony_ci#include "libasmP.h" 36da0c48c4Sopenharmony_ci#include "../libebl/libeblP.h" 37da0c48c4Sopenharmony_ci 38da0c48c4Sopenharmony_ci 39da0c48c4Sopenharmony_cistruct symtoken 40da0c48c4Sopenharmony_ci{ 41da0c48c4Sopenharmony_ci DisasmCtx_t *ctx; 42da0c48c4Sopenharmony_ci void *symcbarg; 43da0c48c4Sopenharmony_ci}; 44da0c48c4Sopenharmony_ci 45da0c48c4Sopenharmony_ci 46da0c48c4Sopenharmony_cistatic int 47da0c48c4Sopenharmony_cidefault_elf_getsym (GElf_Addr addr, Elf32_Word scnndx, GElf_Addr value, 48da0c48c4Sopenharmony_ci char **buf, size_t *buflen, void *arg) 49da0c48c4Sopenharmony_ci{ 50da0c48c4Sopenharmony_ci struct symtoken *symtoken = (struct symtoken *) arg; 51da0c48c4Sopenharmony_ci 52da0c48c4Sopenharmony_ci /* First try the user provided function. */ 53da0c48c4Sopenharmony_ci if (symtoken->ctx->symcb != NULL) 54da0c48c4Sopenharmony_ci { 55da0c48c4Sopenharmony_ci int res = symtoken->ctx->symcb (addr, scnndx, value, buf, buflen, 56da0c48c4Sopenharmony_ci symtoken->symcbarg); 57da0c48c4Sopenharmony_ci if (res >= 0) 58da0c48c4Sopenharmony_ci return res; 59da0c48c4Sopenharmony_ci } 60da0c48c4Sopenharmony_ci 61da0c48c4Sopenharmony_ci // XXX Look up in ELF file. 62da0c48c4Sopenharmony_ci 63da0c48c4Sopenharmony_ci return -1; 64da0c48c4Sopenharmony_ci} 65da0c48c4Sopenharmony_ci 66da0c48c4Sopenharmony_ci 67da0c48c4Sopenharmony_cistruct symaddrpair 68da0c48c4Sopenharmony_ci{ 69da0c48c4Sopenharmony_ci GElf_Addr addr; 70da0c48c4Sopenharmony_ci const char *name; 71da0c48c4Sopenharmony_ci}; 72da0c48c4Sopenharmony_ci 73da0c48c4Sopenharmony_ci 74da0c48c4Sopenharmony_cistatic void 75da0c48c4Sopenharmony_ciread_symtab_exec (DisasmCtx_t *ctx) 76da0c48c4Sopenharmony_ci{ 77da0c48c4Sopenharmony_ci /* We simply use all we can get our hands on. This will produce 78da0c48c4Sopenharmony_ci some duplicate information but this is no problem, we simply 79da0c48c4Sopenharmony_ci ignore the latter definitions. */ 80da0c48c4Sopenharmony_ci Elf_Scn *scn= NULL; 81da0c48c4Sopenharmony_ci while ((scn = elf_nextscn (ctx->elf, scn)) != NULL) 82da0c48c4Sopenharmony_ci { 83da0c48c4Sopenharmony_ci GElf_Shdr shdr_mem; 84da0c48c4Sopenharmony_ci GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 85da0c48c4Sopenharmony_ci Elf_Data *data; 86da0c48c4Sopenharmony_ci if (shdr == NULL || shdr->sh_type != SHT_SYMTAB 87da0c48c4Sopenharmony_ci || (data = elf_getdata (scn, NULL)) == NULL) 88da0c48c4Sopenharmony_ci continue; 89da0c48c4Sopenharmony_ci 90da0c48c4Sopenharmony_ci int xndxscnidx = elf_scnshndx (scn); 91da0c48c4Sopenharmony_ci Elf_Data *xndxdata = NULL; 92da0c48c4Sopenharmony_ci if (xndxscnidx > 0) 93da0c48c4Sopenharmony_ci xndxdata = elf_getdata (elf_getscn (ctx->elf, xndxscnidx), NULL); 94da0c48c4Sopenharmony_ci 95da0c48c4Sopenharmony_ci /* Iterate over all symbols. Add all defined symbols. */ 96da0c48c4Sopenharmony_ci if (shdr->sh_entsize == 0) 97da0c48c4Sopenharmony_ci continue; 98da0c48c4Sopenharmony_ci int nsyms = shdr->sh_size / shdr->sh_entsize; 99da0c48c4Sopenharmony_ci for (int cnt = 1; cnt < nsyms; ++cnt) 100da0c48c4Sopenharmony_ci { 101da0c48c4Sopenharmony_ci Elf32_Word xshndx; 102da0c48c4Sopenharmony_ci GElf_Sym sym_mem; 103da0c48c4Sopenharmony_ci GElf_Sym *sym = gelf_getsymshndx (data, xndxdata, cnt, &sym_mem, 104da0c48c4Sopenharmony_ci &xshndx); 105da0c48c4Sopenharmony_ci if (sym == NULL) 106da0c48c4Sopenharmony_ci continue; 107da0c48c4Sopenharmony_ci 108da0c48c4Sopenharmony_ci /* Undefined symbols are useless here. */ 109da0c48c4Sopenharmony_ci if (sym->st_shndx == SHN_UNDEF) 110da0c48c4Sopenharmony_ci continue; 111da0c48c4Sopenharmony_ci 112da0c48c4Sopenharmony_ci 113da0c48c4Sopenharmony_ci } 114da0c48c4Sopenharmony_ci } 115da0c48c4Sopenharmony_ci} 116da0c48c4Sopenharmony_ci 117da0c48c4Sopenharmony_ci 118da0c48c4Sopenharmony_cistatic void 119da0c48c4Sopenharmony_ciread_symtab (DisasmCtx_t *ctx) 120da0c48c4Sopenharmony_ci{ 121da0c48c4Sopenharmony_ci /* Find the symbol table(s). */ 122da0c48c4Sopenharmony_ci GElf_Ehdr ehdr_mem; 123da0c48c4Sopenharmony_ci GElf_Ehdr *ehdr = gelf_getehdr (ctx->elf, &ehdr_mem); 124da0c48c4Sopenharmony_ci if (ehdr == NULL) 125da0c48c4Sopenharmony_ci return; 126da0c48c4Sopenharmony_ci 127da0c48c4Sopenharmony_ci switch (ehdr->e_type) 128da0c48c4Sopenharmony_ci { 129da0c48c4Sopenharmony_ci case ET_EXEC: 130da0c48c4Sopenharmony_ci case ET_DYN: 131da0c48c4Sopenharmony_ci read_symtab_exec (ctx); 132da0c48c4Sopenharmony_ci break; 133da0c48c4Sopenharmony_ci 134da0c48c4Sopenharmony_ci case ET_REL: 135da0c48c4Sopenharmony_ci // XXX Handle 136da0c48c4Sopenharmony_ci break; 137da0c48c4Sopenharmony_ci 138da0c48c4Sopenharmony_ci default: 139da0c48c4Sopenharmony_ci break; 140da0c48c4Sopenharmony_ci } 141da0c48c4Sopenharmony_ci} 142da0c48c4Sopenharmony_ci 143da0c48c4Sopenharmony_ci 144da0c48c4Sopenharmony_cistatic int 145da0c48c4Sopenharmony_cinull_elf_getsym (GElf_Addr addr __attribute__ ((unused)), 146da0c48c4Sopenharmony_ci Elf32_Word scnndx __attribute__ ((unused)), 147da0c48c4Sopenharmony_ci GElf_Addr value __attribute__ ((unused)), 148da0c48c4Sopenharmony_ci char **buf __attribute__ ((unused)), 149da0c48c4Sopenharmony_ci size_t *buflen __attribute__ ((unused)), 150da0c48c4Sopenharmony_ci void *arg __attribute__ ((unused))) 151da0c48c4Sopenharmony_ci{ 152da0c48c4Sopenharmony_ci return -1; 153da0c48c4Sopenharmony_ci} 154da0c48c4Sopenharmony_ci 155da0c48c4Sopenharmony_ci 156da0c48c4Sopenharmony_ciint 157da0c48c4Sopenharmony_cidisasm_cb (DisasmCtx_t *ctx, const uint8_t **startp, const uint8_t *end, 158da0c48c4Sopenharmony_ci GElf_Addr addr, const char *fmt, DisasmOutputCB_t outcb, 159da0c48c4Sopenharmony_ci void *outcbarg, void *symcbarg) 160da0c48c4Sopenharmony_ci{ 161da0c48c4Sopenharmony_ci struct symtoken symtoken; 162da0c48c4Sopenharmony_ci DisasmGetSymCB_t getsym = ctx->symcb ?: null_elf_getsym; 163da0c48c4Sopenharmony_ci 164da0c48c4Sopenharmony_ci if (ctx->elf != NULL) 165da0c48c4Sopenharmony_ci { 166da0c48c4Sopenharmony_ci /* Read all symbols of the ELF file and stuff them into a hash 167da0c48c4Sopenharmony_ci table. The key is the address and the section index. */ 168da0c48c4Sopenharmony_ci read_symtab (ctx); 169da0c48c4Sopenharmony_ci 170da0c48c4Sopenharmony_ci symtoken.ctx = ctx; 171da0c48c4Sopenharmony_ci symtoken.symcbarg = symcbarg; 172da0c48c4Sopenharmony_ci 173da0c48c4Sopenharmony_ci symcbarg = &symtoken; 174da0c48c4Sopenharmony_ci 175da0c48c4Sopenharmony_ci getsym = default_elf_getsym; 176da0c48c4Sopenharmony_ci } 177da0c48c4Sopenharmony_ci 178da0c48c4Sopenharmony_ci return ctx->ebl->disasm (ctx->ebl, startp, end, addr, fmt, outcb, 179da0c48c4Sopenharmony_ci getsym, outcbarg, symcbarg); 180da0c48c4Sopenharmony_ci} 181da0c48c4Sopenharmony_ciINTDEF (disasm_cb) 182