pf2 0.1.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +29 -2
  3. data/Cargo.lock +650 -0
  4. data/Cargo.toml +3 -0
  5. data/README.md +110 -13
  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 +25 -0
  87. data/ext/pf2/build.rs +3 -0
  88. data/ext/pf2/extconf.rb +6 -1
  89. data/ext/pf2/src/backtrace.rs +126 -0
  90. data/ext/pf2/src/lib.rs +15 -0
  91. data/ext/pf2/src/profile.rs +65 -0
  92. data/ext/pf2/src/profile_serializer.rs +204 -0
  93. data/ext/pf2/src/ringbuffer.rs +152 -0
  94. data/ext/pf2/src/ruby_init.rs +74 -0
  95. data/ext/pf2/src/sample.rs +66 -0
  96. data/ext/pf2/src/siginfo_t.c +5 -0
  97. data/ext/pf2/src/signal_scheduler/configuration.rs +31 -0
  98. data/ext/pf2/src/signal_scheduler/timer_installer.rs +199 -0
  99. data/ext/pf2/src/signal_scheduler.rs +311 -0
  100. data/ext/pf2/src/timer_thread_scheduler.rs +319 -0
  101. data/ext/pf2/src/util.rs +30 -0
  102. data/lib/pf2/cli.rb +1 -1
  103. data/lib/pf2/reporter.rb +48 -16
  104. data/lib/pf2/version.rb +1 -1
  105. data/lib/pf2.rb +20 -5
  106. metadata +128 -5
  107. data/ext/pf2/pf2.c +0 -246
