1 /**********************************************************************
7 Copyright (C) 2010 Shinichiro Hamaji
9 **********************************************************************/
11 #if defined(__clang__) && defined(__has_warning)
12 #if __has_warning("-Wgnu-empty-initializer")
13 #pragma clang diagnostic ignored "-Wgnu-empty-initializer"
15 #if __has_warning("-Wgcc-compat")
16 #pragma clang diagnostic ignored "-Wgcc-compat"
20 #include "ruby/internal/config.h"
21 #include "ruby/defines.h"
22 #include "ruby/missing.h"
23 #include "addr2line.h"
32 #include "ruby/internal/stdbool.h"
34 #if defined(USE_ELF) || defined(HAVE_MACH_O_LOADER_H)
43 #include <sys/types.h>
47 /* Make alloca work the best possible way. */
50 # define alloca __builtin_alloca
59 # ifndef alloca /* predefined by HP cc +Olibcalls */
63 # endif /* HAVE_ALLOCA_H */
65 # define UNREACHABLE __builtin_unreachable()
67 # ifndef UNREACHABLE_RETURN
68 # define UNREACHABLE_RETURN(_) __builtin_unreachable()
73 # define UNREACHABLE abort()
75 #ifndef UNREACHABLE_RETURN
76 # define UNREACHABLE_RETURN(_) return (abort(), (_))
83 #ifdef HAVE_MACH_O_LOADER_H
84 # include <crt_externs.h>
85 # include <mach-o/fat.h>
86 # include <mach-o/loader.h>
87 # include <mach-o/nlist.h>
88 # include <mach-o/stab.h>
99 # if SIZEOF_VOIDP == 8
100 # define ElfW(x) Elf64##_##x
102 # define ElfW(x) Elf32##_##x
106 # if SIZEOF_VOIDP == 8
107 # define ELF_ST_TYPE ELF64_ST_TYPE
109 # define ELF_ST_TYPE ELF32_ST_TYPE
114 #ifdef SHF_COMPRESSED
115 # if defined(ELFCOMPRESS_ZLIB) && defined(HAVE_LIBZ)
116 /* FreeBSD 11.0 lacks ELFCOMPRESS_ZLIB */
118 # define SUPPORT_COMPRESSED_DEBUG_LINE
120 #else /* compatibility with glibc < 2.22 */
121 # define SHF_COMPRESSED 0
125 #define PATH_MAX 4096
128 #define DW_LNS_copy 0x01
129 #define DW_LNS_advance_pc 0x02
130 #define DW_LNS_advance_line 0x03
131 #define DW_LNS_set_file 0x04
132 #define DW_LNS_set_column 0x05
133 #define DW_LNS_negate_stmt 0x06
134 #define DW_LNS_set_basic_block 0x07
135 #define DW_LNS_const_add_pc 0x08
136 #define DW_LNS_fixed_advance_pc 0x09
137 #define DW_LNS_set_prologue_end 0x0a /* DWARF3 */
138 #define DW_LNS_set_epilogue_begin 0x0b /* DWARF3 */
139 #define DW_LNS_set_isa 0x0c /* DWARF3 */
141 /* Line number extended opcode name. */
142 #define DW_LNE_end_sequence 0x01
143 #define DW_LNE_set_address 0x02
144 #define DW_LNE_define_file 0x03
145 #define DW_LNE_set_discriminator 0x04 /* DWARF4 */
147 #define kprintf(...) fprintf(errout, "" __VA_ARGS__)
149 typedef struct line_info
{
151 const char *filename
;
152 const char *path
; /* object path */
157 const char *sname
; /* function name */
159 struct line_info
*next
;
162 struct dwarf_section
{
168 typedef struct obj_info
{
169 const char *path
; /* object path */
175 struct dwarf_section debug_abbrev
;
176 struct dwarf_section debug_info
;
177 struct dwarf_section debug_line
;
178 struct dwarf_section debug_ranges
;
179 struct dwarf_section debug_str_offsets
;
180 struct dwarf_section debug_addr
;
181 struct dwarf_section debug_rnglists
;
182 struct dwarf_section debug_str
;
183 struct dwarf_section debug_line_str
;
184 struct obj_info
*next
;
187 #define DWARF_SECTION_COUNT 9
189 static struct dwarf_section
*
190 obj_dwarf_section_at(obj_info_t
*obj
, int n
)
192 struct dwarf_section
*ary
[] = {
197 &obj
->debug_str_offsets
,
199 &obj
->debug_rnglists
,
203 if (n
< 0 || DWARF_SECTION_COUNT
<= n
) {
204 UNREACHABLE_RETURN(0);
209 struct debug_section_definition
{
211 struct dwarf_section
*dwarf
;
214 /* Avoid consuming stack as this module may be used from signal handler */
215 static char binary_filename
[PATH_MAX
+ 1];
218 uleb128(const char **p
)
223 unsigned char b
= (unsigned char)*(*p
)++;
225 r
+= (unsigned long)b
<< s
;
228 r
+= (b
& 0x7f) << s
;
235 sleb128(const char **p
)
240 unsigned char b
= (unsigned char)*(*p
)++;
243 r
-= (0x80 - b
) << s
;
246 r
+= (b
& 0x3f) << s
;
250 r
+= (b
& 0x7f) << s
;
257 get_nth_dirname(unsigned long dir
, const char *p
, FILE *errout
)
266 kprintf("Unexpected directory number %lu in %s\n",
267 dir
, binary_filename
);
274 static const char *parse_ver5_debug_line_header(
275 const char *p
, int idx
, uint8_t format
,
276 obj_info_t
*obj
, const char **out_path
,
277 uint64_t *out_directory_index
, FILE *errout
);
280 fill_filename(int file
, uint8_t format
, uint16_t version
, const char *include_directories
,
281 const char *filenames
, line_info_t
*line
, obj_info_t
*obj
, FILE *errout
)
284 const char *p
= filenames
;
285 const char *filename
;
289 uint64_t directory_index
= -1;
290 parse_ver5_debug_line_header(filenames
, file
, format
, obj
, &path
, &directory_index
, errout
);
291 line
->filename
= path
;
292 parse_ver5_debug_line_header(include_directories
, (int)directory_index
, format
, obj
, &path
, NULL
, errout
);
293 line
->dirname
= path
;
296 for (i
= 1; i
<= file
; i
++) {
299 /* Need to output binary file name? */
300 kprintf("Unexpected file number %d in %s at %tx\n",
301 file
, binary_filename
, filenames
- obj
->mapped
);
309 /* size of the file. */
313 line
->filename
= filename
;
314 line
->dirname
= get_nth_dirname(dir
, include_directories
, errout
);
321 fill_line(int num_traces
, void **traces
, uintptr_t addr
, int file
, int line
,
322 uint8_t format
, uint16_t version
, const char *include_directories
, const char *filenames
,
323 obj_info_t
*obj
, line_info_t
*lines
, int offset
, FILE *errout
)
326 addr
+= obj
->base_addr
- obj
->vmaddr
;
327 for (i
= offset
; i
< num_traces
; i
++) {
328 uintptr_t a
= (uintptr_t)traces
[i
];
329 /* We assume one line code doesn't result >100 bytes of native code.
330 We may want more reliable way eventually... */
331 if (addr
< a
&& a
< addr
+ 100) {
332 fill_filename(file
, format
, version
, include_directories
, filenames
, &lines
[i
], obj
, errout
);
333 lines
[i
].line
= line
;
338 struct LineNumberProgramHeader
{
339 uint64_t unit_length
;
341 uint8_t format
; /* 4 or 8 */
342 uint64_t header_length
;
343 uint8_t minimum_instruction_length
;
344 uint8_t maximum_operations_per_instruction
;
345 uint8_t default_is_stmt
;
349 /* uint8_t standard_opcode_lengths[opcode_base-1]; */
350 const char *include_directories
;
351 const char *filenames
;
352 const char *cu_start
;
357 parse_debug_line_header(obj_info_t
*obj
, const char **pp
, struct LineNumberProgramHeader
*header
, FILE *errout
)
360 header
->unit_length
= *(uint32_t *)p
;
361 p
+= sizeof(uint32_t);
364 if (header
->unit_length
== 0xffffffff) {
365 header
->unit_length
= *(uint64_t *)p
;
366 p
+= sizeof(uint64_t);
370 header
->cu_end
= p
+ header
->unit_length
;
372 header
->version
= *(uint16_t *)p
;
373 p
+= sizeof(uint16_t);
374 if (header
->version
> 5) return -1;
376 if (header
->version
>= 5) {
377 /* address_size = *(uint8_t *)p++; */
378 /* segment_selector_size = *(uint8_t *)p++; */
382 header
->header_length
= header
->format
== 4 ? *(uint32_t *)p
: *(uint64_t *)p
;
384 header
->cu_start
= p
+ header
->header_length
;
386 header
->minimum_instruction_length
= *(uint8_t *)p
++;
388 if (header
->version
>= 4) {
389 /* maximum_operations_per_instruction = *(uint8_t *)p; */
390 if (*p
!= 1) return -1; /* For non-VLIW architectures, this field is 1 */
394 header
->default_is_stmt
= *(uint8_t *)p
++;
395 header
->line_base
= *(int8_t *)p
++;
396 header
->line_range
= *(uint8_t *)p
++;
397 header
->opcode_base
= *(uint8_t *)p
++;
398 /* header->standard_opcode_lengths = (uint8_t *)p - 1; */
399 p
+= header
->opcode_base
- 1;
401 if (header
->version
>= 5) {
402 header
->include_directories
= p
;
403 p
= parse_ver5_debug_line_header(p
, -1, header
->format
, obj
, NULL
, NULL
, errout
);
404 header
->filenames
= p
;
407 header
->include_directories
= p
;
409 /* temporary measure for compress-debug-sections */
410 if (p
>= header
->cu_end
) return -1;
412 /* skip include directories */
414 p
= memchr(p
, '\0', header
->cu_end
- p
);
420 header
->filenames
= p
;
423 *pp
= header
->cu_start
;
429 parse_debug_line_cu(int num_traces
, void **traces
, const char **debug_line
,
430 obj_info_t
*obj
, line_info_t
*lines
, int offset
, FILE *errout
)
432 const char *p
= (const char *)*debug_line
;
433 struct LineNumberProgramHeader header
;
436 unsigned long addr
= 0;
437 unsigned int file
= 1;
438 unsigned int line
= 1;
439 /* unsigned int column = 0; */
441 /* int basic_block = 0; */
442 /* int end_sequence = 0; */
443 /* int prologue_end = 0; */
444 /* int epilogue_begin = 0; */
445 /* unsigned int isa = 0; */
447 if (parse_debug_line_header(obj
, &p
, &header
, errout
))
449 is_stmt
= header
.default_is_stmt
;
451 #define FILL_LINE() \
453 fill_line(num_traces, traces, addr, file, line, \
456 header.include_directories, \
458 obj, lines, offset, errout); \
459 /*basic_block = prologue_end = epilogue_begin = 0;*/ \
462 while (p
< header
.cu_end
) {
464 unsigned char op
= *p
++;
469 case DW_LNS_advance_pc
:
470 a
= uleb128(&p
) * header
.minimum_instruction_length
;
473 case DW_LNS_advance_line
: {
474 long a
= sleb128(&p
);
478 case DW_LNS_set_file
:
479 file
= (unsigned int)uleb128(&p
);
481 case DW_LNS_set_column
:
482 /*column = (unsigned int)*/(void)uleb128(&p
);
484 case DW_LNS_negate_stmt
:
487 case DW_LNS_set_basic_block
:
488 /*basic_block = 1; */
490 case DW_LNS_const_add_pc
:
491 a
= ((255UL - header
.opcode_base
) / header
.line_range
) *
492 header
.minimum_instruction_length
;
495 case DW_LNS_fixed_advance_pc
:
497 p
+= sizeof(uint16_t);
500 case DW_LNS_set_prologue_end
:
501 /* prologue_end = 1; */
503 case DW_LNS_set_epilogue_begin
:
504 /* epilogue_begin = 1; */
507 /* isa = (unsigned int)*/(void)uleb128(&p
);
513 case DW_LNE_end_sequence
:
514 /* end_sequence = 1; */
520 is_stmt
= header
.default_is_stmt
;
521 /* end_sequence = 0; */
524 case DW_LNE_set_address
:
525 addr
= *(unsigned long *)p
;
526 p
+= sizeof(unsigned long);
528 case DW_LNE_define_file
:
529 kprintf("Unsupported operation in %s\n",
532 case DW_LNE_set_discriminator
:
533 /* TODO:currently ignore */
537 kprintf("Unknown extended opcode: %d in %s\n",
538 op
, binary_filename
);
542 uint8_t adjusted_opcode
= op
- header
.opcode_base
;
543 uint8_t operation_advance
= adjusted_opcode
/ header
.line_range
;
544 /* NOTE: this code doesn't support VLIW */
545 addr
+= operation_advance
* header
.minimum_instruction_length
;
546 line
+= header
.line_base
+ (adjusted_opcode
% header
.line_range
);
551 *debug_line
= (char *)p
;
556 parse_debug_line(int num_traces
, void **traces
,
557 const char *debug_line
, unsigned long size
,
558 obj_info_t
*obj
, line_info_t
*lines
, int offset
, FILE *errout
)
560 const char *debug_line_end
= debug_line
+ size
;
561 while (debug_line
< debug_line_end
) {
562 if (parse_debug_line_cu(num_traces
, traces
, &debug_line
, obj
, lines
, offset
, errout
))
565 if (debug_line
!= debug_line_end
) {
566 kprintf("Unexpected size of .debug_line in %s\n",
572 /* read file and fill lines */
574 fill_lines(int num_traces
, void **traces
, int check_debuglink
,
575 obj_info_t
**objp
, line_info_t
*lines
, int offset
, FILE *errout
);
578 append_obj(obj_info_t
**objp
)
580 obj_info_t
*newobj
= calloc(1, sizeof(obj_info_t
));
581 if (*objp
) (*objp
)->next
= newobj
;
586 /* Ideally we should check 4 paths to follow gnu_debuglink:
588 * - /usr/lib/debug/.build-id/ab/cdef1234.debug
589 * - /usr/bin/ruby.debug
590 * - /usr/bin/.debug/ruby.debug
591 * - /usr/lib/debug/usr/bin/ruby.debug.
593 * but we handle only two cases for now as the two formats are
594 * used by some linux distributions.
596 * See GDB's info for detail.
597 * https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html
600 // check the path pattern of "/usr/lib/debug/usr/bin/ruby.debug"
602 follow_debuglink(const char *debuglink
, int num_traces
, void **traces
,
603 obj_info_t
**objp
, line_info_t
*lines
, int offset
, FILE *errout
)
605 static const char global_debug_dir
[] = "/usr/lib/debug";
606 const size_t global_debug_dir_len
= sizeof(global_debug_dir
) - 1;
608 obj_info_t
*o1
= *objp
, *o2
;
611 p
= strrchr(binary_filename
, '/');
617 len
= strlen(binary_filename
);
618 if (len
>= PATH_MAX
- global_debug_dir_len
)
619 len
= PATH_MAX
- global_debug_dir_len
- 1;
620 memmove(binary_filename
+ global_debug_dir_len
, binary_filename
, len
);
621 memcpy(binary_filename
, global_debug_dir
, global_debug_dir_len
);
622 len
+= global_debug_dir_len
;
623 strlcpy(binary_filename
+ len
, debuglink
, PATH_MAX
- len
);
627 o2
->base_addr
= o1
->base_addr
;
629 fill_lines(num_traces
, traces
, 0, objp
, lines
, offset
, errout
);
632 // check the path pattern of "/usr/lib/debug/.build-id/ab/cdef1234.debug"
634 follow_debuglink_build_id(const char *build_id
, size_t build_id_size
, int num_traces
, void **traces
,
635 obj_info_t
**objp
, line_info_t
*lines
, int offset
, FILE *errout
)
637 static const char global_debug_dir
[] = "/usr/lib/debug/.build-id/";
638 const size_t global_debug_dir_len
= sizeof(global_debug_dir
) - 1;
640 obj_info_t
*o1
= *objp
, *o2
;
643 if (PATH_MAX
< global_debug_dir_len
+ 1 + build_id_size
* 2 + 6) return;
645 memcpy(binary_filename
, global_debug_dir
, global_debug_dir_len
);
646 p
= binary_filename
+ global_debug_dir_len
;
647 for (i
= 0; i
< build_id_size
; i
++) {
648 static const char tbl
[] = "0123456789abcdef";
649 unsigned char n
= build_id
[i
];
652 if (i
== 0) *p
++ = '/';
658 o2
->base_addr
= o1
->base_addr
;
660 fill_lines(num_traces
, traces
, 0, objp
, lines
, offset
, errout
);
666 DW_TAG_compile_unit
= 0x11,
667 DW_TAG_inlined_subroutine
= 0x1d,
668 DW_TAG_subprogram
= 0x2e,
671 /* Attributes encodings */
674 DW_AT_sibling
= 0x01,
675 DW_AT_location
= 0x02,
682 DW_AT_ordering
= 0x09,
684 DW_AT_byte_size
= 0x0b,
686 DW_AT_bit_size
= 0x0d,
689 DW_AT_stmt_list
= 0x10,
691 DW_AT_high_pc
= 0x12,
692 DW_AT_language
= 0x13,
695 DW_AT_discr_value
= 0x16,
696 DW_AT_visibility
= 0x17,
698 DW_AT_string_length
= 0x19,
699 DW_AT_common_reference
= 0x1a,
700 DW_AT_comp_dir
= 0x1b,
701 DW_AT_const_value
= 0x1c,
702 DW_AT_containing_type
= 0x1d,
703 DW_AT_default_value
= 0x1e,
706 DW_AT_is_optional
= 0x21,
707 DW_AT_lower_bound
= 0x22,
710 DW_AT_producer
= 0x25,
712 DW_AT_prototyped
= 0x27,
715 DW_AT_return_addr
= 0x2a,
717 DW_AT_start_scope
= 0x2c,
719 DW_AT_bit_stride
= 0x2e,
720 DW_AT_upper_bound
= 0x2f,
722 DW_AT_abstract_origin
= 0x31,
723 DW_AT_accessibility
= 0x32,
724 DW_AT_address_class
= 0x33,
725 DW_AT_artificial
= 0x34,
726 DW_AT_base_types
= 0x35,
727 DW_AT_calling_convention
= 0x36,
729 DW_AT_data_member_location
= 0x38,
730 DW_AT_decl_column
= 0x39,
731 DW_AT_decl_file
= 0x3a,
732 DW_AT_decl_line
= 0x3b,
733 DW_AT_declaration
= 0x3c,
734 DW_AT_discr_list
= 0x3d,
735 DW_AT_encoding
= 0x3e,
736 DW_AT_external
= 0x3f,
737 DW_AT_frame_base
= 0x40,
739 DW_AT_identifier_case
= 0x42,
741 DW_AT_namelist_item
= 0x44,
742 DW_AT_priority
= 0x45,
743 DW_AT_segment
= 0x46,
744 DW_AT_specification
= 0x47,
745 DW_AT_static_link
= 0x48,
747 DW_AT_use_location
= 0x4a,
748 DW_AT_variable_parameter
= 0x4b,
749 DW_AT_virtuality
= 0x4c,
750 DW_AT_vtable_elem_location
= 0x4d,
751 DW_AT_allocated
= 0x4e,
752 DW_AT_associated
= 0x4f,
753 DW_AT_data_location
= 0x50,
754 DW_AT_byte_stride
= 0x51,
755 DW_AT_entry_pc
= 0x52,
756 DW_AT_use_UTF8
= 0x53,
757 DW_AT_extension
= 0x54,
759 DW_AT_trampoline
= 0x56,
760 DW_AT_call_column
= 0x57,
761 DW_AT_call_file
= 0x58,
762 DW_AT_call_line
= 0x59,
763 DW_AT_description
= 0x5a,
764 DW_AT_binary_scale
= 0x5b,
765 DW_AT_decimal_scale
= 0x5c,
767 DW_AT_decimal_sign
= 0x5e,
768 DW_AT_digit_count
= 0x5f,
769 DW_AT_picture_string
= 0x60,
770 DW_AT_mutable
= 0x61,
771 DW_AT_threads_scaled
= 0x62,
772 DW_AT_explicit
= 0x63,
773 DW_AT_object_pointer
= 0x64,
774 DW_AT_endianity
= 0x65,
775 DW_AT_elemental
= 0x66,
777 DW_AT_recursive
= 0x68,
778 DW_AT_signature
= 0x69,
779 DW_AT_main_subprogram
= 0x6a,
780 DW_AT_data_bit_offset
= 0x6b,
781 DW_AT_const_expr
= 0x6c,
782 DW_AT_enum_class
= 0x6d,
783 DW_AT_linkage_name
= 0x6e,
784 DW_AT_string_length_bit_size
= 0x6f,
785 DW_AT_string_length_byte_size
= 0x70,
787 DW_AT_str_offsets_base
= 0x72,
788 DW_AT_addr_base
= 0x73,
789 DW_AT_rnglists_base
= 0x74,
791 DW_AT_dwo_name
= 0x76,
792 DW_AT_reference
= 0x77,
793 DW_AT_rvalue_reference
= 0x78,
795 DW_AT_call_all_calls
= 0x7a,
796 DW_AT_call_all_source_calls
= 0x7b,
797 DW_AT_call_all_tail_calls
= 0x7c,
798 DW_AT_call_return_pc
= 0x7d,
799 DW_AT_call_value
= 0x7e,
800 DW_AT_call_origin
= 0x7f,
801 DW_AT_call_parameter
= 0x80,
802 DW_AT_call_pc
= 0x81,
803 DW_AT_call_tail_call
= 0x82,
804 DW_AT_call_target
= 0x83,
805 DW_AT_call_target_clobbered
= 0x84,
806 DW_AT_call_data_location
= 0x85,
807 DW_AT_call_data_value
= 0x86,
808 DW_AT_noreturn
= 0x87,
809 DW_AT_alignment
= 0x88,
810 DW_AT_export_symbols
= 0x89,
811 DW_AT_deleted
= 0x8a,
812 DW_AT_defaulted
= 0x8b,
813 DW_AT_loclists_base
= 0x8c,
814 DW_AT_lo_user
= 0x2000,
815 DW_AT_hi_user
= 0x3fff
818 /* Attribute form encodings */
823 DW_FORM_block2
= 0x03,
824 DW_FORM_block4
= 0x04,
825 DW_FORM_data2
= 0x05,
826 DW_FORM_data4
= 0x06,
827 DW_FORM_data8
= 0x07,
828 DW_FORM_string
= 0x08,
829 DW_FORM_block
= 0x09,
830 DW_FORM_block1
= 0x0a,
831 DW_FORM_data1
= 0x0b,
833 DW_FORM_sdata
= 0x0d,
835 DW_FORM_udata
= 0x0f,
836 DW_FORM_ref_addr
= 0x10,
841 DW_FORM_ref_udata
= 0x15,
842 DW_FORM_indirect
= 0x16,
843 DW_FORM_sec_offset
= 0x17,
844 DW_FORM_exprloc
= 0x18,
845 DW_FORM_flag_present
= 0x19,
847 DW_FORM_addrx
= 0x1b,
848 DW_FORM_ref_sup4
= 0x1c,
849 DW_FORM_strp_sup
= 0x1d,
850 DW_FORM_data16
= 0x1e,
851 DW_FORM_line_strp
= 0x1f,
852 DW_FORM_ref_sig8
= 0x20,
853 DW_FORM_implicit_const
= 0x21,
854 DW_FORM_loclistx
= 0x22,
855 DW_FORM_rnglistx
= 0x23,
856 DW_FORM_ref_sup8
= 0x24,
857 DW_FORM_strx1
= 0x25,
858 DW_FORM_strx2
= 0x26,
859 DW_FORM_strx3
= 0x27,
860 DW_FORM_strx4
= 0x28,
861 DW_FORM_addrx1
= 0x29,
862 DW_FORM_addrx2
= 0x2a,
863 DW_FORM_addrx3
= 0x2b,
864 DW_FORM_addrx4
= 0x2c,
866 /* GNU extensions for referring to .gnu_debugaltlink dwz-compressed info */
867 DW_FORM_GNU_ref_alt
= 0x1f20,
868 DW_FORM_GNU_strp_alt
= 0x1f21
871 /* Range list entry encodings */
873 DW_RLE_end_of_list
= 0x00,
874 DW_RLE_base_addressx
= 0x01,
875 DW_RLE_startx_endx
= 0x02,
876 DW_RLE_startx_length
= 0x03,
877 DW_RLE_offset_pair
= 0x04,
878 DW_RLE_base_address
= 0x05,
879 DW_RLE_start_end
= 0x06,
880 DW_RLE_start_length
= 0x07
892 # define ABBREV_TABLE_SIZE 256
896 uint8_t current_version
;
897 const char *current_cu
;
898 uint64_t current_low_pc
;
899 uint64_t current_str_offsets_base
;
900 uint64_t current_addr_base
;
901 uint64_t current_rnglists_base
;
902 const char *debug_line_cu_end
;
903 uint8_t debug_line_format
;
904 uint16_t debug_line_version
;
905 const char *debug_line_files
;
906 const char *debug_line_directories
;
912 int format
; // 4 or 8
913 uint8_t address_size
;
915 const char *abbrev_table
[ABBREV_TABLE_SIZE
];
938 #if defined(WORDS_BIGENDIAN)
939 #define MERGE_2INTS(a,b,sz) (((uint64_t)(a)<<sz)|(b))
941 #define MERGE_2INTS(a,b,sz) (((uint64_t)(b)<<sz)|(a))
945 get_uint16(const uint8_t *p
)
947 return (uint16_t)MERGE_2INTS(p
[0],p
[1],8);
951 get_uint32(const uint8_t *p
)
953 return (uint32_t)MERGE_2INTS(get_uint16(p
),get_uint16(p
+2),16);
957 get_uint64(const uint8_t *p
)
959 return MERGE_2INTS(get_uint32(p
),get_uint32(p
+4),32);
963 read_uint8(const char **ptr
)
965 const char *p
= *ptr
;
971 read_uint16(const char **ptr
)
973 const char *p
= *ptr
;
975 return get_uint16((const uint8_t *)p
);
979 read_uint24(const char **ptr
)
981 const char *p
= *ptr
;
983 return ((uint8_t)*p
<< 16) | get_uint16((const uint8_t *)p
+1);
987 read_uint32(const char **ptr
)
989 const char *p
= *ptr
;
991 return get_uint32((const uint8_t *)p
);
995 read_uint64(const char **ptr
)
997 const unsigned char *p
= (const unsigned char *)*ptr
;
998 *ptr
= (char *)(p
+ 8);
999 return get_uint64(p
);
1003 read_uintptr(const char **ptr
)
1005 const unsigned char *p
= (const unsigned char *)*ptr
;
1006 *ptr
= (char *)(p
+ SIZEOF_VOIDP
);
1007 #if SIZEOF_VOIDP == 8
1008 return get_uint64(p
);
1010 return get_uint32(p
);
1015 read_uint(DebugInfoReader
*reader
)
1017 if (reader
->format
== 4) {
1018 return read_uint32(&reader
->p
);
1019 } else { /* 64 bit */
1020 return read_uint64(&reader
->p
);
1025 read_uleb128(DebugInfoReader
*reader
)
1027 return uleb128(&reader
->p
);
1031 read_sleb128(DebugInfoReader
*reader
)
1033 return sleb128(&reader
->p
);
1037 debug_info_reader_init(DebugInfoReader
*reader
, obj_info_t
*obj
)
1039 reader
->file
= obj
->mapped
;
1041 reader
->p
= obj
->debug_info
.ptr
;
1042 reader
->pend
= obj
->debug_info
.ptr
+ obj
->debug_info
.size
;
1043 reader
->debug_line_cu_end
= obj
->debug_line
.ptr
;
1044 reader
->current_low_pc
= 0;
1045 reader
->current_str_offsets_base
= 0;
1046 reader
->current_addr_base
= 0;
1047 reader
->current_rnglists_base
= 0;
1051 di_skip_die_attributes(const char **p
)
1054 uint64_t at
= uleb128(p
);
1055 uint64_t form
= uleb128(p
);
1056 if (!at
&& !form
) break;
1060 case DW_FORM_implicit_const
:
1068 di_read_debug_abbrev_cu(DebugInfoReader
*reader
)
1071 const char *p
= reader
->q0
;
1073 uint64_t abbrev_number
= uleb128(&p
);
1074 if (abbrev_number
<= prev
) break;
1075 if (abbrev_number
< ABBREV_TABLE_SIZE
) {
1076 reader
->abbrev_table
[abbrev_number
] = p
;
1078 prev
= abbrev_number
;
1079 uleb128(&p
); /* tag */
1080 p
++; /* has_children */
1081 di_skip_die_attributes(&p
);
1086 di_read_debug_line_cu(DebugInfoReader
*reader
, FILE *errout
)
1089 struct LineNumberProgramHeader header
;
1091 p
= (const char *)reader
->debug_line_cu_end
;
1092 if (parse_debug_line_header(reader
->obj
, &p
, &header
, errout
))
1095 reader
->debug_line_cu_end
= (char *)header
.cu_end
;
1096 reader
->debug_line_format
= header
.format
;
1097 reader
->debug_line_version
= header
.version
;
1098 reader
->debug_line_directories
= (char *)header
.include_directories
;
1099 reader
->debug_line_files
= (char *)header
.filenames
;
1105 set_addr_idx_value(DebugInfoValue
*v
, uint64_t n
)
1112 set_uint_value(DebugInfoValue
*v
, uint64_t n
)
1119 set_int_value(DebugInfoValue
*v
, int64_t n
)
1126 set_cstr_value(DebugInfoValue
*v
, const char *s
)
1134 set_cstrp_value(DebugInfoValue
*v
, const char *s
, uint64_t off
)
1142 set_data_value(DebugInfoValue
*v
, const char *s
)
1149 get_cstr_value(DebugInfoValue
*v
)
1152 return v
->as
.ptr
+ v
->off
;
1159 resolve_strx(DebugInfoReader
*reader
, uint64_t idx
)
1161 const char *p
= reader
->obj
->debug_str_offsets
.ptr
+ reader
->current_str_offsets_base
;
1163 if (reader
->format
== 4) {
1164 off
= ((uint32_t *)p
)[idx
];
1167 off
= ((uint64_t *)p
)[idx
];
1169 return reader
->obj
->debug_str
.ptr
+ off
;
1173 debug_info_reader_read_addr_value_member(DebugInfoReader
*reader
, DebugInfoValue
*v
, int size
)
1176 set_uint_value(v
, read_uint32(&reader
->p
));
1177 } else if (size
== 8) {
1178 set_uint_value(v
, read_uint64(&reader
->p
));
1185 #define debug_info_reader_read_addr_value(reader, v, mem) \
1186 if (!debug_info_reader_read_addr_value_member((reader), (v), (reader)->mem)) { \
1187 kprintf("unknown " #mem ":%d", (reader)->mem); \
1193 debug_info_reader_read_value(DebugInfoReader
*reader
, uint64_t form
, DebugInfoValue
*v
, FILE *errout
)
1197 debug_info_reader_read_addr_value(reader
, v
, address_size
);
1199 case DW_FORM_block2
:
1200 v
->size
= read_uint16(&reader
->p
);
1201 set_data_value(v
, reader
->p
);
1202 reader
->p
+= v
->size
;
1204 case DW_FORM_block4
:
1205 v
->size
= read_uint32(&reader
->p
);
1206 set_data_value(v
, reader
->p
);
1207 reader
->p
+= v
->size
;
1210 set_uint_value(v
, read_uint16(&reader
->p
));
1213 set_uint_value(v
, read_uint32(&reader
->p
));
1216 set_uint_value(v
, read_uint64(&reader
->p
));
1218 case DW_FORM_string
:
1219 v
->size
= strlen(reader
->p
);
1220 set_cstr_value(v
, reader
->p
);
1221 reader
->p
+= v
->size
+ 1;
1224 v
->size
= uleb128(&reader
->p
);
1225 set_data_value(v
, reader
->p
);
1226 reader
->p
+= v
->size
;
1228 case DW_FORM_block1
:
1229 v
->size
= read_uint8(&reader
->p
);
1230 set_data_value(v
, reader
->p
);
1231 reader
->p
+= v
->size
;
1234 set_uint_value(v
, read_uint8(&reader
->p
));
1237 set_uint_value(v
, read_uint8(&reader
->p
));
1240 set_int_value(v
, read_sleb128(reader
));
1243 set_cstrp_value(v
, reader
->obj
->debug_str
.ptr
, read_uint(reader
));
1246 set_uint_value(v
, read_uleb128(reader
));
1248 case DW_FORM_ref_addr
:
1249 if (reader
->current_version
<= 2) {
1250 // DWARF Version 2 specifies that references have
1251 // the same size as an address on the target system
1252 debug_info_reader_read_addr_value(reader
, v
, address_size
);
1254 debug_info_reader_read_addr_value(reader
, v
, format
);
1258 set_uint_value(v
, read_uint8(&reader
->p
));
1261 set_uint_value(v
, read_uint16(&reader
->p
));
1264 set_uint_value(v
, read_uint32(&reader
->p
));
1267 set_uint_value(v
, read_uint64(&reader
->p
));
1269 case DW_FORM_ref_udata
:
1270 set_uint_value(v
, uleb128(&reader
->p
));
1272 case DW_FORM_indirect
:
1273 /* TODO: read the referred value */
1274 set_uint_value(v
, uleb128(&reader
->p
));
1276 case DW_FORM_sec_offset
:
1277 set_uint_value(v
, read_uint(reader
)); /* offset */
1278 /* addrptr: debug_addr */
1279 /* lineptr: debug_line */
1280 /* loclist: debug_loclists */
1281 /* loclistptr: debug_loclists */
1282 /* macptr: debug_macro */
1283 /* rnglist: debug_rnglists */
1284 /* rnglistptr: debug_rnglists */
1285 /* stroffsetsptr: debug_str_offsets */
1287 case DW_FORM_exprloc
:
1288 v
->size
= (size_t)read_uleb128(reader
);
1289 set_data_value(v
, reader
->p
);
1290 reader
->p
+= v
->size
;
1292 case DW_FORM_flag_present
:
1293 set_uint_value(v
, 1);
1296 set_cstr_value(v
, resolve_strx(reader
, uleb128(&reader
->p
)));
1299 set_addr_idx_value(v
, uleb128(&reader
->p
));
1301 case DW_FORM_ref_sup4
:
1302 set_uint_value(v
, read_uint32(&reader
->p
));
1304 case DW_FORM_strp_sup
:
1305 set_uint_value(v
, read_uint(reader
));
1306 /* *p = reader->sup_file + reader->sup_str->sh_offset + ret; */
1308 case DW_FORM_data16
:
1310 set_data_value(v
, reader
->p
);
1311 reader
->p
+= v
->size
;
1313 case DW_FORM_line_strp
:
1314 set_cstrp_value(v
, reader
->obj
->debug_line_str
.ptr
, read_uint(reader
));
1316 case DW_FORM_ref_sig8
:
1317 set_uint_value(v
, read_uint64(&reader
->p
));
1319 case DW_FORM_implicit_const
:
1320 set_int_value(v
, sleb128(&reader
->q
));
1322 case DW_FORM_loclistx
:
1323 set_uint_value(v
, read_uleb128(reader
));
1325 case DW_FORM_rnglistx
:
1326 set_uint_value(v
, read_uleb128(reader
));
1328 case DW_FORM_ref_sup8
:
1329 set_uint_value(v
, read_uint64(&reader
->p
));
1332 set_cstr_value(v
, resolve_strx(reader
, read_uint8(&reader
->p
)));
1335 set_cstr_value(v
, resolve_strx(reader
, read_uint16(&reader
->p
)));
1338 set_cstr_value(v
, resolve_strx(reader
, read_uint24(&reader
->p
)));
1341 set_cstr_value(v
, resolve_strx(reader
, read_uint32(&reader
->p
)));
1343 case DW_FORM_addrx1
:
1344 set_addr_idx_value(v
, read_uint8(&reader
->p
));
1346 case DW_FORM_addrx2
:
1347 set_addr_idx_value(v
, read_uint16(&reader
->p
));
1349 case DW_FORM_addrx3
:
1350 set_addr_idx_value(v
, read_uint24(&reader
->p
));
1352 case DW_FORM_addrx4
:
1353 set_addr_idx_value(v
, read_uint32(&reader
->p
));
1355 /* we have no support for actually reading the real values of these refs out
1356 * of the .gnu_debugaltlink dwz-compressed debuginfo at the moment, but "read"
1357 * them anyway so that we advance the reader by the right amount. */
1358 case DW_FORM_GNU_ref_alt
:
1359 case DW_FORM_GNU_strp_alt
:
1361 set_uint_value(v
, 0);
1370 kprintf("%d: unsupported form: %#"PRIx64
"\n", __LINE__
, form
);
1374 /* find abbrev in current compilation unit */
1376 di_find_abbrev(DebugInfoReader
*reader
, uint64_t abbrev_number
, FILE *errout
)
1379 if (abbrev_number
< ABBREV_TABLE_SIZE
) {
1380 return reader
->abbrev_table
[abbrev_number
];
1382 p
= reader
->abbrev_table
[ABBREV_TABLE_SIZE
-1];
1383 /* skip 255th record */
1384 uleb128(&p
); /* tag */
1385 p
++; /* has_children */
1386 di_skip_die_attributes(&p
);
1387 for (uint64_t n
= uleb128(&p
); abbrev_number
!= n
; n
= uleb128(&p
)) {
1389 kprintf("%d: Abbrev Number %"PRId64
" not found\n",__LINE__
, abbrev_number
);
1392 uleb128(&p
); /* tag */
1393 p
++; /* has_children */
1394 di_skip_die_attributes(&p
);
1401 hexdump0(const unsigned char *p
, size_t n
, FILE *errout
)
1404 kprintf(" 0 1 2 3 4 5 6 7 8 9 A B C D E F\n");
1405 for (i
=0; i
< n
; i
++){
1408 kprintf("%02" PRIdSIZE
": %02X ", i
/16, p
[i
]);
1411 kprintf("%02X\n", p
[i
]);
1414 kprintf("%02X ", p
[i
]);
1418 if ((i
& 15) != 15) {
1422 #define hexdump(p,n,e) hexdump0((const unsigned char *)p, n, e)
1425 div_inspect(DebugInfoValue
*v
, FILE *errout
)
1429 kprintf("%d: type:%d size:%" PRIxSIZE
" v:%"PRIx64
"\n",__LINE__
,v
->type
,v
->size
,v
->as
.uint64
);
1432 kprintf("%d: type:%d size:%" PRIxSIZE
" v:%"PRId64
"\n",__LINE__
,v
->type
,v
->size
,(int64_t)v
->as
.uint64
);
1435 kprintf("%d: type:%d size:%" PRIxSIZE
" v:'%s'\n",__LINE__
,v
->type
,v
->size
,v
->as
.ptr
);
1438 kprintf("%d: type:%d size:%" PRIxSIZE
" v:\n",__LINE__
,v
->type
,v
->size
);
1439 hexdump(v
->as
.ptr
, 16, errout
);
1446 di_read_die(DebugInfoReader
*reader
, DIE
*die
, FILE *errout
)
1448 uint64_t abbrev_number
= uleb128(&reader
->p
);
1449 if (abbrev_number
== 0) {
1454 if (!(reader
->q
= di_find_abbrev(reader
, abbrev_number
, errout
))) return NULL
;
1456 die
->pos
= reader
->p
- reader
->obj
->debug_info
.ptr
- 1;
1457 die
->tag
= (int)uleb128(&reader
->q
); /* tag */
1458 die
->has_children
= *reader
->q
++; /* has_children */
1459 if (die
->has_children
) {
1465 static DebugInfoValue
*
1466 di_read_record(DebugInfoReader
*reader
, DebugInfoValue
*vp
, FILE *errout
)
1468 uint64_t at
= uleb128(&reader
->q
);
1469 uint64_t form
= uleb128(&reader
->q
);
1470 if (!at
|| !form
) return NULL
;
1473 if (!debug_info_reader_read_value(reader
, form
, vp
, errout
)) return NULL
;
1478 di_skip_records(DebugInfoReader
*reader
, FILE *errout
)
1481 DebugInfoValue v
= {{0}};
1482 uint64_t at
= uleb128(&reader
->q
);
1483 uint64_t form
= uleb128(&reader
->q
);
1484 if (!at
|| !form
) return true;
1485 if (!debug_info_reader_read_value(reader
, form
, &v
, errout
)) return false;
1489 typedef struct addr_header
{
1491 uint64_t unit_length
;
1493 uint8_t address_size
;
1494 /* uint8_t segment_selector_size; */
1498 addr_header_init(obj_info_t
*obj
, addr_header_t
*header
, FILE *errout
)
1500 const char *p
= obj
->debug_addr
.ptr
;
1504 if (!p
) return true;
1506 header
->unit_length
= *(uint32_t *)p
;
1507 p
+= sizeof(uint32_t);
1510 if (header
->unit_length
== 0xffffffff) {
1511 header
->unit_length
= *(uint64_t *)p
;
1512 p
+= sizeof(uint64_t);
1516 p
+= 2; /* version */
1517 header
->address_size
= *p
++;
1518 if (header
->address_size
!= 4 && header
->address_size
!= 8) {
1519 kprintf("unknown address_size:%d", header
->address_size
);
1522 p
++; /* segment_selector_size */
1527 read_addr(addr_header_t
*header
, uint64_t addr_base
, uint64_t idx
) {
1528 if (header
->address_size
== 4) {
1529 return ((uint32_t*)(header
->ptr
+ addr_base
))[idx
];
1532 return ((uint64_t*)(header
->ptr
+ addr_base
))[idx
];
1536 typedef struct rnglists_header
{
1537 uint64_t unit_length
;
1539 uint8_t address_size
;
1540 uint32_t offset_entry_count
;
1541 } rnglists_header_t
;
1544 rnglists_header_init(obj_info_t
*obj
, rnglists_header_t
*header
, FILE *errout
)
1546 const char *p
= obj
->debug_rnglists
.ptr
;
1548 if (!p
) return true;
1550 header
->unit_length
= *(uint32_t *)p
;
1551 p
+= sizeof(uint32_t);
1554 if (header
->unit_length
== 0xffffffff) {
1555 header
->unit_length
= *(uint64_t *)p
;
1556 p
+= sizeof(uint64_t);
1560 p
+= 2; /* version */
1561 header
->address_size
= *p
++;
1562 if (header
->address_size
!= 4 && header
->address_size
!= 8) {
1563 kprintf("unknown address_size:%d", header
->address_size
);
1566 p
++; /* segment_selector_size */
1567 header
->offset_entry_count
= *(uint32_t *)p
;
1581 ranges_set(ranges_t
*ptr
, DebugInfoValue
*v
, addr_header_t
*addr_header
, uint64_t addr_base
)
1584 if (v
->type
== VAL_uint
) {
1587 else if (v
->type
== VAL_addr
) {
1588 n
= read_addr(addr_header
, addr_base
, v
->as
.addr_idx
);
1593 ptr
->low_pc_set
= true;
1596 if (v
->form
== DW_FORM_addr
) {
1600 ptr
->high_pc
= ptr
->low_pc
+ n
;
1602 ptr
->high_pc_set
= true;
1606 ptr
->ranges_set
= true;
1612 read_dw_form_addr(DebugInfoReader
*reader
, const char **ptr
, FILE *errout
)
1614 const char *p
= *ptr
;
1615 *ptr
= p
+ reader
->address_size
;
1616 if (reader
->address_size
== 4) {
1617 return read_uint32(&p
);
1619 return read_uint64(&p
);
1624 ranges_include(DebugInfoReader
*reader
, ranges_t
*ptr
, uint64_t addr
, rnglists_header_t
*rnglists_header
, FILE *errout
)
1626 if (ptr
->high_pc_set
) {
1627 if (ptr
->ranges_set
|| !ptr
->low_pc_set
) {
1630 if (ptr
->low_pc
<= addr
&& addr
<= ptr
->high_pc
) {
1631 return (uintptr_t)ptr
->low_pc
;
1634 else if (ptr
->ranges_set
) {
1635 /* TODO: support base address selection entry */
1637 uint64_t base
= ptr
->low_pc_set
? ptr
->low_pc
: reader
->current_low_pc
;
1638 bool base_valid
= true;
1639 if (reader
->current_version
>= 5) {
1640 if (rnglists_header
->offset_entry_count
== 0) {
1641 // DW_FORM_sec_offset
1642 p
= reader
->obj
->debug_rnglists
.ptr
+ ptr
->ranges
+ reader
->current_rnglists_base
;
1646 const char *offset_array
= reader
->obj
->debug_rnglists
.ptr
+ reader
->current_rnglists_base
;
1647 if (rnglists_header
->format
== 4) {
1648 p
= offset_array
+ ((uint32_t *)offset_array
)[ptr
->ranges
];
1651 p
= offset_array
+ ((uint64_t *)offset_array
)[ptr
->ranges
];
1655 uint8_t rle
= read_uint8(&p
);
1656 uintptr_t from
= 0, to
= 0;
1657 if (rle
== DW_RLE_end_of_list
) break;
1659 case DW_RLE_base_addressx
:
1661 base_valid
= false; /* not supported yet */
1663 case DW_RLE_startx_endx
:
1667 case DW_RLE_startx_length
:
1671 case DW_RLE_offset_pair
:
1672 if (!base_valid
) break;
1673 from
= (uintptr_t)base
+ uleb128(&p
);
1674 to
= (uintptr_t)base
+ uleb128(&p
);
1676 case DW_RLE_base_address
:
1677 base
= read_dw_form_addr(reader
, &p
, errout
);
1680 case DW_RLE_start_end
:
1681 from
= (uintptr_t)read_dw_form_addr(reader
, &p
, errout
);
1682 to
= (uintptr_t)read_dw_form_addr(reader
, &p
, errout
);
1684 case DW_RLE_start_length
:
1685 from
= (uintptr_t)read_dw_form_addr(reader
, &p
, errout
);
1686 to
= from
+ uleb128(&p
);
1689 if (from
<= addr
&& addr
< to
) {
1695 p
= reader
->obj
->debug_ranges
.ptr
+ ptr
->ranges
;
1697 uintptr_t from
= read_uintptr(&p
);
1698 uintptr_t to
= read_uintptr(&p
);
1699 if (!from
&& !to
) break;
1700 if (from
== UINTPTR_MAX
) {
1701 /* base address selection entry */
1704 else if (base
+ from
<= addr
&& addr
< base
+ to
) {
1705 return (uintptr_t)base
+ from
;
1709 else if (ptr
->low_pc_set
) {
1710 if (ptr
->low_pc
== addr
) {
1711 return (uintptr_t)ptr
->low_pc
;
1719 ranges_inspect(DebugInfoReader
*reader
, ranges_t
*ptr
, FILE *errout
)
1721 if (ptr
->high_pc_set
) {
1722 if (ptr
->ranges_set
|| !ptr
->low_pc_set
) {
1723 kprintf("low_pc_set:%d high_pc_set:%d ranges_set:%d\n",ptr
->low_pc_set
,ptr
->high_pc_set
,ptr
->ranges_set
);
1726 kprintf("low_pc:%"PRIx64
" high_pc:%"PRIx64
"\n",ptr
->low_pc
,ptr
->high_pc
);
1728 else if (ptr
->ranges_set
) {
1729 char *p
= reader
->obj
->debug_ranges
.ptr
+ ptr
->ranges
;
1730 kprintf("low_pc:%"PRIx64
" ranges:%"PRIx64
" %lx ",ptr
->low_pc
,ptr
->ranges
, p
-reader
->obj
->mapped
);
1732 uintptr_t from
= read_uintptr(&p
);
1733 uintptr_t to
= read_uintptr(&p
);
1734 if (!from
&& !to
) break;
1735 kprintf("%"PRIx64
"-%"PRIx64
" ",ptr
->low_pc
+from
,ptr
->low_pc
+to
);
1739 else if (ptr
->low_pc_set
) {
1740 kprintf("low_pc:%"PRIx64
"\n",ptr
->low_pc
);
1749 di_read_cu(DebugInfoReader
*reader
, FILE *errout
)
1751 uint64_t unit_length
;
1753 uint64_t debug_abbrev_offset
;
1755 reader
->current_cu
= reader
->p
;
1756 unit_length
= read_uint32(&reader
->p
);
1757 if (unit_length
== 0xffffffff) {
1758 unit_length
= read_uint64(&reader
->p
);
1761 reader
->cu_end
= reader
->p
+ unit_length
;
1762 version
= read_uint16(&reader
->p
);
1763 reader
->current_version
= version
;
1767 else if (version
== 5) {
1768 /* unit_type = */ read_uint8(&reader
->p
);
1769 reader
->address_size
= read_uint8(&reader
->p
);
1770 debug_abbrev_offset
= read_uint(reader
);
1773 debug_abbrev_offset
= read_uint(reader
);
1774 reader
->address_size
= read_uint8(&reader
->p
);
1776 if (reader
->address_size
!= 4 && reader
->address_size
!= 8) {
1777 kprintf("unknown address_size:%d", reader
->address_size
);
1780 reader
->q0
= reader
->obj
->debug_abbrev
.ptr
+ debug_abbrev_offset
;
1783 di_read_debug_abbrev_cu(reader
);
1784 if (di_read_debug_line_cu(reader
, errout
)) return -1;
1789 if (!di_read_die(reader
, &die
, errout
)) continue;
1791 if (die
.tag
!= DW_TAG_compile_unit
) {
1792 if (!di_skip_records(reader
, errout
)) return -1;
1796 reader
->current_str_offsets_base
= 0;
1797 reader
->current_addr_base
= 0;
1798 reader
->current_rnglists_base
= 0;
1800 DebugInfoValue low_pc
= {{0}};
1801 /* enumerate abbrev */
1803 DebugInfoValue v
= {{0}};
1804 if (!di_read_record(reader
, &v
, errout
)) break;
1807 // clang may output DW_AT_addr_base after DW_AT_low_pc.
1808 // We need to resolve the DW_FORM_addr* after DW_AT_addr_base is parsed.
1811 case DW_AT_str_offsets_base
:
1812 reader
->current_str_offsets_base
= v
.as
.uint64
;
1814 case DW_AT_addr_base
:
1815 reader
->current_addr_base
= v
.as
.uint64
;
1817 case DW_AT_rnglists_base
:
1818 reader
->current_rnglists_base
= v
.as
.uint64
;
1822 // Resolve the DW_FORM_addr of DW_AT_low_pc
1823 switch (low_pc
.type
) {
1825 reader
->current_low_pc
= low_pc
.as
.uint64
;
1829 addr_header_t header
= {0};
1830 if (!addr_header_init(reader
->obj
, &header
, errout
)) return -1;
1831 reader
->current_low_pc
= read_addr(&header
, reader
->current_addr_base
, low_pc
.as
.addr_idx
);
1841 read_abstract_origin(DebugInfoReader
*reader
, uint64_t form
, uint64_t abstract_origin
, line_info_t
*line
, FILE *errout
)
1843 const char *p
= reader
->p
;
1844 const char *q
= reader
->q
;
1845 int level
= reader
->level
;
1853 case DW_FORM_ref_udata
:
1854 reader
->p
= reader
->current_cu
+ abstract_origin
;
1856 case DW_FORM_ref_addr
:
1857 goto finish
; /* not supported yet */
1858 case DW_FORM_ref_sig8
:
1859 goto finish
; /* not supported yet */
1860 case DW_FORM_ref_sup4
:
1861 case DW_FORM_ref_sup8
:
1862 goto finish
; /* not supported yet */
1866 if (!di_read_die(reader
, &die
, errout
)) goto finish
;
1868 /* enumerate abbrev */
1870 DebugInfoValue v
= {{0}};
1871 if (!di_read_record(reader
, &v
, errout
)) break;
1874 line
->sname
= get_cstr_value(&v
);
1882 reader
->level
= level
;
1886 debug_info_read(DebugInfoReader
*reader
, int num_traces
, void **traces
,
1887 line_info_t
*lines
, int offset
, FILE *errout
)
1890 addr_header_t addr_header
= {0};
1891 if (!addr_header_init(reader
->obj
, &addr_header
, errout
)) return false;
1893 rnglists_header_t rnglists_header
= {0};
1894 if (!rnglists_header_init(reader
->obj
, &rnglists_header
, errout
)) return false;
1896 while (reader
->p
< reader
->cu_end
) {
1898 ranges_t ranges
= {0};
1899 line_info_t line
= {0};
1901 if (!di_read_die(reader
, &die
, errout
)) continue;
1902 /* kprintf("%d:%tx: <%d>\n",__LINE__,die.pos,reader->level,die.tag); */
1904 if (die
.tag
!= DW_TAG_subprogram
&& die
.tag
!= DW_TAG_inlined_subroutine
) {
1906 if (!di_skip_records(reader
, errout
)) return false;
1910 /* enumerate abbrev */
1912 DebugInfoValue v
= {{0}};
1913 /* ptrdiff_t pos = reader->p - reader->p0; */
1914 if (!di_read_record(reader
, &v
, errout
)) break;
1915 /* kprintf("\n%d:%tx: AT:%lx FORM:%lx\n",__LINE__,pos,v.at,v.form); */
1916 /* div_inspect(&v, errout); */
1919 line
.sname
= get_cstr_value(&v
);
1921 case DW_AT_call_file
:
1922 fill_filename((int)v
.as
.uint64
, reader
->debug_line_format
, reader
->debug_line_version
, reader
->debug_line_directories
, reader
->debug_line_files
, &line
, reader
->obj
, errout
);
1924 case DW_AT_call_line
:
1925 line
.line
= (int)v
.as
.uint64
;
1930 ranges_set(&ranges
, &v
, &addr_header
, reader
->current_addr_base
);
1932 case DW_AT_declaration
:
1936 break; /* goto skip_die; */
1937 case DW_AT_abstract_origin
:
1938 read_abstract_origin(reader
, v
.form
, v
.as
.uint64
, &line
, errout
);
1939 break; /* goto skip_die; */
1942 /* ranges_inspect(reader, &ranges, errout); */
1943 /* kprintf("%d:%tx: %x ",__LINE__,diepos,die.tag); */
1944 for (int i
=offset
; i
< num_traces
; i
++) {
1945 uintptr_t addr
= (uintptr_t)traces
[i
];
1946 uintptr_t offset
= addr
- reader
->obj
->base_addr
+ reader
->obj
->vmaddr
;
1947 uintptr_t saddr
= ranges_include(reader
, &ranges
, offset
, &rnglists_header
, errout
);
1948 if (saddr
== UINTPTR_MAX
) return false;
1950 /* kprintf("%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); */
1951 if (lines
[i
].sname
) {
1952 line_info_t
*lp
= malloc(sizeof(line_info_t
));
1953 memcpy(lp
, &lines
[i
], sizeof(line_info_t
));
1955 lp
->dirname
= line
.dirname
;
1956 lp
->filename
= line
.filename
;
1957 lp
->line
= line
.line
;
1960 lines
[i
].path
= reader
->obj
->path
;
1961 lines
[i
].base_addr
= line
.base_addr
;
1962 lines
[i
].sname
= line
.sname
;
1963 lines
[i
].saddr
= saddr
+ reader
->obj
->base_addr
- reader
->obj
->vmaddr
;
1970 // This function parses the following attributes of Line Number Program Header in DWARF 5:
1972 // * directory_entry_format_count
1973 // * directory_entry_format
1974 // * directories_count
1979 // * file_name_entry_format_count
1980 // * file_name_entry_format
1981 // * file_names_count
1984 // It records DW_LNCT_path and DW_LNCT_directory_index at the index "idx".
1986 parse_ver5_debug_line_header(const char *p
, int idx
, uint8_t format
,
1987 obj_info_t
*obj
, const char **out_path
,
1988 uint64_t *out_directory_index
, FILE *errout
)
1991 int entry_format_count
= *(uint8_t *)p
++;
1992 const char *entry_format
= p
;
1994 /* skip the part of entry_format */
1995 for (i
= 0; i
< entry_format_count
* 2; i
++) uleb128(&p
);
1997 int entry_count
= (int)uleb128(&p
);
1999 DebugInfoReader reader
= {0};
2000 debug_info_reader_init(&reader
, obj
);
2001 reader
.format
= format
;
2003 for (j
= 0; j
< entry_count
; j
++) {
2004 const char *format
= entry_format
;
2005 for (i
= 0; i
< entry_format_count
; i
++) {
2006 DebugInfoValue v
= {{0}};
2007 unsigned long dw_lnct
= uleb128(&format
);
2008 unsigned long dw_form
= uleb128(&format
);
2009 if (!debug_info_reader_read_value(&reader
, dw_form
, &v
, errout
)) return 0;
2010 if (dw_lnct
== 1 /* DW_LNCT_path */ && v
.type
== VAL_cstr
&& out_path
)
2011 *out_path
= v
.as
.ptr
+ v
.off
;
2012 if (dw_lnct
== 2 /* DW_LNCT_directory_index */ && v
.type
== VAL_uint
&& out_directory_index
)
2013 *out_directory_index
= v
.as
.uint64
;
2015 if (j
== idx
) return 0;
2022 static unsigned long
2023 uncompress_debug_section(ElfW(Shdr
) *shdr
, char *file
, char **ptr
)
2026 #ifdef SUPPORT_COMPRESSED_DEBUG_LINE
2027 ElfW(Chdr
) *chdr
= (ElfW(Chdr
) *)(file
+ shdr
->sh_offset
);
2028 unsigned long destsize
= chdr
->ch_size
;
2031 if (chdr
->ch_type
!= ELFCOMPRESS_ZLIB
) {
2032 /* unsupported compression type */
2036 *ptr
= malloc(destsize
);
2037 if (!*ptr
) return 0;
2038 ret
= uncompress((Bytef
*)*ptr
, &destsize
,
2039 (const Bytef
*)chdr
+ sizeof(ElfW(Chdr
)),
2040 shdr
->sh_size
- sizeof(ElfW(Chdr
)));
2041 if (ret
!= Z_OK
) goto fail
;
2051 /* read file and fill lines */
2053 fill_lines(int num_traces
, void **traces
, int check_debuglink
,
2054 obj_info_t
**objp
, line_info_t
*lines
, int offset
, FILE *errout
)
2059 ElfW(Shdr
) *shdr
, *shstr_shdr
;
2060 ElfW(Shdr
) *gnu_debuglink_shdr
= NULL
;
2061 ElfW(Shdr
) *note_gnu_build_id
= NULL
;
2065 ElfW(Shdr
) *symtab_shdr
= NULL
, *strtab_shdr
= NULL
;
2066 ElfW(Shdr
) *dynsym_shdr
= NULL
, *dynstr_shdr
= NULL
;
2067 obj_info_t
*obj
= *objp
;
2068 uintptr_t dladdr_fbase
= 0;
2070 fd
= open(binary_filename
, O_RDONLY
);
2074 filesize
= lseek(fd
, 0, SEEK_END
);
2078 kprintf("lseek: %s\n", strerror(e
));
2081 #if SIZEOF_OFF_T > SIZEOF_SIZE_T
2082 if (filesize
> (off_t
)SIZE_MAX
) {
2084 kprintf("Too large file %s\n", binary_filename
);
2088 lseek(fd
, 0, SEEK_SET
);
2089 /* async-signal unsafe */
2090 file
= (char *)mmap(NULL
, (size_t)filesize
, PROT_READ
, MAP_SHARED
, fd
, 0);
2091 if (file
== MAP_FAILED
) {
2094 kprintf("mmap: %s\n", strerror(e
));
2099 ehdr
= (ElfW(Ehdr
) *)file
;
2100 if (memcmp(ehdr
->e_ident
, "\177ELF", 4) != 0) {
2102 * Huh? Maybe filename was overridden by setproctitle() and
2103 * it match non-elf file.
2108 obj
->mapped_size
= (size_t)filesize
;
2110 shdr
= (ElfW(Shdr
) *)(file
+ ehdr
->e_shoff
);
2112 shstr_shdr
= shdr
+ ehdr
->e_shstrndx
;
2113 shstr
= file
+ shstr_shdr
->sh_offset
;
2115 for (i
= 0; i
< ehdr
->e_shnum
; i
++) {
2116 char *section_name
= shstr
+ shdr
[i
].sh_name
;
2117 switch (shdr
[i
].sh_type
) {
2119 if (!strcmp(section_name
, ".strtab")) {
2120 strtab_shdr
= shdr
+ i
;
2122 else if (!strcmp(section_name
, ".dynstr")) {
2123 dynstr_shdr
= shdr
+ i
;
2127 /* if (!strcmp(section_name, ".symtab")) */
2128 symtab_shdr
= shdr
+ i
;
2131 /* if (!strcmp(section_name, ".dynsym")) */
2132 dynsym_shdr
= shdr
+ i
;
2135 if (!strcmp(section_name
, ".note.gnu.build-id")) {
2136 note_gnu_build_id
= shdr
+ i
;
2140 if (!strcmp(section_name
, ".gnu_debuglink")) {
2141 gnu_debuglink_shdr
= shdr
+ i
;
2144 const char *debug_section_names
[] = {
2149 ".debug_str_offsets",
2156 for (j
=0; j
< DWARF_SECTION_COUNT
; j
++) {
2157 struct dwarf_section
*s
= obj_dwarf_section_at(obj
, j
);
2159 if (strcmp(section_name
, debug_section_names
[j
]) != 0)
2162 s
->ptr
= file
+ shdr
[i
].sh_offset
;
2163 s
->size
= shdr
[i
].sh_size
;
2164 s
->flags
= shdr
[i
].sh_flags
;
2165 if (s
->flags
& SHF_COMPRESSED
) {
2166 s
->size
= uncompress_debug_section(&shdr
[i
], file
, &s
->ptr
);
2167 if (!s
->size
) goto fail
;
2177 /* main executable */
2179 if (dynsym_shdr
&& dynstr_shdr
) {
2180 char *strtab
= file
+ dynstr_shdr
->sh_offset
;
2181 ElfW(Sym
) *symtab
= (ElfW(Sym
) *)(file
+ dynsym_shdr
->sh_offset
);
2182 int symtab_count
= (int)(dynsym_shdr
->sh_size
/ sizeof(ElfW(Sym
)));
2183 void *handle
= dlopen(NULL
, RTLD_NOW
|RTLD_LOCAL
);
2185 for (j
= 0; j
< symtab_count
; j
++) {
2186 ElfW(Sym
) *sym
= &symtab
[j
];
2189 if (ELF_ST_TYPE(sym
->st_info
) != STT_FUNC
|| sym
->st_size
== 0) continue;
2190 s
= dlsym(handle
, strtab
+ sym
->st_name
);
2191 if (s
&& dladdr(s
, &info
)) {
2192 obj
->base_addr
= dladdr_fbase
;
2193 dladdr_fbase
= (uintptr_t)info
.dli_fbase
;
2199 if (ehdr
->e_type
== ET_EXEC
) {
2203 /* PIE (position-independent executable) */
2204 obj
->base_addr
= dladdr_fbase
;
2209 if (obj
->debug_info
.ptr
&& obj
->debug_abbrev
.ptr
) {
2210 DebugInfoReader reader
;
2211 debug_info_reader_init(&reader
, obj
);
2213 while (reader
.p
< reader
.pend
) {
2214 /* kprintf("%d:%tx: CU[%d]\n", __LINE__, reader.p - reader.obj->debug_info.ptr, i++); */
2215 if (di_read_cu(&reader
, errout
)) goto use_symtab
;
2216 if (!debug_info_read(&reader
, num_traces
, traces
, lines
, offset
, errout
))
2221 /* This file doesn't have dwarf, use symtab or dynsym */
2224 /* This file doesn't have symtab, use dynsym instead */
2225 symtab_shdr
= dynsym_shdr
;
2226 strtab_shdr
= dynstr_shdr
;
2229 if (symtab_shdr
&& strtab_shdr
) {
2230 char *strtab
= file
+ strtab_shdr
->sh_offset
;
2231 ElfW(Sym
) *symtab
= (ElfW(Sym
) *)(file
+ symtab_shdr
->sh_offset
);
2232 int symtab_count
= (int)(symtab_shdr
->sh_size
/ sizeof(ElfW(Sym
)));
2233 for (j
= 0; j
< symtab_count
; j
++) {
2234 ElfW(Sym
) *sym
= &symtab
[j
];
2235 uintptr_t saddr
= (uintptr_t)sym
->st_value
+ obj
->base_addr
;
2236 if (ELF_ST_TYPE(sym
->st_info
) != STT_FUNC
) continue;
2237 for (i
= offset
; i
< num_traces
; i
++) {
2238 uintptr_t d
= (uintptr_t)traces
[i
] - saddr
;
2239 if (lines
[i
].line
> 0 || d
> (uintptr_t)sym
->st_size
)
2241 /* fill symbol name and addr from .symtab */
2242 if (!lines
[i
].sname
) lines
[i
].sname
= strtab
+ sym
->st_name
;
2243 lines
[i
].saddr
= saddr
;
2244 lines
[i
].path
= obj
->path
;
2245 lines
[i
].base_addr
= obj
->base_addr
;
2251 if (!obj
->debug_line
.ptr
) {
2252 /* This file doesn't have .debug_line section,
2253 let's check .gnu_debuglink section instead. */
2254 if (gnu_debuglink_shdr
&& check_debuglink
) {
2255 follow_debuglink(file
+ gnu_debuglink_shdr
->sh_offset
,
2257 objp
, lines
, offset
, errout
);
2259 if (note_gnu_build_id
&& check_debuglink
) {
2260 ElfW(Nhdr
) *nhdr
= (ElfW(Nhdr
)*) (file
+ note_gnu_build_id
->sh_offset
);
2261 const char *build_id
= (char *)(nhdr
+ 1) + nhdr
->n_namesz
;
2262 follow_debuglink_build_id(build_id
, nhdr
->n_descsz
,
2264 objp
, lines
, offset
, errout
);
2269 if (parse_debug_line(num_traces
, traces
,
2270 obj
->debug_line
.ptr
,
2271 obj
->debug_line
.size
,
2272 obj
, lines
, offset
, errout
) == -1)
2276 return dladdr_fbase
;
2278 return (uintptr_t)-1;
2281 /* read file and fill lines */
2283 fill_lines(int num_traces
, void **traces
, int check_debuglink
,
2284 obj_info_t
**objp
, line_info_t
*lines
, int offset
, FILE *errout
)
2287 # define LP(x) x##_64
2293 char *file
, *p
= NULL
;
2294 obj_info_t
*obj
= *objp
;
2295 struct LP(mach_header
) *header
;
2296 uintptr_t dladdr_fbase
= 0;
2299 char *s
= binary_filename
;
2300 char *base
= strrchr(binary_filename
, '/')+1;
2301 size_t max
= PATH_MAX
;
2302 size_t size
= strlen(binary_filename
);
2303 size_t basesize
= size
- (base
- binary_filename
);
2307 size
= strlcpy(s
, ".dSYM/Contents/Resources/DWARF/", max
);
2308 if (size
== 0) goto fail
;
2311 if (max
<= basesize
) goto fail
;
2312 memcpy(s
, base
, basesize
);
2315 fd
= open(binary_filename
, O_RDONLY
);
2317 *p
= 0; /* binary_filename becomes original file name */
2318 fd
= open(binary_filename
, O_RDONLY
);
2325 filesize
= lseek(fd
, 0, SEEK_END
);
2329 kprintf("lseek: %s\n", strerror(e
));
2332 #if SIZEOF_OFF_T > SIZEOF_SIZE_T
2333 if (filesize
> (off_t
)SIZE_MAX
) {
2335 kprintf("Too large file %s\n", binary_filename
);
2339 lseek(fd
, 0, SEEK_SET
);
2340 /* async-signal unsafe */
2341 file
= (char *)mmap(NULL
, (size_t)filesize
, PROT_READ
, MAP_SHARED
, fd
, 0);
2342 if (file
== MAP_FAILED
) {
2345 kprintf("mmap: %s\n", strerror(e
));
2351 obj
->mapped_size
= (size_t)filesize
;
2353 header
= (struct LP(mach_header
) *)file
;
2354 if (header
->magic
== LP(MH_MAGIC
)) {
2355 /* non universal binary */
2358 else if (header
->magic
== FAT_CIGAM
) {
2359 struct LP(mach_header
) *mhp
= _NSGetMachExecuteHeader();
2360 struct fat_header
*fat
= (struct fat_header
*)file
;
2361 char *q
= file
+ sizeof(*fat
);
2362 uint32_t nfat_arch
= __builtin_bswap32(fat
->nfat_arch
);
2363 /* kprintf("%d: fat:%s %d\n",__LINE__, binary_filename,nfat_arch); */
2364 for (uint32_t i
= 0; i
< nfat_arch
; i
++) {
2365 struct fat_arch
*arch
= (struct fat_arch
*)q
;
2366 cpu_type_t cputype
= __builtin_bswap32(arch
->cputype
);
2367 cpu_subtype_t cpusubtype
= __builtin_bswap32(arch
->cpusubtype
);
2368 uint32_t offset
= __builtin_bswap32(arch
->offset
);
2369 /* kprintf("%d: fat %d %x/%x %x/%x\n",__LINE__, i, mhp->cputype,mhp->cpusubtype, cputype,cpusubtype); */
2370 if (mhp
->cputype
== cputype
&&
2371 (cpu_subtype_t
)(mhp
->cpusubtype
& ~CPU_SUBTYPE_MASK
) == cpusubtype
) {
2374 header
= (struct LP(mach_header
) *)p
;
2375 if (header
->magic
== LP(MH_MAGIC
)) {
2376 goto found_mach_header
;
2382 kprintf("'%s' is not a Mach-O universal binary file!\n",binary_filename
);
2388 # define bitsize "64"
2390 # define bitsize "32"
2392 kprintf("'%s' is not a " bitsize
2393 "-bit Mach-O file!\n",binary_filename
);
2399 p
+= sizeof(*header
);
2401 for (uint32_t i
= 0; i
< (uint32_t)header
->ncmds
; i
++) {
2402 struct load_command
*lcmd
= (struct load_command
*)p
;
2403 switch (lcmd
->cmd
) {
2404 case LP(LC_SEGMENT
):
2406 static const char *debug_section_names
[] = {
2411 "__debug_str_offsets",
2417 struct LP(segment_command
) *scmd
= (struct LP(segment_command
) *)lcmd
;
2418 if (strcmp(scmd
->segname
, "__TEXT") == 0) {
2419 obj
->vmaddr
= scmd
->vmaddr
;
2421 else if (strcmp(scmd
->segname
, "__DWARF") == 0) {
2422 p
+= sizeof(struct LP(segment_command
));
2423 for (uint64_t i
= 0; i
< scmd
->nsects
; i
++) {
2424 struct LP(section
) *sect
= (struct LP(section
) *)p
;
2425 p
+= sizeof(struct LP(section
));
2426 for (int j
=0; j
< DWARF_SECTION_COUNT
; j
++) {
2427 struct dwarf_section
*s
= obj_dwarf_section_at(obj
, j
);
2429 if (strcmp(sect
->sectname
, debug_section_names
[j
]) != 0)
2432 s
->ptr
= file
+ sect
->offset
;
2433 s
->size
= sect
->size
;
2434 s
->flags
= sect
->flags
;
2435 if (s
->flags
& SHF_COMPRESSED
) {
2447 struct symtab_command
*cmd
= (struct symtab_command
*)lcmd
;
2448 struct LP(nlist
) *nl
= (struct LP(nlist
) *)(file
+ cmd
->symoff
);
2449 char *strtab
= file
+ cmd
->stroff
, *sname
= 0;
2451 uintptr_t saddr
= 0;
2452 /* kprintf("[%2d]: %x/symtab %p\n", i, cmd->cmd, (void *)p); */
2453 for (j
= 0; j
< cmd
->nsyms
; j
++) {
2454 uintptr_t symsize
, d
;
2455 struct LP(nlist
) *e
= &nl
[j
];
2456 /* 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); */
2457 if (e
->n_type
!= N_FUN
) continue;
2459 saddr
= (uintptr_t)e
->n_value
+ obj
->base_addr
- obj
->vmaddr
;
2460 sname
= strtab
+ e
->n_un
.n_strx
;
2461 /* 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); */
2464 for (int k
= offset
; k
< num_traces
; k
++) {
2465 d
= (uintptr_t)traces
[k
] - saddr
;
2466 symsize
= e
->n_value
;
2467 /* kprintf("%lx %lx %lx\n",saddr,symsize,traces[k]); */
2468 if (lines
[k
].line
> 0 || d
> (uintptr_t)symsize
)
2470 /* fill symbol name and addr from .symtab */
2471 if (!lines
[k
].sname
) lines
[k
].sname
= sname
;
2472 lines
[k
].saddr
= saddr
;
2473 lines
[k
].path
= obj
->path
;
2474 lines
[k
].base_addr
= obj
->base_addr
;
2482 if (obj
->debug_info
.ptr
&& obj
->debug_abbrev
.ptr
) {
2483 DebugInfoReader reader
;
2484 debug_info_reader_init(&reader
, obj
);
2485 while (reader
.p
< reader
.pend
) {
2486 if (di_read_cu(&reader
, errout
)) goto fail
;
2487 if (!debug_info_read(&reader
, num_traces
, traces
, lines
, offset
, errout
))
2492 if (parse_debug_line(num_traces
, traces
,
2493 obj
->debug_line
.ptr
,
2494 obj
->debug_line
.size
,
2495 obj
, lines
, offset
, errout
) == -1)
2498 return dladdr_fbase
;
2500 return (uintptr_t)-1;
2504 #define HAVE_MAIN_EXE_PATH
2505 #if defined(__FreeBSD__) || defined(__DragonFly__)
2506 # include <sys/sysctl.h>
2508 /* ssize_t main_exe_path(FILE *errout)
2510 * store the path of the main executable to `binary_filename`,
2511 * and returns strlen(binary_filename).
2512 * it is NUL terminated.
2514 #if defined(__linux__) || defined(__NetBSD__)
2516 main_exe_path(FILE *errout
)
2518 # if defined(__linux__)
2519 # define PROC_SELF_EXE "/proc/self/exe"
2520 # elif defined(__NetBSD__)
2521 # define PROC_SELF_EXE "/proc/curproc/exe"
2523 ssize_t len
= readlink(PROC_SELF_EXE
, binary_filename
, PATH_MAX
);
2524 if (len
< 0) return 0;
2525 binary_filename
[len
] = 0;
2528 #elif defined(__FreeBSD__) || defined(__DragonFly__)
2530 main_exe_path(FILE *errout
)
2532 int mib
[4] = {CTL_KERN
, KERN_PROC
, KERN_PROC_PATHNAME
, -1};
2533 size_t len
= PATH_MAX
;
2534 int err
= sysctl(mib
, 4, binary_filename
, &len
, NULL
, 0);
2536 kprintf("Can't get the path of ruby");
2539 len
--; /* sysctl sets strlen+1 */
2542 #elif defined(HAVE_LIBPROC_H)
2544 main_exe_path(FILE *errout
)
2546 int len
= proc_pidpath(getpid(), binary_filename
, PATH_MAX
);
2547 if (len
== 0) return 0;
2548 binary_filename
[len
] = 0;
2552 #undef HAVE_MAIN_EXE_PATH
2556 print_line0(line_info_t
*line
, void *address
, FILE *errout
)
2558 uintptr_t addr
= (uintptr_t)address
;
2559 uintptr_t d
= addr
- line
->saddr
;
2562 if (line
->dirname
&& line
->dirname
[0]) {
2563 kprintf("%s(%s) %s/%s:%d\n", line
->path
, line
->sname
, line
->dirname
, line
->filename
, line
->line
);
2566 kprintf("%s(%s) %s:%d\n", line
->path
, line
->sname
, line
->filename
, line
->line
);
2569 else if (!line
->path
) {
2570 kprintf("[0x%"PRIxPTR
"]\n", addr
);
2572 else if (!line
->sname
) {
2573 kprintf("%s(0x%"PRIxPTR
") [0x%"PRIxPTR
"]\n", line
->path
, addr
-line
->base_addr
, addr
);
2575 else if (!line
->saddr
) {
2576 kprintf("%s(%s) [0x%"PRIxPTR
"]\n", line
->path
, line
->sname
, addr
);
2578 else if (line
->line
<= 0) {
2579 kprintf("%s(%s+0x%"PRIxPTR
") [0x%"PRIxPTR
"]\n", line
->path
, line
->sname
,
2582 else if (!line
->filename
) {
2583 kprintf("%s(%s+0x%"PRIxPTR
") [0x%"PRIxPTR
"] ???:%d\n", line
->path
, line
->sname
,
2584 d
, addr
, line
->line
);
2586 else if (line
->dirname
&& line
->dirname
[0]) {
2587 kprintf("%s(%s+0x%"PRIxPTR
") [0x%"PRIxPTR
"] %s/%s:%d\n", line
->path
, line
->sname
,
2588 d
, addr
, line
->dirname
, line
->filename
, line
->line
);
2591 kprintf("%s(%s+0x%"PRIxPTR
") [0x%"PRIxPTR
"] %s:%d\n", line
->path
, line
->sname
,
2592 d
, addr
, line
->filename
, line
->line
);
2597 print_line(line_info_t
*line
, void *address
, FILE *errout
)
2599 print_line0(line
, address
, errout
);
2601 print_line(line
->next
, NULL
, errout
);
2606 rb_dump_backtrace_with_lines(int num_traces
, void **traces
, FILE *errout
)
2609 /* async-signal unsafe */
2610 line_info_t
*lines
= (line_info_t
*)calloc(num_traces
, sizeof(line_info_t
));
2611 obj_info_t
*obj
= NULL
;
2612 /* 2 is NULL + main executable */
2613 void **dladdr_fbases
= (void **)calloc(num_traces
+2, sizeof(void *));
2615 #ifdef HAVE_MAIN_EXE_PATH
2616 char *main_path
= NULL
; /* used on printing backtrace */
2618 if ((len
= main_exe_path(errout
)) > 0) {
2619 main_path
= (char *)alloca(len
+ 1);
2622 memcpy(main_path
, binary_filename
, len
+1);
2624 obj
->path
= main_path
;
2625 addr
= fill_lines(num_traces
, traces
, 1, &obj
, lines
, -1, errout
);
2626 if (addr
!= (uintptr_t)-1) {
2627 dladdr_fbases
[0] = (void *)addr
;
2633 /* fill source lines by reading dwarf */
2634 for (i
= 0; i
< num_traces
; i
++) {
2636 if (lines
[i
].line
) continue;
2637 if (dladdr(traces
[i
], &info
)) {
2641 /* skip symbols which is in already checked objects */
2642 /* if the binary is strip-ed, this may effect */
2643 for (p
=dladdr_fbases
; *p
; p
++) {
2644 if (*p
== info
.dli_fbase
) {
2645 if (info
.dli_fname
) lines
[i
].path
= info
.dli_fname
;
2646 if (info
.dli_sname
) lines
[i
].sname
= info
.dli_sname
;
2650 *p
= info
.dli_fbase
;
2653 obj
->base_addr
= (uintptr_t)info
.dli_fbase
;
2654 path
= info
.dli_fname
;
2656 if (path
) lines
[i
].path
= path
;
2657 if (info
.dli_sname
) {
2658 lines
[i
].sname
= info
.dli_sname
;
2659 lines
[i
].saddr
= (uintptr_t)info
.dli_saddr
;
2661 strlcpy(binary_filename
, path
, PATH_MAX
);
2662 if (fill_lines(num_traces
, traces
, 1, &obj
, lines
, i
, errout
) == (uintptr_t)-1)
2670 for (i
= 0; i
< num_traces
; i
++) {
2671 print_line(&lines
[i
], traces
[i
], errout
);
2673 /* FreeBSD's backtrace may show _start and so on */
2674 if (lines
[i
].sname
&& strcmp("main", lines
[i
].sname
) == 0)
2680 obj_info_t
*o
= obj
;
2681 for (i
=0; i
< DWARF_SECTION_COUNT
; i
++) {
2682 struct dwarf_section
*s
= obj_dwarf_section_at(obj
, i
);
2683 if (s
->flags
& SHF_COMPRESSED
) {
2687 if (obj
->mapped_size
) {
2688 munmap(obj
->mapped
, obj
->mapped_size
);
2693 for (i
= 0; i
< num_traces
; i
++) {
2694 line_info_t
*line
= lines
[i
].next
;
2696 line_info_t
*l
= line
;
2702 free(dladdr_fbases
);
2707 #else /* defined(USE_ELF) */
2708 #error not supported