pf2 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +22 -2
  3. data/Cargo.lock +186 -17
  4. data/Cargo.toml +1 -1
  5. data/README.md +17 -6
  6. data/Rakefile +8 -0
  7. data/crates/backtrace-sys2/.gitignore +1 -0
  8. data/crates/backtrace-sys2/Cargo.toml +9 -0
  9. data/crates/backtrace-sys2/build.rs +48 -0
  10. data/crates/backtrace-sys2/src/lib.rs +5 -0
  11. data/crates/backtrace-sys2/src/libbacktrace/.gitignore +15 -0
  12. data/crates/backtrace-sys2/src/libbacktrace/Isaac.Newton-Opticks.txt +9286 -0
  13. data/crates/backtrace-sys2/src/libbacktrace/LICENSE +29 -0
  14. data/crates/backtrace-sys2/src/libbacktrace/Makefile.am +623 -0
  15. data/crates/backtrace-sys2/src/libbacktrace/Makefile.in +2666 -0
  16. data/crates/backtrace-sys2/src/libbacktrace/README.md +36 -0
  17. data/crates/backtrace-sys2/src/libbacktrace/aclocal.m4 +864 -0
  18. data/crates/backtrace-sys2/src/libbacktrace/alloc.c +167 -0
  19. data/crates/backtrace-sys2/src/libbacktrace/allocfail.c +136 -0
  20. data/crates/backtrace-sys2/src/libbacktrace/allocfail.sh +104 -0
  21. data/crates/backtrace-sys2/src/libbacktrace/atomic.c +113 -0
  22. data/crates/backtrace-sys2/src/libbacktrace/backtrace-supported.h.in +66 -0
  23. data/crates/backtrace-sys2/src/libbacktrace/backtrace.c +129 -0
  24. data/crates/backtrace-sys2/src/libbacktrace/backtrace.h +189 -0
  25. data/crates/backtrace-sys2/src/libbacktrace/btest.c +501 -0
  26. data/crates/backtrace-sys2/src/libbacktrace/compile +348 -0
  27. data/crates/backtrace-sys2/src/libbacktrace/config/enable.m4 +38 -0
  28. data/crates/backtrace-sys2/src/libbacktrace/config/lead-dot.m4 +31 -0
  29. data/crates/backtrace-sys2/src/libbacktrace/config/libtool.m4 +7436 -0
  30. data/crates/backtrace-sys2/src/libbacktrace/config/ltoptions.m4 +369 -0
  31. data/crates/backtrace-sys2/src/libbacktrace/config/ltsugar.m4 +123 -0
  32. data/crates/backtrace-sys2/src/libbacktrace/config/ltversion.m4 +23 -0
  33. data/crates/backtrace-sys2/src/libbacktrace/config/lt~obsolete.m4 +98 -0
  34. data/crates/backtrace-sys2/src/libbacktrace/config/multi.m4 +68 -0
  35. data/crates/backtrace-sys2/src/libbacktrace/config/override.m4 +117 -0
  36. data/crates/backtrace-sys2/src/libbacktrace/config/unwind_ipinfo.m4 +37 -0
  37. data/crates/backtrace-sys2/src/libbacktrace/config/warnings.m4 +227 -0
  38. data/crates/backtrace-sys2/src/libbacktrace/config.guess +1700 -0
  39. data/crates/backtrace-sys2/src/libbacktrace/config.h.in +182 -0
  40. data/crates/backtrace-sys2/src/libbacktrace/config.sub +1885 -0
  41. data/crates/backtrace-sys2/src/libbacktrace/configure +15740 -0
  42. data/crates/backtrace-sys2/src/libbacktrace/configure.ac +613 -0
  43. data/crates/backtrace-sys2/src/libbacktrace/dwarf.c +4402 -0
  44. data/crates/backtrace-sys2/src/libbacktrace/edtest.c +120 -0
  45. data/crates/backtrace-sys2/src/libbacktrace/edtest2.c +43 -0
  46. data/crates/backtrace-sys2/src/libbacktrace/elf.c +7443 -0
  47. data/crates/backtrace-sys2/src/libbacktrace/fileline.c +407 -0
  48. data/crates/backtrace-sys2/src/libbacktrace/filenames.h +52 -0
  49. data/crates/backtrace-sys2/src/libbacktrace/filetype.awk +13 -0
  50. data/crates/backtrace-sys2/src/libbacktrace/install-debuginfo-for-buildid.sh.in +65 -0
  51. data/crates/backtrace-sys2/src/libbacktrace/install-sh +501 -0
  52. data/crates/backtrace-sys2/src/libbacktrace/instrumented_alloc.c +114 -0
  53. data/crates/backtrace-sys2/src/libbacktrace/internal.h +389 -0
  54. data/crates/backtrace-sys2/src/libbacktrace/libtool.m4 +7436 -0
  55. data/crates/backtrace-sys2/src/libbacktrace/ltmain.sh +8636 -0
  56. data/crates/backtrace-sys2/src/libbacktrace/ltoptions.m4 +369 -0
  57. data/crates/backtrace-sys2/src/libbacktrace/ltsugar.m4 +123 -0
  58. data/crates/backtrace-sys2/src/libbacktrace/ltversion.m4 +23 -0
  59. data/crates/backtrace-sys2/src/libbacktrace/lt~obsolete.m4 +98 -0
  60. data/crates/backtrace-sys2/src/libbacktrace/macho.c +1355 -0
  61. data/crates/backtrace-sys2/src/libbacktrace/missing +215 -0
  62. data/crates/backtrace-sys2/src/libbacktrace/mmap.c +331 -0
  63. data/crates/backtrace-sys2/src/libbacktrace/mmapio.c +110 -0
  64. data/crates/backtrace-sys2/src/libbacktrace/move-if-change +83 -0
  65. data/crates/backtrace-sys2/src/libbacktrace/mtest.c +410 -0
  66. data/crates/backtrace-sys2/src/libbacktrace/nounwind.c +66 -0
  67. data/crates/backtrace-sys2/src/libbacktrace/pecoff.c +957 -0
  68. data/crates/backtrace-sys2/src/libbacktrace/posix.c +104 -0
  69. data/crates/backtrace-sys2/src/libbacktrace/print.c +92 -0
  70. data/crates/backtrace-sys2/src/libbacktrace/read.c +110 -0
  71. data/crates/backtrace-sys2/src/libbacktrace/simple.c +108 -0
  72. data/crates/backtrace-sys2/src/libbacktrace/sort.c +108 -0
  73. data/crates/backtrace-sys2/src/libbacktrace/state.c +72 -0
  74. data/crates/backtrace-sys2/src/libbacktrace/stest.c +137 -0
  75. data/crates/backtrace-sys2/src/libbacktrace/test-driver +148 -0
  76. data/crates/backtrace-sys2/src/libbacktrace/test_format.c +55 -0
  77. data/crates/backtrace-sys2/src/libbacktrace/testlib.c +234 -0
  78. data/crates/backtrace-sys2/src/libbacktrace/testlib.h +110 -0
  79. data/crates/backtrace-sys2/src/libbacktrace/ttest.c +161 -0
  80. data/crates/backtrace-sys2/src/libbacktrace/unittest.c +92 -0
  81. data/crates/backtrace-sys2/src/libbacktrace/unknown.c +65 -0
  82. data/crates/backtrace-sys2/src/libbacktrace/xcoff.c +1606 -0
  83. data/crates/backtrace-sys2/src/libbacktrace/xztest.c +508 -0
  84. data/crates/backtrace-sys2/src/libbacktrace/zstdtest.c +523 -0
  85. data/crates/backtrace-sys2/src/libbacktrace/ztest.c +541 -0
  86. data/ext/pf2/Cargo.toml +1 -0
  87. data/ext/pf2/src/backtrace.rs +126 -0
  88. data/ext/pf2/src/lib.rs +1 -0
  89. data/ext/pf2/src/profile.rs +16 -1
  90. data/ext/pf2/src/profile_serializer.rs +95 -21
  91. data/ext/pf2/src/ringbuffer.rs +7 -0
  92. data/ext/pf2/src/ruby_init.rs +18 -6
  93. data/ext/pf2/src/sample.rs +22 -1
  94. data/ext/pf2/src/signal_scheduler/configuration.rs +7 -0
  95. data/ext/pf2/src/signal_scheduler/timer_installer.rs +34 -27
  96. data/ext/pf2/src/signal_scheduler.rs +95 -26
  97. data/ext/pf2/src/timer_thread_scheduler.rs +88 -12
  98. data/ext/pf2/src/util.rs +2 -2
  99. data/lib/pf2/reporter.rb +12 -5
  100. data/lib/pf2/version.rb +1 -1
  101. data/lib/pf2.rb +3 -6
  102. metadata +96 -2
@@ -0,0 +1,957 @@
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
+ #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
+ }