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