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 "../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 : 111 : 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 [ # # ]: 0 : if (sym == NULL)
104 : 0 : continue;
105 : :
106 : : /* Undefined symbols are useless here. */
107 [ # # ]: 0 : if (sym->st_shndx == SHN_UNDEF)
108 : 0 : continue;
109 : :
110 : :
111 : : }
112 : : }
113 : 0 : }
114 : :
115 : :
116 : : static void
117 : 2 : read_symtab (DisasmCtx_t *ctx)
118 : : {
119 : : /* Find the symbol table(s). */
120 : : GElf_Ehdr ehdr_mem;
121 : 2 : GElf_Ehdr *ehdr = gelf_getehdr (ctx->elf, &ehdr_mem);
122 [ + - ]: 2 : if (ehdr == NULL)
123 : 2 : return;
124 : :
125 [ - + ]: 2 : switch (ehdr->e_type)
126 : : {
127 : : case ET_EXEC:
128 : : case ET_DYN:
129 : 0 : read_symtab_exec (ctx);
130 : 2 : 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 : 2 : 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 [ - + ]: 2 : DisasmGetSymCB_t getsym = ctx->symcb ?: null_elf_getsym;
161 : :
162 [ + - ]: 2 : 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 : 2 : read_symtab (ctx);
167 : :
168 : 2 : symtoken.ctx = ctx;
169 : 2 : symtoken.symcbarg = symcbarg;
170 : :
171 : 2 : symcbarg = &symtoken;
172 : :
173 : 2 : getsym = default_elf_getsym;
174 : : }
175 : :
176 : 2 : return ctx->ebl->disasm (startp, end, addr, fmt, outcb, getsym, outcbarg,
177 : : symcbarg);
178 : : }
179 : 0 : INTDEF (disasm_cb)
|