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