Warning: That file was not part of the compilation database. It may have many parsing errors.

1/* pecoff.c -- Get debug data from a PE/COFFF file for backtraces.
2 Copyright (C) 2015-2017 Free Software Foundation, Inc.
3 Adapted from elf.c by Tristan Gingold, AdaCore.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are
7met:
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
21THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31POSSIBILITY OF SUCH DAMAGE. */
32
33#include "config.h"
34
35#include <stdlib.h>
36#include <string.h>
37#include <sys/types.h>
38
39#include "backtrace.h"
40#include "internal.h"
41
42/* Coff file header. */
43
44typedef struct {
45 uint16_t machine;
46 uint16_t number_of_sections;
47 uint32_t time_date_stamp;
48 uint32_t pointer_to_symbol_table;
49 uint32_t number_of_symbols;
50 uint16_t size_of_optional_header;
51 uint16_t characteristics;
52} b_coff_file_header;
53
54/* Coff optional header. */
55
56typedef struct {
57 uint16_t magic;
58 uint8_t major_linker_version;
59 uint8_t minor_linker_version;
60 uint32_t size_of_code;
61 uint32_t size_of_initialized_data;
62 uint32_t size_of_uninitialized_data;
63 uint32_t address_of_entry_point;
64 uint32_t base_of_code;
65 union {
66 struct {
67 uint32_t base_of_data;
68 uint32_t image_base;
69 } pe;
70 struct {
71 uint64_t image_base;
72 } pep;
73 } u;
74} b_coff_optional_header;
75
76/* Values of magic in optional header. */
77
78#define PE_MAGIC 0x10b /* PE32 executable. */
79#define PEP_MAGIC 0x20b /* PE32+ executable (for 64bit targets). */
80
81/* Coff section header. */
82
83typedef struct {
84 char name[8];
85 uint32_t virtual_size;
86 uint32_t virtual_address;
87 uint32_t size_of_raw_data;
88 uint32_t pointer_to_raw_data;
89 uint32_t pointer_to_relocations;
90 uint32_t pointer_to_line_numbers;
91 uint16_t number_of_relocations;
92 uint16_t number_of_line_numbers;
93 uint32_t characteristics;
94} b_coff_section_header;
95
96/* Coff symbol name. */
97
98typedef union {
99 char short_name[8];
100 struct {
101 unsigned char zeroes[4];
102 unsigned char off[4];
103 } long_name;
104} b_coff_name;
105
106/* Coff symbol (external representation which is unaligned). */
107
108typedef struct {
109 b_coff_name name;
110 unsigned char value[4];
111 unsigned char section_number[2];
112 unsigned char type[2];
113 unsigned char storage_class;
114 unsigned char number_of_aux_symbols;
115} b_coff_external_symbol;
116
117/* Symbol types. */
118
119#define N_TBSHFT 4 /* Shift for the derived type. */
120#define IMAGE_SYM_DTYPE_FUNCTION 2 /* Function derived type. */
121
122/* Size of a coff symbol. */
123
124#define SYM_SZ 18
125
126/* Coff symbol, internal representation (aligned). */
127
128typedef struct {
129 const char *name;
130 uint32_t value;
131 int16_t sec;
132 uint16_t type;
133 uint16_t sc;
134} b_coff_internal_symbol;
135
136/* An index of sections we care about. */
137
138enum debug_section
139{
140 DEBUG_INFO,
141 DEBUG_LINE,
142 DEBUG_ABBREV,
143 DEBUG_RANGES,
144 DEBUG_STR,
145 DEBUG_MAX
146};
147
148/* Names of sections, indexed by enum debug_section. */
149
150static const char * const debug_section_names[DEBUG_MAX] =
151{
152 ".debug_info",
153 ".debug_line",
154 ".debug_abbrev",
155 ".debug_ranges",
156 ".debug_str"
157};
158
159/* Information we gather for the sections we care about. */
160
161struct debug_section_info
162{
163 /* Section file offset. */
164 off_t offset;
165 /* Section size. */
166 size_t size;
167 /* Section contents, after read from file. */
168 const unsigned char *data;
169};
170
171/* Information we keep for an coff symbol. */
172
173struct coff_symbol
174{
175 /* The name of the symbol. */
176 const char *name;
177 /* The address of the symbol. */
178 uintptr_t address;
179};
180
181/* Information to pass to coff_syminfo. */
182
183struct coff_syminfo_data
184{
185 /* Symbols for the next module. */
186 struct coff_syminfo_data *next;
187 /* The COFF symbols, sorted by address. */
188 struct coff_symbol *symbols;
189 /* The number of symbols. */
190 size_t count;
191};
192
193/* A dummy callback function used when we can't find any debug info. */
194
195static int
196coff_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
197 uintptr_t pc ATTRIBUTE_UNUSED,
198 backtrace_full_callback callback ATTRIBUTE_UNUSED,
199 backtrace_error_callback error_callback, void *data)
200{
201 error_callback (data, "no debug info in PE/COFF executable", -1);
202 return 0;
203}
204
205/* A dummy callback function used when we can't find a symbol
206 table. */
207
208static void
209coff_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,
210 uintptr_t addr ATTRIBUTE_UNUSED,
211 backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,
212 backtrace_error_callback error_callback, void *data)
213{
214 error_callback (data, "no symbol table in PE/COFF executable", -1);
215}
216
217/* Read a potentially unaligned 4 byte word at P, using native endianness. */
218
219static uint32_t
220coff_read4 (const unsigned char *p)
221{
222 uint32_t res;
223
224 memcpy (&res, p, 4);
225 return res;
226}
227
228/* Read a potentially unaligned 2 byte word at P, using native endianness.
229 All 2 byte word in symbols are always aligned, but for coherency all
230 fields are declared as char arrays. */
231
232static uint16_t
233coff_read2 (const unsigned char *p)
234{
235 uint16_t res;
236
237 memcpy (&res, p, sizeof (res));
238 return res;
239}
240
241/* Return the length (without the trailing 0) of a COFF short name. */
242
243static size_t
244coff_short_name_len (const char *name)
245{
246 int i;
247
248 for (i = 0; i < 8; i++)
249 if (name[i] == 0)
250 return i;
251 return 8;
252}
253
254/* Return true iff COFF short name CNAME is the same as NAME (a NUL-terminated
255 string). */
256
257static int
258coff_short_name_eq (const char *name, const char *cname)
259{
260 int i;
261
262 for (i = 0; i < 8; i++)
263 {
264 if (name[i] != cname[i])
265 return 0;
266 if (name[i] == 0)
267 return 1;
268 }
269 return name[8] == 0;
270}
271
272/* Return true iff NAME is the same as string at offset OFF. */
273
274static int
275coff_long_name_eq (const char *name, unsigned int off,
276 struct backtrace_view *str_view)
277{
278 if (off >= str_view->len)
279 return 0;
280 return strcmp (name, (const char *)str_view->data + off) == 0;
281}
282
283/* Compare struct coff_symbol for qsort. */
284
285static int
286coff_symbol_compare (const void *v1, const void *v2)
287{
288 const struct coff_symbol *e1 = (const struct coff_symbol *) v1;
289 const struct coff_symbol *e2 = (const struct coff_symbol *) v2;
290
291 if (e1->address < e2->address)
292 return -1;
293 else if (e1->address > e2->address)
294 return 1;
295 else
296 return 0;
297}
298
299/* Convert SYM to internal (and aligned) format ISYM, using string table
300 from STRTAB and STRTAB_SIZE, and number of sections SECTS_NUM.
301 Return -1 in case of error (invalid section number or string index). */
302
303static int
304coff_expand_symbol (b_coff_internal_symbol *isym,
305 const b_coff_external_symbol *sym,
306 uint16_t sects_num,
307 const unsigned char *strtab, size_t strtab_size)
308{
309 isym->type = coff_read2 (sym->type);
310 isym->sec = coff_read2 (sym->section_number);
311 isym->sc = sym->storage_class;
312
313 if (isym->sec > 0 && (uint16_t) isym->sec > sects_num)
314 return -1;
315 if (sym->name.short_name[0] != 0)
316 isym->name = sym->name.short_name;
317 else
318 {
319 uint32_t off = coff_read4 (sym->name.long_name.off);
320
321 if (off >= strtab_size)
322 return -1;
323 isym->name = (const char *) strtab + off;
324 }
325 return 0;
326}
327
328/* Return true iff SYM is a defined symbol for a function. Data symbols
329 aren't considered because they aren't easily identified (same type as
330 section names, presence of symbols defined by the linker script). */
331
332static int
333coff_is_function_symbol (const b_coff_internal_symbol *isym)
334{
335 return (isym->type >> N_TBSHFT) == IMAGE_SYM_DTYPE_FUNCTION
336 && isym->sec > 0;
337}
338
339/* Initialize the symbol table info for coff_syminfo. */
340
341static int
342coff_initialize_syminfo (struct backtrace_state *state,
343 uintptr_t base_address,
344 const b_coff_section_header *sects, size_t sects_num,
345 const b_coff_external_symbol *syms, size_t syms_size,
346 const unsigned char *strtab, size_t strtab_size,
347 backtrace_error_callback error_callback,
348 void *data, struct coff_syminfo_data *sdata)
349{
350 size_t syms_count;
351 char *coff_symstr;
352 size_t coff_symstr_len;
353 size_t coff_symbol_count;
354 size_t coff_symbol_size;
355 struct coff_symbol *coff_symbols;
356 struct coff_symbol *coff_sym;
357 char *coff_str;
358 size_t i;
359
360 syms_count = syms_size / SYM_SZ;
361
362 /* We only care about function symbols. Count them. Also count size of
363 strings for in-symbol names. */
364 coff_symbol_count = 0;
365 coff_symstr_len = 0;
366 for (i = 0; i < syms_count; ++i)
367 {
368 const b_coff_external_symbol *asym = &syms[i];
369 b_coff_internal_symbol isym;
370
371 if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size) < 0)
372 {
373 error_callback (data, "invalid section or offset in coff symbol", 0);
374 return 0;
375 }
376 if (coff_is_function_symbol (&isym))
377 {
378 ++coff_symbol_count;
379 if (asym->name.short_name[0] != 0)
380 coff_symstr_len += coff_short_name_len (asym->name.short_name) + 1;
381 }
382
383 i += asym->number_of_aux_symbols;
384 }
385
386 coff_symbol_size = (coff_symbol_count + 1) * sizeof (struct coff_symbol);
387 coff_symbols = ((struct coff_symbol *)
388 backtrace_alloc (state, coff_symbol_size, error_callback,
389 data));
390 if (coff_symbols == NULL)
391 return 0;
392
393 /* Allocate memory for symbols strings. */
394 if (coff_symstr_len > 0)
395 {
396 coff_symstr = ((char *)
397 backtrace_alloc (state, coff_symstr_len, error_callback,
398 data));
399 if (coff_symstr == NULL)
400 {
401 backtrace_free (state, coff_symbols, coff_symbol_size,
402 error_callback, data);
403 return 0;
404 }
405 }
406 else
407 coff_symstr = NULL;
408
409 /* Copy symbols. */
410 coff_sym = coff_symbols;
411 coff_str = coff_symstr;
412 for (i = 0; i < syms_count; ++i)
413 {
414 const b_coff_external_symbol *asym = &syms[i];
415 b_coff_internal_symbol isym;
416
417 if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size))
418 {
419 /* Should not fail, as it was already tested in the previous
420 loop. */
421 abort ();
422 }
423 if (coff_is_function_symbol (&isym))
424 {
425 const char *name;
426 int16_t secnum;
427
428 if (asym->name.short_name[0] != 0)
429 {
430 size_t len = coff_short_name_len (isym.name);
431 name = coff_str;
432 memcpy (coff_str, isym.name, len);
433 coff_str[len] = 0;
434 coff_str += len + 1;
435 }
436 else
437 name = isym.name;
438
439 /* Strip leading '_'. */
440 if (name[0] == '_')
441 name++;
442
443 /* Symbol value is section relative, so we need to read the address
444 of its section. */
445 secnum = coff_read2 (asym->section_number);
446
447 coff_sym->name = name;
448 coff_sym->address = (coff_read4 (asym->value)
449 + sects[secnum - 1].virtual_address
450 + base_address);
451 coff_sym++;
452 }
453
454 i += asym->number_of_aux_symbols;
455 }
456
457 /* End of symbols marker. */
458 coff_sym->name = NULL;
459 coff_sym->address = -1;
460
461 backtrace_qsort (coff_symbols, coff_symbol_count,
462 sizeof (struct coff_symbol), coff_symbol_compare);
463
464 sdata->next = NULL;
465 sdata->symbols = coff_symbols;
466 sdata->count = coff_symbol_count;
467
468 return 1;
469}
470
471/* Add EDATA to the list in STATE. */
472
473static void
474coff_add_syminfo_data (struct backtrace_state *state,
475 struct coff_syminfo_data *sdata)
476{
477 if (!state->threaded)
478 {
479 struct coff_syminfo_data **pp;
480
481 for (pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
482 *pp != NULL;
483 pp = &(*pp)->next)
484 ;
485 *pp = sdata;
486 }
487 else
488 {
489 while (1)
490 {
491 struct coff_syminfo_data **pp;
492
493 pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
494
495 while (1)
496 {
497 struct coff_syminfo_data *p;
498
499 p = backtrace_atomic_load_pointer (pp);
500
501 if (p == NULL)
502 break;
503
504 pp = &p->next;
505 }
506
507 if (__sync_bool_compare_and_swap (pp, NULL, sdata))
508 break;
509 }
510 }
511}
512
513/* Compare an ADDR against an elf_symbol for bsearch. We allocate one
514 extra entry in the array so that this can look safely at the next
515 entry. */
516
517static int
518coff_symbol_search (const void *vkey, const void *ventry)
519{
520 const uintptr_t *key = (const uintptr_t *) vkey;
521 const struct coff_symbol *entry = (const struct coff_symbol *) ventry;
522 uintptr_t addr;
523
524 addr = *key;
525 if (addr < entry->address)
526 return -1;
527 else if (addr >= entry[1].address)
528 return 1;
529 else
530 return 0;
531}
532
533/* Return the symbol name and value for an ADDR. */
534
535static void
536coff_syminfo (struct backtrace_state *state, uintptr_t addr,
537 backtrace_syminfo_callback callback,
538 backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
539 void *data)
540{
541 struct coff_syminfo_data *sdata;
542 struct coff_symbol *sym = NULL;
543
544 if (!state->threaded)
545 {
546 for (sdata = (struct coff_syminfo_data *) state->syminfo_data;
547 sdata != NULL;
548 sdata = sdata->next)
549 {
550 sym = ((struct coff_symbol *)
551 bsearch (&addr, sdata->symbols, sdata->count,
552 sizeof (struct coff_symbol), coff_symbol_search));
553 if (sym != NULL)
554 break;
555 }
556 }
557 else
558 {
559 struct coff_syminfo_data **pp;
560
561 pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
562 while (1)
563 {
564 sdata = backtrace_atomic_load_pointer (pp);
565 if (sdata == NULL)
566 break;
567
568 sym = ((struct coff_symbol *)
569 bsearch (&addr, sdata->symbols, sdata->count,
570 sizeof (struct coff_symbol), coff_symbol_search));
571 if (sym != NULL)
572 break;
573
574 pp = &sdata->next;
575 }
576 }
577
578 if (sym == NULL)
579 callback (data, addr, NULL, 0, 0);
580 else
581 callback (data, addr, sym->name, sym->address, 0);
582}
583
584/* Add the backtrace data for one PE/COFF file. Returns 1 on success,
585 0 on failure (in both cases descriptor is closed). */
586
587static int
588coff_add (struct backtrace_state *state, int descriptor,
589 backtrace_error_callback error_callback, void *data,
590 fileline *fileline_fn, int *found_sym, int *found_dwarf)
591{
592 struct backtrace_view fhdr_view;
593 off_t fhdr_off;
594 int magic_ok;
595 b_coff_file_header fhdr;
596 off_t opt_sects_off;
597 size_t opt_sects_size;
598 unsigned int sects_num;
599 struct backtrace_view sects_view;
600 int sects_view_valid;
601 const b_coff_optional_header *opt_hdr;
602 const b_coff_section_header *sects;
603 struct backtrace_view str_view;
604 int str_view_valid;
605 size_t str_size;
606 off_t str_off;
607 struct backtrace_view syms_view;
608 off_t syms_off;
609 size_t syms_size;
610 int syms_view_valid;
611 unsigned int syms_num;
612 unsigned int i;
613 struct debug_section_info sections[DEBUG_MAX];
614 off_t min_offset;
615 off_t max_offset;
616 struct backtrace_view debug_view;
617 int debug_view_valid;
618 uintptr_t image_base;
619
620 *found_sym = 0;
621 *found_dwarf = 0;
622
623 sects_view_valid = 0;
624 syms_view_valid = 0;
625 str_view_valid = 0;
626 debug_view_valid = 0;
627
628 /* Map the MS-DOS stub (if any) and extract file header offset. */
629 if (!backtrace_get_view (state, descriptor, 0, 0x40, error_callback,
630 data, &fhdr_view))
631 goto fail;
632
633 {
634 const char *vptr = (const char *)fhdr_view.data;
635
636 if (vptr[0] == 'M' && vptr[1] == 'Z')
637 memcpy (&fhdr_off, vptr + 0x3c, 4);
638 else
639 fhdr_off = 0;
640 }
641
642 backtrace_release_view (state, &fhdr_view, error_callback, data);
643
644 /* Map the coff file header. */
645 if (!backtrace_get_view (state, descriptor, fhdr_off,
646 sizeof (b_coff_file_header) + 4,
647 error_callback, data, &fhdr_view))
648 goto fail;
649
650 if (fhdr_off != 0)
651 {
652 const char *magic = (const char *) fhdr_view.data;
653 magic_ok = memcmp (magic, "PE\0", 4) == 0;
654 fhdr_off += 4;
655
656 memcpy (&fhdr, fhdr_view.data + 4, sizeof fhdr);
657 }
658 else
659 {
660 memcpy (&fhdr, fhdr_view.data, sizeof fhdr);
661 /* TODO: test fhdr.machine for coff but non-PE platforms. */
662 magic_ok = 0;
663 }
664 backtrace_release_view (state, &fhdr_view, error_callback, data);
665
666 if (!magic_ok)
667 {
668 error_callback (data, "executable file is not COFF", 0);
669 goto fail;
670 }
671
672 sects_num = fhdr.number_of_sections;
673 syms_num = fhdr.number_of_symbols;
674
675 opt_sects_off = fhdr_off + sizeof (fhdr);
676 opt_sects_size = (fhdr.size_of_optional_header
677 + sects_num * sizeof (b_coff_section_header));
678
679 /* To translate PC to file/line when using DWARF, we need to find
680 the .debug_info and .debug_line sections. */
681
682 /* Read the optional header and the section headers. */
683
684 if (!backtrace_get_view (state, descriptor, opt_sects_off, opt_sects_size,
685 error_callback, data, &sects_view))
686 goto fail;
687 sects_view_valid = 1;
688 opt_hdr = (const b_coff_optional_header *) sects_view.data;
689 sects = (const b_coff_section_header *)
690 (sects_view.data + fhdr.size_of_optional_header);
691
692 if (fhdr.size_of_optional_header > sizeof (*opt_hdr))
693 {
694 if (opt_hdr->magic == PE_MAGIC)
695 image_base = opt_hdr->u.pe.image_base;
696 else if (opt_hdr->magic == PEP_MAGIC)
697 image_base = opt_hdr->u.pep.image_base;
698 else
699 {
700 error_callback (data, "bad magic in PE optional header", 0);
701 goto fail;
702 }
703 }
704 else
705 image_base = 0;
706
707 /* Read the symbol table and the string table. */
708
709 if (fhdr.pointer_to_symbol_table == 0)
710 {
711 /* No symbol table, no string table. */
712 str_off = 0;
713 str_size = 0;
714 syms_num = 0;
715 syms_size = 0;
716 }
717 else
718 {
719 /* Symbol table is followed by the string table. The string table
720 starts with its length (on 4 bytes).
721 Map the symbol table and the length of the string table. */
722 syms_off = fhdr.pointer_to_symbol_table;
723 syms_size = syms_num * SYM_SZ;
724
725 if (!backtrace_get_view (state, descriptor, syms_off, syms_size + 4,
726 error_callback, data, &syms_view))
727 goto fail;
728 syms_view_valid = 1;
729
730 memcpy (&str_size, syms_view.data + syms_size, 4);
731
732 str_off = syms_off + syms_size;
733
734 if (str_size > 4)
735 {
736 /* Map string table (including the length word). */
737
738 if (!backtrace_get_view (state, descriptor, str_off, str_size,
739 error_callback, data, &str_view))
740 goto fail;
741 str_view_valid = 1;
742 }
743 }
744
745 memset (sections, 0, sizeof sections);
746
747 /* Look for the symbol table. */
748 for (i = 0; i < sects_num; ++i)
749 {
750 const b_coff_section_header *s = sects + i;
751 unsigned int str_off;
752 int j;
753
754 if (s->name[0] == '/')
755 {
756 /* Extended section name. */
757 str_off = atoi (s->name + 1);
758 }
759 else
760 str_off = 0;
761
762 for (j = 0; j < (int) DEBUG_MAX; ++j)
763 {
764 const char *dbg_name = debug_section_names[j];
765 int match;
766
767 if (str_off != 0)
768 match = coff_long_name_eq (dbg_name, str_off, &str_view);
769 else
770 match = coff_short_name_eq (dbg_name, s->name);
771 if (match)
772 {
773 sections[j].offset = s->pointer_to_raw_data;
774 sections[j].size = s->virtual_size <= s->size_of_raw_data ?
775 s->virtual_size : s->size_of_raw_data;
776 break;
777 }
778 }
779 }
780
781 if (syms_num != 0)
782 {
783 struct coff_syminfo_data *sdata;
784
785 sdata = ((struct coff_syminfo_data *)
786 backtrace_alloc (state, sizeof *sdata, error_callback, data));
787 if (sdata == NULL)
788 goto fail;
789
790 if (!coff_initialize_syminfo (state, image_base,
791 sects, sects_num,
792 syms_view.data, syms_size,
793 str_view.data, str_size,
794 error_callback, data, sdata))
795 {
796 backtrace_free (state, sdata, sizeof *sdata, error_callback, data);
797 goto fail;
798 }
799
800 *found_sym = 1;
801
802 coff_add_syminfo_data (state, sdata);
803 }
804
805 backtrace_release_view (state, &sects_view, error_callback, data);
806 sects_view_valid = 0;
807 backtrace_release_view (state, &syms_view, error_callback, data);
808 syms_view_valid = 0;
809
810 /* Read all the debug sections in a single view, since they are
811 probably adjacent in the file. We never release this view. */
812
813 min_offset = 0;
814 max_offset = 0;
815 for (i = 0; i < (int) DEBUG_MAX; ++i)
816 {
817 off_t end;
818
819 if (sections[i].size == 0)
820 continue;
821 if (min_offset == 0 || sections[i].offset < min_offset)
822 min_offset = sections[i].offset;
823 end = sections[i].offset + sections[i].size;
824 if (end > max_offset)
825 max_offset = end;
826 }
827 if (min_offset == 0 || max_offset == 0)
828 {
829 if (!backtrace_close (descriptor, error_callback, data))
830 goto fail;
831 *fileline_fn = coff_nodebug;
832 return 1;
833 }
834
835 if (!backtrace_get_view (state, descriptor, min_offset,
836 max_offset - min_offset,
837 error_callback, data, &debug_view))
838 goto fail;
839 debug_view_valid = 1;
840
841 /* We've read all we need from the executable. */
842 if (!backtrace_close (descriptor, error_callback, data))
843 goto fail;
844 descriptor = -1;
845
846 for (i = 0; i < (int) DEBUG_MAX; ++i)
847 {
848 if (sections[i].size == 0)
849 sections[i].data = NULL;
850 else
851 sections[i].data = ((const unsigned char *) debug_view.data
852 + (sections[i].offset - min_offset));
853 }
854
855 if (!backtrace_dwarf_add (state, /* base_address */ 0,
856 sections[DEBUG_INFO].data,
857 sections[DEBUG_INFO].size,
858 sections[DEBUG_LINE].data,
859 sections[DEBUG_LINE].size,
860 sections[DEBUG_ABBREV].data,
861 sections[DEBUG_ABBREV].size,
862 sections[DEBUG_RANGES].data,
863 sections[DEBUG_RANGES].size,
864 sections[DEBUG_STR].data,
865 sections[DEBUG_STR].size,
866 0, /* FIXME */
867 error_callback, data, fileline_fn))
868 goto fail;
869
870 *found_dwarf = 1;
871
872 return 1;
873
874 fail:
875 if (sects_view_valid)
876 backtrace_release_view (state, &sects_view, error_callback, data);
877 if (str_view_valid)
878 backtrace_release_view (state, &str_view, error_callback, data);
879 if (syms_view_valid)
880 backtrace_release_view (state, &syms_view, error_callback, data);
881 if (debug_view_valid)
882 backtrace_release_view (state, &debug_view, error_callback, data);
883 if (descriptor != -1)
884 backtrace_close (descriptor, error_callback, data);
885 return 0;
886}
887
888/* Initialize the backtrace data we need from an ELF executable. At
889 the ELF level, all we need to do is find the debug info
890 sections. */
891
892int
893backtrace_initialize (struct backtrace_state *state,
894 const char *filename ATTRIBUTE_UNUSED, int descriptor,
895 backtrace_error_callback error_callback,
896 void *data, fileline *fileline_fn)
897{
898 int ret;
899 int found_sym;
900 int found_dwarf;
901 fileline coff_fileline_fn;
902
903 ret = coff_add (state, descriptor, error_callback, data,
904 &coff_fileline_fn, &found_sym, &found_dwarf);
905 if (!ret)
906 return 0;
907
908 if (!state->threaded)
909 {
910 if (found_sym)
911 state->syminfo_fn = coff_syminfo;
912 else if (state->syminfo_fn == NULL)
913 state->syminfo_fn = coff_nosyms;
914 }
915 else
916 {
917 if (found_sym)
918 backtrace_atomic_store_pointer (&state->syminfo_fn, coff_syminfo);
919 else
920 __sync_bool_compare_and_swap (&state->syminfo_fn, NULL, coff_nosyms);
921 }
922
923 if (!state->threaded)
924 {
925 if (state->fileline_fn == NULL || state->fileline_fn == coff_nodebug)
926 *fileline_fn = coff_fileline_fn;
927 }
928 else
929 {
930 fileline current_fn;
931
932 current_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
933 if (current_fn == NULL || current_fn == coff_nodebug)
934 *fileline_fn = coff_fileline_fn;
935 }
936
937 return 1;
938}
939

Warning: That file was not part of the compilation database. It may have many parsing errors.