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"
22#include "ruby/missing.h"
34#if defined(USE_ELF) || defined(HAVE_MACH_O_LOADER_H)
50# define alloca __builtin_alloca
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>
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
115# if defined(ELFCOMPRESS_ZLIB) && defined(HAVE_LIBZ)
118# define SUPPORT_COMPRESSED_DEBUG_LINE
121# define SHF_COMPRESSED 0
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
138#define DW_LNS_set_epilogue_begin 0x0b
139#define DW_LNS_set_isa 0x0c
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
147#define kprintf(...) fprintf(errout, "" __VA_ARGS__)
149typedef struct line_info {
151 const char *filename;
159 struct line_info *next;
162struct dwarf_section {
168typedef struct obj_info {
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
189static struct dwarf_section *
190obj_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) {
209struct debug_section_definition {
211 struct dwarf_section *dwarf;
215static char binary_filename[PATH_MAX + 1];
218uleb128(
const char **p)
223 unsigned char b = (
unsigned char)*(*p)++;
225 r += (
unsigned long)b << s;
228 r += (b & 0x7f) << s;
235sleb128(
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;
257get_nth_dirname(
unsigned long dir,
const char *p,
FILE *errout)
266 kprintf(
"Unexpected directory number %lu in %s\n",
267 dir, binary_filename);
274static 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);
280fill_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++) {
300 kprintf(
"Unexpected file number %d in %s at %tx\n",
301 file, binary_filename, filenames - obj->mapped);
313 line->filename = filename;
314 line->dirname = get_nth_dirname(dir, include_directories, errout);
321fill_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];
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;
338struct LineNumberProgramHeader {
339 uint64_t unit_length;
342 uint64_t header_length;
343 uint8_t minimum_instruction_length;
344 uint8_t maximum_operations_per_instruction;
345 uint8_t default_is_stmt;
350 const char *include_directories;
351 const char *filenames;
352 const char *cu_start;
357parse_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) {
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) {
390 if (*p != 1)
return -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++;
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;
410 if (p >= header->cu_end)
return -1;
414 p = memchr(p,
'\0', header->cu_end - p);
420 header->filenames = p;
423 *pp = header->cu_start;
429parse_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;
447 if (parse_debug_line_header(obj, &p, &header, errout))
449 is_stmt = header.default_is_stmt;
453 fill_line(num_traces, traces, addr, file, line, \
456 header.include_directories, \
458 obj, lines, offset, errout); \
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:
484 case DW_LNS_negate_stmt:
487 case DW_LNS_set_basic_block:
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:
503 case DW_LNS_set_epilogue_begin:
513 case DW_LNE_end_sequence:
520 is_stmt = header.default_is_stmt;
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:
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;
545 addr += operation_advance * header.minimum_instruction_length;
546 line += header.line_base + (adjusted_opcode % header.line_range);
551 *debug_line = (
char *)p;
556parse_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",
574fill_lines(
int num_traces,
void **traces,
int check_debuglink,
575 obj_info_t **objp, line_info_t *lines,
int offset,
FILE *errout);
578append_obj(obj_info_t **objp)
580 obj_info_t *newobj = calloc(1,
sizeof(obj_info_t));
581 if (*objp) (*objp)->next = newobj;
602follow_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);
634follow_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,
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
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,
867 DW_FORM_GNU_ref_alt = 0x1f20,
868 DW_FORM_GNU_strp_alt = 0x1f21
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;
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))
945get_uint16(
const uint8_t *p)
947 return (uint16_t)MERGE_2INTS(p[0],p[1],8);
951get_uint32(
const uint8_t *p)
953 return (uint32_t)MERGE_2INTS(get_uint16(p),get_uint16(p+2),16);
957get_uint64(
const uint8_t *p)
959 return MERGE_2INTS(get_uint32(p),get_uint32(p+4),32);
963read_uint8(
const char **ptr)
965 const char *p = *ptr;
971read_uint16(
const char **ptr)
973 const char *p = *ptr;
975 return get_uint16((
const uint8_t *)p);
979read_uint24(
const char **ptr)
981 const char *p = *ptr;
983 return ((uint8_t)*p << 16) | get_uint16((
const uint8_t *)p+1);
987read_uint32(
const char **ptr)
989 const char *p = *ptr;
991 return get_uint32((
const uint8_t *)p);
995read_uint64(
const char **ptr)
997 const unsigned char *p = (
const unsigned char *)*ptr;
998 *ptr = (
char *)(p + 8);
999 return get_uint64(p);
1003read_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);
1015read_uint(DebugInfoReader *reader)
1017 if (reader->format == 4) {
1018 return read_uint32(&reader->p);
1020 return read_uint64(&reader->p);
1025read_uleb128(DebugInfoReader *reader)
1027 return uleb128(&reader->p);
1031read_sleb128(DebugInfoReader *reader)
1033 return sleb128(&reader->p);
1037debug_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;
1051di_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:
1068di_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;
1081 di_skip_die_attributes(&p);
1086di_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;
1105set_addr_idx_value(DebugInfoValue *v, uint64_t n)
1112set_uint_value(DebugInfoValue *v, uint64_t n)
1119set_int_value(DebugInfoValue *v, int64_t n)
1126set_cstr_value(DebugInfoValue *v,
const char *s)
1134set_cstrp_value(DebugInfoValue *v,
const char *s, uint64_t
off)
1142set_data_value(DebugInfoValue *v,
const char *s)
1149get_cstr_value(DebugInfoValue *v)
1152 return v->as.ptr + v->off;
1159resolve_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;
1173debug_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); \
1193debug_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) {
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:
1274 set_uint_value(v, uleb128(&reader->p));
1276 case DW_FORM_sec_offset:
1277 set_uint_value(v, read_uint(reader));
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));
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));
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);
1376di_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];
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);
1394 di_skip_die_attributes(&p);
1401hexdump0(
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)
1425div_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);
1446di_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);
1458 die->has_children = *reader->q++;
1459 if (die->has_children) {
1465static DebugInfoValue *
1466di_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;
1478di_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;
1489typedef struct addr_header {
1491 uint64_t unit_length;
1493 uint8_t address_size;
1498addr_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);
1517 header->address_size = *p++;
1518 if (header->address_size != 4 && header->address_size != 8) {
1519 kprintf(
"unknown address_size:%d", header->address_size);
1527read_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];
1536typedef struct rnglists_header {
1537 uint64_t unit_length;
1539 uint8_t address_size;
1540 uint32_t offset_entry_count;
1544rnglists_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);
1561 header->address_size = *p++;
1562 if (header->address_size != 4 && header->address_size != 8) {
1563 kprintf(
"unknown address_size:%d", header->address_size);
1567 header->offset_entry_count = *(uint32_t *)p;
1581ranges_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;
1612read_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);
1624ranges_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) {
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) {
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:
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) {
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;
1719ranges_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);
1749di_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 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}};
1803 DebugInfoValue v = {{0}};
1804 if (!di_read_record(reader, &v, errout))
break;
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;
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);
1841read_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:
1858 case DW_FORM_ref_sig8:
1860 case DW_FORM_ref_sup4:
1861 case DW_FORM_ref_sup8:
1866 if (!di_read_die(reader, &die, errout))
goto finish;
1870 DebugInfoValue v = {{0}};
1871 if (!di_read_record(reader, &v, errout))
break;
1874 line->sname = get_cstr_value(&v);
1882 reader->level = level;
1886debug_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;
1904 if (die.tag != DW_TAG_subprogram && die.tag != DW_TAG_inlined_subroutine) {
1906 if (!di_skip_records(reader, errout))
return false;
1912 DebugInfoValue v = {{0}};
1914 if (!di_read_record(reader, &v, errout))
break;
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:
1937 case DW_AT_abstract_origin:
1938 read_abstract_origin(reader, v.form, v.as.uint64, &line, errout);
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;
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;
1986parse_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;
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 && v.type == VAL_cstr && out_path)
2011 *out_path = v.as.ptr + v.off;
2012 if (dw_lnct == 2 && v.type == VAL_uint && out_directory_index)
2013 *out_directory_index = v.as.uint64;
2015 if (j == idx)
return 0;
2023uncompress_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) {
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;
2053fill_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);
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) {
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;
2128 symtab_shdr = shdr + i;
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;
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) {
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) {
2215 if (di_read_cu(&reader, errout))
goto use_symtab;
2216 if (!debug_info_read(&reader, num_traces, traces, lines, offset, errout))
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)
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) {
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;
2283fill_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);
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);
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)) {
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);
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);
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
2437 && strncmp(sect->sectname, debug_section_names[j], 16) != 0
2442 s->ptr = file + sect->offset;
2443 s->size = sect->size;
2444 s->flags = sect->flags;
2445 if (s->flags & SHF_COMPRESSED) {
2457 struct symtab_command *cmd = (
struct symtab_command *)lcmd;
2458 struct LP(nlist) *nl = (
struct LP(nlist) *)(file + cmd->symoff);
2459 char *strtab = file + cmd->stroff, *sname = 0;
2461 uintptr_t saddr = 0;
2463 for (j = 0; j < cmd->nsyms; j++) {
2464 uintptr_t symsize, d;
2465 struct LP(nlist) *e = &nl[j];
2467 if (e->n_type != N_FUN)
continue;
2469 saddr = (uintptr_t)e->n_value + obj->base_addr - obj->vmaddr;
2470 sname = strtab + e->n_un.n_strx;
2474 for (
int k = offset; k < num_traces; k++) {
2475 d = (uintptr_t)traces[k] - saddr;
2476 symsize = e->n_value;
2478 if (lines[k].line > 0 || d > (uintptr_t)symsize)
2481 if (!lines[k].sname) lines[k].sname = sname;
2482 lines[k].saddr = saddr;
2483 lines[k].path = obj->path;
2484 lines[k].base_addr = obj->base_addr;
2492 if (obj->debug_info.ptr && obj->debug_abbrev.ptr) {
2493 DebugInfoReader reader;
2494 debug_info_reader_init(&reader, obj);
2495 while (reader.p < reader.pend) {
2496 if (di_read_cu(&reader, errout))
goto fail;
2497 if (!debug_info_read(&reader, num_traces, traces, lines, offset, errout))
2502 if (parse_debug_line(num_traces, traces,
2503 obj->debug_line.ptr,
2504 obj->debug_line.size,
2505 obj, lines, offset, errout) == -1)
2508 return dladdr_fbase;
2510 return (uintptr_t)-1;
2514#define HAVE_MAIN_EXE_PATH
2515#if defined(__FreeBSD__) || defined(__DragonFly__)
2516# include <sys/sysctl.h>
2524#if defined(__linux__) || defined(__NetBSD__)
2526main_exe_path(
FILE *errout)
2528# if defined(__linux__)
2529# define PROC_SELF_EXE "/proc/self/exe"
2530# elif defined(__NetBSD__)
2531# define PROC_SELF_EXE "/proc/curproc/exe"
2533 ssize_t
len = readlink(PROC_SELF_EXE, binary_filename, PATH_MAX);
2534 if (
len < 0)
return 0;
2535 binary_filename[
len] = 0;
2538#elif defined(__FreeBSD__) || defined(__DragonFly__)
2540main_exe_path(
FILE *errout)
2542 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
2543 size_t len = PATH_MAX;
2544 int err = sysctl(mib, 4, binary_filename, &
len, NULL, 0);
2546 kprintf(
"Can't get the path of ruby");
2552#elif defined(HAVE_LIBPROC_H)
2554main_exe_path(
FILE *errout)
2556 int len = proc_pidpath(getpid(), binary_filename, PATH_MAX);
2557 if (
len == 0)
return 0;
2558 binary_filename[
len] = 0;
2562#undef HAVE_MAIN_EXE_PATH
2566print_line0(line_info_t *line,
void *address,
FILE *errout)
2568 uintptr_t addr = (uintptr_t)address;
2569 uintptr_t d = addr - line->saddr;
2572 if (line->dirname && line->dirname[0]) {
2573 kprintf(
"%s(%s) %s/%s:%d\n", line->path, line->sname, line->dirname, line->filename, line->line);
2576 kprintf(
"%s(%s) %s:%d\n", line->path, line->sname, line->filename, line->line);
2579 else if (!line->path) {
2580 kprintf(
"[0x%"PRIxPTR
"]\n", addr);
2582 else if (!line->sname) {
2583 kprintf(
"%s(0x%"PRIxPTR
") [0x%"PRIxPTR
"]\n", line->path, addr-line->base_addr, addr);
2585 else if (!line->saddr) {
2586 kprintf(
"%s(%s) [0x%"PRIxPTR
"]\n", line->path, line->sname, addr);
2588 else if (line->line <= 0) {
2589 kprintf(
"%s(%s+0x%"PRIxPTR
") [0x%"PRIxPTR
"]\n", line->path, line->sname,
2592 else if (!line->filename) {
2593 kprintf(
"%s(%s+0x%"PRIxPTR
") [0x%"PRIxPTR
"] ???:%d\n", line->path, line->sname,
2594 d, addr, line->line);
2596 else if (line->dirname && line->dirname[0]) {
2597 kprintf(
"%s(%s+0x%"PRIxPTR
") [0x%"PRIxPTR
"] %s/%s:%d\n", line->path, line->sname,
2598 d, addr, line->dirname, line->filename, line->line);
2601 kprintf(
"%s(%s+0x%"PRIxPTR
") [0x%"PRIxPTR
"] %s:%d\n", line->path, line->sname,
2602 d, addr, line->filename, line->line);
2607print_line(line_info_t *line,
void *address,
FILE *errout)
2609 print_line0(line, address, errout);
2611 print_line(line->next, NULL, errout);
2616rb_dump_backtrace_with_lines(
int num_traces,
void **traces,
FILE *errout)
2620 line_info_t *lines = (line_info_t *)calloc(num_traces,
sizeof(line_info_t));
2621 obj_info_t *obj = NULL;
2623 void **dladdr_fbases = (
void **)calloc(num_traces+2,
sizeof(
void *));
2625#ifdef HAVE_MAIN_EXE_PATH
2626 char *main_path = NULL;
2628 if ((
len = main_exe_path(errout)) > 0) {
2629 main_path = (
char *)alloca(
len + 1);
2632 memcpy(main_path, binary_filename,
len+1);
2634 obj->path = main_path;
2635 addr = fill_lines(num_traces, traces, 1, &obj, lines, 0, errout);
2636 if (addr != (uintptr_t)-1) {
2637 dladdr_fbases[0] = (
void *)addr;
2644 for (i = 0; i < num_traces; i++) {
2646 if (lines[i].line)
continue;
2647 if (dladdr(traces[i], &info)) {
2653 for (p=dladdr_fbases; *p; p++) {
2654 if (*p == info.dli_fbase) {
2655 if (info.dli_fname) lines[i].path = info.dli_fname;
2656 if (info.dli_sname) lines[i].sname = info.dli_sname;
2660 *p = info.dli_fbase;
2663 obj->base_addr = (uintptr_t)info.dli_fbase;
2664 path = info.dli_fname;
2666 if (path) lines[i].path = path;
2667 if (info.dli_sname) {
2668 lines[i].sname = info.dli_sname;
2669 lines[i].saddr = (uintptr_t)info.dli_saddr;
2671 strlcpy(binary_filename, path, PATH_MAX);
2672 if (fill_lines(num_traces, traces, 1, &obj, lines, i, errout) == (uintptr_t)-1)
2680 for (i = 0; i < num_traces; i++) {
2681 print_line(&lines[i], traces[i], errout);
2684 if (lines[i].sname && strcmp(
"main", lines[i].sname) == 0)
2690 obj_info_t *o = obj;
2691 for (i=0; i < DWARF_SECTION_COUNT; i++) {
2692 struct dwarf_section *s = obj_dwarf_section_at(obj, i);
2693 if (s->flags & SHF_COMPRESSED) {
2697 if (obj->mapped_size) {
2698 munmap(obj->mapped, obj->mapped_size);
2703 for (i = 0; i < num_traces; i++) {
2704 line_info_t *line = lines[i].next;
2706 line_info_t *l = line;
2712 free(dladdr_fbases);
#define UNREACHABLE_RETURN
Old name of RBIMPL_UNREACHABLE_RETURN.
int off
Offset inside of ptr.
int len
Length of the buffer.
VALUE type(ANYARGS)
ANYARGS-ed function type.
#define errno
Ractor-aware version of errno.