1 /* pecoff.c -- Get debug data from a PE/COFFF file for backtraces.
2 Copyright (C) 2015-2023 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"
42 /* Coff file header. */
46 uint16_t number_of_sections
;
47 uint32_t time_date_stamp
;
48 uint32_t pointer_to_symbol_table
;
49 uint32_t number_of_symbols
;
50 uint16_t size_of_optional_header
;
51 uint16_t characteristics
;
54 /* Coff optional header. */
58 uint8_t major_linker_version
;
59 uint8_t minor_linker_version
;
60 uint32_t size_of_code
;
61 uint32_t size_of_initialized_data
;
62 uint32_t size_of_uninitialized_data
;
63 uint32_t address_of_entry_point
;
64 uint32_t base_of_code
;
67 uint32_t base_of_data
;
74 } b_coff_optional_header
;
76 /* Values of magic in optional header. */
78 #define PE_MAGIC 0x10b /* PE32 executable. */
79 #define PEP_MAGIC 0x20b /* PE32+ executable (for 64bit targets). */
81 /* Coff section header. */
85 uint32_t virtual_size
;
86 uint32_t virtual_address
;
87 uint32_t size_of_raw_data
;
88 uint32_t pointer_to_raw_data
;
89 uint32_t pointer_to_relocations
;
90 uint32_t pointer_to_line_numbers
;
91 uint16_t number_of_relocations
;
92 uint16_t number_of_line_numbers
;
93 uint32_t characteristics
;
94 } b_coff_section_header
;
96 /* Coff symbol name. */
101 unsigned char zeroes
[4];
102 unsigned char off
[4];
106 /* Coff symbol (external representation which is unaligned). */
110 unsigned char value
[4];
111 unsigned char section_number
[2];
112 unsigned char type
[2];
113 unsigned char storage_class
;
114 unsigned char number_of_aux_symbols
;
115 } b_coff_external_symbol
;
119 #define N_TBSHFT 4 /* Shift for the derived type. */
120 #define IMAGE_SYM_DTYPE_FUNCTION 2 /* Function derived type. */
122 /* Size of a coff symbol. */
126 /* Coff symbol, internal representation (aligned). */
134 } b_coff_internal_symbol
;
136 /* Names of sections, indexed by enum dwarf_section in internal.h. */
138 static const char * const debug_section_names
[DEBUG_MAX
] =
146 ".debug_str_offsets",
151 /* Information we gather for the sections we care about. */
153 struct debug_section_info
155 /* Section file offset. */
161 /* Information we keep for an coff symbol. */
165 /* The name of the symbol. */
167 /* The address of the symbol. */
171 /* Information to pass to coff_syminfo. */
173 struct coff_syminfo_data
175 /* Symbols for the next module. */
176 struct coff_syminfo_data
*next
;
177 /* The COFF symbols, sorted by address. */
178 struct coff_symbol
*symbols
;
179 /* The number of symbols. */
183 /* A dummy callback function used when we can't find any debug info. */
186 coff_nodebug (struct backtrace_state
*state ATTRIBUTE_UNUSED
,
187 uintptr_t pc ATTRIBUTE_UNUSED
,
188 backtrace_full_callback callback ATTRIBUTE_UNUSED
,
189 backtrace_error_callback error_callback
, void *data
)
191 error_callback (data
, "no debug info in PE/COFF executable", -1);
195 /* A dummy callback function used when we can't find a symbol
199 coff_nosyms (struct backtrace_state
*state ATTRIBUTE_UNUSED
,
200 uintptr_t addr ATTRIBUTE_UNUSED
,
201 backtrace_syminfo_callback callback ATTRIBUTE_UNUSED
,
202 backtrace_error_callback error_callback
, void *data
)
204 error_callback (data
, "no symbol table in PE/COFF executable", -1);
207 /* Read a potentially unaligned 4 byte word at P, using native endianness. */
210 coff_read4 (const unsigned char *p
)
218 /* Read a potentially unaligned 2 byte word at P, using native endianness.
219 All 2 byte word in symbols are always aligned, but for coherency all
220 fields are declared as char arrays. */
223 coff_read2 (const unsigned char *p
)
227 memcpy (&res
, p
, sizeof (res
));
231 /* Return the length (without the trailing 0) of a COFF short name. */
234 coff_short_name_len (const char *name
)
238 for (i
= 0; i
< 8; i
++)
244 /* Return true iff COFF short name CNAME is the same as NAME (a NUL-terminated
248 coff_short_name_eq (const char *name
, const char *cname
)
252 for (i
= 0; i
< 8; i
++)
254 if (name
[i
] != cname
[i
])
262 /* Return true iff NAME is the same as string at offset OFF. */
265 coff_long_name_eq (const char *name
, unsigned int off
,
266 struct backtrace_view
*str_view
)
268 if (off
>= str_view
->len
)
270 return strcmp (name
, (const char *)str_view
->data
+ off
) == 0;
273 /* Compare struct coff_symbol for qsort. */
276 coff_symbol_compare (const void *v1
, const void *v2
)
278 const struct coff_symbol
*e1
= (const struct coff_symbol
*) v1
;
279 const struct coff_symbol
*e2
= (const struct coff_symbol
*) v2
;
281 if (e1
->address
< e2
->address
)
283 else if (e1
->address
> e2
->address
)
289 /* Convert SYM to internal (and aligned) format ISYM, using string table
290 from STRTAB and STRTAB_SIZE, and number of sections SECTS_NUM.
291 Return -1 in case of error (invalid section number or string index). */
294 coff_expand_symbol (b_coff_internal_symbol
*isym
,
295 const b_coff_external_symbol
*sym
,
297 const unsigned char *strtab
, size_t strtab_size
)
299 isym
->type
= coff_read2 (sym
->type
);
300 isym
->sec
= coff_read2 (sym
->section_number
);
301 isym
->sc
= sym
->storage_class
;
303 if (isym
->sec
> 0 && (uint16_t) isym
->sec
> sects_num
)
305 if (sym
->name
.short_name
[0] != 0)
306 isym
->name
= sym
->name
.short_name
;
309 uint32_t off
= coff_read4 (sym
->name
.long_name
.off
);
311 if (off
>= strtab_size
)
313 isym
->name
= (const char *) strtab
+ off
;
318 /* Return true iff SYM is a defined symbol for a function. Data symbols
319 aren't considered because they aren't easily identified (same type as
320 section names, presence of symbols defined by the linker script). */
323 coff_is_function_symbol (const b_coff_internal_symbol
*isym
)
325 return (isym
->type
>> N_TBSHFT
) == IMAGE_SYM_DTYPE_FUNCTION
329 /* Initialize the symbol table info for coff_syminfo. */
332 coff_initialize_syminfo (struct backtrace_state
*state
,
333 uintptr_t base_address
, int is_64
,
334 const b_coff_section_header
*sects
, size_t sects_num
,
335 const b_coff_external_symbol
*syms
, size_t syms_size
,
336 const unsigned char *strtab
, size_t strtab_size
,
337 backtrace_error_callback error_callback
,
338 void *data
, struct coff_syminfo_data
*sdata
)
342 size_t coff_symstr_len
;
343 size_t coff_symbol_count
;
344 size_t coff_symbol_size
;
345 struct coff_symbol
*coff_symbols
;
346 struct coff_symbol
*coff_sym
;
350 syms_count
= syms_size
/ SYM_SZ
;
352 /* We only care about function symbols. Count them. Also count size of
353 strings for in-symbol names. */
354 coff_symbol_count
= 0;
356 for (i
= 0; i
< syms_count
; ++i
)
358 const b_coff_external_symbol
*asym
= &syms
[i
];
359 b_coff_internal_symbol isym
;
361 if (coff_expand_symbol (&isym
, asym
, sects_num
, strtab
, strtab_size
) < 0)
363 error_callback (data
, "invalid section or offset in coff symbol", 0);
366 if (coff_is_function_symbol (&isym
))
369 if (asym
->name
.short_name
[0] != 0)
370 coff_symstr_len
+= coff_short_name_len (asym
->name
.short_name
) + 1;
373 i
+= asym
->number_of_aux_symbols
;
376 coff_symbol_size
= (coff_symbol_count
+ 1) * sizeof (struct coff_symbol
);
377 coff_symbols
= ((struct coff_symbol
*)
378 backtrace_alloc (state
, coff_symbol_size
, error_callback
,
380 if (coff_symbols
== NULL
)
383 /* Allocate memory for symbols strings. */
384 if (coff_symstr_len
> 0)
386 coff_symstr
= ((char *)
387 backtrace_alloc (state
, coff_symstr_len
, error_callback
,
389 if (coff_symstr
== NULL
)
391 backtrace_free (state
, coff_symbols
, coff_symbol_size
,
392 error_callback
, data
);
400 coff_sym
= coff_symbols
;
401 coff_str
= coff_symstr
;
402 for (i
= 0; i
< syms_count
; ++i
)
404 const b_coff_external_symbol
*asym
= &syms
[i
];
405 b_coff_internal_symbol isym
;
407 if (coff_expand_symbol (&isym
, asym
, sects_num
, strtab
, strtab_size
))
409 /* Should not fail, as it was already tested in the previous
413 if (coff_is_function_symbol (&isym
))
418 if (asym
->name
.short_name
[0] != 0)
420 size_t len
= coff_short_name_len (isym
.name
);
422 memcpy (coff_str
, isym
.name
, len
);
431 /* Strip leading '_'. */
436 /* Symbol value is section relative, so we need to read the address
438 secnum
= coff_read2 (asym
->section_number
);
440 coff_sym
->name
= name
;
441 coff_sym
->address
= (coff_read4 (asym
->value
)
442 + sects
[secnum
- 1].virtual_address
447 i
+= asym
->number_of_aux_symbols
;
450 /* End of symbols marker. */
451 coff_sym
->name
= NULL
;
452 coff_sym
->address
= -1;
454 backtrace_qsort (coff_symbols
, coff_symbol_count
,
455 sizeof (struct coff_symbol
), coff_symbol_compare
);
458 sdata
->symbols
= coff_symbols
;
459 sdata
->count
= coff_symbol_count
;
464 /* Add EDATA to the list in STATE. */
467 coff_add_syminfo_data (struct backtrace_state
*state
,
468 struct coff_syminfo_data
*sdata
)
470 if (!state
->threaded
)
472 struct coff_syminfo_data
**pp
;
474 for (pp
= (struct coff_syminfo_data
**) (void *) &state
->syminfo_data
;
484 struct coff_syminfo_data
**pp
;
486 pp
= (struct coff_syminfo_data
**) (void *) &state
->syminfo_data
;
490 struct coff_syminfo_data
*p
;
492 p
= backtrace_atomic_load_pointer (pp
);
500 if (__sync_bool_compare_and_swap (pp
, NULL
, sdata
))
506 /* Compare an ADDR against an elf_symbol for bsearch. We allocate one
507 extra entry in the array so that this can look safely at the next
511 coff_symbol_search (const void *vkey
, const void *ventry
)
513 const uintptr_t *key
= (const uintptr_t *) vkey
;
514 const struct coff_symbol
*entry
= (const struct coff_symbol
*) ventry
;
518 if (addr
< entry
->address
)
520 else if (addr
>= entry
[1].address
)
526 /* Return the symbol name and value for an ADDR. */
529 coff_syminfo (struct backtrace_state
*state
, uintptr_t addr
,
530 backtrace_syminfo_callback callback
,
531 backtrace_error_callback error_callback ATTRIBUTE_UNUSED
,
534 struct coff_syminfo_data
*sdata
;
535 struct coff_symbol
*sym
= NULL
;
537 if (!state
->threaded
)
539 for (sdata
= (struct coff_syminfo_data
*) state
->syminfo_data
;
543 sym
= ((struct coff_symbol
*)
544 bsearch (&addr
, sdata
->symbols
, sdata
->count
,
545 sizeof (struct coff_symbol
), coff_symbol_search
));
552 struct coff_syminfo_data
**pp
;
554 pp
= (struct coff_syminfo_data
**) (void *) &state
->syminfo_data
;
557 sdata
= backtrace_atomic_load_pointer (pp
);
561 sym
= ((struct coff_symbol
*)
562 bsearch (&addr
, sdata
->symbols
, sdata
->count
,
563 sizeof (struct coff_symbol
), coff_symbol_search
));
572 callback (data
, addr
, NULL
, 0, 0);
574 callback (data
, addr
, sym
->name
, sym
->address
, 0);
577 /* Add the backtrace data for one PE/COFF file. Returns 1 on success,
578 0 on failure (in both cases descriptor is closed). */
581 coff_add (struct backtrace_state
*state
, int descriptor
,
582 backtrace_error_callback error_callback
, void *data
,
583 fileline
*fileline_fn
, int *found_sym
, int *found_dwarf
)
585 struct backtrace_view fhdr_view
;
588 b_coff_file_header fhdr
;
590 size_t opt_sects_size
;
591 unsigned int sects_num
;
592 struct backtrace_view sects_view
;
593 int sects_view_valid
;
594 const b_coff_optional_header
*opt_hdr
;
595 const b_coff_section_header
*sects
;
596 struct backtrace_view str_view
;
600 struct backtrace_view syms_view
;
604 unsigned int syms_num
;
606 struct debug_section_info sections
[DEBUG_MAX
];
609 struct backtrace_view debug_view
;
610 int debug_view_valid
;
612 uintptr_t image_base
;
613 struct dwarf_sections dwarf_sections
;
618 sects_view_valid
= 0;
621 debug_view_valid
= 0;
623 /* Map the MS-DOS stub (if any) and extract file header offset. */
624 if (!backtrace_get_view (state
, descriptor
, 0, 0x40, error_callback
,
629 const unsigned char *vptr
= fhdr_view
.data
;
631 if (vptr
[0] == 'M' && vptr
[1] == 'Z')
632 fhdr_off
= coff_read4 (vptr
+ 0x3c);
637 backtrace_release_view (state
, &fhdr_view
, error_callback
, data
);
639 /* Map the coff file header. */
640 if (!backtrace_get_view (state
, descriptor
, fhdr_off
,
641 sizeof (b_coff_file_header
) + 4,
642 error_callback
, data
, &fhdr_view
))
647 const char *magic
= (const char *) fhdr_view
.data
;
648 magic_ok
= memcmp (magic
, "PE\0", 4) == 0;
651 memcpy (&fhdr
, fhdr_view
.data
+ 4, sizeof fhdr
);
655 memcpy (&fhdr
, fhdr_view
.data
, sizeof fhdr
);
656 /* TODO: test fhdr.machine for coff but non-PE platforms. */
659 backtrace_release_view (state
, &fhdr_view
, error_callback
, data
);
663 error_callback (data
, "executable file is not COFF", 0);
667 sects_num
= fhdr
.number_of_sections
;
668 syms_num
= fhdr
.number_of_symbols
;
670 opt_sects_off
= fhdr_off
+ sizeof (fhdr
);
671 opt_sects_size
= (fhdr
.size_of_optional_header
672 + sects_num
* sizeof (b_coff_section_header
));
674 /* To translate PC to file/line when using DWARF, we need to find
675 the .debug_info and .debug_line sections. */
677 /* Read the optional header and the section headers. */
679 if (!backtrace_get_view (state
, descriptor
, opt_sects_off
, opt_sects_size
,
680 error_callback
, data
, §s_view
))
682 sects_view_valid
= 1;
683 opt_hdr
= (const b_coff_optional_header
*) sects_view
.data
;
684 sects
= (const b_coff_section_header
*)
685 (sects_view
.data
+ fhdr
.size_of_optional_header
);
688 if (fhdr
.size_of_optional_header
> sizeof (*opt_hdr
))
690 if (opt_hdr
->magic
== PE_MAGIC
)
691 image_base
= opt_hdr
->u
.pe
.image_base
;
692 else if (opt_hdr
->magic
== PEP_MAGIC
)
694 image_base
= opt_hdr
->u
.pep
.image_base
;
699 error_callback (data
, "bad magic in PE optional header", 0);
706 /* Read the symbol table and the string table. */
708 if (fhdr
.pointer_to_symbol_table
== 0)
710 /* No symbol table, no string table. */
718 /* Symbol table is followed by the string table. The string table
719 starts with its length (on 4 bytes).
720 Map the symbol table and the length of the string table. */
721 syms_off
= fhdr
.pointer_to_symbol_table
;
722 syms_size
= syms_num
* SYM_SZ
;
724 if (!backtrace_get_view (state
, descriptor
, syms_off
, syms_size
+ 4,
725 error_callback
, data
, &syms_view
))
729 str_size
= coff_read4 (syms_view
.data
+ syms_size
);
731 str_off
= syms_off
+ syms_size
;
735 /* Map string table (including the length word). */
737 if (!backtrace_get_view (state
, descriptor
, str_off
, str_size
,
738 error_callback
, data
, &str_view
))
744 memset (sections
, 0, sizeof sections
);
746 /* Look for the symbol table. */
747 for (i
= 0; i
< sects_num
; ++i
)
749 const b_coff_section_header
*s
= sects
+ i
;
750 unsigned int str_off
;
753 if (s
->name
[0] == '/')
755 /* Extended section name. */
756 str_off
= atoi (s
->name
+ 1);
761 for (j
= 0; j
< (int) DEBUG_MAX
; ++j
)
763 const char *dbg_name
= debug_section_names
[j
];
767 match
= coff_long_name_eq (dbg_name
, str_off
, &str_view
);
769 match
= coff_short_name_eq (dbg_name
, s
->name
);
772 sections
[j
].offset
= s
->pointer_to_raw_data
;
773 sections
[j
].size
= s
->virtual_size
<= s
->size_of_raw_data
?
774 s
->virtual_size
: s
->size_of_raw_data
;
782 struct coff_syminfo_data
*sdata
;
784 sdata
= ((struct coff_syminfo_data
*)
785 backtrace_alloc (state
, sizeof *sdata
, error_callback
, data
));
789 if (!coff_initialize_syminfo (state
, image_base
, is_64
,
791 syms_view
.data
, syms_size
,
792 str_view
.data
, str_size
,
793 error_callback
, data
, sdata
))
795 backtrace_free (state
, sdata
, sizeof *sdata
, error_callback
, data
);
801 coff_add_syminfo_data (state
, sdata
);
804 backtrace_release_view (state
, §s_view
, error_callback
, data
);
805 sects_view_valid
= 0;
808 backtrace_release_view (state
, &syms_view
, error_callback
, data
);
812 /* Read all the debug sections in a single view, since they are
813 probably adjacent in the file. We never release this view. */
817 for (i
= 0; i
< (int) DEBUG_MAX
; ++i
)
821 if (sections
[i
].size
== 0)
823 if (min_offset
== 0 || sections
[i
].offset
< min_offset
)
824 min_offset
= sections
[i
].offset
;
825 end
= sections
[i
].offset
+ sections
[i
].size
;
826 if (end
> max_offset
)
829 if (min_offset
== 0 || max_offset
== 0)
831 if (!backtrace_close (descriptor
, error_callback
, data
))
833 *fileline_fn
= coff_nodebug
;
837 if (!backtrace_get_view (state
, descriptor
, min_offset
,
838 max_offset
- min_offset
,
839 error_callback
, data
, &debug_view
))
841 debug_view_valid
= 1;
843 /* We've read all we need from the executable. */
844 if (!backtrace_close (descriptor
, error_callback
, data
))
848 for (i
= 0; i
< (int) DEBUG_MAX
; ++i
)
850 size_t size
= sections
[i
].size
;
851 dwarf_sections
.size
[i
] = size
;
853 dwarf_sections
.data
[i
] = NULL
;
855 dwarf_sections
.data
[i
] = ((const unsigned char *) debug_view
.data
856 + (sections
[i
].offset
- min_offset
));
859 if (!backtrace_dwarf_add (state
, /* base_address */ 0, &dwarf_sections
,
860 0, /* FIXME: is_bigendian */
862 error_callback
, data
, fileline_fn
,
863 NULL
/* returned fileline_entry */))
871 if (sects_view_valid
)
872 backtrace_release_view (state
, §s_view
, error_callback
, data
);
874 backtrace_release_view (state
, &str_view
, error_callback
, data
);
876 backtrace_release_view (state
, &syms_view
, error_callback
, data
);
877 if (debug_view_valid
)
878 backtrace_release_view (state
, &debug_view
, error_callback
, data
);
879 if (descriptor
!= -1)
880 backtrace_close (descriptor
, error_callback
, data
);
884 /* Initialize the backtrace data we need from an ELF executable. At
885 the ELF level, all we need to do is find the debug info
889 backtrace_initialize (struct backtrace_state
*state
,
890 const char *filename ATTRIBUTE_UNUSED
, int descriptor
,
891 backtrace_error_callback error_callback
,
892 void *data
, fileline
*fileline_fn
)
897 fileline coff_fileline_fn
;
899 ret
= coff_add (state
, descriptor
, error_callback
, data
,
900 &coff_fileline_fn
, &found_sym
, &found_dwarf
);
904 if (!state
->threaded
)
907 state
->syminfo_fn
= coff_syminfo
;
908 else if (state
->syminfo_fn
== NULL
)
909 state
->syminfo_fn
= coff_nosyms
;
914 backtrace_atomic_store_pointer (&state
->syminfo_fn
, coff_syminfo
);
916 (void) __sync_bool_compare_and_swap (&state
->syminfo_fn
, NULL
,
920 if (!state
->threaded
)
922 if (state
->fileline_fn
== NULL
|| state
->fileline_fn
== coff_nodebug
)
923 *fileline_fn
= coff_fileline_fn
;
929 current_fn
= backtrace_atomic_load_pointer (&state
->fileline_fn
);
930 if (current_fn
== NULL
|| current_fn
== coff_nodebug
)
931 *fileline_fn
= coff_fileline_fn
;