File: | ddb/db_elf.c |
Warning: | line 67, column 8 Value stored to 'errstr' during its initialization is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: db_elf.c,v 1.32 2021/03/12 10:22:46 jsg Exp $ */ |
2 | /* $NetBSD: db_elf.c,v 1.13 2000/07/07 21:55:18 jhawk Exp $ */ |
3 | |
4 | /*- |
5 | * Copyright (c) 1997 The NetBSD Foundation, Inc. |
6 | * All rights reserved. |
7 | * |
8 | * This code is derived from software contributed to The NetBSD Foundation |
9 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, |
10 | * NASA Ames Research Center. |
11 | * |
12 | * Redistribution and use in source and binary forms, with or without |
13 | * modification, are permitted provided that the following conditions |
14 | * are met: |
15 | * 1. Redistributions of source code must retain the above copyright |
16 | * notice, this list of conditions and the following disclaimer. |
17 | * 2. Redistributions in binary form must reproduce the above copyright |
18 | * notice, this list of conditions and the following disclaimer in the |
19 | * documentation and/or other materials provided with the distribution. |
20 | * |
21 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
22 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
23 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
24 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
31 | * POSSIBILITY OF SUCH DAMAGE. |
32 | */ |
33 | |
34 | #include <sys/param.h> |
35 | #include <sys/stdint.h> |
36 | #include <sys/systm.h> |
37 | #include <sys/exec.h> |
38 | |
39 | #include <machine/db_machdep.h> |
40 | |
41 | #include <ddb/db_elf.h> |
42 | #include <ddb/db_sym.h> |
43 | #include <ddb/db_output.h> |
44 | |
45 | #include <sys/exec_elf.h> |
46 | |
47 | db_symtab_t db_symtab; |
48 | |
49 | Elf_SymElf64_Sym *db_elf_sym_lookup(char *); |
50 | |
51 | /* |
52 | * Find the symbol table and strings; tell ddb about them. |
53 | * |
54 | * symsize: size of symbol table |
55 | * symtab: pointer to start of symbol table |
56 | * esymtab: pointer to end of string table, for checking - rounded up to |
57 | * integer boundary |
58 | */ |
59 | int |
60 | db_elf_sym_init(int symsize, void *symtab, void *esymtab, const char *name) |
61 | { |
62 | Elf_EhdrElf64_Ehdr *elf; |
63 | Elf_ShdrElf64_Shdr *shp; |
64 | Elf_SymElf64_Sym *symp, *symtab_start, *symtab_end; |
65 | char *shstrtab, *strtab_start, *strtab_end; |
66 | int i; |
67 | char *errstr = ""; |
Value stored to 'errstr' during its initialization is never read | |
68 | |
69 | if (ALIGNED_POINTER(symtab, long)1 == 0) { |
70 | db_printf("[ %s symbol table has bad start address %p ]\n", |
71 | name, symtab); |
72 | return (0); |
73 | } |
74 | |
75 | symtab_start = symtab_end = NULL((void *)0); |
76 | strtab_start = strtab_end = NULL((void *)0); |
77 | |
78 | /* |
79 | * The format of the symbols loaded by the boot program is: |
80 | * |
81 | * Elf exec header |
82 | * first section header |
83 | * . . . |
84 | * . . . |
85 | * last section header |
86 | * first symbol, string, or line table section |
87 | * . . . |
88 | * . . . |
89 | * last symbol, string, or line table section |
90 | */ |
91 | |
92 | /* |
93 | * Validate the Elf header. |
94 | */ |
95 | elf = (Elf_EhdrElf64_Ehdr *)symtab; |
96 | if (memcmp(elf->e_ident, ELFMAG, SELFMAG)__builtin_memcmp((elf->e_ident), ("\177ELF"), (4)) != 0 || |
97 | elf->e_ident[EI_CLASS4] != ELFCLASS2) { |
98 | errstr = "bad magic"; |
99 | goto badheader; |
100 | } |
101 | |
102 | if (elf->e_machine != ELF_TARG_MACH62) { |
103 | errstr = "bad e_machine"; |
104 | goto badheader; |
105 | } |
106 | |
107 | /* |
108 | * Find the section header string table (.shstrtab), and look up |
109 | * the symbol table (.symtab) and string table (.strtab) via their |
110 | * names in shstrtab, rather than by table type. |
111 | * This works in the presence of multiple string tables, such as |
112 | * stabs data found when booting bsd.gdb. |
113 | */ |
114 | shp = (Elf_ShdrElf64_Shdr *)((char *)symtab + elf->e_shoff); |
115 | shstrtab = (char *)symtab + shp[elf->e_shstrndx].sh_offset; |
116 | for (i = 0; i < elf->e_shnum; i++) { |
117 | if (shp[i].sh_type == SHT_SYMTAB2) { |
118 | int j; |
119 | |
120 | if (shp[i].sh_offset == 0) |
121 | continue; |
122 | symtab_start = (Elf_SymElf64_Sym *)((char *)symtab + |
123 | shp[i].sh_offset); |
124 | symtab_end = (Elf_SymElf64_Sym *)((char *)symtab + |
125 | shp[i].sh_offset + shp[i].sh_size); |
126 | j = shp[i].sh_link; |
127 | if (shp[j].sh_offset == 0) |
128 | continue; |
129 | strtab_start = (char *)symtab + shp[j].sh_offset; |
130 | strtab_end = (char *)symtab + shp[j].sh_offset + |
131 | shp[j].sh_size; |
132 | break; |
133 | } |
134 | |
135 | /* |
136 | * This is the old way of doing things. |
137 | * XXX - verify that it's not needed. |
138 | */ |
139 | if (strcmp(".strtab", shstrtab+shp[i].sh_name) == 0) { |
140 | strtab_start = (char *)symtab + shp[i].sh_offset; |
141 | strtab_end = (char *)symtab + shp[i].sh_offset + |
142 | shp[i].sh_size; |
143 | } else if (strcmp(".symtab", shstrtab+shp[i].sh_name) == 0) { |
144 | symtab_start = (Elf_SymElf64_Sym *)((char *)symtab + |
145 | shp[i].sh_offset); |
146 | symtab_end = (Elf_SymElf64_Sym *)((char *)symtab + |
147 | shp[i].sh_offset + shp[i].sh_size); |
148 | } |
149 | } |
150 | |
151 | /* |
152 | * Now, sanity check the symbols against the string table. |
153 | */ |
154 | if (symtab_start == NULL((void *)0) || strtab_start == NULL((void *)0) || |
155 | ALIGNED_POINTER(symtab_start, long)1 == 0) { |
156 | errstr = "symtab unaligned"; |
157 | goto badheader; |
158 | } |
159 | for (symp = symtab_start; symp < symtab_end; symp++) |
160 | if (symp->st_name + strtab_start > strtab_end) { |
161 | errstr = "symtab corrupted"; |
162 | goto badheader; |
163 | } |
164 | |
165 | /* |
166 | * Link the symbol table into the debugger. |
167 | */ |
168 | db_symtab.start = (char *)symtab_start; |
169 | db_symtab.end = (char *)symtab_end; |
170 | db_symtab.name = name; |
171 | db_symtab.private = (char *)symtab; |
172 | |
173 | db_printf("[ using %lu bytes of %s ELF symbol table ]\n", |
174 | (u_long)roundup(((char *)esymtab - (char *)symtab), sizeof(u_long))((((((char *)esymtab - (char *)symtab))+((sizeof(u_long))-1)) /(sizeof(u_long)))*(sizeof(u_long))), |
175 | name); |
176 | |
177 | return (1); |
178 | |
179 | badheader: |
180 | db_printf("[ %s ELF symbol table not valid: %s ]\n", name, errstr); |
181 | return (0); |
182 | } |
183 | |
184 | /* |
185 | * Internal helper function - return a pointer to the string table |
186 | * for the current symbol table. |
187 | */ |
188 | char * |
189 | db_elf_find_strtab(db_symtab_t *stab) |
190 | { |
191 | Elf_EhdrElf64_Ehdr *elf = STAB_TO_EHDR(stab)((Elf64_Ehdr *)((stab)->private)); |
192 | Elf_ShdrElf64_Shdr *shp = STAB_TO_SHDR(stab, elf)((Elf64_Shdr *)((stab)->private + (elf)->e_shoff)); |
193 | char *shstrtab; |
194 | int i; |
195 | |
196 | shstrtab = (char *)elf + shp[elf->e_shstrndx].sh_offset; |
197 | for (i = 0; i < elf->e_shnum; i++) { |
198 | if (shp[i].sh_type == SHT_SYMTAB2) |
199 | return ((char *)elf + shp[shp[i].sh_link].sh_offset); |
200 | if (strcmp(".strtab", shstrtab+shp[i].sh_name) == 0) |
201 | return ((char *)elf + shp[i].sh_offset); |
202 | } |
203 | |
204 | return (NULL((void *)0)); |
205 | } |
206 | |
207 | /* |
208 | * Internal helper function - return a pointer to the section |
209 | * named ``sname''. |
210 | */ |
211 | const char * |
212 | db_elf_find_section(db_symtab_t *stab, size_t *size, const char *sname) |
213 | { |
214 | Elf_EhdrElf64_Ehdr *elf = STAB_TO_EHDR(stab)((Elf64_Ehdr *)((stab)->private)); |
215 | Elf_ShdrElf64_Shdr *shp = STAB_TO_SHDR(stab, elf)((Elf64_Shdr *)((stab)->private + (elf)->e_shoff)); |
216 | char *shstrtab; |
217 | int i; |
218 | |
219 | shstrtab = (char *)elf + shp[elf->e_shstrndx].sh_offset; |
220 | for (i = 0; i < elf->e_shnum; i++) { |
221 | if ((shp[i].sh_flags & SHF_ALLOC0x2) != 0 && |
222 | strcmp(sname, shstrtab+shp[i].sh_name) == 0) { |
223 | *size = shp[i].sh_size; |
224 | return ((char *)elf + shp[i].sh_offset); |
225 | } |
226 | } |
227 | |
228 | return (NULL((void *)0)); |
229 | } |
230 | |
231 | /* |
232 | * Lookup the symbol with the given name. |
233 | */ |
234 | Elf_SymElf64_Sym * |
235 | db_elf_sym_lookup(char *symstr) |
236 | { |
237 | db_symtab_t *stab = &db_symtab; |
238 | Elf_SymElf64_Sym *symp, *symtab_start, *symtab_end; |
239 | char *strtab; |
240 | |
241 | if (stab->private == NULL((void *)0)) |
242 | return (NULL((void *)0)); |
243 | |
244 | symtab_start = STAB_TO_SYMSTART(stab)((Elf64_Sym *)((stab)->start)); |
245 | symtab_end = STAB_TO_SYMEND(stab)((Elf64_Sym *)((stab)->end)); |
246 | |
247 | strtab = db_elf_find_strtab(stab); |
248 | if (strtab == NULL((void *)0)) |
249 | return (NULL((void *)0)); |
250 | |
251 | for (symp = symtab_start; symp < symtab_end; symp++) { |
252 | if (symp->st_name != 0 && |
253 | db_eqname(strtab + symp->st_name, symstr, 0)) |
254 | return (symp); |
255 | } |
256 | |
257 | return (NULL((void *)0)); |
258 | } |
259 | |
260 | /* |
261 | * Search for the symbol with the given address (matching within the |
262 | * provided threshold). |
263 | */ |
264 | Elf_SymElf64_Sym * |
265 | db_elf_sym_search(vaddr_t off, db_strategy_t strategy, db_expr_t *diffp) |
266 | { |
267 | db_symtab_t *stab = &db_symtab; |
268 | Elf_SymElf64_Sym *rsymp, *symp, *symtab_start, *symtab_end; |
269 | db_expr_t diff = *diffp; |
270 | |
271 | if (stab->private == NULL((void *)0)) |
272 | return (NULL((void *)0)); |
273 | |
274 | symtab_start = STAB_TO_SYMSTART(stab)((Elf64_Sym *)((stab)->start)); |
275 | symtab_end = STAB_TO_SYMEND(stab)((Elf64_Sym *)((stab)->end)); |
276 | |
277 | rsymp = NULL((void *)0); |
278 | |
279 | for (symp = symtab_start; symp < symtab_end; symp++) { |
280 | if (symp->st_name == 0) |
281 | continue; |
282 | #if 0 |
283 | /* This prevents me from seeing anythin in locore.s -- eeh */ |
284 | if (ELF_SYM_TYPE(symp->st_info) != Elf_estt_object && |
285 | ELF_SYM_TYPE(symp->st_info) != Elf_estt_func) |
286 | continue; |
287 | #endif |
288 | |
289 | if (off >= symp->st_value) { |
290 | if ((off - symp->st_value) < diff) { |
291 | diff = off - symp->st_value; |
292 | rsymp = symp; |
293 | if (diff == 0) { |
294 | if (strategy == DB_STGY_PROC2 && |
295 | ELF_ST_TYPE(symp->st_info)(((unsigned int) symp->st_info) & 0xf) |
296 | == STT_FUNC2 && |
297 | ELF_ST_BIND(symp->st_info)((symp->st_info) >> 4) |
298 | != STB_LOCAL0) |
299 | break; |
300 | if (strategy == DB_STGY_ANY0 && |
301 | ELF_ST_BIND(symp->st_info)((symp->st_info) >> 4) |
302 | != STB_LOCAL0) |
303 | break; |
304 | } |
305 | } else if ((off - symp->st_value) == diff) { |
306 | if (rsymp == NULL((void *)0)) |
307 | rsymp = symp; |
308 | else if (ELF_ST_BIND(rsymp->st_info)((rsymp->st_info) >> 4) |
309 | == STB_LOCAL0 && |
310 | ELF_ST_BIND(symp->st_info)((symp->st_info) >> 4) |
311 | != STB_LOCAL0) { |
312 | /* pick the external symbol */ |
313 | rsymp = symp; |
314 | } |
315 | } |
316 | } |
317 | } |
318 | |
319 | if (rsymp == NULL((void *)0)) |
320 | *diffp = off; |
321 | else |
322 | *diffp = diff; |
323 | |
324 | return (rsymp); |
325 | } |
326 | |
327 | /* |
328 | * Return the name and value for a symbol. |
329 | */ |
330 | void |
331 | db_symbol_values(Elf_SymElf64_Sym *sym, char **namep, db_expr_t *valuep) |
332 | { |
333 | db_symtab_t *stab = &db_symtab; |
334 | Elf_SymElf64_Sym *symp = (Elf_SymElf64_Sym *)sym; |
335 | char *strtab; |
336 | |
337 | if (sym == NULL((void *)0)) { |
338 | *namep = NULL((void *)0); |
339 | return; |
340 | } |
341 | |
342 | if (stab->private == NULL((void *)0)) |
343 | return; |
344 | |
345 | if (namep) { |
346 | strtab = db_elf_find_strtab(stab); |
347 | if (strtab == NULL((void *)0)) |
348 | *namep = NULL((void *)0); |
349 | else |
350 | *namep = strtab + symp->st_name; |
351 | } |
352 | |
353 | if (valuep) |
354 | *valuep = symp->st_value; |
355 | } |
356 | |
357 | /* |
358 | * Return the file and line number of the current program counter |
359 | * if we can find the appropriate debugging symbol. |
360 | */ |
361 | int |
362 | db_elf_line_at_pc(Elf_SymElf64_Sym *cursym, char **filename, |
363 | int *linenum, db_expr_t off) |
364 | { |
365 | db_symtab_t *stab = &db_symtab; |
366 | static char path[PATH_MAX1024]; |
367 | const char *linetab, *dirname, *basename; |
368 | size_t linetab_size; |
369 | |
370 | if (stab->private == NULL((void *)0)) |
371 | return (0); |
372 | |
373 | linetab = db_elf_find_section(stab, &linetab_size, ".debug_line"); |
374 | if (linetab == NULL((void *)0)) |
375 | return (0); |
376 | |
377 | if (!db_dwarf_line_at_pc(linetab, linetab_size, off, |
378 | &dirname, &basename, linenum)) |
379 | return (0); |
380 | |
381 | if (dirname == NULL((void *)0)) |
382 | strlcpy(path, basename, sizeof(path)); |
383 | else |
384 | snprintf(path, sizeof(path), "%s/%s", dirname, basename); |
385 | *filename = path; |
386 | return (1); |
387 | } |
388 | |
389 | void |
390 | db_elf_sym_forall(db_forall_func_t db_forall_func, void *arg) |
391 | { |
392 | db_symtab_t *stab = &db_symtab; |
393 | char *strtab; |
394 | static char suffix[2]; |
395 | Elf_SymElf64_Sym *symp, *symtab_start, *symtab_end; |
396 | |
397 | if (stab->private == NULL((void *)0)) |
398 | return; |
399 | |
400 | symtab_start = STAB_TO_SYMSTART(stab)((Elf64_Sym *)((stab)->start)); |
401 | symtab_end = STAB_TO_SYMEND(stab)((Elf64_Sym *)((stab)->end)); |
402 | |
403 | strtab = db_elf_find_strtab(stab); |
404 | if (strtab == NULL((void *)0)) |
405 | return; |
406 | |
407 | for (symp = symtab_start; symp < symtab_end; symp++) |
408 | if (symp->st_name != 0) { |
409 | suffix[1] = '\0'; |
410 | switch (ELF_ST_TYPE(symp->st_info)(((unsigned int) symp->st_info) & 0xf)) { |
411 | case STT_OBJECT1: |
412 | suffix[0] = '+'; |
413 | break; |
414 | case STT_FUNC2: |
415 | suffix[0] = '*'; |
416 | break; |
417 | case STT_SECTION3: |
418 | suffix[0] = '&'; |
419 | break; |
420 | case STT_FILE4: |
421 | suffix[0] = '/'; |
422 | break; |
423 | default: |
424 | suffix[0] = '\0'; |
425 | } |
426 | (*db_forall_func)(symp, |
427 | strtab + symp->st_name, suffix, 0, arg); |
428 | } |
429 | } |
430 | |
431 | Elf_SymElf64_Sym * |
432 | db_symbol_by_name(char *name, db_expr_t *valuep) |
433 | { |
434 | Elf_SymElf64_Sym *sym; |
435 | |
436 | sym = db_elf_sym_lookup(name); |
437 | if (sym == NULL((void *)0)) |
438 | return (NULL((void *)0)); |
439 | db_symbol_values(sym, &name, valuep); |
440 | return (sym); |
441 | } |