v / thirdparty / libbacktrace / windows.c
1295 lines · 1084 sloc · 30.65 KB · e78481994a892734d00a24a16951a2df75f76631
Raw
1// pecoff.c:
2#include <stdlib.h>
3#include <string.h>
4#include <sys/types.h>
5
6
7#ifdef HAVE_WINDOWS_H
8#ifndef WIN32_LEAN_AND_MEAN
9#define WIN32_LEAN_AND_MEAN
10#endif
11
12#ifndef NOMINMAX
13#define NOMINMAX
14#endif
15
16#include <windows.h>
17
18#ifdef HAVE_TLHELP32_H
19#include <tlhelp32.h>
20
21#ifdef UNICODE
22/* If UNICODE is defined, all the symbols are replaced by a macro to use the
23 wide variant. But we need the ansi variant, so undef the macros. */
24#undef MODULEENTRY32
25#undef Module32First
26#undef Module32Next
27#endif
28#endif
29
30#if defined(_ARM_)
31#define NTAPI
32#else
33#define NTAPI __stdcall
34#endif
35
36/* This is a simplified (but binary compatible) version of what Microsoft
37 defines in their documentation. */
38struct dll_notification_data
39{
40 ULONG reserved;
41 /* The name as UNICODE_STRING struct. */
42 PVOID full_dll_name;
43 PVOID base_dll_name;
44 PVOID dll_base;
45 ULONG size_of_image;
46};
47
48#define LDR_DLL_NOTIFICATION_REASON_LOADED 1
49
50typedef LONG NTSTATUS;
51typedef VOID (CALLBACK *LDR_DLL_NOTIFICATION)(ULONG,
52 struct dll_notification_data*,
53 PVOID);
54typedef NTSTATUS (NTAPI *LDR_REGISTER_FUNCTION)(ULONG,
55 LDR_DLL_NOTIFICATION, PVOID,
56 PVOID*);
57#endif
58
59/* Coff file header. */
60
61typedef struct {
62 uint16_t machine;
63 uint16_t number_of_sections;
64 uint32_t time_date_stamp;
65 uint32_t pointer_to_symbol_table;
66 uint32_t number_of_symbols;
67 uint16_t size_of_optional_header;
68 uint16_t characteristics;
69} b_coff_file_header;
70
71/* Coff optional header. */
72
73typedef struct {
74 uint16_t magic;
75 uint8_t major_linker_version;
76 uint8_t minor_linker_version;
77 uint32_t size_of_code;
78 uint32_t size_of_initialized_data;
79 uint32_t size_of_uninitialized_data;
80 uint32_t address_of_entry_point;
81 uint32_t base_of_code;
82 union {
83 struct {
84 uint32_t base_of_data;
85 uint32_t image_base;
86 } pe;
87 struct {
88 uint64_t image_base;
89 } pep;
90 } u;
91} b_coff_optional_header;
92
93/* Values of magic in optional header. */
94
95#define PE_MAGIC 0x10b /* PE32 executable. */
96#define PEP_MAGIC 0x20b /* PE32+ executable (for 64bit targets). */
97
98/* Coff section header. */
99
100typedef struct {
101 char name[8];
102 uint32_t virtual_size;
103 uint32_t virtual_address;
104 uint32_t size_of_raw_data;
105 uint32_t pointer_to_raw_data;
106 uint32_t pointer_to_relocations;
107 uint32_t pointer_to_line_numbers;
108 uint16_t number_of_relocations;
109 uint16_t number_of_line_numbers;
110 uint32_t characteristics;
111} b_coff_section_header;
112
113/* Coff symbol name. */
114
115typedef union {
116 char short_name[8];
117 struct {
118 unsigned char zeroes[4];
119 unsigned char off[4];
120 } long_name;
121} b_coff_name;
122
123/* Coff symbol (external representation which is unaligned). */
124
125typedef struct {
126 b_coff_name name;
127 unsigned char value[4];
128 unsigned char section_number[2];
129 unsigned char type[2];
130 unsigned char storage_class;
131 unsigned char number_of_aux_symbols;
132} b_coff_external_symbol;
133
134/* Symbol types. */
135
136#define N_TBSHFT 4 /* Shift for the derived type. */
137#define IMAGE_SYM_DTYPE_FUNCTION 2 /* Function derived type. */
138
139/* Size of a coff symbol. */
140
141#define SYM_SZ 18
142
143/* Coff symbol, internal representation (aligned). */
144
145typedef struct {
146 const char *name;
147 uint32_t value;
148 int16_t sec;
149 uint16_t type;
150 uint16_t sc;
151} b_coff_internal_symbol;
152
153/* Names of sections, indexed by enum dwarf_section in internal.h. */
154
155static const char * const debug_section_names[DEBUG_MAX] =
156{
157 ".debug_info",
158 ".debug_line",
159 ".debug_abbrev",
160 ".debug_ranges",
161 ".debug_str",
162 ".debug_addr",
163 ".debug_str_offsets",
164 ".debug_line_str",
165 ".debug_rnglists"
166};
167
168/* Information we gather for the sections we care about. */
169
170struct debug_section_info
171{
172 /* Section file offset. */
173 off_t offset;
174 /* Section size. */
175 size_t size;
176};
177
178/* Information we keep for an coff symbol. */
179
180struct coff_symbol
181{
182 /* The name of the symbol. */
183 const char *name;
184 /* The address of the symbol. */
185 uintptr_t address;
186};
187
188/* Information to pass to coff_syminfo. */
189
190struct coff_syminfo_data
191{
192 /* Symbols for the next module. */
193 struct coff_syminfo_data *next;
194 /* The COFF symbols, sorted by address. */
195 struct coff_symbol *symbols;
196 /* The number of symbols. */
197 size_t count;
198};
199
200/* A dummy callback function used when we can't find any debug info. */
201
202static int
203coff_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
204 uintptr_t pc ATTRIBUTE_UNUSED,
205 backtrace_full_callback callback ATTRIBUTE_UNUSED,
206 backtrace_error_callback error_callback, void *data)
207{
208 error_callback (data, "no debug info in PE/COFF executable (make sure to compile with -g)", -1);
209 return 0;
210}
211
212/* A dummy callback function used when we can't find a symbol
213 table. */
214
215static void
216coff_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,
217 uintptr_t addr ATTRIBUTE_UNUSED,
218 backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,
219 backtrace_error_callback error_callback, void *data)
220{
221 error_callback (data, "no symbol table in PE/COFF executable", -1);
222}
223
224/* Read a potentially unaligned 4 byte word at P, using native endianness. */
225
226static uint32_t
227coff_read4 (const unsigned char *p)
228{
229 uint32_t res;
230
231 memcpy (&res, p, 4);
232 return res;
233}
234
235/* Read a potentially unaligned 2 byte word at P, using native endianness.
236 All 2 byte word in symbols are always aligned, but for coherency all
237 fields are declared as char arrays. */
238
239static uint16_t
240coff_read2 (const unsigned char *p)
241{
242 uint16_t res;
243
244 memcpy (&res, p, sizeof (res));
245 return res;
246}
247
248/* Return the length (without the trailing 0) of a COFF short name. */
249
250static size_t
251coff_short_name_len (const char *name)
252{
253 int i;
254
255 for (i = 0; i < 8; i++)
256 if (name[i] == 0)
257 return i;
258 return 8;
259}
260
261/* Return true iff COFF short name CNAME is the same as NAME (a NUL-terminated
262 string). */
263
264static int
265coff_short_name_eq (const char *name, const char *cname)
266{
267 int i;
268
269 for (i = 0; i < 8; i++)
270 {
271 if (name[i] != cname[i])
272 return 0;
273 if (name[i] == 0)
274 return 1;
275 }
276 return name[8] == 0;
277}
278
279/* Return true iff NAME is the same as string at offset OFF. */
280
281static int
282coff_long_name_eq (const char *name, unsigned int off,
283 struct backtrace_view *str_view)
284{
285 if (off >= str_view->len)
286 return 0;
287 return strcmp (name, (const char *)str_view->data + off) == 0;
288}
289
290/* Compare struct coff_symbol for qsort. */
291
292static int
293coff_symbol_compare (const void *v1, const void *v2)
294{
295 const struct coff_symbol *e1 = (const struct coff_symbol *) v1;
296 const struct coff_symbol *e2 = (const struct coff_symbol *) v2;
297
298 if (e1->address < e2->address)
299 return -1;
300 else if (e1->address > e2->address)
301 return 1;
302 else
303 return 0;
304}
305
306/* Convert SYM to internal (and aligned) format ISYM, using string table
307 from STRTAB and STRTAB_SIZE, and number of sections SECTS_NUM.
308 Return -1 in case of error (invalid section number or string index). */
309
310static int
311coff_expand_symbol (b_coff_internal_symbol *isym,
312 const b_coff_external_symbol *sym,
313 uint16_t sects_num,
314 const unsigned char *strtab, size_t strtab_size)
315{
316 isym->type = coff_read2 (sym->type);
317 isym->sec = coff_read2 (sym->section_number);
318 isym->sc = sym->storage_class;
319
320 if (isym->sec > 0 && (uint16_t) isym->sec > sects_num)
321 return -1;
322 if (sym->name.short_name[0] != 0)
323 isym->name = sym->name.short_name;
324 else
325 {
326 uint32_t off = coff_read4 (sym->name.long_name.off);
327
328 if (off >= strtab_size)
329 return -1;
330 isym->name = (const char *) strtab + off;
331 }
332 return 0;
333}
334
335/* Return true iff SYM is a defined symbol for a function. Data symbols
336 aren't considered because they aren't easily identified (same type as
337 section names, presence of symbols defined by the linker script). */
338
339static int
340coff_is_function_symbol (const b_coff_internal_symbol *isym)
341{
342 return (isym->type >> N_TBSHFT) == IMAGE_SYM_DTYPE_FUNCTION
343 && isym->sec > 0;
344}
345
346/* Initialize the symbol table info for coff_syminfo. */
347
348static int
349coff_initialize_syminfo (struct backtrace_state *state,
350 struct libbacktrace_base_address base_address,
351 int is_64, const b_coff_section_header *sects,
352 size_t sects_num, const b_coff_external_symbol *syms,
353 size_t syms_size, const unsigned char *strtab,
354 size_t strtab_size,
355 backtrace_error_callback error_callback,
356 void *data, struct coff_syminfo_data *sdata)
357{
358 size_t syms_count;
359 char *coff_symstr;
360 size_t coff_symstr_len;
361 size_t coff_symbol_count;
362 size_t coff_symbol_size;
363 struct coff_symbol *coff_symbols;
364 struct coff_symbol *coff_sym;
365 char *coff_str;
366 size_t i;
367
368 syms_count = syms_size / SYM_SZ;
369
370 /* We only care about function symbols. Count them. Also count size of
371 strings for in-symbol names. */
372 coff_symbol_count = 0;
373 coff_symstr_len = 0;
374 for (i = 0; i < syms_count; ++i)
375 {
376 const b_coff_external_symbol *asym = &syms[i];
377 b_coff_internal_symbol isym;
378
379 if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size) < 0)
380 {
381 error_callback (data, "invalid section or offset in coff symbol", 0);
382 return 0;
383 }
384 if (coff_is_function_symbol (&isym))
385 {
386 ++coff_symbol_count;
387 if (asym->name.short_name[0] != 0)
388 coff_symstr_len += coff_short_name_len (asym->name.short_name) + 1;
389 }
390
391 i += asym->number_of_aux_symbols;
392 }
393
394 coff_symbol_size = (coff_symbol_count + 1) * sizeof (struct coff_symbol);
395 coff_symbols = ((struct coff_symbol *)
396 backtrace_alloc (state, coff_symbol_size, error_callback,
397 data));
398 if (coff_symbols == NULL)
399 return 0;
400
401 /* Allocate memory for symbols strings. */
402 if (coff_symstr_len > 0)
403 {
404 coff_symstr = ((char *)
405 backtrace_alloc (state, coff_symstr_len, error_callback,
406 data));
407 if (coff_symstr == NULL)
408 {
409 backtrace_free (state, coff_symbols, coff_symbol_size,
410 error_callback, data);
411 return 0;
412 }
413 }
414 else
415 coff_symstr = NULL;
416
417 /* Copy symbols. */
418 coff_sym = coff_symbols;
419 coff_str = coff_symstr;
420 for (i = 0; i < syms_count; ++i)
421 {
422 const b_coff_external_symbol *asym = &syms[i];
423 b_coff_internal_symbol isym;
424
425 if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size))
426 {
427 /* Should not fail, as it was already tested in the previous
428 loop. */
429 abort ();
430 }
431 if (coff_is_function_symbol (&isym))
432 {
433 const char *name;
434 int16_t secnum;
435
436 if (asym->name.short_name[0] != 0)
437 {
438 size_t len = coff_short_name_len (isym.name);
439 name = coff_str;
440 memcpy (coff_str, isym.name, len);
441 coff_str[len] = 0;
442 coff_str += len + 1;
443 }
444 else
445 name = isym.name;
446
447 if (!is_64)
448 {
449 /* Strip leading '_'. */
450 if (name[0] == '_')
451 name++;
452 }
453
454 /* Symbol value is section relative, so we need to read the address
455 of its section. */
456 secnum = coff_read2 (asym->section_number);
457
458 coff_sym->name = name;
459 coff_sym->address =
460 libbacktrace_add_base ((coff_read4 (asym->value)
461 + sects[secnum - 1].virtual_address),
462 base_address);
463 coff_sym++;
464 }
465
466 i += asym->number_of_aux_symbols;
467 }
468
469 /* End of symbols marker. */
470 coff_sym->name = NULL;
471 coff_sym->address = -1;
472
473 backtrace_qsort (coff_symbols, coff_symbol_count,
474 sizeof (struct coff_symbol), coff_symbol_compare);
475
476 sdata->next = NULL;
477 sdata->symbols = coff_symbols;
478 sdata->count = coff_symbol_count;
479
480 return 1;
481}
482
483/* Add EDATA to the list in STATE. */
484
485static void
486coff_add_syminfo_data (struct backtrace_state *state,
487 struct coff_syminfo_data *sdata)
488{
489 if (!state->threaded)
490 {
491 struct coff_syminfo_data **pp;
492
493 for (pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
494 *pp != NULL;
495 pp = &(*pp)->next)
496 ;
497 *pp = sdata;
498 }
499 else
500 {
501 while (1)
502 {
503 struct coff_syminfo_data **pp;
504
505 pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
506
507 while (1)
508 {
509 struct coff_syminfo_data *p;
510
511 p = backtrace_atomic_load_pointer (pp);
512
513 if (p == NULL)
514 break;
515
516 pp = &p->next;
517 }
518
519 if (__sync_bool_compare_and_swap (pp, NULL, sdata))
520 break;
521 }
522 }
523}
524
525/* Compare an ADDR against an elf_symbol for bsearch. We allocate one
526 extra entry in the array so that this can look safely at the next
527 entry. */
528
529static int
530coff_symbol_search (const void *vkey, const void *ventry)
531{
532 const uintptr_t *key = (const uintptr_t *) vkey;
533 const struct coff_symbol *entry = (const struct coff_symbol *) ventry;
534 uintptr_t addr;
535
536 addr = *key;
537 if (addr < entry->address)
538 return -1;
539 else if (addr >= entry[1].address)
540 return 1;
541 else
542 return 0;
543}
544
545/* Return the symbol name and value for an ADDR. */
546
547static void
548coff_syminfo (struct backtrace_state *state, uintptr_t addr,
549 backtrace_syminfo_callback callback,
550 backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
551 void *data)
552{
553 struct coff_syminfo_data *sdata;
554 struct coff_symbol *sym = NULL;
555
556 if (!state->threaded)
557 {
558 for (sdata = (struct coff_syminfo_data *) state->syminfo_data;
559 sdata != NULL;
560 sdata = sdata->next)
561 {
562 sym = ((struct coff_symbol *)
563 bsearch (&addr, sdata->symbols, sdata->count,
564 sizeof (struct coff_symbol), coff_symbol_search));
565 if (sym != NULL)
566 break;
567 }
568 }
569 else
570 {
571 struct coff_syminfo_data **pp;
572
573 pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
574 while (1)
575 {
576 sdata = backtrace_atomic_load_pointer (pp);
577 if (sdata == NULL)
578 break;
579
580 sym = ((struct coff_symbol *)
581 bsearch (&addr, sdata->symbols, sdata->count,
582 sizeof (struct coff_symbol), coff_symbol_search));
583 if (sym != NULL)
584 break;
585
586 pp = &sdata->next;
587 }
588 }
589
590 if (sym == NULL)
591 callback (data, addr, NULL, 0, 0);
592 else
593 callback (data, addr, sym->name, sym->address, 0);
594}
595
596/* Add the backtrace data for one PE/COFF file. Returns 1 on success,
597 0 on failure (in both cases descriptor is closed). */
598
599static int
600coff_add (struct backtrace_state *state, int descriptor,
601 backtrace_error_callback error_callback, void *data,
602 fileline *fileline_fn, int *found_sym, int *found_dwarf,
603 uintptr_t module_handle ATTRIBUTE_UNUSED)
604{
605 struct backtrace_view fhdr_view;
606 off_t fhdr_off;
607 int magic_ok;
608 b_coff_file_header fhdr;
609 off_t opt_sects_off;
610 size_t opt_sects_size;
611 unsigned int sects_num;
612 struct backtrace_view sects_view;
613 int sects_view_valid;
614 const b_coff_optional_header *opt_hdr;
615 const b_coff_section_header *sects;
616 struct backtrace_view str_view;
617 int str_view_valid;
618 size_t str_size;
619 off_t str_off;
620 struct backtrace_view syms_view;
621 off_t syms_off;
622 size_t syms_size;
623 int syms_view_valid;
624 unsigned int syms_num;
625 unsigned int i;
626 struct debug_section_info sections[DEBUG_MAX];
627 off_t min_offset;
628 off_t max_offset;
629 struct backtrace_view debug_view;
630 int debug_view_valid;
631 int is_64;
632 struct libbacktrace_base_address image_base;
633 struct libbacktrace_base_address base_address;
634 struct dwarf_sections dwarf_sections;
635
636 *found_sym = 0;
637 *found_dwarf = 0;
638
639 sects_view_valid = 0;
640 syms_view_valid = 0;
641 str_view_valid = 0;
642 debug_view_valid = 0;
643
644 /* Map the MS-DOS stub (if any) and extract file header offset. */
645 if (!backtrace_get_view (state, descriptor, 0, 0x40, error_callback,
646 data, &fhdr_view))
647 goto fail;
648
649 {
650 const unsigned char *vptr = fhdr_view.data;
651
652 if (vptr[0] == 'M' && vptr[1] == 'Z')
653 fhdr_off = coff_read4 (vptr + 0x3c);
654 else
655 fhdr_off = 0;
656 }
657
658 backtrace_release_view (state, &fhdr_view, error_callback, data);
659
660 /* Map the coff file header. */
661 if (!backtrace_get_view (state, descriptor, fhdr_off,
662 sizeof (b_coff_file_header) + 4,
663 error_callback, data, &fhdr_view))
664 goto fail;
665
666 if (fhdr_off != 0)
667 {
668 const char *magic = (const char *) fhdr_view.data;
669 magic_ok = memcmp (magic, "PE\0", 4) == 0;
670 fhdr_off += 4;
671
672 memcpy (&fhdr, (const unsigned char *) fhdr_view.data + 4, sizeof fhdr);
673 }
674 else
675 {
676 memcpy (&fhdr, fhdr_view.data, sizeof fhdr);
677 /* TODO: test fhdr.machine for coff but non-PE platforms. */
678 magic_ok = 0;
679 }
680 backtrace_release_view (state, &fhdr_view, error_callback, data);
681
682 if (!magic_ok)
683 {
684 error_callback (data, "executable file is not COFF", 0);
685 goto fail;
686 }
687
688 sects_num = fhdr.number_of_sections;
689 syms_num = fhdr.number_of_symbols;
690
691 opt_sects_off = fhdr_off + sizeof (fhdr);
692 opt_sects_size = (fhdr.size_of_optional_header
693 + sects_num * sizeof (b_coff_section_header));
694
695 /* To translate PC to file/line when using DWARF, we need to find
696 the .debug_info and .debug_line sections. */
697
698 /* Read the optional header and the section headers. */
699
700 if (!backtrace_get_view (state, descriptor, opt_sects_off, opt_sects_size,
701 error_callback, data, §s_view))
702 goto fail;
703 sects_view_valid = 1;
704 opt_hdr = (const b_coff_optional_header *) sects_view.data;
705 sects = (const b_coff_section_header *)
706 ((const unsigned char *) sects_view.data + fhdr.size_of_optional_header);
707
708 is_64 = 0;
709 memset (&image_base, 0, sizeof image_base);
710 if (fhdr.size_of_optional_header > sizeof (*opt_hdr))
711 {
712 if (opt_hdr->magic == PE_MAGIC)
713 image_base.m = opt_hdr->u.pe.image_base;
714 else if (opt_hdr->magic == PEP_MAGIC)
715 {
716 image_base.m = opt_hdr->u.pep.image_base;
717 is_64 = 1;
718 }
719 else
720 {
721 error_callback (data, "bad magic in PE optional header", 0);
722 goto fail;
723 }
724 }
725
726 /* Read the symbol table and the string table. */
727
728 if (fhdr.pointer_to_symbol_table == 0)
729 {
730 /* No symbol table, no string table. */
731 str_off = 0;
732 str_size = 0;
733 syms_num = 0;
734 syms_size = 0;
735 }
736 else
737 {
738 /* Symbol table is followed by the string table. The string table
739 starts with its length (on 4 bytes).
740 Map the symbol table and the length of the string table. */
741 syms_off = fhdr.pointer_to_symbol_table;
742 syms_size = syms_num * SYM_SZ;
743
744 if (!backtrace_get_view (state, descriptor, syms_off, syms_size + 4,
745 error_callback, data, &syms_view))
746 goto fail;
747 syms_view_valid = 1;
748
749 str_size = coff_read4 ((const unsigned char *) syms_view.data
750 + syms_size);
751
752 str_off = syms_off + syms_size;
753
754 if (str_size > 4)
755 {
756 /* Map string table (including the length word). */
757
758 if (!backtrace_get_view (state, descriptor, str_off, str_size,
759 error_callback, data, &str_view))
760 goto fail;
761 str_view_valid = 1;
762 }
763 }
764
765 memset (sections, 0, sizeof sections);
766
767 /* Look for the symbol table. */
768 for (i = 0; i < sects_num; ++i)
769 {
770 const b_coff_section_header *s = sects + i;
771 unsigned int str_off;
772 int j;
773
774 if (s->name[0] == '/')
775 {
776 /* Extended section name. */
777 str_off = atoi (s->name + 1);
778 }
779 else
780 str_off = 0;
781
782 for (j = 0; j < (int) DEBUG_MAX; ++j)
783 {
784 const char *dbg_name = debug_section_names[j];
785 int match;
786
787 if (str_off != 0)
788 match = coff_long_name_eq (dbg_name, str_off, &str_view);
789 else
790 match = coff_short_name_eq (dbg_name, s->name);
791 if (match)
792 {
793 sections[j].offset = s->pointer_to_raw_data;
794 sections[j].size = s->virtual_size <= s->size_of_raw_data ?
795 s->virtual_size : s->size_of_raw_data;
796 break;
797 }
798 }
799 }
800
801 if (syms_num != 0)
802 {
803 struct coff_syminfo_data *sdata;
804
805 sdata = ((struct coff_syminfo_data *)
806 backtrace_alloc (state, sizeof *sdata, error_callback, data));
807 if (sdata == NULL)
808 goto fail;
809
810 if (!coff_initialize_syminfo (state, image_base, is_64,
811 sects, sects_num,
812 syms_view.data, syms_size,
813 str_view.data, str_size,
814 error_callback, data, sdata))
815 {
816 backtrace_free (state, sdata, sizeof *sdata, error_callback, data);
817 goto fail;
818 }
819
820 *found_sym = 1;
821
822 coff_add_syminfo_data (state, sdata);
823 }
824
825 backtrace_release_view (state, §s_view, error_callback, data);
826 sects_view_valid = 0;
827 if (syms_view_valid)
828 {
829 backtrace_release_view (state, &syms_view, error_callback, data);
830 syms_view_valid = 0;
831 }
832
833 /* Read all the debug sections in a single view, since they are
834 probably adjacent in the file. We never release this view. */
835
836 min_offset = 0;
837 max_offset = 0;
838 for (i = 0; i < (int) DEBUG_MAX; ++i)
839 {
840 off_t end;
841
842 if (sections[i].size == 0)
843 continue;
844 if (min_offset == 0 || sections[i].offset < min_offset)
845 min_offset = sections[i].offset;
846 end = sections[i].offset + sections[i].size;
847 if (end > max_offset)
848 max_offset = end;
849 }
850 if (min_offset == 0 || max_offset == 0)
851 {
852 if (!backtrace_close (descriptor, error_callback, data))
853 goto fail;
854 *fileline_fn = coff_nodebug;
855 return 1;
856 }
857
858 if (!backtrace_get_view (state, descriptor, min_offset,
859 max_offset - min_offset,
860 error_callback, data, &debug_view))
861 goto fail;
862 debug_view_valid = 1;
863
864 /* We've read all we need from the executable. */
865 if (!backtrace_close (descriptor, error_callback, data))
866 goto fail;
867 descriptor = -1;
868
869 for (i = 0; i < (int) DEBUG_MAX; ++i)
870 {
871 size_t size = sections[i].size;
872 dwarf_sections.size[i] = size;
873 if (size == 0)
874 dwarf_sections.data[i] = NULL;
875 else
876 dwarf_sections.data[i] = ((const unsigned char *) debug_view.data
877 + (sections[i].offset - min_offset));
878 }
879
880 memset (&base_address, 0, sizeof base_address);
881#ifdef HAVE_WINDOWS_H
882 base_address.m = module_handle - image_base.m;
883#endif
884
885 if (!backtrace_dwarf_add (state, base_address, &dwarf_sections,
886 0, /* FIXME: is_bigendian */
887 NULL, /* altlink */
888 error_callback, data, fileline_fn,
889 NULL /* returned fileline_entry */))
890 goto fail;
891
892 *found_dwarf = 1;
893
894 return 1;
895
896 fail:
897 if (sects_view_valid)
898 backtrace_release_view (state, §s_view, error_callback, data);
899 if (str_view_valid)
900 backtrace_release_view (state, &str_view, error_callback, data);
901 if (syms_view_valid)
902 backtrace_release_view (state, &syms_view, error_callback, data);
903 if (debug_view_valid)
904 backtrace_release_view (state, &debug_view, error_callback, data);
905 if (descriptor != -1)
906 backtrace_close (descriptor, error_callback, data);
907 return 0;
908}
909
910#ifdef HAVE_WINDOWS_H
911struct dll_notification_context
912{
913 struct backtrace_state *state;
914 backtrace_error_callback error_callback;
915 void *data;
916};
917
918static VOID CALLBACK
919dll_notification (ULONG reason,
920 struct dll_notification_data *notification_data,
921 PVOID context)
922{
923 char module_name[MAX_PATH];
924 int descriptor;
925 struct dll_notification_context* dll_context =
926 (struct dll_notification_context*) context;
927 struct backtrace_state *state = dll_context->state;
928 void *data = dll_context->data;
929 backtrace_error_callback error_callback = dll_context->data;
930 fileline fileline;
931 int found_sym;
932 int found_dwarf;
933 HMODULE module_handle;
934
935 if (reason != LDR_DLL_NOTIFICATION_REASON_LOADED)
936 return;
937
938 if (!GetModuleHandleExW ((GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
939 | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT),
940 (wchar_t*) notification_data->dll_base,
941 &module_handle))
942 return;
943
944 if (!GetModuleFileNameA ((HMODULE) module_handle, module_name, MAX_PATH - 1))
945 return;
946
947 descriptor = backtrace_open (module_name, error_callback, data, NULL);
948
949 if (descriptor < 0)
950 return;
951
952 coff_add (state, descriptor, error_callback, data, &fileline, &found_sym,
953 &found_dwarf, (uintptr_t) module_handle);
954}
955#endif /* defined(HAVE_WINDOWS_H) */
956
957/* Initialize the backtrace data we need from an ELF executable. At
958 the ELF level, all we need to do is find the debug info
959 sections. */
960
961int
962backtrace_initialize (struct backtrace_state *state,
963 const char *filename ATTRIBUTE_UNUSED, int descriptor,
964 backtrace_error_callback error_callback,
965 void *data, fileline *fileline_fn)
966{
967 int ret;
968 int found_sym;
969 int found_dwarf;
970 fileline coff_fileline_fn;
971 uintptr_t module_handle = 0;
972#ifdef HAVE_TLHELP32_H
973 fileline module_fileline_fn;
974 int module_found_sym;
975 HANDLE snapshot;
976#endif
977
978#ifdef HAVE_WINDOWS_H
979 HMODULE nt_dll_handle;
980
981 module_handle = (uintptr_t) GetModuleHandle (NULL);
982#endif
983
984 ret = coff_add (state, descriptor, error_callback, data,
985 &coff_fileline_fn, &found_sym, &found_dwarf, module_handle);
986 if (!ret)
987 return 0;
988
989#ifdef HAVE_TLHELP32_H
990 do
991 {
992 snapshot = CreateToolhelp32Snapshot (TH32CS_SNAPMODULE, 0);
993 }
994 while (snapshot == INVALID_HANDLE_VALUE
995 && GetLastError () == ERROR_BAD_LENGTH);
996
997 if (snapshot != INVALID_HANDLE_VALUE)
998 {
999 MODULEENTRY32 entry;
1000 BOOL ok;
1001 entry.dwSize = sizeof (MODULEENTRY32);
1002
1003 for (ok = Module32First (snapshot, &entry); ok; ok = Module32Next (snapshot, &entry))
1004 {
1005 if (strcmp (filename, entry.szExePath) == 0)
1006 continue;
1007
1008 module_handle = (uintptr_t) entry.hModule;
1009 if (module_handle == 0)
1010 continue;
1011
1012 descriptor = backtrace_open (entry.szExePath, error_callback, data,
1013 NULL);
1014 if (descriptor < 0)
1015 continue;
1016
1017 coff_add (state, descriptor, error_callback, data,
1018 &module_fileline_fn, &module_found_sym, &found_dwarf,
1019 module_handle);
1020 if (module_found_sym)
1021 found_sym = 1;
1022 }
1023
1024 CloseHandle (snapshot);
1025 }
1026#endif
1027
1028#ifdef HAVE_WINDOWS_H
1029 nt_dll_handle = GetModuleHandleW (L"ntdll.dll");
1030 if (nt_dll_handle)
1031 {
1032 LDR_REGISTER_FUNCTION register_func;
1033 const char register_name[] = "LdrRegisterDllNotification";
1034 register_func = (void*) GetProcAddress (nt_dll_handle,
1035 register_name);
1036
1037 if (register_func)
1038 {
1039 PVOID cookie;
1040 struct dll_notification_context *context
1041 = backtrace_alloc (state,
1042 sizeof (struct dll_notification_context),
1043 error_callback, data);
1044
1045 if (context)
1046 {
1047 context->state = state;
1048 context->data = data;
1049 context->error_callback = error_callback;
1050
1051 register_func (0, &dll_notification, context, &cookie);
1052 }
1053 }
1054 }
1055#endif /* defined(HAVE_WINDOWS_H) */
1056
1057 if (!state->threaded)
1058 {
1059 if (found_sym)
1060 state->syminfo_fn = coff_syminfo;
1061 else if (state->syminfo_fn == NULL)
1062 state->syminfo_fn = coff_nosyms;
1063 }
1064 else
1065 {
1066 if (found_sym)
1067 backtrace_atomic_store_pointer (&state->syminfo_fn, coff_syminfo);
1068 else
1069 (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
1070 coff_nosyms);
1071 }
1072
1073 if (!state->threaded)
1074 {
1075 if (state->fileline_fn == NULL || state->fileline_fn == coff_nodebug)
1076 *fileline_fn = coff_fileline_fn;
1077 }
1078 else
1079 {
1080 fileline current_fn;
1081
1082 current_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
1083 if (current_fn == NULL || current_fn == coff_nodebug)
1084 *fileline_fn = coff_fileline_fn;
1085 }
1086
1087 return 1;
1088}
1089// read.c:
1090#include <errno.h>
1091#include <stdlib.h>
1092#include <sys/types.h>
1093#include <unistd.h>
1094
1095
1096/* This file implements file views when mmap is not available. */
1097
1098/* Create a view of SIZE bytes from DESCRIPTOR at OFFSET. */
1099
1100int
1101backtrace_get_view (struct backtrace_state *state, int descriptor,
1102 off_t offset, uint64_t size,
1103 backtrace_error_callback error_callback,
1104 void *data, struct backtrace_view *view)
1105{
1106 uint64_t got;
1107 ssize_t r;
1108
1109 if ((uint64_t) (size_t) size != size)
1110 {
1111 error_callback (data, "file size too large", 0);
1112 return 0;
1113 }
1114
1115 if (lseek (descriptor, offset, SEEK_SET) < 0)
1116 {
1117 error_callback (data, "lseek", errno);
1118 return 0;
1119 }
1120
1121 view->base = backtrace_alloc (state, size, error_callback, data);
1122 if (view->base == NULL)
1123 return 0;
1124 view->data = view->base;
1125 view->len = size;
1126
1127 got = 0;
1128 while (got < size)
1129 {
1130 r = read (descriptor, view->base, size - got);
1131 if (r < 0)
1132 {
1133 error_callback (data, "read", errno);
1134 free (view->base);
1135 return 0;
1136 }
1137 if (r == 0)
1138 break;
1139 got += (uint64_t) r;
1140 }
1141
1142 if (got < size)
1143 {
1144 error_callback (data, "file too short", 0);
1145 free (view->base);
1146 return 0;
1147 }
1148
1149 return 1;
1150}
1151
1152/* Release a view read by backtrace_get_view. */
1153
1154void
1155backtrace_release_view (struct backtrace_state *state,
1156 struct backtrace_view *view,
1157 backtrace_error_callback error_callback,
1158 void *data)
1159{
1160 backtrace_free (state, view->base, view->len, error_callback, data);
1161 view->data = NULL;
1162 view->base = NULL;
1163}
1164// alloc.c:
1165#include <errno.h>
1166#include <stdlib.h>
1167#include <sys/types.h>
1168
1169
1170/* Allocation routines to use on systems that do not support anonymous
1171 mmap. This implementation just uses malloc, which means that the
1172 backtrace functions may not be safely invoked from a signal
1173 handler. */
1174
1175/* Allocate memory like malloc. If ERROR_CALLBACK is NULL, don't
1176 report an error. */
1177
1178void *
1179backtrace_alloc (struct backtrace_state *state ATTRIBUTE_UNUSED,
1180 size_t size, backtrace_error_callback error_callback,
1181 void *data)
1182{
1183 void *ret;
1184
1185 ret = malloc (size);
1186 if (ret == NULL)
1187 {
1188 if (error_callback)
1189 error_callback (data, "malloc", errno);
1190 }
1191 return ret;
1192}
1193
1194/* Free memory. */
1195
1196void
1197backtrace_free (struct backtrace_state *state ATTRIBUTE_UNUSED,
1198 void *p, size_t size ATTRIBUTE_UNUSED,
1199 backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
1200 void *data ATTRIBUTE_UNUSED)
1201{
1202 free (p);
1203}
1204
1205/* Grow VEC by SIZE bytes. */
1206
1207void *
1208backtrace_vector_grow (struct backtrace_state *state ATTRIBUTE_UNUSED,
1209 size_t size, backtrace_error_callback error_callback,
1210 void *data, struct backtrace_vector *vec)
1211{
1212 void *ret;
1213
1214 if (size > vec->alc)
1215 {
1216 size_t alc;
1217 void *base;
1218
1219 if (vec->size == 0)
1220 alc = 32 * size;
1221 else if (vec->size >= 4096)
1222 alc = vec->size + 4096;
1223 else
1224 alc = 2 * vec->size;
1225
1226 if (alc < vec->size + size)
1227 alc = vec->size + size;
1228
1229 base = realloc (vec->base, alc);
1230 if (base == NULL)
1231 {
1232 error_callback (data, "realloc", errno);
1233 return NULL;
1234 }
1235
1236 vec->base = base;
1237 vec->alc = alc - vec->size;
1238 }
1239
1240 ret = (char *) vec->base + vec->size;
1241 vec->size += size;
1242 vec->alc -= size;
1243 return ret;
1244}
1245
1246/* Finish the current allocation on VEC. */
1247
1248void *
1249backtrace_vector_finish (struct backtrace_state *state,
1250 struct backtrace_vector *vec,
1251 backtrace_error_callback error_callback,
1252 void *data)
1253{
1254 void *ret;
1255
1256 /* With this allocator we call realloc in backtrace_vector_grow,
1257 which means we can't easily reuse the memory here. So just
1258 release it. */
1259 if (!backtrace_vector_release (state, vec, error_callback, data))
1260 return NULL;
1261 ret = vec->base;
1262 vec->base = NULL;
1263 vec->size = 0;
1264 vec->alc = 0;
1265 return ret;
1266}
1267
1268/* Release any extra space allocated for VEC. */
1269
1270int
1271backtrace_vector_release (struct backtrace_state *state ATTRIBUTE_UNUSED,
1272 struct backtrace_vector *vec,
1273 backtrace_error_callback error_callback,
1274 void *data)
1275{
1276 vec->alc = 0;
1277
1278 if (vec->size == 0)
1279 {
1280 /* As of C17, realloc with size 0 is marked as an obsolescent feature, use
1281 free instead. */
1282 free (vec->base);
1283 vec->base = NULL;
1284 return 1;
1285 }
1286
1287 vec->base = realloc (vec->base, vec->size);
1288 if (vec->base == NULL)
1289 {
1290 error_callback (data, "realloc", errno);
1291 return 0;
1292 }
1293
1294 return 1;
1295}
1296