@@ -0,0 +1,1606 @@
1
+ /* xcoff.c -- Get debug data from an XCOFF file for backtraces.
2
+ Copyright (C) 2012-2021 Free Software Foundation, Inc.
3
+ Adapted from elf.c.
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 <errno.h>
36
+ #include <stdlib.h>
37
+ #include <string.h>
38
+ #include <sys/types.h>
39
+
40
+ #ifdef HAVE_LOADQUERY
41
+ #include <sys/ldr.h>
42
+ #endif
43
+
44
+ #include "backtrace.h"
45
+ #include "internal.h"
46
+
47
+ /* The configure script must tell us whether we are 32-bit or 64-bit
48
+ XCOFF. We could make this code test and support either possibility,
49
+ but there is no point. This code only works for the currently
50
+ running executable, which means that we know the XCOFF mode at
51
+ configure time. */
52
+
53
+ #if BACKTRACE_XCOFF_SIZE != 32 && BACKTRACE_XCOFF_SIZE != 64
54
+ #error "Unknown BACKTRACE_XCOFF_SIZE"
55
+ #endif
56
+
57
+ /* XCOFF file header. */
58
+
59
+ #if BACKTRACE_XCOFF_SIZE == 32
60
+
61
+ typedef struct {
62
+ uint16_t f_magic;
63
+ uint16_t f_nscns;
64
+ uint32_t f_timdat;
65
+ uint32_t f_symptr;
66
+ uint32_t f_nsyms;
67
+ uint16_t f_opthdr;
68
+ uint16_t f_flags;
69
+ } b_xcoff_filhdr;
70
+
71
+ #define XCOFF_MAGIC 0737
72
+
73
+ #else /* BACKTRACE_XCOFF_SIZE != 32 */
74
+
75
+ typedef struct {
76
+ uint16_t f_magic;
77
+ uint16_t f_nscns;
78
+ uint32_t f_timdat;
79
+ uint64_t f_symptr;
80
+ uint16_t f_opthdr;
81
+ uint16_t f_flags;
82
+ uint32_t f_nsyms;
83
+ } b_xcoff_filhdr;
84
+
85
+ #define XCOFF_MAGIC 0767
86
+
87
+ #endif /* BACKTRACE_XCOFF_SIZE != 32 */
88
+
89
+ #define F_SHROBJ 0x2000 /* File is a shared object. */
90
+
91
+ /* XCOFF section header. */
92
+
93
+ #if BACKTRACE_XCOFF_SIZE == 32
94
+
95
+ typedef struct {
96
+ char s_name[8];
97
+ uint32_t s_paddr;
98
+ uint32_t s_vaddr;
99
+ uint32_t s_size;
100
+ uint32_t s_scnptr;
101
+ uint32_t s_relptr;
102
+ uint32_t s_lnnoptr;
103
+ uint16_t s_nreloc;
104
+ uint16_t s_nlnno;
105
+ uint32_t s_flags;
106
+ } b_xcoff_scnhdr;
107
+
108
+ #define _OVERFLOW_MARKER 65535
109
+
110
+ #else /* BACKTRACE_XCOFF_SIZE != 32 */
111
+
112
+ typedef struct {
113
+ char name[8];
114
+ uint64_t s_paddr;
115
+ uint64_t s_vaddr;
116
+ uint64_t s_size;
117
+ uint64_t s_scnptr;
118
+ uint64_t s_relptr;
119
+ uint64_t s_lnnoptr;
120
+ uint32_t s_nreloc;
121
+ uint32_t s_nlnno;
122
+ uint32_t s_flags;
123
+ } b_xcoff_scnhdr;
124
+
125
+ #endif /* BACKTRACE_XCOFF_SIZE != 32 */
126
+
127
+ #define STYP_DWARF 0x10 /* DWARF debugging section. */
128
+ #define STYP_TEXT 0x20 /* Executable text (code) section. */
129
+ #define STYP_OVRFLO 0x8000 /* Line-number field overflow section. */
130
+
131
+ #define SSUBTYP_DWINFO 0x10000 /* DWARF info section. */
132
+ #define SSUBTYP_DWLINE 0x20000 /* DWARF line-number section. */
133
+ #define SSUBTYP_DWARNGE 0x50000 /* DWARF aranges section. */
134
+ #define SSUBTYP_DWABREV 0x60000 /* DWARF abbreviation section. */
135
+ #define SSUBTYP_DWSTR 0x70000 /* DWARF strings section. */
136
+
137
+ /* XCOFF symbol. */
138
+
139
+ #define SYMNMLEN 8
140
+
141
+ #if BACKTRACE_XCOFF_SIZE == 32
142
+
143
+ typedef struct {
144
+ union {
145
+ char _name[SYMNMLEN];
146
+ struct {
147
+ uint32_t _zeroes;
148
+ uint32_t _offset;
149
+ } _s;
150
+ } _u;
151
+ #define n_name _u._name
152
+ #define n_zeroes _u._s._zeroes
153
+ #define n_offset_ _u._s._offset
154
+
155
+ uint32_t n_value;
156
+ int16_t n_scnum;
157
+ uint16_t n_type;
158
+ uint8_t n_sclass;
159
+ uint8_t n_numaux;
160
+ } __attribute__ ((packed)) b_xcoff_syment;
161
+
162
+ #else /* BACKTRACE_XCOFF_SIZE != 32 */
163
+
164
+ typedef struct {
165
+ uint64_t n_value;
166
+ uint32_t n_offset_;
167
+ int16_t n_scnum;
168
+ uint16_t n_type;
169
+ uint8_t n_sclass;
170
+ uint8_t n_numaux;
171
+ } __attribute__ ((packed)) b_xcoff_syment;
172
+
173
+ #endif /* BACKTRACE_XCOFF_SIZE != 32 */
174
+
175
+ #define SYMESZ 18
176
+
177
+ #define C_EXT 2 /* External symbol. */
178
+ #define C_FCN 101 /* Beginning or end of function. */
179
+ #define C_FILE 103 /* Source file name. */
180
+ #define C_HIDEXT 107 /* Unnamed external symbol. */
181
+ #define C_BINCL 108 /* Beginning of include file. */
182
+ #define C_EINCL 109 /* End of include file. */
183
+ #define C_WEAKEXT 111 /* Weak external symbol. */
184
+
185
+ #define ISFCN(x) ((x) & 0x0020)
186
+
187
+ /* XCOFF AUX entry. */
188
+
189
+ #define AUXESZ 18
190
+ #define FILNMLEN 14
191
+
192
+ typedef union {
193
+ #if BACKTRACE_XCOFF_SIZE == 32
194
+ struct {
195
+ uint16_t pad;
196
+ uint16_t x_lnnohi;
197
+ uint16_t x_lnno;
198
+ } x_block;
199
+ #else
200
+ struct {
201
+ uint32_t x_lnno;
202
+ } x_block;
203
+ #endif
204
+ union {
205
+ char x_fname[FILNMLEN];
206
+ struct {
207
+ uint32_t x_zeroes;
208
+ uint32_t x_offset;
209
+ char pad[FILNMLEN-8];
210
+ uint8_t x_ftype;
211
+ } _x;
212
+ } x_file;
213
+ #if BACKTRACE_XCOFF_SIZE == 32
214
+ struct {
215
+ uint32_t x_exptr;
216
+ uint32_t x_fsize;
217
+ uint32_t x_lnnoptr;
218
+ uint32_t x_endndx;
219
+ } x_fcn;
220
+ #else
221
+ struct {
222
+ uint64_t x_lnnoptr;
223
+ uint32_t x_fsize;
224
+ uint32_t x_endndx;
225
+ } x_fcn;
226
+ #endif
227
+ struct {
228
+ uint8_t pad[AUXESZ-1];
229
+ uint8_t x_auxtype;
230
+ } x_auxtype;
231
+ } __attribute__ ((packed)) b_xcoff_auxent;
232
+
233
+ /* XCOFF line number entry. */
234
+
235
+ #if BACKTRACE_XCOFF_SIZE == 32
236
+
237
+ typedef struct {
238
+ union {
239
+ uint32_t l_symndx;
240
+ uint32_t l_paddr;
241
+ } l_addr;
242
+ uint16_t l_lnno;
243
+ } b_xcoff_lineno;
244
+
245
+ #define LINESZ 6
246
+
247
+ #else /* BACKTRACE_XCOFF_SIZE != 32 */
248
+
249
+ typedef struct {
250
+ union {
251
+ uint32_t l_symndx;
252
+ uint64_t l_paddr;
253
+ } l_addr;
254
+ uint32_t l_lnno;
255
+ } b_xcoff_lineno;
256
+
257
+ #define LINESZ 12
258
+
259
+ #endif /* BACKTRACE_XCOFF_SIZE != 32 */
260
+
261
+ #if BACKTRACE_XCOFF_SIZE == 32
262
+ #define XCOFF_AIX_TEXTBASE 0x10000000u
263
+ #else
264
+ #define XCOFF_AIX_TEXTBASE 0x100000000ul
265
+ #endif
266
+
267
+ /* AIX big archive fixed-length header. */
268
+
269
+ #define AIAMAGBIG "<bigaf>\n"
270
+
271
+ typedef struct {
272
+ char fl_magic[8]; /* Archive magic string. */
273
+ char fl_memoff[20]; /* Offset to member table. */
274
+ char fl_gstoff[20]; /* Offset to global symbol table. */
275
+ char fl_gst64off[20]; /* Offset to global symbol table for 64-bit objects. */
276
+ char fl_fstmoff[20]; /* Offset to first archive member. */
277
+ char fl_freeoff[20]; /* Offset to first member on free list. */
278
+ } b_ar_fl_hdr;
279
+
280
+ /* AIX big archive file member header. */
281
+
282
+ typedef struct {
283
+ char ar_size[20]; /* File member size - decimal. */
284
+ char ar_nxtmem[20]; /* Next member offset - decimal. */
285
+ char ar_prvmem[20]; /* Previous member offset - decimal. */
286
+ char ar_date[12]; /* File member date - decimal. */
287
+ char ar_uid[12]; /* File member userid - decimal. */
288
+ char ar_gid[12]; /* File member group id - decimal. */
289
+ char ar_mode[12]; /* File member mode - octal. */
290
+ char ar_namlen[4]; /* File member name length - decimal. */
291
+ char ar_name[2]; /* Start of member name. */
292
+ } b_ar_hdr;
293
+
294
+
295
+ /* Information we keep for an XCOFF symbol. */
296
+
297
+ struct xcoff_symbol
298
+ {
299
+ /* The name of the symbol. */
300
+ const char *name;
301
+ /* The address of the symbol. */
302
+ uintptr_t address;
303
+ /* The size of the symbol. */
304
+ size_t size;
305
+ };
306
+
307
+ /* Information to pass to xcoff_syminfo. */
308
+
309
+ struct xcoff_syminfo_data
310
+ {
311
+ /* Symbols for the next module. */
312
+ struct xcoff_syminfo_data *next;
313
+ /* The XCOFF symbols, sorted by address. */
314
+ struct xcoff_symbol *symbols;
315
+ /* The number of symbols. */
316
+ size_t count;
317
+ };
318
+
319
+ /* Information about an include file. */
320
+
321
+ struct xcoff_incl
322
+ {
323
+ /* File name. */
324
+ const char *filename;
325
+ /* Offset to first line number from the include file. */
326
+ uintptr_t begin;
327
+ /* Offset to last line number from the include file. */
328
+ uintptr_t end;
329
+ };
330
+
331
+ /* A growable vector of include files information. */
332
+
333
+ struct xcoff_incl_vector
334
+ {
335
+ /* Memory. This is an array of struct xcoff_incl. */
336
+ struct backtrace_vector vec;
337
+ /* Number of include files. */
338
+ size_t count;
339
+ };
340
+
341
+ /* A growable vector of functions information. */
342
+
343
+ struct xcoff_func
344
+ {
345
+ /* PC. */
346
+ uintptr_t pc;
347
+ /* The size of the function. */
348
+ size_t size;
349
+ /* Function name. */
350
+ const char *name;
351
+ /* File name. */
352
+ const char *filename;
353
+ /* Pointer to first lnno entry. */
354
+ uintptr_t lnnoptr;
355
+ /* Base address of containing section. */
356
+ uintptr_t sect_base;
357
+ /* Starting source line number. */
358
+ int lnno;
359
+ };
360
+
361
+ /* A growable vector of function information. This is used while
362
+ reading the function symbols. */
363
+
364
+ struct xcoff_func_vector
365
+ {
366
+ /* Memory. This is an array of struct xcoff_func. */
367
+ struct backtrace_vector vec;
368
+ /* Number of valid mappings. */
369
+ size_t count;
370
+ };
371
+
372
+ /* The information we need to map a PC to a file and line. */
373
+
374
+ struct xcoff_fileline_data
375
+ {
376
+ /* The data for the next file we know about. */
377
+ struct xcoff_fileline_data *next;
378
+ /* Functions information. */
379
+ struct xcoff_func_vector func_vec;
380
+ /* Include files information. */
381
+ struct xcoff_incl_vector incl_vec;
382
+ /* Line numbers information. */
383
+ const unsigned char *linenos;
384
+ size_t linenos_size;
385
+ uint64_t lnnoptr0;
386
+ /* Loader address. */
387
+ uintptr_t base_address;
388
+ };
389
+
390
+ /* Information we gather for the DWARF sections we care about. */
391
+
392
+ struct dwsect_info
393
+ {
394
+ /* Section file offset. */
395
+ off_t offset;
396
+ /* Section size. */
397
+ size_t size;
398
+ /* Section contents, after read from file. */
399
+ const unsigned char *data;
400
+ };
401
+
402
+ /* A dummy callback function used when we can't find any debug info. */
403
+
404
+ static int
405
+ xcoff_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
406
+ uintptr_t pc ATTRIBUTE_UNUSED,
407
+ backtrace_full_callback callback ATTRIBUTE_UNUSED,
408
+ backtrace_error_callback error_callback, void *data)
409
+ {
410
+ error_callback (data, "no debug info in XCOFF executable", -1);
411
+ return 0;
412
+ }
413
+
414
+ /* A dummy callback function used when we can't find a symbol
415
+ table. */
416
+
417
+ static void
418
+ xcoff_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,
419
+ uintptr_t addr ATTRIBUTE_UNUSED,
420
+ backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,
421
+ backtrace_error_callback error_callback, void *data)
422
+ {
423
+ error_callback (data, "no symbol table in XCOFF executable", -1);
424
+ }
425
+
426
+ /* Compare struct xcoff_symbol for qsort. */
427
+
428
+ static int
429
+ xcoff_symbol_compare (const void *v1, const void *v2)
430
+ {
431
+ const struct xcoff_symbol *e1 = (const struct xcoff_symbol *) v1;
432
+ const struct xcoff_symbol *e2 = (const struct xcoff_symbol *) v2;
433
+
434
+ if (e1->address < e2->address)
435
+ return -1;
436
+ else if (e1->address > e2->address)
437
+ return 1;
438
+ else
439
+ return 0;
440
+ }
441
+
442
+ /* Compare an ADDR against an xcoff_symbol for bsearch. */
443
+
444
+ static int
445
+ xcoff_symbol_search (const void *vkey, const void *ventry)
446
+ {
447
+ const uintptr_t *key = (const uintptr_t *) vkey;
448
+ const struct xcoff_symbol *entry = (const struct xcoff_symbol *) ventry;
449
+ uintptr_t addr;
450
+
451
+ addr = *key;
452
+ if (addr < entry->address)
453
+ return -1;
454
+ else if ((entry->size == 0 && addr > entry->address)
455
+ || (entry->size > 0 && addr >= entry->address + entry->size))
456
+ return 1;
457
+ else
458
+ return 0;
459
+ }
460
+
461
+ /* Add XDATA to the list in STATE. */
462
+
463
+ static void
464
+ xcoff_add_syminfo_data (struct backtrace_state *state,
465
+ struct xcoff_syminfo_data *xdata)
466
+ {
467
+ if (!state->threaded)
468
+ {
469
+ struct xcoff_syminfo_data **pp;
470
+
471
+ for (pp = (struct xcoff_syminfo_data **) (void *) &state->syminfo_data;
472
+ *pp != NULL;
473
+ pp = &(*pp)->next)
474
+ ;
475
+ *pp = xdata;
476
+ }
477
+ else
478
+ {
479
+ while (1)
480
+ {
481
+ struct xcoff_syminfo_data **pp;
482
+
483
+ pp = (struct xcoff_syminfo_data **) (void *) &state->syminfo_data;
484
+
485
+ while (1)
486
+ {
487
+ struct xcoff_syminfo_data *p;
488
+
489
+ p = backtrace_atomic_load_pointer (pp);
490
+
491
+ if (p == NULL)
492
+ break;
493
+
494
+ pp = &p->next;
495
+ }
496
+
497
+ if (__sync_bool_compare_and_swap (pp, NULL, xdata))
498
+ break;
499
+ }
500
+ }
501
+ }
502
+
503
+ /* Return the symbol name and value for an ADDR. */
504
+
505
+ static void
506
+ xcoff_syminfo (struct backtrace_state *state ATTRIBUTE_UNUSED, uintptr_t addr,
507
+ backtrace_syminfo_callback callback,
508
+ backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
509
+ void *data)
510
+ {
511
+ struct xcoff_syminfo_data *edata;
512
+ struct xcoff_symbol *sym = NULL;
513
+ const char *name;
514
+
515
+ if (!state->threaded)
516
+ {
517
+ for (edata = (struct xcoff_syminfo_data *) state->syminfo_data;
518
+ edata != NULL;
519
+ edata = edata->next)
520
+ {
521
+ sym = ((struct xcoff_symbol *)
522
+ bsearch (&addr, edata->symbols, edata->count,
523
+ sizeof (struct xcoff_symbol), xcoff_symbol_search));
524
+ if (sym != NULL)
525
+ break;
526
+ }
527
+ }
528
+ else
529
+ {
530
+ struct xcoff_syminfo_data **pp;
531
+
532
+ pp = (struct xcoff_syminfo_data **) (void *) &state->syminfo_data;
533
+ while (1)
534
+ {
535
+ edata = backtrace_atomic_load_pointer (pp);
536
+ if (edata == NULL)
537
+ break;
538
+
539
+ sym = ((struct xcoff_symbol *)
540
+ bsearch (&addr, edata->symbols, edata->count,
541
+ sizeof (struct xcoff_symbol), xcoff_symbol_search));
542
+ if (sym != NULL)
543
+ break;
544
+
545
+ pp = &edata->next;
546
+ }
547
+ }
548
+
549
+ if (sym == NULL)
550
+ callback (data, addr, NULL, 0, 0);
551
+ else
552
+ {
553
+ name = sym->name;
554
+ /* AIX prepends a '.' to function entry points, remove it. */
555
+ if (name && *name == '.')
556
+ ++name;
557
+ callback (data, addr, name, sym->address, sym->size);
558
+ }
559
+ }
560
+
561
+ /* Return the name of an XCOFF symbol. */
562
+
563
+ static const char *
564
+ xcoff_symname (const b_xcoff_syment *asym,
565
+ const unsigned char *strtab, size_t strtab_size)
566
+ {
567
+ #if BACKTRACE_XCOFF_SIZE == 32
568
+ if (asym->n_zeroes != 0)
569
+ {
570
+ /* Make a copy as we will release the symtab view. */
571
+ char name[SYMNMLEN+1];
572
+ strncpy (name, asym->n_name, SYMNMLEN);
573
+ name[SYMNMLEN] = '\0';
574
+ return strdup (name);
575
+ }
576
+ #endif
577
+ if (asym->n_sclass & 0x80)
578
+ return NULL; /* .debug */
579
+ if (asym->n_offset_ >= strtab_size)
580
+ return NULL;
581
+ return (const char *) strtab + asym->n_offset_;
582
+ }
583
+
584
+ /* Initialize the symbol table info for xcoff_syminfo. */
585
+
586
+ static int
587
+ xcoff_initialize_syminfo (struct backtrace_state *state,
588
+ uintptr_t base_address,
589
+ const b_xcoff_scnhdr *sects,
590
+ const b_xcoff_syment *syms, size_t nsyms,
591
+ const unsigned char *strtab, size_t strtab_size,
592
+ backtrace_error_callback error_callback, void *data,
593
+ struct xcoff_syminfo_data *sdata)
594
+ {
595
+ size_t xcoff_symbol_count;
596
+ size_t xcoff_symbol_size;
597
+ struct xcoff_symbol *xcoff_symbols;
598
+ size_t i;
599
+ unsigned int j;
600
+
601
+ /* We only care about function symbols. Count them. */
602
+ xcoff_symbol_count = 0;
603
+ for (i = 0; i < nsyms; ++i)
604
+ {
605
+ const b_xcoff_syment *asym = &syms[i];
606
+ if ((asym->n_sclass == C_EXT || asym->n_sclass == C_HIDEXT
607
+ || asym->n_sclass == C_WEAKEXT)
608
+ && ISFCN (asym->n_type) && asym->n_numaux > 0 && asym->n_scnum > 0)
609
+ ++xcoff_symbol_count;
610
+
611
+ i += asym->n_numaux;
612
+ }
613
+
614
+ xcoff_symbol_size = xcoff_symbol_count * sizeof (struct xcoff_symbol);
615
+ xcoff_symbols = ((struct xcoff_symbol *)
616
+ backtrace_alloc (state, xcoff_symbol_size, error_callback,
617
+ data));
618
+ if (xcoff_symbols == NULL)
619
+ return 0;
620
+
621
+ j = 0;
622
+ for (i = 0; i < nsyms; ++i)
623
+ {
624
+ const b_xcoff_syment *asym = &syms[i];
625
+ if ((asym->n_sclass == C_EXT || asym->n_sclass == C_HIDEXT
626
+ || asym->n_sclass == C_WEAKEXT)
627
+ && ISFCN (asym->n_type) && asym->n_numaux > 0 && asym->n_scnum > 0)
628
+ {
629
+ const b_xcoff_auxent *aux = (const b_xcoff_auxent *) (asym + 1);
630
+ xcoff_symbols[j].name = xcoff_symname (asym, strtab, strtab_size);
631
+ xcoff_symbols[j].address = base_address + asym->n_value
632
+ - sects[asym->n_scnum - 1].s_paddr;
633
+ /* x_fsize will be 0 if there is no debug information. */
634
+ xcoff_symbols[j].size = aux->x_fcn.x_fsize;
635
+ ++j;
636
+ }
637
+
638
+ i += asym->n_numaux;
639
+ }
640
+
641
+ backtrace_qsort (xcoff_symbols, xcoff_symbol_count,
642
+ sizeof (struct xcoff_symbol), xcoff_symbol_compare);
643
+
644
+ sdata->next = NULL;
645
+ sdata->symbols = xcoff_symbols;
646
+ sdata->count = xcoff_symbol_count;
647
+
648
+ return 1;
649
+ }
650
+
651
+ /* Compare struct xcoff_func for qsort. */
652
+
653
+ static int
654
+ xcoff_func_compare (const void *v1, const void *v2)
655
+ {
656
+ const struct xcoff_func *fn1 = (const struct xcoff_func *) v1;
657
+ const struct xcoff_func *fn2 = (const struct xcoff_func *) v2;
658
+
659
+ if (fn1->pc < fn2->pc)
660
+ return -1;
661
+ else if (fn1->pc > fn2->pc)
662
+ return 1;
663
+ else
664
+ return 0;
665
+ }
666
+
667
+ /* Compare a PC against an xcoff_func for bsearch. */
668
+
669
+ static int
670
+ xcoff_func_search (const void *vkey, const void *ventry)
671
+ {
672
+ const uintptr_t *key = (const uintptr_t *) vkey;
673
+ const struct xcoff_func *entry = (const struct xcoff_func *) ventry;
674
+ uintptr_t pc;
675
+
676
+ pc = *key;
677
+ if (pc < entry->pc)
678
+ return -1;
679
+ else if ((entry->size == 0 && pc > entry->pc)
680
+ || (entry->size > 0 && pc >= entry->pc + entry->size))
681
+ return 1;
682
+ else
683
+ return 0;
684
+ }
685
+
686
+ /* Compare struct xcoff_incl for qsort. */
687
+
688
+ static int
689
+ xcoff_incl_compare (const void *v1, const void *v2)
690
+ {
691
+ const struct xcoff_incl *in1 = (const struct xcoff_incl *) v1;
692
+ const struct xcoff_incl *in2 = (const struct xcoff_incl *) v2;
693
+
694
+ if (in1->begin < in2->begin)
695
+ return -1;
696
+ else if (in1->begin > in2->begin)
697
+ return 1;
698
+ else
699
+ return 0;
700
+ }
701
+
702
+ /* Find a lnnoptr in an include file. */
703
+
704
+ static int
705
+ xcoff_incl_search (const void *vkey, const void *ventry)
706
+ {
707
+ const uintptr_t *key = (const uintptr_t *) vkey;
708
+ const struct xcoff_incl *entry = (const struct xcoff_incl *) ventry;
709
+ uintptr_t lnno;
710
+
711
+ lnno = *key;
712
+ if (lnno < entry->begin)
713
+ return -1;
714
+ else if (lnno > entry->end)
715
+ return 1;
716
+ else
717
+ return 0;
718
+ }
719
+
720
+ /* Look for a PC in the function vector for one module. On success,
721
+ call CALLBACK and return whatever it returns. On error, call
722
+ ERROR_CALLBACK and return 0. Sets *FOUND to 1 if the PC is found,
723
+ 0 if not. */
724
+
725
+ static int
726
+ xcoff_lookup_pc (struct backtrace_state *state ATTRIBUTE_UNUSED,
727
+ struct xcoff_fileline_data *fdata, uintptr_t pc,
728
+ backtrace_full_callback callback,
729
+ backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
730
+ void *data, int *found)
731
+ {
732
+ const struct xcoff_incl *incl, *bincl;
733
+ const struct xcoff_func *fn;
734
+ const b_xcoff_lineno *lineno;
735
+ const unsigned char *lineptr;
736
+ const char *function;
737
+ const char *filename;
738
+ uintptr_t lnnoptr, match;
739
+ uint32_t lnno = 0;
740
+
741
+ *found = 1;
742
+
743
+ if ((pc & 3) != 0)
744
+ ++pc;
745
+
746
+ /* Find the function first. */
747
+ fn = ((struct xcoff_func *)
748
+ bsearch (&pc, fdata->func_vec.vec.base, fdata->func_vec.count,
749
+ sizeof (struct xcoff_func), xcoff_func_search));
750
+ if (fn == NULL)
751
+ {
752
+ *found = 0;
753
+ return 0;
754
+ }
755
+
756
+ filename = fn->filename;
757
+
758
+ /* Find the line number next. */
759
+
760
+ /* Skip first entry that points to symtab. */
761
+ lnnoptr = fn->lnnoptr + LINESZ;
762
+ match = lnnoptr;
763
+
764
+ lineptr = fdata->linenos + (lnnoptr - fdata->lnnoptr0);
765
+ while (lineptr + LINESZ <= fdata->linenos + fdata->linenos_size)
766
+ {
767
+ lineno = (const b_xcoff_lineno *) lineptr;
768
+ if (lineno->l_lnno == 0)
769
+ break;
770
+ if (pc <= fdata->base_address + lineno->l_addr.l_paddr - fn->sect_base)
771
+ break;
772
+ match = lnnoptr;
773
+ lnno = lineno->l_lnno;
774
+
775
+ lnnoptr += LINESZ;
776
+ lineptr += LINESZ;
777
+ }
778
+
779
+ /* If part of a function other than the beginning comes from an
780
+ include file, the line numbers are absolute, rather than
781
+ relative to the beginning of the function. */
782
+ incl = ((struct xcoff_incl *)
783
+ bsearch (&match, fdata->incl_vec.vec.base,
784
+ fdata->incl_vec.count, sizeof (struct xcoff_incl),
785
+ xcoff_incl_search));
786
+ if (incl != NULL)
787
+ {
788
+ bincl = ((struct xcoff_incl *)
789
+ bsearch (&fn->lnnoptr, fdata->incl_vec.vec.base,
790
+ fdata->incl_vec.count, sizeof (struct xcoff_incl),
791
+ xcoff_incl_search));
792
+ if (bincl != NULL && strcmp (incl->filename, bincl->filename) == 0)
793
+ {
794
+ lnno += fn->lnno - 1;
795
+ }
796
+ filename = incl->filename;
797
+ }
798
+ else
799
+ {
800
+ lnno += fn->lnno - 1;
801
+ }
802
+
803
+ function = fn->name;
804
+ /* AIX prepends a '.' to function entry points, remove it. */
805
+ if (function != NULL && *function == '.')
806
+ ++function;
807
+ return callback (data, pc, filename, lnno, function);
808
+ }
809
+
810
+ /* Return the file/line information for a PC using the XCOFF lineno
811
+ mapping we built earlier. */
812
+
813
+ static int
814
+ xcoff_fileline (struct backtrace_state *state, uintptr_t pc,
815
+ backtrace_full_callback callback,
816
+ backtrace_error_callback error_callback, void *data)
817
+
818
+ {
819
+ struct xcoff_fileline_data *fdata;
820
+ int found;
821
+ int ret;
822
+
823
+ if (!state->threaded)
824
+ {
825
+ for (fdata = (struct xcoff_fileline_data *) state->fileline_data;
826
+ fdata != NULL;
827
+ fdata = fdata->next)
828
+ {
829
+ ret = xcoff_lookup_pc (state, fdata, pc, callback, error_callback,
830
+ data, &found);
831
+ if (ret != 0 || found)
832
+ return ret;
833
+ }
834
+ }
835
+ else
836
+ {
837
+ struct xcoff_fileline_data **pp;
838
+
839
+ pp = (struct xcoff_fileline_data **) (void *) &state->fileline_data;
840
+ while (1)
841
+ {
842
+ fdata = backtrace_atomic_load_pointer (pp);
843
+ if (fdata == NULL)
844
+ break;
845
+
846
+ ret = xcoff_lookup_pc (state, fdata, pc, callback, error_callback,
847
+ data, &found);
848
+ if (ret != 0 || found)
849
+ return ret;
850
+
851
+ pp = &fdata->next;
852
+ }
853
+ }
854
+
855
+ /* FIXME: See if any libraries have been dlopen'ed. */
856
+
857
+ return callback (data, pc, NULL, 0, NULL);
858
+ }
859
+
860
+ /* Initialize the function vector info for xcoff_fileline. */
861
+
862
+ static int
863
+ xcoff_initialize_fileline (struct backtrace_state *state,
864
+ uintptr_t base_address,
865
+ const b_xcoff_scnhdr *sects,
866
+ const b_xcoff_syment *syms, size_t nsyms,
867
+ const unsigned char *strtab, size_t strtab_size,
868
+ const unsigned char *linenos, size_t linenos_size,
869
+ uint64_t lnnoptr0,
870
+ backtrace_error_callback error_callback, void *data)
871
+ {
872
+ struct xcoff_fileline_data *fdata;
873
+ struct xcoff_func *fn;
874
+ const b_xcoff_syment *fsym;
875
+ const b_xcoff_auxent *aux;
876
+ const char *filename;
877
+ const char *name;
878
+ struct xcoff_incl *incl;
879
+ uintptr_t begin, end;
880
+ uintptr_t lnno, lnnoptr;
881
+ uint32_t fsize;
882
+ size_t i;
883
+
884
+ fdata = ((struct xcoff_fileline_data *)
885
+ backtrace_alloc (state, sizeof (struct xcoff_fileline_data),
886
+ error_callback, data));
887
+ if (fdata == NULL)
888
+ return 0;
889
+ memset (fdata, 0, sizeof *fdata);
890
+ fdata->base_address = base_address;
891
+ fdata->linenos = linenos;
892
+ fdata->linenos_size = linenos_size;
893
+ fdata->lnnoptr0 = lnnoptr0;
894
+
895
+ begin = 0;
896
+ filename = NULL;
897
+ fsym = NULL;
898
+ lnnoptr = 0;
899
+ fsize = 0;
900
+ for (i = 0; i < nsyms; ++i)
901
+ {
902
+ const b_xcoff_syment *asym = &syms[i];
903
+
904
+ switch (asym->n_sclass)
905
+ {
906
+ case C_BINCL:
907
+ begin = asym->n_value;
908
+ break;
909
+
910
+ case C_EINCL:
911
+ if (begin == 0)
912
+ break;
913
+ end = asym->n_value;
914
+ incl = ((struct xcoff_incl *)
915
+ backtrace_vector_grow (state, sizeof (struct xcoff_incl),
916
+ error_callback, data,
917
+ &fdata->incl_vec.vec));
918
+ if (incl != NULL)
919
+ {
920
+ incl->filename = xcoff_symname (asym, strtab, strtab_size);
921
+ incl->begin = begin;
922
+ incl->end = end;
923
+ ++fdata->incl_vec.count;
924
+ }
925
+ begin = 0;
926
+ break;
927
+
928
+ case C_FILE:
929
+ filename = xcoff_symname (asym, strtab, strtab_size);
930
+ if (filename == NULL)
931
+ break;
932
+
933
+ /* If the file auxiliary entry is not used, the symbol name is
934
+ the name of the source file. If the file auxiliary entry is
935
+ used, then the symbol name should be .file, and the first
936
+ file auxiliary entry (by convention) contains the source
937
+ file name. */
938
+
939
+ if (asym->n_numaux > 0 && strcmp (filename, ".file") == 0)
940
+ {
941
+ aux = (const b_xcoff_auxent *) (asym + 1);
942
+ if (aux->x_file._x.x_zeroes != 0)
943
+ {
944
+ /* Make a copy as we will release the symtab view. */
945
+ char name[FILNMLEN+1];
946
+ strncpy (name, aux->x_file.x_fname, FILNMLEN);
947
+ name[FILNMLEN] = '\0';
948
+ filename = strdup (name);
949
+ }
950
+ else if (aux->x_file._x.x_offset < strtab_size)
951
+ filename = (const char *) strtab + aux->x_file._x.x_offset;
952
+ else
953
+ filename = NULL;
954
+ }
955
+ break;
956
+
957
+ case C_EXT:
958
+ case C_HIDEXT:
959
+ case C_WEAKEXT:
960
+ fsym = NULL;
961
+ lnnoptr = 0;
962
+ fsize = 0;
963
+ if (!ISFCN (asym->n_type) || asym->n_numaux == 0
964
+ || asym->n_scnum <= 0)
965
+ break;
966
+ if (filename == NULL)
967
+ break;
968
+ aux = (const b_xcoff_auxent *) (asym + 1);
969
+ lnnoptr = aux->x_fcn.x_lnnoptr;
970
+ if (lnnoptr < lnnoptr0
971
+ || lnnoptr + LINESZ > lnnoptr0 + linenos_size)
972
+ break;
973
+ /* x_fsize will be 0 if there is no debug information. */
974
+ fsize = aux->x_fcn.x_fsize;
975
+ fsym = asym;
976
+ break;
977
+
978
+ case C_FCN:
979
+ if (asym->n_numaux == 0)
980
+ break;
981
+ if (fsym == NULL)
982
+ break;
983
+ name = xcoff_symname (asym, strtab, strtab_size);
984
+ if (name == NULL || strcmp (name, ".bf") != 0)
985
+ {
986
+ fsym = NULL;
987
+ break;
988
+ }
989
+ aux = (const b_xcoff_auxent *) (asym + 1);
990
+ #if BACKTRACE_XCOFF_SIZE == 32
991
+ lnno = (uint32_t) aux->x_block.x_lnnohi << 16
992
+ | aux->x_block.x_lnno;
993
+ #else
994
+ lnno = aux->x_block.x_lnno;
995
+ #endif
996
+ fn = ((struct xcoff_func *)
997
+ backtrace_vector_grow (state, sizeof (struct xcoff_func),
998
+ error_callback, data,
999
+ &fdata->func_vec.vec));
1000
+ if (fn == NULL)
1001
+ break;
1002
+ fn->name = xcoff_symname (fsym, strtab, strtab_size);
1003
+ fn->filename = filename;
1004
+ fn->sect_base = sects[fsym->n_scnum - 1].s_paddr;
1005
+ fn->pc = base_address + fsym->n_value - fn->sect_base;
1006
+ fn->size = fsize;
1007
+ fn->lnno = lnno;
1008
+ fn->lnnoptr = lnnoptr;
1009
+ ++fdata->func_vec.count;
1010
+ break;
1011
+ }
1012
+
1013
+ i += asym->n_numaux;
1014
+ }
1015
+
1016
+ if (!backtrace_vector_release (state, &fdata->func_vec.vec, error_callback,
1017
+ data))
1018
+ goto fail;
1019
+ backtrace_qsort (fdata->func_vec.vec.base, fdata->func_vec.count,
1020
+ sizeof (struct xcoff_func), xcoff_func_compare);
1021
+
1022
+ if (!backtrace_vector_release (state, &fdata->incl_vec.vec, error_callback,
1023
+ data))
1024
+ goto fail;
1025
+ backtrace_qsort (fdata->incl_vec.vec.base, fdata->incl_vec.count,
1026
+ sizeof (struct xcoff_incl), xcoff_incl_compare);
1027
+
1028
+ if (!state->threaded)
1029
+ {
1030
+ struct xcoff_fileline_data **pp;
1031
+
1032
+ for (pp = (struct xcoff_fileline_data **) (void *) &state->fileline_data;
1033
+ *pp != NULL;
1034
+ pp = &(*pp)->next)
1035
+ ;
1036
+ *pp = fdata;
1037
+ }
1038
+ else
1039
+ {
1040
+ while (1)
1041
+ {
1042
+ struct xcoff_fileline_data **pp;
1043
+
1044
+ pp = (struct xcoff_fileline_data **) (void *) &state->fileline_data;
1045
+
1046
+ while (1)
1047
+ {
1048
+ struct xcoff_fileline_data *p;
1049
+
1050
+ p = backtrace_atomic_load_pointer (pp);
1051
+
1052
+ if (p == NULL)
1053
+ break;
1054
+
1055
+ pp = &p->next;
1056
+ }
1057
+
1058
+ if (__sync_bool_compare_and_swap (pp, NULL, fdata))
1059
+ break;
1060
+ }
1061
+ }
1062
+
1063
+ return 1;
1064
+
1065
+ fail:
1066
+ return 0;
1067
+ }
1068
+
1069
+ /* Add the backtrace data for one XCOFF file. Returns 1 on success,
1070
+ 0 on failure (in both cases descriptor is closed). */
1071
+
1072
+ static int
1073
+ xcoff_add (struct backtrace_state *state, int descriptor, off_t offset,
1074
+ uintptr_t base_address, backtrace_error_callback error_callback,
1075
+ void *data, fileline *fileline_fn, int *found_sym, int exe)
1076
+ {
1077
+ struct backtrace_view fhdr_view;
1078
+ struct backtrace_view sects_view;
1079
+ struct backtrace_view linenos_view;
1080
+ struct backtrace_view syms_view;
1081
+ struct backtrace_view str_view;
1082
+ struct backtrace_view dwarf_view;
1083
+ b_xcoff_filhdr fhdr;
1084
+ const b_xcoff_scnhdr *sects;
1085
+ const b_xcoff_scnhdr *stext;
1086
+ uint64_t lnnoptr;
1087
+ uint32_t nlnno;
1088
+ off_t str_off;
1089
+ off_t min_offset;
1090
+ off_t max_offset;
1091
+ struct dwsect_info dwsect[DEBUG_MAX];
1092
+ size_t sects_size;
1093
+ size_t syms_size;
1094
+ int32_t str_size;
1095
+ int sects_view_valid;
1096
+ int linenos_view_valid;
1097
+ int syms_view_valid;
1098
+ int str_view_valid;
1099
+ int dwarf_view_valid;
1100
+ int magic_ok;
1101
+ int i;
1102
+ struct dwarf_sections dwarf_sections;
1103
+
1104
+ *found_sym = 0;
1105
+
1106
+ sects_view_valid = 0;
1107
+ linenos_view_valid = 0;
1108
+ syms_view_valid = 0;
1109
+ str_view_valid = 0;
1110
+ dwarf_view_valid = 0;
1111
+
1112
+ str_size = 0;
1113
+
1114
+ /* Map the XCOFF file header. */
1115
+ if (!backtrace_get_view (state, descriptor, offset, sizeof (b_xcoff_filhdr),
1116
+ error_callback, data, &fhdr_view))
1117
+ goto fail;
1118
+
1119
+ memcpy (&fhdr, fhdr_view.data, sizeof fhdr);
1120
+ magic_ok = (fhdr.f_magic == XCOFF_MAGIC);
1121
+
1122
+ backtrace_release_view (state, &fhdr_view, error_callback, data);
1123
+
1124
+ if (!magic_ok)
1125
+ {
1126
+ if (exe)
1127
+ error_callback (data, "executable file is not XCOFF", 0);
1128
+ goto fail;
1129
+ }
1130
+
1131
+ /* Verify object is of expected type. */
1132
+ if ((exe && (fhdr.f_flags & F_SHROBJ))
1133
+ || (!exe && !(fhdr.f_flags & F_SHROBJ)))
1134
+ goto fail;
1135
+
1136
+ /* Read the section headers. */
1137
+
1138
+ sects_size = fhdr.f_nscns * sizeof (b_xcoff_scnhdr);
1139
+
1140
+ if (!backtrace_get_view (state, descriptor,
1141
+ offset + sizeof (fhdr) + fhdr.f_opthdr,
1142
+ sects_size, error_callback, data, &sects_view))
1143
+ goto fail;
1144
+ sects_view_valid = 1;
1145
+ sects = (const b_xcoff_scnhdr *) sects_view.data;
1146
+
1147
+ /* FIXME: assumes only one .text section. */
1148
+ for (i = 0; i < fhdr.f_nscns; ++i)
1149
+ if ((sects[i].s_flags & 0xffff) == STYP_TEXT)
1150
+ break;
1151
+ if (i == fhdr.f_nscns)
1152
+ goto fail;
1153
+
1154
+ stext = &sects[i];
1155
+
1156
+ /* AIX ldinfo_textorg includes the XCOFF headers. */
1157
+ base_address = (exe ? XCOFF_AIX_TEXTBASE : base_address) + stext->s_scnptr;
1158
+
1159
+ lnnoptr = stext->s_lnnoptr;
1160
+ nlnno = stext->s_nlnno;
1161
+
1162
+ #if BACKTRACE_XCOFF_SIZE == 32
1163
+ if (nlnno == _OVERFLOW_MARKER)
1164
+ {
1165
+ int sntext = i + 1;
1166
+ /* Find the matching .ovrflo section. */
1167
+ for (i = 0; i < fhdr.f_nscns; ++i)
1168
+ {
1169
+ if (((sects[i].s_flags & 0xffff) == STYP_OVRFLO)
1170
+ && sects[i].s_nlnno == sntext)
1171
+ {
1172
+ nlnno = sects[i].s_vaddr;
1173
+ break;
1174
+ }
1175
+ }
1176
+ }
1177
+ #endif
1178
+
1179
+ /* Read the symbol table and the string table. */
1180
+
1181
+ if (fhdr.f_symptr != 0)
1182
+ {
1183
+ struct xcoff_syminfo_data *sdata;
1184
+
1185
+ /* Symbol table is followed by the string table. The string table
1186
+ starts with its length (on 4 bytes).
1187
+ Map the symbol table and the length of the string table. */
1188
+ syms_size = fhdr.f_nsyms * sizeof (b_xcoff_syment);
1189
+
1190
+ if (!backtrace_get_view (state, descriptor, offset + fhdr.f_symptr,
1191
+ syms_size + 4, error_callback, data,
1192
+ &syms_view))
1193
+ goto fail;
1194
+ syms_view_valid = 1;
1195
+
1196
+ memcpy (&str_size, syms_view.data + syms_size, 4);
1197
+
1198
+ str_off = fhdr.f_symptr + syms_size;
1199
+
1200
+ if (str_size > 4)
1201
+ {
1202
+ /* Map string table (including the length word). */
1203
+
1204
+ if (!backtrace_get_view (state, descriptor, offset + str_off,
1205
+ str_size, error_callback, data, &str_view))
1206
+ goto fail;
1207
+ str_view_valid = 1;
1208
+ }
1209
+
1210
+ sdata = ((struct xcoff_syminfo_data *)
1211
+ backtrace_alloc (state, sizeof *sdata, error_callback, data));
1212
+ if (sdata == NULL)
1213
+ goto fail;
1214
+
1215
+ if (!xcoff_initialize_syminfo (state, base_address, sects,
1216
+ syms_view.data, fhdr.f_nsyms,
1217
+ str_view.data, str_size,
1218
+ error_callback, data, sdata))
1219
+ {
1220
+ backtrace_free (state, sdata, sizeof *sdata, error_callback, data);
1221
+ goto fail;
1222
+ }
1223
+
1224
+ *found_sym = 1;
1225
+
1226
+ xcoff_add_syminfo_data (state, sdata);
1227
+ }
1228
+
1229
+ /* Read all the DWARF sections in a single view, since they are
1230
+ probably adjacent in the file. We never release this view. */
1231
+
1232
+ min_offset = 0;
1233
+ max_offset = 0;
1234
+ memset (dwsect, 0, sizeof dwsect);
1235
+ for (i = 0; i < fhdr.f_nscns; ++i)
1236
+ {
1237
+ off_t end;
1238
+ int idx;
1239
+
1240
+ if ((sects[i].s_flags & 0xffff) != STYP_DWARF
1241
+ || sects[i].s_size == 0)
1242
+ continue;
1243
+ /* Map DWARF section to array index. */
1244
+ switch (sects[i].s_flags & 0xffff0000)
1245
+ {
1246
+ case SSUBTYP_DWINFO:
1247
+ idx = DEBUG_INFO;
1248
+ break;
1249
+ case SSUBTYP_DWLINE:
1250
+ idx = DEBUG_LINE;
1251
+ break;
1252
+ case SSUBTYP_DWABREV:
1253
+ idx = DEBUG_ABBREV;
1254
+ break;
1255
+ case SSUBTYP_DWARNGE:
1256
+ idx = DEBUG_RANGES;
1257
+ break;
1258
+ case SSUBTYP_DWSTR:
1259
+ idx = DEBUG_STR;
1260
+ break;
1261
+ default:
1262
+ continue;
1263
+ }
1264
+ if (min_offset == 0 || (off_t) sects[i].s_scnptr < min_offset)
1265
+ min_offset = sects[i].s_scnptr;
1266
+ end = sects[i].s_scnptr + sects[i].s_size;
1267
+ if (end > max_offset)
1268
+ max_offset = end;
1269
+ dwsect[idx].offset = sects[i].s_scnptr;
1270
+ dwsect[idx].size = sects[i].s_size;
1271
+ }
1272
+ if (min_offset != 0 && max_offset != 0)
1273
+ {
1274
+ if (!backtrace_get_view (state, descriptor, offset + min_offset,
1275
+ max_offset - min_offset,
1276
+ error_callback, data, &dwarf_view))
1277
+ goto fail;
1278
+ dwarf_view_valid = 1;
1279
+
1280
+ for (i = 0; i < (int) DEBUG_MAX; ++i)
1281
+ {
1282
+ if (dwsect[i].offset == 0)
1283
+ dwsect[i].data = NULL;
1284
+ else
1285
+ dwsect[i].data = ((const unsigned char *) dwarf_view.data
1286
+ + (dwsect[i].offset - min_offset));
1287
+ }
1288
+
1289
+ memset (&dwarf_sections, 0, sizeof dwarf_sections);
1290
+
1291
+ dwarf_sections.data[DEBUG_INFO] = dwsect[DEBUG_INFO].data;
1292
+ dwarf_sections.size[DEBUG_INFO] = dwsect[DEBUG_INFO].size;
1293
+ #if BACKTRACE_XCOFF_SIZE == 32
1294
+ /* XXX workaround for broken lineoff */
1295
+ dwarf_sections.data[DEBUG_LINE] = dwsect[DEBUG_LINE].data - 4;
1296
+ #else
1297
+ /* XXX workaround for broken lineoff */
1298
+ dwarf_sections.data[DEBUG_LINE] = dwsect[DEBUG_LINE].data - 12;
1299
+ #endif
1300
+ dwarf_sections.size[DEBUG_LINE] = dwsect[DEBUG_LINE].size;
1301
+ dwarf_sections.data[DEBUG_ABBREV] = dwsect[DEBUG_ABBREV].data;
1302
+ dwarf_sections.size[DEBUG_ABBREV] = dwsect[DEBUG_ABBREV].size;
1303
+ dwarf_sections.data[DEBUG_RANGES] = dwsect[DEBUG_RANGES].data;
1304
+ dwarf_sections.size[DEBUG_RANGES] = dwsect[DEBUG_RANGES].size;
1305
+ dwarf_sections.data[DEBUG_STR] = dwsect[DEBUG_STR].data;
1306
+ dwarf_sections.size[DEBUG_STR] = dwsect[DEBUG_STR].size;
1307
+
1308
+ if (!backtrace_dwarf_add (state, 0, &dwarf_sections,
1309
+ 1, /* big endian */
1310
+ NULL, /* altlink */
1311
+ error_callback, data, fileline_fn,
1312
+ NULL /* returned fileline_entry */))
1313
+ goto fail;
1314
+ }
1315
+
1316
+ /* Read the XCOFF line number entries if DWARF sections not found. */
1317
+
1318
+ if (!dwarf_view_valid && fhdr.f_symptr != 0 && lnnoptr != 0)
1319
+ {
1320
+ size_t linenos_size = (size_t) nlnno * LINESZ;
1321
+
1322
+ /* We never release this view. */
1323
+ if (!backtrace_get_view (state, descriptor, offset + lnnoptr,
1324
+ linenos_size,
1325
+ error_callback, data, &linenos_view))
1326
+ goto fail;
1327
+ linenos_view_valid = 1;
1328
+
1329
+ if (xcoff_initialize_fileline (state, base_address, sects,
1330
+ syms_view.data, fhdr.f_nsyms,
1331
+ str_view.data, str_size,
1332
+ linenos_view.data, linenos_size,
1333
+ lnnoptr, error_callback, data))
1334
+ *fileline_fn = xcoff_fileline;
1335
+ }
1336
+
1337
+ backtrace_release_view (state, &sects_view, error_callback, data);
1338
+ sects_view_valid = 0;
1339
+ if (syms_view_valid)
1340
+ backtrace_release_view (state, &syms_view, error_callback, data);
1341
+ syms_view_valid = 0;
1342
+
1343
+ /* We've read all we need from the executable. */
1344
+ if (!backtrace_close (descriptor, error_callback, data))
1345
+ goto fail;
1346
+ descriptor = -1;
1347
+
1348
+ return 1;
1349
+
1350
+ fail:
1351
+ if (sects_view_valid)
1352
+ backtrace_release_view (state, &sects_view, error_callback, data);
1353
+ if (str_view_valid)
1354
+ backtrace_release_view (state, &str_view, error_callback, data);
1355
+ if (syms_view_valid)
1356
+ backtrace_release_view (state, &syms_view, error_callback, data);
1357
+ if (linenos_view_valid)
1358
+ backtrace_release_view (state, &linenos_view, error_callback, data);
1359
+ if (dwarf_view_valid)
1360
+ backtrace_release_view (state, &dwarf_view, error_callback, data);
1361
+ if (descriptor != -1 && offset == 0)
1362
+ backtrace_close (descriptor, error_callback, data);
1363
+ return 0;
1364
+ }
1365
+
1366
+ #ifdef HAVE_LOADQUERY
1367
+
1368
+ /* Read an integer value in human-readable format from an AIX
1369
+ big archive fixed-length or member header. */
1370
+
1371
+ static int
1372
+ xcoff_parse_decimal (const char *buf, size_t size, off_t *off)
1373
+ {
1374
+ char str[32];
1375
+ char *end;
1376
+
1377
+ if (size >= sizeof str)
1378
+ return 0;
1379
+ memcpy (str, buf, size);
1380
+ str[size] = '\0';
1381
+ *off = strtol (str, &end, 10);
1382
+ if (*end != '\0' && *end != ' ')
1383
+ return 0;
1384
+
1385
+ return 1;
1386
+ }
1387
+
1388
+ /* Add the backtrace data for a member of an AIX big archive.
1389
+ Returns 1 on success, 0 on failure. */
1390
+
1391
+ static int
1392
+ xcoff_armem_add (struct backtrace_state *state, int descriptor,
1393
+ uintptr_t base_address, const char *member,
1394
+ backtrace_error_callback error_callback, void *data,
1395
+ fileline *fileline_fn, int *found_sym)
1396
+ {
1397
+ struct backtrace_view view;
1398
+ b_ar_fl_hdr fl_hdr;
1399
+ const b_ar_hdr *ar_hdr;
1400
+ off_t off;
1401
+ off_t len;
1402
+ int memlen;
1403
+
1404
+ *found_sym = 0;
1405
+
1406
+ /* Map archive fixed-length header. */
1407
+
1408
+ if (!backtrace_get_view (state, descriptor, 0, sizeof (b_ar_fl_hdr),
1409
+ error_callback, data, &view))
1410
+ goto fail;
1411
+
1412
+ memcpy (&fl_hdr, view.data, sizeof (b_ar_fl_hdr));
1413
+
1414
+ backtrace_release_view (state, &view, error_callback, data);
1415
+
1416
+ if (memcmp (fl_hdr.fl_magic, AIAMAGBIG, 8) != 0)
1417
+ goto fail;
1418
+
1419
+ memlen = strlen (member);
1420
+
1421
+ /* Read offset of first archive member. */
1422
+ if (!xcoff_parse_decimal (fl_hdr.fl_fstmoff, sizeof fl_hdr.fl_fstmoff, &off))
1423
+ goto fail;
1424
+ while (off != 0)
1425
+ {
1426
+ /* Map archive member header and member name. */
1427
+
1428
+ if (!backtrace_get_view (state, descriptor, off,
1429
+ sizeof (b_ar_hdr) + memlen,
1430
+ error_callback, data, &view))
1431
+ break;
1432
+
1433
+ ar_hdr = (const b_ar_hdr *) view.data;
1434
+
1435
+ /* Read archive member name length. */
1436
+ if (!xcoff_parse_decimal (ar_hdr->ar_namlen, sizeof ar_hdr->ar_namlen,
1437
+ &len))
1438
+ {
1439
+ backtrace_release_view (state, &view, error_callback, data);
1440
+ break;
1441
+ }
1442
+ if (len == memlen && !memcmp (ar_hdr->ar_name, member, memlen))
1443
+ {
1444
+ off = (off + sizeof (b_ar_hdr) + memlen + 1) & ~1;
1445
+
1446
+ /* The archive can contain several members with the same name
1447
+ (e.g. 32-bit and 64-bit), so continue if not ok. */
1448
+
1449
+ if (xcoff_add (state, descriptor, off, base_address, error_callback,
1450
+ data, fileline_fn, found_sym, 0))
1451
+ {
1452
+ backtrace_release_view (state, &view, error_callback, data);
1453
+ return 1;
1454
+ }
1455
+ }
1456
+
1457
+ /* Read offset of next archive member. */
1458
+ if (!xcoff_parse_decimal (ar_hdr->ar_nxtmem, sizeof ar_hdr->ar_nxtmem,
1459
+ &off))
1460
+ {
1461
+ backtrace_release_view (state, &view, error_callback, data);
1462
+ break;
1463
+ }
1464
+ backtrace_release_view (state, &view, error_callback, data);
1465
+ }
1466
+
1467
+ fail:
1468
+ /* No matching member found. */
1469
+ backtrace_close (descriptor, error_callback, data);
1470
+ return 0;
1471
+ }
1472
+
1473
+ /* Add the backtrace data for dynamically loaded libraries. */
1474
+
1475
+ static void
1476
+ xcoff_add_shared_libs (struct backtrace_state *state,
1477
+ backtrace_error_callback error_callback,
1478
+ void *data, fileline *fileline_fn, int *found_sym)
1479
+ {
1480
+ const struct ld_info *ldinfo;
1481
+ void *buf;
1482
+ unsigned int buflen;
1483
+ const char *member;
1484
+ int descriptor;
1485
+ int does_not_exist;
1486
+ int lib_found_sym;
1487
+ int ret;
1488
+
1489
+ /* Retrieve the list of loaded libraries. */
1490
+
1491
+ buf = NULL;
1492
+ buflen = 512;
1493
+ do
1494
+ {
1495
+ buf = realloc (buf, buflen);
1496
+ if (buf == NULL)
1497
+ {
1498
+ ret = -1;
1499
+ break;
1500
+ }
1501
+ ret = loadquery (L_GETINFO, buf, buflen);
1502
+ if (ret == 0)
1503
+ break;
1504
+ buflen *= 2;
1505
+ }
1506
+ while (ret == -1 && errno == ENOMEM);
1507
+ if (ret != 0)
1508
+ {
1509
+ free (buf);
1510
+ return;
1511
+ }
1512
+
1513
+ ldinfo = (const struct ld_info *) buf;
1514
+ while ((const char *) ldinfo < (const char *) buf + buflen)
1515
+ {
1516
+ if (*ldinfo->ldinfo_filename != '/')
1517
+ goto next;
1518
+
1519
+ descriptor = backtrace_open (ldinfo->ldinfo_filename, error_callback,
1520
+ data, &does_not_exist);
1521
+ if (descriptor < 0)
1522
+ goto next;
1523
+
1524
+ /* Check if it is an archive (member name not empty). */
1525
+
1526
+ member = ldinfo->ldinfo_filename + strlen (ldinfo->ldinfo_filename) + 1;
1527
+ if (*member)
1528
+ {
1529
+ xcoff_armem_add (state, descriptor,
1530
+ (uintptr_t) ldinfo->ldinfo_textorg, member,
1531
+ error_callback, data, fileline_fn, &lib_found_sym);
1532
+ }
1533
+ else
1534
+ {
1535
+ xcoff_add (state, descriptor, 0, (uintptr_t) ldinfo->ldinfo_textorg,
1536
+ error_callback, data, fileline_fn, &lib_found_sym, 0);
1537
+ }
1538
+ if (lib_found_sym)
1539
+ *found_sym = 1;
1540
+
1541
+ next:
1542
+ if (ldinfo->ldinfo_next == 0)
1543
+ break;
1544
+ ldinfo = (const struct ld_info *) ((const char *) ldinfo
1545
+ + ldinfo->ldinfo_next);
1546
+ }
1547
+
1548
+ free (buf);
1549
+ }
1550
+ #endif /* HAVE_LOADQUERY */
1551
+
1552
+ /* Initialize the backtrace data we need from an XCOFF executable.
1553
+ Returns 1 on success, 0 on failure. */
1554
+
1555
+ int
1556
+ backtrace_initialize (struct backtrace_state *state,
1557
+ const char *filename ATTRIBUTE_UNUSED, int descriptor,
1558
+ backtrace_error_callback error_callback,
1559
+ void *data, fileline *fileline_fn)
1560
+ {
1561
+ int ret;
1562
+ int found_sym;
1563
+ fileline xcoff_fileline_fn = xcoff_nodebug;
1564
+
1565
+ ret = xcoff_add (state, descriptor, 0, 0, error_callback, data,
1566
+ &xcoff_fileline_fn, &found_sym, 1);
1567
+ if (!ret)
1568
+ return 0;
1569
+
1570
+ #ifdef HAVE_LOADQUERY
1571
+ xcoff_add_shared_libs (state, error_callback, data, &xcoff_fileline_fn,
1572
+ &found_sym);
1573
+ #endif
1574
+
1575
+ if (!state->threaded)
1576
+ {
1577
+ if (found_sym)
1578
+ state->syminfo_fn = xcoff_syminfo;
1579
+ else if (state->syminfo_fn == NULL)
1580
+ state->syminfo_fn = xcoff_nosyms;
1581
+ }
1582
+ else
1583
+ {
1584
+ if (found_sym)
1585
+ backtrace_atomic_store_pointer (&state->syminfo_fn, xcoff_syminfo);
1586
+ else
1587
+ (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
1588
+ xcoff_nosyms);
1589
+ }
1590
+
1591
+ if (!state->threaded)
1592
+ {
1593
+ if (state->fileline_fn == NULL || state->fileline_fn == xcoff_nodebug)
1594
+ *fileline_fn = xcoff_fileline_fn;
1595
+ }
1596
+ else
1597
+ {
1598
+ fileline current_fn;
1599
+
1600
+ current_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
1601
+ if (current_fn == NULL || current_fn == xcoff_nodebug)
1602
+ *fileline_fn = xcoff_fileline_fn;
1603
+ }
1604
+
1605
+ return 1;
1606
+ }