Fortran: Unlimited polymorphic intrinsic function arguments [PR84006]
[official-gcc.git] / libbacktrace / pecoff.c
blobbbb59e26d7a643b16cb318fff09f1c993eb20cd1
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
65 #if defined(_ARM_)
66 #define NTAPI
67 #else
68 #define NTAPI __stdcall
69 #endif
71 /* This is a simplified (but binary compatible) version of what Microsoft
72 defines in their documentation. */
73 struct dll_notification_data
75 ULONG reserved;
76 /* The name as UNICODE_STRING struct. */
77 PVOID full_dll_name;
78 PVOID base_dll_name;
79 PVOID dll_base;
80 ULONG size_of_image;
83 #define LDR_DLL_NOTIFICATION_REASON_LOADED 1
85 typedef LONG NTSTATUS;
86 typedef VOID CALLBACK (*LDR_DLL_NOTIFICATION)(ULONG,
87 struct dll_notification_data*,
88 PVOID);
89 typedef NTSTATUS NTAPI (*LDR_REGISTER_FUNCTION)(ULONG,
90 LDR_DLL_NOTIFICATION, PVOID,
91 PVOID*);
92 #endif
94 /* Coff file header. */
96 typedef struct {
97 uint16_t machine;
98 uint16_t number_of_sections;
99 uint32_t time_date_stamp;
100 uint32_t pointer_to_symbol_table;
101 uint32_t number_of_symbols;
102 uint16_t size_of_optional_header;
103 uint16_t characteristics;
104 } b_coff_file_header;
106 /* Coff optional header. */
108 typedef struct {
109 uint16_t magic;
110 uint8_t major_linker_version;
111 uint8_t minor_linker_version;
112 uint32_t size_of_code;
113 uint32_t size_of_initialized_data;
114 uint32_t size_of_uninitialized_data;
115 uint32_t address_of_entry_point;
116 uint32_t base_of_code;
117 union {
118 struct {
119 uint32_t base_of_data;
120 uint32_t image_base;
121 } pe;
122 struct {
123 uint64_t image_base;
124 } pep;
125 } u;
126 } b_coff_optional_header;
128 /* Values of magic in optional header. */
130 #define PE_MAGIC 0x10b /* PE32 executable. */
131 #define PEP_MAGIC 0x20b /* PE32+ executable (for 64bit targets). */
133 /* Coff section header. */
135 typedef struct {
136 char name[8];
137 uint32_t virtual_size;
138 uint32_t virtual_address;
139 uint32_t size_of_raw_data;
140 uint32_t pointer_to_raw_data;
141 uint32_t pointer_to_relocations;
142 uint32_t pointer_to_line_numbers;
143 uint16_t number_of_relocations;
144 uint16_t number_of_line_numbers;
145 uint32_t characteristics;
146 } b_coff_section_header;
148 /* Coff symbol name. */
150 typedef union {
151 char short_name[8];
152 struct {
153 unsigned char zeroes[4];
154 unsigned char off[4];
155 } long_name;
156 } b_coff_name;
158 /* Coff symbol (external representation which is unaligned). */
160 typedef struct {
161 b_coff_name name;
162 unsigned char value[4];
163 unsigned char section_number[2];
164 unsigned char type[2];
165 unsigned char storage_class;
166 unsigned char number_of_aux_symbols;
167 } b_coff_external_symbol;
169 /* Symbol types. */
171 #define N_TBSHFT 4 /* Shift for the derived type. */
172 #define IMAGE_SYM_DTYPE_FUNCTION 2 /* Function derived type. */
174 /* Size of a coff symbol. */
176 #define SYM_SZ 18
178 /* Coff symbol, internal representation (aligned). */
180 typedef struct {
181 const char *name;
182 uint32_t value;
183 int16_t sec;
184 uint16_t type;
185 uint16_t sc;
186 } b_coff_internal_symbol;
188 /* Names of sections, indexed by enum dwarf_section in internal.h. */
190 static const char * const debug_section_names[DEBUG_MAX] =
192 ".debug_info",
193 ".debug_line",
194 ".debug_abbrev",
195 ".debug_ranges",
196 ".debug_str",
197 ".debug_addr",
198 ".debug_str_offsets",
199 ".debug_line_str",
200 ".debug_rnglists"
203 /* Information we gather for the sections we care about. */
205 struct debug_section_info
207 /* Section file offset. */
208 off_t offset;
209 /* Section size. */
210 size_t size;
213 /* Information we keep for an coff symbol. */
215 struct coff_symbol
217 /* The name of the symbol. */
218 const char *name;
219 /* The address of the symbol. */
220 uintptr_t address;
223 /* Information to pass to coff_syminfo. */
225 struct coff_syminfo_data
227 /* Symbols for the next module. */
228 struct coff_syminfo_data *next;
229 /* The COFF symbols, sorted by address. */
230 struct coff_symbol *symbols;
231 /* The number of symbols. */
232 size_t count;
235 /* A dummy callback function used when we can't find any debug info. */
237 static int
238 coff_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
239 uintptr_t pc ATTRIBUTE_UNUSED,
240 backtrace_full_callback callback ATTRIBUTE_UNUSED,
241 backtrace_error_callback error_callback, void *data)
243 error_callback (data, "no debug info in PE/COFF executable", -1);
244 return 0;
247 /* A dummy callback function used when we can't find a symbol
248 table. */
250 static void
251 coff_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,
252 uintptr_t addr ATTRIBUTE_UNUSED,
253 backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,
254 backtrace_error_callback error_callback, void *data)
256 error_callback (data, "no symbol table in PE/COFF executable", -1);
259 /* Read a potentially unaligned 4 byte word at P, using native endianness. */
261 static uint32_t
262 coff_read4 (const unsigned char *p)
264 uint32_t res;
266 memcpy (&res, p, 4);
267 return res;
270 /* Read a potentially unaligned 2 byte word at P, using native endianness.
271 All 2 byte word in symbols are always aligned, but for coherency all
272 fields are declared as char arrays. */
274 static uint16_t
275 coff_read2 (const unsigned char *p)
277 uint16_t res;
279 memcpy (&res, p, sizeof (res));
280 return res;
283 /* Return the length (without the trailing 0) of a COFF short name. */
285 static size_t
286 coff_short_name_len (const char *name)
288 int i;
290 for (i = 0; i < 8; i++)
291 if (name[i] == 0)
292 return i;
293 return 8;
296 /* Return true iff COFF short name CNAME is the same as NAME (a NUL-terminated
297 string). */
299 static int
300 coff_short_name_eq (const char *name, const char *cname)
302 int i;
304 for (i = 0; i < 8; i++)
306 if (name[i] != cname[i])
307 return 0;
308 if (name[i] == 0)
309 return 1;
311 return name[8] == 0;
314 /* Return true iff NAME is the same as string at offset OFF. */
316 static int
317 coff_long_name_eq (const char *name, unsigned int off,
318 struct backtrace_view *str_view)
320 if (off >= str_view->len)
321 return 0;
322 return strcmp (name, (const char *)str_view->data + off) == 0;
325 /* Compare struct coff_symbol for qsort. */
327 static int
328 coff_symbol_compare (const void *v1, const void *v2)
330 const struct coff_symbol *e1 = (const struct coff_symbol *) v1;
331 const struct coff_symbol *e2 = (const struct coff_symbol *) v2;
333 if (e1->address < e2->address)
334 return -1;
335 else if (e1->address > e2->address)
336 return 1;
337 else
338 return 0;
341 /* Convert SYM to internal (and aligned) format ISYM, using string table
342 from STRTAB and STRTAB_SIZE, and number of sections SECTS_NUM.
343 Return -1 in case of error (invalid section number or string index). */
345 static int
346 coff_expand_symbol (b_coff_internal_symbol *isym,
347 const b_coff_external_symbol *sym,
348 uint16_t sects_num,
349 const unsigned char *strtab, size_t strtab_size)
351 isym->type = coff_read2 (sym->type);
352 isym->sec = coff_read2 (sym->section_number);
353 isym->sc = sym->storage_class;
355 if (isym->sec > 0 && (uint16_t) isym->sec > sects_num)
356 return -1;
357 if (sym->name.short_name[0] != 0)
358 isym->name = sym->name.short_name;
359 else
361 uint32_t off = coff_read4 (sym->name.long_name.off);
363 if (off >= strtab_size)
364 return -1;
365 isym->name = (const char *) strtab + off;
367 return 0;
370 /* Return true iff SYM is a defined symbol for a function. Data symbols
371 aren't considered because they aren't easily identified (same type as
372 section names, presence of symbols defined by the linker script). */
374 static int
375 coff_is_function_symbol (const b_coff_internal_symbol *isym)
377 return (isym->type >> N_TBSHFT) == IMAGE_SYM_DTYPE_FUNCTION
378 && isym->sec > 0;
381 /* Initialize the symbol table info for coff_syminfo. */
383 static int
384 coff_initialize_syminfo (struct backtrace_state *state,
385 uintptr_t base_address, int is_64,
386 const b_coff_section_header *sects, size_t sects_num,
387 const b_coff_external_symbol *syms, size_t syms_size,
388 const unsigned char *strtab, size_t strtab_size,
389 backtrace_error_callback error_callback,
390 void *data, struct coff_syminfo_data *sdata)
392 size_t syms_count;
393 char *coff_symstr;
394 size_t coff_symstr_len;
395 size_t coff_symbol_count;
396 size_t coff_symbol_size;
397 struct coff_symbol *coff_symbols;
398 struct coff_symbol *coff_sym;
399 char *coff_str;
400 size_t i;
402 syms_count = syms_size / SYM_SZ;
404 /* We only care about function symbols. Count them. Also count size of
405 strings for in-symbol names. */
406 coff_symbol_count = 0;
407 coff_symstr_len = 0;
408 for (i = 0; i < syms_count; ++i)
410 const b_coff_external_symbol *asym = &syms[i];
411 b_coff_internal_symbol isym;
413 if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size) < 0)
415 error_callback (data, "invalid section or offset in coff symbol", 0);
416 return 0;
418 if (coff_is_function_symbol (&isym))
420 ++coff_symbol_count;
421 if (asym->name.short_name[0] != 0)
422 coff_symstr_len += coff_short_name_len (asym->name.short_name) + 1;
425 i += asym->number_of_aux_symbols;
428 coff_symbol_size = (coff_symbol_count + 1) * sizeof (struct coff_symbol);
429 coff_symbols = ((struct coff_symbol *)
430 backtrace_alloc (state, coff_symbol_size, error_callback,
431 data));
432 if (coff_symbols == NULL)
433 return 0;
435 /* Allocate memory for symbols strings. */
436 if (coff_symstr_len > 0)
438 coff_symstr = ((char *)
439 backtrace_alloc (state, coff_symstr_len, error_callback,
440 data));
441 if (coff_symstr == NULL)
443 backtrace_free (state, coff_symbols, coff_symbol_size,
444 error_callback, data);
445 return 0;
448 else
449 coff_symstr = NULL;
451 /* Copy symbols. */
452 coff_sym = coff_symbols;
453 coff_str = coff_symstr;
454 for (i = 0; i < syms_count; ++i)
456 const b_coff_external_symbol *asym = &syms[i];
457 b_coff_internal_symbol isym;
459 if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size))
461 /* Should not fail, as it was already tested in the previous
462 loop. */
463 abort ();
465 if (coff_is_function_symbol (&isym))
467 const char *name;
468 int16_t secnum;
470 if (asym->name.short_name[0] != 0)
472 size_t len = coff_short_name_len (isym.name);
473 name = coff_str;
474 memcpy (coff_str, isym.name, len);
475 coff_str[len] = 0;
476 coff_str += len + 1;
478 else
479 name = isym.name;
481 if (!is_64)
483 /* Strip leading '_'. */
484 if (name[0] == '_')
485 name++;
488 /* Symbol value is section relative, so we need to read the address
489 of its section. */
490 secnum = coff_read2 (asym->section_number);
492 coff_sym->name = name;
493 coff_sym->address = (coff_read4 (asym->value)
494 + sects[secnum - 1].virtual_address
495 + base_address);
496 coff_sym++;
499 i += asym->number_of_aux_symbols;
502 /* End of symbols marker. */
503 coff_sym->name = NULL;
504 coff_sym->address = -1;
506 backtrace_qsort (coff_symbols, coff_symbol_count,
507 sizeof (struct coff_symbol), coff_symbol_compare);
509 sdata->next = NULL;
510 sdata->symbols = coff_symbols;
511 sdata->count = coff_symbol_count;
513 return 1;
516 /* Add EDATA to the list in STATE. */
518 static void
519 coff_add_syminfo_data (struct backtrace_state *state,
520 struct coff_syminfo_data *sdata)
522 if (!state->threaded)
524 struct coff_syminfo_data **pp;
526 for (pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
527 *pp != NULL;
528 pp = &(*pp)->next)
530 *pp = sdata;
532 else
534 while (1)
536 struct coff_syminfo_data **pp;
538 pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
540 while (1)
542 struct coff_syminfo_data *p;
544 p = backtrace_atomic_load_pointer (pp);
546 if (p == NULL)
547 break;
549 pp = &p->next;
552 if (__sync_bool_compare_and_swap (pp, NULL, sdata))
553 break;
558 /* Compare an ADDR against an elf_symbol for bsearch. We allocate one
559 extra entry in the array so that this can look safely at the next
560 entry. */
562 static int
563 coff_symbol_search (const void *vkey, const void *ventry)
565 const uintptr_t *key = (const uintptr_t *) vkey;
566 const struct coff_symbol *entry = (const struct coff_symbol *) ventry;
567 uintptr_t addr;
569 addr = *key;
570 if (addr < entry->address)
571 return -1;
572 else if (addr >= entry[1].address)
573 return 1;
574 else
575 return 0;
578 /* Return the symbol name and value for an ADDR. */
580 static void
581 coff_syminfo (struct backtrace_state *state, uintptr_t addr,
582 backtrace_syminfo_callback callback,
583 backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
584 void *data)
586 struct coff_syminfo_data *sdata;
587 struct coff_symbol *sym = NULL;
589 if (!state->threaded)
591 for (sdata = (struct coff_syminfo_data *) state->syminfo_data;
592 sdata != NULL;
593 sdata = sdata->next)
595 sym = ((struct coff_symbol *)
596 bsearch (&addr, sdata->symbols, sdata->count,
597 sizeof (struct coff_symbol), coff_symbol_search));
598 if (sym != NULL)
599 break;
602 else
604 struct coff_syminfo_data **pp;
606 pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
607 while (1)
609 sdata = backtrace_atomic_load_pointer (pp);
610 if (sdata == NULL)
611 break;
613 sym = ((struct coff_symbol *)
614 bsearch (&addr, sdata->symbols, sdata->count,
615 sizeof (struct coff_symbol), coff_symbol_search));
616 if (sym != NULL)
617 break;
619 pp = &sdata->next;
623 if (sym == NULL)
624 callback (data, addr, NULL, 0, 0);
625 else
626 callback (data, addr, sym->name, sym->address, 0);
629 /* Add the backtrace data for one PE/COFF file. Returns 1 on success,
630 0 on failure (in both cases descriptor is closed). */
632 static int
633 coff_add (struct backtrace_state *state, int descriptor,
634 backtrace_error_callback error_callback, void *data,
635 fileline *fileline_fn, int *found_sym, int *found_dwarf,
636 uintptr_t module_handle ATTRIBUTE_UNUSED)
638 struct backtrace_view fhdr_view;
639 off_t fhdr_off;
640 int magic_ok;
641 b_coff_file_header fhdr;
642 off_t opt_sects_off;
643 size_t opt_sects_size;
644 unsigned int sects_num;
645 struct backtrace_view sects_view;
646 int sects_view_valid;
647 const b_coff_optional_header *opt_hdr;
648 const b_coff_section_header *sects;
649 struct backtrace_view str_view;
650 int str_view_valid;
651 size_t str_size;
652 off_t str_off;
653 struct backtrace_view syms_view;
654 off_t syms_off;
655 size_t syms_size;
656 int syms_view_valid;
657 unsigned int syms_num;
658 unsigned int i;
659 struct debug_section_info sections[DEBUG_MAX];
660 off_t min_offset;
661 off_t max_offset;
662 struct backtrace_view debug_view;
663 int debug_view_valid;
664 int is_64;
665 uintptr_t image_base;
666 uintptr_t base_address = 0;
667 struct dwarf_sections dwarf_sections;
669 *found_sym = 0;
670 *found_dwarf = 0;
672 sects_view_valid = 0;
673 syms_view_valid = 0;
674 str_view_valid = 0;
675 debug_view_valid = 0;
677 /* Map the MS-DOS stub (if any) and extract file header offset. */
678 if (!backtrace_get_view (state, descriptor, 0, 0x40, error_callback,
679 data, &fhdr_view))
680 goto fail;
683 const unsigned char *vptr = fhdr_view.data;
685 if (vptr[0] == 'M' && vptr[1] == 'Z')
686 fhdr_off = coff_read4 (vptr + 0x3c);
687 else
688 fhdr_off = 0;
691 backtrace_release_view (state, &fhdr_view, error_callback, data);
693 /* Map the coff file header. */
694 if (!backtrace_get_view (state, descriptor, fhdr_off,
695 sizeof (b_coff_file_header) + 4,
696 error_callback, data, &fhdr_view))
697 goto fail;
699 if (fhdr_off != 0)
701 const char *magic = (const char *) fhdr_view.data;
702 magic_ok = memcmp (magic, "PE\0", 4) == 0;
703 fhdr_off += 4;
705 memcpy (&fhdr, fhdr_view.data + 4, sizeof fhdr);
707 else
709 memcpy (&fhdr, fhdr_view.data, sizeof fhdr);
710 /* TODO: test fhdr.machine for coff but non-PE platforms. */
711 magic_ok = 0;
713 backtrace_release_view (state, &fhdr_view, error_callback, data);
715 if (!magic_ok)
717 error_callback (data, "executable file is not COFF", 0);
718 goto fail;
721 sects_num = fhdr.number_of_sections;
722 syms_num = fhdr.number_of_symbols;
724 opt_sects_off = fhdr_off + sizeof (fhdr);
725 opt_sects_size = (fhdr.size_of_optional_header
726 + sects_num * sizeof (b_coff_section_header));
728 /* To translate PC to file/line when using DWARF, we need to find
729 the .debug_info and .debug_line sections. */
731 /* Read the optional header and the section headers. */
733 if (!backtrace_get_view (state, descriptor, opt_sects_off, opt_sects_size,
734 error_callback, data, &sects_view))
735 goto fail;
736 sects_view_valid = 1;
737 opt_hdr = (const b_coff_optional_header *) sects_view.data;
738 sects = (const b_coff_section_header *)
739 (sects_view.data + fhdr.size_of_optional_header);
741 is_64 = 0;
742 if (fhdr.size_of_optional_header > sizeof (*opt_hdr))
744 if (opt_hdr->magic == PE_MAGIC)
745 image_base = opt_hdr->u.pe.image_base;
746 else if (opt_hdr->magic == PEP_MAGIC)
748 image_base = opt_hdr->u.pep.image_base;
749 is_64 = 1;
751 else
753 error_callback (data, "bad magic in PE optional header", 0);
754 goto fail;
757 else
758 image_base = 0;
760 /* Read the symbol table and the string table. */
762 if (fhdr.pointer_to_symbol_table == 0)
764 /* No symbol table, no string table. */
765 str_off = 0;
766 str_size = 0;
767 syms_num = 0;
768 syms_size = 0;
770 else
772 /* Symbol table is followed by the string table. The string table
773 starts with its length (on 4 bytes).
774 Map the symbol table and the length of the string table. */
775 syms_off = fhdr.pointer_to_symbol_table;
776 syms_size = syms_num * SYM_SZ;
778 if (!backtrace_get_view (state, descriptor, syms_off, syms_size + 4,
779 error_callback, data, &syms_view))
780 goto fail;
781 syms_view_valid = 1;
783 str_size = coff_read4 (syms_view.data + syms_size);
785 str_off = syms_off + syms_size;
787 if (str_size > 4)
789 /* Map string table (including the length word). */
791 if (!backtrace_get_view (state, descriptor, str_off, str_size,
792 error_callback, data, &str_view))
793 goto fail;
794 str_view_valid = 1;
798 memset (sections, 0, sizeof sections);
800 /* Look for the symbol table. */
801 for (i = 0; i < sects_num; ++i)
803 const b_coff_section_header *s = sects + i;
804 unsigned int str_off;
805 int j;
807 if (s->name[0] == '/')
809 /* Extended section name. */
810 str_off = atoi (s->name + 1);
812 else
813 str_off = 0;
815 for (j = 0; j < (int) DEBUG_MAX; ++j)
817 const char *dbg_name = debug_section_names[j];
818 int match;
820 if (str_off != 0)
821 match = coff_long_name_eq (dbg_name, str_off, &str_view);
822 else
823 match = coff_short_name_eq (dbg_name, s->name);
824 if (match)
826 sections[j].offset = s->pointer_to_raw_data;
827 sections[j].size = s->virtual_size <= s->size_of_raw_data ?
828 s->virtual_size : s->size_of_raw_data;
829 break;
834 if (syms_num != 0)
836 struct coff_syminfo_data *sdata;
838 sdata = ((struct coff_syminfo_data *)
839 backtrace_alloc (state, sizeof *sdata, error_callback, data));
840 if (sdata == NULL)
841 goto fail;
843 if (!coff_initialize_syminfo (state, image_base, is_64,
844 sects, sects_num,
845 syms_view.data, syms_size,
846 str_view.data, str_size,
847 error_callback, data, sdata))
849 backtrace_free (state, sdata, sizeof *sdata, error_callback, data);
850 goto fail;
853 *found_sym = 1;
855 coff_add_syminfo_data (state, sdata);
858 backtrace_release_view (state, &sects_view, error_callback, data);
859 sects_view_valid = 0;
860 if (syms_view_valid)
862 backtrace_release_view (state, &syms_view, error_callback, data);
863 syms_view_valid = 0;
866 /* Read all the debug sections in a single view, since they are
867 probably adjacent in the file. We never release this view. */
869 min_offset = 0;
870 max_offset = 0;
871 for (i = 0; i < (int) DEBUG_MAX; ++i)
873 off_t end;
875 if (sections[i].size == 0)
876 continue;
877 if (min_offset == 0 || sections[i].offset < min_offset)
878 min_offset = sections[i].offset;
879 end = sections[i].offset + sections[i].size;
880 if (end > max_offset)
881 max_offset = end;
883 if (min_offset == 0 || max_offset == 0)
885 if (!backtrace_close (descriptor, error_callback, data))
886 goto fail;
887 *fileline_fn = coff_nodebug;
888 return 1;
891 if (!backtrace_get_view (state, descriptor, min_offset,
892 max_offset - min_offset,
893 error_callback, data, &debug_view))
894 goto fail;
895 debug_view_valid = 1;
897 /* We've read all we need from the executable. */
898 if (!backtrace_close (descriptor, error_callback, data))
899 goto fail;
900 descriptor = -1;
902 for (i = 0; i < (int) DEBUG_MAX; ++i)
904 size_t size = sections[i].size;
905 dwarf_sections.size[i] = size;
906 if (size == 0)
907 dwarf_sections.data[i] = NULL;
908 else
909 dwarf_sections.data[i] = ((const unsigned char *) debug_view.data
910 + (sections[i].offset - min_offset));
913 #ifdef HAVE_WINDOWS_H
914 base_address = module_handle - image_base;
915 #endif
917 if (!backtrace_dwarf_add (state, base_address, &dwarf_sections,
918 0, /* FIXME: is_bigendian */
919 NULL, /* altlink */
920 error_callback, data, fileline_fn,
921 NULL /* returned fileline_entry */))
922 goto fail;
924 *found_dwarf = 1;
926 return 1;
928 fail:
929 if (sects_view_valid)
930 backtrace_release_view (state, &sects_view, error_callback, data);
931 if (str_view_valid)
932 backtrace_release_view (state, &str_view, error_callback, data);
933 if (syms_view_valid)
934 backtrace_release_view (state, &syms_view, error_callback, data);
935 if (debug_view_valid)
936 backtrace_release_view (state, &debug_view, error_callback, data);
937 if (descriptor != -1)
938 backtrace_close (descriptor, error_callback, data);
939 return 0;
942 #ifdef HAVE_WINDOWS_H
943 struct dll_notification_context
945 struct backtrace_state *state;
946 backtrace_error_callback error_callback;
947 void *data;
950 static VOID CALLBACK
951 dll_notification (ULONG reason,
952 struct dll_notification_data *notification_data,
953 PVOID context)
955 char module_name[MAX_PATH];
956 int descriptor;
957 struct dll_notification_context* dll_context =
958 (struct dll_notification_context*) context;
959 struct backtrace_state *state = dll_context->state;
960 void *data = dll_context->data;
961 backtrace_error_callback error_callback = dll_context->data;
962 fileline fileline;
963 int found_sym;
964 int found_dwarf;
965 HMODULE module_handle;
967 if (reason != LDR_DLL_NOTIFICATION_REASON_LOADED)
968 return;
970 if (!GetModuleHandleExW ((GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
971 | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT),
972 (wchar_t*) notification_data->dll_base,
973 &module_handle))
974 return;
976 if (!GetModuleFileNameA ((HMODULE) module_handle, module_name, MAX_PATH - 1))
977 return;
979 descriptor = backtrace_open (module_name, error_callback, data, NULL);
981 if (descriptor < 0)
982 return;
984 coff_add (state, descriptor, error_callback, data, &fileline, &found_sym,
985 &found_dwarf, (uintptr_t) module_handle);
987 #endif /* defined(HAVE_WINDOWS_H) */
989 /* Initialize the backtrace data we need from an ELF executable. At
990 the ELF level, all we need to do is find the debug info
991 sections. */
994 backtrace_initialize (struct backtrace_state *state,
995 const char *filename ATTRIBUTE_UNUSED, int descriptor,
996 backtrace_error_callback error_callback,
997 void *data, fileline *fileline_fn)
999 int ret;
1000 int found_sym;
1001 int found_dwarf;
1002 fileline coff_fileline_fn;
1003 uintptr_t module_handle = 0;
1004 #ifdef HAVE_TLHELP32_H
1005 fileline module_fileline_fn;
1006 int module_found_sym;
1007 HANDLE snapshot;
1008 #endif
1010 #ifdef HAVE_WINDOWS_H
1011 HMODULE nt_dll_handle;
1013 module_handle = (uintptr_t) GetModuleHandle (NULL);
1014 #endif
1016 ret = coff_add (state, descriptor, error_callback, data,
1017 &coff_fileline_fn, &found_sym, &found_dwarf, module_handle);
1018 if (!ret)
1019 return 0;
1021 #ifdef HAVE_TLHELP32_H
1024 snapshot = CreateToolhelp32Snapshot (TH32CS_SNAPMODULE, 0);
1026 while (snapshot == INVALID_HANDLE_VALUE
1027 && GetLastError () == ERROR_BAD_LENGTH);
1029 if (snapshot != INVALID_HANDLE_VALUE)
1031 MODULEENTRY32 entry;
1032 BOOL ok;
1033 entry.dwSize = sizeof (MODULEENTRY32);
1035 for (ok = Module32First (snapshot, &entry); ok; ok = Module32Next (snapshot, &entry))
1037 if (strcmp (filename, entry.szExePath) == 0)
1038 continue;
1040 module_handle = (uintptr_t) entry.hModule;
1041 if (module_handle == 0)
1042 continue;
1044 descriptor = backtrace_open (entry.szExePath, error_callback, data,
1045 NULL);
1046 if (descriptor < 0)
1047 continue;
1049 coff_add (state, descriptor, error_callback, data,
1050 &module_fileline_fn, &module_found_sym, &found_dwarf,
1051 module_handle);
1052 if (module_found_sym)
1053 found_sym = 1;
1056 CloseHandle (snapshot);
1058 #endif
1060 #ifdef HAVE_WINDOWS_H
1061 nt_dll_handle = GetModuleHandleW (L"ntdll.dll");
1062 if (nt_dll_handle)
1064 LDR_REGISTER_FUNCTION register_func;
1065 const char register_name[] = "LdrRegisterDllNotification";
1066 register_func = (void*) GetProcAddress (nt_dll_handle,
1067 register_name);
1069 if (register_func)
1071 PVOID cookie;
1072 struct dll_notification_context *context
1073 = backtrace_alloc (state,
1074 sizeof (struct dll_notification_context),
1075 error_callback, data);
1077 if (context)
1079 context->state = state;
1080 context->data = data;
1081 context->error_callback = error_callback;
1083 register_func (0, &dll_notification, context, &cookie);
1087 #endif /* defined(HAVE_WINDOWS_H) */
1089 if (!state->threaded)
1091 if (found_sym)
1092 state->syminfo_fn = coff_syminfo;
1093 else if (state->syminfo_fn == NULL)
1094 state->syminfo_fn = coff_nosyms;
1096 else
1098 if (found_sym)
1099 backtrace_atomic_store_pointer (&state->syminfo_fn, coff_syminfo);
1100 else
1101 (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
1102 coff_nosyms);
1105 if (!state->threaded)
1107 if (state->fileline_fn == NULL || state->fileline_fn == coff_nodebug)
1108 *fileline_fn = coff_fileline_fn;
1110 else
1112 fileline current_fn;
1114 current_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
1115 if (current_fn == NULL || current_fn == coff_nodebug)
1116 *fileline_fn = coff_fileline_fn;
1119 return 1;