libstdc++: Guard uses of is_pointer_interconvertible_v [PR114891]
[official-gcc.git] / libbacktrace / pecoff.c
blob4f2678411785aee0ac8f704115c6a8fbf24bd45c
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>
53 #ifdef HAVE_TLHELP32_H
54 #include <tlhelp32.h>
56 #ifdef UNICODE
57 /* If UNICODE is defined, all the symbols are replaced by a macro to use the
58 wide variant. But we need the ansi variant, so undef the macros. */
59 #undef MODULEENTRY32
60 #undef Module32First
61 #undef Module32Next
62 #endif
63 #endif
64 #endif
66 /* Coff file header. */
68 typedef struct {
69 uint16_t machine;
70 uint16_t number_of_sections;
71 uint32_t time_date_stamp;
72 uint32_t pointer_to_symbol_table;
73 uint32_t number_of_symbols;
74 uint16_t size_of_optional_header;
75 uint16_t characteristics;
76 } b_coff_file_header;
78 /* Coff optional header. */
80 typedef struct {
81 uint16_t magic;
82 uint8_t major_linker_version;
83 uint8_t minor_linker_version;
84 uint32_t size_of_code;
85 uint32_t size_of_initialized_data;
86 uint32_t size_of_uninitialized_data;
87 uint32_t address_of_entry_point;
88 uint32_t base_of_code;
89 union {
90 struct {
91 uint32_t base_of_data;
92 uint32_t image_base;
93 } pe;
94 struct {
95 uint64_t image_base;
96 } pep;
97 } u;
98 } b_coff_optional_header;
100 /* Values of magic in optional header. */
102 #define PE_MAGIC 0x10b /* PE32 executable. */
103 #define PEP_MAGIC 0x20b /* PE32+ executable (for 64bit targets). */
105 /* Coff section header. */
107 typedef struct {
108 char name[8];
109 uint32_t virtual_size;
110 uint32_t virtual_address;
111 uint32_t size_of_raw_data;
112 uint32_t pointer_to_raw_data;
113 uint32_t pointer_to_relocations;
114 uint32_t pointer_to_line_numbers;
115 uint16_t number_of_relocations;
116 uint16_t number_of_line_numbers;
117 uint32_t characteristics;
118 } b_coff_section_header;
120 /* Coff symbol name. */
122 typedef union {
123 char short_name[8];
124 struct {
125 unsigned char zeroes[4];
126 unsigned char off[4];
127 } long_name;
128 } b_coff_name;
130 /* Coff symbol (external representation which is unaligned). */
132 typedef struct {
133 b_coff_name name;
134 unsigned char value[4];
135 unsigned char section_number[2];
136 unsigned char type[2];
137 unsigned char storage_class;
138 unsigned char number_of_aux_symbols;
139 } b_coff_external_symbol;
141 /* Symbol types. */
143 #define N_TBSHFT 4 /* Shift for the derived type. */
144 #define IMAGE_SYM_DTYPE_FUNCTION 2 /* Function derived type. */
146 /* Size of a coff symbol. */
148 #define SYM_SZ 18
150 /* Coff symbol, internal representation (aligned). */
152 typedef struct {
153 const char *name;
154 uint32_t value;
155 int16_t sec;
156 uint16_t type;
157 uint16_t sc;
158 } b_coff_internal_symbol;
160 /* Names of sections, indexed by enum dwarf_section in internal.h. */
162 static const char * const debug_section_names[DEBUG_MAX] =
164 ".debug_info",
165 ".debug_line",
166 ".debug_abbrev",
167 ".debug_ranges",
168 ".debug_str",
169 ".debug_addr",
170 ".debug_str_offsets",
171 ".debug_line_str",
172 ".debug_rnglists"
175 /* Information we gather for the sections we care about. */
177 struct debug_section_info
179 /* Section file offset. */
180 off_t offset;
181 /* Section size. */
182 size_t size;
185 /* Information we keep for an coff symbol. */
187 struct coff_symbol
189 /* The name of the symbol. */
190 const char *name;
191 /* The address of the symbol. */
192 uintptr_t address;
195 /* Information to pass to coff_syminfo. */
197 struct coff_syminfo_data
199 /* Symbols for the next module. */
200 struct coff_syminfo_data *next;
201 /* The COFF symbols, sorted by address. */
202 struct coff_symbol *symbols;
203 /* The number of symbols. */
204 size_t count;
207 /* A dummy callback function used when we can't find any debug info. */
209 static int
210 coff_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
211 uintptr_t pc ATTRIBUTE_UNUSED,
212 backtrace_full_callback callback ATTRIBUTE_UNUSED,
213 backtrace_error_callback error_callback, void *data)
215 error_callback (data, "no debug info in PE/COFF executable", -1);
216 return 0;
219 /* A dummy callback function used when we can't find a symbol
220 table. */
222 static void
223 coff_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,
224 uintptr_t addr ATTRIBUTE_UNUSED,
225 backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,
226 backtrace_error_callback error_callback, void *data)
228 error_callback (data, "no symbol table in PE/COFF executable", -1);
231 /* Read a potentially unaligned 4 byte word at P, using native endianness. */
233 static uint32_t
234 coff_read4 (const unsigned char *p)
236 uint32_t res;
238 memcpy (&res, p, 4);
239 return res;
242 /* Read a potentially unaligned 2 byte word at P, using native endianness.
243 All 2 byte word in symbols are always aligned, but for coherency all
244 fields are declared as char arrays. */
246 static uint16_t
247 coff_read2 (const unsigned char *p)
249 uint16_t res;
251 memcpy (&res, p, sizeof (res));
252 return res;
255 /* Return the length (without the trailing 0) of a COFF short name. */
257 static size_t
258 coff_short_name_len (const char *name)
260 int i;
262 for (i = 0; i < 8; i++)
263 if (name[i] == 0)
264 return i;
265 return 8;
268 /* Return true iff COFF short name CNAME is the same as NAME (a NUL-terminated
269 string). */
271 static int
272 coff_short_name_eq (const char *name, const char *cname)
274 int i;
276 for (i = 0; i < 8; i++)
278 if (name[i] != cname[i])
279 return 0;
280 if (name[i] == 0)
281 return 1;
283 return name[8] == 0;
286 /* Return true iff NAME is the same as string at offset OFF. */
288 static int
289 coff_long_name_eq (const char *name, unsigned int off,
290 struct backtrace_view *str_view)
292 if (off >= str_view->len)
293 return 0;
294 return strcmp (name, (const char *)str_view->data + off) == 0;
297 /* Compare struct coff_symbol for qsort. */
299 static int
300 coff_symbol_compare (const void *v1, const void *v2)
302 const struct coff_symbol *e1 = (const struct coff_symbol *) v1;
303 const struct coff_symbol *e2 = (const struct coff_symbol *) v2;
305 if (e1->address < e2->address)
306 return -1;
307 else if (e1->address > e2->address)
308 return 1;
309 else
310 return 0;
313 /* Convert SYM to internal (and aligned) format ISYM, using string table
314 from STRTAB and STRTAB_SIZE, and number of sections SECTS_NUM.
315 Return -1 in case of error (invalid section number or string index). */
317 static int
318 coff_expand_symbol (b_coff_internal_symbol *isym,
319 const b_coff_external_symbol *sym,
320 uint16_t sects_num,
321 const unsigned char *strtab, size_t strtab_size)
323 isym->type = coff_read2 (sym->type);
324 isym->sec = coff_read2 (sym->section_number);
325 isym->sc = sym->storage_class;
327 if (isym->sec > 0 && (uint16_t) isym->sec > sects_num)
328 return -1;
329 if (sym->name.short_name[0] != 0)
330 isym->name = sym->name.short_name;
331 else
333 uint32_t off = coff_read4 (sym->name.long_name.off);
335 if (off >= strtab_size)
336 return -1;
337 isym->name = (const char *) strtab + off;
339 return 0;
342 /* Return true iff SYM is a defined symbol for a function. Data symbols
343 aren't considered because they aren't easily identified (same type as
344 section names, presence of symbols defined by the linker script). */
346 static int
347 coff_is_function_symbol (const b_coff_internal_symbol *isym)
349 return (isym->type >> N_TBSHFT) == IMAGE_SYM_DTYPE_FUNCTION
350 && isym->sec > 0;
353 /* Initialize the symbol table info for coff_syminfo. */
355 static int
356 coff_initialize_syminfo (struct backtrace_state *state,
357 uintptr_t base_address, int is_64,
358 const b_coff_section_header *sects, size_t sects_num,
359 const b_coff_external_symbol *syms, size_t syms_size,
360 const unsigned char *strtab, size_t strtab_size,
361 backtrace_error_callback error_callback,
362 void *data, struct coff_syminfo_data *sdata)
364 size_t syms_count;
365 char *coff_symstr;
366 size_t coff_symstr_len;
367 size_t coff_symbol_count;
368 size_t coff_symbol_size;
369 struct coff_symbol *coff_symbols;
370 struct coff_symbol *coff_sym;
371 char *coff_str;
372 size_t i;
374 syms_count = syms_size / SYM_SZ;
376 /* We only care about function symbols. Count them. Also count size of
377 strings for in-symbol names. */
378 coff_symbol_count = 0;
379 coff_symstr_len = 0;
380 for (i = 0; i < syms_count; ++i)
382 const b_coff_external_symbol *asym = &syms[i];
383 b_coff_internal_symbol isym;
385 if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size) < 0)
387 error_callback (data, "invalid section or offset in coff symbol", 0);
388 return 0;
390 if (coff_is_function_symbol (&isym))
392 ++coff_symbol_count;
393 if (asym->name.short_name[0] != 0)
394 coff_symstr_len += coff_short_name_len (asym->name.short_name) + 1;
397 i += asym->number_of_aux_symbols;
400 coff_symbol_size = (coff_symbol_count + 1) * sizeof (struct coff_symbol);
401 coff_symbols = ((struct coff_symbol *)
402 backtrace_alloc (state, coff_symbol_size, error_callback,
403 data));
404 if (coff_symbols == NULL)
405 return 0;
407 /* Allocate memory for symbols strings. */
408 if (coff_symstr_len > 0)
410 coff_symstr = ((char *)
411 backtrace_alloc (state, coff_symstr_len, error_callback,
412 data));
413 if (coff_symstr == NULL)
415 backtrace_free (state, coff_symbols, coff_symbol_size,
416 error_callback, data);
417 return 0;
420 else
421 coff_symstr = NULL;
423 /* Copy symbols. */
424 coff_sym = coff_symbols;
425 coff_str = coff_symstr;
426 for (i = 0; i < syms_count; ++i)
428 const b_coff_external_symbol *asym = &syms[i];
429 b_coff_internal_symbol isym;
431 if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size))
433 /* Should not fail, as it was already tested in the previous
434 loop. */
435 abort ();
437 if (coff_is_function_symbol (&isym))
439 const char *name;
440 int16_t secnum;
442 if (asym->name.short_name[0] != 0)
444 size_t len = coff_short_name_len (isym.name);
445 name = coff_str;
446 memcpy (coff_str, isym.name, len);
447 coff_str[len] = 0;
448 coff_str += len + 1;
450 else
451 name = isym.name;
453 if (!is_64)
455 /* Strip leading '_'. */
456 if (name[0] == '_')
457 name++;
460 /* Symbol value is section relative, so we need to read the address
461 of its section. */
462 secnum = coff_read2 (asym->section_number);
464 coff_sym->name = name;
465 coff_sym->address = (coff_read4 (asym->value)
466 + sects[secnum - 1].virtual_address
467 + base_address);
468 coff_sym++;
471 i += asym->number_of_aux_symbols;
474 /* End of symbols marker. */
475 coff_sym->name = NULL;
476 coff_sym->address = -1;
478 backtrace_qsort (coff_symbols, coff_symbol_count,
479 sizeof (struct coff_symbol), coff_symbol_compare);
481 sdata->next = NULL;
482 sdata->symbols = coff_symbols;
483 sdata->count = coff_symbol_count;
485 return 1;
488 /* Add EDATA to the list in STATE. */
490 static void
491 coff_add_syminfo_data (struct backtrace_state *state,
492 struct coff_syminfo_data *sdata)
494 if (!state->threaded)
496 struct coff_syminfo_data **pp;
498 for (pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
499 *pp != NULL;
500 pp = &(*pp)->next)
502 *pp = sdata;
504 else
506 while (1)
508 struct coff_syminfo_data **pp;
510 pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
512 while (1)
514 struct coff_syminfo_data *p;
516 p = backtrace_atomic_load_pointer (pp);
518 if (p == NULL)
519 break;
521 pp = &p->next;
524 if (__sync_bool_compare_and_swap (pp, NULL, sdata))
525 break;
530 /* Compare an ADDR against an elf_symbol for bsearch. We allocate one
531 extra entry in the array so that this can look safely at the next
532 entry. */
534 static int
535 coff_symbol_search (const void *vkey, const void *ventry)
537 const uintptr_t *key = (const uintptr_t *) vkey;
538 const struct coff_symbol *entry = (const struct coff_symbol *) ventry;
539 uintptr_t addr;
541 addr = *key;
542 if (addr < entry->address)
543 return -1;
544 else if (addr >= entry[1].address)
545 return 1;
546 else
547 return 0;
550 /* Return the symbol name and value for an ADDR. */
552 static void
553 coff_syminfo (struct backtrace_state *state, uintptr_t addr,
554 backtrace_syminfo_callback callback,
555 backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
556 void *data)
558 struct coff_syminfo_data *sdata;
559 struct coff_symbol *sym = NULL;
561 if (!state->threaded)
563 for (sdata = (struct coff_syminfo_data *) state->syminfo_data;
564 sdata != NULL;
565 sdata = sdata->next)
567 sym = ((struct coff_symbol *)
568 bsearch (&addr, sdata->symbols, sdata->count,
569 sizeof (struct coff_symbol), coff_symbol_search));
570 if (sym != NULL)
571 break;
574 else
576 struct coff_syminfo_data **pp;
578 pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
579 while (1)
581 sdata = backtrace_atomic_load_pointer (pp);
582 if (sdata == NULL)
583 break;
585 sym = ((struct coff_symbol *)
586 bsearch (&addr, sdata->symbols, sdata->count,
587 sizeof (struct coff_symbol), coff_symbol_search));
588 if (sym != NULL)
589 break;
591 pp = &sdata->next;
595 if (sym == NULL)
596 callback (data, addr, NULL, 0, 0);
597 else
598 callback (data, addr, sym->name, sym->address, 0);
601 /* Add the backtrace data for one PE/COFF file. Returns 1 on success,
602 0 on failure (in both cases descriptor is closed). */
604 static int
605 coff_add (struct backtrace_state *state, int descriptor,
606 backtrace_error_callback error_callback, void *data,
607 fileline *fileline_fn, int *found_sym, int *found_dwarf,
608 uintptr_t module_handle ATTRIBUTE_UNUSED)
610 struct backtrace_view fhdr_view;
611 off_t fhdr_off;
612 int magic_ok;
613 b_coff_file_header fhdr;
614 off_t opt_sects_off;
615 size_t opt_sects_size;
616 unsigned int sects_num;
617 struct backtrace_view sects_view;
618 int sects_view_valid;
619 const b_coff_optional_header *opt_hdr;
620 const b_coff_section_header *sects;
621 struct backtrace_view str_view;
622 int str_view_valid;
623 size_t str_size;
624 off_t str_off;
625 struct backtrace_view syms_view;
626 off_t syms_off;
627 size_t syms_size;
628 int syms_view_valid;
629 unsigned int syms_num;
630 unsigned int i;
631 struct debug_section_info sections[DEBUG_MAX];
632 off_t min_offset;
633 off_t max_offset;
634 struct backtrace_view debug_view;
635 int debug_view_valid;
636 int is_64;
637 uintptr_t image_base;
638 uintptr_t base_address = 0;
639 struct dwarf_sections dwarf_sections;
641 *found_sym = 0;
642 *found_dwarf = 0;
644 sects_view_valid = 0;
645 syms_view_valid = 0;
646 str_view_valid = 0;
647 debug_view_valid = 0;
649 /* Map the MS-DOS stub (if any) and extract file header offset. */
650 if (!backtrace_get_view (state, descriptor, 0, 0x40, error_callback,
651 data, &fhdr_view))
652 goto fail;
655 const unsigned char *vptr = fhdr_view.data;
657 if (vptr[0] == 'M' && vptr[1] == 'Z')
658 fhdr_off = coff_read4 (vptr + 0x3c);
659 else
660 fhdr_off = 0;
663 backtrace_release_view (state, &fhdr_view, error_callback, data);
665 /* Map the coff file header. */
666 if (!backtrace_get_view (state, descriptor, fhdr_off,
667 sizeof (b_coff_file_header) + 4,
668 error_callback, data, &fhdr_view))
669 goto fail;
671 if (fhdr_off != 0)
673 const char *magic = (const char *) fhdr_view.data;
674 magic_ok = memcmp (magic, "PE\0", 4) == 0;
675 fhdr_off += 4;
677 memcpy (&fhdr, fhdr_view.data + 4, sizeof fhdr);
679 else
681 memcpy (&fhdr, fhdr_view.data, sizeof fhdr);
682 /* TODO: test fhdr.machine for coff but non-PE platforms. */
683 magic_ok = 0;
685 backtrace_release_view (state, &fhdr_view, error_callback, data);
687 if (!magic_ok)
689 error_callback (data, "executable file is not COFF", 0);
690 goto fail;
693 sects_num = fhdr.number_of_sections;
694 syms_num = fhdr.number_of_symbols;
696 opt_sects_off = fhdr_off + sizeof (fhdr);
697 opt_sects_size = (fhdr.size_of_optional_header
698 + sects_num * sizeof (b_coff_section_header));
700 /* To translate PC to file/line when using DWARF, we need to find
701 the .debug_info and .debug_line sections. */
703 /* Read the optional header and the section headers. */
705 if (!backtrace_get_view (state, descriptor, opt_sects_off, opt_sects_size,
706 error_callback, data, &sects_view))
707 goto fail;
708 sects_view_valid = 1;
709 opt_hdr = (const b_coff_optional_header *) sects_view.data;
710 sects = (const b_coff_section_header *)
711 (sects_view.data + fhdr.size_of_optional_header);
713 is_64 = 0;
714 if (fhdr.size_of_optional_header > sizeof (*opt_hdr))
716 if (opt_hdr->magic == PE_MAGIC)
717 image_base = opt_hdr->u.pe.image_base;
718 else if (opt_hdr->magic == PEP_MAGIC)
720 image_base = opt_hdr->u.pep.image_base;
721 is_64 = 1;
723 else
725 error_callback (data, "bad magic in PE optional header", 0);
726 goto fail;
729 else
730 image_base = 0;
732 /* Read the symbol table and the string table. */
734 if (fhdr.pointer_to_symbol_table == 0)
736 /* No symbol table, no string table. */
737 str_off = 0;
738 str_size = 0;
739 syms_num = 0;
740 syms_size = 0;
742 else
744 /* Symbol table is followed by the string table. The string table
745 starts with its length (on 4 bytes).
746 Map the symbol table and the length of the string table. */
747 syms_off = fhdr.pointer_to_symbol_table;
748 syms_size = syms_num * SYM_SZ;
750 if (!backtrace_get_view (state, descriptor, syms_off, syms_size + 4,
751 error_callback, data, &syms_view))
752 goto fail;
753 syms_view_valid = 1;
755 str_size = coff_read4 (syms_view.data + syms_size);
757 str_off = syms_off + syms_size;
759 if (str_size > 4)
761 /* Map string table (including the length word). */
763 if (!backtrace_get_view (state, descriptor, str_off, str_size,
764 error_callback, data, &str_view))
765 goto fail;
766 str_view_valid = 1;
770 memset (sections, 0, sizeof sections);
772 /* Look for the symbol table. */
773 for (i = 0; i < sects_num; ++i)
775 const b_coff_section_header *s = sects + i;
776 unsigned int str_off;
777 int j;
779 if (s->name[0] == '/')
781 /* Extended section name. */
782 str_off = atoi (s->name + 1);
784 else
785 str_off = 0;
787 for (j = 0; j < (int) DEBUG_MAX; ++j)
789 const char *dbg_name = debug_section_names[j];
790 int match;
792 if (str_off != 0)
793 match = coff_long_name_eq (dbg_name, str_off, &str_view);
794 else
795 match = coff_short_name_eq (dbg_name, s->name);
796 if (match)
798 sections[j].offset = s->pointer_to_raw_data;
799 sections[j].size = s->virtual_size <= s->size_of_raw_data ?
800 s->virtual_size : s->size_of_raw_data;
801 break;
806 if (syms_num != 0)
808 struct coff_syminfo_data *sdata;
810 sdata = ((struct coff_syminfo_data *)
811 backtrace_alloc (state, sizeof *sdata, error_callback, data));
812 if (sdata == NULL)
813 goto fail;
815 if (!coff_initialize_syminfo (state, image_base, is_64,
816 sects, sects_num,
817 syms_view.data, syms_size,
818 str_view.data, str_size,
819 error_callback, data, sdata))
821 backtrace_free (state, sdata, sizeof *sdata, error_callback, data);
822 goto fail;
825 *found_sym = 1;
827 coff_add_syminfo_data (state, sdata);
830 backtrace_release_view (state, &sects_view, error_callback, data);
831 sects_view_valid = 0;
832 if (syms_view_valid)
834 backtrace_release_view (state, &syms_view, error_callback, data);
835 syms_view_valid = 0;
838 /* Read all the debug sections in a single view, since they are
839 probably adjacent in the file. We never release this view. */
841 min_offset = 0;
842 max_offset = 0;
843 for (i = 0; i < (int) DEBUG_MAX; ++i)
845 off_t end;
847 if (sections[i].size == 0)
848 continue;
849 if (min_offset == 0 || sections[i].offset < min_offset)
850 min_offset = sections[i].offset;
851 end = sections[i].offset + sections[i].size;
852 if (end > max_offset)
853 max_offset = end;
855 if (min_offset == 0 || max_offset == 0)
857 if (!backtrace_close (descriptor, error_callback, data))
858 goto fail;
859 *fileline_fn = coff_nodebug;
860 return 1;
863 if (!backtrace_get_view (state, descriptor, min_offset,
864 max_offset - min_offset,
865 error_callback, data, &debug_view))
866 goto fail;
867 debug_view_valid = 1;
869 /* We've read all we need from the executable. */
870 if (!backtrace_close (descriptor, error_callback, data))
871 goto fail;
872 descriptor = -1;
874 for (i = 0; i < (int) DEBUG_MAX; ++i)
876 size_t size = sections[i].size;
877 dwarf_sections.size[i] = size;
878 if (size == 0)
879 dwarf_sections.data[i] = NULL;
880 else
881 dwarf_sections.data[i] = ((const unsigned char *) debug_view.data
882 + (sections[i].offset - min_offset));
885 #ifdef HAVE_WINDOWS_H
886 base_address = module_handle - image_base;
887 #endif
889 if (!backtrace_dwarf_add (state, base_address, &dwarf_sections,
890 0, /* FIXME: is_bigendian */
891 NULL, /* altlink */
892 error_callback, data, fileline_fn,
893 NULL /* returned fileline_entry */))
894 goto fail;
896 *found_dwarf = 1;
898 return 1;
900 fail:
901 if (sects_view_valid)
902 backtrace_release_view (state, &sects_view, error_callback, data);
903 if (str_view_valid)
904 backtrace_release_view (state, &str_view, error_callback, data);
905 if (syms_view_valid)
906 backtrace_release_view (state, &syms_view, error_callback, data);
907 if (debug_view_valid)
908 backtrace_release_view (state, &debug_view, error_callback, data);
909 if (descriptor != -1)
910 backtrace_close (descriptor, error_callback, data);
911 return 0;
914 /* Initialize the backtrace data we need from an ELF executable. At
915 the ELF level, all we need to do is find the debug info
916 sections. */
919 backtrace_initialize (struct backtrace_state *state,
920 const char *filename ATTRIBUTE_UNUSED, int descriptor,
921 backtrace_error_callback error_callback,
922 void *data, fileline *fileline_fn)
924 int ret;
925 int found_sym;
926 int found_dwarf;
927 fileline coff_fileline_fn;
928 uintptr_t module_handle = 0;
929 #ifdef HAVE_TLHELP32_H
930 fileline module_fileline_fn;
931 int module_found_sym;
932 HANDLE snapshot;
933 #endif
935 #ifdef HAVE_WINDOWS_H
936 module_handle = (uintptr_t) GetModuleHandle (NULL);
937 #endif
939 ret = coff_add (state, descriptor, error_callback, data,
940 &coff_fileline_fn, &found_sym, &found_dwarf, module_handle);
941 if (!ret)
942 return 0;
944 #ifdef HAVE_TLHELP32_H
947 snapshot = CreateToolhelp32Snapshot (TH32CS_SNAPMODULE, 0);
949 while (snapshot == INVALID_HANDLE_VALUE
950 && GetLastError () == ERROR_BAD_LENGTH);
952 if (snapshot != INVALID_HANDLE_VALUE)
954 MODULEENTRY32 entry;
955 BOOL ok;
956 entry.dwSize = sizeof (MODULEENTRY32);
958 for (ok = Module32First (snapshot, &entry); ok; ok = Module32Next (snapshot, &entry))
960 if (strcmp (filename, entry.szExePath) == 0)
961 continue;
963 module_handle = (uintptr_t) entry.hModule;
964 if (module_handle == 0)
965 continue;
967 descriptor = backtrace_open (entry.szExePath, error_callback, data,
968 NULL);
969 if (descriptor < 0)
970 continue;
972 coff_add (state, descriptor, error_callback, data,
973 &module_fileline_fn, &module_found_sym, &found_dwarf,
974 module_handle);
975 if (module_found_sym)
976 found_sym = 1;
979 CloseHandle (snapshot);
981 #endif
983 if (!state->threaded)
985 if (found_sym)
986 state->syminfo_fn = coff_syminfo;
987 else if (state->syminfo_fn == NULL)
988 state->syminfo_fn = coff_nosyms;
990 else
992 if (found_sym)
993 backtrace_atomic_store_pointer (&state->syminfo_fn, coff_syminfo);
994 else
995 (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
996 coff_nosyms);
999 if (!state->threaded)
1001 if (state->fileline_fn == NULL || state->fileline_fn == coff_nodebug)
1002 *fileline_fn = coff_fileline_fn;
1004 else
1006 fileline current_fn;
1008 current_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
1009 if (current_fn == NULL || current_fn == coff_nodebug)
1010 *fileline_fn = coff_fileline_fn;
1013 return 1;