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