libbacktrace: simplify DWARF section handling
[official-gcc.git] / libbacktrace / pecoff.c
blobfe64a7e695bcb4f524d9f2203dcdb588107c95f7
1 /* pecoff.c -- Get debug data from a PE/COFFF file for backtraces.
2 Copyright (C) 2015-2019 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"
147 /* Information we gather for the sections we care about. */
149 struct debug_section_info
151 /* Section file offset. */
152 off_t offset;
153 /* Section size. */
154 size_t size;
157 /* Information we keep for an coff symbol. */
159 struct coff_symbol
161 /* The name of the symbol. */
162 const char *name;
163 /* The address of the symbol. */
164 uintptr_t address;
167 /* Information to pass to coff_syminfo. */
169 struct coff_syminfo_data
171 /* Symbols for the next module. */
172 struct coff_syminfo_data *next;
173 /* The COFF symbols, sorted by address. */
174 struct coff_symbol *symbols;
175 /* The number of symbols. */
176 size_t count;
179 /* A dummy callback function used when we can't find any debug info. */
181 static int
182 coff_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
183 uintptr_t pc ATTRIBUTE_UNUSED,
184 backtrace_full_callback callback ATTRIBUTE_UNUSED,
185 backtrace_error_callback error_callback, void *data)
187 error_callback (data, "no debug info in PE/COFF executable", -1);
188 return 0;
191 /* A dummy callback function used when we can't find a symbol
192 table. */
194 static void
195 coff_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,
196 uintptr_t addr ATTRIBUTE_UNUSED,
197 backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,
198 backtrace_error_callback error_callback, void *data)
200 error_callback (data, "no symbol table in PE/COFF executable", -1);
203 /* Read a potentially unaligned 4 byte word at P, using native endianness. */
205 static uint32_t
206 coff_read4 (const unsigned char *p)
208 uint32_t res;
210 memcpy (&res, p, 4);
211 return res;
214 /* Read a potentially unaligned 2 byte word at P, using native endianness.
215 All 2 byte word in symbols are always aligned, but for coherency all
216 fields are declared as char arrays. */
218 static uint16_t
219 coff_read2 (const unsigned char *p)
221 uint16_t res;
223 memcpy (&res, p, sizeof (res));
224 return res;
227 /* Return the length (without the trailing 0) of a COFF short name. */
229 static size_t
230 coff_short_name_len (const char *name)
232 int i;
234 for (i = 0; i < 8; i++)
235 if (name[i] == 0)
236 return i;
237 return 8;
240 /* Return true iff COFF short name CNAME is the same as NAME (a NUL-terminated
241 string). */
243 static int
244 coff_short_name_eq (const char *name, const char *cname)
246 int i;
248 for (i = 0; i < 8; i++)
250 if (name[i] != cname[i])
251 return 0;
252 if (name[i] == 0)
253 return 1;
255 return name[8] == 0;
258 /* Return true iff NAME is the same as string at offset OFF. */
260 static int
261 coff_long_name_eq (const char *name, unsigned int off,
262 struct backtrace_view *str_view)
264 if (off >= str_view->len)
265 return 0;
266 return strcmp (name, (const char *)str_view->data + off) == 0;
269 /* Compare struct coff_symbol for qsort. */
271 static int
272 coff_symbol_compare (const void *v1, const void *v2)
274 const struct coff_symbol *e1 = (const struct coff_symbol *) v1;
275 const struct coff_symbol *e2 = (const struct coff_symbol *) v2;
277 if (e1->address < e2->address)
278 return -1;
279 else if (e1->address > e2->address)
280 return 1;
281 else
282 return 0;
285 /* Convert SYM to internal (and aligned) format ISYM, using string table
286 from STRTAB and STRTAB_SIZE, and number of sections SECTS_NUM.
287 Return -1 in case of error (invalid section number or string index). */
289 static int
290 coff_expand_symbol (b_coff_internal_symbol *isym,
291 const b_coff_external_symbol *sym,
292 uint16_t sects_num,
293 const unsigned char *strtab, size_t strtab_size)
295 isym->type = coff_read2 (sym->type);
296 isym->sec = coff_read2 (sym->section_number);
297 isym->sc = sym->storage_class;
299 if (isym->sec > 0 && (uint16_t) isym->sec > sects_num)
300 return -1;
301 if (sym->name.short_name[0] != 0)
302 isym->name = sym->name.short_name;
303 else
305 uint32_t off = coff_read4 (sym->name.long_name.off);
307 if (off >= strtab_size)
308 return -1;
309 isym->name = (const char *) strtab + off;
311 return 0;
314 /* Return true iff SYM is a defined symbol for a function. Data symbols
315 aren't considered because they aren't easily identified (same type as
316 section names, presence of symbols defined by the linker script). */
318 static int
319 coff_is_function_symbol (const b_coff_internal_symbol *isym)
321 return (isym->type >> N_TBSHFT) == IMAGE_SYM_DTYPE_FUNCTION
322 && isym->sec > 0;
325 /* Initialize the symbol table info for coff_syminfo. */
327 static int
328 coff_initialize_syminfo (struct backtrace_state *state,
329 uintptr_t base_address,
330 const b_coff_section_header *sects, size_t sects_num,
331 const b_coff_external_symbol *syms, size_t syms_size,
332 const unsigned char *strtab, size_t strtab_size,
333 backtrace_error_callback error_callback,
334 void *data, struct coff_syminfo_data *sdata)
336 size_t syms_count;
337 char *coff_symstr;
338 size_t coff_symstr_len;
339 size_t coff_symbol_count;
340 size_t coff_symbol_size;
341 struct coff_symbol *coff_symbols;
342 struct coff_symbol *coff_sym;
343 char *coff_str;
344 size_t i;
346 syms_count = syms_size / SYM_SZ;
348 /* We only care about function symbols. Count them. Also count size of
349 strings for in-symbol names. */
350 coff_symbol_count = 0;
351 coff_symstr_len = 0;
352 for (i = 0; i < syms_count; ++i)
354 const b_coff_external_symbol *asym = &syms[i];
355 b_coff_internal_symbol isym;
357 if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size) < 0)
359 error_callback (data, "invalid section or offset in coff symbol", 0);
360 return 0;
362 if (coff_is_function_symbol (&isym))
364 ++coff_symbol_count;
365 if (asym->name.short_name[0] != 0)
366 coff_symstr_len += coff_short_name_len (asym->name.short_name) + 1;
369 i += asym->number_of_aux_symbols;
372 coff_symbol_size = (coff_symbol_count + 1) * sizeof (struct coff_symbol);
373 coff_symbols = ((struct coff_symbol *)
374 backtrace_alloc (state, coff_symbol_size, error_callback,
375 data));
376 if (coff_symbols == NULL)
377 return 0;
379 /* Allocate memory for symbols strings. */
380 if (coff_symstr_len > 0)
382 coff_symstr = ((char *)
383 backtrace_alloc (state, coff_symstr_len, error_callback,
384 data));
385 if (coff_symstr == NULL)
387 backtrace_free (state, coff_symbols, coff_symbol_size,
388 error_callback, data);
389 return 0;
392 else
393 coff_symstr = NULL;
395 /* Copy symbols. */
396 coff_sym = coff_symbols;
397 coff_str = coff_symstr;
398 for (i = 0; i < syms_count; ++i)
400 const b_coff_external_symbol *asym = &syms[i];
401 b_coff_internal_symbol isym;
403 if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size))
405 /* Should not fail, as it was already tested in the previous
406 loop. */
407 abort ();
409 if (coff_is_function_symbol (&isym))
411 const char *name;
412 int16_t secnum;
414 if (asym->name.short_name[0] != 0)
416 size_t len = coff_short_name_len (isym.name);
417 name = coff_str;
418 memcpy (coff_str, isym.name, len);
419 coff_str[len] = 0;
420 coff_str += len + 1;
422 else
423 name = isym.name;
425 /* Strip leading '_'. */
426 if (name[0] == '_')
427 name++;
429 /* Symbol value is section relative, so we need to read the address
430 of its section. */
431 secnum = coff_read2 (asym->section_number);
433 coff_sym->name = name;
434 coff_sym->address = (coff_read4 (asym->value)
435 + sects[secnum - 1].virtual_address
436 + base_address);
437 coff_sym++;
440 i += asym->number_of_aux_symbols;
443 /* End of symbols marker. */
444 coff_sym->name = NULL;
445 coff_sym->address = -1;
447 backtrace_qsort (coff_symbols, coff_symbol_count,
448 sizeof (struct coff_symbol), coff_symbol_compare);
450 sdata->next = NULL;
451 sdata->symbols = coff_symbols;
452 sdata->count = coff_symbol_count;
454 return 1;
457 /* Add EDATA to the list in STATE. */
459 static void
460 coff_add_syminfo_data (struct backtrace_state *state,
461 struct coff_syminfo_data *sdata)
463 if (!state->threaded)
465 struct coff_syminfo_data **pp;
467 for (pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
468 *pp != NULL;
469 pp = &(*pp)->next)
471 *pp = sdata;
473 else
475 while (1)
477 struct coff_syminfo_data **pp;
479 pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
481 while (1)
483 struct coff_syminfo_data *p;
485 p = backtrace_atomic_load_pointer (pp);
487 if (p == NULL)
488 break;
490 pp = &p->next;
493 if (__sync_bool_compare_and_swap (pp, NULL, sdata))
494 break;
499 /* Compare an ADDR against an elf_symbol for bsearch. We allocate one
500 extra entry in the array so that this can look safely at the next
501 entry. */
503 static int
504 coff_symbol_search (const void *vkey, const void *ventry)
506 const uintptr_t *key = (const uintptr_t *) vkey;
507 const struct coff_symbol *entry = (const struct coff_symbol *) ventry;
508 uintptr_t addr;
510 addr = *key;
511 if (addr < entry->address)
512 return -1;
513 else if (addr >= entry[1].address)
514 return 1;
515 else
516 return 0;
519 /* Return the symbol name and value for an ADDR. */
521 static void
522 coff_syminfo (struct backtrace_state *state, uintptr_t addr,
523 backtrace_syminfo_callback callback,
524 backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
525 void *data)
527 struct coff_syminfo_data *sdata;
528 struct coff_symbol *sym = NULL;
530 if (!state->threaded)
532 for (sdata = (struct coff_syminfo_data *) state->syminfo_data;
533 sdata != NULL;
534 sdata = sdata->next)
536 sym = ((struct coff_symbol *)
537 bsearch (&addr, sdata->symbols, sdata->count,
538 sizeof (struct coff_symbol), coff_symbol_search));
539 if (sym != NULL)
540 break;
543 else
545 struct coff_syminfo_data **pp;
547 pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
548 while (1)
550 sdata = backtrace_atomic_load_pointer (pp);
551 if (sdata == NULL)
552 break;
554 sym = ((struct coff_symbol *)
555 bsearch (&addr, sdata->symbols, sdata->count,
556 sizeof (struct coff_symbol), coff_symbol_search));
557 if (sym != NULL)
558 break;
560 pp = &sdata->next;
564 if (sym == NULL)
565 callback (data, addr, NULL, 0, 0);
566 else
567 callback (data, addr, sym->name, sym->address, 0);
570 /* Add the backtrace data for one PE/COFF file. Returns 1 on success,
571 0 on failure (in both cases descriptor is closed). */
573 static int
574 coff_add (struct backtrace_state *state, int descriptor,
575 backtrace_error_callback error_callback, void *data,
576 fileline *fileline_fn, int *found_sym, int *found_dwarf)
578 struct backtrace_view fhdr_view;
579 off_t fhdr_off;
580 int magic_ok;
581 b_coff_file_header fhdr;
582 off_t opt_sects_off;
583 size_t opt_sects_size;
584 unsigned int sects_num;
585 struct backtrace_view sects_view;
586 int sects_view_valid;
587 const b_coff_optional_header *opt_hdr;
588 const b_coff_section_header *sects;
589 struct backtrace_view str_view;
590 int str_view_valid;
591 size_t str_size;
592 off_t str_off;
593 struct backtrace_view syms_view;
594 off_t syms_off;
595 size_t syms_size;
596 int syms_view_valid;
597 unsigned int syms_num;
598 unsigned int i;
599 struct debug_section_info sections[DEBUG_MAX];
600 off_t min_offset;
601 off_t max_offset;
602 struct backtrace_view debug_view;
603 int debug_view_valid;
604 uintptr_t image_base;
605 struct dwarf_sections dwarf_sections;
607 *found_sym = 0;
608 *found_dwarf = 0;
610 sects_view_valid = 0;
611 syms_view_valid = 0;
612 str_view_valid = 0;
613 debug_view_valid = 0;
615 /* Map the MS-DOS stub (if any) and extract file header offset. */
616 if (!backtrace_get_view (state, descriptor, 0, 0x40, error_callback,
617 data, &fhdr_view))
618 goto fail;
621 const unsigned char *vptr = fhdr_view.data;
623 if (vptr[0] == 'M' && vptr[1] == 'Z')
624 fhdr_off = coff_read4 (vptr + 0x3c);
625 else
626 fhdr_off = 0;
629 backtrace_release_view (state, &fhdr_view, error_callback, data);
631 /* Map the coff file header. */
632 if (!backtrace_get_view (state, descriptor, fhdr_off,
633 sizeof (b_coff_file_header) + 4,
634 error_callback, data, &fhdr_view))
635 goto fail;
637 if (fhdr_off != 0)
639 const char *magic = (const char *) fhdr_view.data;
640 magic_ok = memcmp (magic, "PE\0", 4) == 0;
641 fhdr_off += 4;
643 memcpy (&fhdr, fhdr_view.data + 4, sizeof fhdr);
645 else
647 memcpy (&fhdr, fhdr_view.data, sizeof fhdr);
648 /* TODO: test fhdr.machine for coff but non-PE platforms. */
649 magic_ok = 0;
651 backtrace_release_view (state, &fhdr_view, error_callback, data);
653 if (!magic_ok)
655 error_callback (data, "executable file is not COFF", 0);
656 goto fail;
659 sects_num = fhdr.number_of_sections;
660 syms_num = fhdr.number_of_symbols;
662 opt_sects_off = fhdr_off + sizeof (fhdr);
663 opt_sects_size = (fhdr.size_of_optional_header
664 + sects_num * sizeof (b_coff_section_header));
666 /* To translate PC to file/line when using DWARF, we need to find
667 the .debug_info and .debug_line sections. */
669 /* Read the optional header and the section headers. */
671 if (!backtrace_get_view (state, descriptor, opt_sects_off, opt_sects_size,
672 error_callback, data, &sects_view))
673 goto fail;
674 sects_view_valid = 1;
675 opt_hdr = (const b_coff_optional_header *) sects_view.data;
676 sects = (const b_coff_section_header *)
677 (sects_view.data + fhdr.size_of_optional_header);
679 if (fhdr.size_of_optional_header > sizeof (*opt_hdr))
681 if (opt_hdr->magic == PE_MAGIC)
682 image_base = opt_hdr->u.pe.image_base;
683 else if (opt_hdr->magic == PEP_MAGIC)
684 image_base = opt_hdr->u.pep.image_base;
685 else
687 error_callback (data, "bad magic in PE optional header", 0);
688 goto fail;
691 else
692 image_base = 0;
694 /* Read the symbol table and the string table. */
696 if (fhdr.pointer_to_symbol_table == 0)
698 /* No symbol table, no string table. */
699 str_off = 0;
700 str_size = 0;
701 syms_num = 0;
702 syms_size = 0;
704 else
706 /* Symbol table is followed by the string table. The string table
707 starts with its length (on 4 bytes).
708 Map the symbol table and the length of the string table. */
709 syms_off = fhdr.pointer_to_symbol_table;
710 syms_size = syms_num * SYM_SZ;
712 if (!backtrace_get_view (state, descriptor, syms_off, syms_size + 4,
713 error_callback, data, &syms_view))
714 goto fail;
715 syms_view_valid = 1;
717 str_size = coff_read4 (syms_view.data + syms_size);
719 str_off = syms_off + syms_size;
721 if (str_size > 4)
723 /* Map string table (including the length word). */
725 if (!backtrace_get_view (state, descriptor, str_off, str_size,
726 error_callback, data, &str_view))
727 goto fail;
728 str_view_valid = 1;
732 memset (sections, 0, sizeof sections);
734 /* Look for the symbol table. */
735 for (i = 0; i < sects_num; ++i)
737 const b_coff_section_header *s = sects + i;
738 unsigned int str_off;
739 int j;
741 if (s->name[0] == '/')
743 /* Extended section name. */
744 str_off = atoi (s->name + 1);
746 else
747 str_off = 0;
749 for (j = 0; j < (int) DEBUG_MAX; ++j)
751 const char *dbg_name = debug_section_names[j];
752 int match;
754 if (str_off != 0)
755 match = coff_long_name_eq (dbg_name, str_off, &str_view);
756 else
757 match = coff_short_name_eq (dbg_name, s->name);
758 if (match)
760 sections[j].offset = s->pointer_to_raw_data;
761 sections[j].size = s->virtual_size <= s->size_of_raw_data ?
762 s->virtual_size : s->size_of_raw_data;
763 break;
768 if (syms_num != 0)
770 struct coff_syminfo_data *sdata;
772 sdata = ((struct coff_syminfo_data *)
773 backtrace_alloc (state, sizeof *sdata, error_callback, data));
774 if (sdata == NULL)
775 goto fail;
777 if (!coff_initialize_syminfo (state, image_base,
778 sects, sects_num,
779 syms_view.data, syms_size,
780 str_view.data, str_size,
781 error_callback, data, sdata))
783 backtrace_free (state, sdata, sizeof *sdata, error_callback, data);
784 goto fail;
787 *found_sym = 1;
789 coff_add_syminfo_data (state, sdata);
792 backtrace_release_view (state, &sects_view, error_callback, data);
793 sects_view_valid = 0;
794 if (syms_view_valid)
796 backtrace_release_view (state, &syms_view, error_callback, data);
797 syms_view_valid = 0;
800 /* Read all the debug sections in a single view, since they are
801 probably adjacent in the file. We never release this view. */
803 min_offset = 0;
804 max_offset = 0;
805 for (i = 0; i < (int) DEBUG_MAX; ++i)
807 off_t end;
809 if (sections[i].size == 0)
810 continue;
811 if (min_offset == 0 || sections[i].offset < min_offset)
812 min_offset = sections[i].offset;
813 end = sections[i].offset + sections[i].size;
814 if (end > max_offset)
815 max_offset = end;
817 if (min_offset == 0 || max_offset == 0)
819 if (!backtrace_close (descriptor, error_callback, data))
820 goto fail;
821 *fileline_fn = coff_nodebug;
822 return 1;
825 if (!backtrace_get_view (state, descriptor, min_offset,
826 max_offset - min_offset,
827 error_callback, data, &debug_view))
828 goto fail;
829 debug_view_valid = 1;
831 /* We've read all we need from the executable. */
832 if (!backtrace_close (descriptor, error_callback, data))
833 goto fail;
834 descriptor = -1;
836 for (i = 0; i < (int) DEBUG_MAX; ++i)
838 size_t size = sections[i].size;
839 dwarf_sections.size[i] = size;
840 if (size == 0)
841 dwarf_sections.data[i] = NULL;
842 else
843 dwarf_sections.data[i] = ((const unsigned char *) debug_view.data
844 + (sections[i].offset - min_offset));
847 if (!backtrace_dwarf_add (state, /* base_address */ 0, &dwarf_sections,
848 0, /* FIXME: is_bigendian */
849 NULL, /* altlink */
850 error_callback, data, fileline_fn,
851 NULL /* returned fileline_entry */))
852 goto fail;
854 *found_dwarf = 1;
856 return 1;
858 fail:
859 if (sects_view_valid)
860 backtrace_release_view (state, &sects_view, error_callback, data);
861 if (str_view_valid)
862 backtrace_release_view (state, &str_view, error_callback, data);
863 if (syms_view_valid)
864 backtrace_release_view (state, &syms_view, error_callback, data);
865 if (debug_view_valid)
866 backtrace_release_view (state, &debug_view, error_callback, data);
867 if (descriptor != -1)
868 backtrace_close (descriptor, error_callback, data);
869 return 0;
872 /* Initialize the backtrace data we need from an ELF executable. At
873 the ELF level, all we need to do is find the debug info
874 sections. */
877 backtrace_initialize (struct backtrace_state *state,
878 const char *filename ATTRIBUTE_UNUSED, int descriptor,
879 backtrace_error_callback error_callback,
880 void *data, fileline *fileline_fn)
882 int ret;
883 int found_sym;
884 int found_dwarf;
885 fileline coff_fileline_fn;
887 ret = coff_add (state, descriptor, error_callback, data,
888 &coff_fileline_fn, &found_sym, &found_dwarf);
889 if (!ret)
890 return 0;
892 if (!state->threaded)
894 if (found_sym)
895 state->syminfo_fn = coff_syminfo;
896 else if (state->syminfo_fn == NULL)
897 state->syminfo_fn = coff_nosyms;
899 else
901 if (found_sym)
902 backtrace_atomic_store_pointer (&state->syminfo_fn, coff_syminfo);
903 else
904 (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
905 coff_nosyms);
908 if (!state->threaded)
910 if (state->fileline_fn == NULL || state->fileline_fn == coff_nodebug)
911 *fileline_fn = coff_fileline_fn;
913 else
915 fileline current_fn;
917 current_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
918 if (current_fn == NULL || current_fn == coff_nodebug)
919 *fileline_fn = coff_fileline_fn;
922 return 1;