Extend objdump's --show-all-symbols option so that it also shows the extra symbols...
[binutils-gdb.git] / libbacktrace / pecoff.c
blob9e437d810c73a115c5bbfa16359d693b997da29b
1 /* pecoff.c -- Get debug data from a PE/COFFF file for backtraces.
2 Copyright (C) 2015-2024 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 #ifdef HAVE_WINDOWS_H
43 #ifndef WIN32_MEAN_AND_LEAN
44 #define WIN32_MEAN_AND_LEAN
45 #endif
47 #ifndef NOMINMAX
48 #define NOMINMAX
49 #endif
51 #include <windows.h>
52 #endif
54 /* Coff file header. */
56 typedef struct {
57 uint16_t machine;
58 uint16_t number_of_sections;
59 uint32_t time_date_stamp;
60 uint32_t pointer_to_symbol_table;
61 uint32_t number_of_symbols;
62 uint16_t size_of_optional_header;
63 uint16_t characteristics;
64 } b_coff_file_header;
66 /* Coff optional header. */
68 typedef struct {
69 uint16_t magic;
70 uint8_t major_linker_version;
71 uint8_t minor_linker_version;
72 uint32_t size_of_code;
73 uint32_t size_of_initialized_data;
74 uint32_t size_of_uninitialized_data;
75 uint32_t address_of_entry_point;
76 uint32_t base_of_code;
77 union {
78 struct {
79 uint32_t base_of_data;
80 uint32_t image_base;
81 } pe;
82 struct {
83 uint64_t image_base;
84 } pep;
85 } u;
86 } b_coff_optional_header;
88 /* Values of magic in optional header. */
90 #define PE_MAGIC 0x10b /* PE32 executable. */
91 #define PEP_MAGIC 0x20b /* PE32+ executable (for 64bit targets). */
93 /* Coff section header. */
95 typedef struct {
96 char name[8];
97 uint32_t virtual_size;
98 uint32_t virtual_address;
99 uint32_t size_of_raw_data;
100 uint32_t pointer_to_raw_data;
101 uint32_t pointer_to_relocations;
102 uint32_t pointer_to_line_numbers;
103 uint16_t number_of_relocations;
104 uint16_t number_of_line_numbers;
105 uint32_t characteristics;
106 } b_coff_section_header;
108 /* Coff symbol name. */
110 typedef union {
111 char short_name[8];
112 struct {
113 unsigned char zeroes[4];
114 unsigned char off[4];
115 } long_name;
116 } b_coff_name;
118 /* Coff symbol (external representation which is unaligned). */
120 typedef struct {
121 b_coff_name name;
122 unsigned char value[4];
123 unsigned char section_number[2];
124 unsigned char type[2];
125 unsigned char storage_class;
126 unsigned char number_of_aux_symbols;
127 } b_coff_external_symbol;
129 /* Symbol types. */
131 #define N_TBSHFT 4 /* Shift for the derived type. */
132 #define IMAGE_SYM_DTYPE_FUNCTION 2 /* Function derived type. */
134 /* Size of a coff symbol. */
136 #define SYM_SZ 18
138 /* Coff symbol, internal representation (aligned). */
140 typedef struct {
141 const char *name;
142 uint32_t value;
143 int16_t sec;
144 uint16_t type;
145 uint16_t sc;
146 } b_coff_internal_symbol;
148 /* Names of sections, indexed by enum dwarf_section in internal.h. */
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",
157 ".debug_addr",
158 ".debug_str_offsets",
159 ".debug_line_str",
160 ".debug_rnglists"
163 /* Information we gather for the sections we care about. */
165 struct debug_section_info
167 /* Section file offset. */
168 off_t offset;
169 /* Section size. */
170 size_t size;
173 /* Information we keep for an coff symbol. */
175 struct coff_symbol
177 /* The name of the symbol. */
178 const char *name;
179 /* The address of the symbol. */
180 uintptr_t address;
183 /* Information to pass to coff_syminfo. */
185 struct coff_syminfo_data
187 /* Symbols for the next module. */
188 struct coff_syminfo_data *next;
189 /* The COFF symbols, sorted by address. */
190 struct coff_symbol *symbols;
191 /* The number of symbols. */
192 size_t count;
195 /* A dummy callback function used when we can't find any debug info. */
197 static int
198 coff_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
199 uintptr_t pc ATTRIBUTE_UNUSED,
200 backtrace_full_callback callback ATTRIBUTE_UNUSED,
201 backtrace_error_callback error_callback, void *data)
203 error_callback (data, "no debug info in PE/COFF executable", -1);
204 return 0;
207 /* A dummy callback function used when we can't find a symbol
208 table. */
210 static void
211 coff_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,
212 uintptr_t addr ATTRIBUTE_UNUSED,
213 backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,
214 backtrace_error_callback error_callback, void *data)
216 error_callback (data, "no symbol table in PE/COFF executable", -1);
219 /* Read a potentially unaligned 4 byte word at P, using native endianness. */
221 static uint32_t
222 coff_read4 (const unsigned char *p)
224 uint32_t res;
226 memcpy (&res, p, 4);
227 return res;
230 /* Read a potentially unaligned 2 byte word at P, using native endianness.
231 All 2 byte word in symbols are always aligned, but for coherency all
232 fields are declared as char arrays. */
234 static uint16_t
235 coff_read2 (const unsigned char *p)
237 uint16_t res;
239 memcpy (&res, p, sizeof (res));
240 return res;
243 /* Return the length (without the trailing 0) of a COFF short name. */
245 static size_t
246 coff_short_name_len (const char *name)
248 int i;
250 for (i = 0; i < 8; i++)
251 if (name[i] == 0)
252 return i;
253 return 8;
256 /* Return true iff COFF short name CNAME is the same as NAME (a NUL-terminated
257 string). */
259 static int
260 coff_short_name_eq (const char *name, const char *cname)
262 int i;
264 for (i = 0; i < 8; i++)
266 if (name[i] != cname[i])
267 return 0;
268 if (name[i] == 0)
269 return 1;
271 return name[8] == 0;
274 /* Return true iff NAME is the same as string at offset OFF. */
276 static int
277 coff_long_name_eq (const char *name, unsigned int off,
278 struct backtrace_view *str_view)
280 if (off >= str_view->len)
281 return 0;
282 return strcmp (name, (const char *)str_view->data + off) == 0;
285 /* Compare struct coff_symbol for qsort. */
287 static int
288 coff_symbol_compare (const void *v1, const void *v2)
290 const struct coff_symbol *e1 = (const struct coff_symbol *) v1;
291 const struct coff_symbol *e2 = (const struct coff_symbol *) v2;
293 if (e1->address < e2->address)
294 return -1;
295 else if (e1->address > e2->address)
296 return 1;
297 else
298 return 0;
301 /* Convert SYM to internal (and aligned) format ISYM, using string table
302 from STRTAB and STRTAB_SIZE, and number of sections SECTS_NUM.
303 Return -1 in case of error (invalid section number or string index). */
305 static int
306 coff_expand_symbol (b_coff_internal_symbol *isym,
307 const b_coff_external_symbol *sym,
308 uint16_t sects_num,
309 const unsigned char *strtab, size_t strtab_size)
311 isym->type = coff_read2 (sym->type);
312 isym->sec = coff_read2 (sym->section_number);
313 isym->sc = sym->storage_class;
315 if (isym->sec > 0 && (uint16_t) isym->sec > sects_num)
316 return -1;
317 if (sym->name.short_name[0] != 0)
318 isym->name = sym->name.short_name;
319 else
321 uint32_t off = coff_read4 (sym->name.long_name.off);
323 if (off >= strtab_size)
324 return -1;
325 isym->name = (const char *) strtab + off;
327 return 0;
330 /* Return true iff SYM is a defined symbol for a function. Data symbols
331 aren't considered because they aren't easily identified (same type as
332 section names, presence of symbols defined by the linker script). */
334 static int
335 coff_is_function_symbol (const b_coff_internal_symbol *isym)
337 return (isym->type >> N_TBSHFT) == IMAGE_SYM_DTYPE_FUNCTION
338 && isym->sec > 0;
341 /* Initialize the symbol table info for coff_syminfo. */
343 static int
344 coff_initialize_syminfo (struct backtrace_state *state,
345 uintptr_t base_address, int is_64,
346 const b_coff_section_header *sects, size_t sects_num,
347 const b_coff_external_symbol *syms, size_t syms_size,
348 const unsigned char *strtab, size_t strtab_size,
349 backtrace_error_callback error_callback,
350 void *data, struct coff_syminfo_data *sdata)
352 size_t syms_count;
353 char *coff_symstr;
354 size_t coff_symstr_len;
355 size_t coff_symbol_count;
356 size_t coff_symbol_size;
357 struct coff_symbol *coff_symbols;
358 struct coff_symbol *coff_sym;
359 char *coff_str;
360 size_t i;
362 syms_count = syms_size / SYM_SZ;
364 /* We only care about function symbols. Count them. Also count size of
365 strings for in-symbol names. */
366 coff_symbol_count = 0;
367 coff_symstr_len = 0;
368 for (i = 0; i < syms_count; ++i)
370 const b_coff_external_symbol *asym = &syms[i];
371 b_coff_internal_symbol isym;
373 if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size) < 0)
375 error_callback (data, "invalid section or offset in coff symbol", 0);
376 return 0;
378 if (coff_is_function_symbol (&isym))
380 ++coff_symbol_count;
381 if (asym->name.short_name[0] != 0)
382 coff_symstr_len += coff_short_name_len (asym->name.short_name) + 1;
385 i += asym->number_of_aux_symbols;
388 coff_symbol_size = (coff_symbol_count + 1) * sizeof (struct coff_symbol);
389 coff_symbols = ((struct coff_symbol *)
390 backtrace_alloc (state, coff_symbol_size, error_callback,
391 data));
392 if (coff_symbols == NULL)
393 return 0;
395 /* Allocate memory for symbols strings. */
396 if (coff_symstr_len > 0)
398 coff_symstr = ((char *)
399 backtrace_alloc (state, coff_symstr_len, error_callback,
400 data));
401 if (coff_symstr == NULL)
403 backtrace_free (state, coff_symbols, coff_symbol_size,
404 error_callback, data);
405 return 0;
408 else
409 coff_symstr = NULL;
411 /* Copy symbols. */
412 coff_sym = coff_symbols;
413 coff_str = coff_symstr;
414 for (i = 0; i < syms_count; ++i)
416 const b_coff_external_symbol *asym = &syms[i];
417 b_coff_internal_symbol isym;
419 if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size))
421 /* Should not fail, as it was already tested in the previous
422 loop. */
423 abort ();
425 if (coff_is_function_symbol (&isym))
427 const char *name;
428 int16_t secnum;
430 if (asym->name.short_name[0] != 0)
432 size_t len = coff_short_name_len (isym.name);
433 name = coff_str;
434 memcpy (coff_str, isym.name, len);
435 coff_str[len] = 0;
436 coff_str += len + 1;
438 else
439 name = isym.name;
441 if (!is_64)
443 /* Strip leading '_'. */
444 if (name[0] == '_')
445 name++;
448 /* Symbol value is section relative, so we need to read the address
449 of its section. */
450 secnum = coff_read2 (asym->section_number);
452 coff_sym->name = name;
453 coff_sym->address = (coff_read4 (asym->value)
454 + sects[secnum - 1].virtual_address
455 + base_address);
456 coff_sym++;
459 i += asym->number_of_aux_symbols;
462 /* End of symbols marker. */
463 coff_sym->name = NULL;
464 coff_sym->address = -1;
466 backtrace_qsort (coff_symbols, coff_symbol_count,
467 sizeof (struct coff_symbol), coff_symbol_compare);
469 sdata->next = NULL;
470 sdata->symbols = coff_symbols;
471 sdata->count = coff_symbol_count;
473 return 1;
476 /* Add EDATA to the list in STATE. */
478 static void
479 coff_add_syminfo_data (struct backtrace_state *state,
480 struct coff_syminfo_data *sdata)
482 if (!state->threaded)
484 struct coff_syminfo_data **pp;
486 for (pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
487 *pp != NULL;
488 pp = &(*pp)->next)
490 *pp = sdata;
492 else
494 while (1)
496 struct coff_syminfo_data **pp;
498 pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
500 while (1)
502 struct coff_syminfo_data *p;
504 p = backtrace_atomic_load_pointer (pp);
506 if (p == NULL)
507 break;
509 pp = &p->next;
512 if (__sync_bool_compare_and_swap (pp, NULL, sdata))
513 break;
518 /* Compare an ADDR against an elf_symbol for bsearch. We allocate one
519 extra entry in the array so that this can look safely at the next
520 entry. */
522 static int
523 coff_symbol_search (const void *vkey, const void *ventry)
525 const uintptr_t *key = (const uintptr_t *) vkey;
526 const struct coff_symbol *entry = (const struct coff_symbol *) ventry;
527 uintptr_t addr;
529 addr = *key;
530 if (addr < entry->address)
531 return -1;
532 else if (addr >= entry[1].address)
533 return 1;
534 else
535 return 0;
538 /* Return the symbol name and value for an ADDR. */
540 static void
541 coff_syminfo (struct backtrace_state *state, uintptr_t addr,
542 backtrace_syminfo_callback callback,
543 backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
544 void *data)
546 struct coff_syminfo_data *sdata;
547 struct coff_symbol *sym = NULL;
549 if (!state->threaded)
551 for (sdata = (struct coff_syminfo_data *) state->syminfo_data;
552 sdata != NULL;
553 sdata = sdata->next)
555 sym = ((struct coff_symbol *)
556 bsearch (&addr, sdata->symbols, sdata->count,
557 sizeof (struct coff_symbol), coff_symbol_search));
558 if (sym != NULL)
559 break;
562 else
564 struct coff_syminfo_data **pp;
566 pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
567 while (1)
569 sdata = backtrace_atomic_load_pointer (pp);
570 if (sdata == NULL)
571 break;
573 sym = ((struct coff_symbol *)
574 bsearch (&addr, sdata->symbols, sdata->count,
575 sizeof (struct coff_symbol), coff_symbol_search));
576 if (sym != NULL)
577 break;
579 pp = &sdata->next;
583 if (sym == NULL)
584 callback (data, addr, NULL, 0, 0);
585 else
586 callback (data, addr, sym->name, sym->address, 0);
589 /* Add the backtrace data for one PE/COFF file. Returns 1 on success,
590 0 on failure (in both cases descriptor is closed). */
592 static int
593 coff_add (struct backtrace_state *state, int descriptor,
594 backtrace_error_callback error_callback, void *data,
595 fileline *fileline_fn, int *found_sym, int *found_dwarf)
597 struct backtrace_view fhdr_view;
598 off_t fhdr_off;
599 int magic_ok;
600 b_coff_file_header fhdr;
601 off_t opt_sects_off;
602 size_t opt_sects_size;
603 unsigned int sects_num;
604 struct backtrace_view sects_view;
605 int sects_view_valid;
606 const b_coff_optional_header *opt_hdr;
607 const b_coff_section_header *sects;
608 struct backtrace_view str_view;
609 int str_view_valid;
610 size_t str_size;
611 off_t str_off;
612 struct backtrace_view syms_view;
613 off_t syms_off;
614 size_t syms_size;
615 int syms_view_valid;
616 unsigned int syms_num;
617 unsigned int i;
618 struct debug_section_info sections[DEBUG_MAX];
619 off_t min_offset;
620 off_t max_offset;
621 struct backtrace_view debug_view;
622 int debug_view_valid;
623 int is_64;
624 uintptr_t image_base;
625 uintptr_t base_address = 0;
626 struct dwarf_sections dwarf_sections;
628 *found_sym = 0;
629 *found_dwarf = 0;
631 sects_view_valid = 0;
632 syms_view_valid = 0;
633 str_view_valid = 0;
634 debug_view_valid = 0;
636 /* Map the MS-DOS stub (if any) and extract file header offset. */
637 if (!backtrace_get_view (state, descriptor, 0, 0x40, error_callback,
638 data, &fhdr_view))
639 goto fail;
642 const unsigned char *vptr = fhdr_view.data;
644 if (vptr[0] == 'M' && vptr[1] == 'Z')
645 fhdr_off = coff_read4 (vptr + 0x3c);
646 else
647 fhdr_off = 0;
650 backtrace_release_view (state, &fhdr_view, error_callback, data);
652 /* Map the coff file header. */
653 if (!backtrace_get_view (state, descriptor, fhdr_off,
654 sizeof (b_coff_file_header) + 4,
655 error_callback, data, &fhdr_view))
656 goto fail;
658 if (fhdr_off != 0)
660 const char *magic = (const char *) fhdr_view.data;
661 magic_ok = memcmp (magic, "PE\0", 4) == 0;
662 fhdr_off += 4;
664 memcpy (&fhdr, fhdr_view.data + 4, sizeof fhdr);
666 else
668 memcpy (&fhdr, fhdr_view.data, sizeof fhdr);
669 /* TODO: test fhdr.machine for coff but non-PE platforms. */
670 magic_ok = 0;
672 backtrace_release_view (state, &fhdr_view, error_callback, data);
674 if (!magic_ok)
676 error_callback (data, "executable file is not COFF", 0);
677 goto fail;
680 sects_num = fhdr.number_of_sections;
681 syms_num = fhdr.number_of_symbols;
683 opt_sects_off = fhdr_off + sizeof (fhdr);
684 opt_sects_size = (fhdr.size_of_optional_header
685 + sects_num * sizeof (b_coff_section_header));
687 /* To translate PC to file/line when using DWARF, we need to find
688 the .debug_info and .debug_line sections. */
690 /* Read the optional header and the section headers. */
692 if (!backtrace_get_view (state, descriptor, opt_sects_off, opt_sects_size,
693 error_callback, data, &sects_view))
694 goto fail;
695 sects_view_valid = 1;
696 opt_hdr = (const b_coff_optional_header *) sects_view.data;
697 sects = (const b_coff_section_header *)
698 (sects_view.data + fhdr.size_of_optional_header);
700 is_64 = 0;
701 if (fhdr.size_of_optional_header > sizeof (*opt_hdr))
703 if (opt_hdr->magic == PE_MAGIC)
704 image_base = opt_hdr->u.pe.image_base;
705 else if (opt_hdr->magic == PEP_MAGIC)
707 image_base = opt_hdr->u.pep.image_base;
708 is_64 = 1;
710 else
712 error_callback (data, "bad magic in PE optional header", 0);
713 goto fail;
716 else
717 image_base = 0;
719 /* Read the symbol table and the string table. */
721 if (fhdr.pointer_to_symbol_table == 0)
723 /* No symbol table, no string table. */
724 str_off = 0;
725 str_size = 0;
726 syms_num = 0;
727 syms_size = 0;
729 else
731 /* Symbol table is followed by the string table. The string table
732 starts with its length (on 4 bytes).
733 Map the symbol table and the length of the string table. */
734 syms_off = fhdr.pointer_to_symbol_table;
735 syms_size = syms_num * SYM_SZ;
737 if (!backtrace_get_view (state, descriptor, syms_off, syms_size + 4,
738 error_callback, data, &syms_view))
739 goto fail;
740 syms_view_valid = 1;
742 str_size = coff_read4 (syms_view.data + syms_size);
744 str_off = syms_off + syms_size;
746 if (str_size > 4)
748 /* Map string table (including the length word). */
750 if (!backtrace_get_view (state, descriptor, str_off, str_size,
751 error_callback, data, &str_view))
752 goto fail;
753 str_view_valid = 1;
757 memset (sections, 0, sizeof sections);
759 /* Look for the symbol table. */
760 for (i = 0; i < sects_num; ++i)
762 const b_coff_section_header *s = sects + i;
763 unsigned int str_off;
764 int j;
766 if (s->name[0] == '/')
768 /* Extended section name. */
769 str_off = atoi (s->name + 1);
771 else
772 str_off = 0;
774 for (j = 0; j < (int) DEBUG_MAX; ++j)
776 const char *dbg_name = debug_section_names[j];
777 int match;
779 if (str_off != 0)
780 match = coff_long_name_eq (dbg_name, str_off, &str_view);
781 else
782 match = coff_short_name_eq (dbg_name, s->name);
783 if (match)
785 sections[j].offset = s->pointer_to_raw_data;
786 sections[j].size = s->virtual_size <= s->size_of_raw_data ?
787 s->virtual_size : s->size_of_raw_data;
788 break;
793 if (syms_num != 0)
795 struct coff_syminfo_data *sdata;
797 sdata = ((struct coff_syminfo_data *)
798 backtrace_alloc (state, sizeof *sdata, error_callback, data));
799 if (sdata == NULL)
800 goto fail;
802 if (!coff_initialize_syminfo (state, image_base, is_64,
803 sects, sects_num,
804 syms_view.data, syms_size,
805 str_view.data, str_size,
806 error_callback, data, sdata))
808 backtrace_free (state, sdata, sizeof *sdata, error_callback, data);
809 goto fail;
812 *found_sym = 1;
814 coff_add_syminfo_data (state, sdata);
817 backtrace_release_view (state, &sects_view, error_callback, data);
818 sects_view_valid = 0;
819 if (syms_view_valid)
821 backtrace_release_view (state, &syms_view, error_callback, data);
822 syms_view_valid = 0;
825 /* Read all the debug sections in a single view, since they are
826 probably adjacent in the file. We never release this view. */
828 min_offset = 0;
829 max_offset = 0;
830 for (i = 0; i < (int) DEBUG_MAX; ++i)
832 off_t end;
834 if (sections[i].size == 0)
835 continue;
836 if (min_offset == 0 || sections[i].offset < min_offset)
837 min_offset = sections[i].offset;
838 end = sections[i].offset + sections[i].size;
839 if (end > max_offset)
840 max_offset = end;
842 if (min_offset == 0 || max_offset == 0)
844 if (!backtrace_close (descriptor, error_callback, data))
845 goto fail;
846 *fileline_fn = coff_nodebug;
847 return 1;
850 if (!backtrace_get_view (state, descriptor, min_offset,
851 max_offset - min_offset,
852 error_callback, data, &debug_view))
853 goto fail;
854 debug_view_valid = 1;
856 /* We've read all we need from the executable. */
857 if (!backtrace_close (descriptor, error_callback, data))
858 goto fail;
859 descriptor = -1;
861 for (i = 0; i < (int) DEBUG_MAX; ++i)
863 size_t size = sections[i].size;
864 dwarf_sections.size[i] = size;
865 if (size == 0)
866 dwarf_sections.data[i] = NULL;
867 else
868 dwarf_sections.data[i] = ((const unsigned char *) debug_view.data
869 + (sections[i].offset - min_offset));
872 #ifdef HAVE_WINDOWS_H
874 uintptr_t module_handle;
876 module_handle = (uintptr_t) GetModuleHandle (NULL);
877 base_address = module_handle - image_base;
879 #endif
881 if (!backtrace_dwarf_add (state, base_address, &dwarf_sections,
882 0, /* FIXME: is_bigendian */
883 NULL, /* altlink */
884 error_callback, data, fileline_fn,
885 NULL /* returned fileline_entry */))
886 goto fail;
888 *found_dwarf = 1;
890 return 1;
892 fail:
893 if (sects_view_valid)
894 backtrace_release_view (state, &sects_view, error_callback, data);
895 if (str_view_valid)
896 backtrace_release_view (state, &str_view, error_callback, data);
897 if (syms_view_valid)
898 backtrace_release_view (state, &syms_view, error_callback, data);
899 if (debug_view_valid)
900 backtrace_release_view (state, &debug_view, error_callback, data);
901 if (descriptor != -1)
902 backtrace_close (descriptor, error_callback, data);
903 return 0;
906 /* Initialize the backtrace data we need from an ELF executable. At
907 the ELF level, all we need to do is find the debug info
908 sections. */
911 backtrace_initialize (struct backtrace_state *state,
912 const char *filename ATTRIBUTE_UNUSED, int descriptor,
913 backtrace_error_callback error_callback,
914 void *data, fileline *fileline_fn)
916 int ret;
917 int found_sym;
918 int found_dwarf;
919 fileline coff_fileline_fn;
921 ret = coff_add (state, descriptor, error_callback, data,
922 &coff_fileline_fn, &found_sym, &found_dwarf);
923 if (!ret)
924 return 0;
926 if (!state->threaded)
928 if (found_sym)
929 state->syminfo_fn = coff_syminfo;
930 else if (state->syminfo_fn == NULL)
931 state->syminfo_fn = coff_nosyms;
933 else
935 if (found_sym)
936 backtrace_atomic_store_pointer (&state->syminfo_fn, coff_syminfo);
937 else
938 (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
939 coff_nosyms);
942 if (!state->threaded)
944 if (state->fileline_fn == NULL || state->fileline_fn == coff_nodebug)
945 *fileline_fn = coff_fileline_fn;
947 else
949 fileline current_fn;
951 current_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
952 if (current_fn == NULL || current_fn == coff_nodebug)
953 *fileline_fn = coff_fileline_fn;
956 return 1;