gcc/
[official-gcc.git] / libbacktrace / pecoff.c
blobc7d32aa6b4750495f9b4860db8cc9fe4535c87a2
1 /* pecoff.c -- Get debug data from a PE/COFFF file for backtraces.
2 Copyright (C) 2015-2016 Free Software Foundation, Inc.
3 Adapted from elf.c by Tristan Gingold, AdaCore.
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
9 (1) Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
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.
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.
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. */
33 #include "config.h"
35 #include <stdlib.h>
36 #include <string.h>
37 #include <sys/types.h>
39 #include "backtrace.h"
40 #include "internal.h"
42 /* Coff file header. */
44 typedef 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;
54 /* Coff optional header. */
56 typedef 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;
76 /* Values of magic in optional header. */
78 #define PE_MAGIC 0x10b /* PE32 executable. */
79 #define PEP_MAGIC 0x20b /* PE32+ executable (for 64bit targets). */
81 /* Coff section header. */
83 typedef 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;
96 /* Coff symbol name. */
98 typedef 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;
106 /* Coff symbol (external representation which is unaligned). */
108 typedef 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;
117 /* Symbol types. */
119 #define N_TBSHFT 4 /* Shift for the derived type. */
120 #define IMAGE_SYM_DTYPE_FUNCTION 2 /* Function derived type. */
122 /* Size of a coff symbol. */
124 #define SYM_SZ 18
126 /* Coff symbol, internal representation (aligned). */
128 typedef 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;
136 /* An index of sections we care about. */
138 enum debug_section
140 DEBUG_INFO,
141 DEBUG_LINE,
142 DEBUG_ABBREV,
143 DEBUG_RANGES,
144 DEBUG_STR,
145 DEBUG_MAX
148 /* Names of sections, indexed by enum debug_section. */
150 static const char * const debug_section_names[DEBUG_MAX] =
152 ".debug_info",
153 ".debug_line",
154 ".debug_abbrev",
155 ".debug_ranges",
156 ".debug_str"
159 /* Information we gather for the sections we care about. */
161 struct debug_section_info
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;
171 /* Information we keep for an coff symbol. */
173 struct coff_symbol
175 /* The name of the symbol. */
176 const char *name;
177 /* The address of the symbol. */
178 uintptr_t address;
181 /* Information to pass to coff_syminfo. */
183 struct coff_syminfo_data
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;
193 /* A dummy callback function used when we can't find any debug info. */
195 static int
196 coff_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)
201 error_callback (data, "no debug info in PE/COFF executable", -1);
202 return 0;
205 /* A dummy callback function used when we can't find a symbol
206 table. */
208 static void
209 coff_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)
214 error_callback (data, "no symbol table in PE/COFF executable", -1);
217 /* Read a potentially unaligned 4 byte word at P, using native endianness. */
219 static uint32_t
220 coff_read4 (const unsigned char *p)
222 uint32_t res;
224 memcpy (&res, p, 4);
225 return res;
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. */
232 static uint16_t
233 coff_read2 (const unsigned char *p)
235 uint16_t res;
237 memcpy (&res, p, sizeof (res));
238 return res;
241 /* Return the length (without the trailing 0) of a COFF short name. */
243 static size_t
244 coff_short_name_len (const char *name)
246 int i;
248 for (i = 0; i < 8; i++)
249 if (name[i] == 0)
250 return i;
251 return 8;
254 /* Return true iff COFF short name CNAME is the same as NAME (a NUL-terminated
255 string). */
257 static int
258 coff_short_name_eq (const char *name, const char *cname)
260 int i;
262 for (i = 0; i < 8; i++)
264 if (name[i] != cname[i])
265 return 0;
266 if (name[i] == 0)
267 return 1;
269 return name[8] == 0;
272 /* Return true iff NAME is the same as string at offset OFF. */
274 static int
275 coff_long_name_eq (const char *name, unsigned int off,
276 struct backtrace_view *str_view)
278 if (off >= str_view->len)
279 return 0;
280 return strcmp (name, (const char *)str_view->data + off) == 0;
283 /* Compare struct coff_symbol for qsort. */
285 static int
286 coff_symbol_compare (const void *v1, const void *v2)
288 const struct coff_symbol *e1 = (const struct coff_symbol *) v1;
289 const struct coff_symbol *e2 = (const struct coff_symbol *) v2;
291 if (e1->address < e2->address)
292 return -1;
293 else if (e1->address > e2->address)
294 return 1;
295 else
296 return 0;
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). */
303 static int
304 coff_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)
309 isym->type = coff_read2 (sym->type);
310 isym->sec = coff_read2 (sym->section_number);
311 isym->sc = sym->storage_class;
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
319 uint32_t off = coff_read4 (sym->name.long_name.off);
321 if (off >= strtab_size)
322 return -1;
323 isym->name = (const char *) strtab + off;
325 return 0;
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). */
332 static int
333 coff_is_function_symbol (const b_coff_internal_symbol *isym)
335 return (isym->type >> N_TBSHFT) == IMAGE_SYM_DTYPE_FUNCTION
336 && isym->sec > 0;
339 /* Initialize the symbol table info for coff_syminfo. */
341 static int
342 coff_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)
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;
360 syms_count = syms_size / SYM_SZ;
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)
368 const b_coff_external_symbol *asym = &syms[i];
369 b_coff_internal_symbol isym;
371 if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size) < 0)
373 error_callback (data, "invalid section or offset in coff symbol", 0);
374 return 0;
376 if (coff_is_function_symbol (&isym))
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;
383 i += asym->number_of_aux_symbols;
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;
393 /* Allocate memory for symbols strings. */
394 if (coff_symstr_len > 0)
396 coff_symstr = ((char *)
397 backtrace_alloc (state, coff_symstr_len, error_callback,
398 data));
399 if (coff_symstr == NULL)
401 backtrace_free (state, coff_symbols, coff_symbol_size,
402 error_callback, data);
403 return 0;
406 else
407 coff_symstr = NULL;
409 /* Copy symbols. */
410 coff_sym = coff_symbols;
411 coff_str = coff_symstr;
412 for (i = 0; i < syms_count; ++i)
414 const b_coff_external_symbol *asym = &syms[i];
415 b_coff_internal_symbol isym;
417 if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size))
419 /* Should not fail, as it was already tested in the previous
420 loop. */
421 abort ();
423 if (coff_is_function_symbol (&isym))
425 const char *name;
426 int16_t secnum;
428 if (asym->name.short_name[0] != 0)
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;
436 else
437 name = isym.name;
439 /* Strip leading '_'. */
440 if (name[0] == '_')
441 name++;
443 /* Symbol value is section relative, so we need to read the address
444 of its section. */
445 secnum = coff_read2 (asym->section_number);
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++;
454 i += asym->number_of_aux_symbols;
457 /* End of symbols marker. */
458 coff_sym->name = NULL;
459 coff_sym->address = -1;
461 backtrace_qsort (coff_symbols, coff_symbol_count,
462 sizeof (struct coff_symbol), coff_symbol_compare);
464 sdata->next = NULL;
465 sdata->symbols = coff_symbols;
466 sdata->count = coff_symbol_count;
468 return 1;
471 /* Add EDATA to the list in STATE. */
473 static void
474 coff_add_syminfo_data (struct backtrace_state *state,
475 struct coff_syminfo_data *sdata)
477 if (!state->threaded)
479 struct coff_syminfo_data **pp;
481 for (pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
482 *pp != NULL;
483 pp = &(*pp)->next)
485 *pp = sdata;
487 else
489 while (1)
491 struct coff_syminfo_data **pp;
493 pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
495 while (1)
497 struct coff_syminfo_data *p;
499 p = backtrace_atomic_load_pointer (pp);
501 if (p == NULL)
502 break;
504 pp = &p->next;
507 if (__sync_bool_compare_and_swap (pp, NULL, sdata))
508 break;
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. */
517 static int
518 coff_symbol_search (const void *vkey, const void *ventry)
520 const uintptr_t *key = (const uintptr_t *) vkey;
521 const struct coff_symbol *entry = (const struct coff_symbol *) ventry;
522 uintptr_t addr;
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;
533 /* Return the symbol name and value for an ADDR. */
535 static void
536 coff_syminfo (struct backtrace_state *state, uintptr_t addr,
537 backtrace_syminfo_callback callback,
538 backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
539 void *data)
541 struct coff_syminfo_data *sdata;
542 struct coff_symbol *sym = NULL;
544 if (!state->threaded)
546 for (sdata = (struct coff_syminfo_data *) state->syminfo_data;
547 sdata != NULL;
548 sdata = sdata->next)
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;
557 else
559 struct coff_syminfo_data **pp;
561 pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
562 while (1)
564 sdata = backtrace_atomic_load_pointer (pp);
565 if (sdata == NULL)
566 break;
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;
574 pp = &sdata->next;
578 if (sym == NULL)
579 callback (data, addr, NULL, 0, 0);
580 else
581 callback (data, addr, sym->name, sym->address, 0);
584 /* Add the backtrace data for one PE/COFF file. Returns 1 on success,
585 0 on failure (in both cases descriptor is closed). */
587 static int
588 coff_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)
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;
620 *found_sym = 0;
621 *found_dwarf = 0;
623 sects_view_valid = 0;
624 syms_view_valid = 0;
625 str_view_valid = 0;
626 debug_view_valid = 0;
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;
634 const char *vptr = (const char *)fhdr_view.data;
636 if (vptr[0] == 'M' && vptr[1] == 'Z')
637 memcpy (&fhdr_off, vptr + 0x3c, 4);
638 else
639 fhdr_off = 0;
642 backtrace_release_view (state, &fhdr_view, error_callback, data);
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;
650 if (fhdr_off != 0)
652 const char *magic = (const char *) fhdr_view.data;
653 magic_ok = memcmp (magic, "PE\0", 4) == 0;
654 fhdr_off += 4;
656 memcpy (&fhdr, fhdr_view.data + 4, sizeof fhdr);
658 else
660 memcpy (&fhdr, fhdr_view.data, sizeof fhdr);
661 /* TODO: test fhdr.machine for coff but non-PE platforms. */
662 magic_ok = 0;
664 backtrace_release_view (state, &fhdr_view, error_callback, data);
666 if (!magic_ok)
668 error_callback (data, "executable file is not COFF", 0);
669 goto fail;
672 sects_num = fhdr.number_of_sections;
673 syms_num = fhdr.number_of_symbols;
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));
679 /* To translate PC to file/line when using DWARF, we need to find
680 the .debug_info and .debug_line sections. */
682 /* Read the optional header and the section headers. */
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);
692 if (fhdr.size_of_optional_header > sizeof (*opt_hdr))
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
700 error_callback (data, "bad magic in PE optional header", 0);
701 goto fail;
704 else
705 image_base = 0;
707 /* Read the symbol table and the string table. */
709 if (fhdr.pointer_to_symbol_table == 0)
711 /* No symbol table, no string table. */
712 str_off = 0;
713 str_size = 0;
714 syms_num = 0;
715 syms_size = 0;
717 else
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;
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;
730 memcpy (&str_size, syms_view.data + syms_size, 4);
732 str_off = syms_off + syms_size;
734 if (str_size > 4)
736 /* Map string table (including the length word). */
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;
745 memset (sections, 0, sizeof sections);
747 /* Look for the symbol table. */
748 for (i = 0; i < sects_num; ++i)
750 const b_coff_section_header *s = sects + i;
751 unsigned int str_off;
752 int j;
754 if (s->name[0] == '/')
756 /* Extended section name. */
757 str_off = atoi (s->name + 1);
759 else
760 str_off = 0;
762 for (j = 0; j < (int) DEBUG_MAX; ++j)
764 const char *dbg_name = debug_section_names[j];
765 int match;
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)
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;
781 if (syms_num != 0)
783 struct coff_syminfo_data *sdata;
785 sdata = ((struct coff_syminfo_data *)
786 backtrace_alloc (state, sizeof *sdata, error_callback, data));
787 if (sdata == NULL)
788 goto fail;
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))
796 backtrace_free (state, sdata, sizeof *sdata, error_callback, data);
797 goto fail;
800 *found_sym = 1;
802 coff_add_syminfo_data (state, sdata);
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;
810 /* Read all the debug sections in a single view, since they are
811 probably adjacent in the file. We never release this view. */
813 min_offset = 0;
814 max_offset = 0;
815 for (i = 0; i < (int) DEBUG_MAX; ++i)
817 off_t end;
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;
827 if (min_offset == 0 || max_offset == 0)
829 if (!backtrace_close (descriptor, error_callback, data))
830 goto fail;
831 *fileline_fn = coff_nodebug;
832 return 1;
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;
841 /* We've read all we need from the executable. */
842 if (!backtrace_close (descriptor, error_callback, data))
843 goto fail;
844 descriptor = -1;
846 for (i = 0; i < (int) DEBUG_MAX; ++i)
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));
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;
870 *found_dwarf = 1;
872 return 1;
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;
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. */
893 backtrace_initialize (struct backtrace_state *state, int descriptor,
894 backtrace_error_callback error_callback,
895 void *data, fileline *fileline_fn)
897 int ret;
898 int found_sym;
899 int found_dwarf;
900 fileline coff_fileline_fn;
902 ret = coff_add (state, descriptor, error_callback, data,
903 &coff_fileline_fn, &found_sym, &found_dwarf);
904 if (!ret)
905 return 0;
907 if (!state->threaded)
909 if (found_sym)
910 state->syminfo_fn = coff_syminfo;
911 else if (state->syminfo_fn == NULL)
912 state->syminfo_fn = coff_nosyms;
914 else
916 if (found_sym)
917 backtrace_atomic_store_pointer (&state->syminfo_fn, coff_syminfo);
918 else
919 __sync_bool_compare_and_swap (&state->syminfo_fn, NULL, coff_nosyms);
922 if (!state->threaded)
924 if (state->fileline_fn == NULL || state->fileline_fn == coff_nodebug)
925 *fileline_fn = coff_fileline_fn;
927 else
929 fileline current_fn;
931 current_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
932 if (current_fn == NULL || current_fn == coff_nodebug)
933 *fileline_fn = coff_fileline_fn;
936 return 1;