The FreeRADIUS server $Id: f3670dba8951ca10eb4948feb3dc3db9423a334f $
Loading...
Searching...
No Matches
pecoff.c
Go to the documentation of this file.
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.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are
7met:
8
9 (1) Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
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.
16
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.
20
21THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31POSSIBILITY OF SUCH DAMAGE. */
32
33#include "config.h"
34
35#include <stdlib.h>
36#include <string.h>
37#include <sys/types.h>
38
39#include "backtrace.h"
40#include "internal.h"
41
42#ifdef HAVE_WINDOWS_H
43#ifndef WIN32_LEAN_AND_MEAN
44#define WIN32_LEAN_AND_MEAN
45#endif
46
47#ifndef NOMINMAX
48#define NOMINMAX
49#endif
50
51#include <windows.h>
52
53#ifdef HAVE_TLHELP32_H
54#include <tlhelp32.h>
55
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
65#if defined(_ARM_)
66#define NTAPI
67#else
68#define NTAPI __stdcall
69#endif
70
71/* This is a simplified (but binary compatible) version of what Microsoft
72 defines in their documentation. */
73struct dll_notification_data
74{
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;
81};
82
83#define LDR_DLL_NOTIFICATION_REASON_LOADED 1
84
85typedef LONG NTSTATUS;
86typedef VOID (CALLBACK *LDR_DLL_NOTIFICATION)(ULONG,
87 struct dll_notification_data*,
88 PVOID);
89typedef NTSTATUS (NTAPI *LDR_REGISTER_FUNCTION)(ULONG,
90 LDR_DLL_NOTIFICATION, PVOID,
91 PVOID*);
92#endif
93
94/* Coff file header. */
95
105
106/* Coff optional header. */
107
127
128/* Values of magic in optional header. */
129
130#define PE_MAGIC 0x10b /* PE32 executable. */
131#define PEP_MAGIC 0x20b /* PE32+ executable (for 64bit targets). */
132
133/* Coff section header. */
134
147
148/* Coff symbol name. */
149
150typedef union {
151 char short_name[8];
152 struct {
153 unsigned char zeroes[4];
154 unsigned char off[4];
155 } long_name;
157
158/* Coff symbol (external representation which is unaligned). */
159
160typedef struct {
162 unsigned char value[4];
163 unsigned char section_number[2];
164 unsigned char type[2];
165 unsigned char storage_class;
168
169/* Symbol types. */
170
171#define N_TBSHFT 4 /* Shift for the derived type. */
172#define IMAGE_SYM_DTYPE_FUNCTION 2 /* Function derived type. */
173
174/* Size of a coff symbol. */
175
176#define SYM_SZ 18
177
178/* Coff symbol, internal representation (aligned). */
179
187
188/* Names of sections, indexed by enum dwarf_section in internal.h. */
189
190static const char * const debug_section_names[DEBUG_MAX] =
191{
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"
201};
202
203/* Information we gather for the sections we care about. */
204
206{
207 /* Section file offset. */
209 /* Section size. */
210 size_t size;
211};
212
213/* Information we keep for an coff symbol. */
214
216{
217 /* The name of the symbol. */
218 const char *name;
219 /* The address of the symbol. */
220 uintptr_t address;
221};
222
223/* Information to pass to coff_syminfo. */
224
226{
227 /* Symbols for the next module. */
229 /* The COFF symbols, sorted by address. */
231 /* The number of symbols. */
232 size_t count;
233};
234
235/* A dummy callback function used when we can't find any debug info. */
236
237static int
239 uintptr_t pc ATTRIBUTE_UNUSED,
242{
243 error_callback (data, "no debug info in PE/COFF executable (make sure to compile with -g)", -1);
244 return 0;
245}
246
247/* A dummy callback function used when we can't find a symbol
248 table. */
249
250static void
252 uintptr_t addr ATTRIBUTE_UNUSED,
255{
256 error_callback (data, "no symbol table in PE/COFF executable", -1);
257}
258
259/* Read a potentially unaligned 4 byte word at P, using native endianness. */
260
261static uint32_t
262coff_read4 (const unsigned char *p)
263{
264 uint32_t res;
265
266 memcpy (&res, p, 4);
267 return res;
268}
269
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. */
273
274static uint16_t
275coff_read2 (const unsigned char *p)
276{
277 uint16_t res;
278
279 memcpy (&res, p, sizeof (res));
280 return res;
281}
282
283/* Return the length (without the trailing 0) of a COFF short name. */
284
285static size_t
287{
288 int i;
289
290 for (i = 0; i < 8; i++)
291 if (name[i] == 0)
292 return i;
293 return 8;
294}
295
296/* Return true iff COFF short name CNAME is the same as NAME (a NUL-terminated
297 string). */
298
299static int
300coff_short_name_eq (const char *name, const char *cname)
301{
302 int i;
303
304 for (i = 0; i < 8; i++)
305 {
306 if (name[i] != cname[i])
307 return 0;
308 if (name[i] == 0)
309 return 1;
310 }
311 return name[8] == 0;
312}
313
314/* Return true iff NAME is the same as string at offset OFF. */
315
316static int
317coff_long_name_eq (const char *name, unsigned int off,
318 struct backtrace_view *str_view)
319{
320 if (off >= str_view->len)
321 return 0;
322 return strcmp (name, (const char *)str_view->data + off) == 0;
323}
324
325/* Compare struct coff_symbol for qsort. */
326
327static int
328coff_symbol_compare (const void *v1, const void *v2)
329{
330 const struct coff_symbol *e1 = (const struct coff_symbol *) v1;
331 const struct coff_symbol *e2 = (const struct coff_symbol *) v2;
332
333 if (e1->address < e2->address)
334 return -1;
335 else if (e1->address > e2->address)
336 return 1;
337 else
338 return 0;
339}
340
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). */
344
345static int
347 const b_coff_external_symbol *sym,
348 uint16_t sects_num,
349 const unsigned char *strtab, size_t strtab_size)
350{
351 isym->type = coff_read2 (sym->type);
352 isym->sec = coff_read2 (sym->section_number);
353 isym->sc = sym->storage_class;
354
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
360 {
361 uint32_t off = coff_read4 (sym->name.long_name.off);
362
363 if (off >= strtab_size)
364 return -1;
365 isym->name = (const char *) strtab + off;
366 }
367 return 0;
368}
369
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). */
373
374static int
376{
377 return (isym->type >> N_TBSHFT) == IMAGE_SYM_DTYPE_FUNCTION
378 && isym->sec > 0;
379}
380
381/* Initialize the symbol table info for coff_syminfo. */
382
383static int
385 struct libbacktrace_base_address base_address,
386 int is_64, const b_coff_section_header *sects,
387 size_t sects_num, const b_coff_external_symbol *syms,
388 size_t syms_size, const unsigned char *strtab,
389 size_t strtab_size,
391 void *data, struct coff_syminfo_data *sdata)
392{
393 size_t syms_count;
394 char *coff_symstr;
395 size_t coff_symstr_len;
396 size_t coff_symbol_count;
397 size_t coff_symbol_size;
398 struct coff_symbol *coff_symbols;
399 struct coff_symbol *coff_sym;
400 char *coff_str;
401 size_t i;
402
403 syms_count = syms_size / SYM_SZ;
404
405 /* We only care about function symbols. Count them. Also count size of
406 strings for in-symbol names. */
407 coff_symbol_count = 0;
408 coff_symstr_len = 0;
409 for (i = 0; i < syms_count; ++i)
410 {
411 const b_coff_external_symbol *asym = &syms[i];
413
414 if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size) < 0)
415 {
416 error_callback (data, "invalid section or offset in coff symbol", 0);
417 return 0;
418 }
419 if (coff_is_function_symbol (&isym))
420 {
421 ++coff_symbol_count;
422 if (asym->name.short_name[0] != 0)
423 coff_symstr_len += coff_short_name_len (asym->name.short_name) + 1;
424 }
425
426 i += asym->number_of_aux_symbols;
427 }
428
429 coff_symbol_size = (coff_symbol_count + 1) * sizeof (struct coff_symbol);
430 coff_symbols = ((struct coff_symbol *)
431 backtrace_alloc (state, coff_symbol_size, error_callback,
432 data));
433 if (coff_symbols == NULL)
434 return 0;
435
436 /* Allocate memory for symbols strings. */
437 if (coff_symstr_len > 0)
438 {
439 coff_symstr = ((char *)
440 backtrace_alloc (state, coff_symstr_len, error_callback,
441 data));
442 if (coff_symstr == NULL)
443 {
444 backtrace_free (state, coff_symbols, coff_symbol_size,
446 return 0;
447 }
448 }
449 else
450 coff_symstr = NULL;
451
452 /* Copy symbols. */
453 coff_sym = coff_symbols;
454 coff_str = coff_symstr;
455 for (i = 0; i < syms_count; ++i)
456 {
457 const b_coff_external_symbol *asym = &syms[i];
459
460 if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size))
461 {
462 /* Should not fail, as it was already tested in the previous
463 loop. */
464 abort ();
465 }
466 if (coff_is_function_symbol (&isym))
467 {
468 const char *name;
469 int16_t secnum;
470
471 if (asym->name.short_name[0] != 0)
472 {
473 size_t len = coff_short_name_len (isym.name);
474 name = coff_str;
475 memcpy (coff_str, isym.name, len);
476 coff_str[len] = 0;
477 coff_str += len + 1;
478 }
479 else
480 name = isym.name;
481
482 if (!is_64)
483 {
484 /* Strip leading '_'. */
485 if (name[0] == '_')
486 name++;
487 }
488
489 /* Symbol value is section relative, so we need to read the address
490 of its section. */
491 secnum = coff_read2 (asym->section_number);
492
493 coff_sym->name = name;
494 coff_sym->address =
496 + sects[secnum - 1].virtual_address),
497 base_address);
498 coff_sym++;
499 }
500
501 i += asym->number_of_aux_symbols;
502 }
503
504 /* End of symbols marker. */
505 coff_sym->name = NULL;
506 coff_sym->address = -1;
507
508 backtrace_qsort (coff_symbols, coff_symbol_count,
509 sizeof (struct coff_symbol), coff_symbol_compare);
510
511 sdata->next = NULL;
512 sdata->symbols = coff_symbols;
513 sdata->count = coff_symbol_count;
514
515 return 1;
516}
517
518/* Add EDATA to the list in STATE. */
519
520static void
522 struct coff_syminfo_data *sdata)
523{
524 if (!state->threaded)
525 {
526 struct coff_syminfo_data **pp;
527
528 for (pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
529 *pp != NULL;
530 pp = &(*pp)->next)
531 ;
532 *pp = sdata;
533 }
534 else
535 {
536 while (1)
537 {
538 struct coff_syminfo_data **pp;
539
540 pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
541
542 while (1)
543 {
544 struct coff_syminfo_data *p;
545
547
548 if (p == NULL)
549 break;
550
551 pp = &p->next;
552 }
553
554 if (__sync_bool_compare_and_swap (pp, NULL, sdata))
555 break;
556 }
557 }
558}
559
560/* Compare an ADDR against an elf_symbol for bsearch. We allocate one
561 extra entry in the array so that this can look safely at the next
562 entry. */
563
564static int
565coff_symbol_search (const void *vkey, const void *ventry)
566{
567 const uintptr_t *key = (const uintptr_t *) vkey;
568 const struct coff_symbol *entry = (const struct coff_symbol *) ventry;
569 uintptr_t addr;
570
571 addr = *key;
572 if (addr < entry->address)
573 return -1;
574 else if (addr >= entry[1].address)
575 return 1;
576 else
577 return 0;
578}
579
580/* Return the symbol name and value for an ADDR. */
581
582static void
583coff_syminfo (struct backtrace_state *state, uintptr_t addr,
586 void *data)
587{
588 struct coff_syminfo_data *sdata;
589 struct coff_symbol *sym = NULL;
590
591 if (!state->threaded)
592 {
593 for (sdata = (struct coff_syminfo_data *) state->syminfo_data;
594 sdata != NULL;
595 sdata = sdata->next)
596 {
597 sym = ((struct coff_symbol *)
598 bsearch (&addr, sdata->symbols, sdata->count,
599 sizeof (struct coff_symbol), coff_symbol_search));
600 if (sym != NULL)
601 break;
602 }
603 }
604 else
605 {
606 struct coff_syminfo_data **pp;
607
608 pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
609 while (1)
610 {
612 if (sdata == NULL)
613 break;
614
615 sym = ((struct coff_symbol *)
616 bsearch (&addr, sdata->symbols, sdata->count,
617 sizeof (struct coff_symbol), coff_symbol_search));
618 if (sym != NULL)
619 break;
620
621 pp = &sdata->next;
622 }
623 }
624
625 if (sym == NULL)
626 callback (data, addr, NULL, 0, 0);
627 else
628 callback (data, addr, sym->name, sym->address, 0);
629}
630
631/* Add the backtrace data for one PE/COFF file. Returns 1 on success,
632 0 on failure (in both cases descriptor is closed). */
633
634static int
635coff_add (struct backtrace_state *state, int descriptor,
637 fileline *fileline_fn, int *found_sym, int *found_dwarf,
638 uintptr_t module_handle ATTRIBUTE_UNUSED)
639{
640 struct backtrace_view fhdr_view;
641 off_t fhdr_off;
642 int magic_ok;
644 off_t opt_sects_off;
645 size_t opt_sects_size;
646 unsigned int sects_num;
647 struct backtrace_view sects_view;
648 int sects_view_valid;
649 const b_coff_optional_header *opt_hdr;
650 const b_coff_section_header *sects;
651 struct backtrace_view str_view;
652 int str_view_valid;
653 size_t str_size;
654 off_t str_off;
655 struct backtrace_view syms_view;
656 off_t syms_off;
657 size_t syms_size;
658 int syms_view_valid;
659 unsigned int syms_num;
660 unsigned int i;
661 struct debug_section_info sections[DEBUG_MAX];
662 off_t min_offset;
663 off_t max_offset;
664 struct backtrace_view debug_view;
665 int debug_view_valid;
666 int is_64;
667 struct libbacktrace_base_address image_base;
668 struct libbacktrace_base_address base_address;
670
671 *found_sym = 0;
672 *found_dwarf = 0;
673
674 sects_view_valid = 0;
675 syms_view_valid = 0;
676 str_view_valid = 0;
677 debug_view_valid = 0;
678
679 /* Map the MS-DOS stub (if any) and extract file header offset. */
680 if (!backtrace_get_view (state, descriptor, 0, 0x40, error_callback,
681 data, &fhdr_view))
682 goto fail;
683
684 {
685 const unsigned char *vptr = fhdr_view.data;
686
687 if (vptr[0] == 'M' && vptr[1] == 'Z')
688 fhdr_off = coff_read4 (vptr + 0x3c);
689 else
690 fhdr_off = 0;
691 }
692
694
695 /* Map the coff file header. */
696 if (!backtrace_get_view (state, descriptor, fhdr_off,
697 sizeof (b_coff_file_header) + 4,
698 error_callback, data, &fhdr_view))
699 goto fail;
700
701 if (fhdr_off != 0)
702 {
703 const char *magic = (const char *) fhdr_view.data;
704 magic_ok = memcmp (magic, "PE\0", 4) == 0;
705 fhdr_off += 4;
706
707 memcpy (&fhdr, (const unsigned char *) fhdr_view.data + 4, sizeof fhdr);
708 }
709 else
710 {
711 memcpy (&fhdr, fhdr_view.data, sizeof fhdr);
712 /* TODO: test fhdr.machine for coff but non-PE platforms. */
713 magic_ok = 0;
714 }
716
717 if (!magic_ok)
718 {
719 error_callback (data, "executable file is not COFF", 0);
720 goto fail;
721 }
722
723 sects_num = fhdr.number_of_sections;
724 syms_num = fhdr.number_of_symbols;
725
726 opt_sects_off = fhdr_off + sizeof (fhdr);
727 opt_sects_size = (fhdr.size_of_optional_header
728 + sects_num * sizeof (b_coff_section_header));
729
730 /* To translate PC to file/line when using DWARF, we need to find
731 the .debug_info and .debug_line sections. */
732
733 /* Read the optional header and the section headers. */
734
735 if (!backtrace_get_view (state, descriptor, opt_sects_off, opt_sects_size,
736 error_callback, data, &sects_view))
737 goto fail;
738 sects_view_valid = 1;
739 opt_hdr = (const b_coff_optional_header *) sects_view.data;
740 sects = (const b_coff_section_header *)
741 ((const unsigned char *) sects_view.data + fhdr.size_of_optional_header);
742
743 is_64 = 0;
744 memset (&image_base, 0, sizeof image_base);
745 if (fhdr.size_of_optional_header > sizeof (*opt_hdr))
746 {
747 if (opt_hdr->magic == PE_MAGIC)
748 image_base.m = opt_hdr->u.pe.image_base;
749 else if (opt_hdr->magic == PEP_MAGIC)
750 {
751 image_base.m = opt_hdr->u.pep.image_base;
752 is_64 = 1;
753 }
754 else
755 {
756 error_callback (data, "bad magic in PE optional header", 0);
757 goto fail;
758 }
759 }
760
761 /* Read the symbol table and the string table. */
762
763 if (fhdr.pointer_to_symbol_table == 0)
764 {
765 /* No symbol table, no string table. */
766 str_off = 0;
767 str_size = 0;
768 syms_num = 0;
769 syms_size = 0;
770 }
771 else
772 {
773 /* Symbol table is followed by the string table. The string table
774 starts with its length (on 4 bytes).
775 Map the symbol table and the length of the string table. */
776 syms_off = fhdr.pointer_to_symbol_table;
777 syms_size = syms_num * SYM_SZ;
778
779 if (!backtrace_get_view (state, descriptor, syms_off, syms_size + 4,
780 error_callback, data, &syms_view))
781 goto fail;
782 syms_view_valid = 1;
783
784 str_size = coff_read4 ((const unsigned char *) syms_view.data
785 + syms_size);
786
787 str_off = syms_off + syms_size;
788
789 if (str_size > 4)
790 {
791 /* Map string table (including the length word). */
792
793 if (!backtrace_get_view (state, descriptor, str_off, str_size,
794 error_callback, data, &str_view))
795 goto fail;
796 str_view_valid = 1;
797 }
798 }
799
800 memset (sections, 0, sizeof sections);
801
802 /* Look for the symbol table. */
803 for (i = 0; i < sects_num; ++i)
804 {
805 const b_coff_section_header *s = sects + i;
806 unsigned int str_off;
807 int j;
808
809 if (s->name[0] == '/')
810 {
811 /* Extended section name. */
812 str_off = atoi (s->name + 1);
813 }
814 else
815 str_off = 0;
816
817 for (j = 0; j < (int) DEBUG_MAX; ++j)
818 {
819 const char *dbg_name = debug_section_names[j];
820 int match;
821
822 if (str_off != 0)
823 match = coff_long_name_eq (dbg_name, str_off, &str_view);
824 else
825 match = coff_short_name_eq (dbg_name, s->name);
826 if (match)
827 {
828 sections[j].offset = s->pointer_to_raw_data;
829 sections[j].size = s->virtual_size <= s->size_of_raw_data ?
831 break;
832 }
833 }
834 }
835
836 if (syms_num != 0)
837 {
838 struct coff_syminfo_data *sdata;
839
840 sdata = ((struct coff_syminfo_data *)
842 if (sdata == NULL)
843 goto fail;
844
845 if (!coff_initialize_syminfo (state, image_base, is_64,
846 sects, sects_num,
847 syms_view.data, syms_size,
848 str_view.data, str_size,
850 {
852 goto fail;
853 }
854
855 *found_sym = 1;
856
858 }
859
861 sects_view_valid = 0;
862 if (syms_view_valid)
863 {
865 syms_view_valid = 0;
866 }
867
868 /* Read all the debug sections in a single view, since they are
869 probably adjacent in the file. We never release this view. */
870
871 min_offset = 0;
872 max_offset = 0;
873 for (i = 0; i < (int) DEBUG_MAX; ++i)
874 {
875 off_t end;
876
877 if (sections[i].size == 0)
878 continue;
879 if (min_offset == 0 || sections[i].offset < min_offset)
880 min_offset = sections[i].offset;
881 end = sections[i].offset + sections[i].size;
882 if (end > max_offset)
883 max_offset = end;
884 }
885 if (min_offset == 0 || max_offset == 0)
886 {
887 if (!backtrace_close (descriptor, error_callback, data))
888 goto fail;
889 *fileline_fn = coff_nodebug;
890 return 1;
891 }
892
893 if (!backtrace_get_view (state, descriptor, min_offset,
894 max_offset - min_offset,
895 error_callback, data, &debug_view))
896 goto fail;
897 debug_view_valid = 1;
898
899 /* We've read all we need from the executable. */
900 if (!backtrace_close (descriptor, error_callback, data))
901 goto fail;
902 descriptor = -1;
903
904 for (i = 0; i < (int) DEBUG_MAX; ++i)
905 {
906 size_t size = sections[i].size;
907 dwarf_sections.size[i] = size;
908 if (size == 0)
909 dwarf_sections.data[i] = NULL;
910 else
911 dwarf_sections.data[i] = ((const unsigned char *) debug_view.data
912 + (sections[i].offset - min_offset));
913 }
914
915 memset (&base_address, 0, sizeof base_address);
916#ifdef HAVE_WINDOWS_H
917 base_address.m = module_handle - image_base.m;
918#endif
919
920 if (!backtrace_dwarf_add (state, base_address, &dwarf_sections,
921 0, /* FIXME: is_bigendian */
922 NULL, /* altlink */
923 error_callback, data, fileline_fn,
924 NULL /* returned fileline_entry */))
925 goto fail;
926
927 *found_dwarf = 1;
928
929 return 1;
930
931 fail:
932 if (sects_view_valid)
934 if (str_view_valid)
936 if (syms_view_valid)
938 if (debug_view_valid)
940 if (descriptor != -1)
941 backtrace_close (descriptor, error_callback, data);
942 return 0;
943}
944
945#ifdef HAVE_WINDOWS_H
946struct dll_notification_context
947{
948 struct backtrace_state *state;
950 void *data;
951};
952
953static VOID CALLBACK
954dll_notification (ULONG reason,
955 struct dll_notification_data *notification_data,
956 PVOID context)
957{
958 char module_name[MAX_PATH];
959 int descriptor;
960 struct dll_notification_context* dll_context =
961 (struct dll_notification_context*) context;
962 struct backtrace_state *state = dll_context->state;
963 void *data = dll_context->data;
964 backtrace_error_callback error_callback = dll_context->data;
966 int found_sym;
967 int found_dwarf;
968 HMODULE module_handle;
969
970 if (reason != LDR_DLL_NOTIFICATION_REASON_LOADED)
971 return;
972
973 if (!GetModuleHandleExW ((GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
974 | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT),
975 (wchar_t*) notification_data->dll_base,
976 &module_handle))
977 return;
978
979 if (!GetModuleFileNameA ((HMODULE) module_handle, module_name, MAX_PATH - 1))
980 return;
981
982 descriptor = backtrace_open (module_name, error_callback, data, NULL);
983
984 if (descriptor < 0)
985 return;
986
987 coff_add (state, descriptor, error_callback, data, &fileline, &found_sym,
988 &found_dwarf, (uintptr_t) module_handle);
989}
990#endif /* defined(HAVE_WINDOWS_H) */
991
992/* Initialize the backtrace data we need from an ELF executable. At
993 the ELF level, all we need to do is find the debug info
994 sections. */
995
996int
998 const char *filename ATTRIBUTE_UNUSED, int descriptor,
1000 void *data, fileline *fileline_fn)
1001{
1002 int ret;
1003 int found_sym;
1004 int found_dwarf;
1005 fileline coff_fileline_fn;
1006 uintptr_t module_handle = 0;
1007#ifdef HAVE_TLHELP32_H
1008 fileline module_fileline_fn;
1009 int module_found_sym;
1010 HANDLE snapshot;
1011#endif
1012
1013#ifdef HAVE_WINDOWS_H
1014 HMODULE nt_dll_handle;
1015
1016 module_handle = (uintptr_t) GetModuleHandle (NULL);
1017#endif
1018
1019 ret = coff_add (state, descriptor, error_callback, data,
1020 &coff_fileline_fn, &found_sym, &found_dwarf, module_handle);
1021 if (!ret)
1022 return 0;
1023
1024#ifdef HAVE_TLHELP32_H
1025 do
1026 {
1027 snapshot = CreateToolhelp32Snapshot (TH32CS_SNAPMODULE, 0);
1028 }
1029 while (snapshot == INVALID_HANDLE_VALUE
1030 && GetLastError () == ERROR_BAD_LENGTH);
1031
1032 if (snapshot != INVALID_HANDLE_VALUE)
1033 {
1034 MODULEENTRY32 entry;
1035 BOOL ok;
1036 entry.dwSize = sizeof (MODULEENTRY32);
1037
1038 for (ok = Module32First (snapshot, &entry); ok; ok = Module32Next (snapshot, &entry))
1039 {
1040 if (strcmp (filename, entry.szExePath) == 0)
1041 continue;
1042
1043 module_handle = (uintptr_t) entry.hModule;
1044 if (module_handle == 0)
1045 continue;
1046
1047 descriptor = backtrace_open (entry.szExePath, error_callback, data,
1048 NULL);
1049 if (descriptor < 0)
1050 continue;
1051
1052 coff_add (state, descriptor, error_callback, data,
1053 &module_fileline_fn, &module_found_sym, &found_dwarf,
1054 module_handle);
1055 if (module_found_sym)
1056 found_sym = 1;
1057 }
1058
1059 CloseHandle (snapshot);
1060 }
1061#endif
1062
1063#ifdef HAVE_WINDOWS_H
1064 nt_dll_handle = GetModuleHandleW (L"ntdll.dll");
1065 if (nt_dll_handle)
1066 {
1067 LDR_REGISTER_FUNCTION register_func;
1068 const char register_name[] = "LdrRegisterDllNotification";
1069 register_func = (void*) GetProcAddress (nt_dll_handle,
1070 register_name);
1071
1072 if (register_func)
1073 {
1074 PVOID cookie;
1075 struct dll_notification_context *context
1077 sizeof (struct dll_notification_context),
1079
1080 if (context)
1081 {
1082 context->state = state;
1083 context->data = data;
1084 context->error_callback = error_callback;
1085
1086 register_func (0, &dll_notification, context, &cookie);
1087 }
1088 }
1089 }
1090#endif /* defined(HAVE_WINDOWS_H) */
1091
1092 if (!state->threaded)
1093 {
1094 if (found_sym)
1095 state->syminfo_fn = coff_syminfo;
1096 else if (state->syminfo_fn == NULL)
1097 state->syminfo_fn = coff_nosyms;
1098 }
1099 else
1100 {
1101 if (found_sym)
1103 else
1104 (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
1105 coff_nosyms);
1106 }
1107
1108 if (!state->threaded)
1109 {
1110 if (state->fileline_fn == NULL || state->fileline_fn == coff_nodebug)
1111 *fileline_fn = coff_fileline_fn;
1112 }
1113 else
1114 {
1115 fileline current_fn;
1116
1117 current_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
1118 if (current_fn == NULL || current_fn == coff_nodebug)
1119 *fileline_fn = coff_fileline_fn;
1120 }
1121
1122 return 1;
1123}
void * backtrace_alloc(struct backtrace_state *state ATTRIBUTE_UNUSED, size_t size, backtrace_error_callback error_callback, void *data)
Definition alloc.c:51
void backtrace_free(struct backtrace_state *state ATTRIBUTE_UNUSED, void *p, size_t size ATTRIBUTE_UNUSED, backtrace_error_callback error_callback ATTRIBUTE_UNUSED, void *data ATTRIBUTE_UNUSED)
Definition alloc.c:69
void(* backtrace_syminfo_callback)(void *data, uintptr_t pc, const char *symname, uintptr_t symval, uintptr_t symsize)
Definition backtrace.h:165
void(* backtrace_error_callback)(void *data, const char *msg, int errnum)
Definition backtrace.h:66
int(* backtrace_full_callback)(void *data, uintptr_t pc, const char *filename, int lineno, const char *function)
Definition backtrace.h:100
static void error_callback(void *data, const char *msg, int errnum)
Definition print.c:53
static int context
Definition radmin.c:69
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:228
Test enumeration values.
Definition dict_test.h:92
int backtrace_dwarf_add(struct backtrace_state *state, struct libbacktrace_base_address base_address, const struct dwarf_sections *dwarf_sections, int is_bigendian, struct dwarf_data *fileline_altlink, backtrace_error_callback error_callback, void *data, fileline *fileline_fn, struct dwarf_data **fileline_entry)
Definition dwarf.c:4536
#define ATTRIBUTE_UNUSED
Definition filenames.h:42
void backtrace_qsort(void *base, size_t count, size_t size, int(*compar)(const void *, const void *))
Definition sort.c:61
fileline fileline_fn
Definition internal.h:151
void backtrace_release_view(struct backtrace_state *state, struct backtrace_view *view, backtrace_error_callback error_callback, void *data)
Definition read.c:102
const char * filename
Definition internal.h:143
#define backtrace_atomic_load_pointer(p)
Definition internal.h:115
const void * data
Definition internal.h:185
int(* fileline)(struct backtrace_state *state, uintptr_t pc, backtrace_full_callback callback, backtrace_error_callback error_callback, void *data)
Definition internal.h:127
#define libbacktrace_add_base(pc, base)
Definition internal.h:361
const unsigned char * data[DEBUG_MAX]
Definition internal.h:323
@ DEBUG_MAX
Definition internal.h:316
int backtrace_close(int descriptor, backtrace_error_callback error_callback, void *data)
Definition posix.c:95
size_t size[DEBUG_MAX]
Definition internal.h:324
#define backtrace_atomic_store_pointer(p, v)
Definition internal.h:117
int backtrace_get_view(struct backtrace_state *state, int descriptor, off_t offset, uint64_t size, backtrace_error_callback error_callback, void *data, struct backtrace_view *view)
Definition read.c:48
int backtrace_open(const char *filename, backtrace_error_callback error_callback, void *data, int *does_not_exist)
Definition posix.c:59
#define __sync_bool_compare_and_swap(A, B, C)
Definition internal.h:77
unsigned short uint16_t
unsigned int uint32_t
unsigned char uint8_t
long long int off_t
static int coff_nodebug(struct backtrace_state *state ATTRIBUTE_UNUSED, uintptr_t pc ATTRIBUTE_UNUSED, backtrace_full_callback callback ATTRIBUTE_UNUSED, backtrace_error_callback error_callback, void *data)
Definition pecoff.c:238
static void coff_nosyms(struct backtrace_state *state ATTRIBUTE_UNUSED, uintptr_t addr ATTRIBUTE_UNUSED, backtrace_syminfo_callback callback ATTRIBUTE_UNUSED, backtrace_error_callback error_callback, void *data)
Definition pecoff.c:251
unsigned char number_of_aux_symbols
Definition pecoff.c:166
unsigned char value[4]
Definition pecoff.c:162
unsigned char storage_class
Definition pecoff.c:165
uint16_t machine
Definition pecoff.c:97
uint16_t number_of_relocations
Definition pecoff.c:143
uint16_t characteristics
Definition pecoff.c:103
unsigned char section_number[2]
Definition pecoff.c:163
static void coff_add_syminfo_data(struct backtrace_state *state, struct coff_syminfo_data *sdata)
Definition pecoff.c:521
uint32_t virtual_size
Definition pecoff.c:137
static size_t coff_short_name_len(const char *name)
Definition pecoff.c:286
uint32_t characteristics
Definition pecoff.c:145
uint32_t size_of_uninitialized_data
Definition pecoff.c:114
#define IMAGE_SYM_DTYPE_FUNCTION
Definition pecoff.c:172
uint16_t number_of_line_numbers
Definition pecoff.c:144
static uint16_t coff_read2(const unsigned char *p)
Definition pecoff.c:275
static int coff_symbol_compare(const void *v1, const void *v2)
Definition pecoff.c:328
uint8_t major_linker_version
Definition pecoff.c:110
uint32_t virtual_address
Definition pecoff.c:138
b_coff_name name
Definition pecoff.c:161
static int coff_short_name_eq(const char *name, const char *cname)
Definition pecoff.c:300
static int coff_symbol_search(const void *vkey, const void *ventry)
Definition pecoff.c:565
uint8_t minor_linker_version
Definition pecoff.c:111
uint32_t size_of_code
Definition pecoff.c:112
uint32_t address_of_entry_point
Definition pecoff.c:115
uint32_t pointer_to_relocations
Definition pecoff.c:141
uint32_t number_of_symbols
Definition pecoff.c:101
uint32_t time_date_stamp
Definition pecoff.c:99
#define SYM_SZ
Definition pecoff.c:176
size_t size
Definition elf.c:369
char short_name[8]
Definition pecoff.c:151
static int coff_long_name_eq(const char *name, unsigned int off, struct backtrace_view *str_view)
Definition pecoff.c:317
#define N_TBSHFT
Definition pecoff.c:171
struct coff_symbol * symbols
Definition pecoff.c:230
struct b_coff_name::@7 long_name
uint16_t number_of_sections
Definition pecoff.c:98
unsigned char type[2]
Definition pecoff.c:164
static uint32_t coff_read4(const unsigned char *p)
Definition pecoff.c:262
static int coff_expand_symbol(b_coff_internal_symbol *isym, const b_coff_external_symbol *sym, uint16_t sects_num, const unsigned char *strtab, size_t strtab_size)
Definition pecoff.c:346
int backtrace_initialize(struct backtrace_state *state, const char *filename ATTRIBUTE_UNUSED, int descriptor, backtrace_error_callback error_callback, void *data, fileline *fileline_fn)
Definition pecoff.c:997
uint16_t size_of_optional_header
Definition pecoff.c:102
#define PE_MAGIC
Definition pecoff.c:130
const char * name
Definition pecoff.c:218
#define PEP_MAGIC
Definition pecoff.c:131
union b_coff_optional_header::@4 u
uint32_t size_of_initialized_data
Definition pecoff.c:113
uint32_t base_of_code
Definition pecoff.c:116
uint32_t size_of_raw_data
Definition pecoff.c:139
static int coff_initialize_syminfo(struct backtrace_state *state, struct libbacktrace_base_address base_address, int is_64, const b_coff_section_header *sects, size_t sects_num, const b_coff_external_symbol *syms, size_t syms_size, const unsigned char *strtab, size_t strtab_size, backtrace_error_callback error_callback, void *data, struct coff_syminfo_data *sdata)
Definition pecoff.c:384
const char * name
Definition pecoff.c:181
static int coff_add(struct backtrace_state *state, int descriptor, backtrace_error_callback error_callback, void *data, fileline *fileline_fn, int *found_sym, int *found_dwarf, uintptr_t module_handle ATTRIBUTE_UNUSED)
Definition pecoff.c:635
struct coff_syminfo_data * next
Definition pecoff.c:228
uint32_t pointer_to_symbol_table
Definition pecoff.c:100
static const char *const debug_section_names[DEBUG_MAX]
Definition pecoff.c:190
static int coff_is_function_symbol(const b_coff_internal_symbol *isym)
Definition pecoff.c:375
static void coff_syminfo(struct backtrace_state *state, uintptr_t addr, backtrace_syminfo_callback callback, backtrace_error_callback error_callback ATTRIBUTE_UNUSED, void *data)
Definition pecoff.c:583
uint32_t pointer_to_raw_data
Definition pecoff.c:140
uint32_t pointer_to_line_numbers
Definition pecoff.c:142
uintptr_t address
Definition pecoff.c:220
static char const * name
fr_aka_sim_id_type_t type
void * state
Definition testlib.c:46
Functions to help with cleanup.
static fr_slen_t data
Definition value.h:1340