v / thirdparty / libbacktrace
Raw file | 4303 loc (3570 sloc) | 118.99 KB | Latest commit hash 76a735450
1// NOTE: Portions of the code have been modified in order to fix compilation in TCC - Ned
2
3// backtrace.h:
4#ifndef BACKTRACE_H
5#define BACKTRACE_H
6
7#include <stddef.h>
8#include <stdint.h>
9#include <stdio.h>
10
11#ifdef __cplusplus
12extern "C" {
13#endif
14
15struct backtrace_state;
16
17typedef void (*backtrace_error_callback)(void *data, const char *msg,
18 int errnum);
19
20extern struct backtrace_state *backtrace_create_state(
21 const char *filename, int threaded, backtrace_error_callback error_callback,
22 void *data);
23
24typedef int (*backtrace_full_callback)(void *data, uintptr_t pc,
25 const char *filename, int lineno,
26 const char *function);
27
28extern int backtrace_full(struct backtrace_state *state, int skip,
29 backtrace_full_callback callback,
30 backtrace_error_callback error_callback, void *data);
31
32typedef int (*backtrace_simple_callback)(void *data, uintptr_t pc);
33
34extern int backtrace_simple(struct backtrace_state *state, int skip,
35 backtrace_simple_callback callback,
36 backtrace_error_callback error_callback,
37 void *data);
38
39extern void backtrace_print(struct backtrace_state *state, int skip, FILE *);
40
41extern int backtrace_pcinfo(struct backtrace_state *state, uintptr_t pc,
42 backtrace_full_callback callback,
43 backtrace_error_callback error_callback,
44 void *data);
45
46typedef void (*backtrace_syminfo_callback)(void *data, uintptr_t pc,
47 const char *symname,
48 uintptr_t symval, uintptr_t symsize);
49
50extern int backtrace_syminfo(struct backtrace_state *state, uintptr_t addr,
51 backtrace_syminfo_callback callback,
52 backtrace_error_callback error_callback,
53 void *data);
54
55#ifdef __cplusplus
56}
57#endif
58
59#endif
60
61// internal.h:
62#ifndef BACKTRACE_INTERNAL_H
63#define BACKTRACE_INTERNAL_H
64
65#ifndef GCC_VERSION
66#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
67#endif
68
69#if (GCC_VERSION < 2007)
70#define __attribute__(x)
71#endif
72
73#ifndef ATTRIBUTE_UNUSED
74#define ATTRIBUTE_UNUSED __attribute__((__unused__))
75#endif
76
77#ifndef ATTRIBUTE_MALLOC
78#if (GCC_VERSION >= 2096)
79#define ATTRIBUTE_MALLOC __attribute__((__malloc__))
80#else
81#define ATTRIBUTE_MALLOC
82#endif
83#endif
84
85#ifndef ATTRIBUTE_FALLTHROUGH
86#if (GCC_VERSION >= 7000)
87#define ATTRIBUTE_FALLTHROUGH __attribute__((__fallthrough__))
88#else
89#define ATTRIBUTE_FALLTHROUGH
90#endif
91#endif
92
93#ifndef HAVE_SYNC_FUNCTIONS
94
95#define __sync_bool_compare_and_swap(A, B, C) (abort(), 1)
96#define __sync_lock_test_and_set(A, B) (abort(), 0)
97#define __sync_lock_release(A) abort()
98
99#endif
100#ifdef HAVE_ATOMIC_FUNCTIONS
101
102#define backtrace_atomic_load_pointer(p) __atomic_load_n((p), __ATOMIC_ACQUIRE)
103#define backtrace_atomic_load_int(p) __atomic_load_n((p), __ATOMIC_ACQUIRE)
104#define backtrace_atomic_store_pointer(p, v) \
105 __atomic_store_n((p), (v), __ATOMIC_RELEASE)
106#define backtrace_atomic_store_size_t(p, v) \
107 __atomic_store_n((p), (v), __ATOMIC_RELEASE)
108#define backtrace_atomic_store_int(p, v) \
109 __atomic_store_n((p), (v), __ATOMIC_RELEASE)
110
111#else
112#ifdef HAVE_SYNC_FUNCTIONS
113
114extern void *backtrace_atomic_load_pointer(void *);
115extern int backtrace_atomic_load_int(int *);
116extern void backtrace_atomic_store_pointer(void *, void *);
117extern void backtrace_atomic_store_size_t(size_t *, size_t);
118extern void backtrace_atomic_store_int(int *, int);
119
120#else
121
122#define backtrace_atomic_load_pointer(p) (abort(), (void *)NULL)
123#define backtrace_atomic_load_int(p) (abort(), 0)
124#define backtrace_atomic_store_pointer(p, v) abort()
125#define backtrace_atomic_store_size_t(p, v) abort()
126#define backtrace_atomic_store_int(p, v) abort()
127
128#endif
129#endif
130
131typedef int (*fileline)(struct backtrace_state *state, uintptr_t pc,
132 backtrace_full_callback callback,
133 backtrace_error_callback error_callback, void *data);
134
135typedef void (*syminfo)(struct backtrace_state *state, uintptr_t pc,
136 backtrace_syminfo_callback callback,
137 backtrace_error_callback error_callback, void *data);
138
139struct backtrace_state {
140 const char *filename;
141
142 int threaded;
143
144 void *lock;
145
146 fileline fileline_fn;
147
148 void *fileline_data;
149
150 syminfo syminfo_fn;
151
152 void *syminfo_data;
153
154 int fileline_initialization_failed;
155
156 int lock_alloc;
157
158 struct backtrace_freelist_struct *freelist;
159};
160
161extern int backtrace_open(const char *filename,
162 backtrace_error_callback error_callback, void *data,
163 int *does_not_exist);
164
165struct backtrace_view {
166 const void *data;
167
168 void *base;
169
170 size_t len;
171};
172
173extern int backtrace_get_view(struct backtrace_state *state, int descriptor,
174 off_t offset, uint64_t size,
175 backtrace_error_callback error_callback,
176 void *data, struct backtrace_view *view);
177
178extern void backtrace_release_view(struct backtrace_state *state,
179 struct backtrace_view *view,
180 backtrace_error_callback error_callback,
181 void *data);
182
183extern int backtrace_close(int descriptor,
184 backtrace_error_callback error_callback, void *data);
185
186extern void backtrace_qsort(void *base, size_t count, size_t size,
187 int (*compar)(const void *, const void *));
188
189extern void *backtrace_alloc(struct backtrace_state *state, size_t size,
190 backtrace_error_callback error_callback,
191 void *data) ATTRIBUTE_MALLOC;
192
193extern void backtrace_free(struct backtrace_state *state, void *mem,
194 size_t size, backtrace_error_callback error_callback,
195 void *data);
196
197struct backtrace_vector {
198 void *base;
199
200 size_t size;
201
202 size_t alc;
203};
204
205extern void *backtrace_vector_grow(struct backtrace_state *state, size_t size,
206 backtrace_error_callback error_callback,
207 void *data, struct backtrace_vector *vec);
208
209extern void *backtrace_vector_finish(struct backtrace_state *state,
210 struct backtrace_vector *vec,
211 backtrace_error_callback error_callback,
212 void *data);
213
214extern int backtrace_vector_release(struct backtrace_state *state,
215 struct backtrace_vector *vec,
216 backtrace_error_callback error_callback,
217 void *data);
218
219static inline void backtrace_vector_free(
220 struct backtrace_state *state, struct backtrace_vector *vec,
221 backtrace_error_callback error_callback, void *data) {
222 vec->alc += vec->size;
223 vec->size = 0;
224 backtrace_vector_release(state, vec, error_callback, data);
225}
226
227extern int backtrace_initialize(struct backtrace_state *state,
228 const char *filename, int descriptor,
229 backtrace_error_callback error_callback,
230 void *data, fileline *fileline_fn);
231
232enum dwarf_section {
233 DEBUG_INFO,
234 DEBUG_LINE,
235 DEBUG_ABBREV,
236 DEBUG_RANGES,
237 DEBUG_STR,
238 DEBUG_ADDR,
239 DEBUG_STR_OFFSETS,
240 DEBUG_LINE_STR,
241 DEBUG_RNGLISTS,
242
243 DEBUG_MAX
244};
245
246struct dwarf_sections {
247 const unsigned char *data[DEBUG_MAX];
248 size_t size[DEBUG_MAX];
249};
250
251struct dwarf_data;
252
253extern int backtrace_dwarf_add(struct backtrace_state *state,
254 uintptr_t base_address,
255 const struct dwarf_sections *dwarf_sections,
256 int is_bigendian,
257 struct dwarf_data *fileline_altlink,
258 backtrace_error_callback error_callback,
259 void *data, fileline *fileline_fn,
260 struct dwarf_data **fileline_entry);
261
262struct backtrace_call_full {
263 backtrace_full_callback full_callback;
264 backtrace_error_callback full_error_callback;
265 void *full_data;
266 int ret;
267};
268
269extern void backtrace_syminfo_to_full_callback(void *data, uintptr_t pc,
270 const char *symname,
271 uintptr_t symval,
272 uintptr_t symsize);
273
274extern void backtrace_syminfo_to_full_error_callback(void *, const char *, int);
275
276extern int backtrace_uncompress_zdebug(struct backtrace_state *,
277 const unsigned char *compressed,
278 size_t compressed_size,
279 backtrace_error_callback, void *data,
280 unsigned char **uncompressed,
281 size_t *uncompressed_size);
282
283extern int backtrace_uncompress_lzma(struct backtrace_state *,
284 const unsigned char *compressed,
285 size_t compressed_size,
286 backtrace_error_callback, void *data,
287 unsigned char **uncompressed,
288 size_t *uncompressed_size);
289
290#endif
291
292// filenames.h:
293#ifndef GCC_VERSION
294#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
295#endif
296
297#if (GCC_VERSION < 2007)
298#define __attribute__(x)
299#endif
300
301#ifndef ATTRIBUTE_UNUSED
302#define ATTRIBUTE_UNUSED __attribute__((__unused__))
303#endif
304
305#if defined(__MSDOS__) || defined(_WIN32) || defined(__OS2__) || \
306 defined(__CYGWIN__)
307#define IS_DIR_SEPARATOR(c) ((c) == '/' || (c) == '\\')
308#define HAS_DRIVE_SPEC(f) ((f)[0] != '\0' && (f)[1] == ':')
309#define IS_ABSOLUTE_PATH(f) (IS_DIR_SEPARATOR((f)[0]) || HAS_DRIVE_SPEC(f))
310#else
311#define IS_DIR_SEPARATOR(c) ((c) == '/')
312#define IS_ABSOLUTE_PATH(f) (IS_DIR_SEPARATOR((f)[0]))
313#endif
314
315// atomic.c:
316#include <sys/types.h>
317
318// dwarf.c:
319#include <errno.h>
320#include <stdlib.h>
321#include <string.h>
322#include <sys/types.h>
323
324enum dwarf_tag {
325 DW_TAG_entry_point = 0x3,
326 DW_TAG_compile_unit = 0x11,
327 DW_TAG_inlined_subroutine = 0x1d,
328 DW_TAG_subprogram = 0x2e,
329 DW_TAG_skeleton_unit = 0x4a,
330};
331
332enum dwarf_form {
333 DW_FORM_addr = 0x01,
334 DW_FORM_block2 = 0x03,
335 DW_FORM_block4 = 0x04,
336 DW_FORM_data2 = 0x05,
337 DW_FORM_data4 = 0x06,
338 DW_FORM_data8 = 0x07,
339 DW_FORM_string = 0x08,
340 DW_FORM_block = 0x09,
341 DW_FORM_block1 = 0x0a,
342 DW_FORM_data1 = 0x0b,
343 DW_FORM_flag = 0x0c,
344 DW_FORM_sdata = 0x0d,
345 DW_FORM_strp = 0x0e,
346 DW_FORM_udata = 0x0f,
347 DW_FORM_ref_addr = 0x10,
348 DW_FORM_ref1 = 0x11,
349 DW_FORM_ref2 = 0x12,
350 DW_FORM_ref4 = 0x13,
351 DW_FORM_ref8 = 0x14,
352 DW_FORM_ref_udata = 0x15,
353 DW_FORM_indirect = 0x16,
354 DW_FORM_sec_offset = 0x17,
355 DW_FORM_exprloc = 0x18,
356 DW_FORM_flag_present = 0x19,
357 DW_FORM_ref_sig8 = 0x20,
358 DW_FORM_strx = 0x1a,
359 DW_FORM_addrx = 0x1b,
360 DW_FORM_ref_sup4 = 0x1c,
361 DW_FORM_strp_sup = 0x1d,
362 DW_FORM_data16 = 0x1e,
363 DW_FORM_line_strp = 0x1f,
364 DW_FORM_implicit_const = 0x21,
365 DW_FORM_loclistx = 0x22,
366 DW_FORM_rnglistx = 0x23,
367 DW_FORM_ref_sup8 = 0x24,
368 DW_FORM_strx1 = 0x25,
369 DW_FORM_strx2 = 0x26,
370 DW_FORM_strx3 = 0x27,
371 DW_FORM_strx4 = 0x28,
372 DW_FORM_addrx1 = 0x29,
373 DW_FORM_addrx2 = 0x2a,
374 DW_FORM_addrx3 = 0x2b,
375 DW_FORM_addrx4 = 0x2c,
376 DW_FORM_GNU_addr_index = 0x1f01,
377 DW_FORM_GNU_str_index = 0x1f02,
378 DW_FORM_GNU_ref_alt = 0x1f20,
379 DW_FORM_GNU_strp_alt = 0x1f21
380};
381
382enum dwarf_attribute {
383 DW_AT_sibling = 0x01,
384 DW_AT_location = 0x02,
385 DW_AT_name = 0x03,
386 DW_AT_ordering = 0x09,
387 DW_AT_subscr_data = 0x0a,
388 DW_AT_byte_size = 0x0b,
389 DW_AT_bit_offset = 0x0c,
390 DW_AT_bit_size = 0x0d,
391 DW_AT_element_list = 0x0f,
392 DW_AT_stmt_list = 0x10,
393 DW_AT_low_pc = 0x11,
394 DW_AT_high_pc = 0x12,
395 DW_AT_language = 0x13,
396 DW_AT_member = 0x14,
397 DW_AT_discr = 0x15,
398 DW_AT_discr_value = 0x16,
399 DW_AT_visibility = 0x17,
400 DW_AT_import = 0x18,
401 DW_AT_string_length = 0x19,
402 DW_AT_common_reference = 0x1a,
403 DW_AT_comp_dir = 0x1b,
404 DW_AT_const_value = 0x1c,
405 DW_AT_containing_type = 0x1d,
406 DW_AT_default_value = 0x1e,
407 DW_AT_inline = 0x20,
408 DW_AT_is_optional = 0x21,
409 DW_AT_lower_bound = 0x22,
410 DW_AT_producer = 0x25,
411 DW_AT_prototyped = 0x27,
412 DW_AT_return_addr = 0x2a,
413 DW_AT_start_scope = 0x2c,
414 DW_AT_bit_stride = 0x2e,
415 DW_AT_upper_bound = 0x2f,
416 DW_AT_abstract_origin = 0x31,
417 DW_AT_accessibility = 0x32,
418 DW_AT_address_class = 0x33,
419 DW_AT_artificial = 0x34,
420 DW_AT_base_types = 0x35,
421 DW_AT_calling_convention = 0x36,
422 DW_AT_count = 0x37,
423 DW_AT_data_member_location = 0x38,
424 DW_AT_decl_column = 0x39,
425 DW_AT_decl_file = 0x3a,
426 DW_AT_decl_line = 0x3b,
427 DW_AT_declaration = 0x3c,
428 DW_AT_discr_list = 0x3d,
429 DW_AT_encoding = 0x3e,
430 DW_AT_external = 0x3f,
431 DW_AT_frame_base = 0x40,
432 DW_AT_friend = 0x41,
433 DW_AT_identifier_case = 0x42,
434 DW_AT_macro_info = 0x43,
435 DW_AT_namelist_items = 0x44,
436 DW_AT_priority = 0x45,
437 DW_AT_segment = 0x46,
438 DW_AT_specification = 0x47,
439 DW_AT_static_link = 0x48,
440 DW_AT_type = 0x49,
441 DW_AT_use_location = 0x4a,
442 DW_AT_variable_parameter = 0x4b,
443 DW_AT_virtuality = 0x4c,
444 DW_AT_vtable_elem_location = 0x4d,
445 DW_AT_allocated = 0x4e,
446 DW_AT_associated = 0x4f,
447 DW_AT_data_location = 0x50,
448 DW_AT_byte_stride = 0x51,
449 DW_AT_entry_pc = 0x52,
450 DW_AT_use_UTF8 = 0x53,
451 DW_AT_extension = 0x54,
452 DW_AT_ranges = 0x55,
453 DW_AT_trampoline = 0x56,
454 DW_AT_call_column = 0x57,
455 DW_AT_call_file = 0x58,
456 DW_AT_call_line = 0x59,
457 DW_AT_description = 0x5a,
458 DW_AT_binary_scale = 0x5b,
459 DW_AT_decimal_scale = 0x5c,
460 DW_AT_small = 0x5d,
461 DW_AT_decimal_sign = 0x5e,
462 DW_AT_digit_count = 0x5f,
463 DW_AT_picture_string = 0x60,
464 DW_AT_mutable = 0x61,
465 DW_AT_threads_scaled = 0x62,
466 DW_AT_explicit = 0x63,
467 DW_AT_object_pointer = 0x64,
468 DW_AT_endianity = 0x65,
469 DW_AT_elemental = 0x66,
470 DW_AT_pure = 0x67,
471 DW_AT_recursive = 0x68,
472 DW_AT_signature = 0x69,
473 DW_AT_main_subprogram = 0x6a,
474 DW_AT_data_bit_offset = 0x6b,
475 DW_AT_const_expr = 0x6c,
476 DW_AT_enum_class = 0x6d,
477 DW_AT_linkage_name = 0x6e,
478 DW_AT_string_length_bit_size = 0x6f,
479 DW_AT_string_length_byte_size = 0x70,
480 DW_AT_rank = 0x71,
481 DW_AT_str_offsets_base = 0x72,
482 DW_AT_addr_base = 0x73,
483 DW_AT_rnglists_base = 0x74,
484 DW_AT_dwo_name = 0x76,
485 DW_AT_reference = 0x77,
486 DW_AT_rvalue_reference = 0x78,
487 DW_AT_macros = 0x79,
488 DW_AT_call_all_calls = 0x7a,
489 DW_AT_call_all_source_calls = 0x7b,
490 DW_AT_call_all_tail_calls = 0x7c,
491 DW_AT_call_return_pc = 0x7d,
492 DW_AT_call_value = 0x7e,
493 DW_AT_call_origin = 0x7f,
494 DW_AT_call_parameter = 0x80,
495 DW_AT_call_pc = 0x81,
496 DW_AT_call_tail_call = 0x82,
497 DW_AT_call_target = 0x83,
498 DW_AT_call_target_clobbered = 0x84,
499 DW_AT_call_data_location = 0x85,
500 DW_AT_call_data_value = 0x86,
501 DW_AT_noreturn = 0x87,
502 DW_AT_alignment = 0x88,
503 DW_AT_export_symbols = 0x89,
504 DW_AT_deleted = 0x8a,
505 DW_AT_defaulted = 0x8b,
506 DW_AT_loclists_base = 0x8c,
507 DW_AT_lo_user = 0x2000,
508 DW_AT_hi_user = 0x3fff,
509 DW_AT_MIPS_fde = 0x2001,
510 DW_AT_MIPS_loop_begin = 0x2002,
511 DW_AT_MIPS_tail_loop_begin = 0x2003,
512 DW_AT_MIPS_epilog_begin = 0x2004,
513 DW_AT_MIPS_loop_unroll_factor = 0x2005,
514 DW_AT_MIPS_software_pipeline_depth = 0x2006,
515 DW_AT_MIPS_linkage_name = 0x2007,
516 DW_AT_MIPS_stride = 0x2008,
517 DW_AT_MIPS_abstract_name = 0x2009,
518 DW_AT_MIPS_clone_origin = 0x200a,
519 DW_AT_MIPS_has_inlines = 0x200b,
520 DW_AT_HP_block_index = 0x2000,
521 DW_AT_HP_unmodifiable = 0x2001,
522 DW_AT_HP_prologue = 0x2005,
523 DW_AT_HP_epilogue = 0x2008,
524 DW_AT_HP_actuals_stmt_list = 0x2010,
525 DW_AT_HP_proc_per_section = 0x2011,
526 DW_AT_HP_raw_data_ptr = 0x2012,
527 DW_AT_HP_pass_by_reference = 0x2013,
528 DW_AT_HP_opt_level = 0x2014,
529 DW_AT_HP_prof_version_id = 0x2015,
530 DW_AT_HP_opt_flags = 0x2016,
531 DW_AT_HP_cold_region_low_pc = 0x2017,
532 DW_AT_HP_cold_region_high_pc = 0x2018,
533 DW_AT_HP_all_variables_modifiable = 0x2019,
534 DW_AT_HP_linkage_name = 0x201a,
535 DW_AT_HP_prof_flags = 0x201b,
536 DW_AT_HP_unit_name = 0x201f,
537 DW_AT_HP_unit_size = 0x2020,
538 DW_AT_HP_widened_byte_size = 0x2021,
539 DW_AT_HP_definition_points = 0x2022,
540 DW_AT_HP_default_location = 0x2023,
541 DW_AT_HP_is_result_param = 0x2029,
542 DW_AT_sf_names = 0x2101,
543 DW_AT_src_info = 0x2102,
544 DW_AT_mac_info = 0x2103,
545 DW_AT_src_coords = 0x2104,
546 DW_AT_body_begin = 0x2105,
547 DW_AT_body_end = 0x2106,
548 DW_AT_GNU_vector = 0x2107,
549 DW_AT_GNU_guarded_by = 0x2108,
550 DW_AT_GNU_pt_guarded_by = 0x2109,
551 DW_AT_GNU_guarded = 0x210a,
552 DW_AT_GNU_pt_guarded = 0x210b,
553 DW_AT_GNU_locks_excluded = 0x210c,
554 DW_AT_GNU_exclusive_locks_required = 0x210d,
555 DW_AT_GNU_shared_locks_required = 0x210e,
556 DW_AT_GNU_odr_signature = 0x210f,
557 DW_AT_GNU_template_name = 0x2110,
558 DW_AT_GNU_call_site_value = 0x2111,
559 DW_AT_GNU_call_site_data_value = 0x2112,
560 DW_AT_GNU_call_site_target = 0x2113,
561 DW_AT_GNU_call_site_target_clobbered = 0x2114,
562 DW_AT_GNU_tail_call = 0x2115,
563 DW_AT_GNU_all_tail_call_sites = 0x2116,
564 DW_AT_GNU_all_call_sites = 0x2117,
565 DW_AT_GNU_all_source_call_sites = 0x2118,
566 DW_AT_GNU_macros = 0x2119,
567 DW_AT_GNU_deleted = 0x211a,
568 DW_AT_GNU_dwo_name = 0x2130,
569 DW_AT_GNU_dwo_id = 0x2131,
570 DW_AT_GNU_ranges_base = 0x2132,
571 DW_AT_GNU_addr_base = 0x2133,
572 DW_AT_GNU_pubnames = 0x2134,
573 DW_AT_GNU_pubtypes = 0x2135,
574 DW_AT_GNU_discriminator = 0x2136,
575 DW_AT_GNU_locviews = 0x2137,
576 DW_AT_GNU_entry_view = 0x2138,
577 DW_AT_VMS_rtnbeg_pd_address = 0x2201,
578 DW_AT_use_GNAT_descriptive_type = 0x2301,
579 DW_AT_GNAT_descriptive_type = 0x2302,
580 DW_AT_GNU_numerator = 0x2303,
581 DW_AT_GNU_denominator = 0x2304,
582 DW_AT_GNU_bias = 0x2305,
583 DW_AT_upc_threads_scaled = 0x3210,
584 DW_AT_PGI_lbase = 0x3a00,
585 DW_AT_PGI_soffset = 0x3a01,
586 DW_AT_PGI_lstride = 0x3a02,
587 DW_AT_APPLE_optimized = 0x3fe1,
588 DW_AT_APPLE_flags = 0x3fe2,
589 DW_AT_APPLE_isa = 0x3fe3,
590 DW_AT_APPLE_block = 0x3fe4,
591 DW_AT_APPLE_major_runtime_vers = 0x3fe5,
592 DW_AT_APPLE_runtime_class = 0x3fe6,
593 DW_AT_APPLE_omit_frame_ptr = 0x3fe7,
594 DW_AT_APPLE_property_name = 0x3fe8,
595 DW_AT_APPLE_property_getter = 0x3fe9,
596 DW_AT_APPLE_property_setter = 0x3fea,
597 DW_AT_APPLE_property_attribute = 0x3feb,
598 DW_AT_APPLE_objc_complete_type = 0x3fec,
599 DW_AT_APPLE_property = 0x3fed
600};
601
602enum dwarf_line_number_op {
603 DW_LNS_extended_op = 0x0,
604 DW_LNS_copy = 0x1,
605 DW_LNS_advance_pc = 0x2,
606 DW_LNS_advance_line = 0x3,
607 DW_LNS_set_file = 0x4,
608 DW_LNS_set_column = 0x5,
609 DW_LNS_negate_stmt = 0x6,
610 DW_LNS_set_basic_block = 0x7,
611 DW_LNS_const_add_pc = 0x8,
612 DW_LNS_fixed_advance_pc = 0x9,
613 DW_LNS_set_prologue_end = 0xa,
614 DW_LNS_set_epilogue_begin = 0xb,
615 DW_LNS_set_isa = 0xc,
616};
617
618enum dwarf_extended_line_number_op {
619 DW_LNE_end_sequence = 0x1,
620 DW_LNE_set_address = 0x2,
621 DW_LNE_define_file = 0x3,
622 DW_LNE_set_discriminator = 0x4,
623};
624
625enum dwarf_line_number_content_type {
626 DW_LNCT_path = 0x1,
627 DW_LNCT_directory_index = 0x2,
628 DW_LNCT_timestamp = 0x3,
629 DW_LNCT_size = 0x4,
630 DW_LNCT_MD5 = 0x5,
631 DW_LNCT_lo_user = 0x2000,
632 DW_LNCT_hi_user = 0x3fff
633};
634
635enum dwarf_range_list_entry {
636 DW_RLE_end_of_list = 0x00,
637 DW_RLE_base_addressx = 0x01,
638 DW_RLE_startx_endx = 0x02,
639 DW_RLE_startx_length = 0x03,
640 DW_RLE_offset_pair = 0x04,
641 DW_RLE_base_address = 0x05,
642 DW_RLE_start_end = 0x06,
643 DW_RLE_start_length = 0x07
644};
645
646enum dwarf_unit_type {
647 DW_UT_compile = 0x01,
648 DW_UT_type = 0x02,
649 DW_UT_partial = 0x03,
650 DW_UT_skeleton = 0x04,
651 DW_UT_split_compile = 0x05,
652 DW_UT_split_type = 0x06,
653 DW_UT_lo_user = 0x80,
654 DW_UT_hi_user = 0xff
655};
656
657#if !defined(HAVE_DECL_STRNLEN) || !HAVE_DECL_STRNLEN
658
659static size_t xstrnlen(const char *s, size_t maxlen) {
660 size_t i;
661
662 for (i = 0; i < maxlen; ++i)
663 if (s[i] == '\0') break;
664 return i;
665}
666
667#define strnlen xstrnlen
668
669#endif
670
671struct dwarf_buf {
672 const char *name;
673
674 const unsigned char *start;
675
676 const unsigned char *buf;
677
678 size_t left;
679
680 int is_bigendian;
681
682 backtrace_error_callback error_callback;
683
684 void *data;
685
686 int reported_underflow;
687};
688
689struct attr {
690 enum dwarf_attribute name;
691
692 enum dwarf_form form;
693
694 int64_t val;
695};
696
697struct abbrev {
698 uint64_t code;
699
700 enum dwarf_tag tag;
701
702 int has_children;
703
704 size_t num_attrs;
705
706 struct attr *attrs;
707};
708
709struct abbrevs {
710 size_t num_abbrevs;
711
712 struct abbrev *abbrevs;
713};
714
715enum attr_val_encoding {
716
717 ATTR_VAL_NONE,
718
719 ATTR_VAL_ADDRESS,
720
721 ATTR_VAL_ADDRESS_INDEX,
722
723 ATTR_VAL_UINT,
724
725 ATTR_VAL_SINT,
726
727 ATTR_VAL_STRING,
728
729 ATTR_VAL_STRING_INDEX,
730
731 ATTR_VAL_REF_UNIT,
732
733 ATTR_VAL_REF_INFO,
734
735 ATTR_VAL_REF_ALT_INFO,
736
737 ATTR_VAL_REF_SECTION,
738
739 ATTR_VAL_REF_TYPE,
740
741 ATTR_VAL_RNGLISTS_INDEX,
742
743 ATTR_VAL_BLOCK,
744
745 ATTR_VAL_EXPR,
746};
747
748struct attr_val {
749 enum attr_val_encoding encoding;
750 union {
751 uint64_t uint;
752
753 int64_t sint;
754
755 const char *string;
756
757 } u;
758};
759
760struct line_header {
761 int version;
762
763 int addrsize;
764
765 unsigned int min_insn_len;
766
767 unsigned int max_ops_per_insn;
768
769 int line_base;
770
771 unsigned int line_range;
772
773 unsigned int opcode_base;
774
775 const unsigned char *opcode_lengths;
776
777 size_t dirs_count;
778
779 const char **dirs;
780
781 size_t filenames_count;
782
783 const char **filenames;
784};
785
786struct line_header_format {
787 int lnct;
788 enum dwarf_form form;
789};
790
791struct line {
792 uintptr_t pc;
793
794 const char *filename;
795
796 int lineno;
797
798 int idx;
799};
800
801struct line_vector {
802 struct backtrace_vector vec;
803
804 size_t count;
805};
806
807struct function {
808 const char *name;
809
810 const char *caller_filename;
811
812 int caller_lineno;
813
814 struct function_addrs *function_addrs;
815 size_t function_addrs_count;
816};
817
818struct function_addrs {
819 uint64_t low;
820 uint64_t high;
821
822 struct function *function;
823};
824
825struct function_vector {
826 struct backtrace_vector vec;
827
828 size_t count;
829};
830
831struct unit {
832 const unsigned char *unit_data;
833
834 size_t unit_data_len;
835
836 size_t unit_data_offset;
837
838 size_t low_offset;
839
840 size_t high_offset;
841
842 int version;
843
844 int is_dwarf64;
845
846 int addrsize;
847
848 off_t lineoff;
849
850 uint64_t str_offsets_base;
851
852 uint64_t addr_base;
853
854 uint64_t rnglists_base;
855
856 const char *filename;
857
858 const char *comp_dir;
859
860 const char *abs_filename;
861
862 struct abbrevs abbrevs;
863
864 struct line *lines;
865
866 size_t lines_count;
867
868 struct function_addrs *function_addrs;
869 size_t function_addrs_count;
870};
871
872struct unit_addrs {
873 uint64_t low;
874 uint64_t high;
875
876 struct unit *u;
877};
878
879struct unit_addrs_vector {
880 struct backtrace_vector vec;
881
882 size_t count;
883};
884
885struct unit_vector {
886 struct backtrace_vector vec;
887 size_t count;
888};
889
890struct dwarf_data {
891 struct dwarf_data *next;
892
893 struct dwarf_data *altlink;
894
895 uintptr_t base_address;
896
897 struct unit_addrs *addrs;
898
899 size_t addrs_count;
900
901 struct unit **units;
902
903 size_t units_count;
904
905 struct dwarf_sections dwarf_sections;
906
907 int is_bigendian;
908
909 struct function_vector fvec;
910};
911
912static void dwarf_buf_error(struct dwarf_buf *buf, const char *msg,
913 int errnum) {
914 char b[200];
915
916 snprintf(b, sizeof b, "%s in %s at %d", msg, buf->name,
917 (int)(buf->buf - buf->start));
918 buf->error_callback(buf->data, b, errnum);
919}
920
921static int require(struct dwarf_buf *buf, size_t count) {
922 if (buf->left >= count) return 1;
923
924 if (!buf->reported_underflow) {
925 dwarf_buf_error(buf, "DWARF underflow", 0);
926 buf->reported_underflow = 1;
927 }
928
929 return 0;
930}
931
932static int advance(struct dwarf_buf *buf, size_t count) {
933 if (!require(buf, count)) return 0;
934 buf->buf += count;
935 buf->left -= count;
936 return 1;
937}
938
939static const char *read_string(struct dwarf_buf *buf) {
940 const char *p = (const char *)buf->buf;
941 size_t len = strnlen(p, buf->left);
942
943 size_t count = len + 1;
944
945 if (!advance(buf, count)) return NULL;
946
947 return p;
948}
949
950static unsigned char read_byte(struct dwarf_buf *buf) {
951 const unsigned char *p = buf->buf;
952
953 if (!advance(buf, 1)) return 0;
954 return p[0];
955}
956
957static signed char read_sbyte(struct dwarf_buf *buf) {
958 const unsigned char *p = buf->buf;
959
960 if (!advance(buf, 1)) return 0;
961 return (*p ^ 0x80) - 0x80;
962}
963
964static uint16_t read_uint16(struct dwarf_buf *buf) {
965 const unsigned char *p = buf->buf;
966
967 if (!advance(buf, 2)) return 0;
968 if (buf->is_bigendian)
969 return ((uint16_t)p[0] << 8) | (uint16_t)p[1];
970 else
971 return ((uint16_t)p[1] << 8) | (uint16_t)p[0];
972}
973
974static uint32_t read_uint24(struct dwarf_buf *buf) {
975 const unsigned char *p = buf->buf;
976
977 if (!advance(buf, 3)) return 0;
978 if (buf->is_bigendian)
979 return (((uint32_t)p[0] << 16) | ((uint32_t)p[1] << 8) | (uint32_t)p[2]);
980 else
981 return (((uint32_t)p[2] << 16) | ((uint32_t)p[1] << 8) | (uint32_t)p[0]);
982}
983
984static uint32_t read_uint32(struct dwarf_buf *buf) {
985 const unsigned char *p = buf->buf;
986
987 if (!advance(buf, 4)) return 0;
988 if (buf->is_bigendian)
989 return (((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) |
990 ((uint32_t)p[2] << 8) | (uint32_t)p[3]);
991 else
992 return (((uint32_t)p[3] << 24) | ((uint32_t)p[2] << 16) |
993 ((uint32_t)p[1] << 8) | (uint32_t)p[0]);
994}
995
996static uint64_t read_uint64(struct dwarf_buf *buf) {
997 const unsigned char *p = buf->buf;
998
999 if (!advance(buf, 8)) return 0;
1000 if (buf->is_bigendian)
1001 return (((uint64_t)p[0] << 56) | ((uint64_t)p[1] << 48) |
1002 ((uint64_t)p[2] << 40) | ((uint64_t)p[3] << 32) |
1003 ((uint64_t)p[4] << 24) | ((uint64_t)p[5] << 16) |
1004 ((uint64_t)p[6] << 8) | (uint64_t)p[7]);
1005 else
1006 return (((uint64_t)p[7] << 56) | ((uint64_t)p[6] << 48) |
1007 ((uint64_t)p[5] << 40) | ((uint64_t)p[4] << 32) |
1008 ((uint64_t)p[3] << 24) | ((uint64_t)p[2] << 16) |
1009 ((uint64_t)p[1] << 8) | (uint64_t)p[0]);
1010}
1011
1012static uint64_t read_offset(struct dwarf_buf *buf, int is_dwarf64) {
1013 if (is_dwarf64)
1014 return read_uint64(buf);
1015 else
1016 return read_uint32(buf);
1017}
1018
1019static uint64_t read_address(struct dwarf_buf *buf, int addrsize) {
1020 switch (addrsize) {
1021 case 1:
1022 return read_byte(buf);
1023 case 2:
1024 return read_uint16(buf);
1025 case 4:
1026 return read_uint32(buf);
1027 case 8:
1028 return read_uint64(buf);
1029 default:
1030 dwarf_buf_error(buf, "unrecognized address size", 0);
1031 return 0;
1032 }
1033}
1034
1035static int is_highest_address(uint64_t address, int addrsize) {
1036 switch (addrsize) {
1037 case 1:
1038 return address == (unsigned char)-1;
1039 case 2:
1040 return address == (uint16_t)-1;
1041 case 4:
1042 return address == (uint32_t)-1;
1043 case 8:
1044 return address == (uint64_t)-1;
1045 default:
1046 return 0;
1047 }
1048}
1049
1050static uint64_t read_uleb128(struct dwarf_buf *buf) {
1051 uint64_t ret;
1052 unsigned int shift;
1053 int overflow;
1054 unsigned char b;
1055
1056 ret = 0;
1057 shift = 0;
1058 overflow = 0;
1059 do {
1060 const unsigned char *p;
1061
1062 p = buf->buf;
1063 if (!advance(buf, 1)) return 0;
1064 b = *p;
1065 if (shift < 64)
1066 ret |= ((uint64_t)(b & 0x7f)) << shift;
1067 else if (!overflow) {
1068 dwarf_buf_error(buf, "LEB128 overflows uint64_t", 0);
1069 overflow = 1;
1070 }
1071 shift += 7;
1072 } while ((b & 0x80) != 0);
1073
1074 return ret;
1075}
1076
1077static int64_t read_sleb128(struct dwarf_buf *buf) {
1078 uint64_t val;
1079 unsigned int shift;
1080 int overflow;
1081 unsigned char b;
1082
1083 val = 0;
1084 shift = 0;
1085 overflow = 0;
1086 do {
1087 const unsigned char *p;
1088
1089 p = buf->buf;
1090 if (!advance(buf, 1)) return 0;
1091 b = *p;
1092 if (shift < 64)
1093 val |= ((uint64_t)(b & 0x7f)) << shift;
1094 else if (!overflow) {
1095 dwarf_buf_error(buf, "signed LEB128 overflows uint64_t", 0);
1096 overflow = 1;
1097 }
1098 shift += 7;
1099 } while ((b & 0x80) != 0);
1100
1101 if ((b & 0x40) != 0 && shift < 64) val |= ((uint64_t)-1) << shift;
1102
1103 return (int64_t)val;
1104}
1105
1106static size_t leb128_len(const unsigned char *p) {
1107 size_t ret;
1108
1109 ret = 1;
1110 while ((*p & 0x80) != 0) {
1111 ++p;
1112 ++ret;
1113 }
1114 return ret;
1115}
1116
1117static uint64_t read_initial_length(struct dwarf_buf *buf, int *is_dwarf64) {
1118 uint64_t len;
1119
1120 len = read_uint32(buf);
1121 if (len == 0xffffffff) {
1122 len = read_uint64(buf);
1123 *is_dwarf64 = 1;
1124 } else
1125 *is_dwarf64 = 0;
1126
1127 return len;
1128}
1129
1130static void free_abbrevs(struct backtrace_state *state, struct abbrevs *abbrevs,
1131 backtrace_error_callback error_callback, void *data) {
1132 size_t i;
1133
1134 for (i = 0; i < abbrevs->num_abbrevs; ++i)
1135 backtrace_free(state, abbrevs->abbrevs[i].attrs,
1136 abbrevs->abbrevs[i].num_attrs * sizeof(struct attr),
1137 error_callback, data);
1138 backtrace_free(state, abbrevs->abbrevs,
1139 abbrevs->num_abbrevs * sizeof(struct abbrev), error_callback,
1140 data);
1141 abbrevs->num_abbrevs = 0;
1142 abbrevs->abbrevs = NULL;
1143}
1144
1145static int read_attribute(enum dwarf_form form, uint64_t implicit_val,
1146 struct dwarf_buf *buf, int is_dwarf64, int version,
1147 int addrsize,
1148 const struct dwarf_sections *dwarf_sections,
1149 struct dwarf_data *altlink, struct attr_val *val) {
1150 memset(val, 0, sizeof *val);
1151
1152 switch (form) {
1153 case DW_FORM_addr:
1154 val->encoding = ATTR_VAL_ADDRESS;
1155 val->u.uint = read_address(buf, addrsize);
1156 return 1;
1157 case DW_FORM_block2:
1158 val->encoding = ATTR_VAL_BLOCK;
1159 return advance(buf, read_uint16(buf));
1160 case DW_FORM_block4:
1161 val->encoding = ATTR_VAL_BLOCK;
1162 return advance(buf, read_uint32(buf));
1163 case DW_FORM_data2:
1164 val->encoding = ATTR_VAL_UINT;
1165 val->u.uint = read_uint16(buf);
1166 return 1;
1167 case DW_FORM_data4:
1168 val->encoding = ATTR_VAL_UINT;
1169 val->u.uint = read_uint32(buf);
1170 return 1;
1171 case DW_FORM_data8:
1172 val->encoding = ATTR_VAL_UINT;
1173 val->u.uint = read_uint64(buf);
1174 return 1;
1175 case DW_FORM_data16:
1176 val->encoding = ATTR_VAL_BLOCK;
1177 return advance(buf, 16);
1178 case DW_FORM_string:
1179 val->encoding = ATTR_VAL_STRING;
1180 val->u.string = read_string(buf);
1181 return val->u.string == NULL ? 0 : 1;
1182 case DW_FORM_block:
1183 val->encoding = ATTR_VAL_BLOCK;
1184 return advance(buf, read_uleb128(buf));
1185 case DW_FORM_block1:
1186 val->encoding = ATTR_VAL_BLOCK;
1187 return advance(buf, read_byte(buf));
1188 case DW_FORM_data1:
1189 val->encoding = ATTR_VAL_UINT;
1190 val->u.uint = read_byte(buf);
1191 return 1;
1192 case DW_FORM_flag:
1193 val->encoding = ATTR_VAL_UINT;
1194 val->u.uint = read_byte(buf);
1195 return 1;
1196 case DW_FORM_sdata:
1197 val->encoding = ATTR_VAL_SINT;
1198 val->u.sint = read_sleb128(buf);
1199 return 1;
1200 case DW_FORM_strp: {
1201 uint64_t offset;
1202
1203 offset = read_offset(buf, is_dwarf64);
1204 if (offset >= dwarf_sections->size[DEBUG_STR]) {
1205 dwarf_buf_error(buf, "DW_FORM_strp out of range", 0);
1206 return 0;
1207 }
1208 val->encoding = ATTR_VAL_STRING;
1209 val->u.string = (const char *)dwarf_sections->data[DEBUG_STR] + offset;
1210 return 1;
1211 }
1212 case DW_FORM_line_strp: {
1213 uint64_t offset;
1214
1215 offset = read_offset(buf, is_dwarf64);
1216 if (offset >= dwarf_sections->size[DEBUG_LINE_STR]) {
1217 dwarf_buf_error(buf, "DW_FORM_line_strp out of range", 0);
1218 return 0;
1219 }
1220 val->encoding = ATTR_VAL_STRING;
1221 val->u.string =
1222 (const char *)dwarf_sections->data[DEBUG_LINE_STR] + offset;
1223 return 1;
1224 }
1225 case DW_FORM_udata:
1226 val->encoding = ATTR_VAL_UINT;
1227 val->u.uint = read_uleb128(buf);
1228 return 1;
1229 case DW_FORM_ref_addr:
1230 val->encoding = ATTR_VAL_REF_INFO;
1231 if (version == 2)
1232 val->u.uint = read_address(buf, addrsize);
1233 else
1234 val->u.uint = read_offset(buf, is_dwarf64);
1235 return 1;
1236 case DW_FORM_ref1:
1237 val->encoding = ATTR_VAL_REF_UNIT;
1238 val->u.uint = read_byte(buf);
1239 return 1;
1240 case DW_FORM_ref2:
1241 val->encoding = ATTR_VAL_REF_UNIT;
1242 val->u.uint = read_uint16(buf);
1243 return 1;
1244 case DW_FORM_ref4:
1245 val->encoding = ATTR_VAL_REF_UNIT;
1246 val->u.uint = read_uint32(buf);
1247 return 1;
1248 case DW_FORM_ref8:
1249 val->encoding = ATTR_VAL_REF_UNIT;
1250 val->u.uint = read_uint64(buf);
1251 return 1;
1252 case DW_FORM_ref_udata:
1253 val->encoding = ATTR_VAL_REF_UNIT;
1254 val->u.uint = read_uleb128(buf);
1255 return 1;
1256 case DW_FORM_indirect: {
1257 uint64_t form;
1258
1259 form = read_uleb128(buf);
1260 if (form == DW_FORM_implicit_const) {
1261 dwarf_buf_error(buf, "DW_FORM_indirect to DW_FORM_implicit_const", 0);
1262 return 0;
1263 }
1264 return read_attribute((enum dwarf_form)form, 0, buf, is_dwarf64, version,
1265 addrsize, dwarf_sections, altlink, val);
1266 }
1267 case DW_FORM_sec_offset:
1268 val->encoding = ATTR_VAL_REF_SECTION;
1269 val->u.uint = read_offset(buf, is_dwarf64);
1270 return 1;
1271 case DW_FORM_exprloc:
1272 val->encoding = ATTR_VAL_EXPR;
1273 return advance(buf, read_uleb128(buf));
1274 case DW_FORM_flag_present:
1275 val->encoding = ATTR_VAL_UINT;
1276 val->u.uint = 1;
1277 return 1;
1278 case DW_FORM_ref_sig8:
1279 val->encoding = ATTR_VAL_REF_TYPE;
1280 val->u.uint = read_uint64(buf);
1281 return 1;
1282 case DW_FORM_strx:
1283 case DW_FORM_strx1:
1284 case DW_FORM_strx2:
1285 case DW_FORM_strx3:
1286 case DW_FORM_strx4: {
1287 uint64_t offset;
1288
1289 switch (form) {
1290 case DW_FORM_strx:
1291 offset = read_uleb128(buf);
1292 break;
1293 case DW_FORM_strx1:
1294 offset = read_byte(buf);
1295 break;
1296 case DW_FORM_strx2:
1297 offset = read_uint16(buf);
1298 break;
1299 case DW_FORM_strx3:
1300 offset = read_uint24(buf);
1301 break;
1302 case DW_FORM_strx4:
1303 offset = read_uint32(buf);
1304 break;
1305 default:
1306
1307 return 0;
1308 }
1309 val->encoding = ATTR_VAL_STRING_INDEX;
1310 val->u.uint = offset;
1311 return 1;
1312 }
1313 case DW_FORM_addrx:
1314 case DW_FORM_addrx1:
1315 case DW_FORM_addrx2:
1316 case DW_FORM_addrx3:
1317 case DW_FORM_addrx4: {
1318 uint64_t offset;
1319
1320 switch (form) {
1321 case DW_FORM_addrx:
1322 offset = read_uleb128(buf);
1323 break;
1324 case DW_FORM_addrx1:
1325 offset = read_byte(buf);
1326 break;
1327 case DW_FORM_addrx2:
1328 offset = read_uint16(buf);
1329 break;
1330 case DW_FORM_addrx3:
1331 offset = read_uint24(buf);
1332 break;
1333 case DW_FORM_addrx4:
1334 offset = read_uint32(buf);
1335 break;
1336 default:
1337
1338 return 0;
1339 }
1340 val->encoding = ATTR_VAL_ADDRESS_INDEX;
1341 val->u.uint = offset;
1342 return 1;
1343 }
1344 case DW_FORM_ref_sup4:
1345 val->encoding = ATTR_VAL_REF_SECTION;
1346 val->u.uint = read_uint32(buf);
1347 return 1;
1348 case DW_FORM_ref_sup8:
1349 val->encoding = ATTR_VAL_REF_SECTION;
1350 val->u.uint = read_uint64(buf);
1351 return 1;
1352 case DW_FORM_implicit_const:
1353 val->encoding = ATTR_VAL_UINT;
1354 val->u.uint = implicit_val;
1355 return 1;
1356 case DW_FORM_loclistx:
1357
1358 val->encoding = ATTR_VAL_REF_SECTION;
1359 val->u.uint = read_uleb128(buf);
1360 return 1;
1361 case DW_FORM_rnglistx:
1362 val->encoding = ATTR_VAL_RNGLISTS_INDEX;
1363 val->u.uint = read_uleb128(buf);
1364 return 1;
1365 case DW_FORM_GNU_addr_index:
1366 val->encoding = ATTR_VAL_REF_SECTION;
1367 val->u.uint = read_uleb128(buf);
1368 return 1;
1369 case DW_FORM_GNU_str_index:
1370 val->encoding = ATTR_VAL_REF_SECTION;
1371 val->u.uint = read_uleb128(buf);
1372 return 1;
1373 case DW_FORM_GNU_ref_alt:
1374 val->u.uint = read_offset(buf, is_dwarf64);
1375 if (altlink == NULL) {
1376 val->encoding = ATTR_VAL_NONE;
1377 return 1;
1378 }
1379 val->encoding = ATTR_VAL_REF_ALT_INFO;
1380 return 1;
1381 case DW_FORM_strp_sup:
1382 case DW_FORM_GNU_strp_alt: {
1383 uint64_t offset;
1384
1385 offset = read_offset(buf, is_dwarf64);
1386 if (altlink == NULL) {
1387 val->encoding = ATTR_VAL_NONE;
1388 return 1;
1389 }
1390 if (offset >= altlink->dwarf_sections.size[DEBUG_STR]) {
1391 dwarf_buf_error(buf, "DW_FORM_strp_sup out of range", 0);
1392 return 0;
1393 }
1394 val->encoding = ATTR_VAL_STRING;
1395 val->u.string =
1396 (const char *)altlink->dwarf_sections.data[DEBUG_STR] + offset;
1397 return 1;
1398 }
1399 default:
1400 dwarf_buf_error(buf, "unrecognized DWARF form", -1);
1401 return 0;
1402 }
1403}
1404
1405static int resolve_string(const struct dwarf_sections *dwarf_sections,
1406 int is_dwarf64, int is_bigendian,
1407 uint64_t str_offsets_base, const struct attr_val *val,
1408 backtrace_error_callback error_callback, void *data,
1409 const char **string) {
1410 switch (val->encoding) {
1411 case ATTR_VAL_STRING:
1412 *string = val->u.string;
1413 return 1;
1414
1415 case ATTR_VAL_STRING_INDEX: {
1416 uint64_t offset;
1417 struct dwarf_buf offset_buf;
1418
1419 offset = val->u.uint * (is_dwarf64 ? 8 : 4) + str_offsets_base;
1420 if (offset + (is_dwarf64 ? 8 : 4) >
1421 dwarf_sections->size[DEBUG_STR_OFFSETS]) {
1422 error_callback(data, "DW_FORM_strx value out of range", 0);
1423 return 0;
1424 }
1425
1426 offset_buf.name = ".debug_str_offsets";
1427 offset_buf.start = dwarf_sections->data[DEBUG_STR_OFFSETS];
1428 offset_buf.buf = dwarf_sections->data[DEBUG_STR_OFFSETS] + offset;
1429 offset_buf.left = dwarf_sections->size[DEBUG_STR_OFFSETS] - offset;
1430 offset_buf.is_bigendian = is_bigendian;
1431 offset_buf.error_callback = error_callback;
1432 offset_buf.data = data;
1433 offset_buf.reported_underflow = 0;
1434
1435 offset = read_offset(&offset_buf, is_dwarf64);
1436 if (offset >= dwarf_sections->size[DEBUG_STR]) {
1437 dwarf_buf_error(&offset_buf, "DW_FORM_strx offset out of range", 0);
1438 return 0;
1439 }
1440 *string = (const char *)dwarf_sections->data[DEBUG_STR] + offset;
1441 return 1;
1442 }
1443
1444 default:
1445 return 1;
1446 }
1447}
1448
1449static int resolve_addr_index(const struct dwarf_sections *dwarf_sections,
1450 uint64_t addr_base, int addrsize,
1451 int is_bigendian, uint64_t addr_index,
1452 backtrace_error_callback error_callback,
1453 void *data, uint64_t *address) {
1454 uint64_t offset;
1455 struct dwarf_buf addr_buf;
1456
1457 offset = addr_index * addrsize + addr_base;
1458 if (offset + addrsize > dwarf_sections->size[DEBUG_ADDR]) {
1459 error_callback(data, "DW_FORM_addrx value out of range", 0);
1460 return 0;
1461 }
1462
1463 addr_buf.name = ".debug_addr";
1464 addr_buf.start = dwarf_sections->data[DEBUG_ADDR];
1465 addr_buf.buf = dwarf_sections->data[DEBUG_ADDR] + offset;
1466 addr_buf.left = dwarf_sections->size[DEBUG_ADDR] - offset;
1467 addr_buf.is_bigendian = is_bigendian;
1468 addr_buf.error_callback = error_callback;
1469 addr_buf.data = data;
1470 addr_buf.reported_underflow = 0;
1471
1472 *address = read_address(&addr_buf, addrsize);
1473 return 1;
1474}
1475
1476static int units_search(const void *vkey, const void *ventry) {
1477 const size_t *key = (const size_t *)vkey;
1478 const struct unit *entry = *((const struct unit *const *)ventry);
1479 size_t offset;
1480
1481 offset = *key;
1482 if (offset < entry->low_offset)
1483 return -1;
1484 else if (offset >= entry->high_offset)
1485 return 1;
1486 else
1487 return 0;
1488}
1489
1490static struct unit *find_unit(struct unit **pu, size_t units_count,
1491 size_t offset) {
1492 struct unit **u;
1493 u = bsearch(&offset, pu, units_count, sizeof(struct unit *), units_search);
1494 return u == NULL ? NULL : *u;
1495}
1496
1497static int function_addrs_compare(const void *v1, const void *v2) {
1498 const struct function_addrs *a1 = (const struct function_addrs *)v1;
1499 const struct function_addrs *a2 = (const struct function_addrs *)v2;
1500
1501 if (a1->low < a2->low) return -1;
1502 if (a1->low > a2->low) return 1;
1503 if (a1->high < a2->high) return 1;
1504 if (a1->high > a2->high) return -1;
1505 return strcmp(a1->function->name, a2->function->name);
1506}
1507
1508static int function_addrs_search(const void *vkey, const void *ventry) {
1509 const uintptr_t *key = (const uintptr_t *)vkey;
1510 const struct function_addrs *entry = (const struct function_addrs *)ventry;
1511 uintptr_t pc;
1512
1513 pc = *key;
1514 if (pc < entry->low)
1515 return -1;
1516 else if (pc > (entry + 1)->low)
1517 return 1;
1518 else
1519 return 0;
1520}
1521
1522static int add_unit_addr(struct backtrace_state *state, void *rdata,
1523 uint64_t lowpc, uint64_t highpc,
1524 backtrace_error_callback error_callback, void *data,
1525 void *pvec) {
1526 struct unit *u = (struct unit *)rdata;
1527 struct unit_addrs_vector *vec = (struct unit_addrs_vector *)pvec;
1528 struct unit_addrs *p;
1529
1530 if (vec->count > 0) {
1531 p = (struct unit_addrs *)vec->vec.base + (vec->count - 1);
1532 if ((lowpc == p->high || lowpc == p->high + 1) && u == p->u) {
1533 if (highpc > p->high) p->high = highpc;
1534 return 1;
1535 }
1536 }
1537
1538 p = ((struct unit_addrs *)backtrace_vector_grow(
1539 state, sizeof(struct unit_addrs), error_callback, data, &vec->vec));
1540 if (p == NULL) return 0;
1541
1542 p->low = lowpc;
1543 p->high = highpc;
1544 p->u = u;
1545
1546 ++vec->count;
1547
1548 return 1;
1549}
1550
1551static int unit_addrs_compare(const void *v1, const void *v2) {
1552 const struct unit_addrs *a1 = (const struct unit_addrs *)v1;
1553 const struct unit_addrs *a2 = (const struct unit_addrs *)v2;
1554
1555 if (a1->low < a2->low) return -1;
1556 if (a1->low > a2->low) return 1;
1557 if (a1->high < a2->high) return 1;
1558 if (a1->high > a2->high) return -1;
1559 if (a1->u->lineoff < a2->u->lineoff) return -1;
1560 if (a1->u->lineoff > a2->u->lineoff) return 1;
1561 return 0;
1562}
1563
1564static int unit_addrs_search(const void *vkey, const void *ventry) {
1565 const uintptr_t *key = (const uintptr_t *)vkey;
1566 const struct unit_addrs *entry = (const struct unit_addrs *)ventry;
1567 uintptr_t pc;
1568
1569 pc = *key;
1570 if (pc < entry->low)
1571 return -1;
1572 else if (pc > (entry + 1)->low)
1573 return 1;
1574 else
1575 return 0;
1576}
1577
1578static int line_compare(const void *v1, const void *v2) {
1579 const struct line *ln1 = (const struct line *)v1;
1580 const struct line *ln2 = (const struct line *)v2;
1581
1582 if (ln1->pc < ln2->pc)
1583 return -1;
1584 else if (ln1->pc > ln2->pc)
1585 return 1;
1586 else if (ln1->idx < ln2->idx)
1587 return -1;
1588 else if (ln1->idx > ln2->idx)
1589 return 1;
1590 else
1591 return 0;
1592}
1593
1594static int line_search(const void *vkey, const void *ventry) {
1595 const uintptr_t *key = (const uintptr_t *)vkey;
1596 const struct line *entry = (const struct line *)ventry;
1597 uintptr_t pc;
1598
1599 pc = *key;
1600 if (pc < entry->pc)
1601 return -1;
1602 else if (pc >= (entry + 1)->pc)
1603 return 1;
1604 else
1605 return 0;
1606}
1607
1608static int abbrev_compare(const void *v1, const void *v2) {
1609 const struct abbrev *a1 = (const struct abbrev *)v1;
1610 const struct abbrev *a2 = (const struct abbrev *)v2;
1611
1612 if (a1->code < a2->code)
1613 return -1;
1614 else if (a1->code > a2->code)
1615 return 1;
1616 else {
1617 return 0;
1618 }
1619}
1620
1621static int read_abbrevs(struct backtrace_state *state, uint64_t abbrev_offset,
1622 const unsigned char *dwarf_abbrev,
1623 size_t dwarf_abbrev_size, int is_bigendian,
1624 backtrace_error_callback error_callback, void *data,
1625 struct abbrevs *abbrevs) {
1626 struct dwarf_buf abbrev_buf;
1627 struct dwarf_buf count_buf;
1628 size_t num_abbrevs;
1629
1630 abbrevs->num_abbrevs = 0;
1631 abbrevs->abbrevs = NULL;
1632
1633 if (abbrev_offset >= dwarf_abbrev_size) {
1634 error_callback(data, "abbrev offset out of range", 0);
1635 return 0;
1636 }
1637
1638 abbrev_buf.name = ".debug_abbrev";
1639 abbrev_buf.start = dwarf_abbrev;
1640 abbrev_buf.buf = dwarf_abbrev + abbrev_offset;
1641 abbrev_buf.left = dwarf_abbrev_size - abbrev_offset;
1642 abbrev_buf.is_bigendian = is_bigendian;
1643 abbrev_buf.error_callback = error_callback;
1644 abbrev_buf.data = data;
1645 abbrev_buf.reported_underflow = 0;
1646
1647 count_buf = abbrev_buf;
1648 num_abbrevs = 0;
1649 while (read_uleb128(&count_buf) != 0) {
1650 if (count_buf.reported_underflow) return 0;
1651 ++num_abbrevs;
1652
1653 read_uleb128(&count_buf);
1654
1655 read_byte(&count_buf);
1656
1657 while (read_uleb128(&count_buf) != 0) {
1658 uint64_t form;
1659
1660 form = read_uleb128(&count_buf);
1661 if ((enum dwarf_form)form == DW_FORM_implicit_const)
1662 read_sleb128(&count_buf);
1663 }
1664
1665 read_uleb128(&count_buf);
1666 }
1667
1668 if (count_buf.reported_underflow) return 0;
1669
1670 if (num_abbrevs == 0) return 1;
1671
1672 abbrevs->abbrevs = ((struct abbrev *)backtrace_alloc(
1673 state, num_abbrevs * sizeof(struct abbrev), error_callback, data));
1674 if (abbrevs->abbrevs == NULL) return 0;
1675 abbrevs->num_abbrevs = num_abbrevs;
1676 memset(abbrevs->abbrevs, 0, num_abbrevs * sizeof(struct abbrev));
1677
1678 num_abbrevs = 0;
1679 while (1) {
1680 uint64_t code;
1681 struct abbrev a;
1682 size_t num_attrs;
1683 struct attr *attrs;
1684
1685 if (abbrev_buf.reported_underflow) goto fail;
1686
1687 code = read_uleb128(&abbrev_buf);
1688 if (code == 0) break;
1689
1690 a.code = code;
1691 a.tag = (enum dwarf_tag)read_uleb128(&abbrev_buf);
1692 a.has_children = read_byte(&abbrev_buf);
1693
1694 count_buf = abbrev_buf;
1695 num_attrs = 0;
1696 while (read_uleb128(&count_buf) != 0) {
1697 uint64_t form;
1698
1699 ++num_attrs;
1700 form = read_uleb128(&count_buf);
1701 if ((enum dwarf_form)form == DW_FORM_implicit_const)
1702 read_sleb128(&count_buf);
1703 }
1704
1705 if (num_attrs == 0) {
1706 attrs = NULL;
1707 read_uleb128(&abbrev_buf);
1708 read_uleb128(&abbrev_buf);
1709 } else {
1710 attrs = ((struct attr *)backtrace_alloc(state, num_attrs * sizeof *attrs,
1711 error_callback, data));
1712 if (attrs == NULL) goto fail;
1713 num_attrs = 0;
1714 while (1) {
1715 uint64_t name;
1716 uint64_t form;
1717
1718 name = read_uleb128(&abbrev_buf);
1719 form = read_uleb128(&abbrev_buf);
1720 if (name == 0) break;
1721 attrs[num_attrs].name = (enum dwarf_attribute)name;
1722 attrs[num_attrs].form = (enum dwarf_form)form;
1723 if ((enum dwarf_form)form == DW_FORM_implicit_const)
1724 attrs[num_attrs].val = read_sleb128(&abbrev_buf);
1725 else
1726 attrs[num_attrs].val = 0;
1727 ++num_attrs;
1728 }
1729 }
1730
1731 a.num_attrs = num_attrs;
1732 a.attrs = attrs;
1733
1734 abbrevs->abbrevs[num_abbrevs] = a;
1735 ++num_abbrevs;
1736 }
1737
1738 backtrace_qsort(abbrevs->abbrevs, abbrevs->num_abbrevs, sizeof(struct abbrev),
1739 abbrev_compare);
1740
1741 return 1;
1742
1743fail:
1744 free_abbrevs(state, abbrevs, error_callback, data);
1745 return 0;
1746}
1747
1748static const struct abbrev *lookup_abbrev(
1749 struct abbrevs *abbrevs, uint64_t code,
1750 backtrace_error_callback error_callback, void *data) {
1751 struct abbrev key;
1752 void *p;
1753
1754 if (code - 1 < abbrevs->num_abbrevs &&
1755 abbrevs->abbrevs[code - 1].code == code)
1756 return &abbrevs->abbrevs[code - 1];
1757
1758 memset(&key, 0, sizeof key);
1759 key.code = code;
1760 p = bsearch(&key, abbrevs->abbrevs, abbrevs->num_abbrevs,
1761 sizeof(struct abbrev), abbrev_compare);
1762 if (p == NULL) {
1763 error_callback(data, "invalid abbreviation code", 0);
1764 return NULL;
1765 }
1766 return (const struct abbrev *)p;
1767}
1768
1769struct pcrange {
1770 uint64_t lowpc;
1771 int have_lowpc;
1772 int lowpc_is_addr_index;
1773 uint64_t highpc;
1774 int have_highpc;
1775 int highpc_is_relative;
1776 int highpc_is_addr_index;
1777 uint64_t ranges;
1778 int have_ranges;
1779 int ranges_is_index;
1780};
1781
1782static void update_pcrange(const struct attr *attr, const struct attr_val *val,
1783 struct pcrange *pcrange) {
1784 switch (attr->name) {
1785 case DW_AT_low_pc:
1786 if (val->encoding == ATTR_VAL_ADDRESS) {
1787 pcrange->lowpc = val->u.uint;
1788 pcrange->have_lowpc = 1;
1789 } else if (val->encoding == ATTR_VAL_ADDRESS_INDEX) {
1790 pcrange->lowpc = val->u.uint;
1791 pcrange->have_lowpc = 1;
1792 pcrange->lowpc_is_addr_index = 1;
1793 }
1794 break;
1795
1796 case DW_AT_high_pc:
1797 if (val->encoding == ATTR_VAL_ADDRESS) {
1798 pcrange->highpc = val->u.uint;
1799 pcrange->have_highpc = 1;
1800 } else if (val->encoding == ATTR_VAL_UINT) {
1801 pcrange->highpc = val->u.uint;
1802 pcrange->have_highpc = 1;
1803 pcrange->highpc_is_relative = 1;
1804 } else if (val->encoding == ATTR_VAL_ADDRESS_INDEX) {
1805 pcrange->highpc = val->u.uint;
1806 pcrange->have_highpc = 1;
1807 pcrange->highpc_is_addr_index = 1;
1808 }
1809 break;
1810
1811 case DW_AT_ranges:
1812 if (val->encoding == ATTR_VAL_UINT ||
1813 val->encoding == ATTR_VAL_REF_SECTION) {
1814 pcrange->ranges = val->u.uint;
1815 pcrange->have_ranges = 1;
1816 } else if (val->encoding == ATTR_VAL_RNGLISTS_INDEX) {
1817 pcrange->ranges = val->u.uint;
1818 pcrange->have_ranges = 1;
1819 pcrange->ranges_is_index = 1;
1820 }
1821 break;
1822
1823 default:
1824 break;
1825 }
1826}
1827
1828static int add_low_high_range(
1829 struct backtrace_state *state, const struct dwarf_sections *dwarf_sections,
1830 uintptr_t base_address, int is_bigendian, struct unit *u,
1831 const struct pcrange *pcrange,
1832 int (*add_range)(struct backtrace_state *state, void *rdata, uint64_t lowpc,
1833 uint64_t highpc, backtrace_error_callback error_callback,
1834 void *data, void *vec),
1835 void *rdata, backtrace_error_callback error_callback, void *data,
1836 void *vec) {
1837 uint64_t lowpc;
1838 uint64_t highpc;
1839
1840 lowpc = pcrange->lowpc;
1841 if (pcrange->lowpc_is_addr_index) {
1842 if (!resolve_addr_index(dwarf_sections, u->addr_base, u->addrsize,
1843 is_bigendian, lowpc, error_callback, data, &lowpc))
1844 return 0;
1845 }
1846
1847 highpc = pcrange->highpc;
1848 if (pcrange->highpc_is_addr_index) {
1849 if (!resolve_addr_index(dwarf_sections, u->addr_base, u->addrsize,
1850 is_bigendian, highpc, error_callback, data,
1851 &highpc))
1852 return 0;
1853 }
1854 if (pcrange->highpc_is_relative) highpc += lowpc;
1855
1856 lowpc += base_address;
1857 highpc += base_address;
1858
1859 return add_range(state, rdata, lowpc, highpc, error_callback, data, vec);
1860}
1861
1862static int add_ranges_from_ranges(
1863 struct backtrace_state *state, const struct dwarf_sections *dwarf_sections,
1864 uintptr_t base_address, int is_bigendian, struct unit *u, uint64_t base,
1865 const struct pcrange *pcrange,
1866 int (*add_range)(struct backtrace_state *state, void *rdata, uint64_t lowpc,
1867 uint64_t highpc, backtrace_error_callback error_callback,
1868 void *data, void *vec),
1869 void *rdata, backtrace_error_callback error_callback, void *data,
1870 void *vec) {
1871 struct dwarf_buf ranges_buf;
1872
1873 if (pcrange->ranges >= dwarf_sections->size[DEBUG_RANGES]) {
1874 error_callback(data, "ranges offset out of range", 0);
1875 return 0;
1876 }
1877
1878 ranges_buf.name = ".debug_ranges";
1879 ranges_buf.start = dwarf_sections->data[DEBUG_RANGES];
1880 ranges_buf.buf = dwarf_sections->data[DEBUG_RANGES] + pcrange->ranges;
1881 ranges_buf.left = dwarf_sections->size[DEBUG_RANGES] - pcrange->ranges;
1882 ranges_buf.is_bigendian = is_bigendian;
1883 ranges_buf.error_callback = error_callback;
1884 ranges_buf.data = data;
1885 ranges_buf.reported_underflow = 0;
1886
1887 while (1) {
1888 uint64_t low;
1889 uint64_t high;
1890
1891 if (ranges_buf.reported_underflow) return 0;
1892
1893 low = read_address(&ranges_buf, u->addrsize);
1894 high = read_address(&ranges_buf, u->addrsize);
1895
1896 if (low == 0 && high == 0) break;
1897
1898 if (is_highest_address(low, u->addrsize))
1899 base = high;
1900 else {
1901 if (!add_range(state, rdata, low + base + base_address,
1902 high + base + base_address, error_callback, data, vec))
1903 return 0;
1904 }
1905 }
1906
1907 if (ranges_buf.reported_underflow) return 0;
1908
1909 return 1;
1910}
1911
1912static int add_ranges_from_rnglists(
1913 struct backtrace_state *state, const struct dwarf_sections *dwarf_sections,
1914 uintptr_t base_address, int is_bigendian, struct unit *u, uint64_t base,
1915 const struct pcrange *pcrange,
1916 int (*add_range)(struct backtrace_state *state, void *rdata, uint64_t lowpc,
1917 uint64_t highpc, backtrace_error_callback error_callback,
1918 void *data, void *vec),
1919 void *rdata, backtrace_error_callback error_callback, void *data,
1920 void *vec) {
1921 uint64_t offset;
1922 struct dwarf_buf rnglists_buf;
1923
1924 if (!pcrange->ranges_is_index)
1925 offset = pcrange->ranges;
1926 else
1927 offset = u->rnglists_base + pcrange->ranges * (u->is_dwarf64 ? 8 : 4);
1928 if (offset >= dwarf_sections->size[DEBUG_RNGLISTS]) {
1929 error_callback(data, "rnglists offset out of range", 0);
1930 return 0;
1931 }
1932
1933 rnglists_buf.name = ".debug_rnglists";
1934 rnglists_buf.start = dwarf_sections->data[DEBUG_RNGLISTS];
1935 rnglists_buf.buf = dwarf_sections->data[DEBUG_RNGLISTS] + offset;
1936 rnglists_buf.left = dwarf_sections->size[DEBUG_RNGLISTS] - offset;
1937 rnglists_buf.is_bigendian = is_bigendian;
1938 rnglists_buf.error_callback = error_callback;
1939 rnglists_buf.data = data;
1940 rnglists_buf.reported_underflow = 0;
1941
1942 if (pcrange->ranges_is_index) {
1943 offset = read_offset(&rnglists_buf, u->is_dwarf64);
1944 offset += u->rnglists_base;
1945 if (offset >= dwarf_sections->size[DEBUG_RNGLISTS]) {
1946 error_callback(data, "rnglists index offset out of range", 0);
1947 return 0;
1948 }
1949 rnglists_buf.buf = dwarf_sections->data[DEBUG_RNGLISTS] + offset;
1950 rnglists_buf.left = dwarf_sections->size[DEBUG_RNGLISTS] - offset;
1951 }
1952
1953 while (1) {
1954 unsigned char rle;
1955
1956 rle = read_byte(&rnglists_buf);
1957 if (rle == DW_RLE_end_of_list) break;
1958 switch (rle) {
1959 case DW_RLE_base_addressx: {
1960 uint64_t index;
1961
1962 index = read_uleb128(&rnglists_buf);
1963 if (!resolve_addr_index(dwarf_sections, u->addr_base, u->addrsize,
1964 is_bigendian, index, error_callback, data,
1965 &base))
1966 return 0;
1967 } break;
1968
1969 case DW_RLE_startx_endx: {
1970 uint64_t index;
1971 uint64_t low;
1972 uint64_t high;
1973
1974 index = read_uleb128(&rnglists_buf);
1975 if (!resolve_addr_index(dwarf_sections, u->addr_base, u->addrsize,
1976 is_bigendian, index, error_callback, data,
1977 &low))
1978 return 0;
1979 index = read_uleb128(&rnglists_buf);
1980 if (!resolve_addr_index(dwarf_sections, u->addr_base, u->addrsize,
1981 is_bigendian, index, error_callback, data,
1982 &high))
1983 return 0;
1984 if (!add_range(state, rdata, low + base_address, high + base_address,
1985 error_callback, data, vec))
1986 return 0;
1987 } break;
1988
1989 case DW_RLE_startx_length: {
1990 uint64_t index;
1991 uint64_t low;
1992 uint64_t length;
1993
1994 index = read_uleb128(&rnglists_buf);
1995 if (!resolve_addr_index(dwarf_sections, u->addr_base, u->addrsize,
1996 is_bigendian, index, error_callback, data,
1997 &low))
1998 return 0;
1999 length = read_uleb128(&rnglists_buf);
2000 low += base_address;
2001 if (!add_range(state, rdata, low, low + length, error_callback, data,
2002 vec))
2003 return 0;
2004 } break;
2005
2006 case DW_RLE_offset_pair: {
2007 uint64_t low;
2008 uint64_t high;
2009
2010 low = read_uleb128(&rnglists_buf);
2011 high = read_uleb128(&rnglists_buf);
2012 if (!add_range(state, rdata, low + base + base_address,
2013 high + base + base_address, error_callback, data, vec))
2014 return 0;
2015 } break;
2016
2017 case DW_RLE_base_address:
2018 base = read_address(&rnglists_buf, u->addrsize);
2019 break;
2020
2021 case DW_RLE_start_end: {
2022 uint64_t low;
2023 uint64_t high;
2024
2025 low = read_address(&rnglists_buf, u->addrsize);
2026 high = read_address(&rnglists_buf, u->addrsize);
2027 if (!add_range(state, rdata, low + base_address, high + base_address,
2028 error_callback, data, vec))
2029 return 0;
2030 } break;
2031
2032 case DW_RLE_start_length: {
2033 uint64_t low;
2034 uint64_t length;
2035
2036 low = read_address(&rnglists_buf, u->addrsize);
2037 length = read_uleb128(&rnglists_buf);
2038 low += base_address;
2039 if (!add_range(state, rdata, low, low + length, error_callback, data,
2040 vec))
2041 return 0;
2042 } break;
2043
2044 default:
2045 dwarf_buf_error(&rnglists_buf, "unrecognized DW_RLE value", -1);
2046 return 0;
2047 }
2048 }
2049
2050 if (rnglists_buf.reported_underflow) return 0;
2051
2052 return 1;
2053}
2054
2055static int add_ranges(
2056 struct backtrace_state *state, const struct dwarf_sections *dwarf_sections,
2057 uintptr_t base_address, int is_bigendian, struct unit *u, uint64_t base,
2058 const struct pcrange *pcrange,
2059 int (*add_range)(struct backtrace_state *state, void *rdata, uint64_t lowpc,
2060 uint64_t highpc, backtrace_error_callback error_callback,
2061 void *data, void *vec),
2062 void *rdata, backtrace_error_callback error_callback, void *data,
2063 void *vec) {
2064 if (pcrange->have_lowpc && pcrange->have_highpc)
2065 return add_low_high_range(state, dwarf_sections, base_address, is_bigendian,
2066 u, pcrange, add_range, rdata, error_callback,
2067 data, vec);
2068
2069 if (!pcrange->have_ranges) {
2070 return 1;
2071 }
2072
2073 if (u->version < 5)
2074 return add_ranges_from_ranges(state, dwarf_sections, base_address,
2075 is_bigendian, u, base, pcrange, add_range,
2076 rdata, error_callback, data, vec);
2077 else
2078 return add_ranges_from_rnglists(state, dwarf_sections, base_address,
2079 is_bigendian, u, base, pcrange, add_range,
2080 rdata, error_callback, data, vec);
2081}
2082
2083static int find_address_ranges(
2084 struct backtrace_state *state, uintptr_t base_address,
2085 struct dwarf_buf *unit_buf, const struct dwarf_sections *dwarf_sections,
2086 int is_bigendian, struct dwarf_data *altlink,
2087 backtrace_error_callback error_callback, void *data, struct unit *u,
2088 struct unit_addrs_vector *addrs, enum dwarf_tag *unit_tag) {
2089 while (unit_buf->left > 0) {
2090 uint64_t code;
2091 const struct abbrev *abbrev;
2092 struct pcrange pcrange;
2093 struct attr_val name_val;
2094 int have_name_val;
2095 struct attr_val comp_dir_val;
2096 int have_comp_dir_val;
2097 size_t i;
2098
2099 code = read_uleb128(unit_buf);
2100 if (code == 0) return 1;
2101
2102 abbrev = lookup_abbrev(&u->abbrevs, code, error_callback, data);
2103 if (abbrev == NULL) return 0;
2104
2105 if (unit_tag != NULL) *unit_tag = abbrev->tag;
2106
2107 memset(&pcrange, 0, sizeof pcrange);
2108 memset(&name_val, 0, sizeof name_val);
2109 have_name_val = 0;
2110 memset(&comp_dir_val, 0, sizeof comp_dir_val);
2111 have_comp_dir_val = 0;
2112 for (i = 0; i < abbrev->num_attrs; ++i) {
2113 struct attr_val val;
2114
2115 if (!read_attribute(abbrev->attrs[i].form, abbrev->attrs[i].val, unit_buf,
2116 u->is_dwarf64, u->version, u->addrsize,
2117 dwarf_sections, altlink, &val))
2118 return 0;
2119
2120 switch (abbrev->attrs[i].name) {
2121 case DW_AT_low_pc:
2122 case DW_AT_high_pc:
2123 case DW_AT_ranges:
2124 update_pcrange(&abbrev->attrs[i], &val, &pcrange);
2125 break;
2126
2127 case DW_AT_stmt_list:
2128 if ((abbrev->tag == DW_TAG_compile_unit ||
2129 abbrev->tag == DW_TAG_skeleton_unit) &&
2130 (val.encoding == ATTR_VAL_UINT ||
2131 val.encoding == ATTR_VAL_REF_SECTION))
2132 u->lineoff = val.u.uint;
2133 break;
2134
2135 case DW_AT_name:
2136 if (abbrev->tag == DW_TAG_compile_unit ||
2137 abbrev->tag == DW_TAG_skeleton_unit) {
2138 name_val = val;
2139 have_name_val = 1;
2140 }
2141 break;
2142
2143 case DW_AT_comp_dir:
2144 if (abbrev->tag == DW_TAG_compile_unit ||
2145 abbrev->tag == DW_TAG_skeleton_unit) {
2146 comp_dir_val = val;
2147 have_comp_dir_val = 1;
2148 }
2149 break;
2150
2151 case DW_AT_str_offsets_base:
2152 if ((abbrev->tag == DW_TAG_compile_unit ||
2153 abbrev->tag == DW_TAG_skeleton_unit) &&
2154 val.encoding == ATTR_VAL_REF_SECTION)
2155 u->str_offsets_base = val.u.uint;
2156 break;
2157
2158 case DW_AT_addr_base:
2159 if ((abbrev->tag == DW_TAG_compile_unit ||
2160 abbrev->tag == DW_TAG_skeleton_unit) &&
2161 val.encoding == ATTR_VAL_REF_SECTION)
2162 u->addr_base = val.u.uint;
2163 break;
2164
2165 case DW_AT_rnglists_base:
2166 if ((abbrev->tag == DW_TAG_compile_unit ||
2167 abbrev->tag == DW_TAG_skeleton_unit) &&
2168 val.encoding == ATTR_VAL_REF_SECTION)
2169 u->rnglists_base = val.u.uint;
2170 break;
2171
2172 default:
2173 break;
2174 }
2175 }
2176
2177 if (have_name_val) {
2178 if (!resolve_string(dwarf_sections, u->is_dwarf64, is_bigendian,
2179 u->str_offsets_base, &name_val, error_callback, data,
2180 &u->filename))
2181 return 0;
2182 }
2183 if (have_comp_dir_val) {
2184 if (!resolve_string(dwarf_sections, u->is_dwarf64, is_bigendian,
2185 u->str_offsets_base, &comp_dir_val, error_callback,
2186 data, &u->comp_dir))
2187 return 0;
2188 }
2189
2190 if (abbrev->tag == DW_TAG_compile_unit ||
2191 abbrev->tag == DW_TAG_subprogram ||
2192 abbrev->tag == DW_TAG_skeleton_unit) {
2193 if (!add_ranges(state, dwarf_sections, base_address, is_bigendian, u,
2194 pcrange.lowpc, &pcrange, add_unit_addr, (void *)u,
2195 error_callback, data, (void *)addrs))
2196 return 0;
2197
2198 if ((abbrev->tag == DW_TAG_compile_unit ||
2199 abbrev->tag == DW_TAG_skeleton_unit) &&
2200 (pcrange.have_ranges || (pcrange.have_lowpc && pcrange.have_highpc)))
2201 return 1;
2202 }
2203
2204 if (abbrev->has_children) {
2205 if (!find_address_ranges(state, base_address, unit_buf, dwarf_sections,
2206 is_bigendian, altlink, error_callback, data, u,
2207 addrs, NULL))
2208 return 0;
2209 }
2210 }
2211
2212 return 1;
2213}
2214
2215static int build_address_map(struct backtrace_state *state,
2216 uintptr_t base_address,
2217 const struct dwarf_sections *dwarf_sections,
2218 int is_bigendian, struct dwarf_data *altlink,
2219 backtrace_error_callback error_callback,
2220 void *data, struct unit_addrs_vector *addrs,
2221 struct unit_vector *unit_vec) {
2222 struct dwarf_buf info;
2223 struct backtrace_vector units;
2224 size_t units_count;
2225 size_t i;
2226 struct unit **pu;
2227 size_t unit_offset = 0;
2228 struct unit_addrs *pa;
2229
2230 memset(&addrs->vec, 0, sizeof addrs->vec);
2231 memset(&unit_vec->vec, 0, sizeof unit_vec->vec);
2232 addrs->count = 0;
2233 unit_vec->count = 0;
2234
2235 info.name = ".debug_info";
2236 info.start = dwarf_sections->data[DEBUG_INFO];
2237 info.buf = info.start;
2238 info.left = dwarf_sections->size[DEBUG_INFO];
2239 info.is_bigendian = is_bigendian;
2240 info.error_callback = error_callback;
2241 info.data = data;
2242 info.reported_underflow = 0;
2243
2244 memset(&units, 0, sizeof units);
2245 units_count = 0;
2246
2247 while (info.left > 0) {
2248 const unsigned char *unit_data_start;
2249 uint64_t len;
2250 int is_dwarf64;
2251 struct dwarf_buf unit_buf;
2252 int version;
2253 int unit_type;
2254 uint64_t abbrev_offset;
2255 int addrsize;
2256 struct unit *u;
2257 enum dwarf_tag unit_tag;
2258
2259 if (info.reported_underflow) goto fail;
2260
2261 unit_data_start = info.buf;
2262
2263 len = read_initial_length(&info, &is_dwarf64);
2264 unit_buf = info;
2265 unit_buf.left = len;
2266
2267 if (!advance(&info, len)) goto fail;
2268
2269 version = read_uint16(&unit_buf);
2270 if (version < 2 || version > 5) {
2271 dwarf_buf_error(&unit_buf, "unrecognized DWARF version", -1);
2272 goto fail;
2273 }
2274
2275 if (version < 5)
2276 unit_type = 0;
2277 else {
2278 unit_type = read_byte(&unit_buf);
2279 if (unit_type == DW_UT_type || unit_type == DW_UT_split_type) {
2280 continue;
2281 }
2282 }
2283
2284 pu = ((struct unit **)backtrace_vector_grow(state, sizeof(struct unit *),
2285 error_callback, data, &units));
2286 if (pu == NULL) goto fail;
2287
2288 u = ((struct unit *)backtrace_alloc(state, sizeof *u, error_callback,
2289 data));
2290 if (u == NULL) goto fail;
2291
2292 *pu = u;
2293 ++units_count;
2294
2295 if (version < 5)
2296 addrsize = 0;
2297 else
2298 addrsize = read_byte(&unit_buf);
2299
2300 memset(&u->abbrevs, 0, sizeof u->abbrevs);
2301 abbrev_offset = read_offset(&unit_buf, is_dwarf64);
2302 if (!read_abbrevs(state, abbrev_offset, dwarf_sections->data[DEBUG_ABBREV],
2303 dwarf_sections->size[DEBUG_ABBREV], is_bigendian,
2304 error_callback, data, &u->abbrevs))
2305 goto fail;
2306
2307 if (version < 5) addrsize = read_byte(&unit_buf);
2308
2309 switch (unit_type) {
2310 case 0:
2311 break;
2312 case DW_UT_compile:
2313 case DW_UT_partial:
2314 break;
2315 case DW_UT_skeleton:
2316 case DW_UT_split_compile:
2317 read_uint64(&unit_buf);
2318 break;
2319 default:
2320 break;
2321 }
2322
2323 u->low_offset = unit_offset;
2324 unit_offset += len + (is_dwarf64 ? 12 : 4);
2325 u->high_offset = unit_offset;
2326 u->unit_data = unit_buf.buf;
2327 u->unit_data_len = unit_buf.left;
2328 u->unit_data_offset = unit_buf.buf - unit_data_start;
2329 u->version = version;
2330 u->is_dwarf64 = is_dwarf64;
2331 u->addrsize = addrsize;
2332 u->filename = NULL;
2333 u->comp_dir = NULL;
2334 u->abs_filename = NULL;
2335 u->lineoff = 0;
2336 u->str_offsets_base = 0;
2337 u->addr_base = 0;
2338 u->rnglists_base = 0;
2339
2340 u->lines = NULL;
2341 u->lines_count = 0;
2342 u->function_addrs = NULL;
2343 u->function_addrs_count = 0;
2344
2345 if (!find_address_ranges(state, base_address, &unit_buf, dwarf_sections,
2346 is_bigendian, altlink, error_callback, data, u,
2347 addrs, &unit_tag))
2348 goto fail;
2349
2350 if (unit_buf.reported_underflow) goto fail;
2351 }
2352 if (info.reported_underflow) goto fail;
2353
2354 pa = ((struct unit_addrs *)backtrace_vector_grow(
2355 state, sizeof(struct unit_addrs), error_callback, data, &addrs->vec));
2356 if (pa == NULL) goto fail;
2357 pa->low = 0;
2358 --pa->low;
2359 pa->high = pa->low;
2360 pa->u = NULL;
2361
2362 unit_vec->vec = units;
2363 unit_vec->count = units_count;
2364 return 1;
2365
2366fail:
2367 if (units_count > 0) {
2368 pu = (struct unit **)units.base;
2369 for (i = 0; i < units_count; i++) {
2370 free_abbrevs(state, &pu[i]->abbrevs, error_callback, data);
2371 backtrace_free(state, pu[i], sizeof **pu, error_callback, data);
2372 }
2373 backtrace_vector_free(state, &units, error_callback, data);
2374 }
2375 if (addrs->count > 0) {
2376 backtrace_vector_free(state, &addrs->vec, error_callback, data);
2377 addrs->count = 0;
2378 }
2379 return 0;
2380}
2381
2382static int add_line(struct backtrace_state *state, struct dwarf_data *ddata,
2383 uintptr_t pc, const char *filename, int lineno,
2384 backtrace_error_callback error_callback, void *data,
2385 struct line_vector *vec) {
2386 struct line *ln;
2387
2388 if (vec->count > 0) {
2389 ln = (struct line *)vec->vec.base + (vec->count - 1);
2390 if (pc == ln->pc && filename == ln->filename && lineno == ln->lineno)
2391 return 1;
2392 }
2393
2394 ln = ((struct line *)backtrace_vector_grow(state, sizeof(struct line),
2395 error_callback, data, &vec->vec));
2396 if (ln == NULL) return 0;
2397
2398 ln->pc = pc + ddata->base_address;
2399
2400 ln->filename = filename;
2401 ln->lineno = lineno;
2402 ln->idx = vec->count;
2403
2404 ++vec->count;
2405
2406 return 1;
2407}
2408
2409static void free_line_header(struct backtrace_state *state,
2410 struct line_header *hdr,
2411 backtrace_error_callback error_callback,
2412 void *data) {
2413 if (hdr->dirs_count != 0)
2414 backtrace_free(state, hdr->dirs, hdr->dirs_count * sizeof(const char *),
2415 error_callback, data);
2416 backtrace_free(state, hdr->filenames, hdr->filenames_count * sizeof(char *),
2417 error_callback, data);
2418}
2419
2420static int read_v2_paths(struct backtrace_state *state, struct unit *u,
2421 struct dwarf_buf *hdr_buf, struct line_header *hdr) {
2422 const unsigned char *p;
2423 const unsigned char *pend;
2424 size_t i;
2425
2426 hdr->dirs_count = 0;
2427 p = hdr_buf->buf;
2428 pend = p + hdr_buf->left;
2429 while (p < pend && *p != '\0') {
2430 p += strnlen((const char *)p, pend - p) + 1;
2431 ++hdr->dirs_count;
2432 }
2433
2434 ++hdr->dirs_count;
2435 hdr->dirs = ((const char **)backtrace_alloc(
2436 state, hdr->dirs_count * sizeof(const char *), hdr_buf->error_callback,
2437 hdr_buf->data));
2438 if (hdr->dirs == NULL) return 0;
2439
2440 hdr->dirs[0] = u->comp_dir;
2441 i = 1;
2442 while (*hdr_buf->buf != '\0') {
2443 if (hdr_buf->reported_underflow) return 0;
2444
2445 hdr->dirs[i] = read_string(hdr_buf);
2446 if (hdr->dirs[i] == NULL) return 0;
2447 ++i;
2448 }
2449 if (!advance(hdr_buf, 1)) return 0;
2450
2451 hdr->filenames_count = 0;
2452 p = hdr_buf->buf;
2453 pend = p + hdr_buf->left;
2454 while (p < pend && *p != '\0') {
2455 p += strnlen((const char *)p, pend - p) + 1;
2456 p += leb128_len(p);
2457 p += leb128_len(p);
2458 p += leb128_len(p);
2459 ++hdr->filenames_count;
2460 }
2461
2462 ++hdr->filenames_count;
2463 hdr->filenames = ((const char **)backtrace_alloc(
2464 state, hdr->filenames_count * sizeof(char *), hdr_buf->error_callback,
2465 hdr_buf->data));
2466 if (hdr->filenames == NULL) return 0;
2467 hdr->filenames[0] = u->filename;
2468 i = 1;
2469 while (*hdr_buf->buf != '\0') {
2470 const char *filename;
2471 uint64_t dir_index;
2472
2473 if (hdr_buf->reported_underflow) return 0;
2474
2475 filename = read_string(hdr_buf);
2476 if (filename == NULL) return 0;
2477 dir_index = read_uleb128(hdr_buf);
2478 if (IS_ABSOLUTE_PATH(filename) ||
2479 (dir_index < hdr->dirs_count && hdr->dirs[dir_index] == NULL))
2480 hdr->filenames[i] = filename;
2481 else {
2482 const char *dir;
2483 size_t dir_len;
2484 size_t filename_len;
2485 char *s;
2486
2487 if (dir_index < hdr->dirs_count)
2488 dir = hdr->dirs[dir_index];
2489 else {
2490 dwarf_buf_error(hdr_buf,
2491 ("invalid directory index in "
2492 "line number program header"),
2493 0);
2494 return 0;
2495 }
2496 dir_len = strlen(dir);
2497 filename_len = strlen(filename);
2498 s = ((char *)backtrace_alloc(state, dir_len + filename_len + 2,
2499 hdr_buf->error_callback, hdr_buf->data));
2500 if (s == NULL) return 0;
2501 memcpy(s, dir, dir_len);
2502
2503 s[dir_len] = '/';
2504 memcpy(s + dir_len + 1, filename, filename_len + 1);
2505 hdr->filenames[i] = s;
2506 }
2507
2508 read_uleb128(hdr_buf);
2509 read_uleb128(hdr_buf);
2510
2511 ++i;
2512 }
2513
2514 return 1;
2515}
2516
2517static int read_lnct(struct backtrace_state *state, struct dwarf_data *ddata,
2518 struct unit *u, struct dwarf_buf *hdr_buf,
2519 const struct line_header *hdr, size_t formats_count,
2520 const struct line_header_format *formats,
2521 const char **string) {
2522 size_t i;
2523 const char *dir;
2524 const char *path;
2525
2526 dir = NULL;
2527 path = NULL;
2528 for (i = 0; i < formats_count; i++) {
2529 struct attr_val val;
2530
2531 if (!read_attribute(formats[i].form, 0, hdr_buf, u->is_dwarf64, u->version,
2532 hdr->addrsize, &ddata->dwarf_sections, ddata->altlink,
2533 &val))
2534 return 0;
2535 switch (formats[i].lnct) {
2536 case DW_LNCT_path:
2537 if (!resolve_string(&ddata->dwarf_sections, u->is_dwarf64,
2538 ddata->is_bigendian, u->str_offsets_base, &val,
2539 hdr_buf->error_callback, hdr_buf->data, &path))
2540 return 0;
2541 break;
2542 case DW_LNCT_directory_index:
2543 if (val.encoding == ATTR_VAL_UINT) {
2544 if (val.u.uint >= hdr->dirs_count) {
2545 dwarf_buf_error(hdr_buf,
2546 ("invalid directory index in "
2547 "line number program header"),
2548 0);
2549 return 0;
2550 }
2551 dir = hdr->dirs[val.u.uint];
2552 }
2553 break;
2554 default:
2555
2556 break;
2557 }
2558 }
2559
2560 if (path == NULL) {
2561 dwarf_buf_error(hdr_buf, "missing file name in line number program header",
2562 0);
2563 return 0;
2564 }
2565
2566 if (dir == NULL)
2567 *string = path;
2568 else {
2569 size_t dir_len;
2570 size_t path_len;
2571 char *s;
2572
2573 dir_len = strlen(dir);
2574 path_len = strlen(path);
2575 s = (char *)backtrace_alloc(state, dir_len + path_len + 2,
2576 hdr_buf->error_callback, hdr_buf->data);
2577 if (s == NULL) return 0;
2578 memcpy(s, dir, dir_len);
2579
2580 s[dir_len] = '/';
2581 memcpy(s + dir_len + 1, path, path_len + 1);
2582 *string = s;
2583 }
2584
2585 return 1;
2586}
2587
2588static int read_line_header_format_entries(
2589 struct backtrace_state *state, struct dwarf_data *ddata, struct unit *u,
2590 struct dwarf_buf *hdr_buf, struct line_header *hdr, size_t *pcount,
2591 const char ***ppaths) {
2592 size_t formats_count;
2593 struct line_header_format *formats;
2594 size_t paths_count;
2595 const char **paths;
2596 size_t i;
2597 int ret;
2598
2599 formats_count = read_byte(hdr_buf);
2600 if (formats_count == 0)
2601 formats = NULL;
2602 else {
2603 formats = ((struct line_header_format *)backtrace_alloc(
2604 state, (formats_count * sizeof(struct line_header_format)),
2605 hdr_buf->error_callback, hdr_buf->data));
2606 if (formats == NULL) return 0;
2607
2608 for (i = 0; i < formats_count; i++) {
2609 formats[i].lnct = (int)read_uleb128(hdr_buf);
2610 formats[i].form = (enum dwarf_form)read_uleb128(hdr_buf);
2611 }
2612 }
2613
2614 paths_count = read_uleb128(hdr_buf);
2615 if (paths_count == 0) {
2616 *pcount = 0;
2617 *ppaths = NULL;
2618 ret = 1;
2619 goto exit;
2620 }
2621
2622 paths =
2623 ((const char **)backtrace_alloc(state, paths_count * sizeof(const char *),
2624 hdr_buf->error_callback, hdr_buf->data));
2625 if (paths == NULL) {
2626 ret = 0;
2627 goto exit;
2628 }
2629 for (i = 0; i < paths_count; i++) {
2630 if (!read_lnct(state, ddata, u, hdr_buf, hdr, formats_count, formats,
2631 &paths[i])) {
2632 backtrace_free(state, paths, paths_count * sizeof(const char *),
2633 hdr_buf->error_callback, hdr_buf->data);
2634 ret = 0;
2635 goto exit;
2636 }
2637 }
2638
2639 *pcount = paths_count;
2640 *ppaths = paths;
2641
2642 ret = 1;
2643
2644exit:
2645 if (formats != NULL)
2646 backtrace_free(state, formats,
2647 formats_count * sizeof(struct line_header_format),
2648 hdr_buf->error_callback, hdr_buf->data);
2649
2650 return ret;
2651}
2652
2653static int read_line_header(struct backtrace_state *state,
2654 struct dwarf_data *ddata, struct unit *u,
2655 int is_dwarf64, struct dwarf_buf *line_buf,
2656 struct line_header *hdr) {
2657 uint64_t hdrlen;
2658 struct dwarf_buf hdr_buf;
2659
2660 hdr->version = read_uint16(line_buf);
2661 if (hdr->version < 2 || hdr->version > 5) {
2662 dwarf_buf_error(line_buf, "unsupported line number version", -1);
2663 return 0;
2664 }
2665
2666 if (hdr->version < 5)
2667 hdr->addrsize = u->addrsize;
2668 else {
2669 hdr->addrsize = read_byte(line_buf);
2670
2671 if (read_byte(line_buf) != 0) {
2672 dwarf_buf_error(line_buf, "non-zero segment_selector_size not supported",
2673 -1);
2674 return 0;
2675 }
2676 }
2677
2678 hdrlen = read_offset(line_buf, is_dwarf64);
2679
2680 hdr_buf = *line_buf;
2681 hdr_buf.left = hdrlen;
2682
2683 if (!advance(line_buf, hdrlen)) return 0;
2684
2685 hdr->min_insn_len = read_byte(&hdr_buf);
2686 if (hdr->version < 4)
2687 hdr->max_ops_per_insn = 1;
2688 else
2689 hdr->max_ops_per_insn = read_byte(&hdr_buf);
2690
2691 read_byte(&hdr_buf);
2692
2693 hdr->line_base = read_sbyte(&hdr_buf);
2694 hdr->line_range = read_byte(&hdr_buf);
2695
2696 hdr->opcode_base = read_byte(&hdr_buf);
2697 hdr->opcode_lengths = hdr_buf.buf;
2698 if (!advance(&hdr_buf, hdr->opcode_base - 1)) return 0;
2699
2700 if (hdr->version < 5) {
2701 if (!read_v2_paths(state, u, &hdr_buf, hdr)) return 0;
2702 } else {
2703 if (!read_line_header_format_entries(state, ddata, u, &hdr_buf, hdr,
2704 &hdr->dirs_count, &hdr->dirs))
2705 return 0;
2706 if (!read_line_header_format_entries(state, ddata, u, &hdr_buf, hdr,
2707 &hdr->filenames_count,
2708 &hdr->filenames))
2709 return 0;
2710 }
2711
2712 if (hdr_buf.reported_underflow) return 0;
2713
2714 return 1;
2715}
2716
2717static int read_line_program(struct backtrace_state *state,
2718 struct dwarf_data *ddata,
2719 const struct line_header *hdr,
2720 struct dwarf_buf *line_buf,
2721 struct line_vector *vec) {
2722 uint64_t address;
2723 unsigned int op_index;
2724 const char *reset_filename;
2725 const char *filename;
2726 int lineno;
2727
2728 address = 0;
2729 op_index = 0;
2730 if (hdr->filenames_count > 1)
2731 reset_filename = hdr->filenames[1];
2732 else
2733 reset_filename = "";
2734 filename = reset_filename;
2735 lineno = 1;
2736 while (line_buf->left > 0) {
2737 unsigned int op;
2738
2739 op = read_byte(line_buf);
2740 if (op >= hdr->opcode_base) {
2741 unsigned int advance;
2742
2743 op -= hdr->opcode_base;
2744 advance = op / hdr->line_range;
2745 address +=
2746 (hdr->min_insn_len * (op_index + advance) / hdr->max_ops_per_insn);
2747 op_index = (op_index + advance) % hdr->max_ops_per_insn;
2748 lineno += hdr->line_base + (int)(op % hdr->line_range);
2749 add_line(state, ddata, address, filename, lineno,
2750 line_buf->error_callback, line_buf->data, vec);
2751 } else if (op == DW_LNS_extended_op) {
2752 uint64_t len;
2753
2754 len = read_uleb128(line_buf);
2755 op = read_byte(line_buf);
2756 switch (op) {
2757 case DW_LNE_end_sequence:
2758
2759 address = 0;
2760 op_index = 0;
2761 filename = reset_filename;
2762 lineno = 1;
2763 break;
2764 case DW_LNE_set_address:
2765 address = read_address(line_buf, hdr->addrsize);
2766 break;
2767 case DW_LNE_define_file: {
2768 const char *f;
2769 unsigned int dir_index;
2770
2771 f = read_string(line_buf);
2772 if (f == NULL) return 0;
2773 dir_index = read_uleb128(line_buf);
2774
2775 read_uleb128(line_buf);
2776 read_uleb128(line_buf);
2777 if (IS_ABSOLUTE_PATH(f))
2778 filename = f;
2779 else {
2780 const char *dir;
2781 size_t dir_len;
2782 size_t f_len;
2783 char *p;
2784
2785 if (dir_index < hdr->dirs_count)
2786 dir = hdr->dirs[dir_index];
2787 else {
2788 dwarf_buf_error(line_buf,
2789 ("invalid directory index "
2790 "in line number program"),
2791 0);
2792 return 0;
2793 }
2794 dir_len = strlen(dir);
2795 f_len = strlen(f);
2796 p = ((char *)backtrace_alloc(state, dir_len + f_len + 2,
2797 line_buf->error_callback,
2798 line_buf->data));
2799 if (p == NULL) return 0;
2800 memcpy(p, dir, dir_len);
2801
2802 p[dir_len] = '/';
2803 memcpy(p + dir_len + 1, f, f_len + 1);
2804 filename = p;
2805 }
2806 } break;
2807 case DW_LNE_set_discriminator:
2808
2809 read_uleb128(line_buf);
2810 break;
2811 default:
2812 if (!advance(line_buf, len - 1)) return 0;
2813 break;
2814 }
2815 } else {
2816 switch (op) {
2817 case DW_LNS_copy:
2818 add_line(state, ddata, address, filename, lineno,
2819 line_buf->error_callback, line_buf->data, vec);
2820 break;
2821 case DW_LNS_advance_pc: {
2822 uint64_t advance;
2823
2824 advance = read_uleb128(line_buf);
2825 address += (hdr->min_insn_len * (op_index + advance) /
2826 hdr->max_ops_per_insn);
2827 op_index = (op_index + advance) % hdr->max_ops_per_insn;
2828 } break;
2829 case DW_LNS_advance_line:
2830 lineno += (int)read_sleb128(line_buf);
2831 break;
2832 case DW_LNS_set_file: {
2833 uint64_t fileno;
2834
2835 fileno = read_uleb128(line_buf);
2836 if (fileno >= hdr->filenames_count) {
2837 dwarf_buf_error(line_buf,
2838 ("invalid file number in "
2839 "line number program"),
2840 0);
2841 return 0;
2842 }
2843 filename = hdr->filenames[fileno];
2844 } break;
2845 case DW_LNS_set_column:
2846 read_uleb128(line_buf);
2847 break;
2848 case DW_LNS_negate_stmt:
2849 break;
2850 case DW_LNS_set_basic_block:
2851 break;
2852 case DW_LNS_const_add_pc: {
2853 unsigned int advance;
2854
2855 op = 255 - hdr->opcode_base;
2856 advance = op / hdr->line_range;
2857 address += (hdr->min_insn_len * (op_index + advance) /
2858 hdr->max_ops_per_insn);
2859 op_index = (op_index + advance) % hdr->max_ops_per_insn;
2860 } break;
2861 case DW_LNS_fixed_advance_pc:
2862 address += read_uint16(line_buf);
2863 op_index = 0;
2864 break;
2865 case DW_LNS_set_prologue_end:
2866 break;
2867 case DW_LNS_set_epilogue_begin:
2868 break;
2869 case DW_LNS_set_isa:
2870 read_uleb128(line_buf);
2871 break;
2872 default: {
2873 unsigned int i;
2874
2875 for (i = hdr->opcode_lengths[op - 1]; i > 0; --i)
2876 read_uleb128(line_buf);
2877 } break;
2878 }
2879 }
2880 }
2881
2882 return 1;
2883}
2884
2885static int read_line_info(struct backtrace_state *state,
2886 struct dwarf_data *ddata,
2887 backtrace_error_callback error_callback, void *data,
2888 struct unit *u, struct line_header *hdr,
2889 struct line **lines, size_t *lines_count) {
2890 struct line_vector vec;
2891 struct dwarf_buf line_buf;
2892 uint64_t len;
2893 int is_dwarf64;
2894 struct line *ln;
2895
2896 memset(&vec.vec, 0, sizeof vec.vec);
2897 vec.count = 0;
2898
2899 memset(hdr, 0, sizeof *hdr);
2900
2901 if (u->lineoff != (off_t)(size_t)u->lineoff ||
2902 (size_t)u->lineoff >= ddata->dwarf_sections.size[DEBUG_LINE]) {
2903 error_callback(data, "unit line offset out of range", 0);
2904 goto fail;
2905 }
2906
2907 line_buf.name = ".debug_line";
2908 line_buf.start = ddata->dwarf_sections.data[DEBUG_LINE];
2909 line_buf.buf = ddata->dwarf_sections.data[DEBUG_LINE] + u->lineoff;
2910 line_buf.left = ddata->dwarf_sections.size[DEBUG_LINE] - u->lineoff;
2911 line_buf.is_bigendian = ddata->is_bigendian;
2912 line_buf.error_callback = error_callback;
2913 line_buf.data = data;
2914 line_buf.reported_underflow = 0;
2915
2916 len = read_initial_length(&line_buf, &is_dwarf64);
2917 line_buf.left = len;
2918
2919 if (!read_line_header(state, ddata, u, is_dwarf64, &line_buf, hdr)) goto fail;
2920
2921 if (!read_line_program(state, ddata, hdr, &line_buf, &vec)) goto fail;
2922
2923 if (line_buf.reported_underflow) goto fail;
2924
2925 if (vec.count == 0) {
2926 goto fail;
2927 }
2928
2929 ln = ((struct line *)backtrace_vector_grow(state, sizeof(struct line),
2930 error_callback, data, &vec.vec));
2931 if (ln == NULL) goto fail;
2932 ln->pc = (uintptr_t)-1;
2933 ln->filename = NULL;
2934 ln->lineno = 0;
2935 ln->idx = 0;
2936
2937 if (!backtrace_vector_release(state, &vec.vec, error_callback, data))
2938 goto fail;
2939
2940 ln = (struct line *)vec.vec.base;
2941 backtrace_qsort(ln, vec.count, sizeof(struct line), line_compare);
2942
2943 *lines = ln;
2944 *lines_count = vec.count;
2945
2946 return 1;
2947
2948fail:
2949 backtrace_vector_free(state, &vec.vec, error_callback, data);
2950 free_line_header(state, hdr, error_callback, data);
2951 *lines = (struct line *)(uintptr_t)-1;
2952 *lines_count = 0;
2953 return 0;
2954}
2955
2956static const char *read_referenced_name(struct dwarf_data *, struct unit *,
2957 uint64_t, backtrace_error_callback,
2958 void *);
2959
2960static const char *read_referenced_name_from_attr(
2961 struct dwarf_data *ddata, struct unit *u, struct attr *attr,
2962 struct attr_val *val, backtrace_error_callback error_callback, void *data) {
2963 switch (attr->name) {
2964 case DW_AT_abstract_origin:
2965 case DW_AT_specification:
2966 break;
2967 default:
2968 return NULL;
2969 }
2970
2971 if (attr->form == DW_FORM_ref_sig8) return NULL;
2972
2973 if (val->encoding == ATTR_VAL_REF_INFO) {
2974 struct unit *unit =
2975 find_unit(ddata->units, ddata->units_count, val->u.uint);
2976 if (unit == NULL) return NULL;
2977
2978 uint64_t offset = val->u.uint - unit->low_offset;
2979 return read_referenced_name(ddata, unit, offset, error_callback, data);
2980 }
2981
2982 if (val->encoding == ATTR_VAL_UINT || val->encoding == ATTR_VAL_REF_UNIT)
2983 return read_referenced_name(ddata, u, val->u.uint, error_callback, data);
2984
2985 if (val->encoding == ATTR_VAL_REF_ALT_INFO) {
2986 struct unit *alt_unit = find_unit(ddata->altlink->units,
2987 ddata->altlink->units_count, val->u.uint);
2988 if (alt_unit == NULL) return NULL;
2989
2990 uint64_t offset = val->u.uint - alt_unit->low_offset;
2991 return read_referenced_name(ddata->altlink, alt_unit, offset,
2992 error_callback, data);
2993 }
2994
2995 return NULL;
2996}
2997
2998static const char *read_referenced_name(struct dwarf_data *ddata,
2999 struct unit *u, uint64_t offset,
3000 backtrace_error_callback error_callback,
3001 void *data) {
3002 struct dwarf_buf unit_buf;
3003 uint64_t code;
3004 const struct abbrev *abbrev;
3005 const char *ret;
3006 size_t i;
3007
3008 if (offset < u->unit_data_offset ||
3009 offset - u->unit_data_offset >= u->unit_data_len) {
3010 error_callback(data, "abstract origin or specification out of range", 0);
3011 return NULL;
3012 }
3013
3014 offset -= u->unit_data_offset;
3015
3016 unit_buf.name = ".debug_info";
3017 unit_buf.start = ddata->dwarf_sections.data[DEBUG_INFO];
3018 unit_buf.buf = u->unit_data + offset;
3019 unit_buf.left = u->unit_data_len - offset;
3020 unit_buf.is_bigendian = ddata->is_bigendian;
3021 unit_buf.error_callback = error_callback;
3022 unit_buf.data = data;
3023 unit_buf.reported_underflow = 0;
3024
3025 code = read_uleb128(&unit_buf);
3026 if (code == 0) {
3027 dwarf_buf_error(&unit_buf, "invalid abstract origin or specification", 0);
3028 return NULL;
3029 }
3030
3031 abbrev = lookup_abbrev(&u->abbrevs, code, error_callback, data);
3032 if (abbrev == NULL) return NULL;
3033
3034 ret = NULL;
3035 for (i = 0; i < abbrev->num_attrs; ++i) {
3036 struct attr_val val;
3037
3038 if (!read_attribute(abbrev->attrs[i].form, abbrev->attrs[i].val, &unit_buf,
3039 u->is_dwarf64, u->version, u->addrsize,
3040 &ddata->dwarf_sections, ddata->altlink, &val))
3041 return NULL;
3042
3043 switch (abbrev->attrs[i].name) {
3044 case DW_AT_name:
3045
3046 if (ret != NULL) break;
3047 if (!resolve_string(&ddata->dwarf_sections, u->is_dwarf64,
3048 ddata->is_bigendian, u->str_offsets_base, &val,
3049 error_callback, data, &ret))
3050 return NULL;
3051 break;
3052
3053 case DW_AT_linkage_name:
3054 case DW_AT_MIPS_linkage_name:
3055
3056 {
3057 const char *s;
3058
3059 s = NULL;
3060 if (!resolve_string(&ddata->dwarf_sections, u->is_dwarf64,
3061 ddata->is_bigendian, u->str_offsets_base, &val,
3062 error_callback, data, &s))
3063 return NULL;
3064 if (s != NULL) return s;
3065 } break;
3066
3067 case DW_AT_specification:
3068
3069 {
3070 const char *name;
3071
3072 name = read_referenced_name_from_attr(ddata, u, &abbrev->attrs[i], &val,
3073 error_callback, data);
3074 if (name != NULL) ret = name;
3075 } break;
3076
3077 default:
3078 break;
3079 }
3080 }
3081
3082 return ret;
3083}
3084
3085static int add_function_range(struct backtrace_state *state, void *rdata,
3086 uint64_t lowpc, uint64_t highpc,
3087 backtrace_error_callback error_callback,
3088 void *data, void *pvec) {
3089 struct function *function = (struct function *)rdata;
3090 struct function_vector *vec = (struct function_vector *)pvec;
3091 struct function_addrs *p;
3092
3093 if (vec->count > 0) {
3094 p = (struct function_addrs *)vec->vec.base + (vec->count - 1);
3095 if ((lowpc == p->high || lowpc == p->high + 1) && function == p->function) {
3096 if (highpc > p->high) p->high = highpc;
3097 return 1;
3098 }
3099 }
3100
3101 p = ((struct function_addrs *)backtrace_vector_grow(
3102 state, sizeof(struct function_addrs), error_callback, data, &vec->vec));
3103 if (p == NULL) return 0;
3104
3105 p->low = lowpc;
3106 p->high = highpc;
3107 p->function = function;
3108
3109 ++vec->count;
3110
3111 return 1;
3112}
3113
3114static int read_function_entry(struct backtrace_state *state,
3115 struct dwarf_data *ddata, struct unit *u,
3116 uint64_t base, struct dwarf_buf *unit_buf,
3117 const struct line_header *lhdr,
3118 backtrace_error_callback error_callback,
3119 void *data, struct function_vector *vec_function,
3120 struct function_vector *vec_inlined) {
3121 while (unit_buf->left > 0) {
3122 uint64_t code;
3123 const struct abbrev *abbrev;
3124 int is_function;
3125 struct function *function;
3126 struct function_vector *vec;
3127 size_t i;
3128 struct pcrange pcrange;
3129 int have_linkage_name;
3130
3131 code = read_uleb128(unit_buf);
3132 if (code == 0) return 1;
3133
3134 abbrev = lookup_abbrev(&u->abbrevs, code, error_callback, data);
3135 if (abbrev == NULL) return 0;
3136
3137 is_function = (abbrev->tag == DW_TAG_subprogram ||
3138 abbrev->tag == DW_TAG_entry_point ||
3139 abbrev->tag == DW_TAG_inlined_subroutine);
3140
3141 if (abbrev->tag == DW_TAG_inlined_subroutine)
3142 vec = vec_inlined;
3143 else
3144 vec = vec_function;
3145
3146 function = NULL;
3147 if (is_function) {
3148 function = ((struct function *)backtrace_alloc(state, sizeof *function,
3149 error_callback, data));
3150 if (function == NULL) return 0;
3151 memset(function, 0, sizeof *function);
3152 }
3153
3154 memset(&pcrange, 0, sizeof pcrange);
3155 have_linkage_name = 0;
3156 for (i = 0; i < abbrev->num_attrs; ++i) {
3157 struct attr_val val;
3158
3159 if (!read_attribute(abbrev->attrs[i].form, abbrev->attrs[i].val, unit_buf,
3160 u->is_dwarf64, u->version, u->addrsize,
3161 &ddata->dwarf_sections, ddata->altlink, &val))
3162 return 0;
3163
3164 if ((abbrev->tag == DW_TAG_compile_unit ||
3165 abbrev->tag == DW_TAG_skeleton_unit) &&
3166 abbrev->attrs[i].name == DW_AT_low_pc) {
3167 if (val.encoding == ATTR_VAL_ADDRESS)
3168 base = val.u.uint;
3169 else if (val.encoding == ATTR_VAL_ADDRESS_INDEX) {
3170 if (!resolve_addr_index(&ddata->dwarf_sections, u->addr_base,
3171 u->addrsize, ddata->is_bigendian, val.u.uint,
3172 error_callback, data, &base))
3173 return 0;
3174 }
3175 }
3176
3177 if (is_function) {
3178 switch (abbrev->attrs[i].name) {
3179 case DW_AT_call_file:
3180 if (val.encoding == ATTR_VAL_UINT) {
3181 if (val.u.uint >= lhdr->filenames_count) {
3182 dwarf_buf_error(unit_buf,
3183 ("invalid file number in "
3184 "DW_AT_call_file attribute"),
3185 0);
3186 return 0;
3187 }
3188 function->caller_filename = lhdr->filenames[val.u.uint];
3189 }
3190 break;
3191
3192 case DW_AT_call_line:
3193 if (val.encoding == ATTR_VAL_UINT)
3194 function->caller_lineno = val.u.uint;
3195 break;
3196
3197 case DW_AT_abstract_origin:
3198 case DW_AT_specification:
3199
3200 if (have_linkage_name) break;
3201 {
3202 const char *name;
3203
3204 name = read_referenced_name_from_attr(ddata, u, &abbrev->attrs[i],
3205 &val, error_callback, data);
3206 if (name != NULL) function->name = name;
3207 }
3208 break;
3209
3210 case DW_AT_name:
3211
3212 if (function->name != NULL) break;
3213 if (!resolve_string(&ddata->dwarf_sections, u->is_dwarf64,
3214 ddata->is_bigendian, u->str_offsets_base, &val,
3215 error_callback, data, &function->name))
3216 return 0;
3217 break;
3218
3219 case DW_AT_linkage_name:
3220 case DW_AT_MIPS_linkage_name:
3221
3222 {
3223 const char *s;
3224
3225 s = NULL;
3226 if (!resolve_string(&ddata->dwarf_sections, u->is_dwarf64,
3227 ddata->is_bigendian, u->str_offsets_base, &val,
3228 error_callback, data, &s))
3229 return 0;
3230 if (s != NULL) {
3231 function->name = s;
3232 have_linkage_name = 1;
3233 }
3234 } break;
3235
3236 case DW_AT_low_pc:
3237 case DW_AT_high_pc:
3238 case DW_AT_ranges:
3239 update_pcrange(&abbrev->attrs[i], &val, &pcrange);
3240 break;
3241
3242 default:
3243 break;
3244 }
3245 }
3246 }
3247
3248 if (is_function && function->name == NULL) {
3249 backtrace_free(state, function, sizeof *function, error_callback, data);
3250 is_function = 0;
3251 }
3252
3253 if (is_function) {
3254 if (pcrange.have_ranges || (pcrange.have_lowpc && pcrange.have_highpc)) {
3255 if (!add_ranges(state, &ddata->dwarf_sections, ddata->base_address,
3256 ddata->is_bigendian, u, base, &pcrange,
3257 add_function_range, (void *)function, error_callback,
3258 data, (void *)vec))
3259 return 0;
3260 } else {
3261 backtrace_free(state, function, sizeof *function, error_callback, data);
3262 is_function = 0;
3263 }
3264 }
3265
3266 if (abbrev->has_children) {
3267 if (!is_function) {
3268 if (!read_function_entry(state, ddata, u, base, unit_buf, lhdr,
3269 error_callback, data, vec_function,
3270 vec_inlined))
3271 return 0;
3272 } else {
3273 struct function_vector fvec;
3274
3275 memset(&fvec, 0, sizeof fvec);
3276
3277 if (!read_function_entry(state, ddata, u, base, unit_buf, lhdr,
3278 error_callback, data, vec_function, &fvec))
3279 return 0;
3280
3281 if (fvec.count > 0) {
3282 struct function_addrs *p;
3283 struct function_addrs *faddrs;
3284
3285 p = ((struct function_addrs *)backtrace_vector_grow(
3286 state, sizeof(struct function_addrs), error_callback, data,
3287 &fvec.vec));
3288 if (p == NULL) return 0;
3289 p->low = 0;
3290 --p->low;
3291 p->high = p->low;
3292 p->function = NULL;
3293
3294 if (!backtrace_vector_release(state, &fvec.vec, error_callback, data))
3295 return 0;
3296
3297 faddrs = (struct function_addrs *)fvec.vec.base;
3298 backtrace_qsort(faddrs, fvec.count, sizeof(struct function_addrs),
3299 function_addrs_compare);
3300
3301 function->function_addrs = faddrs;
3302 function->function_addrs_count = fvec.count;
3303 }
3304 }
3305 }
3306 }
3307
3308 return 1;
3309}
3310
3311static void read_function_info(
3312 struct backtrace_state *state, struct dwarf_data *ddata,
3313 const struct line_header *lhdr, backtrace_error_callback error_callback,
3314 void *data, struct unit *u, struct function_vector *fvec,
3315 struct function_addrs **ret_addrs, size_t *ret_addrs_count) {
3316 struct function_vector lvec;
3317 struct function_vector *pfvec;
3318 struct dwarf_buf unit_buf;
3319 struct function_addrs *p;
3320 struct function_addrs *addrs;
3321 size_t addrs_count;
3322
3323 if (fvec != NULL)
3324 pfvec = fvec;
3325 else {
3326 memset(&lvec, 0, sizeof lvec);
3327 pfvec = &lvec;
3328 }
3329
3330 unit_buf.name = ".debug_info";
3331 unit_buf.start = ddata->dwarf_sections.data[DEBUG_INFO];
3332 unit_buf.buf = u->unit_data;
3333 unit_buf.left = u->unit_data_len;
3334 unit_buf.is_bigendian = ddata->is_bigendian;
3335 unit_buf.error_callback = error_callback;
3336 unit_buf.data = data;
3337 unit_buf.reported_underflow = 0;
3338
3339 while (unit_buf.left > 0) {
3340 if (!read_function_entry(state, ddata, u, 0, &unit_buf, lhdr,
3341 error_callback, data, pfvec, pfvec))
3342 return;
3343 }
3344
3345 if (pfvec->count == 0) return;
3346
3347 p = ((struct function_addrs *)backtrace_vector_grow(
3348 state, sizeof(struct function_addrs), error_callback, data, &pfvec->vec));
3349 if (p == NULL) return;
3350 p->low = 0;
3351 --p->low;
3352 p->high = p->low;
3353 p->function = NULL;
3354
3355 addrs_count = pfvec->count;
3356
3357 if (fvec == NULL) {
3358 if (!backtrace_vector_release(state, &lvec.vec, error_callback, data))
3359 return;
3360 addrs = (struct function_addrs *)pfvec->vec.base;
3361 } else {
3362 addrs = ((struct function_addrs *)backtrace_vector_finish(
3363 state, &fvec->vec, error_callback, data));
3364 if (addrs == NULL) return;
3365 fvec->count = 0;
3366 }
3367
3368 backtrace_qsort(addrs, addrs_count, sizeof(struct function_addrs),
3369 function_addrs_compare);
3370
3371 *ret_addrs = addrs;
3372 *ret_addrs_count = addrs_count;
3373}
3374
3375static int report_inlined_functions(uintptr_t pc, struct function *function,
3376 backtrace_full_callback callback,
3377 void *data, const char **filename,
3378 int *lineno) {
3379 struct function_addrs *p;
3380 struct function_addrs *match;
3381 struct function *inlined;
3382 int ret;
3383
3384 if (function->function_addrs_count == 0) return 0;
3385
3386 if (pc + 1 == 0) return 0;
3387
3388 p = ((struct function_addrs *)bsearch(
3389 &pc, function->function_addrs, function->function_addrs_count,
3390 sizeof(struct function_addrs), function_addrs_search));
3391 if (p == NULL) return 0;
3392
3393 while (pc == (p + 1)->low) ++p;
3394 match = NULL;
3395 while (1) {
3396 if (pc < p->high) {
3397 match = p;
3398 break;
3399 }
3400 if (p == function->function_addrs) break;
3401 if ((p - 1)->low < p->low) break;
3402 --p;
3403 }
3404 if (match == NULL) return 0;
3405
3406 inlined = match->function;
3407
3408 ret = report_inlined_functions(pc, inlined, callback, data, filename, lineno);
3409 if (ret != 0) return ret;
3410
3411 ret = callback(data, pc, *filename, *lineno, inlined->name);
3412 if (ret != 0) return ret;
3413
3414 *filename = inlined->caller_filename;
3415 *lineno = inlined->caller_lineno;
3416
3417 return 0;
3418}
3419
3420static int dwarf_lookup_pc(struct backtrace_state *state,
3421 struct dwarf_data *ddata, uintptr_t pc,
3422 backtrace_full_callback callback,
3423 backtrace_error_callback error_callback, void *data,
3424 int *found) {
3425 struct unit_addrs *entry;
3426 int found_entry;
3427 struct unit *u;
3428 int new_data;
3429 struct line *lines;
3430 struct line *ln;
3431 struct function_addrs *p;
3432 struct function_addrs *fmatch;
3433 struct function *function;
3434 const char *filename;
3435 int lineno;
3436 int ret;
3437
3438 *found = 1;
3439
3440 entry = (ddata->addrs_count == 0 || pc + 1 == 0
3441 ? NULL
3442 : bsearch(&pc, ddata->addrs, ddata->addrs_count,
3443 sizeof(struct unit_addrs), unit_addrs_search));
3444
3445 if (entry == NULL) {
3446 *found = 0;
3447 return 0;
3448 }
3449
3450 while (pc == (entry + 1)->low) ++entry;
3451 found_entry = 0;
3452 while (1) {
3453 if (pc < entry->high) {
3454 found_entry = 1;
3455 break;
3456 }
3457 if (entry == ddata->addrs) break;
3458 if ((entry - 1)->low < entry->low) break;
3459 --entry;
3460 }
3461 if (!found_entry) {
3462 *found = 0;
3463 return 0;
3464 }
3465
3466 u = entry->u;
3467 lines = u->lines;
3468
3469 while (entry > ddata->addrs && pc >= (entry - 1)->low &&
3470 pc < (entry - 1)->high) {
3471 if (state->threaded)
3472 lines = (struct line *)backtrace_atomic_load_pointer(&u->lines);
3473
3474 if (lines != (struct line *)(uintptr_t)-1) break;
3475
3476 --entry;
3477
3478 u = entry->u;
3479 lines = u->lines;
3480 }
3481
3482 if (state->threaded) lines = backtrace_atomic_load_pointer(&u->lines);
3483
3484 new_data = 0;
3485 if (lines == NULL) {
3486 struct function_addrs *function_addrs;
3487 size_t function_addrs_count;
3488 struct line_header lhdr;
3489 size_t count;
3490
3491 function_addrs = NULL;
3492 function_addrs_count = 0;
3493 if (read_line_info(state, ddata, error_callback, data, entry->u, &lhdr,
3494 &lines, &count)) {
3495 struct function_vector *pfvec;
3496
3497 if (state->threaded)
3498 pfvec = NULL;
3499 else
3500 pfvec = &ddata->fvec;
3501 read_function_info(state, ddata, &lhdr, error_callback, data, entry->u,
3502 pfvec, &function_addrs, &function_addrs_count);
3503 free_line_header(state, &lhdr, error_callback, data);
3504 new_data = 1;
3505 }
3506
3507 if (!state->threaded) {
3508 u->lines_count = count;
3509 u->function_addrs = function_addrs;
3510 u->function_addrs_count = function_addrs_count;
3511 u->lines = lines;
3512 } else {
3513 backtrace_atomic_store_size_t(&u->lines_count, count);
3514 backtrace_atomic_store_pointer(&u->function_addrs, function_addrs);
3515 backtrace_atomic_store_size_t(&u->function_addrs_count,
3516 function_addrs_count);
3517 backtrace_atomic_store_pointer(&u->lines, lines);
3518 }
3519 }
3520
3521 if (lines == (struct line *)(uintptr_t)-1) {
3522 if (new_data)
3523 return dwarf_lookup_pc(state, ddata, pc, callback, error_callback, data,
3524 found);
3525 return callback(data, pc, NULL, 0, NULL);
3526 }
3527
3528 ln = (struct line *)bsearch(&pc, lines, entry->u->lines_count,
3529 sizeof(struct line), line_search);
3530 if (ln == NULL) {
3531 if (entry->u->abs_filename == NULL) {
3532 const char *filename;
3533
3534 filename = entry->u->filename;
3535 if (filename != NULL && !IS_ABSOLUTE_PATH(filename) &&
3536 entry->u->comp_dir != NULL) {
3537 size_t filename_len;
3538 const char *dir;
3539 size_t dir_len;
3540 char *s;
3541
3542 filename_len = strlen(filename);
3543 dir = entry->u->comp_dir;
3544 dir_len = strlen(dir);
3545 s = (char *)backtrace_alloc(state, dir_len + filename_len + 2,
3546 error_callback, data);
3547 if (s == NULL) {
3548 *found = 0;
3549 return 0;
3550 }
3551 memcpy(s, dir, dir_len);
3552
3553 s[dir_len] = '/';
3554 memcpy(s + dir_len + 1, filename, filename_len + 1);
3555 filename = s;
3556 }
3557 entry->u->abs_filename = filename;
3558 }
3559
3560 return callback(data, pc, entry->u->abs_filename, 0, NULL);
3561 }
3562
3563 if (entry->u->function_addrs_count == 0)
3564 return callback(data, pc, ln->filename, ln->lineno, NULL);
3565
3566 p = ((struct function_addrs *)bsearch(
3567 &pc, entry->u->function_addrs, entry->u->function_addrs_count,
3568 sizeof(struct function_addrs), function_addrs_search));
3569 if (p == NULL) return callback(data, pc, ln->filename, ln->lineno, NULL);
3570
3571 while (pc == (p + 1)->low) ++p;
3572 fmatch = NULL;
3573 while (1) {
3574 if (pc < p->high) {
3575 fmatch = p;
3576 break;
3577 }
3578 if (p == entry->u->function_addrs) break;
3579 if ((p - 1)->low < p->low) break;
3580 --p;
3581 }
3582 if (fmatch == NULL) return callback(data, pc, ln->filename, ln->lineno, NULL);
3583
3584 function = fmatch->function;
3585
3586 filename = ln->filename;
3587 lineno = ln->lineno;
3588
3589 ret = report_inlined_functions(pc, function, callback, data, &filename,
3590 &lineno);
3591 if (ret != 0) return ret;
3592
3593 return callback(data, pc, filename, lineno, function->name);
3594}
3595
3596static int dwarf_fileline(struct backtrace_state *state, uintptr_t pc,
3597 backtrace_full_callback callback,
3598 backtrace_error_callback error_callback, void *data) {
3599 struct dwarf_data *ddata;
3600 int found;
3601 int ret;
3602
3603 if (!state->threaded) {
3604 for (ddata = (struct dwarf_data *)state->fileline_data; ddata != NULL;
3605 ddata = ddata->next) {
3606 ret = dwarf_lookup_pc(state, ddata, pc, callback, error_callback, data,
3607 &found);
3608 if (ret != 0 || found) return ret;
3609 }
3610 } else {
3611 struct dwarf_data **pp;
3612
3613 pp = (struct dwarf_data **)(void *)&state->fileline_data;
3614 while (1) {
3615 ddata = backtrace_atomic_load_pointer(pp);
3616 if (ddata == NULL) break;
3617
3618 ret = dwarf_lookup_pc(state, ddata, pc, callback, error_callback, data,
3619 &found);
3620 if (ret != 0 || found) return ret;
3621
3622 pp = &ddata->next;
3623 }
3624 }
3625
3626 return callback(data, pc, NULL, 0, NULL);
3627}
3628
3629static struct dwarf_data *build_dwarf_data(
3630 struct backtrace_state *state, uintptr_t base_address,
3631 const struct dwarf_sections *dwarf_sections, int is_bigendian,
3632 struct dwarf_data *altlink, backtrace_error_callback error_callback,
3633 void *data) {
3634 struct unit_addrs_vector addrs_vec;
3635 struct unit_addrs *addrs;
3636 size_t addrs_count;
3637 struct unit_vector units_vec;
3638 struct unit **units;
3639 size_t units_count;
3640 struct dwarf_data *fdata;
3641
3642 if (!build_address_map(state, base_address, dwarf_sections, is_bigendian,
3643 altlink, error_callback, data, &addrs_vec, &units_vec))
3644 return NULL;
3645
3646 if (!backtrace_vector_release(state, &addrs_vec.vec, error_callback, data))
3647 return NULL;
3648 if (!backtrace_vector_release(state, &units_vec.vec, error_callback, data))
3649 return NULL;
3650 addrs = (struct unit_addrs *)addrs_vec.vec.base;
3651 units = (struct unit **)units_vec.vec.base;
3652 addrs_count = addrs_vec.count;
3653 units_count = units_vec.count;
3654 backtrace_qsort(addrs, addrs_count, sizeof(struct unit_addrs),
3655 unit_addrs_compare);
3656
3657 fdata = ((struct dwarf_data *)backtrace_alloc(
3658 state, sizeof(struct dwarf_data), error_callback, data));
3659 if (fdata == NULL) return NULL;
3660
3661 fdata->next = NULL;
3662 fdata->altlink = altlink;
3663 fdata->base_address = base_address;
3664 fdata->addrs = addrs;
3665 fdata->addrs_count = addrs_count;
3666 fdata->units = units;
3667 fdata->units_count = units_count;
3668 fdata->dwarf_sections = *dwarf_sections;
3669 fdata->is_bigendian = is_bigendian;
3670 memset(&fdata->fvec, 0, sizeof fdata->fvec);
3671
3672 return fdata;
3673}
3674
3675int backtrace_dwarf_add(struct backtrace_state *state, uintptr_t base_address,
3676 const struct dwarf_sections *dwarf_sections,
3677 int is_bigendian, struct dwarf_data *fileline_altlink,
3678 backtrace_error_callback error_callback, void *data,
3679 fileline *fileline_fn,
3680 struct dwarf_data **fileline_entry) {
3681 struct dwarf_data *fdata;
3682
3683 fdata = build_dwarf_data(state, base_address, dwarf_sections, is_bigendian,
3684 fileline_altlink, error_callback, data);
3685 if (fdata == NULL) return 0;
3686
3687 if (fileline_entry != NULL) *fileline_entry = fdata;
3688
3689 if (!state->threaded) {
3690 struct dwarf_data **pp;
3691
3692 for (pp = (struct dwarf_data **)(void *)&state->fileline_data; *pp != NULL;
3693 pp = &(*pp)->next)
3694 ;
3695 *pp = fdata;
3696 } else {
3697 while (1) {
3698 struct dwarf_data **pp;
3699
3700 pp = (struct dwarf_data **)(void *)&state->fileline_data;
3701
3702 while (1) {
3703 struct dwarf_data *p;
3704
3705 p = backtrace_atomic_load_pointer(pp);
3706
3707 if (p == NULL) break;
3708
3709 pp = &p->next;
3710 }
3711
3712 if (__sync_bool_compare_and_swap(pp, NULL, fdata)) break;
3713 }
3714 }
3715
3716 *fileline_fn = dwarf_fileline;
3717
3718 return 1;
3719}
3720
3721// fileline.c:
3722#include <errno.h>
3723#include <fcntl.h>
3724#include <stdlib.h>
3725#include <sys/stat.h>
3726#include <sys/types.h>
3727#include <unistd.h>
3728
3729#if defined(HAVE_KERN_PROC_ARGS) || defined(HAVE_KERN_PROC)
3730#include <sys/sysctl.h>
3731#endif
3732
3733#ifdef HAVE_MACH_O_DYLD_H
3734#include <mach-o/dyld.h>
3735#endif
3736
3737#ifndef HAVE_GETEXECNAME
3738#define getexecname() NULL
3739#endif
3740
3741#if !defined(HAVE_KERN_PROC_ARGS) && !defined(HAVE_KERN_PROC)
3742
3743#define sysctl_exec_name1(state, error_callback, data) NULL
3744#define sysctl_exec_name2(state, error_callback, data) NULL
3745
3746#else
3747static char *sysctl_exec_name(struct backtrace_state *state, int mib0, int mib1,
3748 int mib2, int mib3,
3749 backtrace_error_callback error_callback,
3750 void *data) {
3751 int mib[4];
3752 size_t len;
3753 char *name;
3754 size_t rlen;
3755
3756 mib[0] = mib0;
3757 mib[1] = mib1;
3758 mib[2] = mib2;
3759 mib[3] = mib3;
3760
3761 if (sysctl(mib, 4, NULL, &len, NULL, 0) < 0) return NULL;
3762 name = (char *)backtrace_alloc(state, len, error_callback, data);
3763 if (name == NULL) return NULL;
3764 rlen = len;
3765 if (sysctl(mib, 4, name, &rlen, NULL, 0) < 0) {
3766 backtrace_free(state, name, len, error_callback, data);
3767 return NULL;
3768 }
3769 return name;
3770}
3771
3772#ifdef HAVE_KERN_PROC_ARGS
3773
3774static char *sysctl_exec_name1(struct backtrace_state *state,
3775 backtrace_error_callback error_callback,
3776 void *data) {
3777 return sysctl_exec_name(state, CTL_KERN, KERN_PROC_ARGS, -1,
3778 KERN_PROC_PATHNAME, error_callback, data);
3779}
3780
3781#else
3782
3783#define sysctl_exec_name1(state, error_callback, data) NULL
3784
3785#endif
3786
3787#ifdef HAVE_KERN_PROC
3788
3789static char *sysctl_exec_name2(struct backtrace_state *state,
3790 backtrace_error_callback error_callback,
3791 void *data) {
3792 return sysctl_exec_name(state, CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1,
3793 error_callback, data);
3794}
3795
3796#else
3797
3798#define sysctl_exec_name2(state, error_callback, data) NULL
3799
3800#endif
3801
3802#endif
3803#ifdef HAVE_MACH_O_DYLD_H
3804
3805static char *macho_get_executable_path(struct backtrace_state *state,
3806 backtrace_error_callback error_callback,
3807 void *data) {
3808 uint32_t len;
3809 char *name;
3810
3811 len = 0;
3812 if (_NSGetExecutablePath(NULL, &len) == 0) return NULL;
3813 name = (char *)backtrace_alloc(state, len, error_callback, data);
3814 if (name == NULL) return NULL;
3815 if (_NSGetExecutablePath(name, &len) != 0) {
3816 backtrace_free(state, name, len, error_callback, data);
3817 return NULL;
3818 }
3819 return name;
3820}
3821
3822#else
3823#define macho_get_executable_path(state, error_callback, data) NULL
3824
3825#endif
3826
3827static int fileline_initialize(struct backtrace_state *state,
3828 backtrace_error_callback error_callback,
3829 void *data) {
3830 int failed;
3831 fileline fileline_fn;
3832 int pass;
3833 int called_error_callback;
3834 int descriptor;
3835 const char *filename;
3836 char buf[64];
3837
3838 if (!state->threaded)
3839 failed = state->fileline_initialization_failed;
3840 else
3841 failed = backtrace_atomic_load_int(&state->fileline_initialization_failed);
3842
3843 if (failed) {
3844 error_callback(data, "failed to read executable information", -1);
3845 return 0;
3846 }
3847
3848 if (!state->threaded)
3849 fileline_fn = state->fileline_fn;
3850 else
3851 fileline_fn = backtrace_atomic_load_pointer(&state->fileline_fn);
3852 if (fileline_fn != NULL) return 1;
3853
3854 descriptor = -1;
3855 called_error_callback = 0;
3856 for (pass = 0; pass < 8; ++pass) {
3857 int does_not_exist;
3858
3859 switch (pass) {
3860 case 0:
3861 filename = state->filename;
3862 break;
3863 case 1:
3864 filename = getexecname();
3865 break;
3866 case 2:
3867 filename = "/proc/self/exe";
3868 break;
3869 case 3:
3870 filename = "/proc/curproc/file";
3871 break;
3872 case 4:
3873 snprintf(buf, sizeof(buf), "/proc/%ld/object/a.out", (long)getpid());
3874 filename = buf;
3875 break;
3876 case 5:
3877 filename = sysctl_exec_name1(state, error_callback, data);
3878 break;
3879 case 6:
3880 filename = sysctl_exec_name2(state, error_callback, data);
3881 break;
3882 case 7:
3883 filename = macho_get_executable_path(state, error_callback, data);
3884 break;
3885 default:
3886 abort();
3887 }
3888
3889 if (filename == NULL) continue;
3890
3891 descriptor =
3892 backtrace_open(filename, error_callback, data, &does_not_exist);
3893 if (descriptor < 0 && !does_not_exist) {
3894 called_error_callback = 1;
3895 break;
3896 }
3897 if (descriptor >= 0) break;
3898 }
3899
3900 if (descriptor < 0) {
3901 if (!called_error_callback) {
3902 if (state->filename != NULL)
3903 error_callback(data, state->filename, ENOENT);
3904 else
3905 error_callback(data, "libbacktrace could not find executable to open",
3906 0);
3907 }
3908 failed = 1;
3909 }
3910
3911 if (!failed) {
3912 if (!backtrace_initialize(state, filename, descriptor, error_callback, data,
3913 &fileline_fn))
3914 failed = 1;
3915 }
3916
3917 if (failed) {
3918 if (!state->threaded)
3919 state->fileline_initialization_failed = 1;
3920 else
3921 backtrace_atomic_store_int(&state->fileline_initialization_failed, 1);
3922 return 0;
3923 }
3924
3925 if (!state->threaded)
3926 state->fileline_fn = fileline_fn;
3927 else {
3928 backtrace_atomic_store_pointer(&state->fileline_fn, fileline_fn);
3929 }
3930
3931 return 1;
3932}
3933
3934int backtrace_pcinfo(struct backtrace_state *state, uintptr_t pc,
3935 backtrace_full_callback callback,
3936 backtrace_error_callback error_callback, void *data) {
3937 if (!fileline_initialize(state, error_callback, data)) return 0;
3938
3939 if (state->fileline_initialization_failed) return 0;
3940
3941 return state->fileline_fn(state, pc, callback, error_callback, data);
3942}
3943
3944int backtrace_syminfo(struct backtrace_state *state, uintptr_t pc,
3945 backtrace_syminfo_callback callback,
3946 backtrace_error_callback error_callback, void *data) {
3947 if (!fileline_initialize(state, error_callback, data)) return 0;
3948
3949 if (state->fileline_initialization_failed) return 0;
3950
3951 state->syminfo_fn(state, pc, callback, error_callback, data);
3952 return 1;
3953}
3954
3955void backtrace_syminfo_to_full_callback(void *data, uintptr_t pc,
3956 const char *symname,
3957 uintptr_t symval ATTRIBUTE_UNUSED,
3958 uintptr_t symsize ATTRIBUTE_UNUSED) {
3959 struct backtrace_call_full *bdata = (struct backtrace_call_full *)data;
3960
3961 bdata->ret = bdata->full_callback(bdata->full_data, pc, NULL, 0, symname);
3962}
3963
3964void backtrace_syminfo_to_full_error_callback(void *data, const char *msg,
3965 int errnum) {
3966 struct backtrace_call_full *bdata = (struct backtrace_call_full *)data;
3967
3968 bdata->full_error_callback(bdata->full_data, msg, errnum);
3969}
3970
3971// posix.c:
3972#include <errno.h>
3973#include <fcntl.h>
3974#include <sys/stat.h>
3975#include <sys/types.h>
3976#include <unistd.h>
3977
3978#ifndef O_BINARY
3979#define O_BINARY 0
3980#endif
3981
3982#ifndef O_CLOEXEC
3983#define O_CLOEXEC 0
3984#endif
3985
3986#ifndef FD_CLOEXEC
3987#define FD_CLOEXEC 1
3988#endif
3989
3990int backtrace_open(const char *filename,
3991 backtrace_error_callback error_callback, void *data,
3992 int *does_not_exist) {
3993 int descriptor;
3994
3995 if (does_not_exist != NULL) *does_not_exist = 0;
3996
3997 descriptor = open(filename, (int)(O_RDONLY | O_BINARY | O_CLOEXEC));
3998 if (descriptor < 0) {
3999 if (does_not_exist != NULL && (errno == ENOENT || errno == EACCES))
4000 *does_not_exist = 1;
4001 else
4002 error_callback(data, filename, errno);
4003 return -1;
4004 }
4005
4006#ifdef HAVE_FCNTL
4007
4008 fcntl(descriptor, F_SETFD, FD_CLOEXEC);
4009#endif
4010
4011 return descriptor;
4012}
4013
4014int backtrace_close(int descriptor, backtrace_error_callback error_callback,
4015 void *data) {
4016 if (close(descriptor) < 0) {
4017 error_callback(data, "close", errno);
4018 return 0;
4019 }
4020 return 1;
4021}
4022
4023// print.c:
4024#include <stdio.h>
4025#include <string.h>
4026#include <sys/types.h>
4027
4028struct print_data {
4029 struct backtrace_state *state;
4030 FILE *f;
4031};
4032
4033static int print_callback(void *data, uintptr_t pc, const char *filename,
4034 int lineno, const char *function) {
4035 struct print_data *pdata = (struct print_data *)data;
4036
4037 fprintf(pdata->f, "0x%lx %s\n\t%s:%d\n", (unsigned long)pc,
4038 function == NULL ? "???" : function,
4039 filename == NULL ? "???" : filename, lineno);
4040 return 0;
4041}
4042
4043static void error_callback(void *data, const char *msg, int errnum) {
4044 struct print_data *pdata = (struct print_data *)data;
4045
4046 if (pdata->state->filename != NULL)
4047 fprintf(stderr, "%s: ", pdata->state->filename);
4048 fprintf(stderr, "libbacktrace: %s", msg);
4049 if (errnum > 0) fprintf(stderr, ": %s", strerror(errnum));
4050 fputc('\n', stderr);
4051}
4052
4053void __attribute__((noinline))
4054backtrace_print(struct backtrace_state *state, int skip, FILE *f) {
4055 struct print_data data;
4056
4057 data.state = state;
4058 data.f = f;
4059 backtrace_full(state, skip + 1, print_callback, error_callback,
4060 (void *)&data);
4061}
4062
4063// sort.c:
4064#include <stddef.h>
4065#include <sys/types.h>
4066
4067static void swap(char *a, char *b, size_t size) {
4068 size_t i;
4069
4070 for (i = 0; i < size; i++, a++, b++) {
4071 char t;
4072
4073 t = *a;
4074 *a = *b;
4075 *b = t;
4076 }
4077}
4078
4079void backtrace_qsort(void *basearg, size_t count, size_t size,
4080 int (*compar)(const void *, const void *)) {
4081 char *base = (char *)basearg;
4082 size_t i;
4083 size_t mid;
4084
4085tail_recurse:
4086 if (count < 2) return;
4087
4088 swap(base, base + (count / 2) * size, size);
4089
4090 mid = 0;
4091 for (i = 1; i < count; i++) {
4092 if ((*compar)(base, base + i * size) > 0) {
4093 ++mid;
4094 if (i != mid) swap(base + mid * size, base + i * size, size);
4095 }
4096 }
4097
4098 if (mid > 0) swap(base, base + mid * size, size);
4099
4100 if (2 * mid < count) {
4101 backtrace_qsort(base, mid, size, compar);
4102 base += (mid + 1) * size;
4103 count -= mid + 1;
4104 goto tail_recurse;
4105 } else {
4106 backtrace_qsort(base + (mid + 1) * size, count - (mid + 1), size, compar);
4107 count = mid;
4108 goto tail_recurse;
4109 }
4110}
4111
4112// state.c:
4113#include <string.h>
4114#include <sys/types.h>
4115
4116struct backtrace_state *backtrace_create_state(
4117 const char *filename, int threaded, backtrace_error_callback error_callback,
4118 void *data) {
4119 struct backtrace_state init_state;
4120 struct backtrace_state *state;
4121
4122#ifndef HAVE_SYNC_FUNCTIONS
4123 if (threaded) {
4124 error_callback(data, "backtrace library does not support threads", 0);
4125 return NULL;
4126 }
4127#endif
4128
4129 memset(&init_state, 0, sizeof init_state);
4130 init_state.filename = filename;
4131 init_state.threaded = threaded;
4132
4133 state = ((struct backtrace_state *)backtrace_alloc(&init_state, sizeof *state,
4134 error_callback, data));
4135 if (state == NULL) return NULL;
4136 *state = init_state;
4137
4138 return state;
4139}
4140
4141// backtrace.c:
4142#include <sys/types.h>
4143
4144#ifdef BACKTRACE_SUPPORTED
4145#include <unwind.h>
4146
4147struct backtrace_data {
4148 int skip;
4149
4150 struct backtrace_state *state;
4151
4152 backtrace_full_callback callback;
4153
4154 backtrace_error_callback error_callback;
4155
4156 void *data;
4157
4158 int ret;
4159
4160 int can_alloc;
4161};
4162
4163static _Unwind_Reason_Code unwind(struct _Unwind_Context *context,
4164 void *vdata) {
4165 struct backtrace_data *bdata = (struct backtrace_data *)vdata;
4166 uintptr_t pc;
4167 int ip_before_insn = 0;
4168
4169#ifdef HAVE_GETIPINFO
4170 pc = _Unwind_GetIPInfo(context, &ip_before_insn);
4171#else
4172 pc = _Unwind_GetIP(context);
4173#endif
4174
4175 if (bdata->skip > 0) {
4176 --bdata->skip;
4177 return _URC_NO_REASON;
4178 }
4179
4180 if (!ip_before_insn) --pc;
4181
4182 if (!bdata->can_alloc)
4183 bdata->ret = bdata->callback(bdata->data, pc, NULL, 0, NULL);
4184 else
4185 bdata->ret = backtrace_pcinfo(bdata->state, pc, bdata->callback,
4186 bdata->error_callback, bdata->data);
4187 if (bdata->ret != 0) return _URC_END_OF_STACK;
4188
4189 return _URC_NO_REASON;
4190}
4191
4192int __attribute__((noinline))
4193backtrace_full(struct backtrace_state *state, int skip,
4194 backtrace_full_callback callback,
4195 backtrace_error_callback error_callback, void *data) {
4196 struct backtrace_data bdata;
4197 void *p;
4198
4199 bdata.skip = skip + 1;
4200 bdata.state = state;
4201 bdata.callback = callback;
4202 bdata.error_callback = error_callback;
4203 bdata.data = data;
4204 bdata.ret = 0;
4205
4206 p = backtrace_alloc(state, 4096, NULL, NULL);
4207 if (p == NULL)
4208 bdata.can_alloc = 0;
4209 else {
4210 backtrace_free(state, p, 4096, NULL, NULL);
4211 bdata.can_alloc = 1;
4212 }
4213
4214 _Unwind_Backtrace(unwind, &bdata);
4215 return bdata.ret;
4216}
4217#else
4218// Copied from nounwind.c
4219int
4220backtrace_full (struct backtrace_state *state ATTRIBUTE_UNUSED,
4221 int skip ATTRIBUTE_UNUSED,
4222 backtrace_full_callback callback ATTRIBUTE_UNUSED,
4223 backtrace_error_callback error_callback, void *data)
4224{
4225 error_callback (data,
4226 "no stack trace because unwind library not available",
4227 0);
4228 return 0;
4229}
4230#endif
4231
4232// simple.c:
4233#ifdef BACKTRACE_SUPPORTED
4234#include <unwind.h>
4235
4236struct backtrace_simple_data {
4237 int skip;
4238
4239 struct backtrace_state *state;
4240
4241 backtrace_simple_callback callback;
4242
4243 backtrace_error_callback error_callback;
4244
4245 void *data;
4246
4247 int ret;
4248};
4249
4250static _Unwind_Reason_Code simple_unwind(struct _Unwind_Context *context,
4251 void *vdata) {
4252 struct backtrace_simple_data *bdata = (struct backtrace_simple_data *)vdata;
4253 uintptr_t pc;
4254 int ip_before_insn = 0;
4255
4256#ifdef HAVE_GETIPINFO
4257 pc = _Unwind_GetIPInfo(context, &ip_before_insn);
4258#else
4259 pc = _Unwind_GetIP(context);
4260#endif
4261
4262 if (bdata->skip > 0) {
4263 --bdata->skip;
4264 return _URC_NO_REASON;
4265 }
4266
4267 if (!ip_before_insn) --pc;
4268
4269 bdata->ret = bdata->callback(bdata->data, pc);
4270
4271 if (bdata->ret != 0) return _URC_END_OF_STACK;
4272
4273 return _URC_NO_REASON;
4274}
4275
4276int __attribute__((noinline))
4277backtrace_simple(struct backtrace_state *state, int skip,
4278 backtrace_simple_callback callback,
4279 backtrace_error_callback error_callback, void *data) {
4280 struct backtrace_simple_data bdata;
4281
4282 bdata.skip = skip + 1;
4283 bdata.state = state;
4284 bdata.callback = callback;
4285 bdata.error_callback = error_callback;
4286 bdata.data = data;
4287 bdata.ret = 0;
4288 _Unwind_Backtrace(simple_unwind, &bdata);
4289 return bdata.ret;
4290}
4291#else
4292int
4293backtrace_simple (struct backtrace_state *state ATTRIBUTE_UNUSED,
4294 int skip ATTRIBUTE_UNUSED,
4295 backtrace_simple_callback callback ATTRIBUTE_UNUSED,
4296 backtrace_error_callback error_callback, void *data)
4297{
4298 error_callback (data,
4299 "no stack trace because unwind library not available",
4300 0);
4301 return 0;
4302}
4303#endif