]>
Commit | Line | Data |
---|---|---|
eff02e4f | 1 | /* elf.c -- Get debug data from an ELF file for backtraces. |
818ab71a | 2 | Copyright (C) 2012-2016 Free Software Foundation, Inc. |
eff02e4f ILT |
3 | Written by Ian Lance Taylor, Google. |
4 | ||
5 | Redistribution and use in source and binary forms, with or without | |
6 | modification, are permitted provided that the following conditions are | |
7 | met: | |
8 | ||
9 | (1) Redistributions of source code must retain the above copyright | |
10 | notice, this list of conditions and the following disclaimer. | |
11 | ||
12 | (2) Redistributions in binary form must reproduce the above copyright | |
13 | notice, this list of conditions and the following disclaimer in | |
14 | the documentation and/or other materials provided with the | |
15 | distribution. | |
16 | ||
17 | (3) The name of the author may not be used to | |
18 | endorse or promote products derived from this software without | |
19 | specific prior written permission. | |
20 | ||
21 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
22 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, | |
25 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
28 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
29 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | |
30 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
31 | POSSIBILITY OF SUCH DAMAGE. */ | |
32 | ||
33 | #include "config.h" | |
34 | ||
35 | #include <stdlib.h> | |
36 | #include <string.h> | |
37 | #include <sys/types.h> | |
38 | ||
e561a992 ILT |
39 | #ifdef HAVE_DL_ITERATE_PHDR |
40 | #include <link.h> | |
41 | #endif | |
42 | ||
eff02e4f ILT |
43 | #include "backtrace.h" |
44 | #include "internal.h" | |
45 | ||
e561a992 ILT |
46 | #ifndef HAVE_DL_ITERATE_PHDR |
47 | ||
48 | /* Dummy version of dl_iterate_phdr for systems that don't have it. */ | |
49 | ||
50 | #define dl_phdr_info x_dl_phdr_info | |
51 | #define dl_iterate_phdr x_dl_iterate_phdr | |
52 | ||
53 | struct dl_phdr_info | |
54 | { | |
55 | uintptr_t dlpi_addr; | |
56 | const char *dlpi_name; | |
57 | }; | |
58 | ||
59 | static int | |
60 | dl_iterate_phdr (int (*callback) (struct dl_phdr_info *, | |
61 | size_t, void *) ATTRIBUTE_UNUSED, | |
62 | void *data ATTRIBUTE_UNUSED) | |
63 | { | |
64 | return 0; | |
65 | } | |
66 | ||
67 | #endif /* ! defined (HAVE_DL_ITERATE_PHDR) */ | |
68 | ||
eff02e4f ILT |
69 | /* The configure script must tell us whether we are 32-bit or 64-bit |
70 | ELF. We could make this code test and support either possibility, | |
71 | but there is no point. This code only works for the currently | |
72 | running executable, which means that we know the ELF mode at | |
73 | configure mode. */ | |
74 | ||
75 | #if BACKTRACE_ELF_SIZE != 32 && BACKTRACE_ELF_SIZE != 64 | |
76 | #error "Unknown BACKTRACE_ELF_SIZE" | |
77 | #endif | |
78 | ||
e561a992 ILT |
79 | /* <link.h> might #include <elf.h> which might define our constants |
80 | with slightly different values. Undefine them to be safe. */ | |
81 | ||
82 | #undef EI_NIDENT | |
83 | #undef EI_MAG0 | |
84 | #undef EI_MAG1 | |
85 | #undef EI_MAG2 | |
86 | #undef EI_MAG3 | |
87 | #undef EI_CLASS | |
88 | #undef EI_DATA | |
89 | #undef EI_VERSION | |
90 | #undef ELF_MAG0 | |
91 | #undef ELF_MAG1 | |
92 | #undef ELF_MAG2 | |
93 | #undef ELF_MAG3 | |
94 | #undef ELFCLASS32 | |
95 | #undef ELFCLASS64 | |
96 | #undef ELFDATA2LSB | |
97 | #undef ELFDATA2MSB | |
98 | #undef EV_CURRENT | |
0284b52e | 99 | #undef ET_DYN |
e561a992 ILT |
100 | #undef SHN_LORESERVE |
101 | #undef SHN_XINDEX | |
f1857815 | 102 | #undef SHN_UNDEF |
e561a992 ILT |
103 | #undef SHT_SYMTAB |
104 | #undef SHT_STRTAB | |
105 | #undef SHT_DYNSYM | |
cfa658e4 | 106 | #undef STT_OBJECT |
e561a992 ILT |
107 | #undef STT_FUNC |
108 | ||
eff02e4f ILT |
109 | /* Basic types. */ |
110 | ||
40d15b5b ILT |
111 | typedef uint16_t b_elf_half; /* Elf_Half. */ |
112 | typedef uint32_t b_elf_word; /* Elf_Word. */ | |
113 | typedef int32_t b_elf_sword; /* Elf_Sword. */ | |
eff02e4f ILT |
114 | |
115 | #if BACKTRACE_ELF_SIZE == 32 | |
116 | ||
40d15b5b ILT |
117 | typedef uint32_t b_elf_addr; /* Elf_Addr. */ |
118 | typedef uint32_t b_elf_off; /* Elf_Off. */ | |
eff02e4f | 119 | |
40d15b5b | 120 | typedef uint32_t b_elf_wxword; /* 32-bit Elf_Word, 64-bit ELF_Xword. */ |
eff02e4f ILT |
121 | |
122 | #else | |
123 | ||
40d15b5b ILT |
124 | typedef uint64_t b_elf_addr; /* Elf_Addr. */ |
125 | typedef uint64_t b_elf_off; /* Elf_Off. */ | |
126 | typedef uint64_t b_elf_xword; /* Elf_Xword. */ | |
127 | typedef int64_t b_elf_sxword; /* Elf_Sxword. */ | |
eff02e4f | 128 | |
40d15b5b | 129 | typedef uint64_t b_elf_wxword; /* 32-bit Elf_Word, 64-bit ELF_Xword. */ |
eff02e4f ILT |
130 | |
131 | #endif | |
132 | ||
133 | /* Data structures and associated constants. */ | |
134 | ||
135 | #define EI_NIDENT 16 | |
136 | ||
137 | typedef struct { | |
138 | unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */ | |
40d15b5b ILT |
139 | b_elf_half e_type; /* Identifies object file type */ |
140 | b_elf_half e_machine; /* Specifies required architecture */ | |
141 | b_elf_word e_version; /* Identifies object file version */ | |
142 | b_elf_addr e_entry; /* Entry point virtual address */ | |
143 | b_elf_off e_phoff; /* Program header table file offset */ | |
144 | b_elf_off e_shoff; /* Section header table file offset */ | |
145 | b_elf_word e_flags; /* Processor-specific flags */ | |
146 | b_elf_half e_ehsize; /* ELF header size in bytes */ | |
147 | b_elf_half e_phentsize; /* Program header table entry size */ | |
148 | b_elf_half e_phnum; /* Program header table entry count */ | |
149 | b_elf_half e_shentsize; /* Section header table entry size */ | |
150 | b_elf_half e_shnum; /* Section header table entry count */ | |
151 | b_elf_half e_shstrndx; /* Section header string table index */ | |
152 | } b_elf_ehdr; /* Elf_Ehdr. */ | |
eff02e4f ILT |
153 | |
154 | #define EI_MAG0 0 | |
155 | #define EI_MAG1 1 | |
156 | #define EI_MAG2 2 | |
157 | #define EI_MAG3 3 | |
158 | #define EI_CLASS 4 | |
159 | #define EI_DATA 5 | |
160 | #define EI_VERSION 6 | |
161 | ||
162 | #define ELFMAG0 0x7f | |
163 | #define ELFMAG1 'E' | |
164 | #define ELFMAG2 'L' | |
165 | #define ELFMAG3 'F' | |
166 | ||
167 | #define ELFCLASS32 1 | |
168 | #define ELFCLASS64 2 | |
169 | ||
170 | #define ELFDATA2LSB 1 | |
171 | #define ELFDATA2MSB 2 | |
172 | ||
173 | #define EV_CURRENT 1 | |
174 | ||
0284b52e JJ |
175 | #define ET_DYN 3 |
176 | ||
eff02e4f | 177 | typedef struct { |
40d15b5b ILT |
178 | b_elf_word sh_name; /* Section name, index in string tbl */ |
179 | b_elf_word sh_type; /* Type of section */ | |
180 | b_elf_wxword sh_flags; /* Miscellaneous section attributes */ | |
181 | b_elf_addr sh_addr; /* Section virtual addr at execution */ | |
182 | b_elf_off sh_offset; /* Section file offset */ | |
183 | b_elf_wxword sh_size; /* Size of section in bytes */ | |
184 | b_elf_word sh_link; /* Index of another section */ | |
185 | b_elf_word sh_info; /* Additional section information */ | |
186 | b_elf_wxword sh_addralign; /* Section alignment */ | |
187 | b_elf_wxword sh_entsize; /* Entry size if section holds table */ | |
188 | } b_elf_shdr; /* Elf_Shdr. */ | |
eff02e4f | 189 | |
f1857815 | 190 | #define SHN_UNDEF 0x0000 /* Undefined section */ |
eff02e4f ILT |
191 | #define SHN_LORESERVE 0xFF00 /* Begin range of reserved indices */ |
192 | #define SHN_XINDEX 0xFFFF /* Section index is held elsewhere */ | |
193 | ||
194 | #define SHT_SYMTAB 2 | |
195 | #define SHT_STRTAB 3 | |
196 | #define SHT_DYNSYM 11 | |
197 | ||
198 | #if BACKTRACE_ELF_SIZE == 32 | |
199 | ||
200 | typedef struct | |
201 | { | |
40d15b5b ILT |
202 | b_elf_word st_name; /* Symbol name, index in string tbl */ |
203 | b_elf_addr st_value; /* Symbol value */ | |
204 | b_elf_word st_size; /* Symbol size */ | |
eff02e4f ILT |
205 | unsigned char st_info; /* Symbol binding and type */ |
206 | unsigned char st_other; /* Visibility and other data */ | |
40d15b5b ILT |
207 | b_elf_half st_shndx; /* Symbol section index */ |
208 | } b_elf_sym; /* Elf_Sym. */ | |
eff02e4f ILT |
209 | |
210 | #else /* BACKTRACE_ELF_SIZE != 32 */ | |
211 | ||
212 | typedef struct | |
213 | { | |
40d15b5b | 214 | b_elf_word st_name; /* Symbol name, index in string tbl */ |
eff02e4f ILT |
215 | unsigned char st_info; /* Symbol binding and type */ |
216 | unsigned char st_other; /* Visibility and other data */ | |
40d15b5b ILT |
217 | b_elf_half st_shndx; /* Symbol section index */ |
218 | b_elf_addr st_value; /* Symbol value */ | |
219 | b_elf_xword st_size; /* Symbol size */ | |
220 | } b_elf_sym; /* Elf_Sym. */ | |
eff02e4f ILT |
221 | |
222 | #endif /* BACKTRACE_ELF_SIZE != 32 */ | |
223 | ||
cfa658e4 | 224 | #define STT_OBJECT 1 |
eff02e4f ILT |
225 | #define STT_FUNC 2 |
226 | ||
227 | /* An index of ELF sections we care about. */ | |
228 | ||
229 | enum debug_section | |
230 | { | |
231 | DEBUG_INFO, | |
232 | DEBUG_LINE, | |
233 | DEBUG_ABBREV, | |
234 | DEBUG_RANGES, | |
235 | DEBUG_STR, | |
236 | DEBUG_MAX | |
237 | }; | |
238 | ||
239 | /* Names of sections, indexed by enum elf_section. */ | |
240 | ||
241 | static const char * const debug_section_names[DEBUG_MAX] = | |
242 | { | |
243 | ".debug_info", | |
244 | ".debug_line", | |
245 | ".debug_abbrev", | |
246 | ".debug_ranges", | |
247 | ".debug_str" | |
248 | }; | |
249 | ||
250 | /* Information we gather for the sections we care about. */ | |
251 | ||
252 | struct debug_section_info | |
253 | { | |
254 | /* Section file offset. */ | |
255 | off_t offset; | |
256 | /* Section size. */ | |
257 | size_t size; | |
258 | /* Section contents, after read from file. */ | |
259 | const unsigned char *data; | |
260 | }; | |
261 | ||
262 | /* Information we keep for an ELF symbol. */ | |
263 | ||
264 | struct elf_symbol | |
265 | { | |
266 | /* The name of the symbol. */ | |
267 | const char *name; | |
268 | /* The address of the symbol. */ | |
269 | uintptr_t address; | |
270 | /* The size of the symbol. */ | |
271 | size_t size; | |
272 | }; | |
273 | ||
274 | /* Information to pass to elf_syminfo. */ | |
275 | ||
276 | struct elf_syminfo_data | |
277 | { | |
e561a992 ILT |
278 | /* Symbols for the next module. */ |
279 | struct elf_syminfo_data *next; | |
eff02e4f ILT |
280 | /* The ELF symbols, sorted by address. */ |
281 | struct elf_symbol *symbols; | |
282 | /* The number of symbols. */ | |
283 | size_t count; | |
284 | }; | |
285 | ||
286 | /* A dummy callback function used when we can't find any debug info. */ | |
287 | ||
288 | static int | |
289 | elf_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED, | |
290 | uintptr_t pc ATTRIBUTE_UNUSED, | |
291 | backtrace_full_callback callback ATTRIBUTE_UNUSED, | |
292 | backtrace_error_callback error_callback, void *data) | |
293 | { | |
294 | error_callback (data, "no debug info in ELF executable", -1); | |
295 | return 0; | |
296 | } | |
297 | ||
298 | /* A dummy callback function used when we can't find a symbol | |
299 | table. */ | |
300 | ||
301 | static void | |
302 | elf_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED, | |
cfa658e4 | 303 | uintptr_t addr ATTRIBUTE_UNUSED, |
eff02e4f ILT |
304 | backtrace_syminfo_callback callback ATTRIBUTE_UNUSED, |
305 | backtrace_error_callback error_callback, void *data) | |
306 | { | |
307 | error_callback (data, "no symbol table in ELF executable", -1); | |
308 | } | |
309 | ||
310 | /* Compare struct elf_symbol for qsort. */ | |
311 | ||
312 | static int | |
313 | elf_symbol_compare (const void *v1, const void *v2) | |
314 | { | |
315 | const struct elf_symbol *e1 = (const struct elf_symbol *) v1; | |
316 | const struct elf_symbol *e2 = (const struct elf_symbol *) v2; | |
317 | ||
318 | if (e1->address < e2->address) | |
319 | return -1; | |
320 | else if (e1->address > e2->address) | |
321 | return 1; | |
322 | else | |
323 | return 0; | |
324 | } | |
325 | ||
cfa658e4 | 326 | /* Compare an ADDR against an elf_symbol for bsearch. We allocate one |
eff02e4f ILT |
327 | extra entry in the array so that this can look safely at the next |
328 | entry. */ | |
329 | ||
330 | static int | |
331 | elf_symbol_search (const void *vkey, const void *ventry) | |
332 | { | |
333 | const uintptr_t *key = (const uintptr_t *) vkey; | |
334 | const struct elf_symbol *entry = (const struct elf_symbol *) ventry; | |
cfa658e4 | 335 | uintptr_t addr; |
eff02e4f | 336 | |
cfa658e4 ILT |
337 | addr = *key; |
338 | if (addr < entry->address) | |
eff02e4f | 339 | return -1; |
cfa658e4 | 340 | else if (addr >= entry->address + entry->size) |
eff02e4f ILT |
341 | return 1; |
342 | else | |
343 | return 0; | |
344 | } | |
345 | ||
346 | /* Initialize the symbol table info for elf_syminfo. */ | |
347 | ||
348 | static int | |
349 | elf_initialize_syminfo (struct backtrace_state *state, | |
f1857815 | 350 | uintptr_t base_address, |
eff02e4f ILT |
351 | const unsigned char *symtab_data, size_t symtab_size, |
352 | const unsigned char *strtab, size_t strtab_size, | |
353 | backtrace_error_callback error_callback, | |
354 | void *data, struct elf_syminfo_data *sdata) | |
355 | { | |
356 | size_t sym_count; | |
40d15b5b | 357 | const b_elf_sym *sym; |
eff02e4f ILT |
358 | size_t elf_symbol_count; |
359 | size_t elf_symbol_size; | |
360 | struct elf_symbol *elf_symbols; | |
361 | size_t i; | |
362 | unsigned int j; | |
363 | ||
40d15b5b | 364 | sym_count = symtab_size / sizeof (b_elf_sym); |
eff02e4f ILT |
365 | |
366 | /* We only care about function symbols. Count them. */ | |
40d15b5b | 367 | sym = (const b_elf_sym *) symtab_data; |
eff02e4f ILT |
368 | elf_symbol_count = 0; |
369 | for (i = 0; i < sym_count; ++i, ++sym) | |
370 | { | |
cfa658e4 ILT |
371 | int info; |
372 | ||
373 | info = sym->st_info & 0xf; | |
f1857815 JJ |
374 | if ((info == STT_FUNC || info == STT_OBJECT) |
375 | && sym->st_shndx != SHN_UNDEF) | |
eff02e4f ILT |
376 | ++elf_symbol_count; |
377 | } | |
378 | ||
379 | elf_symbol_size = elf_symbol_count * sizeof (struct elf_symbol); | |
380 | elf_symbols = ((struct elf_symbol *) | |
381 | backtrace_alloc (state, elf_symbol_size, error_callback, | |
382 | data)); | |
383 | if (elf_symbols == NULL) | |
384 | return 0; | |
385 | ||
40d15b5b | 386 | sym = (const b_elf_sym *) symtab_data; |
eff02e4f ILT |
387 | j = 0; |
388 | for (i = 0; i < sym_count; ++i, ++sym) | |
389 | { | |
cfa658e4 ILT |
390 | int info; |
391 | ||
392 | info = sym->st_info & 0xf; | |
393 | if (info != STT_FUNC && info != STT_OBJECT) | |
eff02e4f | 394 | continue; |
f1857815 JJ |
395 | if (sym->st_shndx == SHN_UNDEF) |
396 | continue; | |
eff02e4f ILT |
397 | if (sym->st_name >= strtab_size) |
398 | { | |
399 | error_callback (data, "symbol string index out of range", 0); | |
400 | backtrace_free (state, elf_symbols, elf_symbol_size, error_callback, | |
401 | data); | |
402 | return 0; | |
403 | } | |
404 | elf_symbols[j].name = (const char *) strtab + sym->st_name; | |
f1857815 | 405 | elf_symbols[j].address = sym->st_value + base_address; |
eff02e4f ILT |
406 | elf_symbols[j].size = sym->st_size; |
407 | ++j; | |
408 | } | |
409 | ||
c5604b48 ILT |
410 | backtrace_qsort (elf_symbols, elf_symbol_count, sizeof (struct elf_symbol), |
411 | elf_symbol_compare); | |
eff02e4f | 412 | |
e561a992 | 413 | sdata->next = NULL; |
eff02e4f ILT |
414 | sdata->symbols = elf_symbols; |
415 | sdata->count = elf_symbol_count; | |
416 | ||
417 | return 1; | |
418 | } | |
419 | ||
e561a992 ILT |
420 | /* Add EDATA to the list in STATE. */ |
421 | ||
422 | static void | |
423 | elf_add_syminfo_data (struct backtrace_state *state, | |
424 | struct elf_syminfo_data *edata) | |
425 | { | |
426 | if (!state->threaded) | |
427 | { | |
428 | struct elf_syminfo_data **pp; | |
429 | ||
74f80620 | 430 | for (pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data; |
e561a992 ILT |
431 | *pp != NULL; |
432 | pp = &(*pp)->next) | |
433 | ; | |
434 | *pp = edata; | |
435 | } | |
436 | else | |
437 | { | |
438 | while (1) | |
439 | { | |
440 | struct elf_syminfo_data **pp; | |
441 | ||
74f80620 | 442 | pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data; |
e561a992 ILT |
443 | |
444 | while (1) | |
445 | { | |
446 | struct elf_syminfo_data *p; | |
447 | ||
49579c7e | 448 | p = backtrace_atomic_load_pointer (pp); |
e561a992 ILT |
449 | |
450 | if (p == NULL) | |
451 | break; | |
452 | ||
453 | pp = &p->next; | |
454 | } | |
455 | ||
456 | if (__sync_bool_compare_and_swap (pp, NULL, edata)) | |
457 | break; | |
458 | } | |
459 | } | |
460 | } | |
461 | ||
cfa658e4 | 462 | /* Return the symbol name and value for an ADDR. */ |
eff02e4f ILT |
463 | |
464 | static void | |
cfa658e4 | 465 | elf_syminfo (struct backtrace_state *state, uintptr_t addr, |
eff02e4f ILT |
466 | backtrace_syminfo_callback callback, |
467 | backtrace_error_callback error_callback ATTRIBUTE_UNUSED, | |
468 | void *data) | |
469 | { | |
470 | struct elf_syminfo_data *edata; | |
78625ce6 AM |
471 | struct elf_symbol *sym = NULL; |
472 | ||
473 | if (!state->threaded) | |
474 | { | |
475 | for (edata = (struct elf_syminfo_data *) state->syminfo_data; | |
476 | edata != NULL; | |
477 | edata = edata->next) | |
478 | { | |
479 | sym = ((struct elf_symbol *) | |
cfa658e4 | 480 | bsearch (&addr, edata->symbols, edata->count, |
78625ce6 AM |
481 | sizeof (struct elf_symbol), elf_symbol_search)); |
482 | if (sym != NULL) | |
483 | break; | |
484 | } | |
485 | } | |
486 | else | |
487 | { | |
488 | struct elf_syminfo_data **pp; | |
489 | ||
490 | pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data; | |
491 | while (1) | |
492 | { | |
49579c7e | 493 | edata = backtrace_atomic_load_pointer (pp); |
78625ce6 AM |
494 | if (edata == NULL) |
495 | break; | |
496 | ||
497 | sym = ((struct elf_symbol *) | |
cfa658e4 | 498 | bsearch (&addr, edata->symbols, edata->count, |
78625ce6 AM |
499 | sizeof (struct elf_symbol), elf_symbol_search)); |
500 | if (sym != NULL) | |
501 | break; | |
502 | ||
503 | pp = &edata->next; | |
504 | } | |
505 | } | |
eff02e4f | 506 | |
eff02e4f | 507 | if (sym == NULL) |
1f96a712 | 508 | callback (data, addr, NULL, 0, 0); |
eff02e4f | 509 | else |
1f96a712 | 510 | callback (data, addr, sym->name, sym->address, sym->size); |
eff02e4f ILT |
511 | } |
512 | ||
0284b52e JJ |
513 | /* Add the backtrace data for one ELF file. Returns 1 on success, |
514 | 0 on failure (in both cases descriptor is closed) or -1 if exe | |
515 | is non-zero and the ELF file is ET_DYN, which tells the caller that | |
516 | elf_add will need to be called on the descriptor again after | |
517 | base_address is determined. */ | |
eff02e4f | 518 | |
e561a992 ILT |
519 | static int |
520 | elf_add (struct backtrace_state *state, int descriptor, uintptr_t base_address, | |
521 | backtrace_error_callback error_callback, void *data, | |
0284b52e | 522 | fileline *fileline_fn, int *found_sym, int *found_dwarf, int exe) |
eff02e4f ILT |
523 | { |
524 | struct backtrace_view ehdr_view; | |
40d15b5b | 525 | b_elf_ehdr ehdr; |
eff02e4f ILT |
526 | off_t shoff; |
527 | unsigned int shnum; | |
528 | unsigned int shstrndx; | |
529 | struct backtrace_view shdrs_view; | |
530 | int shdrs_view_valid; | |
40d15b5b ILT |
531 | const b_elf_shdr *shdrs; |
532 | const b_elf_shdr *shstrhdr; | |
eff02e4f ILT |
533 | size_t shstr_size; |
534 | off_t shstr_off; | |
535 | struct backtrace_view names_view; | |
536 | int names_view_valid; | |
537 | const char *names; | |
538 | unsigned int symtab_shndx; | |
539 | unsigned int dynsym_shndx; | |
540 | unsigned int i; | |
541 | struct debug_section_info sections[DEBUG_MAX]; | |
542 | struct backtrace_view symtab_view; | |
543 | int symtab_view_valid; | |
544 | struct backtrace_view strtab_view; | |
545 | int strtab_view_valid; | |
546 | off_t min_offset; | |
547 | off_t max_offset; | |
548 | struct backtrace_view debug_view; | |
549 | int debug_view_valid; | |
550 | ||
e561a992 ILT |
551 | *found_sym = 0; |
552 | *found_dwarf = 0; | |
553 | ||
eff02e4f ILT |
554 | shdrs_view_valid = 0; |
555 | names_view_valid = 0; | |
556 | symtab_view_valid = 0; | |
557 | strtab_view_valid = 0; | |
558 | debug_view_valid = 0; | |
559 | ||
560 | if (!backtrace_get_view (state, descriptor, 0, sizeof ehdr, error_callback, | |
561 | data, &ehdr_view)) | |
562 | goto fail; | |
563 | ||
564 | memcpy (&ehdr, ehdr_view.data, sizeof ehdr); | |
565 | ||
566 | backtrace_release_view (state, &ehdr_view, error_callback, data); | |
567 | ||
568 | if (ehdr.e_ident[EI_MAG0] != ELFMAG0 | |
569 | || ehdr.e_ident[EI_MAG1] != ELFMAG1 | |
570 | || ehdr.e_ident[EI_MAG2] != ELFMAG2 | |
571 | || ehdr.e_ident[EI_MAG3] != ELFMAG3) | |
572 | { | |
573 | error_callback (data, "executable file is not ELF", 0); | |
574 | goto fail; | |
575 | } | |
576 | if (ehdr.e_ident[EI_VERSION] != EV_CURRENT) | |
577 | { | |
578 | error_callback (data, "executable file is unrecognized ELF version", 0); | |
579 | goto fail; | |
580 | } | |
581 | ||
582 | #if BACKTRACE_ELF_SIZE == 32 | |
583 | #define BACKTRACE_ELFCLASS ELFCLASS32 | |
584 | #else | |
585 | #define BACKTRACE_ELFCLASS ELFCLASS64 | |
586 | #endif | |
587 | ||
588 | if (ehdr.e_ident[EI_CLASS] != BACKTRACE_ELFCLASS) | |
589 | { | |
590 | error_callback (data, "executable file is unexpected ELF class", 0); | |
591 | goto fail; | |
592 | } | |
593 | ||
594 | if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB | |
595 | && ehdr.e_ident[EI_DATA] != ELFDATA2MSB) | |
596 | { | |
597 | error_callback (data, "executable file has unknown endianness", 0); | |
598 | goto fail; | |
599 | } | |
600 | ||
0284b52e JJ |
601 | /* If the executable is ET_DYN, it is either a PIE, or we are running |
602 | directly a shared library with .interp. We need to wait for | |
603 | dl_iterate_phdr in that case to determine the actual base_address. */ | |
604 | if (exe && ehdr.e_type == ET_DYN) | |
605 | return -1; | |
606 | ||
eff02e4f ILT |
607 | shoff = ehdr.e_shoff; |
608 | shnum = ehdr.e_shnum; | |
609 | shstrndx = ehdr.e_shstrndx; | |
610 | ||
611 | if ((shnum == 0 || shstrndx == SHN_XINDEX) | |
612 | && shoff != 0) | |
613 | { | |
614 | struct backtrace_view shdr_view; | |
40d15b5b | 615 | const b_elf_shdr *shdr; |
eff02e4f ILT |
616 | |
617 | if (!backtrace_get_view (state, descriptor, shoff, sizeof shdr, | |
618 | error_callback, data, &shdr_view)) | |
619 | goto fail; | |
620 | ||
40d15b5b | 621 | shdr = (const b_elf_shdr *) shdr_view.data; |
eff02e4f ILT |
622 | |
623 | if (shnum == 0) | |
624 | shnum = shdr->sh_size; | |
625 | ||
626 | if (shstrndx == SHN_XINDEX) | |
627 | { | |
628 | shstrndx = shdr->sh_link; | |
629 | ||
630 | /* Versions of the GNU binutils between 2.12 and 2.18 did | |
631 | not handle objects with more than SHN_LORESERVE sections | |
632 | correctly. All large section indexes were offset by | |
633 | 0x100. There is more information at | |
634 | http://sourceware.org/bugzilla/show_bug.cgi?id-5900 . | |
635 | Fortunately these object files are easy to detect, as the | |
636 | GNU binutils always put the section header string table | |
637 | near the end of the list of sections. Thus if the | |
638 | section header string table index is larger than the | |
639 | number of sections, then we know we have to subtract | |
640 | 0x100 to get the real section index. */ | |
641 | if (shstrndx >= shnum && shstrndx >= SHN_LORESERVE + 0x100) | |
642 | shstrndx -= 0x100; | |
643 | } | |
644 | ||
645 | backtrace_release_view (state, &shdr_view, error_callback, data); | |
646 | } | |
647 | ||
648 | /* To translate PC to file/line when using DWARF, we need to find | |
649 | the .debug_info and .debug_line sections. */ | |
650 | ||
651 | /* Read the section headers, skipping the first one. */ | |
652 | ||
40d15b5b ILT |
653 | if (!backtrace_get_view (state, descriptor, shoff + sizeof (b_elf_shdr), |
654 | (shnum - 1) * sizeof (b_elf_shdr), | |
eff02e4f ILT |
655 | error_callback, data, &shdrs_view)) |
656 | goto fail; | |
657 | shdrs_view_valid = 1; | |
40d15b5b | 658 | shdrs = (const b_elf_shdr *) shdrs_view.data; |
eff02e4f ILT |
659 | |
660 | /* Read the section names. */ | |
661 | ||
662 | shstrhdr = &shdrs[shstrndx - 1]; | |
663 | shstr_size = shstrhdr->sh_size; | |
664 | shstr_off = shstrhdr->sh_offset; | |
665 | ||
666 | if (!backtrace_get_view (state, descriptor, shstr_off, shstr_size, | |
667 | error_callback, data, &names_view)) | |
668 | goto fail; | |
669 | names_view_valid = 1; | |
670 | names = (const char *) names_view.data; | |
671 | ||
672 | symtab_shndx = 0; | |
673 | dynsym_shndx = 0; | |
674 | ||
675 | memset (sections, 0, sizeof sections); | |
e561a992 ILT |
676 | |
677 | /* Look for the symbol table. */ | |
eff02e4f ILT |
678 | for (i = 1; i < shnum; ++i) |
679 | { | |
40d15b5b | 680 | const b_elf_shdr *shdr; |
eff02e4f ILT |
681 | unsigned int sh_name; |
682 | const char *name; | |
683 | int j; | |
684 | ||
685 | shdr = &shdrs[i - 1]; | |
686 | ||
687 | if (shdr->sh_type == SHT_SYMTAB) | |
688 | symtab_shndx = i; | |
689 | else if (shdr->sh_type == SHT_DYNSYM) | |
690 | dynsym_shndx = i; | |
691 | ||
692 | sh_name = shdr->sh_name; | |
693 | if (sh_name >= shstr_size) | |
694 | { | |
695 | error_callback (data, "ELF section name out of range", 0); | |
696 | goto fail; | |
697 | } | |
698 | ||
699 | name = names + sh_name; | |
700 | ||
701 | for (j = 0; j < (int) DEBUG_MAX; ++j) | |
702 | { | |
703 | if (strcmp (name, debug_section_names[j]) == 0) | |
704 | { | |
705 | sections[j].offset = shdr->sh_offset; | |
706 | sections[j].size = shdr->sh_size; | |
707 | break; | |
708 | } | |
709 | } | |
710 | } | |
711 | ||
712 | if (symtab_shndx == 0) | |
713 | symtab_shndx = dynsym_shndx; | |
e561a992 | 714 | if (symtab_shndx != 0) |
eff02e4f | 715 | { |
40d15b5b | 716 | const b_elf_shdr *symtab_shdr; |
eff02e4f | 717 | unsigned int strtab_shndx; |
40d15b5b | 718 | const b_elf_shdr *strtab_shdr; |
eff02e4f ILT |
719 | struct elf_syminfo_data *sdata; |
720 | ||
721 | symtab_shdr = &shdrs[symtab_shndx - 1]; | |
722 | strtab_shndx = symtab_shdr->sh_link; | |
723 | if (strtab_shndx >= shnum) | |
724 | { | |
725 | error_callback (data, | |
726 | "ELF symbol table strtab link out of range", 0); | |
727 | goto fail; | |
728 | } | |
729 | strtab_shdr = &shdrs[strtab_shndx - 1]; | |
730 | ||
731 | if (!backtrace_get_view (state, descriptor, symtab_shdr->sh_offset, | |
732 | symtab_shdr->sh_size, error_callback, data, | |
733 | &symtab_view)) | |
734 | goto fail; | |
735 | symtab_view_valid = 1; | |
736 | ||
737 | if (!backtrace_get_view (state, descriptor, strtab_shdr->sh_offset, | |
738 | strtab_shdr->sh_size, error_callback, data, | |
739 | &strtab_view)) | |
740 | goto fail; | |
741 | strtab_view_valid = 1; | |
742 | ||
743 | sdata = ((struct elf_syminfo_data *) | |
744 | backtrace_alloc (state, sizeof *sdata, error_callback, data)); | |
745 | if (sdata == NULL) | |
746 | goto fail; | |
747 | ||
f1857815 | 748 | if (!elf_initialize_syminfo (state, base_address, |
eff02e4f ILT |
749 | symtab_view.data, symtab_shdr->sh_size, |
750 | strtab_view.data, strtab_shdr->sh_size, | |
751 | error_callback, data, sdata)) | |
752 | { | |
753 | backtrace_free (state, sdata, sizeof *sdata, error_callback, data); | |
754 | goto fail; | |
755 | } | |
756 | ||
757 | /* We no longer need the symbol table, but we hold on to the | |
758 | string table permanently. */ | |
759 | backtrace_release_view (state, &symtab_view, error_callback, data); | |
760 | ||
e561a992 ILT |
761 | *found_sym = 1; |
762 | ||
763 | elf_add_syminfo_data (state, sdata); | |
eff02e4f ILT |
764 | } |
765 | ||
766 | /* FIXME: Need to handle compressed debug sections. */ | |
767 | ||
768 | backtrace_release_view (state, &shdrs_view, error_callback, data); | |
769 | shdrs_view_valid = 0; | |
770 | backtrace_release_view (state, &names_view, error_callback, data); | |
771 | names_view_valid = 0; | |
772 | ||
773 | /* Read all the debug sections in a single view, since they are | |
774 | probably adjacent in the file. We never release this view. */ | |
775 | ||
776 | min_offset = 0; | |
777 | max_offset = 0; | |
778 | for (i = 0; i < (int) DEBUG_MAX; ++i) | |
779 | { | |
780 | off_t end; | |
781 | ||
6c084a5b ILT |
782 | if (sections[i].size == 0) |
783 | continue; | |
eff02e4f ILT |
784 | if (min_offset == 0 || sections[i].offset < min_offset) |
785 | min_offset = sections[i].offset; | |
786 | end = sections[i].offset + sections[i].size; | |
787 | if (end > max_offset) | |
788 | max_offset = end; | |
789 | } | |
790 | if (min_offset == 0 || max_offset == 0) | |
791 | { | |
792 | if (!backtrace_close (descriptor, error_callback, data)) | |
793 | goto fail; | |
eff02e4f ILT |
794 | return 1; |
795 | } | |
796 | ||
797 | if (!backtrace_get_view (state, descriptor, min_offset, | |
798 | max_offset - min_offset, | |
799 | error_callback, data, &debug_view)) | |
800 | goto fail; | |
801 | debug_view_valid = 1; | |
802 | ||
803 | /* We've read all we need from the executable. */ | |
804 | if (!backtrace_close (descriptor, error_callback, data)) | |
805 | goto fail; | |
806 | descriptor = -1; | |
807 | ||
808 | for (i = 0; i < (int) DEBUG_MAX; ++i) | |
6c084a5b ILT |
809 | { |
810 | if (sections[i].size == 0) | |
811 | sections[i].data = NULL; | |
812 | else | |
813 | sections[i].data = ((const unsigned char *) debug_view.data | |
814 | + (sections[i].offset - min_offset)); | |
815 | } | |
eff02e4f | 816 | |
e561a992 ILT |
817 | if (!backtrace_dwarf_add (state, base_address, |
818 | sections[DEBUG_INFO].data, | |
819 | sections[DEBUG_INFO].size, | |
820 | sections[DEBUG_LINE].data, | |
821 | sections[DEBUG_LINE].size, | |
822 | sections[DEBUG_ABBREV].data, | |
823 | sections[DEBUG_ABBREV].size, | |
824 | sections[DEBUG_RANGES].data, | |
825 | sections[DEBUG_RANGES].size, | |
826 | sections[DEBUG_STR].data, | |
827 | sections[DEBUG_STR].size, | |
828 | ehdr.e_ident[EI_DATA] == ELFDATA2MSB, | |
829 | error_callback, data, fileline_fn)) | |
eff02e4f ILT |
830 | goto fail; |
831 | ||
e561a992 ILT |
832 | *found_dwarf = 1; |
833 | ||
eff02e4f ILT |
834 | return 1; |
835 | ||
836 | fail: | |
837 | if (shdrs_view_valid) | |
838 | backtrace_release_view (state, &shdrs_view, error_callback, data); | |
839 | if (names_view_valid) | |
840 | backtrace_release_view (state, &names_view, error_callback, data); | |
841 | if (symtab_view_valid) | |
842 | backtrace_release_view (state, &symtab_view, error_callback, data); | |
843 | if (strtab_view_valid) | |
844 | backtrace_release_view (state, &strtab_view, error_callback, data); | |
845 | if (debug_view_valid) | |
846 | backtrace_release_view (state, &debug_view, error_callback, data); | |
847 | if (descriptor != -1) | |
848 | backtrace_close (descriptor, error_callback, data); | |
849 | return 0; | |
850 | } | |
e561a992 ILT |
851 | |
852 | /* Data passed to phdr_callback. */ | |
853 | ||
854 | struct phdr_data | |
855 | { | |
856 | struct backtrace_state *state; | |
857 | backtrace_error_callback error_callback; | |
858 | void *data; | |
859 | fileline *fileline_fn; | |
860 | int *found_sym; | |
861 | int *found_dwarf; | |
0284b52e | 862 | int exe_descriptor; |
e561a992 ILT |
863 | }; |
864 | ||
865 | /* Callback passed to dl_iterate_phdr. Load debug info from shared | |
866 | libraries. */ | |
867 | ||
868 | static int | |
28644f75 UB |
869 | #ifdef __i386__ |
870 | __attribute__ ((__force_align_arg_pointer__)) | |
871 | #endif | |
e561a992 ILT |
872 | phdr_callback (struct dl_phdr_info *info, size_t size ATTRIBUTE_UNUSED, |
873 | void *pdata) | |
874 | { | |
875 | struct phdr_data *pd = (struct phdr_data *) pdata; | |
876 | int descriptor; | |
73f41491 | 877 | int does_not_exist; |
e561a992 ILT |
878 | fileline elf_fileline_fn; |
879 | int found_dwarf; | |
880 | ||
0284b52e JJ |
881 | /* There is not much we can do if we don't have the module name, |
882 | unless executable is ET_DYN, where we expect the very first | |
883 | phdr_callback to be for the PIE. */ | |
582f5a2d | 884 | if (info->dlpi_name == NULL || info->dlpi_name[0] == '\0') |
0284b52e JJ |
885 | { |
886 | if (pd->exe_descriptor == -1) | |
887 | return 0; | |
888 | descriptor = pd->exe_descriptor; | |
889 | pd->exe_descriptor = -1; | |
890 | } | |
891 | else | |
892 | { | |
893 | if (pd->exe_descriptor != -1) | |
894 | { | |
895 | backtrace_close (pd->exe_descriptor, pd->error_callback, pd->data); | |
896 | pd->exe_descriptor = -1; | |
897 | } | |
e561a992 | 898 | |
0284b52e JJ |
899 | descriptor = backtrace_open (info->dlpi_name, pd->error_callback, |
900 | pd->data, &does_not_exist); | |
901 | if (descriptor < 0) | |
902 | return 0; | |
903 | } | |
e561a992 ILT |
904 | |
905 | if (elf_add (pd->state, descriptor, info->dlpi_addr, pd->error_callback, | |
0284b52e | 906 | pd->data, &elf_fileline_fn, pd->found_sym, &found_dwarf, 0)) |
e561a992 ILT |
907 | { |
908 | if (found_dwarf) | |
909 | { | |
910 | *pd->found_dwarf = 1; | |
911 | *pd->fileline_fn = elf_fileline_fn; | |
912 | } | |
913 | } | |
914 | ||
915 | return 0; | |
916 | } | |
917 | ||
918 | /* Initialize the backtrace data we need from an ELF executable. At | |
919 | the ELF level, all we need to do is find the debug info | |
920 | sections. */ | |
921 | ||
922 | int | |
923 | backtrace_initialize (struct backtrace_state *state, int descriptor, | |
924 | backtrace_error_callback error_callback, | |
925 | void *data, fileline *fileline_fn) | |
926 | { | |
0284b52e | 927 | int ret; |
e561a992 ILT |
928 | int found_sym; |
929 | int found_dwarf; | |
26ac52db | 930 | fileline elf_fileline_fn = elf_nodebug; |
e561a992 ILT |
931 | struct phdr_data pd; |
932 | ||
0284b52e JJ |
933 | ret = elf_add (state, descriptor, 0, error_callback, data, &elf_fileline_fn, |
934 | &found_sym, &found_dwarf, 1); | |
935 | if (!ret) | |
e561a992 ILT |
936 | return 0; |
937 | ||
938 | pd.state = state; | |
939 | pd.error_callback = error_callback; | |
940 | pd.data = data; | |
0153887c | 941 | pd.fileline_fn = &elf_fileline_fn; |
e561a992 ILT |
942 | pd.found_sym = &found_sym; |
943 | pd.found_dwarf = &found_dwarf; | |
0284b52e | 944 | pd.exe_descriptor = ret < 0 ? descriptor : -1; |
e561a992 ILT |
945 | |
946 | dl_iterate_phdr (phdr_callback, (void *) &pd); | |
947 | ||
e561a992 ILT |
948 | if (!state->threaded) |
949 | { | |
49579c7e ILT |
950 | if (found_sym) |
951 | state->syminfo_fn = elf_syminfo; | |
952 | else if (state->syminfo_fn == NULL) | |
953 | state->syminfo_fn = elf_nosyms; | |
e561a992 ILT |
954 | } |
955 | else | |
956 | { | |
e561a992 | 957 | if (found_sym) |
49579c7e ILT |
958 | backtrace_atomic_store_pointer (&state->syminfo_fn, elf_syminfo); |
959 | else | |
2f401a8f JDA |
960 | (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL, |
961 | elf_nosyms); | |
e561a992 ILT |
962 | } |
963 | ||
964 | if (!state->threaded) | |
965 | { | |
966 | if (state->fileline_fn == NULL || state->fileline_fn == elf_nodebug) | |
967 | *fileline_fn = elf_fileline_fn; | |
968 | } | |
969 | else | |
970 | { | |
971 | fileline current_fn; | |
972 | ||
49579c7e | 973 | current_fn = backtrace_atomic_load_pointer (&state->fileline_fn); |
e561a992 ILT |
974 | if (current_fn == NULL || current_fn == elf_nodebug) |
975 | *fileline_fn = elf_fileline_fn; | |
976 | } | |
977 | ||
978 | return 1; | |
979 | } |