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