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
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
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. */
37 #include <sys/types.h>
39 #include "backtrace.h"
43 #ifndef WIN32_MEAN_AND_LEAN
44 #define WIN32_MEAN_AND_LEAN
54 /* Coff file header. */
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
;
66 /* Coff optional header. */
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
;
79 uint32_t base_of_data
;
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. */
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. */
113 unsigned char zeroes
[4];
114 unsigned char off
[4];
118 /* Coff symbol (external representation which is unaligned). */
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
;
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. */
138 /* Coff symbol, internal representation (aligned). */
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
] =
158 ".debug_str_offsets",
163 /* Information we gather for the sections we care about. */
165 struct debug_section_info
167 /* Section file offset. */
173 /* Information we keep for an coff symbol. */
177 /* The name of the symbol. */
179 /* The address of the symbol. */
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. */
195 /* A dummy callback function used when we can't find any debug info. */
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);
207 /* A dummy callback function used when we can't find a symbol
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. */
222 coff_read4 (const unsigned char *p
)
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. */
235 coff_read2 (const unsigned char *p
)
239 memcpy (&res
, p
, sizeof (res
));
243 /* Return the length (without the trailing 0) of a COFF short name. */
246 coff_short_name_len (const char *name
)
250 for (i
= 0; i
< 8; i
++)
256 /* Return true iff COFF short name CNAME is the same as NAME (a NUL-terminated
260 coff_short_name_eq (const char *name
, const char *cname
)
264 for (i
= 0; i
< 8; i
++)
266 if (name
[i
] != cname
[i
])
274 /* Return true iff NAME is the same as string at offset OFF. */
277 coff_long_name_eq (const char *name
, unsigned int off
,
278 struct backtrace_view
*str_view
)
280 if (off
>= str_view
->len
)
282 return strcmp (name
, (const char *)str_view
->data
+ off
) == 0;
285 /* Compare struct coff_symbol for qsort. */
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
)
295 else if (e1
->address
> e2
->address
)
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). */
306 coff_expand_symbol (b_coff_internal_symbol
*isym
,
307 const b_coff_external_symbol
*sym
,
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
)
317 if (sym
->name
.short_name
[0] != 0)
318 isym
->name
= sym
->name
.short_name
;
321 uint32_t off
= coff_read4 (sym
->name
.long_name
.off
);
323 if (off
>= strtab_size
)
325 isym
->name
= (const char *) strtab
+ off
;
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). */
335 coff_is_function_symbol (const b_coff_internal_symbol
*isym
)
337 return (isym
->type
>> N_TBSHFT
) == IMAGE_SYM_DTYPE_FUNCTION
341 /* Initialize the symbol table info for coff_syminfo. */
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
)
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
;
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;
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);
378 if (coff_is_function_symbol (&isym
))
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
,
392 if (coff_symbols
== NULL
)
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
,
401 if (coff_symstr
== NULL
)
403 backtrace_free (state
, coff_symbols
, coff_symbol_size
,
404 error_callback
, data
);
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
425 if (coff_is_function_symbol (&isym
))
430 if (asym
->name
.short_name
[0] != 0)
432 size_t len
= coff_short_name_len (isym
.name
);
434 memcpy (coff_str
, isym
.name
, len
);
443 /* Strip leading '_'. */
448 /* Symbol value is section relative, so we need to read the address
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
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
);
470 sdata
->symbols
= coff_symbols
;
471 sdata
->count
= coff_symbol_count
;
476 /* Add EDATA to the list in STATE. */
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
;
496 struct coff_syminfo_data
**pp
;
498 pp
= (struct coff_syminfo_data
**) (void *) &state
->syminfo_data
;
502 struct coff_syminfo_data
*p
;
504 p
= backtrace_atomic_load_pointer (pp
);
512 if (__sync_bool_compare_and_swap (pp
, NULL
, sdata
))
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
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
;
530 if (addr
< entry
->address
)
532 else if (addr
>= entry
[1].address
)
538 /* Return the symbol name and value for an ADDR. */
541 coff_syminfo (struct backtrace_state
*state
, uintptr_t addr
,
542 backtrace_syminfo_callback callback
,
543 backtrace_error_callback error_callback ATTRIBUTE_UNUSED
,
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
;
555 sym
= ((struct coff_symbol
*)
556 bsearch (&addr
, sdata
->symbols
, sdata
->count
,
557 sizeof (struct coff_symbol
), coff_symbol_search
));
564 struct coff_syminfo_data
**pp
;
566 pp
= (struct coff_syminfo_data
**) (void *) &state
->syminfo_data
;
569 sdata
= backtrace_atomic_load_pointer (pp
);
573 sym
= ((struct coff_symbol
*)
574 bsearch (&addr
, sdata
->symbols
, sdata
->count
,
575 sizeof (struct coff_symbol
), coff_symbol_search
));
584 callback (data
, addr
, NULL
, 0, 0);
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). */
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
;
600 b_coff_file_header fhdr
;
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
;
612 struct backtrace_view syms_view
;
616 unsigned int syms_num
;
618 struct debug_section_info sections
[DEBUG_MAX
];
621 struct backtrace_view debug_view
;
622 int debug_view_valid
;
624 uintptr_t image_base
;
625 uintptr_t base_address
= 0;
626 struct dwarf_sections dwarf_sections
;
631 sects_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
,
642 const unsigned char *vptr
= fhdr_view
.data
;
644 if (vptr
[0] == 'M' && vptr
[1] == 'Z')
645 fhdr_off
= coff_read4 (vptr
+ 0x3c);
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
))
660 const char *magic
= (const char *) fhdr_view
.data
;
661 magic_ok
= memcmp (magic
, "PE\0", 4) == 0;
664 memcpy (&fhdr
, fhdr_view
.data
+ 4, sizeof fhdr
);
668 memcpy (&fhdr
, fhdr_view
.data
, sizeof fhdr
);
669 /* TODO: test fhdr.machine for coff but non-PE platforms. */
672 backtrace_release_view (state
, &fhdr_view
, error_callback
, data
);
676 error_callback (data
, "executable file is not COFF", 0);
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
, §s_view
))
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
);
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
;
712 error_callback (data
, "bad magic in PE optional header", 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. */
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
))
742 str_size
= coff_read4 (syms_view
.data
+ syms_size
);
744 str_off
= syms_off
+ syms_size
;
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
))
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
;
766 if (s
->name
[0] == '/')
768 /* Extended section name. */
769 str_off
= atoi (s
->name
+ 1);
774 for (j
= 0; j
< (int) DEBUG_MAX
; ++j
)
776 const char *dbg_name
= debug_section_names
[j
];
780 match
= coff_long_name_eq (dbg_name
, str_off
, &str_view
);
782 match
= coff_short_name_eq (dbg_name
, s
->name
);
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
;
795 struct coff_syminfo_data
*sdata
;
797 sdata
= ((struct coff_syminfo_data
*)
798 backtrace_alloc (state
, sizeof *sdata
, error_callback
, data
));
802 if (!coff_initialize_syminfo (state
, image_base
, is_64
,
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
);
814 coff_add_syminfo_data (state
, sdata
);
817 backtrace_release_view (state
, §s_view
, error_callback
, data
);
818 sects_view_valid
= 0;
821 backtrace_release_view (state
, &syms_view
, error_callback
, data
);
825 /* Read all the debug sections in a single view, since they are
826 probably adjacent in the file. We never release this view. */
830 for (i
= 0; i
< (int) DEBUG_MAX
; ++i
)
834 if (sections
[i
].size
== 0)
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
)
842 if (min_offset
== 0 || max_offset
== 0)
844 if (!backtrace_close (descriptor
, error_callback
, data
))
846 *fileline_fn
= coff_nodebug
;
850 if (!backtrace_get_view (state
, descriptor
, min_offset
,
851 max_offset
- min_offset
,
852 error_callback
, data
, &debug_view
))
854 debug_view_valid
= 1;
856 /* We've read all we need from the executable. */
857 if (!backtrace_close (descriptor
, error_callback
, data
))
861 for (i
= 0; i
< (int) DEBUG_MAX
; ++i
)
863 size_t size
= sections
[i
].size
;
864 dwarf_sections
.size
[i
] = size
;
866 dwarf_sections
.data
[i
] = NULL
;
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
;
881 if (!backtrace_dwarf_add (state
, base_address
, &dwarf_sections
,
882 0, /* FIXME: is_bigendian */
884 error_callback
, data
, fileline_fn
,
885 NULL
/* returned fileline_entry */))
893 if (sects_view_valid
)
894 backtrace_release_view (state
, §s_view
, error_callback
, data
);
896 backtrace_release_view (state
, &str_view
, error_callback
, data
);
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
);
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
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
)
919 fileline coff_fileline_fn
;
921 ret
= coff_add (state
, descriptor
, error_callback
, data
,
922 &coff_fileline_fn
, &found_sym
, &found_dwarf
);
926 if (!state
->threaded
)
929 state
->syminfo_fn
= coff_syminfo
;
930 else if (state
->syminfo_fn
== NULL
)
931 state
->syminfo_fn
= coff_nosyms
;
936 backtrace_atomic_store_pointer (&state
->syminfo_fn
, coff_syminfo
);
938 (void) __sync_bool_compare_and_swap (&state
->syminfo_fn
, NULL
,
942 if (!state
->threaded
)
944 if (state
->fileline_fn
== NULL
|| state
->fileline_fn
== coff_nodebug
)
945 *fileline_fn
= coff_fileline_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
;