[ruby/win32ole] Undefine allocator of WIN32OLE_VARIABLE to get rid of warning
[ruby-80x24.org.git] / addr2line.c
blobf660be912961240e571ff39dad61044e8525bf19
1 /**********************************************************************
3 addr2line.c -
5 $Author$
7 Copyright (C) 2010 Shinichiro Hamaji
9 **********************************************************************/
11 #if defined(__clang__)
12 #pragma clang diagnostic ignored "-Wgnu-empty-initializer"
13 #pragma clang diagnostic ignored "-Wgcc-compat"
14 #endif
16 #include "ruby/internal/config.h"
17 #include "ruby/defines.h"
18 #include "ruby/missing.h"
19 #include "addr2line.h"
21 #include <stdio.h>
22 #include <errno.h>
24 #ifdef HAVE_LIBPROC_H
25 #include <libproc.h>
26 #endif
28 #include "ruby/internal/stdbool.h"
30 #if defined(USE_ELF) || defined(HAVE_MACH_O_LOADER_H)
32 #include <fcntl.h>
33 #include <limits.h>
34 #include <stdio.h>
35 #include <stdint.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <sys/mman.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <unistd.h>
43 /* Make alloca work the best possible way. */
44 #ifdef __GNUC__
45 # ifndef alloca
46 # define alloca __builtin_alloca
47 # endif
48 #else
49 # ifdef HAVE_ALLOCA_H
50 # include <alloca.h>
51 # else
52 # ifdef _AIX
53 #pragma alloca
54 # else
55 # ifndef alloca /* predefined by HP cc +Olibcalls */
56 void *alloca();
57 # endif
58 # endif /* AIX */
59 # endif /* HAVE_ALLOCA_H */
60 #endif /* __GNUC__ */
62 #ifdef HAVE_DLADDR
63 # include <dlfcn.h>
64 #endif
66 #ifdef HAVE_MACH_O_LOADER_H
67 # include <crt_externs.h>
68 # include <mach-o/fat.h>
69 # include <mach-o/loader.h>
70 # include <mach-o/nlist.h>
71 # include <mach-o/stab.h>
72 #endif
74 #ifdef USE_ELF
75 # ifdef __OpenBSD__
76 # include <elf_abi.h>
77 # else
78 # include <elf.h>
79 # endif
81 #ifndef ElfW
82 # if SIZEOF_VOIDP == 8
83 # define ElfW(x) Elf64##_##x
84 # else
85 # define ElfW(x) Elf32##_##x
86 # endif
87 #endif
88 #ifndef ELF_ST_TYPE
89 # if SIZEOF_VOIDP == 8
90 # define ELF_ST_TYPE ELF64_ST_TYPE
91 # else
92 # define ELF_ST_TYPE ELF32_ST_TYPE
93 # endif
94 #endif
95 #endif
97 #ifdef SHF_COMPRESSED
98 # if defined(ELFCOMPRESS_ZLIB) && defined(HAVE_LIBZ)
99 /* FreeBSD 11.0 lacks ELFCOMPRESS_ZLIB */
100 # include <zlib.h>
101 # define SUPPORT_COMPRESSED_DEBUG_LINE
102 # endif
103 #else /* compatibility with glibc < 2.22 */
104 # define SHF_COMPRESSED 0
105 #endif
107 #ifndef PATH_MAX
108 #define PATH_MAX 4096
109 #endif
111 #define DW_LNS_copy 0x01
112 #define DW_LNS_advance_pc 0x02
113 #define DW_LNS_advance_line 0x03
114 #define DW_LNS_set_file 0x04
115 #define DW_LNS_set_column 0x05
116 #define DW_LNS_negate_stmt 0x06
117 #define DW_LNS_set_basic_block 0x07
118 #define DW_LNS_const_add_pc 0x08
119 #define DW_LNS_fixed_advance_pc 0x09
120 #define DW_LNS_set_prologue_end 0x0a /* DWARF3 */
121 #define DW_LNS_set_epilogue_begin 0x0b /* DWARF3 */
122 #define DW_LNS_set_isa 0x0c /* DWARF3 */
124 /* Line number extended opcode name. */
125 #define DW_LNE_end_sequence 0x01
126 #define DW_LNE_set_address 0x02
127 #define DW_LNE_define_file 0x03
128 #define DW_LNE_set_discriminator 0x04 /* DWARF4 */
130 PRINTF_ARGS(static int kprintf(const char *fmt, ...), 1, 2);
132 typedef struct line_info {
133 const char *dirname;
134 const char *filename;
135 const char *path; /* object path */
136 int line;
138 uintptr_t base_addr;
139 uintptr_t saddr;
140 const char *sname; /* function name */
142 struct line_info *next;
143 } line_info_t;
145 struct dwarf_section {
146 char *ptr;
147 size_t size;
148 uint64_t flags;
151 typedef struct obj_info {
152 const char *path; /* object path */
153 char *mapped;
154 size_t mapped_size;
155 void *uncompressed;
156 uintptr_t base_addr;
157 uintptr_t vmaddr;
158 struct dwarf_section debug_abbrev;
159 struct dwarf_section debug_info;
160 struct dwarf_section debug_line;
161 struct dwarf_section debug_ranges;
162 struct dwarf_section debug_rnglists;
163 struct dwarf_section debug_str;
164 struct obj_info *next;
165 } obj_info_t;
167 #define DWARF_SECTION_COUNT 6
169 static struct dwarf_section *
170 obj_dwarf_section_at(obj_info_t *obj, int n)
172 struct dwarf_section *ary[] = {
173 &obj->debug_abbrev,
174 &obj->debug_info,
175 &obj->debug_line,
176 &obj->debug_ranges,
177 &obj->debug_rnglists,
178 &obj->debug_str
180 if (n < 0 || DWARF_SECTION_COUNT <= n) {
181 abort();
183 return ary[n];
186 struct debug_section_definition {
187 const char *name;
188 struct dwarf_section *dwarf;
191 /* Avoid consuming stack as this module may be used from signal handler */
192 static char binary_filename[PATH_MAX + 1];
194 static unsigned long
195 uleb128(const char **p)
197 unsigned long r = 0;
198 int s = 0;
199 for (;;) {
200 unsigned char b = (unsigned char)*(*p)++;
201 if (b < 0x80) {
202 r += (unsigned long)b << s;
203 break;
205 r += (b & 0x7f) << s;
206 s += 7;
208 return r;
211 static long
212 sleb128(const char **p)
214 long r = 0;
215 int s = 0;
216 for (;;) {
217 unsigned char b = (unsigned char)*(*p)++;
218 if (b < 0x80) {
219 if (b & 0x40) {
220 r -= (0x80 - b) << s;
222 else {
223 r += (b & 0x3f) << s;
225 break;
227 r += (b & 0x7f) << s;
228 s += 7;
230 return r;
233 static const char *
234 get_nth_dirname(unsigned long dir, const char *p)
236 if (!dir--) {
237 return "";
239 while (dir--) {
240 while (*p) p++;
241 p++;
242 if (!*p) {
243 kprintf("Unexpected directory number %lu in %s\n",
244 dir, binary_filename);
245 return "";
248 return p;
251 static void
252 fill_filename(int file, const char *include_directories, const char *filenames, line_info_t *line, obj_info_t *obj)
254 int i;
255 const char *p = filenames;
256 const char *filename;
257 unsigned long dir;
258 for (i = 1; i <= file; i++) {
259 filename = p;
260 if (!*p) {
261 /* Need to output binary file name? */
262 kprintf("Unexpected file number %d in %s at %tx\n",
263 file, binary_filename, filenames - obj->mapped);
264 return;
266 while (*p) p++;
267 p++;
268 dir = uleb128(&p);
269 /* last modified. */
270 uleb128(&p);
271 /* size of the file. */
272 uleb128(&p);
274 if (i == file) {
275 line->filename = filename;
276 line->dirname = get_nth_dirname(dir, include_directories);
281 static void
282 fill_line(int num_traces, void **traces, uintptr_t addr, int file, int line,
283 const char *include_directories, const char *filenames,
284 obj_info_t *obj, line_info_t *lines, int offset)
286 int i;
287 addr += obj->base_addr - obj->vmaddr;
288 for (i = offset; i < num_traces; i++) {
289 uintptr_t a = (uintptr_t)traces[i];
290 /* We assume one line code doesn't result >100 bytes of native code.
291 We may want more reliable way eventually... */
292 if (addr < a && a < addr + 100) {
293 fill_filename(file, include_directories, filenames, &lines[i], obj);
294 lines[i].line = line;
299 struct LineNumberProgramHeader {
300 uint64_t unit_length;
301 uint16_t version;
302 uint8_t format; /* 4 or 8 */
303 uint64_t header_length;
304 uint8_t minimum_instruction_length;
305 uint8_t maximum_operations_per_instruction;
306 uint8_t default_is_stmt;
307 int8_t line_base;
308 uint8_t line_range;
309 uint8_t opcode_base;
310 /* uint8_t standard_opcode_lengths[opcode_base-1]; */
311 const char *include_directories;
312 const char *filenames;
313 const char *cu_start;
314 const char *cu_end;
317 static int
318 parse_debug_line_header(const char **pp, struct LineNumberProgramHeader *header)
320 const char *p = *pp;
321 header->unit_length = *(uint32_t *)p;
322 p += sizeof(uint32_t);
324 header->format = 4;
325 if (header->unit_length == 0xffffffff) {
326 header->unit_length = *(uint64_t *)p;
327 p += sizeof(uint64_t);
328 header->format = 8;
331 header->cu_end = p + header->unit_length;
333 header->version = *(uint16_t *)p;
334 p += sizeof(uint16_t);
335 if (header->version > 4) return -1;
337 header->header_length = header->format == 4 ? *(uint32_t *)p : *(uint64_t *)p;
338 p += header->format;
339 header->cu_start = p + header->header_length;
341 header->minimum_instruction_length = *(uint8_t *)p++;
343 if (header->version >= 4) {
344 /* maximum_operations_per_instruction = *(uint8_t *)p; */
345 if (*p != 1) return -1; /* For non-VLIW architectures, this field is 1 */
346 p++;
349 header->default_is_stmt = *(uint8_t *)p++;
350 header->line_base = *(int8_t *)p++;
351 header->line_range = *(uint8_t *)p++;
352 header->opcode_base = *(uint8_t *)p++;
353 /* header->standard_opcode_lengths = (uint8_t *)p - 1; */
354 p += header->opcode_base - 1;
356 header->include_directories = p;
358 /* temporary measure for compress-debug-sections */
359 if (p >= header->cu_end) return -1;
361 /* skip include directories */
362 while (*p) {
363 p = memchr(p, '\0', header->cu_end - p);
364 if (!p) return -1;
365 p++;
367 p++;
369 header->filenames = p;
371 *pp = header->cu_start;
373 return 0;
376 static int
377 parse_debug_line_cu(int num_traces, void **traces, const char **debug_line,
378 obj_info_t *obj, line_info_t *lines, int offset)
380 const char *p = (const char *)*debug_line;
381 struct LineNumberProgramHeader header;
383 /* The registers. */
384 unsigned long addr = 0;
385 unsigned int file = 1;
386 unsigned int line = 1;
387 /* unsigned int column = 0; */
388 int is_stmt;
389 /* int basic_block = 0; */
390 /* int end_sequence = 0; */
391 /* int prologue_end = 0; */
392 /* int epilogue_begin = 0; */
393 /* unsigned int isa = 0; */
395 if (parse_debug_line_header(&p, &header))
396 return -1;
397 is_stmt = header.default_is_stmt;
399 #define FILL_LINE() \
400 do { \
401 fill_line(num_traces, traces, addr, file, line, \
402 header.include_directories, \
403 header.filenames, \
404 obj, lines, offset); \
405 /*basic_block = prologue_end = epilogue_begin = 0;*/ \
406 } while (0)
408 while (p < header.cu_end) {
409 unsigned long a;
410 unsigned char op = *p++;
411 switch (op) {
412 case DW_LNS_copy:
413 FILL_LINE();
414 break;
415 case DW_LNS_advance_pc:
416 a = uleb128(&p) * header.minimum_instruction_length;
417 addr += a;
418 break;
419 case DW_LNS_advance_line: {
420 long a = sleb128(&p);
421 line += a;
422 break;
424 case DW_LNS_set_file:
425 file = (unsigned int)uleb128(&p);
426 break;
427 case DW_LNS_set_column:
428 /*column = (unsigned int)*/(void)uleb128(&p);
429 break;
430 case DW_LNS_negate_stmt:
431 is_stmt = !is_stmt;
432 break;
433 case DW_LNS_set_basic_block:
434 /*basic_block = 1; */
435 break;
436 case DW_LNS_const_add_pc:
437 a = ((255UL - header.opcode_base) / header.line_range) *
438 header.minimum_instruction_length;
439 addr += a;
440 break;
441 case DW_LNS_fixed_advance_pc:
442 a = *(uint16_t *)p;
443 p += sizeof(uint16_t);
444 addr += a;
445 break;
446 case DW_LNS_set_prologue_end:
447 /* prologue_end = 1; */
448 break;
449 case DW_LNS_set_epilogue_begin:
450 /* epilogue_begin = 1; */
451 break;
452 case DW_LNS_set_isa:
453 /* isa = (unsigned int)*/(void)uleb128(&p);
454 break;
455 case 0:
456 a = uleb128(&p);
457 op = *p++;
458 switch (op) {
459 case DW_LNE_end_sequence:
460 /* end_sequence = 1; */
461 FILL_LINE();
462 addr = 0;
463 file = 1;
464 line = 1;
465 /* column = 0; */
466 is_stmt = header.default_is_stmt;
467 /* end_sequence = 0; */
468 /* isa = 0; */
469 break;
470 case DW_LNE_set_address:
471 addr = *(unsigned long *)p;
472 p += sizeof(unsigned long);
473 break;
474 case DW_LNE_define_file:
475 kprintf("Unsupported operation in %s\n",
476 binary_filename);
477 break;
478 case DW_LNE_set_discriminator:
479 /* TODO:currently ignore */
480 uleb128(&p);
481 break;
482 default:
483 kprintf("Unknown extended opcode: %d in %s\n",
484 op, binary_filename);
486 break;
487 default: {
488 uint8_t adjusted_opcode = op - header.opcode_base;
489 uint8_t operation_advance = adjusted_opcode / header.line_range;
490 /* NOTE: this code doesn't support VLIW */
491 addr += operation_advance * header.minimum_instruction_length;
492 line += header.line_base + (adjusted_opcode % header.line_range);
493 FILL_LINE();
497 *debug_line = (char *)p;
498 return 0;
501 static int
502 parse_debug_line(int num_traces, void **traces,
503 const char *debug_line, unsigned long size,
504 obj_info_t *obj, line_info_t *lines, int offset)
506 const char *debug_line_end = debug_line + size;
507 while (debug_line < debug_line_end) {
508 if (parse_debug_line_cu(num_traces, traces, &debug_line, obj, lines, offset))
509 return -1;
511 if (debug_line != debug_line_end) {
512 kprintf("Unexpected size of .debug_line in %s\n",
513 binary_filename);
515 return 0;
518 /* read file and fill lines */
519 static uintptr_t
520 fill_lines(int num_traces, void **traces, int check_debuglink,
521 obj_info_t **objp, line_info_t *lines, int offset);
523 static void
524 append_obj(obj_info_t **objp)
526 obj_info_t *newobj = calloc(1, sizeof(obj_info_t));
527 if (*objp) (*objp)->next = newobj;
528 *objp = newobj;
531 #ifdef USE_ELF
532 /* Ideally we should check 4 paths to follow gnu_debuglink:
534 * - /usr/lib/debug/.build-id/ab/cdef1234.debug
535 * - /usr/bin/ruby.debug
536 * - /usr/bin/.debug/ruby.debug
537 * - /usr/lib/debug/usr/bin/ruby.debug.
539 * but we handle only two cases for now as the two formats are
540 * used by some linux distributions.
542 * See GDB's info for detail.
543 * https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html
546 // check the path pattern of "/usr/lib/debug/usr/bin/ruby.debug"
547 static void
548 follow_debuglink(const char *debuglink, int num_traces, void **traces,
549 obj_info_t **objp, line_info_t *lines, int offset)
551 static const char global_debug_dir[] = "/usr/lib/debug";
552 const size_t global_debug_dir_len = sizeof(global_debug_dir) - 1;
553 char *p;
554 obj_info_t *o1 = *objp, *o2;
555 size_t len;
557 p = strrchr(binary_filename, '/');
558 if (!p) {
559 return;
561 p[1] = '\0';
563 len = strlen(binary_filename);
564 if (len >= PATH_MAX - global_debug_dir_len)
565 len = PATH_MAX - global_debug_dir_len - 1;
566 memmove(binary_filename + global_debug_dir_len, binary_filename, len);
567 memcpy(binary_filename, global_debug_dir, global_debug_dir_len);
568 len += global_debug_dir_len;
569 strlcpy(binary_filename + len, debuglink, PATH_MAX - len);
571 append_obj(objp);
572 o2 = *objp;
573 o2->base_addr = o1->base_addr;
574 o2->path = o1->path;
575 fill_lines(num_traces, traces, 0, objp, lines, offset);
578 // check the path pattern of "/usr/lib/debug/.build-id/ab/cdef1234.debug"
579 static void
580 follow_debuglink_build_id(const char *build_id, size_t build_id_size, int num_traces, void **traces,
581 obj_info_t **objp, line_info_t *lines, int offset)
583 static const char global_debug_dir[] = "/usr/lib/debug/.build-id/";
584 const size_t global_debug_dir_len = sizeof(global_debug_dir) - 1;
585 char *p;
586 obj_info_t *o1 = *objp, *o2;
587 size_t i;
589 if (PATH_MAX < global_debug_dir_len + 1 + build_id_size * 2 + 6) return;
591 memcpy(binary_filename, global_debug_dir, global_debug_dir_len);
592 p = binary_filename + global_debug_dir_len;
593 for (i = 0; i < build_id_size; i++) {
594 static const char tbl[] = "0123456789abcdef";
595 unsigned char n = build_id[i];
596 *p++ = tbl[n / 16];
597 *p++ = tbl[n % 16];
598 if (i == 0) *p++ = '/';
600 strcpy(p, ".debug");
602 append_obj(objp);
603 o2 = *objp;
604 o2->base_addr = o1->base_addr;
605 o2->path = o1->path;
606 fill_lines(num_traces, traces, 0, objp, lines, offset);
608 #endif
610 enum
612 DW_TAG_compile_unit = 0x11,
613 DW_TAG_inlined_subroutine = 0x1d,
614 DW_TAG_subprogram = 0x2e,
617 /* Attributes encodings */
618 enum
620 DW_AT_sibling = 0x01,
621 DW_AT_location = 0x02,
622 DW_AT_name = 0x03,
623 /* Reserved 0x04 */
624 /* Reserved 0x05 */
625 /* Reserved 0x06 */
626 /* Reserved 0x07 */
627 /* Reserved 0x08 */
628 DW_AT_ordering = 0x09,
629 /* Reserved 0x0a */
630 DW_AT_byte_size = 0x0b,
631 /* Reserved 0x0c */
632 DW_AT_bit_size = 0x0d,
633 /* Reserved 0x0e */
634 /* Reserved 0x0f */
635 DW_AT_stmt_list = 0x10,
636 DW_AT_low_pc = 0x11,
637 DW_AT_high_pc = 0x12,
638 DW_AT_language = 0x13,
639 /* Reserved 0x14 */
640 DW_AT_discr = 0x15,
641 DW_AT_discr_value = 0x16,
642 DW_AT_visibility = 0x17,
643 DW_AT_import = 0x18,
644 DW_AT_string_length = 0x19,
645 DW_AT_common_reference = 0x1a,
646 DW_AT_comp_dir = 0x1b,
647 DW_AT_const_value = 0x1c,
648 DW_AT_containing_type = 0x1d,
649 DW_AT_default_value = 0x1e,
650 /* Reserved 0x1f */
651 DW_AT_inline = 0x20,
652 DW_AT_is_optional = 0x21,
653 DW_AT_lower_bound = 0x22,
654 /* Reserved 0x23 */
655 /* Reserved 0x24 */
656 DW_AT_producer = 0x25,
657 /* Reserved 0x26 */
658 DW_AT_prototyped = 0x27,
659 /* Reserved 0x28 */
660 /* Reserved 0x29 */
661 DW_AT_return_addr = 0x2a,
662 /* Reserved 0x2b */
663 DW_AT_start_scope = 0x2c,
664 /* Reserved 0x2d */
665 DW_AT_bit_stride = 0x2e,
666 DW_AT_upper_bound = 0x2f,
667 /* Reserved 0x30 */
668 DW_AT_abstract_origin = 0x31,
669 DW_AT_accessibility = 0x32,
670 DW_AT_address_class = 0x33,
671 DW_AT_artificial = 0x34,
672 DW_AT_base_types = 0x35,
673 DW_AT_calling_convention = 0x36,
674 DW_AT_count = 0x37,
675 DW_AT_data_member_location = 0x38,
676 DW_AT_decl_column = 0x39,
677 DW_AT_decl_file = 0x3a,
678 DW_AT_decl_line = 0x3b,
679 DW_AT_declaration = 0x3c,
680 DW_AT_discr_list = 0x3d,
681 DW_AT_encoding = 0x3e,
682 DW_AT_external = 0x3f,
683 DW_AT_frame_base = 0x40,
684 DW_AT_friend = 0x41,
685 DW_AT_identifier_case = 0x42,
686 /* Reserved 0x43 */
687 DW_AT_namelist_item = 0x44,
688 DW_AT_priority = 0x45,
689 DW_AT_segment = 0x46,
690 DW_AT_specification = 0x47,
691 DW_AT_static_link = 0x48,
692 DW_AT_type = 0x49,
693 DW_AT_use_location = 0x4a,
694 DW_AT_variable_parameter = 0x4b,
695 DW_AT_virtuality = 0x4c,
696 DW_AT_vtable_elem_location = 0x4d,
697 DW_AT_allocated = 0x4e,
698 DW_AT_associated = 0x4f,
699 DW_AT_data_location = 0x50,
700 DW_AT_byte_stride = 0x51,
701 DW_AT_entry_pc = 0x52,
702 DW_AT_use_UTF8 = 0x53,
703 DW_AT_extension = 0x54,
704 DW_AT_ranges = 0x55,
705 DW_AT_trampoline = 0x56,
706 DW_AT_call_column = 0x57,
707 DW_AT_call_file = 0x58,
708 DW_AT_call_line = 0x59,
709 DW_AT_description = 0x5a,
710 DW_AT_binary_scale = 0x5b,
711 DW_AT_decimal_scale = 0x5c,
712 DW_AT_small = 0x5d,
713 DW_AT_decimal_sign = 0x5e,
714 DW_AT_digit_count = 0x5f,
715 DW_AT_picture_string = 0x60,
716 DW_AT_mutable = 0x61,
717 DW_AT_threads_scaled = 0x62,
718 DW_AT_explicit = 0x63,
719 DW_AT_object_pointer = 0x64,
720 DW_AT_endianity = 0x65,
721 DW_AT_elemental = 0x66,
722 DW_AT_pure = 0x67,
723 DW_AT_recursive = 0x68,
724 DW_AT_signature = 0x69,
725 DW_AT_main_subprogram = 0x6a,
726 DW_AT_data_bit_offset = 0x6b,
727 DW_AT_const_expr = 0x6c,
728 DW_AT_enum_class = 0x6d,
729 DW_AT_linkage_name = 0x6e,
730 DW_AT_string_length_bit_size = 0x6f,
731 DW_AT_string_length_byte_size = 0x70,
732 DW_AT_rank = 0x71,
733 DW_AT_str_offsets_base = 0x72,
734 DW_AT_addr_base = 0x73,
735 DW_AT_rnglists_base = 0x74,
736 /* Reserved 0x75 */
737 DW_AT_dwo_name = 0x76,
738 DW_AT_reference = 0x77,
739 DW_AT_rvalue_reference = 0x78,
740 DW_AT_macros = 0x79,
741 DW_AT_call_all_calls = 0x7a,
742 DW_AT_call_all_source_calls = 0x7b,
743 DW_AT_call_all_tail_calls = 0x7c,
744 DW_AT_call_return_pc = 0x7d,
745 DW_AT_call_value = 0x7e,
746 DW_AT_call_origin = 0x7f,
747 DW_AT_call_parameter = 0x80,
748 DW_AT_call_pc = 0x81,
749 DW_AT_call_tail_call = 0x82,
750 DW_AT_call_target = 0x83,
751 DW_AT_call_target_clobbered = 0x84,
752 DW_AT_call_data_location = 0x85,
753 DW_AT_call_data_value = 0x86,
754 DW_AT_noreturn = 0x87,
755 DW_AT_alignment = 0x88,
756 DW_AT_export_symbols = 0x89,
757 DW_AT_deleted = 0x8a,
758 DW_AT_defaulted = 0x8b,
759 DW_AT_loclists_base = 0x8c,
760 DW_AT_lo_user = 0x2000,
761 DW_AT_hi_user = 0x3fff
764 /* Attribute form encodings */
765 enum
767 DW_FORM_addr = 0x01,
768 /* Reserved 0x02 */
769 DW_FORM_block2 = 0x03,
770 DW_FORM_block4 = 0x04,
771 DW_FORM_data2 = 0x05,
772 DW_FORM_data4 = 0x06,
773 DW_FORM_data8 = 0x07,
774 DW_FORM_string = 0x08,
775 DW_FORM_block = 0x09,
776 DW_FORM_block1 = 0x0a,
777 DW_FORM_data1 = 0x0b,
778 DW_FORM_flag = 0x0c,
779 DW_FORM_sdata = 0x0d,
780 DW_FORM_strp = 0x0e,
781 DW_FORM_udata = 0x0f,
782 DW_FORM_ref_addr = 0x10,
783 DW_FORM_ref1 = 0x11,
784 DW_FORM_ref2 = 0x12,
785 DW_FORM_ref4 = 0x13,
786 DW_FORM_ref8 = 0x14,
787 DW_FORM_ref_udata = 0x15,
788 DW_FORM_indirect = 0x16,
789 DW_FORM_sec_offset = 0x17,
790 DW_FORM_exprloc = 0x18,
791 DW_FORM_flag_present = 0x19,
792 DW_FORM_strx = 0x1a,
793 DW_FORM_addrx = 0x1b,
794 DW_FORM_ref_sup4 = 0x1c,
795 DW_FORM_strp_sup = 0x1d,
796 DW_FORM_data16 = 0x1e,
797 DW_FORM_line_strp = 0x1f,
798 DW_FORM_ref_sig8 = 0x20,
799 DW_FORM_implicit_const = 0x21,
800 DW_FORM_loclistx = 0x22,
801 DW_FORM_rnglistx = 0x23,
802 DW_FORM_ref_sup8 = 0x24,
803 DW_FORM_strx1 = 0x25,
804 DW_FORM_strx2 = 0x26,
805 DW_FORM_strx3 = 0x27,
806 DW_FORM_strx4 = 0x28,
807 DW_FORM_addrx1 = 0x29,
808 DW_FORM_addrx2 = 0x2a,
809 DW_FORM_addrx3 = 0x2b,
810 DW_FORM_addrx4 = 0x2c
813 /* Range list entry encodings */
814 enum {
815 DW_RLE_end_of_list = 0x00,
816 DW_RLE_base_addressx = 0x01,
817 DW_RLE_startx_endx = 0x02,
818 DW_RLE_startx_length = 0x03,
819 DW_RLE_offset_pair = 0x04,
820 DW_RLE_base_address = 0x05,
821 DW_RLE_start_end = 0x06,
822 DW_RLE_start_length = 0x07
825 enum {
826 VAL_none = 0,
827 VAL_cstr = 1,
828 VAL_data = 2,
829 VAL_uint = 3,
830 VAL_int = 4
833 # define ABBREV_TABLE_SIZE 256
834 typedef struct {
835 obj_info_t *obj;
836 const char *file;
837 const char *current_cu;
838 uint64_t current_low_pc;
839 const char *debug_line_cu_end;
840 const char *debug_line_files;
841 const char *debug_line_directories;
842 const char *p;
843 const char *cu_end;
844 const char *pend;
845 const char *q0;
846 const char *q;
847 int format; // 4 or 8
848 uint8_t address_size;
849 int level;
850 const char *abbrev_table[ABBREV_TABLE_SIZE];
851 } DebugInfoReader;
853 typedef struct {
854 ptrdiff_t pos;
855 int tag;
856 int has_children;
857 } DIE;
859 typedef struct {
860 union {
861 const char *ptr;
862 uint64_t uint64;
863 int64_t int64;
864 } as;
865 uint64_t off;
866 uint64_t at;
867 uint64_t form;
868 size_t size;
869 int type;
870 } DebugInfoValue;
872 /* TODO: Big Endian */
873 #define MERGE_2INTS(a,b,sz) (((uint64_t)(b)<<sz)|(a))
875 static uint16_t
876 get_uint16(const uint8_t *p)
878 return (uint16_t)MERGE_2INTS(p[0],p[1],8);
881 static uint32_t
882 get_uint32(const uint8_t *p)
884 return (uint32_t)MERGE_2INTS(get_uint16(p),get_uint16(p+2),16);
887 static uint64_t
888 get_uint64(const uint8_t *p)
890 return MERGE_2INTS(get_uint32(p),get_uint32(p+4),32);
893 static uint8_t
894 read_uint8(const char **ptr)
896 const char *p = *ptr;
897 *ptr = (p + 1);
898 return (uint8_t)*p;
901 static uint16_t
902 read_uint16(const char **ptr)
904 const char *p = *ptr;
905 *ptr = (p + 2);
906 return get_uint16((const uint8_t *)p);
909 static uint32_t
910 read_uint24(const char **ptr)
912 const char *p = *ptr;
913 *ptr = (p + 3);
914 return ((uint8_t)*p << 16) | get_uint16((const uint8_t *)p+1);
917 static uint32_t
918 read_uint32(const char **ptr)
920 const char *p = *ptr;
921 *ptr = (p + 4);
922 return get_uint32((const uint8_t *)p);
925 static uint64_t
926 read_uint64(const char **ptr)
928 const unsigned char *p = (const unsigned char *)*ptr;
929 *ptr = (char *)(p + 8);
930 return get_uint64(p);
933 static uintptr_t
934 read_uintptr(const char **ptr)
936 const unsigned char *p = (const unsigned char *)*ptr;
937 *ptr = (char *)(p + SIZEOF_VOIDP);
938 #if SIZEOF_VOIDP == 8
939 return get_uint64(p);
940 #else
941 return get_uint32(p);
942 #endif
945 static uint64_t
946 read_uint(DebugInfoReader *reader)
948 if (reader->format == 4) {
949 return read_uint32(&reader->p);
950 } else { /* 64 bit */
951 return read_uint64(&reader->p);
955 static uint64_t
956 read_uleb128(DebugInfoReader *reader)
958 return uleb128(&reader->p);
961 static int64_t
962 read_sleb128(DebugInfoReader *reader)
964 return sleb128(&reader->p);
967 static void
968 debug_info_reader_init(DebugInfoReader *reader, obj_info_t *obj)
970 reader->file = obj->mapped;
971 reader->obj = obj;
972 reader->p = obj->debug_info.ptr;
973 reader->pend = obj->debug_info.ptr + obj->debug_info.size;
974 reader->debug_line_cu_end = obj->debug_line.ptr;
975 reader->current_low_pc = 0;
978 static void
979 di_skip_die_attributes(const char **p)
981 for (;;) {
982 uint64_t at = uleb128(p);
983 uint64_t form = uleb128(p);
984 if (!at && !form) break;
985 switch (form) {
986 default:
987 break;
988 case DW_FORM_implicit_const:
989 sleb128(p);
990 break;
995 static void
996 di_read_debug_abbrev_cu(DebugInfoReader *reader)
998 uint64_t prev = 0;
999 const char *p = reader->q0;
1000 for (;;) {
1001 uint64_t abbrev_number = uleb128(&p);
1002 if (abbrev_number <= prev) break;
1003 if (abbrev_number < ABBREV_TABLE_SIZE) {
1004 reader->abbrev_table[abbrev_number] = p;
1006 prev = abbrev_number;
1007 uleb128(&p); /* tag */
1008 p++; /* has_children */
1009 di_skip_die_attributes(&p);
1013 static int
1014 di_read_debug_line_cu(DebugInfoReader *reader)
1016 const char *p;
1017 struct LineNumberProgramHeader header;
1019 p = (const char *)reader->debug_line_cu_end;
1020 if (parse_debug_line_header(&p, &header))
1021 return -1;
1023 reader->debug_line_cu_end = (char *)header.cu_end;
1024 reader->debug_line_directories = (char *)header.include_directories;
1025 reader->debug_line_files = (char *)header.filenames;
1027 return 0;
1030 static void
1031 set_uint_value(DebugInfoValue *v, uint64_t n)
1033 v->as.uint64 = n;
1034 v->type = VAL_uint;
1037 static void
1038 set_int_value(DebugInfoValue *v, int64_t n)
1040 v->as.int64 = n;
1041 v->type = VAL_int;
1044 static void
1045 set_cstr_value(DebugInfoValue *v, const char *s)
1047 v->as.ptr = s;
1048 v->off = 0;
1049 v->type = VAL_cstr;
1052 static void
1053 set_cstrp_value(DebugInfoValue *v, const char *s, uint64_t off)
1055 v->as.ptr = s;
1056 v->off = off;
1057 v->type = VAL_cstr;
1060 static void
1061 set_data_value(DebugInfoValue *v, const char *s)
1063 v->as.ptr = s;
1064 v->type = VAL_data;
1067 static const char *
1068 get_cstr_value(DebugInfoValue *v)
1070 if (v->as.ptr) {
1071 return v->as.ptr + v->off;
1072 } else {
1073 return NULL;
1077 static void
1078 debug_info_reader_read_value(DebugInfoReader *reader, uint64_t form, DebugInfoValue *v)
1080 switch (form) {
1081 case DW_FORM_addr:
1082 if (reader->address_size == 4) {
1083 set_uint_value(v, read_uint32(&reader->p));
1084 } else if (reader->address_size == 8) {
1085 set_uint_value(v, read_uint64(&reader->p));
1086 } else {
1087 fprintf(stderr,"unknown address_size:%d", reader->address_size);
1088 abort();
1090 break;
1091 case DW_FORM_block2:
1092 v->size = read_uint16(&reader->p);
1093 set_data_value(v, reader->p);
1094 reader->p += v->size;
1095 break;
1096 case DW_FORM_block4:
1097 v->size = read_uint32(&reader->p);
1098 set_data_value(v, reader->p);
1099 reader->p += v->size;
1100 break;
1101 case DW_FORM_data2:
1102 set_uint_value(v, read_uint16(&reader->p));
1103 break;
1104 case DW_FORM_data4:
1105 set_uint_value(v, read_uint32(&reader->p));
1106 break;
1107 case DW_FORM_data8:
1108 set_uint_value(v, read_uint64(&reader->p));
1109 break;
1110 case DW_FORM_string:
1111 v->size = strlen(reader->p);
1112 set_cstr_value(v, reader->p);
1113 reader->p += v->size + 1;
1114 break;
1115 case DW_FORM_block:
1116 v->size = uleb128(&reader->p);
1117 set_data_value(v, reader->p);
1118 reader->p += v->size;
1119 break;
1120 case DW_FORM_block1:
1121 v->size = read_uint8(&reader->p);
1122 set_data_value(v, reader->p);
1123 reader->p += v->size;
1124 break;
1125 case DW_FORM_data1:
1126 set_uint_value(v, read_uint8(&reader->p));
1127 break;
1128 case DW_FORM_flag:
1129 set_uint_value(v, read_uint8(&reader->p));
1130 break;
1131 case DW_FORM_sdata:
1132 set_int_value(v, read_sleb128(reader));
1133 break;
1134 case DW_FORM_strp:
1135 set_cstrp_value(v, reader->obj->debug_str.ptr, read_uint(reader));
1136 break;
1137 case DW_FORM_udata:
1138 set_uint_value(v, read_uleb128(reader));
1139 break;
1140 case DW_FORM_ref_addr:
1141 if (reader->format == 4) {
1142 set_uint_value(v, read_uint32(&reader->p));
1143 } else if (reader->format == 8) {
1144 set_uint_value(v, read_uint64(&reader->p));
1145 } else {
1146 fprintf(stderr,"unknown format:%d", reader->format);
1147 abort();
1149 break;
1150 case DW_FORM_ref1:
1151 set_uint_value(v, read_uint8(&reader->p));
1152 break;
1153 case DW_FORM_ref2:
1154 set_uint_value(v, read_uint16(&reader->p));
1155 break;
1156 case DW_FORM_ref4:
1157 set_uint_value(v, read_uint32(&reader->p));
1158 break;
1159 case DW_FORM_ref8:
1160 set_uint_value(v, read_uint64(&reader->p));
1161 break;
1162 case DW_FORM_ref_udata:
1163 set_uint_value(v, uleb128(&reader->p));
1164 break;
1165 case DW_FORM_indirect:
1166 /* TODO: read the referred value */
1167 set_uint_value(v, uleb128(&reader->p));
1168 break;
1169 case DW_FORM_sec_offset:
1170 set_uint_value(v, read_uint(reader)); /* offset */
1171 /* addrptr: debug_addr */
1172 /* lineptr: debug_line */
1173 /* loclist: debug_loclists */
1174 /* loclistptr: debug_loclists */
1175 /* macptr: debug_macro */
1176 /* rnglist: debug_rnglists */
1177 /* rnglistptr: debug_rnglists */
1178 /* stroffsetsptr: debug_str_offsets */
1179 break;
1180 case DW_FORM_exprloc:
1181 v->size = (size_t)read_uleb128(reader);
1182 set_data_value(v, reader->p);
1183 reader->p += v->size;
1184 break;
1185 case DW_FORM_flag_present:
1186 set_uint_value(v, 1);
1187 break;
1188 case DW_FORM_strx:
1189 set_uint_value(v, uleb128(&reader->p));
1190 break;
1191 case DW_FORM_addrx:
1192 /* TODO: read .debug_addr */
1193 set_uint_value(v, uleb128(&reader->p));
1194 break;
1195 case DW_FORM_ref_sup4:
1196 set_uint_value(v, read_uint32(&reader->p));
1197 break;
1198 case DW_FORM_strp_sup:
1199 set_uint_value(v, read_uint(reader));
1200 /* *p = reader->sup_file + reader->sup_str->sh_offset + ret; */
1201 break;
1202 case DW_FORM_data16:
1203 v->size = 16;
1204 set_data_value(v, reader->p);
1205 reader->p += v->size;
1206 break;
1207 case DW_FORM_line_strp:
1208 set_uint_value(v, read_uint(reader));
1209 /* *p = reader->file + reader->line->sh_offset + ret; */
1210 break;
1211 case DW_FORM_ref_sig8:
1212 set_uint_value(v, read_uint64(&reader->p));
1213 break;
1214 case DW_FORM_implicit_const:
1215 set_int_value(v, sleb128(&reader->q));
1216 break;
1217 case DW_FORM_loclistx:
1218 set_uint_value(v, read_uleb128(reader));
1219 break;
1220 case DW_FORM_rnglistx:
1221 set_uint_value(v, read_uleb128(reader));
1222 break;
1223 case DW_FORM_ref_sup8:
1224 set_uint_value(v, read_uint64(&reader->p));
1225 break;
1226 case DW_FORM_strx1:
1227 set_uint_value(v, read_uint8(&reader->p));
1228 break;
1229 case DW_FORM_strx2:
1230 set_uint_value(v, read_uint16(&reader->p));
1231 break;
1232 case DW_FORM_strx3:
1233 set_uint_value(v, read_uint24(&reader->p));
1234 break;
1235 case DW_FORM_strx4:
1236 set_uint_value(v, read_uint32(&reader->p));
1237 break;
1238 case DW_FORM_addrx1:
1239 set_uint_value(v, read_uint8(&reader->p));
1240 break;
1241 case DW_FORM_addrx2:
1242 set_uint_value(v, read_uint16(&reader->p));
1243 break;
1244 case DW_FORM_addrx3:
1245 set_uint_value(v, read_uint24(&reader->p));
1246 break;
1247 case DW_FORM_addrx4:
1248 set_uint_value(v, read_uint32(&reader->p));
1249 break;
1250 case 0:
1251 goto fail;
1252 break;
1254 return;
1256 fail:
1257 fprintf(stderr, "%d: unsupported form: %#"PRIx64"\n", __LINE__, form);
1258 exit(1);
1261 /* find abbrev in current compilation unit */
1262 static const char *
1263 di_find_abbrev(DebugInfoReader *reader, uint64_t abbrev_number)
1265 const char *p;
1266 if (abbrev_number < ABBREV_TABLE_SIZE) {
1267 return reader->abbrev_table[abbrev_number];
1269 p = reader->abbrev_table[ABBREV_TABLE_SIZE-1];
1270 /* skip 255th record */
1271 uleb128(&p); /* tag */
1272 p++; /* has_children */
1273 di_skip_die_attributes(&p);
1274 for (uint64_t n = uleb128(&p); abbrev_number != n; n = uleb128(&p)) {
1275 if (n == 0) {
1276 fprintf(stderr,"%d: Abbrev Number %"PRId64" not found\n",__LINE__, abbrev_number);
1277 exit(1);
1279 uleb128(&p); /* tag */
1280 p++; /* has_children */
1281 di_skip_die_attributes(&p);
1283 return p;
1286 #if 0
1287 static void
1288 hexdump0(const unsigned char *p, size_t n)
1290 size_t i;
1291 fprintf(stderr, " 0 1 2 3 4 5 6 7 8 9 A B C D E F\n");
1292 for (i=0; i < n; i++){
1293 switch (i & 15) {
1294 case 0:
1295 fprintf(stderr, "%02zd: %02X ", i/16, p[i]);
1296 break;
1297 case 15:
1298 fprintf(stderr, "%02X\n", p[i]);
1299 break;
1300 default:
1301 fprintf(stderr, "%02X ", p[i]);
1302 break;
1305 if ((i & 15) != 15) {
1306 fprintf(stderr, "\n");
1309 #define hexdump(p,n) hexdump0((const unsigned char *)p, n)
1311 static void
1312 div_inspect(DebugInfoValue *v)
1314 switch (v->type) {
1315 case VAL_uint:
1316 fprintf(stderr,"%d: type:%d size:%zx v:%"PRIx64"\n",__LINE__,v->type,v->size,v->as.uint64);
1317 break;
1318 case VAL_int:
1319 fprintf(stderr,"%d: type:%d size:%zx v:%"PRId64"\n",__LINE__,v->type,v->size,(int64_t)v->as.uint64);
1320 break;
1321 case VAL_cstr:
1322 fprintf(stderr,"%d: type:%d size:%zx v:'%s'\n",__LINE__,v->type,v->size,v->as.ptr);
1323 break;
1324 case VAL_data:
1325 fprintf(stderr,"%d: type:%d size:%zx v:\n",__LINE__,v->type,v->size);
1326 hexdump(v->as.ptr, 16);
1327 break;
1330 #endif
1332 static DIE *
1333 di_read_die(DebugInfoReader *reader, DIE *die)
1335 uint64_t abbrev_number = uleb128(&reader->p);
1336 if (abbrev_number == 0) {
1337 reader->level--;
1338 return NULL;
1341 reader->q = di_find_abbrev(reader, abbrev_number);
1343 die->pos = reader->p - reader->obj->debug_info.ptr - 1;
1344 die->tag = (int)uleb128(&reader->q); /* tag */
1345 die->has_children = *reader->q++; /* has_children */
1346 if (die->has_children) {
1347 reader->level++;
1349 return die;
1352 static DebugInfoValue *
1353 di_read_record(DebugInfoReader *reader, DebugInfoValue *vp)
1355 uint64_t at = uleb128(&reader->q);
1356 uint64_t form = uleb128(&reader->q);
1357 if (!at || !form) return NULL;
1358 vp->at = at;
1359 vp->form = form;
1360 debug_info_reader_read_value(reader, form, vp);
1361 return vp;
1364 static void
1365 di_skip_records(DebugInfoReader *reader)
1367 for (;;) {
1368 DebugInfoValue v = {{}};
1369 uint64_t at = uleb128(&reader->q);
1370 uint64_t form = uleb128(&reader->q);
1371 if (!at || !form) return;
1372 debug_info_reader_read_value(reader, form, &v);
1376 typedef struct {
1377 uint64_t low_pc;
1378 uint64_t high_pc;
1379 uint64_t ranges;
1380 bool low_pc_set;
1381 bool high_pc_set;
1382 bool ranges_set;
1383 } ranges_t;
1385 static void
1386 ranges_set(ranges_t *ptr, DebugInfoValue *v)
1388 switch (v->at) {
1389 case DW_AT_low_pc:
1390 ptr->low_pc = v->as.uint64;
1391 ptr->low_pc_set = true;
1392 break;
1393 case DW_AT_high_pc:
1394 if (v->form == DW_FORM_addr) {
1395 ptr->high_pc = v->as.uint64;
1397 else {
1398 ptr->high_pc = ptr->low_pc + v->as.uint64;
1400 ptr->high_pc_set = true;
1401 break;
1402 case DW_AT_ranges:
1403 ptr->ranges = v->as.uint64;
1404 ptr->ranges_set = true;
1405 break;
1409 static uint64_t
1410 read_dw_form_addr(DebugInfoReader *reader, const char **ptr)
1412 const char *p = *ptr;
1413 *ptr = p + reader->address_size;
1414 if (reader->address_size == 4) {
1415 return read_uint32(&p);
1416 } else if (reader->address_size == 8) {
1417 return read_uint64(&p);
1418 } else {
1419 fprintf(stderr,"unknown address_size:%d", reader->address_size);
1420 abort();
1424 static uintptr_t
1425 ranges_include(DebugInfoReader *reader, ranges_t *ptr, uint64_t addr)
1427 if (ptr->high_pc_set) {
1428 if (ptr->ranges_set || !ptr->low_pc_set) {
1429 exit(1);
1431 if (ptr->low_pc <= addr && addr <= ptr->high_pc) {
1432 return (uintptr_t)ptr->low_pc;
1435 else if (ptr->ranges_set) {
1436 /* TODO: support base address selection entry */
1437 const char *p;
1438 uint64_t base = ptr->low_pc_set ? ptr->low_pc : reader->current_low_pc;
1439 bool base_valid = true;
1440 if (reader->obj->debug_rnglists.ptr) {
1441 p = reader->obj->debug_rnglists.ptr + ptr->ranges;
1442 for (;;) {
1443 uint8_t rle = read_uint8(&p);
1444 uintptr_t from = 0, to = 0;
1445 if (rle == DW_RLE_end_of_list) break;
1446 switch (rle) {
1447 case DW_RLE_base_addressx:
1448 uleb128(&p);
1449 base_valid = false; /* not supported yet */
1450 break;
1451 case DW_RLE_startx_endx:
1452 uleb128(&p);
1453 uleb128(&p);
1454 break;
1455 case DW_RLE_startx_length:
1456 uleb128(&p);
1457 uleb128(&p);
1458 break;
1459 case DW_RLE_offset_pair:
1460 if (!base_valid) break;
1461 from = (uintptr_t)base + uleb128(&p);
1462 to = (uintptr_t)base + uleb128(&p);
1463 break;
1464 case DW_RLE_base_address:
1465 base = read_dw_form_addr(reader, &p);
1466 base_valid = true;
1467 break;
1468 case DW_RLE_start_end:
1469 from = (uintptr_t)read_dw_form_addr(reader, &p);
1470 to = (uintptr_t)read_dw_form_addr(reader, &p);
1471 break;
1472 case DW_RLE_start_length:
1473 from = (uintptr_t)read_dw_form_addr(reader, &p);
1474 to = from + uleb128(&p);
1475 break;
1477 if (from <= addr && addr < to) {
1478 return from;
1481 return false;
1483 p = reader->obj->debug_ranges.ptr + ptr->ranges;
1484 for (;;) {
1485 uintptr_t from = read_uintptr(&p);
1486 uintptr_t to = read_uintptr(&p);
1487 if (!from && !to) break;
1488 if (from == UINTPTR_MAX) {
1489 /* base address selection entry */
1490 base = to;
1492 else if (base + from <= addr && addr < base + to) {
1493 return (uintptr_t)base + from;
1497 else if (ptr->low_pc_set) {
1498 if (ptr->low_pc == addr) {
1499 return (uintptr_t)ptr->low_pc;
1502 return false;
1505 #if 0
1506 static void
1507 ranges_inspect(DebugInfoReader *reader, ranges_t *ptr)
1509 if (ptr->high_pc_set) {
1510 if (ptr->ranges_set || !ptr->low_pc_set) {
1511 fprintf(stderr,"low_pc_set:%d high_pc_set:%d ranges_set:%d\n",ptr->low_pc_set,ptr->high_pc_set,ptr->ranges_set);
1512 exit(1);
1514 fprintf(stderr,"low_pc:%"PRIx64" high_pc:%"PRIx64"\n",ptr->low_pc,ptr->high_pc);
1516 else if (ptr->ranges_set) {
1517 char *p = reader->obj->debug_ranges.ptr + ptr->ranges;
1518 fprintf(stderr,"low_pc:%"PRIx64" ranges:%"PRIx64" %lx ",ptr->low_pc,ptr->ranges, p-reader->obj->mapped);
1519 for (;;) {
1520 uintptr_t from = read_uintptr(&p);
1521 uintptr_t to = read_uintptr(&p);
1522 if (!from && !to) break;
1523 fprintf(stderr,"%"PRIx64"-%"PRIx64" ",ptr->low_pc+from,ptr->low_pc+to);
1525 fprintf(stderr,"\n");
1527 else if (ptr->low_pc_set) {
1528 fprintf(stderr,"low_pc:%"PRIx64"\n",ptr->low_pc);
1530 else {
1531 fprintf(stderr,"empty\n");
1534 #endif
1536 static int
1537 di_read_cu(DebugInfoReader *reader)
1539 uint64_t unit_length;
1540 uint16_t version;
1541 uint64_t debug_abbrev_offset;
1542 reader->format = 4;
1543 reader->current_cu = reader->p;
1544 unit_length = read_uint32(&reader->p);
1545 if (unit_length == 0xffffffff) {
1546 unit_length = read_uint64(&reader->p);
1547 reader->format = 8;
1549 reader->cu_end = reader->p + unit_length;
1550 version = read_uint16(&reader->p);
1551 if (version > 5) {
1552 return -1;
1554 else if (version == 5) {
1555 /* unit_type = */ read_uint8(&reader->p);
1556 reader->address_size = read_uint8(&reader->p);
1557 debug_abbrev_offset = read_uint(reader);
1559 else {
1560 debug_abbrev_offset = read_uint(reader);
1561 reader->address_size = read_uint8(&reader->p);
1563 reader->q0 = reader->obj->debug_abbrev.ptr + debug_abbrev_offset;
1565 reader->level = 0;
1566 di_read_debug_abbrev_cu(reader);
1567 if (di_read_debug_line_cu(reader)) return -1;
1569 #if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER_BUILD_DATE)
1570 /* Though DWARF specifies "the applicable base address defaults to the base
1571 address of the compilation unit", but GCC seems to use zero as default */
1572 #else
1573 do {
1574 DIE die;
1576 if (!di_read_die(reader, &die)) continue;
1578 if (die.tag != DW_TAG_compile_unit) {
1579 di_skip_records(reader);
1580 break;
1583 /* enumerate abbrev */
1584 for (;;) {
1585 DebugInfoValue v = {{}};
1586 if (!di_read_record(reader, &v)) break;
1587 switch (v.at) {
1588 case DW_AT_low_pc:
1589 reader->current_low_pc = v.as.uint64;
1590 break;
1593 } while (0);
1594 #endif
1595 return 0;
1598 static void
1599 read_abstract_origin(DebugInfoReader *reader, uint64_t form, uint64_t abstract_origin, line_info_t *line)
1601 const char *p = reader->p;
1602 const char *q = reader->q;
1603 int level = reader->level;
1604 DIE die;
1606 switch (form) {
1607 case DW_FORM_ref1:
1608 case DW_FORM_ref2:
1609 case DW_FORM_ref4:
1610 case DW_FORM_ref8:
1611 case DW_FORM_ref_udata:
1612 reader->p = reader->current_cu + abstract_origin;
1613 break;
1614 case DW_FORM_ref_addr:
1615 goto finish; /* not supported yet */
1616 case DW_FORM_ref_sig8:
1617 goto finish; /* not supported yet */
1618 case DW_FORM_ref_sup4:
1619 case DW_FORM_ref_sup8:
1620 goto finish; /* not supported yet */
1621 default:
1622 goto finish;
1624 if (!di_read_die(reader, &die)) goto finish;
1626 /* enumerate abbrev */
1627 for (;;) {
1628 DebugInfoValue v = {{}};
1629 if (!di_read_record(reader, &v)) break;
1630 switch (v.at) {
1631 case DW_AT_name:
1632 line->sname = get_cstr_value(&v);
1633 break;
1637 finish:
1638 reader->p = p;
1639 reader->q = q;
1640 reader->level = level;
1643 static void
1644 debug_info_read(DebugInfoReader *reader, int num_traces, void **traces,
1645 line_info_t *lines, int offset) {
1646 while (reader->p < reader->cu_end) {
1647 DIE die;
1648 ranges_t ranges = {};
1649 line_info_t line = {};
1651 if (!di_read_die(reader, &die)) continue;
1652 /* fprintf(stderr,"%d:%tx: <%d>\n",__LINE__,die.pos,reader->level,die.tag); */
1654 if (die.tag != DW_TAG_subprogram && die.tag != DW_TAG_inlined_subroutine) {
1655 skip_die:
1656 di_skip_records(reader);
1657 continue;
1660 /* enumerate abbrev */
1661 for (;;) {
1662 DebugInfoValue v = {{}};
1663 /* ptrdiff_t pos = reader->p - reader->p0; */
1664 if (!di_read_record(reader, &v)) break;
1665 /* fprintf(stderr,"\n%d:%tx: AT:%lx FORM:%lx\n",__LINE__,pos,v.at,v.form); */
1666 /* div_inspect(&v); */
1667 switch (v.at) {
1668 case DW_AT_name:
1669 line.sname = get_cstr_value(&v);
1670 break;
1671 case DW_AT_call_file:
1672 fill_filename((int)v.as.uint64, reader->debug_line_directories, reader->debug_line_files, &line, reader->obj);
1673 break;
1674 case DW_AT_call_line:
1675 line.line = (int)v.as.uint64;
1676 break;
1677 case DW_AT_low_pc:
1678 case DW_AT_high_pc:
1679 case DW_AT_ranges:
1680 ranges_set(&ranges, &v);
1681 break;
1682 case DW_AT_declaration:
1683 goto skip_die;
1684 case DW_AT_inline:
1685 /* 1 or 3 */
1686 break; /* goto skip_die; */
1687 case DW_AT_abstract_origin:
1688 read_abstract_origin(reader, v.form, v.as.uint64, &line);
1689 break; /* goto skip_die; */
1692 /* ranges_inspect(reader, &ranges); */
1693 /* fprintf(stderr,"%d:%tx: %x ",__LINE__,diepos,die.tag); */
1694 for (int i=offset; i < num_traces; i++) {
1695 uintptr_t addr = (uintptr_t)traces[i];
1696 uintptr_t offset = addr - reader->obj->base_addr + reader->obj->vmaddr;
1697 uintptr_t saddr = ranges_include(reader, &ranges, offset);
1698 if (saddr) {
1699 /* fprintf(stderr, "%d:%tx: %d %lx->%lx %x %s: %s/%s %d %s %s %s\n",__LINE__,die.pos, i,addr,offset, die.tag,line.sname,line.dirname,line.filename,line.line,reader->obj->path,line.sname,lines[i].sname); */
1700 if (lines[i].sname) {
1701 line_info_t *lp = malloc(sizeof(line_info_t));
1702 memcpy(lp, &lines[i], sizeof(line_info_t));
1703 lines[i].next = lp;
1704 lp->dirname = line.dirname;
1705 lp->filename = line.filename;
1706 lp->line = line.line;
1707 lp->saddr = 0;
1709 lines[i].path = reader->obj->path;
1710 lines[i].base_addr = line.base_addr;
1711 lines[i].sname = line.sname;
1712 lines[i].saddr = saddr + reader->obj->base_addr - reader->obj->vmaddr;
1718 #ifdef USE_ELF
1719 static unsigned long
1720 uncompress_debug_section(ElfW(Shdr) *shdr, char *file, char **ptr)
1722 *ptr = NULL;
1723 #ifdef SUPPORT_COMPRESSED_DEBUG_LINE
1724 ElfW(Chdr) *chdr = (ElfW(Chdr) *)(file + shdr->sh_offset);
1725 unsigned long destsize = chdr->ch_size;
1726 int ret = 0;
1728 if (chdr->ch_type != ELFCOMPRESS_ZLIB) {
1729 /* unsupported compression type */
1730 return 0;
1733 *ptr = malloc(destsize);
1734 if (!*ptr) return 0;
1735 ret = uncompress((Bytef *)*ptr, &destsize,
1736 (const Bytef*)chdr + sizeof(ElfW(Chdr)),
1737 shdr->sh_size - sizeof(ElfW(Chdr)));
1738 if (ret != Z_OK) goto fail;
1739 return destsize;
1741 fail:
1742 free(*ptr);
1743 *ptr = NULL;
1744 #endif
1745 return 0;
1748 /* read file and fill lines */
1749 static uintptr_t
1750 fill_lines(int num_traces, void **traces, int check_debuglink,
1751 obj_info_t **objp, line_info_t *lines, int offset)
1753 int i, j;
1754 char *shstr;
1755 ElfW(Ehdr) *ehdr;
1756 ElfW(Shdr) *shdr, *shstr_shdr;
1757 ElfW(Shdr) *gnu_debuglink_shdr = NULL;
1758 ElfW(Shdr) *note_gnu_build_id = NULL;
1759 int fd;
1760 off_t filesize;
1761 char *file;
1762 ElfW(Shdr) *symtab_shdr = NULL, *strtab_shdr = NULL;
1763 ElfW(Shdr) *dynsym_shdr = NULL, *dynstr_shdr = NULL;
1764 obj_info_t *obj = *objp;
1765 uintptr_t dladdr_fbase = 0;
1767 fd = open(binary_filename, O_RDONLY);
1768 if (fd < 0) {
1769 goto fail;
1771 filesize = lseek(fd, 0, SEEK_END);
1772 if (filesize < 0) {
1773 int e = errno;
1774 close(fd);
1775 kprintf("lseek: %s\n", strerror(e));
1776 goto fail;
1778 #if SIZEOF_OFF_T > SIZEOF_SIZE_T
1779 if (filesize > (off_t)SIZE_MAX) {
1780 close(fd);
1781 kprintf("Too large file %s\n", binary_filename);
1782 goto fail;
1784 #endif
1785 lseek(fd, 0, SEEK_SET);
1786 /* async-signal unsafe */
1787 file = (char *)mmap(NULL, (size_t)filesize, PROT_READ, MAP_SHARED, fd, 0);
1788 if (file == MAP_FAILED) {
1789 int e = errno;
1790 close(fd);
1791 kprintf("mmap: %s\n", strerror(e));
1792 goto fail;
1794 close(fd);
1796 ehdr = (ElfW(Ehdr) *)file;
1797 if (memcmp(ehdr->e_ident, "\177ELF", 4) != 0) {
1799 * Huh? Maybe filename was overridden by setproctitle() and
1800 * it match non-elf file.
1802 goto fail;
1804 obj->mapped = file;
1805 obj->mapped_size = (size_t)filesize;
1807 shdr = (ElfW(Shdr) *)(file + ehdr->e_shoff);
1809 shstr_shdr = shdr + ehdr->e_shstrndx;
1810 shstr = file + shstr_shdr->sh_offset;
1812 for (i = 0; i < ehdr->e_shnum; i++) {
1813 char *section_name = shstr + shdr[i].sh_name;
1814 switch (shdr[i].sh_type) {
1815 case SHT_STRTAB:
1816 if (!strcmp(section_name, ".strtab")) {
1817 strtab_shdr = shdr + i;
1819 else if (!strcmp(section_name, ".dynstr")) {
1820 dynstr_shdr = shdr + i;
1822 break;
1823 case SHT_SYMTAB:
1824 /* if (!strcmp(section_name, ".symtab")) */
1825 symtab_shdr = shdr + i;
1826 break;
1827 case SHT_DYNSYM:
1828 /* if (!strcmp(section_name, ".dynsym")) */
1829 dynsym_shdr = shdr + i;
1830 break;
1831 case SHT_NOTE:
1832 if (!strcmp(section_name, ".note.gnu.build-id")) {
1833 note_gnu_build_id = shdr + i;
1835 break;
1836 case SHT_PROGBITS:
1837 if (!strcmp(section_name, ".gnu_debuglink")) {
1838 gnu_debuglink_shdr = shdr + i;
1840 else {
1841 const char *debug_section_names[] = {
1842 ".debug_abbrev",
1843 ".debug_info",
1844 ".debug_line",
1845 ".debug_ranges",
1846 ".debug_rnglists",
1847 ".debug_str"
1850 for (j=0; j < DWARF_SECTION_COUNT; j++) {
1851 struct dwarf_section *s = obj_dwarf_section_at(obj, j);
1853 if (strcmp(section_name, debug_section_names[j]) != 0)
1854 continue;
1856 s->ptr = file + shdr[i].sh_offset;
1857 s->size = shdr[i].sh_size;
1858 s->flags = shdr[i].sh_flags;
1859 if (s->flags & SHF_COMPRESSED) {
1860 s->size = uncompress_debug_section(&shdr[i], file, &s->ptr);
1861 if (!s->size) goto fail;
1863 break;
1866 break;
1870 if (offset == -1) {
1871 /* main executable */
1872 offset = 0;
1873 if (dynsym_shdr && dynstr_shdr) {
1874 char *strtab = file + dynstr_shdr->sh_offset;
1875 ElfW(Sym) *symtab = (ElfW(Sym) *)(file + dynsym_shdr->sh_offset);
1876 int symtab_count = (int)(dynsym_shdr->sh_size / sizeof(ElfW(Sym)));
1877 void *handle = dlopen(NULL, RTLD_NOW|RTLD_LOCAL);
1878 if (handle) {
1879 for (j = 0; j < symtab_count; j++) {
1880 ElfW(Sym) *sym = &symtab[j];
1881 Dl_info info;
1882 void *s;
1883 if (ELF_ST_TYPE(sym->st_info) != STT_FUNC || sym->st_size == 0) continue;
1884 s = dlsym(handle, strtab + sym->st_name);
1885 if (s && dladdr(s, &info)) {
1886 obj->base_addr = dladdr_fbase;
1887 dladdr_fbase = (uintptr_t)info.dli_fbase;
1888 break;
1891 dlclose(handle);
1893 if (ehdr->e_type == ET_EXEC) {
1894 obj->base_addr = 0;
1896 else {
1897 /* PIE (position-independent executable) */
1898 obj->base_addr = dladdr_fbase;
1903 if (obj->debug_info.ptr && obj->debug_abbrev.ptr) {
1904 DebugInfoReader reader;
1905 debug_info_reader_init(&reader, obj);
1906 i = 0;
1907 while (reader.p < reader.pend) {
1908 /* fprintf(stderr, "%d:%tx: CU[%d]\n", __LINE__, reader.p - reader.obj->debug_info.ptr, i++); */
1909 if (di_read_cu(&reader)) goto use_symtab;
1910 debug_info_read(&reader, num_traces, traces, lines, offset);
1913 else {
1914 /* This file doesn't have dwarf, use symtab or dynsym */
1915 use_symtab:
1916 if (!symtab_shdr) {
1917 /* This file doesn't have symtab, use dynsym instead */
1918 symtab_shdr = dynsym_shdr;
1919 strtab_shdr = dynstr_shdr;
1922 if (symtab_shdr && strtab_shdr) {
1923 char *strtab = file + strtab_shdr->sh_offset;
1924 ElfW(Sym) *symtab = (ElfW(Sym) *)(file + symtab_shdr->sh_offset);
1925 int symtab_count = (int)(symtab_shdr->sh_size / sizeof(ElfW(Sym)));
1926 for (j = 0; j < symtab_count; j++) {
1927 ElfW(Sym) *sym = &symtab[j];
1928 uintptr_t saddr = (uintptr_t)sym->st_value + obj->base_addr;
1929 if (ELF_ST_TYPE(sym->st_info) != STT_FUNC) continue;
1930 for (i = offset; i < num_traces; i++) {
1931 uintptr_t d = (uintptr_t)traces[i] - saddr;
1932 if (lines[i].line > 0 || d > (uintptr_t)sym->st_size)
1933 continue;
1934 /* fill symbol name and addr from .symtab */
1935 if (!lines[i].sname) lines[i].sname = strtab + sym->st_name;
1936 lines[i].saddr = saddr;
1937 lines[i].path = obj->path;
1938 lines[i].base_addr = obj->base_addr;
1944 if (!obj->debug_line.ptr) {
1945 /* This file doesn't have .debug_line section,
1946 let's check .gnu_debuglink section instead. */
1947 if (gnu_debuglink_shdr && check_debuglink) {
1948 follow_debuglink(file + gnu_debuglink_shdr->sh_offset,
1949 num_traces, traces,
1950 objp, lines, offset);
1952 if (note_gnu_build_id && check_debuglink) {
1953 ElfW(Nhdr) *nhdr = (ElfW(Nhdr)*) (file + note_gnu_build_id->sh_offset);
1954 const char *build_id = (char *)(nhdr + 1) + nhdr->n_namesz;
1955 follow_debuglink_build_id(build_id, nhdr->n_descsz,
1956 num_traces, traces,
1957 objp, lines, offset);
1959 goto finish;
1962 if (parse_debug_line(num_traces, traces,
1963 obj->debug_line.ptr,
1964 obj->debug_line.size,
1965 obj, lines, offset) == -1)
1966 goto fail;
1968 finish:
1969 return dladdr_fbase;
1970 fail:
1971 return (uintptr_t)-1;
1973 #else /* Mach-O */
1974 /* read file and fill lines */
1975 static uintptr_t
1976 fill_lines(int num_traces, void **traces, int check_debuglink,
1977 obj_info_t **objp, line_info_t *lines, int offset)
1979 # ifdef __LP64__
1980 # define LP(x) x##_64
1981 # else
1982 # define LP(x) x
1983 # endif
1984 int fd;
1985 off_t filesize;
1986 char *file, *p = NULL;
1987 obj_info_t *obj = *objp;
1988 struct LP(mach_header) *header;
1989 uintptr_t dladdr_fbase = 0;
1992 char *s = binary_filename;
1993 char *base = strrchr(binary_filename, '/')+1;
1994 size_t max = PATH_MAX;
1995 size_t size = strlen(binary_filename);
1996 size_t basesize = size - (base - binary_filename);
1997 s += size;
1998 max -= size;
1999 p = s;
2000 size = strlcpy(s, ".dSYM/Contents/Resources/DWARF/", max);
2001 if (size == 0) goto fail;
2002 s += size;
2003 max -= size;
2004 if (max <= basesize) goto fail;
2005 memcpy(s, base, basesize);
2006 s[basesize] = 0;
2008 fd = open(binary_filename, O_RDONLY);
2009 if (fd < 0) {
2010 *p = 0; /* binary_filename becomes original file name */
2011 fd = open(binary_filename, O_RDONLY);
2012 if (fd < 0) {
2013 goto fail;
2018 filesize = lseek(fd, 0, SEEK_END);
2019 if (filesize < 0) {
2020 int e = errno;
2021 close(fd);
2022 kprintf("lseek: %s\n", strerror(e));
2023 goto fail;
2025 #if SIZEOF_OFF_T > SIZEOF_SIZE_T
2026 if (filesize > (off_t)SIZE_MAX) {
2027 close(fd);
2028 kprintf("Too large file %s\n", binary_filename);
2029 goto fail;
2031 #endif
2032 lseek(fd, 0, SEEK_SET);
2033 /* async-signal unsafe */
2034 file = (char *)mmap(NULL, (size_t)filesize, PROT_READ, MAP_SHARED, fd, 0);
2035 if (file == MAP_FAILED) {
2036 int e = errno;
2037 close(fd);
2038 kprintf("mmap: %s\n", strerror(e));
2039 goto fail;
2041 close(fd);
2043 obj->mapped = file;
2044 obj->mapped_size = (size_t)filesize;
2046 header = (struct LP(mach_header) *)file;
2047 if (header->magic == LP(MH_MAGIC)) {
2048 /* non universal binary */
2049 p = file;
2051 else if (header->magic == FAT_CIGAM) {
2052 struct LP(mach_header) *mhp = _NSGetMachExecuteHeader();
2053 struct fat_header *fat = (struct fat_header *)file;
2054 char *q = file + sizeof(*fat);
2055 uint32_t nfat_arch = __builtin_bswap32(fat->nfat_arch);
2056 /* fprintf(stderr,"%d: fat:%s %d\n",__LINE__, binary_filename,nfat_arch); */
2057 for (uint32_t i = 0; i < nfat_arch; i++) {
2058 struct fat_arch *arch = (struct fat_arch *)q;
2059 cpu_type_t cputype = __builtin_bswap32(arch->cputype);
2060 cpu_subtype_t cpusubtype = __builtin_bswap32(arch->cpusubtype);
2061 uint32_t offset = __builtin_bswap32(arch->offset);
2062 /* fprintf(stderr,"%d: fat %d %x/%x %x/%x\n",__LINE__, i, mhp->cputype,mhp->cpusubtype, cputype,cpusubtype); */
2063 if (mhp->cputype == cputype &&
2064 (cpu_subtype_t)(mhp->cpusubtype & ~CPU_SUBTYPE_MASK) == cpusubtype) {
2065 p = file + offset;
2066 file = p;
2067 header = (struct LP(mach_header) *)p;
2068 if (header->magic == LP(MH_MAGIC)) {
2069 goto found_mach_header;
2071 break;
2073 q += sizeof(*arch);
2075 kprintf("'%s' is not a Mach-O universal binary file!\n",binary_filename);
2076 close(fd);
2077 goto fail;
2079 else {
2080 kprintf("'%s' is not a "
2081 # ifdef __LP64__
2082 "64"
2083 # else
2084 "32"
2085 # endif
2086 "-bit Mach-O file!\n",binary_filename);
2087 close(fd);
2088 goto fail;
2090 found_mach_header:
2091 p += sizeof(*header);
2093 for (uint32_t i = 0; i < (uint32_t)header->ncmds; i++) {
2094 struct load_command *lcmd = (struct load_command *)p;
2095 switch (lcmd->cmd) {
2096 case LP(LC_SEGMENT):
2098 static const char *debug_section_names[] = {
2099 "__debug_abbrev",
2100 "__debug_info",
2101 "__debug_line",
2102 "__debug_ranges",
2103 "__debug_rnglists",
2104 "__debug_str"
2106 struct LP(segment_command) *scmd = (struct LP(segment_command) *)lcmd;
2107 if (strcmp(scmd->segname, "__TEXT") == 0) {
2108 obj->vmaddr = scmd->vmaddr;
2110 else if (strcmp(scmd->segname, "__DWARF") == 0) {
2111 p += sizeof(struct LP(segment_command));
2112 for (uint64_t i = 0; i < scmd->nsects; i++) {
2113 struct LP(section) *sect = (struct LP(section) *)p;
2114 p += sizeof(struct LP(section));
2115 for (int j=0; j < DWARF_SECTION_COUNT; j++) {
2116 struct dwarf_section *s = obj_dwarf_section_at(obj, j);
2118 if (strcmp(sect->sectname, debug_section_names[j]) != 0)
2119 continue;
2121 s->ptr = file + sect->offset;
2122 s->size = sect->size;
2123 s->flags = sect->flags;
2124 if (s->flags & SHF_COMPRESSED) {
2125 goto fail;
2127 break;
2132 break;
2134 case LC_SYMTAB:
2136 struct symtab_command *cmd = (struct symtab_command *)lcmd;
2137 struct LP(nlist) *nl = (struct LP(nlist) *)(file + cmd->symoff);
2138 char *strtab = file + cmd->stroff, *sname = 0;
2139 uint32_t j;
2140 uintptr_t saddr = 0;
2141 /* kprintf("[%2d]: %x/symtab %p\n", i, cmd->cmd, (void *)p); */
2142 for (j = 0; j < cmd->nsyms; j++) {
2143 uintptr_t symsize, d;
2144 struct LP(nlist) *e = &nl[j];
2145 /* kprintf("[%2d][%4d]: %02x/%x/%x: %s %llx\n", i, j, e->n_type,e->n_sect,e->n_desc,strtab+e->n_un.n_strx,e->n_value); */
2146 if (e->n_type != N_FUN) continue;
2147 if (e->n_sect) {
2148 saddr = (uintptr_t)e->n_value + obj->base_addr - obj->vmaddr;
2149 sname = strtab + e->n_un.n_strx;
2150 /* kprintf("[%2d][%4d]: %02x/%x/%x: %s %llx\n", i, j, e->n_type,e->n_sect,e->n_desc,strtab+e->n_un.n_strx,e->n_value); */
2151 continue;
2153 for (int k = offset; k < num_traces; k++) {
2154 d = (uintptr_t)traces[k] - saddr;
2155 symsize = e->n_value;
2156 /* kprintf("%lx %lx %lx\n",saddr,symsize,traces[k]); */
2157 if (lines[k].line > 0 || d > (uintptr_t)symsize)
2158 continue;
2159 /* fill symbol name and addr from .symtab */
2160 if (!lines[k].sname) lines[k].sname = sname;
2161 lines[k].saddr = saddr;
2162 lines[k].path = obj->path;
2163 lines[k].base_addr = obj->base_addr;
2168 p += lcmd->cmdsize;
2171 if (obj->debug_info.ptr && obj->debug_abbrev.ptr) {
2172 DebugInfoReader reader;
2173 debug_info_reader_init(&reader, obj);
2174 while (reader.p < reader.pend) {
2175 if (di_read_cu(&reader)) goto fail;
2176 debug_info_read(&reader, num_traces, traces, lines, offset);
2180 if (parse_debug_line(num_traces, traces,
2181 obj->debug_line.ptr,
2182 obj->debug_line.size,
2183 obj, lines, offset) == -1)
2184 goto fail;
2186 return dladdr_fbase;
2187 fail:
2188 return (uintptr_t)-1;
2190 #endif
2192 #define HAVE_MAIN_EXE_PATH
2193 #if defined(__FreeBSD__) || defined(__DragonFly__)
2194 # include <sys/sysctl.h>
2195 #endif
2196 /* ssize_t main_exe_path(void)
2198 * store the path of the main executable to `binary_filename`,
2199 * and returns strlen(binary_filename).
2200 * it is NUL terminated.
2202 #if defined(__linux__) || defined(__NetBSD__)
2203 static ssize_t
2204 main_exe_path(void)
2206 # if defined(__linux__)
2207 # define PROC_SELF_EXE "/proc/self/exe"
2208 # elif defined(__NetBSD__)
2209 # define PROC_SELF_EXE "/proc/curproc/exe"
2210 # endif
2211 ssize_t len = readlink(PROC_SELF_EXE, binary_filename, PATH_MAX);
2212 if (len < 0) return 0;
2213 binary_filename[len] = 0;
2214 return len;
2216 #elif defined(__FreeBSD__) || defined(__DragonFly__)
2217 static ssize_t
2218 main_exe_path(void)
2220 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
2221 size_t len = PATH_MAX;
2222 int err = sysctl(mib, 4, binary_filename, &len, NULL, 0);
2223 if (err) {
2224 kprintf("Can't get the path of ruby");
2225 return -1;
2227 len--; /* sysctl sets strlen+1 */
2228 return len;
2230 #elif defined(HAVE_LIBPROC_H)
2231 static ssize_t
2232 main_exe_path(void)
2234 int len = proc_pidpath(getpid(), binary_filename, PATH_MAX);
2235 if (len == 0) return 0;
2236 binary_filename[len] = 0;
2237 return len;
2239 #else
2240 #undef HAVE_MAIN_EXE_PATH
2241 #endif
2243 static void
2244 print_line0(line_info_t *line, void *address)
2246 uintptr_t addr = (uintptr_t)address;
2247 uintptr_t d = addr - line->saddr;
2248 if (!address) {
2249 /* inlined */
2250 if (line->dirname && line->dirname[0]) {
2251 kprintf("%s(%s) %s/%s:%d\n", line->path, line->sname, line->dirname, line->filename, line->line);
2253 else {
2254 kprintf("%s(%s) %s:%d\n", line->path, line->sname, line->filename, line->line);
2257 else if (!line->path) {
2258 kprintf("[0x%"PRIxPTR"]\n", addr);
2260 else if (!line->saddr || !line->sname) {
2261 kprintf("%s(0x%"PRIxPTR") [0x%"PRIxPTR"]\n", line->path, addr-line->base_addr, addr);
2263 else if (line->line <= 0) {
2264 kprintf("%s(%s+0x%"PRIxPTR") [0x%"PRIxPTR"]\n", line->path, line->sname,
2265 d, addr);
2267 else if (!line->filename) {
2268 kprintf("%s(%s+0x%"PRIxPTR") [0x%"PRIxPTR"] ???:%d\n", line->path, line->sname,
2269 d, addr, line->line);
2271 else if (line->dirname && line->dirname[0]) {
2272 kprintf("%s(%s+0x%"PRIxPTR") [0x%"PRIxPTR"] %s/%s:%d\n", line->path, line->sname,
2273 d, addr, line->dirname, line->filename, line->line);
2275 else {
2276 kprintf("%s(%s+0x%"PRIxPTR") [0x%"PRIxPTR"] %s:%d\n", line->path, line->sname,
2277 d, addr, line->filename, line->line);
2281 static void
2282 print_line(line_info_t *line, void *address)
2284 print_line0(line, address);
2285 if (line->next) {
2286 print_line(line->next, NULL);
2290 void
2291 rb_dump_backtrace_with_lines(int num_traces, void **traces)
2293 int i;
2294 /* async-signal unsafe */
2295 line_info_t *lines = (line_info_t *)calloc(num_traces, sizeof(line_info_t));
2296 obj_info_t *obj = NULL;
2297 /* 2 is NULL + main executable */
2298 void **dladdr_fbases = (void **)calloc(num_traces+2, sizeof(void *));
2299 #ifdef HAVE_MAIN_EXE_PATH
2300 char *main_path = NULL; /* used on printing backtrace */
2301 ssize_t len;
2302 if ((len = main_exe_path()) > 0) {
2303 main_path = (char *)alloca(len + 1);
2304 if (main_path) {
2305 uintptr_t addr;
2306 memcpy(main_path, binary_filename, len+1);
2307 append_obj(&obj);
2308 obj->path = main_path;
2309 addr = fill_lines(num_traces, traces, 1, &obj, lines, -1);
2310 if (addr != (uintptr_t)-1) {
2311 dladdr_fbases[0] = (void *)addr;
2315 #endif
2317 /* fill source lines by reading dwarf */
2318 for (i = 0; i < num_traces; i++) {
2319 Dl_info info;
2320 if (lines[i].line) continue;
2321 if (dladdr(traces[i], &info)) {
2322 const char *path;
2323 void **p;
2325 /* skip symbols which is in already checked objects */
2326 /* if the binary is strip-ed, this may effect */
2327 for (p=dladdr_fbases; *p; p++) {
2328 if (*p == info.dli_fbase) {
2329 lines[i].path = info.dli_fname;
2330 lines[i].sname = info.dli_sname;
2331 goto next_line;
2334 *p = info.dli_fbase;
2336 append_obj(&obj);
2337 obj->base_addr = (uintptr_t)info.dli_fbase;
2338 path = info.dli_fname;
2339 obj->path = path;
2340 lines[i].path = path;
2341 lines[i].sname = info.dli_sname;
2342 lines[i].saddr = (uintptr_t)info.dli_saddr;
2343 strlcpy(binary_filename, path, PATH_MAX);
2344 if (fill_lines(num_traces, traces, 1, &obj, lines, i) == (uintptr_t)-1)
2345 break;
2347 next_line:
2348 continue;
2351 /* output */
2352 for (i = 0; i < num_traces; i++) {
2353 print_line(&lines[i], traces[i]);
2355 /* FreeBSD's backtrace may show _start and so on */
2356 if (lines[i].sname && strcmp("main", lines[i].sname) == 0)
2357 break;
2360 /* free */
2361 while (obj) {
2362 obj_info_t *o = obj;
2363 for (i=0; i < DWARF_SECTION_COUNT; i++) {
2364 struct dwarf_section *s = obj_dwarf_section_at(obj, i);
2365 if (s->flags & SHF_COMPRESSED) {
2366 free(s->ptr);
2369 if (obj->mapped_size) {
2370 munmap(obj->mapped, obj->mapped_size);
2372 obj = o->next;
2373 free(o);
2375 for (i = 0; i < num_traces; i++) {
2376 line_info_t *line = lines[i].next;
2377 while (line) {
2378 line_info_t *l = line;
2379 line = line->next;
2380 free(l);
2383 free(lines);
2384 free(dladdr_fbases);
2387 /* From FreeBSD's lib/libstand/printf.c */
2389 * Copyright (c) 1986, 1988, 1991, 1993
2390 * The Regents of the University of California. All rights reserved.
2391 * (c) UNIX System Laboratories, Inc.
2392 * All or some portions of this file are derived from material licensed
2393 * to the University of California by American Telephone and Telegraph
2394 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
2395 * the permission of UNIX System Laboratories, Inc.
2397 * Redistribution and use in source and binary forms, with or without
2398 * modification, are permitted provided that the following conditions
2399 * are met:
2400 * 1. Redistributions of source code must retain the above copyright
2401 * notice, this list of conditions and the following disclaimer.
2402 * 2. Redistributions in binary form must reproduce the above copyright
2403 * notice, this list of conditions and the following disclaimer in the
2404 * documentation and/or other materials provided with the distribution.
2405 * 4. Neither the name of the University nor the names of its contributors
2406 * may be used to endorse or promote products derived from this software
2407 * without specific prior written permission.
2409 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2410 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2411 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2412 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2413 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2414 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2415 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2416 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2417 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2418 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2419 * SUCH DAMAGE.
2421 * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94
2424 #include <stdarg.h>
2425 #define MAXNBUF (sizeof(intmax_t) * CHAR_BIT + 1)
2426 static inline int toupper(int c) { return ('A' <= c && c <= 'Z') ? (c&0x5f) : c; }
2427 #define hex2ascii(hex) (hex2ascii_data[hex])
2428 static const char hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz";
2429 static inline int imax(int a, int b) { return (a > b ? a : b); }
2430 static int kvprintf(char const *fmt, void (*func)(int), void *arg, int radix, va_list ap);
2432 static void putce(int c)
2434 char s[1];
2435 ssize_t ret;
2437 s[0] = (char)c;
2438 ret = write(2, s, 1);
2439 (void)ret;
2442 static int
2443 kprintf(const char *fmt, ...)
2445 va_list ap;
2446 int retval;
2448 va_start(ap, fmt);
2449 retval = kvprintf(fmt, putce, NULL, 10, ap);
2450 va_end(ap);
2451 return retval;
2455 * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
2456 * order; return an optional length and a pointer to the last character
2457 * written in the buffer (i.e., the first character of the string).
2458 * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
2460 static char *
2461 ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
2463 char *p, c;
2465 p = nbuf;
2466 *p = '\0';
2467 do {
2468 c = hex2ascii(num % base);
2469 *++p = upper ? toupper(c) : c;
2470 } while (num /= base);
2471 if (lenp)
2472 *lenp = (int)(p - nbuf);
2473 return (p);
2477 * Scaled down version of printf(3).
2479 * Two additional formats:
2481 * The format %b is supported to decode error registers.
2482 * Its usage is:
2484 * printf("reg=%b\n", regval, "<base><arg>*");
2486 * where <base> is the output base expressed as a control character, e.g.
2487 * \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
2488 * the first of which gives the bit number to be inspected (origin 1), and
2489 * the next characters (up to a control character, i.e. a character <= 32),
2490 * give the name of the register. Thus:
2492 * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
2494 * would produce output:
2496 * reg=3<BITTWO,BITONE>
2498 * XXX: %D -- Hexdump, takes pointer and separator string:
2499 * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX
2500 * ("%*D", len, ptr, " " -> XX XX XX XX ...
2502 static int
2503 kvprintf(char const *fmt, void (*func)(int), void *arg, int radix, va_list ap)
2505 #define PCHAR(c) {int cc=(c); if (func) (*func)(cc); else *d++ = cc; retval++; }
2506 char nbuf[MAXNBUF];
2507 char *d;
2508 const char *p, *percent, *q;
2509 unsigned char *up;
2510 int ch, n;
2511 uintmax_t num;
2512 int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
2513 int cflag, hflag, jflag, tflag, zflag;
2514 int dwidth, upper;
2515 char padc;
2516 int stop = 0, retval = 0;
2518 num = 0;
2519 if (!func)
2520 d = (char *) arg;
2521 else
2522 d = NULL;
2524 if (fmt == NULL)
2525 fmt = "(fmt null)\n";
2527 if (radix < 2 || radix > 36)
2528 radix = 10;
2530 for (;;) {
2531 padc = ' ';
2532 width = 0;
2533 while ((ch = (unsigned char)*fmt++) != '%' || stop) {
2534 if (ch == '\0')
2535 return (retval);
2536 PCHAR(ch);
2538 percent = fmt - 1;
2539 qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
2540 sign = 0; dot = 0; dwidth = 0; upper = 0;
2541 cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
2542 reswitch: switch (ch = (unsigned char)*fmt++) {
2543 case '.':
2544 dot = 1;
2545 goto reswitch;
2546 case '#':
2547 sharpflag = 1;
2548 goto reswitch;
2549 case '+':
2550 sign = 1;
2551 goto reswitch;
2552 case '-':
2553 ladjust = 1;
2554 goto reswitch;
2555 case '%':
2556 PCHAR(ch);
2557 break;
2558 case '*':
2559 if (!dot) {
2560 width = va_arg(ap, int);
2561 if (width < 0) {
2562 ladjust = !ladjust;
2563 width = -width;
2565 } else {
2566 dwidth = va_arg(ap, int);
2568 goto reswitch;
2569 case '0':
2570 if (!dot) {
2571 padc = '0';
2572 goto reswitch;
2574 case '1': case '2': case '3': case '4':
2575 case '5': case '6': case '7': case '8': case '9':
2576 for (n = 0;; ++fmt) {
2577 n = n * 10 + ch - '0';
2578 ch = *fmt;
2579 if (ch < '0' || ch > '9')
2580 break;
2582 if (dot)
2583 dwidth = n;
2584 else
2585 width = n;
2586 goto reswitch;
2587 case 'b':
2588 num = (unsigned int)va_arg(ap, int);
2589 p = va_arg(ap, char *);
2590 for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
2591 PCHAR(*q--);
2593 if (num == 0)
2594 break;
2596 for (tmp = 0; *p;) {
2597 n = *p++;
2598 if (num & (1 << (n - 1))) {
2599 PCHAR(tmp ? ',' : '<');
2600 for (; (n = *p) > ' '; ++p)
2601 PCHAR(n);
2602 tmp = 1;
2603 } else
2604 for (; *p > ' '; ++p)
2605 continue;
2607 if (tmp)
2608 PCHAR('>');
2609 break;
2610 case 'c':
2611 PCHAR(va_arg(ap, int));
2612 break;
2613 case 'D':
2614 up = va_arg(ap, unsigned char *);
2615 p = va_arg(ap, char *);
2616 if (!width)
2617 width = 16;
2618 while(width--) {
2619 PCHAR(hex2ascii(*up >> 4));
2620 PCHAR(hex2ascii(*up & 0x0f));
2621 up++;
2622 if (width)
2623 for (q=p;*q;q++)
2624 PCHAR(*q);
2626 break;
2627 case 'd':
2628 case 'i':
2629 base = 10;
2630 sign = 1;
2631 goto handle_sign;
2632 case 'h':
2633 if (hflag) {
2634 hflag = 0;
2635 cflag = 1;
2636 } else
2637 hflag = 1;
2638 goto reswitch;
2639 case 'j':
2640 jflag = 1;
2641 goto reswitch;
2642 case 'l':
2643 if (lflag) {
2644 lflag = 0;
2645 qflag = 1;
2646 } else
2647 lflag = 1;
2648 goto reswitch;
2649 case 'n':
2650 if (jflag)
2651 *(va_arg(ap, intmax_t *)) = retval;
2652 else if (qflag)
2653 *(va_arg(ap, int64_t *)) = retval;
2654 else if (lflag)
2655 *(va_arg(ap, long *)) = retval;
2656 else if (zflag)
2657 *(va_arg(ap, size_t *)) = retval;
2658 else if (hflag)
2659 *(va_arg(ap, short *)) = retval;
2660 else if (cflag)
2661 *(va_arg(ap, char *)) = retval;
2662 else
2663 *(va_arg(ap, int *)) = retval;
2664 break;
2665 case 'o':
2666 base = 8;
2667 goto handle_nosign;
2668 case 'p':
2669 base = 16;
2670 sharpflag = (width == 0);
2671 sign = 0;
2672 num = (uintptr_t)va_arg(ap, void *);
2673 goto number;
2674 case 'q':
2675 qflag = 1;
2676 goto reswitch;
2677 case 'r':
2678 base = radix;
2679 if (sign)
2680 goto handle_sign;
2681 goto handle_nosign;
2682 case 's':
2683 p = va_arg(ap, char *);
2684 if (p == NULL)
2685 p = "(null)";
2686 if (!dot)
2687 n = (int)strlen (p);
2688 else
2689 for (n = 0; n < dwidth && p[n]; n++)
2690 continue;
2692 width -= n;
2694 if (!ladjust && width > 0)
2695 while (width--)
2696 PCHAR(padc);
2697 while (n--)
2698 PCHAR(*p++);
2699 if (ladjust && width > 0)
2700 while (width--)
2701 PCHAR(padc);
2702 break;
2703 case 't':
2704 tflag = 1;
2705 goto reswitch;
2706 case 'u':
2707 base = 10;
2708 goto handle_nosign;
2709 case 'X':
2710 upper = 1;
2711 case 'x':
2712 base = 16;
2713 goto handle_nosign;
2714 case 'y':
2715 base = 16;
2716 sign = 1;
2717 goto handle_sign;
2718 case 'z':
2719 zflag = 1;
2720 goto reswitch;
2721 handle_nosign:
2722 sign = 0;
2723 if (jflag)
2724 num = va_arg(ap, uintmax_t);
2725 else if (qflag)
2726 num = va_arg(ap, uint64_t);
2727 else if (tflag)
2728 num = va_arg(ap, ptrdiff_t);
2729 else if (lflag)
2730 num = va_arg(ap, unsigned long);
2731 else if (zflag)
2732 num = va_arg(ap, size_t);
2733 else if (hflag)
2734 num = (unsigned short)va_arg(ap, int);
2735 else if (cflag)
2736 num = (unsigned char)va_arg(ap, int);
2737 else
2738 num = va_arg(ap, unsigned int);
2739 goto number;
2740 handle_sign:
2741 if (jflag)
2742 num = va_arg(ap, intmax_t);
2743 else if (qflag)
2744 num = va_arg(ap, int64_t);
2745 else if (tflag)
2746 num = va_arg(ap, ptrdiff_t);
2747 else if (lflag)
2748 num = va_arg(ap, long);
2749 else if (zflag)
2750 num = va_arg(ap, ssize_t);
2751 else if (hflag)
2752 num = (short)va_arg(ap, int);
2753 else if (cflag)
2754 num = (char)va_arg(ap, int);
2755 else
2756 num = va_arg(ap, int);
2757 number:
2758 if (sign && (intmax_t)num < 0) {
2759 neg = 1;
2760 num = -(intmax_t)num;
2762 p = ksprintn(nbuf, num, base, &n, upper);
2763 tmp = 0;
2764 if (sharpflag && num != 0) {
2765 if (base == 8)
2766 tmp++;
2767 else if (base == 16)
2768 tmp += 2;
2770 if (neg)
2771 tmp++;
2773 if (!ladjust && padc == '0')
2774 dwidth = width - tmp;
2775 width -= tmp + imax(dwidth, n);
2776 dwidth -= n;
2777 if (!ladjust)
2778 while (width-- > 0)
2779 PCHAR(' ');
2780 if (neg)
2781 PCHAR('-');
2782 if (sharpflag && num != 0) {
2783 if (base == 8) {
2784 PCHAR('0');
2785 } else if (base == 16) {
2786 PCHAR('0');
2787 PCHAR('x');
2790 while (dwidth-- > 0)
2791 PCHAR('0');
2793 while (*p)
2794 PCHAR(*p--);
2796 if (ladjust)
2797 while (width-- > 0)
2798 PCHAR(' ');
2800 break;
2801 default:
2802 while (percent < fmt)
2803 PCHAR(*percent++);
2805 * Since we ignore an formatting argument it is no
2806 * longer safe to obey the remaining formatting
2807 * arguments as the arguments will no longer match
2808 * the format specs.
2810 stop = 1;
2811 break;
2814 #undef PCHAR
2816 #else /* defined(USE_ELF) */
2817 #error not supported
2818 #endif