Branch data 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 "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 : 0 : GElf_Shdr shdr_mem;
84 : 0 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
85 : 0 : 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 : if (shdr->sh_entsize == 0)
97 : 0 : continue;
98 : 0 : int nsyms = shdr->sh_size / shdr->sh_entsize;
99 [ # # ]: 0 : for (int cnt = 1; cnt < nsyms; ++cnt)
100 : : {
101 : 0 : Elf32_Word xshndx;
102 : 0 : GElf_Sym sym_mem;
103 : 0 : GElf_Sym *sym = gelf_getsymshndx (data, xndxdata, cnt, &sym_mem,
104 : : &xshndx);
105 : 0 : if (sym == NULL)
106 : 0 : continue;
107 : :
108 : : /* Undefined symbols are useless here. */
109 : : if (sym->st_shndx == SHN_UNDEF)
110 : : continue;
111 : :
112 : :
113 : : }
114 : : }
115 : 0 : }
116 : :
117 : :
118 : : static void
119 : 4 : read_symtab (DisasmCtx_t *ctx)
120 : : {
121 : : /* Find the symbol table(s). */
122 : 4 : GElf_Ehdr ehdr_mem;
123 : 4 : GElf_Ehdr *ehdr = gelf_getehdr (ctx->elf, &ehdr_mem);
124 [ - + ]: 4 : if (ehdr == NULL)
125 : 0 : return;
126 : :
127 [ - + ]: 4 : switch (ehdr->e_type)
128 : : {
129 : 0 : case ET_EXEC:
130 : : case ET_DYN:
131 : 0 : read_symtab_exec (ctx);
132 : 0 : break;
133 : :
134 : : case ET_REL:
135 : : // XXX Handle
136 : : break;
137 : :
138 : : default:
139 : : break;
140 : : }
141 : : }
142 : :
143 : :
144 : : static int
145 : 0 : null_elf_getsym (GElf_Addr addr __attribute__ ((unused)),
146 : : Elf32_Word scnndx __attribute__ ((unused)),
147 : : GElf_Addr value __attribute__ ((unused)),
148 : : char **buf __attribute__ ((unused)),
149 : : size_t *buflen __attribute__ ((unused)),
150 : : void *arg __attribute__ ((unused)))
151 : : {
152 : 0 : return -1;
153 : : }
154 : :
155 : :
156 : : int
157 : 4 : disasm_cb (DisasmCtx_t *ctx, const uint8_t **startp, const uint8_t *end,
158 : : GElf_Addr addr, const char *fmt, DisasmOutputCB_t outcb,
159 : : void *outcbarg, void *symcbarg)
160 : : {
161 : 4 : struct symtoken symtoken;
162 [ + - ]: 4 : DisasmGetSymCB_t getsym = ctx->symcb ?: null_elf_getsym;
163 : :
164 [ + - ]: 4 : if (ctx->elf != NULL)
165 : : {
166 : : /* Read all symbols of the ELF file and stuff them into a hash
167 : : table. The key is the address and the section index. */
168 : 4 : read_symtab (ctx);
169 : :
170 : 4 : symtoken.ctx = ctx;
171 : 4 : symtoken.symcbarg = symcbarg;
172 : :
173 : 4 : symcbarg = &symtoken;
174 : :
175 : 4 : getsym = default_elf_getsym;
176 : : }
177 : :
178 : 4 : return ctx->ebl->disasm (ctx->ebl, startp, end, addr, fmt, outcb,
179 : : getsym, outcbarg, symcbarg);
180 : : }
181 : : INTDEF (disasm_cb)
|