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