]> git.ipfire.org Git - thirdparty/gcc.git/blob - libbacktrace/pecoff.c
c++: Setup aliases imported from modules [PR106820]
[thirdparty/gcc.git] / libbacktrace / pecoff.c
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
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
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
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. */
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_MEAN_AND_LEAN
44 #define WIN32_MEAN_AND_LEAN
45 #endif
46
47 #ifndef NOMINMAX
48 #define NOMINMAX
49 #endif
50
51 #include <windows.h>
52 #endif
53
54 /* Coff file header. */
55
56 typedef struct {
57 uint16_t machine;
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;
64 } b_coff_file_header;
65
66 /* Coff optional header. */
67
68 typedef struct {
69 uint16_t magic;
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;
77 union {
78 struct {
79 uint32_t base_of_data;
80 uint32_t image_base;
81 } pe;
82 struct {
83 uint64_t image_base;
84 } pep;
85 } u;
86 } b_coff_optional_header;
87
88 /* Values of magic in optional header. */
89
90 #define PE_MAGIC 0x10b /* PE32 executable. */
91 #define PEP_MAGIC 0x20b /* PE32+ executable (for 64bit targets). */
92
93 /* Coff section header. */
94
95 typedef struct {
96 char name[8];
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;
107
108 /* Coff symbol name. */
109
110 typedef union {
111 char short_name[8];
112 struct {
113 unsigned char zeroes[4];
114 unsigned char off[4];
115 } long_name;
116 } b_coff_name;
117
118 /* Coff symbol (external representation which is unaligned). */
119
120 typedef struct {
121 b_coff_name name;
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;
128
129 /* Symbol types. */
130
131 #define N_TBSHFT 4 /* Shift for the derived type. */
132 #define IMAGE_SYM_DTYPE_FUNCTION 2 /* Function derived type. */
133
134 /* Size of a coff symbol. */
135
136 #define SYM_SZ 18
137
138 /* Coff symbol, internal representation (aligned). */
139
140 typedef struct {
141 const char *name;
142 uint32_t value;
143 int16_t sec;
144 uint16_t type;
145 uint16_t sc;
146 } b_coff_internal_symbol;
147
148 /* Names of sections, indexed by enum dwarf_section in internal.h. */
149
150 static const char * const debug_section_names[DEBUG_MAX] =
151 {
152 ".debug_info",
153 ".debug_line",
154 ".debug_abbrev",
155 ".debug_ranges",
156 ".debug_str",
157 ".debug_addr",
158 ".debug_str_offsets",
159 ".debug_line_str",
160 ".debug_rnglists"
161 };
162
163 /* Information we gather for the sections we care about. */
164
165 struct debug_section_info
166 {
167 /* Section file offset. */
168 off_t offset;
169 /* Section size. */
170 size_t size;
171 };
172
173 /* Information we keep for an coff symbol. */
174
175 struct coff_symbol
176 {
177 /* The name of the symbol. */
178 const char *name;
179 /* The address of the symbol. */
180 uintptr_t address;
181 };
182
183 /* Information to pass to coff_syminfo. */
184
185 struct coff_syminfo_data
186 {
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. */
192 size_t count;
193 };
194
195 /* A dummy callback function used when we can't find any debug info. */
196
197 static int
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)
202 {
203 error_callback (data, "no debug info in PE/COFF executable", -1);
204 return 0;
205 }
206
207 /* A dummy callback function used when we can't find a symbol
208 table. */
209
210 static void
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)
215 {
216 error_callback (data, "no symbol table in PE/COFF executable", -1);
217 }
218
219 /* Read a potentially unaligned 4 byte word at P, using native endianness. */
220
221 static uint32_t
222 coff_read4 (const unsigned char *p)
223 {
224 uint32_t res;
225
226 memcpy (&res, p, 4);
227 return res;
228 }
229
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. */
233
234 static uint16_t
235 coff_read2 (const unsigned char *p)
236 {
237 uint16_t res;
238
239 memcpy (&res, p, sizeof (res));
240 return res;
241 }
242
243 /* Return the length (without the trailing 0) of a COFF short name. */
244
245 static size_t
246 coff_short_name_len (const char *name)
247 {
248 int i;
249
250 for (i = 0; i < 8; i++)
251 if (name[i] == 0)
252 return i;
253 return 8;
254 }
255
256 /* Return true iff COFF short name CNAME is the same as NAME (a NUL-terminated
257 string). */
258
259 static int
260 coff_short_name_eq (const char *name, const char *cname)
261 {
262 int i;
263
264 for (i = 0; i < 8; i++)
265 {
266 if (name[i] != cname[i])
267 return 0;
268 if (name[i] == 0)
269 return 1;
270 }
271 return name[8] == 0;
272 }
273
274 /* Return true iff NAME is the same as string at offset OFF. */
275
276 static int
277 coff_long_name_eq (const char *name, unsigned int off,
278 struct backtrace_view *str_view)
279 {
280 if (off >= str_view->len)
281 return 0;
282 return strcmp (name, (const char *)str_view->data + off) == 0;
283 }
284
285 /* Compare struct coff_symbol for qsort. */
286
287 static int
288 coff_symbol_compare (const void *v1, const void *v2)
289 {
290 const struct coff_symbol *e1 = (const struct coff_symbol *) v1;
291 const struct coff_symbol *e2 = (const struct coff_symbol *) v2;
292
293 if (e1->address < e2->address)
294 return -1;
295 else if (e1->address > e2->address)
296 return 1;
297 else
298 return 0;
299 }
300
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). */
304
305 static int
306 coff_expand_symbol (b_coff_internal_symbol *isym,
307 const b_coff_external_symbol *sym,
308 uint16_t sects_num,
309 const unsigned char *strtab, size_t strtab_size)
310 {
311 isym->type = coff_read2 (sym->type);
312 isym->sec = coff_read2 (sym->section_number);
313 isym->sc = sym->storage_class;
314
315 if (isym->sec > 0 && (uint16_t) isym->sec > sects_num)
316 return -1;
317 if (sym->name.short_name[0] != 0)
318 isym->name = sym->name.short_name;
319 else
320 {
321 uint32_t off = coff_read4 (sym->name.long_name.off);
322
323 if (off >= strtab_size)
324 return -1;
325 isym->name = (const char *) strtab + off;
326 }
327 return 0;
328 }
329
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). */
333
334 static int
335 coff_is_function_symbol (const b_coff_internal_symbol *isym)
336 {
337 return (isym->type >> N_TBSHFT) == IMAGE_SYM_DTYPE_FUNCTION
338 && isym->sec > 0;
339 }
340
341 /* Initialize the symbol table info for coff_syminfo. */
342
343 static int
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)
351 {
352 size_t syms_count;
353 char *coff_symstr;
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;
359 char *coff_str;
360 size_t i;
361
362 syms_count = syms_size / SYM_SZ;
363
364 /* We only care about function symbols. Count them. Also count size of
365 strings for in-symbol names. */
366 coff_symbol_count = 0;
367 coff_symstr_len = 0;
368 for (i = 0; i < syms_count; ++i)
369 {
370 const b_coff_external_symbol *asym = &syms[i];
371 b_coff_internal_symbol isym;
372
373 if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size) < 0)
374 {
375 error_callback (data, "invalid section or offset in coff symbol", 0);
376 return 0;
377 }
378 if (coff_is_function_symbol (&isym))
379 {
380 ++coff_symbol_count;
381 if (asym->name.short_name[0] != 0)
382 coff_symstr_len += coff_short_name_len (asym->name.short_name) + 1;
383 }
384
385 i += asym->number_of_aux_symbols;
386 }
387
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,
391 data));
392 if (coff_symbols == NULL)
393 return 0;
394
395 /* Allocate memory for symbols strings. */
396 if (coff_symstr_len > 0)
397 {
398 coff_symstr = ((char *)
399 backtrace_alloc (state, coff_symstr_len, error_callback,
400 data));
401 if (coff_symstr == NULL)
402 {
403 backtrace_free (state, coff_symbols, coff_symbol_size,
404 error_callback, data);
405 return 0;
406 }
407 }
408 else
409 coff_symstr = NULL;
410
411 /* Copy symbols. */
412 coff_sym = coff_symbols;
413 coff_str = coff_symstr;
414 for (i = 0; i < syms_count; ++i)
415 {
416 const b_coff_external_symbol *asym = &syms[i];
417 b_coff_internal_symbol isym;
418
419 if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size))
420 {
421 /* Should not fail, as it was already tested in the previous
422 loop. */
423 abort ();
424 }
425 if (coff_is_function_symbol (&isym))
426 {
427 const char *name;
428 int16_t secnum;
429
430 if (asym->name.short_name[0] != 0)
431 {
432 size_t len = coff_short_name_len (isym.name);
433 name = coff_str;
434 memcpy (coff_str, isym.name, len);
435 coff_str[len] = 0;
436 coff_str += len + 1;
437 }
438 else
439 name = isym.name;
440
441 if (!is_64)
442 {
443 /* Strip leading '_'. */
444 if (name[0] == '_')
445 name++;
446 }
447
448 /* Symbol value is section relative, so we need to read the address
449 of its section. */
450 secnum = coff_read2 (asym->section_number);
451
452 coff_sym->name = name;
453 coff_sym->address = (coff_read4 (asym->value)
454 + sects[secnum - 1].virtual_address
455 + base_address);
456 coff_sym++;
457 }
458
459 i += asym->number_of_aux_symbols;
460 }
461
462 /* End of symbols marker. */
463 coff_sym->name = NULL;
464 coff_sym->address = -1;
465
466 backtrace_qsort (coff_symbols, coff_symbol_count,
467 sizeof (struct coff_symbol), coff_symbol_compare);
468
469 sdata->next = NULL;
470 sdata->symbols = coff_symbols;
471 sdata->count = coff_symbol_count;
472
473 return 1;
474 }
475
476 /* Add EDATA to the list in STATE. */
477
478 static void
479 coff_add_syminfo_data (struct backtrace_state *state,
480 struct coff_syminfo_data *sdata)
481 {
482 if (!state->threaded)
483 {
484 struct coff_syminfo_data **pp;
485
486 for (pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
487 *pp != NULL;
488 pp = &(*pp)->next)
489 ;
490 *pp = sdata;
491 }
492 else
493 {
494 while (1)
495 {
496 struct coff_syminfo_data **pp;
497
498 pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
499
500 while (1)
501 {
502 struct coff_syminfo_data *p;
503
504 p = backtrace_atomic_load_pointer (pp);
505
506 if (p == NULL)
507 break;
508
509 pp = &p->next;
510 }
511
512 if (__sync_bool_compare_and_swap (pp, NULL, sdata))
513 break;
514 }
515 }
516 }
517
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
520 entry. */
521
522 static int
523 coff_symbol_search (const void *vkey, const void *ventry)
524 {
525 const uintptr_t *key = (const uintptr_t *) vkey;
526 const struct coff_symbol *entry = (const struct coff_symbol *) ventry;
527 uintptr_t addr;
528
529 addr = *key;
530 if (addr < entry->address)
531 return -1;
532 else if (addr >= entry[1].address)
533 return 1;
534 else
535 return 0;
536 }
537
538 /* Return the symbol name and value for an ADDR. */
539
540 static void
541 coff_syminfo (struct backtrace_state *state, uintptr_t addr,
542 backtrace_syminfo_callback callback,
543 backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
544 void *data)
545 {
546 struct coff_syminfo_data *sdata;
547 struct coff_symbol *sym = NULL;
548
549 if (!state->threaded)
550 {
551 for (sdata = (struct coff_syminfo_data *) state->syminfo_data;
552 sdata != NULL;
553 sdata = sdata->next)
554 {
555 sym = ((struct coff_symbol *)
556 bsearch (&addr, sdata->symbols, sdata->count,
557 sizeof (struct coff_symbol), coff_symbol_search));
558 if (sym != NULL)
559 break;
560 }
561 }
562 else
563 {
564 struct coff_syminfo_data **pp;
565
566 pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
567 while (1)
568 {
569 sdata = backtrace_atomic_load_pointer (pp);
570 if (sdata == NULL)
571 break;
572
573 sym = ((struct coff_symbol *)
574 bsearch (&addr, sdata->symbols, sdata->count,
575 sizeof (struct coff_symbol), coff_symbol_search));
576 if (sym != NULL)
577 break;
578
579 pp = &sdata->next;
580 }
581 }
582
583 if (sym == NULL)
584 callback (data, addr, NULL, 0, 0);
585 else
586 callback (data, addr, sym->name, sym->address, 0);
587 }
588
589 /* Add the backtrace data for one PE/COFF file. Returns 1 on success,
590 0 on failure (in both cases descriptor is closed). */
591
592 static int
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)
596 {
597 struct backtrace_view fhdr_view;
598 off_t fhdr_off;
599 int magic_ok;
600 b_coff_file_header fhdr;
601 off_t opt_sects_off;
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;
609 int str_view_valid;
610 size_t str_size;
611 off_t str_off;
612 struct backtrace_view syms_view;
613 off_t syms_off;
614 size_t syms_size;
615 int syms_view_valid;
616 unsigned int syms_num;
617 unsigned int i;
618 struct debug_section_info sections[DEBUG_MAX];
619 off_t min_offset;
620 off_t max_offset;
621 struct backtrace_view debug_view;
622 int debug_view_valid;
623 int is_64;
624 uintptr_t image_base;
625 uintptr_t base_address = 0;
626 struct dwarf_sections dwarf_sections;
627
628 *found_sym = 0;
629 *found_dwarf = 0;
630
631 sects_view_valid = 0;
632 syms_view_valid = 0;
633 str_view_valid = 0;
634 debug_view_valid = 0;
635
636 /* Map the MS-DOS stub (if any) and extract file header offset. */
637 if (!backtrace_get_view (state, descriptor, 0, 0x40, error_callback,
638 data, &fhdr_view))
639 goto fail;
640
641 {
642 const unsigned char *vptr = fhdr_view.data;
643
644 if (vptr[0] == 'M' && vptr[1] == 'Z')
645 fhdr_off = coff_read4 (vptr + 0x3c);
646 else
647 fhdr_off = 0;
648 }
649
650 backtrace_release_view (state, &fhdr_view, error_callback, data);
651
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))
656 goto fail;
657
658 if (fhdr_off != 0)
659 {
660 const char *magic = (const char *) fhdr_view.data;
661 magic_ok = memcmp (magic, "PE\0", 4) == 0;
662 fhdr_off += 4;
663
664 memcpy (&fhdr, fhdr_view.data + 4, sizeof fhdr);
665 }
666 else
667 {
668 memcpy (&fhdr, fhdr_view.data, sizeof fhdr);
669 /* TODO: test fhdr.machine for coff but non-PE platforms. */
670 magic_ok = 0;
671 }
672 backtrace_release_view (state, &fhdr_view, error_callback, data);
673
674 if (!magic_ok)
675 {
676 error_callback (data, "executable file is not COFF", 0);
677 goto fail;
678 }
679
680 sects_num = fhdr.number_of_sections;
681 syms_num = fhdr.number_of_symbols;
682
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));
686
687 /* To translate PC to file/line when using DWARF, we need to find
688 the .debug_info and .debug_line sections. */
689
690 /* Read the optional header and the section headers. */
691
692 if (!backtrace_get_view (state, descriptor, opt_sects_off, opt_sects_size,
693 error_callback, data, &sects_view))
694 goto fail;
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);
699
700 is_64 = 0;
701 if (fhdr.size_of_optional_header > sizeof (*opt_hdr))
702 {
703 if (opt_hdr->magic == PE_MAGIC)
704 image_base = opt_hdr->u.pe.image_base;
705 else if (opt_hdr->magic == PEP_MAGIC)
706 {
707 image_base = opt_hdr->u.pep.image_base;
708 is_64 = 1;
709 }
710 else
711 {
712 error_callback (data, "bad magic in PE optional header", 0);
713 goto fail;
714 }
715 }
716 else
717 image_base = 0;
718
719 /* Read the symbol table and the string table. */
720
721 if (fhdr.pointer_to_symbol_table == 0)
722 {
723 /* No symbol table, no string table. */
724 str_off = 0;
725 str_size = 0;
726 syms_num = 0;
727 syms_size = 0;
728 }
729 else
730 {
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;
736
737 if (!backtrace_get_view (state, descriptor, syms_off, syms_size + 4,
738 error_callback, data, &syms_view))
739 goto fail;
740 syms_view_valid = 1;
741
742 str_size = coff_read4 (syms_view.data + syms_size);
743
744 str_off = syms_off + syms_size;
745
746 if (str_size > 4)
747 {
748 /* Map string table (including the length word). */
749
750 if (!backtrace_get_view (state, descriptor, str_off, str_size,
751 error_callback, data, &str_view))
752 goto fail;
753 str_view_valid = 1;
754 }
755 }
756
757 memset (sections, 0, sizeof sections);
758
759 /* Look for the symbol table. */
760 for (i = 0; i < sects_num; ++i)
761 {
762 const b_coff_section_header *s = sects + i;
763 unsigned int str_off;
764 int j;
765
766 if (s->name[0] == '/')
767 {
768 /* Extended section name. */
769 str_off = atoi (s->name + 1);
770 }
771 else
772 str_off = 0;
773
774 for (j = 0; j < (int) DEBUG_MAX; ++j)
775 {
776 const char *dbg_name = debug_section_names[j];
777 int match;
778
779 if (str_off != 0)
780 match = coff_long_name_eq (dbg_name, str_off, &str_view);
781 else
782 match = coff_short_name_eq (dbg_name, s->name);
783 if (match)
784 {
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;
788 break;
789 }
790 }
791 }
792
793 if (syms_num != 0)
794 {
795 struct coff_syminfo_data *sdata;
796
797 sdata = ((struct coff_syminfo_data *)
798 backtrace_alloc (state, sizeof *sdata, error_callback, data));
799 if (sdata == NULL)
800 goto fail;
801
802 if (!coff_initialize_syminfo (state, image_base, is_64,
803 sects, sects_num,
804 syms_view.data, syms_size,
805 str_view.data, str_size,
806 error_callback, data, sdata))
807 {
808 backtrace_free (state, sdata, sizeof *sdata, error_callback, data);
809 goto fail;
810 }
811
812 *found_sym = 1;
813
814 coff_add_syminfo_data (state, sdata);
815 }
816
817 backtrace_release_view (state, &sects_view, error_callback, data);
818 sects_view_valid = 0;
819 if (syms_view_valid)
820 {
821 backtrace_release_view (state, &syms_view, error_callback, data);
822 syms_view_valid = 0;
823 }
824
825 /* Read all the debug sections in a single view, since they are
826 probably adjacent in the file. We never release this view. */
827
828 min_offset = 0;
829 max_offset = 0;
830 for (i = 0; i < (int) DEBUG_MAX; ++i)
831 {
832 off_t end;
833
834 if (sections[i].size == 0)
835 continue;
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)
840 max_offset = end;
841 }
842 if (min_offset == 0 || max_offset == 0)
843 {
844 if (!backtrace_close (descriptor, error_callback, data))
845 goto fail;
846 *fileline_fn = coff_nodebug;
847 return 1;
848 }
849
850 if (!backtrace_get_view (state, descriptor, min_offset,
851 max_offset - min_offset,
852 error_callback, data, &debug_view))
853 goto fail;
854 debug_view_valid = 1;
855
856 /* We've read all we need from the executable. */
857 if (!backtrace_close (descriptor, error_callback, data))
858 goto fail;
859 descriptor = -1;
860
861 for (i = 0; i < (int) DEBUG_MAX; ++i)
862 {
863 size_t size = sections[i].size;
864 dwarf_sections.size[i] = size;
865 if (size == 0)
866 dwarf_sections.data[i] = NULL;
867 else
868 dwarf_sections.data[i] = ((const unsigned char *) debug_view.data
869 + (sections[i].offset - min_offset));
870 }
871
872 #ifdef HAVE_WINDOWS_H
873 {
874 uintptr_t module_handle;
875
876 module_handle = (uintptr_t) GetModuleHandle (NULL);
877 base_address = module_handle - image_base;
878 }
879 #endif
880
881 if (!backtrace_dwarf_add (state, base_address, &dwarf_sections,
882 0, /* FIXME: is_bigendian */
883 NULL, /* altlink */
884 error_callback, data, fileline_fn,
885 NULL /* returned fileline_entry */))
886 goto fail;
887
888 *found_dwarf = 1;
889
890 return 1;
891
892 fail:
893 if (sects_view_valid)
894 backtrace_release_view (state, &sects_view, error_callback, data);
895 if (str_view_valid)
896 backtrace_release_view (state, &str_view, error_callback, data);
897 if (syms_view_valid)
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);
903 return 0;
904 }
905
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
908 sections. */
909
910 int
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)
915 {
916 int ret;
917 int found_sym;
918 int found_dwarf;
919 fileline coff_fileline_fn;
920
921 ret = coff_add (state, descriptor, error_callback, data,
922 &coff_fileline_fn, &found_sym, &found_dwarf);
923 if (!ret)
924 return 0;
925
926 if (!state->threaded)
927 {
928 if (found_sym)
929 state->syminfo_fn = coff_syminfo;
930 else if (state->syminfo_fn == NULL)
931 state->syminfo_fn = coff_nosyms;
932 }
933 else
934 {
935 if (found_sym)
936 backtrace_atomic_store_pointer (&state->syminfo_fn, coff_syminfo);
937 else
938 (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
939 coff_nosyms);
940 }
941
942 if (!state->threaded)
943 {
944 if (state->fileline_fn == NULL || state->fileline_fn == coff_nodebug)
945 *fileline_fn = coff_fileline_fn;
946 }
947 else
948 {
949 fileline current_fn;
950
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;
954 }
955
956 return 1;
957 }