Fix missing SCNuMAX defines in inttypes.h on hpux11.[01]*
[official-gcc.git] / libbacktrace / pecoff.c
blob221571c862ea92fca92e313014be0ea119cc7471
1 /* pecoff.c -- Get debug data from a PE/COFFF file for backtraces.
2 Copyright (C) 2015-2020 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 /* Names of sections, indexed by enum dwarf_section in internal.h. */
138 static const char * const debug_section_names[DEBUG_MAX] =
140 ".debug_info",
141 ".debug_line",
142 ".debug_abbrev",
143 ".debug_ranges",
144 ".debug_str",
145 ".debug_addr",
146 ".debug_str_offsets",
147 ".debug_line_str",
148 ".debug_rnglists"
151 /* Information we gather for the sections we care about. */
153 struct debug_section_info
155 /* Section file offset. */
156 off_t offset;
157 /* Section size. */
158 size_t size;
161 /* Information we keep for an coff symbol. */
163 struct coff_symbol
165 /* The name of the symbol. */
166 const char *name;
167 /* The address of the symbol. */
168 uintptr_t address;
171 /* Information to pass to coff_syminfo. */
173 struct coff_syminfo_data
175 /* Symbols for the next module. */
176 struct coff_syminfo_data *next;
177 /* The COFF symbols, sorted by address. */
178 struct coff_symbol *symbols;
179 /* The number of symbols. */
180 size_t count;
183 /* A dummy callback function used when we can't find any debug info. */
185 static int
186 coff_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
187 uintptr_t pc ATTRIBUTE_UNUSED,
188 backtrace_full_callback callback ATTRIBUTE_UNUSED,
189 backtrace_error_callback error_callback, void *data)
191 error_callback (data, "no debug info in PE/COFF executable", -1);
192 return 0;
195 /* A dummy callback function used when we can't find a symbol
196 table. */
198 static void
199 coff_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,
200 uintptr_t addr ATTRIBUTE_UNUSED,
201 backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,
202 backtrace_error_callback error_callback, void *data)
204 error_callback (data, "no symbol table in PE/COFF executable", -1);
207 /* Read a potentially unaligned 4 byte word at P, using native endianness. */
209 static uint32_t
210 coff_read4 (const unsigned char *p)
212 uint32_t res;
214 memcpy (&res, p, 4);
215 return res;
218 /* Read a potentially unaligned 2 byte word at P, using native endianness.
219 All 2 byte word in symbols are always aligned, but for coherency all
220 fields are declared as char arrays. */
222 static uint16_t
223 coff_read2 (const unsigned char *p)
225 uint16_t res;
227 memcpy (&res, p, sizeof (res));
228 return res;
231 /* Return the length (without the trailing 0) of a COFF short name. */
233 static size_t
234 coff_short_name_len (const char *name)
236 int i;
238 for (i = 0; i < 8; i++)
239 if (name[i] == 0)
240 return i;
241 return 8;
244 /* Return true iff COFF short name CNAME is the same as NAME (a NUL-terminated
245 string). */
247 static int
248 coff_short_name_eq (const char *name, const char *cname)
250 int i;
252 for (i = 0; i < 8; i++)
254 if (name[i] != cname[i])
255 return 0;
256 if (name[i] == 0)
257 return 1;
259 return name[8] == 0;
262 /* Return true iff NAME is the same as string at offset OFF. */
264 static int
265 coff_long_name_eq (const char *name, unsigned int off,
266 struct backtrace_view *str_view)
268 if (off >= str_view->len)
269 return 0;
270 return strcmp (name, (const char *)str_view->data + off) == 0;
273 /* Compare struct coff_symbol for qsort. */
275 static int
276 coff_symbol_compare (const void *v1, const void *v2)
278 const struct coff_symbol *e1 = (const struct coff_symbol *) v1;
279 const struct coff_symbol *e2 = (const struct coff_symbol *) v2;
281 if (e1->address < e2->address)
282 return -1;
283 else if (e1->address > e2->address)
284 return 1;
285 else
286 return 0;
289 /* Convert SYM to internal (and aligned) format ISYM, using string table
290 from STRTAB and STRTAB_SIZE, and number of sections SECTS_NUM.
291 Return -1 in case of error (invalid section number or string index). */
293 static int
294 coff_expand_symbol (b_coff_internal_symbol *isym,
295 const b_coff_external_symbol *sym,
296 uint16_t sects_num,
297 const unsigned char *strtab, size_t strtab_size)
299 isym->type = coff_read2 (sym->type);
300 isym->sec = coff_read2 (sym->section_number);
301 isym->sc = sym->storage_class;
303 if (isym->sec > 0 && (uint16_t) isym->sec > sects_num)
304 return -1;
305 if (sym->name.short_name[0] != 0)
306 isym->name = sym->name.short_name;
307 else
309 uint32_t off = coff_read4 (sym->name.long_name.off);
311 if (off >= strtab_size)
312 return -1;
313 isym->name = (const char *) strtab + off;
315 return 0;
318 /* Return true iff SYM is a defined symbol for a function. Data symbols
319 aren't considered because they aren't easily identified (same type as
320 section names, presence of symbols defined by the linker script). */
322 static int
323 coff_is_function_symbol (const b_coff_internal_symbol *isym)
325 return (isym->type >> N_TBSHFT) == IMAGE_SYM_DTYPE_FUNCTION
326 && isym->sec > 0;
329 /* Initialize the symbol table info for coff_syminfo. */
331 static int
332 coff_initialize_syminfo (struct backtrace_state *state,
333 uintptr_t base_address,
334 const b_coff_section_header *sects, size_t sects_num,
335 const b_coff_external_symbol *syms, size_t syms_size,
336 const unsigned char *strtab, size_t strtab_size,
337 backtrace_error_callback error_callback,
338 void *data, struct coff_syminfo_data *sdata)
340 size_t syms_count;
341 char *coff_symstr;
342 size_t coff_symstr_len;
343 size_t coff_symbol_count;
344 size_t coff_symbol_size;
345 struct coff_symbol *coff_symbols;
346 struct coff_symbol *coff_sym;
347 char *coff_str;
348 size_t i;
350 syms_count = syms_size / SYM_SZ;
352 /* We only care about function symbols. Count them. Also count size of
353 strings for in-symbol names. */
354 coff_symbol_count = 0;
355 coff_symstr_len = 0;
356 for (i = 0; i < syms_count; ++i)
358 const b_coff_external_symbol *asym = &syms[i];
359 b_coff_internal_symbol isym;
361 if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size) < 0)
363 error_callback (data, "invalid section or offset in coff symbol", 0);
364 return 0;
366 if (coff_is_function_symbol (&isym))
368 ++coff_symbol_count;
369 if (asym->name.short_name[0] != 0)
370 coff_symstr_len += coff_short_name_len (asym->name.short_name) + 1;
373 i += asym->number_of_aux_symbols;
376 coff_symbol_size = (coff_symbol_count + 1) * sizeof (struct coff_symbol);
377 coff_symbols = ((struct coff_symbol *)
378 backtrace_alloc (state, coff_symbol_size, error_callback,
379 data));
380 if (coff_symbols == NULL)
381 return 0;
383 /* Allocate memory for symbols strings. */
384 if (coff_symstr_len > 0)
386 coff_symstr = ((char *)
387 backtrace_alloc (state, coff_symstr_len, error_callback,
388 data));
389 if (coff_symstr == NULL)
391 backtrace_free (state, coff_symbols, coff_symbol_size,
392 error_callback, data);
393 return 0;
396 else
397 coff_symstr = NULL;
399 /* Copy symbols. */
400 coff_sym = coff_symbols;
401 coff_str = coff_symstr;
402 for (i = 0; i < syms_count; ++i)
404 const b_coff_external_symbol *asym = &syms[i];
405 b_coff_internal_symbol isym;
407 if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size))
409 /* Should not fail, as it was already tested in the previous
410 loop. */
411 abort ();
413 if (coff_is_function_symbol (&isym))
415 const char *name;
416 int16_t secnum;
418 if (asym->name.short_name[0] != 0)
420 size_t len = coff_short_name_len (isym.name);
421 name = coff_str;
422 memcpy (coff_str, isym.name, len);
423 coff_str[len] = 0;
424 coff_str += len + 1;
426 else
427 name = isym.name;
429 /* Strip leading '_'. */
430 if (name[0] == '_')
431 name++;
433 /* Symbol value is section relative, so we need to read the address
434 of its section. */
435 secnum = coff_read2 (asym->section_number);
437 coff_sym->name = name;
438 coff_sym->address = (coff_read4 (asym->value)
439 + sects[secnum - 1].virtual_address
440 + base_address);
441 coff_sym++;
444 i += asym->number_of_aux_symbols;
447 /* End of symbols marker. */
448 coff_sym->name = NULL;
449 coff_sym->address = -1;
451 backtrace_qsort (coff_symbols, coff_symbol_count,
452 sizeof (struct coff_symbol), coff_symbol_compare);
454 sdata->next = NULL;
455 sdata->symbols = coff_symbols;
456 sdata->count = coff_symbol_count;
458 return 1;
461 /* Add EDATA to the list in STATE. */
463 static void
464 coff_add_syminfo_data (struct backtrace_state *state,
465 struct coff_syminfo_data *sdata)
467 if (!state->threaded)
469 struct coff_syminfo_data **pp;
471 for (pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
472 *pp != NULL;
473 pp = &(*pp)->next)
475 *pp = sdata;
477 else
479 while (1)
481 struct coff_syminfo_data **pp;
483 pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
485 while (1)
487 struct coff_syminfo_data *p;
489 p = backtrace_atomic_load_pointer (pp);
491 if (p == NULL)
492 break;
494 pp = &p->next;
497 if (__sync_bool_compare_and_swap (pp, NULL, sdata))
498 break;
503 /* Compare an ADDR against an elf_symbol for bsearch. We allocate one
504 extra entry in the array so that this can look safely at the next
505 entry. */
507 static int
508 coff_symbol_search (const void *vkey, const void *ventry)
510 const uintptr_t *key = (const uintptr_t *) vkey;
511 const struct coff_symbol *entry = (const struct coff_symbol *) ventry;
512 uintptr_t addr;
514 addr = *key;
515 if (addr < entry->address)
516 return -1;
517 else if (addr >= entry[1].address)
518 return 1;
519 else
520 return 0;
523 /* Return the symbol name and value for an ADDR. */
525 static void
526 coff_syminfo (struct backtrace_state *state, uintptr_t addr,
527 backtrace_syminfo_callback callback,
528 backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
529 void *data)
531 struct coff_syminfo_data *sdata;
532 struct coff_symbol *sym = NULL;
534 if (!state->threaded)
536 for (sdata = (struct coff_syminfo_data *) state->syminfo_data;
537 sdata != NULL;
538 sdata = sdata->next)
540 sym = ((struct coff_symbol *)
541 bsearch (&addr, sdata->symbols, sdata->count,
542 sizeof (struct coff_symbol), coff_symbol_search));
543 if (sym != NULL)
544 break;
547 else
549 struct coff_syminfo_data **pp;
551 pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
552 while (1)
554 sdata = backtrace_atomic_load_pointer (pp);
555 if (sdata == NULL)
556 break;
558 sym = ((struct coff_symbol *)
559 bsearch (&addr, sdata->symbols, sdata->count,
560 sizeof (struct coff_symbol), coff_symbol_search));
561 if (sym != NULL)
562 break;
564 pp = &sdata->next;
568 if (sym == NULL)
569 callback (data, addr, NULL, 0, 0);
570 else
571 callback (data, addr, sym->name, sym->address, 0);
574 /* Add the backtrace data for one PE/COFF file. Returns 1 on success,
575 0 on failure (in both cases descriptor is closed). */
577 static int
578 coff_add (struct backtrace_state *state, int descriptor,
579 backtrace_error_callback error_callback, void *data,
580 fileline *fileline_fn, int *found_sym, int *found_dwarf)
582 struct backtrace_view fhdr_view;
583 off_t fhdr_off;
584 int magic_ok;
585 b_coff_file_header fhdr;
586 off_t opt_sects_off;
587 size_t opt_sects_size;
588 unsigned int sects_num;
589 struct backtrace_view sects_view;
590 int sects_view_valid;
591 const b_coff_optional_header *opt_hdr;
592 const b_coff_section_header *sects;
593 struct backtrace_view str_view;
594 int str_view_valid;
595 size_t str_size;
596 off_t str_off;
597 struct backtrace_view syms_view;
598 off_t syms_off;
599 size_t syms_size;
600 int syms_view_valid;
601 unsigned int syms_num;
602 unsigned int i;
603 struct debug_section_info sections[DEBUG_MAX];
604 off_t min_offset;
605 off_t max_offset;
606 struct backtrace_view debug_view;
607 int debug_view_valid;
608 uintptr_t image_base;
609 struct dwarf_sections dwarf_sections;
611 *found_sym = 0;
612 *found_dwarf = 0;
614 sects_view_valid = 0;
615 syms_view_valid = 0;
616 str_view_valid = 0;
617 debug_view_valid = 0;
619 /* Map the MS-DOS stub (if any) and extract file header offset. */
620 if (!backtrace_get_view (state, descriptor, 0, 0x40, error_callback,
621 data, &fhdr_view))
622 goto fail;
625 const unsigned char *vptr = fhdr_view.data;
627 if (vptr[0] == 'M' && vptr[1] == 'Z')
628 fhdr_off = coff_read4 (vptr + 0x3c);
629 else
630 fhdr_off = 0;
633 backtrace_release_view (state, &fhdr_view, error_callback, data);
635 /* Map the coff file header. */
636 if (!backtrace_get_view (state, descriptor, fhdr_off,
637 sizeof (b_coff_file_header) + 4,
638 error_callback, data, &fhdr_view))
639 goto fail;
641 if (fhdr_off != 0)
643 const char *magic = (const char *) fhdr_view.data;
644 magic_ok = memcmp (magic, "PE\0", 4) == 0;
645 fhdr_off += 4;
647 memcpy (&fhdr, fhdr_view.data + 4, sizeof fhdr);
649 else
651 memcpy (&fhdr, fhdr_view.data, sizeof fhdr);
652 /* TODO: test fhdr.machine for coff but non-PE platforms. */
653 magic_ok = 0;
655 backtrace_release_view (state, &fhdr_view, error_callback, data);
657 if (!magic_ok)
659 error_callback (data, "executable file is not COFF", 0);
660 goto fail;
663 sects_num = fhdr.number_of_sections;
664 syms_num = fhdr.number_of_symbols;
666 opt_sects_off = fhdr_off + sizeof (fhdr);
667 opt_sects_size = (fhdr.size_of_optional_header
668 + sects_num * sizeof (b_coff_section_header));
670 /* To translate PC to file/line when using DWARF, we need to find
671 the .debug_info and .debug_line sections. */
673 /* Read the optional header and the section headers. */
675 if (!backtrace_get_view (state, descriptor, opt_sects_off, opt_sects_size,
676 error_callback, data, &sects_view))
677 goto fail;
678 sects_view_valid = 1;
679 opt_hdr = (const b_coff_optional_header *) sects_view.data;
680 sects = (const b_coff_section_header *)
681 (sects_view.data + fhdr.size_of_optional_header);
683 if (fhdr.size_of_optional_header > sizeof (*opt_hdr))
685 if (opt_hdr->magic == PE_MAGIC)
686 image_base = opt_hdr->u.pe.image_base;
687 else if (opt_hdr->magic == PEP_MAGIC)
688 image_base = opt_hdr->u.pep.image_base;
689 else
691 error_callback (data, "bad magic in PE optional header", 0);
692 goto fail;
695 else
696 image_base = 0;
698 /* Read the symbol table and the string table. */
700 if (fhdr.pointer_to_symbol_table == 0)
702 /* No symbol table, no string table. */
703 str_off = 0;
704 str_size = 0;
705 syms_num = 0;
706 syms_size = 0;
708 else
710 /* Symbol table is followed by the string table. The string table
711 starts with its length (on 4 bytes).
712 Map the symbol table and the length of the string table. */
713 syms_off = fhdr.pointer_to_symbol_table;
714 syms_size = syms_num * SYM_SZ;
716 if (!backtrace_get_view (state, descriptor, syms_off, syms_size + 4,
717 error_callback, data, &syms_view))
718 goto fail;
719 syms_view_valid = 1;
721 str_size = coff_read4 (syms_view.data + syms_size);
723 str_off = syms_off + syms_size;
725 if (str_size > 4)
727 /* Map string table (including the length word). */
729 if (!backtrace_get_view (state, descriptor, str_off, str_size,
730 error_callback, data, &str_view))
731 goto fail;
732 str_view_valid = 1;
736 memset (sections, 0, sizeof sections);
738 /* Look for the symbol table. */
739 for (i = 0; i < sects_num; ++i)
741 const b_coff_section_header *s = sects + i;
742 unsigned int str_off;
743 int j;
745 if (s->name[0] == '/')
747 /* Extended section name. */
748 str_off = atoi (s->name + 1);
750 else
751 str_off = 0;
753 for (j = 0; j < (int) DEBUG_MAX; ++j)
755 const char *dbg_name = debug_section_names[j];
756 int match;
758 if (str_off != 0)
759 match = coff_long_name_eq (dbg_name, str_off, &str_view);
760 else
761 match = coff_short_name_eq (dbg_name, s->name);
762 if (match)
764 sections[j].offset = s->pointer_to_raw_data;
765 sections[j].size = s->virtual_size <= s->size_of_raw_data ?
766 s->virtual_size : s->size_of_raw_data;
767 break;
772 if (syms_num != 0)
774 struct coff_syminfo_data *sdata;
776 sdata = ((struct coff_syminfo_data *)
777 backtrace_alloc (state, sizeof *sdata, error_callback, data));
778 if (sdata == NULL)
779 goto fail;
781 if (!coff_initialize_syminfo (state, image_base,
782 sects, sects_num,
783 syms_view.data, syms_size,
784 str_view.data, str_size,
785 error_callback, data, sdata))
787 backtrace_free (state, sdata, sizeof *sdata, error_callback, data);
788 goto fail;
791 *found_sym = 1;
793 coff_add_syminfo_data (state, sdata);
796 backtrace_release_view (state, &sects_view, error_callback, data);
797 sects_view_valid = 0;
798 if (syms_view_valid)
800 backtrace_release_view (state, &syms_view, error_callback, data);
801 syms_view_valid = 0;
804 /* Read all the debug sections in a single view, since they are
805 probably adjacent in the file. We never release this view. */
807 min_offset = 0;
808 max_offset = 0;
809 for (i = 0; i < (int) DEBUG_MAX; ++i)
811 off_t end;
813 if (sections[i].size == 0)
814 continue;
815 if (min_offset == 0 || sections[i].offset < min_offset)
816 min_offset = sections[i].offset;
817 end = sections[i].offset + sections[i].size;
818 if (end > max_offset)
819 max_offset = end;
821 if (min_offset == 0 || max_offset == 0)
823 if (!backtrace_close (descriptor, error_callback, data))
824 goto fail;
825 *fileline_fn = coff_nodebug;
826 return 1;
829 if (!backtrace_get_view (state, descriptor, min_offset,
830 max_offset - min_offset,
831 error_callback, data, &debug_view))
832 goto fail;
833 debug_view_valid = 1;
835 /* We've read all we need from the executable. */
836 if (!backtrace_close (descriptor, error_callback, data))
837 goto fail;
838 descriptor = -1;
840 for (i = 0; i < (int) DEBUG_MAX; ++i)
842 size_t size = sections[i].size;
843 dwarf_sections.size[i] = size;
844 if (size == 0)
845 dwarf_sections.data[i] = NULL;
846 else
847 dwarf_sections.data[i] = ((const unsigned char *) debug_view.data
848 + (sections[i].offset - min_offset));
851 if (!backtrace_dwarf_add (state, /* base_address */ 0, &dwarf_sections,
852 0, /* FIXME: is_bigendian */
853 NULL, /* altlink */
854 error_callback, data, fileline_fn,
855 NULL /* returned fileline_entry */))
856 goto fail;
858 *found_dwarf = 1;
860 return 1;
862 fail:
863 if (sects_view_valid)
864 backtrace_release_view (state, &sects_view, error_callback, data);
865 if (str_view_valid)
866 backtrace_release_view (state, &str_view, error_callback, data);
867 if (syms_view_valid)
868 backtrace_release_view (state, &syms_view, error_callback, data);
869 if (debug_view_valid)
870 backtrace_release_view (state, &debug_view, error_callback, data);
871 if (descriptor != -1)
872 backtrace_close (descriptor, error_callback, data);
873 return 0;
876 /* Initialize the backtrace data we need from an ELF executable. At
877 the ELF level, all we need to do is find the debug info
878 sections. */
881 backtrace_initialize (struct backtrace_state *state,
882 const char *filename ATTRIBUTE_UNUSED, int descriptor,
883 backtrace_error_callback error_callback,
884 void *data, fileline *fileline_fn)
886 int ret;
887 int found_sym;
888 int found_dwarf;
889 fileline coff_fileline_fn;
891 ret = coff_add (state, descriptor, error_callback, data,
892 &coff_fileline_fn, &found_sym, &found_dwarf);
893 if (!ret)
894 return 0;
896 if (!state->threaded)
898 if (found_sym)
899 state->syminfo_fn = coff_syminfo;
900 else if (state->syminfo_fn == NULL)
901 state->syminfo_fn = coff_nosyms;
903 else
905 if (found_sym)
906 backtrace_atomic_store_pointer (&state->syminfo_fn, coff_syminfo);
907 else
908 (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
909 coff_nosyms);
912 if (!state->threaded)
914 if (state->fileline_fn == NULL || state->fileline_fn == coff_nodebug)
915 *fileline_fn = coff_fileline_fn;
917 else
919 fileline current_fn;
921 current_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
922 if (current_fn == NULL || current_fn == coff_nodebug)
923 *fileline_fn = coff_fileline_fn;
926 return 1;