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++) {
301 kprintf(
"Unexpected file number %d in %s at %tx\n",
302 file, binary_filename, filenames - obj->mapped);
315 line->filename = filename;
316 line->dirname = get_nth_dirname(dir, include_directories, errout);
323fill_line(
int num_traces,
void **traces, uintptr_t addr,
int file,
int line,
324 uint8_t format, uint16_t version,
const char *include_directories,
const char *filenames,
325 obj_info_t *obj, line_info_t *lines,
int offset,
FILE *errout)
328 addr += obj->base_addr - obj->vmaddr;
329 for (i = offset; i < num_traces; i++) {
330 uintptr_t a = (uintptr_t)traces[i];
333 if (addr < a && a < addr + 100) {
334 fill_filename(file, format, version, include_directories, filenames, &lines[i], obj, errout);
335 lines[i].line = line;
340struct LineNumberProgramHeader {
341 uint64_t unit_length;
344 uint64_t header_length;
345 uint8_t minimum_instruction_length;
346 uint8_t maximum_operations_per_instruction;
347 uint8_t default_is_stmt;
352 const char *include_directories;
353 const char *filenames;
354 const char *cu_start;
359parse_debug_line_header(obj_info_t *obj,
const char **pp,
struct LineNumberProgramHeader *header,
FILE *errout)
362 header->unit_length = *(uint32_t *)p;
363 p +=
sizeof(uint32_t);
366 if (header->unit_length == 0xffffffff) {
367 header->unit_length = *(uint64_t *)p;
368 p +=
sizeof(uint64_t);
372 header->cu_end = p + header->unit_length;
374 header->version = *(uint16_t *)p;
375 p +=
sizeof(uint16_t);
376 if (header->version > 5)
return -1;
378 if (header->version >= 5) {
384 header->header_length = header->format == 4 ? *(uint32_t *)p : *(uint64_t *)p;
386 header->cu_start = p + header->header_length;
388 header->minimum_instruction_length = *(uint8_t *)p++;
390 if (header->version >= 4) {
392 if (*p != 1)
return -1;
396 header->default_is_stmt = *(uint8_t *)p++;
397 header->line_base = *(int8_t *)p++;
398 header->line_range = *(uint8_t *)p++;
399 header->opcode_base = *(uint8_t *)p++;
401 p += header->opcode_base - 1;
403 if (header->version >= 5) {
404 header->include_directories = p;
405 p = parse_ver5_debug_line_header(p, -1, header->format, obj, NULL, NULL, errout);
406 header->filenames = p;
409 header->include_directories = p;
412 if (p >= header->cu_end)
return -1;
416 p = memchr(p,
'\0', header->cu_end - p);
422 header->filenames = p;
425 *pp = header->cu_start;
431parse_debug_line_cu(
int num_traces,
void **traces,
const char **debug_line,
432 obj_info_t *obj, line_info_t *lines,
int offset,
FILE *errout)
434 const char *p = (
const char *)*debug_line;
435 struct LineNumberProgramHeader header;
438 unsigned long addr = 0;
439 unsigned int file = 1;
440 unsigned int line = 1;
449 if (parse_debug_line_header(obj, &p, &header, errout))
451 is_stmt = header.default_is_stmt;
455 fill_line(num_traces, traces, addr, file, line, \
458 header.include_directories, \
460 obj, lines, offset, errout); \
464 while (p < header.cu_end) {
466 unsigned char op = *p++;
471 case DW_LNS_advance_pc:
472 a = uleb128(&p) * header.minimum_instruction_length;
475 case DW_LNS_advance_line: {
476 long a = sleb128(&p);
480 case DW_LNS_set_file:
481 file = (
unsigned int)uleb128(&p);
483 case DW_LNS_set_column:
486 case DW_LNS_negate_stmt:
489 case DW_LNS_set_basic_block:
492 case DW_LNS_const_add_pc:
493 a = ((255UL - header.opcode_base) / header.line_range) *
494 header.minimum_instruction_length;
497 case DW_LNS_fixed_advance_pc:
499 p +=
sizeof(uint16_t);
502 case DW_LNS_set_prologue_end:
505 case DW_LNS_set_epilogue_begin:
515 case DW_LNE_end_sequence:
522 is_stmt = header.default_is_stmt;
526 case DW_LNE_set_address:
527 addr = *(
unsigned long *)p;
528 p +=
sizeof(
unsigned long);
530 case DW_LNE_define_file:
531 kprintf(
"Unsupported operation in %s\n",
534 case DW_LNE_set_discriminator:
539 kprintf(
"Unknown extended opcode: %d in %s\n",
540 op, binary_filename);
544 uint8_t adjusted_opcode = op - header.opcode_base;
545 uint8_t operation_advance = adjusted_opcode / header.line_range;
547 addr += operation_advance * header.minimum_instruction_length;
548 line += header.line_base + (adjusted_opcode % header.line_range);
553 *debug_line = (
char *)p;
558parse_debug_line(
int num_traces,
void **traces,
559 const char *debug_line,
unsigned long size,
560 obj_info_t *obj, line_info_t *lines,
int offset,
FILE *errout)
562 const char *debug_line_end = debug_line + size;
563 while (debug_line < debug_line_end) {
564 if (parse_debug_line_cu(num_traces, traces, &debug_line, obj, lines, offset, errout))
567 if (debug_line != debug_line_end) {
568 kprintf(
"Unexpected size of .debug_line in %s\n",
576fill_lines(
int num_traces,
void **traces,
int check_debuglink,
577 obj_info_t **objp, line_info_t *lines,
int offset,
FILE *errout);
580append_obj(obj_info_t **objp)
582 obj_info_t *newobj = calloc(1,
sizeof(obj_info_t));
583 if (*objp) (*objp)->next = newobj;
604follow_debuglink(
const char *debuglink,
int num_traces,
void **traces,
605 obj_info_t **objp, line_info_t *lines,
int offset,
FILE *errout)
607 static const char global_debug_dir[] =
"/usr/lib/debug";
608 const size_t global_debug_dir_len =
sizeof(global_debug_dir) - 1;
610 obj_info_t *o1 = *objp, *o2;
613 p = strrchr(binary_filename,
'/');
619 len = strlen(binary_filename);
620 if (
len >= PATH_MAX - global_debug_dir_len)
621 len = PATH_MAX - global_debug_dir_len - 1;
622 memmove(binary_filename + global_debug_dir_len, binary_filename,
len);
623 memcpy(binary_filename, global_debug_dir, global_debug_dir_len);
624 len += global_debug_dir_len;
625 strlcpy(binary_filename +
len, debuglink, PATH_MAX -
len);
629 o2->base_addr = o1->base_addr;
631 fill_lines(num_traces, traces, 0, objp, lines, offset, errout);
636follow_debuglink_build_id(
const char *build_id,
size_t build_id_size,
int num_traces,
void **traces,
637 obj_info_t **objp, line_info_t *lines,
int offset,
FILE *errout)
639 static const char global_debug_dir[] =
"/usr/lib/debug/.build-id/";
640 const size_t global_debug_dir_len =
sizeof(global_debug_dir) - 1;
642 obj_info_t *o1 = *objp, *o2;
645 if (PATH_MAX < global_debug_dir_len + 1 + build_id_size * 2 + 6)
return;
647 memcpy(binary_filename, global_debug_dir, global_debug_dir_len);
648 p = binary_filename + global_debug_dir_len;
649 for (i = 0; i < build_id_size; i++) {
650 static const char tbl[] =
"0123456789abcdef";
651 unsigned char n = build_id[i];
654 if (i == 0) *p++ =
'/';
660 o2->base_addr = o1->base_addr;
662 fill_lines(num_traces, traces, 0, objp, lines, offset, errout);
668 DW_TAG_compile_unit = 0x11,
669 DW_TAG_inlined_subroutine = 0x1d,
670 DW_TAG_subprogram = 0x2e,
676 DW_AT_sibling = 0x01,
677 DW_AT_location = 0x02,
684 DW_AT_ordering = 0x09,
686 DW_AT_byte_size = 0x0b,
688 DW_AT_bit_size = 0x0d,
691 DW_AT_stmt_list = 0x10,
693 DW_AT_high_pc = 0x12,
694 DW_AT_language = 0x13,
697 DW_AT_discr_value = 0x16,
698 DW_AT_visibility = 0x17,
700 DW_AT_string_length = 0x19,
701 DW_AT_common_reference = 0x1a,
702 DW_AT_comp_dir = 0x1b,
703 DW_AT_const_value = 0x1c,
704 DW_AT_containing_type = 0x1d,
705 DW_AT_default_value = 0x1e,
708 DW_AT_is_optional = 0x21,
709 DW_AT_lower_bound = 0x22,
712 DW_AT_producer = 0x25,
714 DW_AT_prototyped = 0x27,
717 DW_AT_return_addr = 0x2a,
719 DW_AT_start_scope = 0x2c,
721 DW_AT_bit_stride = 0x2e,
722 DW_AT_upper_bound = 0x2f,
724 DW_AT_abstract_origin = 0x31,
725 DW_AT_accessibility = 0x32,
726 DW_AT_address_class = 0x33,
727 DW_AT_artificial = 0x34,
728 DW_AT_base_types = 0x35,
729 DW_AT_calling_convention = 0x36,
731 DW_AT_data_member_location = 0x38,
732 DW_AT_decl_column = 0x39,
733 DW_AT_decl_file = 0x3a,
734 DW_AT_decl_line = 0x3b,
735 DW_AT_declaration = 0x3c,
736 DW_AT_discr_list = 0x3d,
737 DW_AT_encoding = 0x3e,
738 DW_AT_external = 0x3f,
739 DW_AT_frame_base = 0x40,
741 DW_AT_identifier_case = 0x42,
743 DW_AT_namelist_item = 0x44,
744 DW_AT_priority = 0x45,
745 DW_AT_segment = 0x46,
746 DW_AT_specification = 0x47,
747 DW_AT_static_link = 0x48,
749 DW_AT_use_location = 0x4a,
750 DW_AT_variable_parameter = 0x4b,
751 DW_AT_virtuality = 0x4c,
752 DW_AT_vtable_elem_location = 0x4d,
753 DW_AT_allocated = 0x4e,
754 DW_AT_associated = 0x4f,
755 DW_AT_data_location = 0x50,
756 DW_AT_byte_stride = 0x51,
757 DW_AT_entry_pc = 0x52,
758 DW_AT_use_UTF8 = 0x53,
759 DW_AT_extension = 0x54,
761 DW_AT_trampoline = 0x56,
762 DW_AT_call_column = 0x57,
763 DW_AT_call_file = 0x58,
764 DW_AT_call_line = 0x59,
765 DW_AT_description = 0x5a,
766 DW_AT_binary_scale = 0x5b,
767 DW_AT_decimal_scale = 0x5c,
769 DW_AT_decimal_sign = 0x5e,
770 DW_AT_digit_count = 0x5f,
771 DW_AT_picture_string = 0x60,
772 DW_AT_mutable = 0x61,
773 DW_AT_threads_scaled = 0x62,
774 DW_AT_explicit = 0x63,
775 DW_AT_object_pointer = 0x64,
776 DW_AT_endianity = 0x65,
777 DW_AT_elemental = 0x66,
779 DW_AT_recursive = 0x68,
780 DW_AT_signature = 0x69,
781 DW_AT_main_subprogram = 0x6a,
782 DW_AT_data_bit_offset = 0x6b,
783 DW_AT_const_expr = 0x6c,
784 DW_AT_enum_class = 0x6d,
785 DW_AT_linkage_name = 0x6e,
786 DW_AT_string_length_bit_size = 0x6f,
787 DW_AT_string_length_byte_size = 0x70,
789 DW_AT_str_offsets_base = 0x72,
790 DW_AT_addr_base = 0x73,
791 DW_AT_rnglists_base = 0x74,
793 DW_AT_dwo_name = 0x76,
794 DW_AT_reference = 0x77,
795 DW_AT_rvalue_reference = 0x78,
797 DW_AT_call_all_calls = 0x7a,
798 DW_AT_call_all_source_calls = 0x7b,
799 DW_AT_call_all_tail_calls = 0x7c,
800 DW_AT_call_return_pc = 0x7d,
801 DW_AT_call_value = 0x7e,
802 DW_AT_call_origin = 0x7f,
803 DW_AT_call_parameter = 0x80,
804 DW_AT_call_pc = 0x81,
805 DW_AT_call_tail_call = 0x82,
806 DW_AT_call_target = 0x83,
807 DW_AT_call_target_clobbered = 0x84,
808 DW_AT_call_data_location = 0x85,
809 DW_AT_call_data_value = 0x86,
810 DW_AT_noreturn = 0x87,
811 DW_AT_alignment = 0x88,
812 DW_AT_export_symbols = 0x89,
813 DW_AT_deleted = 0x8a,
814 DW_AT_defaulted = 0x8b,
815 DW_AT_loclists_base = 0x8c,
816 DW_AT_lo_user = 0x2000,
817 DW_AT_hi_user = 0x3fff
825 DW_FORM_block2 = 0x03,
826 DW_FORM_block4 = 0x04,
827 DW_FORM_data2 = 0x05,
828 DW_FORM_data4 = 0x06,
829 DW_FORM_data8 = 0x07,
830 DW_FORM_string = 0x08,
831 DW_FORM_block = 0x09,
832 DW_FORM_block1 = 0x0a,
833 DW_FORM_data1 = 0x0b,
835 DW_FORM_sdata = 0x0d,
837 DW_FORM_udata = 0x0f,
838 DW_FORM_ref_addr = 0x10,
843 DW_FORM_ref_udata = 0x15,
844 DW_FORM_indirect = 0x16,
845 DW_FORM_sec_offset = 0x17,
846 DW_FORM_exprloc = 0x18,
847 DW_FORM_flag_present = 0x19,
849 DW_FORM_addrx = 0x1b,
850 DW_FORM_ref_sup4 = 0x1c,
851 DW_FORM_strp_sup = 0x1d,
852 DW_FORM_data16 = 0x1e,
853 DW_FORM_line_strp = 0x1f,
854 DW_FORM_ref_sig8 = 0x20,
855 DW_FORM_implicit_const = 0x21,
856 DW_FORM_loclistx = 0x22,
857 DW_FORM_rnglistx = 0x23,
858 DW_FORM_ref_sup8 = 0x24,
859 DW_FORM_strx1 = 0x25,
860 DW_FORM_strx2 = 0x26,
861 DW_FORM_strx3 = 0x27,
862 DW_FORM_strx4 = 0x28,
863 DW_FORM_addrx1 = 0x29,
864 DW_FORM_addrx2 = 0x2a,
865 DW_FORM_addrx3 = 0x2b,
866 DW_FORM_addrx4 = 0x2c,
869 DW_FORM_GNU_ref_alt = 0x1f20,
870 DW_FORM_GNU_strp_alt = 0x1f21
875 DW_RLE_end_of_list = 0x00,
876 DW_RLE_base_addressx = 0x01,
877 DW_RLE_startx_endx = 0x02,
878 DW_RLE_startx_length = 0x03,
879 DW_RLE_offset_pair = 0x04,
880 DW_RLE_base_address = 0x05,
881 DW_RLE_start_end = 0x06,
882 DW_RLE_start_length = 0x07
894# define ABBREV_TABLE_SIZE 256
898 uint8_t current_version;
899 const char *current_cu;
900 uint64_t current_low_pc;
901 uint64_t current_str_offsets_base;
902 uint64_t current_addr_base;
903 uint64_t current_rnglists_base;
904 const char *debug_line_cu_end;
905 uint8_t debug_line_format;
906 uint16_t debug_line_version;
907 const char *debug_line_files;
908 const char *debug_line_directories;
915 uint8_t address_size;
917 const char *abbrev_table[ABBREV_TABLE_SIZE];
940#if defined(WORDS_BIGENDIAN)
941#define MERGE_2INTS(a,b,sz) (((uint64_t)(a)<<sz)|(b))
943#define MERGE_2INTS(a,b,sz) (((uint64_t)(b)<<sz)|(a))
947get_uint16(
const uint8_t *p)
949 return (uint16_t)MERGE_2INTS(p[0],p[1],8);
953get_uint32(
const uint8_t *p)
955 return (uint32_t)MERGE_2INTS(get_uint16(p),get_uint16(p+2),16);
959get_uint64(
const uint8_t *p)
961 return MERGE_2INTS(get_uint32(p),get_uint32(p+4),32);
965read_uint8(
const char **ptr)
967 const char *p = *ptr;
973read_uint16(
const char **ptr)
975 const char *p = *ptr;
977 return get_uint16((
const uint8_t *)p);
981read_uint24(
const char **ptr)
983 const char *p = *ptr;
985 return ((uint8_t)*p << 16) | get_uint16((
const uint8_t *)p+1);
989read_uint32(
const char **ptr)
991 const char *p = *ptr;
993 return get_uint32((
const uint8_t *)p);
997read_uint64(
const char **ptr)
999 const unsigned char *p = (
const unsigned char *)*ptr;
1000 *ptr = (
char *)(p + 8);
1001 return get_uint64(p);
1005read_uintptr(
const char **ptr)
1007 const unsigned char *p = (
const unsigned char *)*ptr;
1008 *ptr = (
char *)(p + SIZEOF_VOIDP);
1009#if SIZEOF_VOIDP == 8
1010 return get_uint64(p);
1012 return get_uint32(p);
1017read_uint(DebugInfoReader *reader)
1019 if (reader->format == 4) {
1020 return read_uint32(&reader->p);
1022 return read_uint64(&reader->p);
1027read_uleb128(DebugInfoReader *reader)
1029 return uleb128(&reader->p);
1033read_sleb128(DebugInfoReader *reader)
1035 return sleb128(&reader->p);
1039debug_info_reader_init(DebugInfoReader *reader, obj_info_t *obj)
1041 reader->file = obj->mapped;
1043 reader->p = obj->debug_info.ptr;
1044 reader->pend = obj->debug_info.ptr + obj->debug_info.size;
1045 reader->debug_line_cu_end = obj->debug_line.ptr;
1046 reader->current_low_pc = 0;
1047 reader->current_str_offsets_base = 0;
1048 reader->current_addr_base = 0;
1049 reader->current_rnglists_base = 0;
1053di_skip_die_attributes(
const char **p)
1056 uint64_t at = uleb128(p);
1057 uint64_t form = uleb128(p);
1058 if (!at && !form)
break;
1062 case DW_FORM_implicit_const:
1070di_read_debug_abbrev_cu(DebugInfoReader *reader)
1073 const char *p = reader->q0;
1075 uint64_t abbrev_number = uleb128(&p);
1076 if (abbrev_number <= prev)
break;
1077 if (abbrev_number < ABBREV_TABLE_SIZE) {
1078 reader->abbrev_table[abbrev_number] = p;
1080 prev = abbrev_number;
1083 di_skip_die_attributes(&p);
1088di_read_debug_line_cu(DebugInfoReader *reader,
FILE *errout)
1091 struct LineNumberProgramHeader header;
1093 p = (
const char *)reader->debug_line_cu_end;
1094 if (parse_debug_line_header(reader->obj, &p, &header, errout))
1097 reader->debug_line_cu_end = (
char *)header.cu_end;
1098 reader->debug_line_format = header.format;
1099 reader->debug_line_version = header.version;
1100 reader->debug_line_directories = (
char *)header.include_directories;
1101 reader->debug_line_files = (
char *)header.filenames;
1107set_addr_idx_value(DebugInfoValue *v, uint64_t n)
1114set_uint_value(DebugInfoValue *v, uint64_t n)
1121set_int_value(DebugInfoValue *v, int64_t n)
1128set_cstr_value(DebugInfoValue *v,
const char *s)
1136set_cstrp_value(DebugInfoValue *v,
const char *s, uint64_t
off)
1144set_data_value(DebugInfoValue *v,
const char *s)
1151get_cstr_value(DebugInfoValue *v)
1154 return v->as.ptr + v->off;
1161resolve_strx(DebugInfoReader *reader, uint64_t idx)
1163 const char *p = reader->obj->debug_str_offsets.ptr + reader->current_str_offsets_base;
1165 if (reader->format == 4) {
1166 off = ((uint32_t *)p)[idx];
1169 off = ((uint64_t *)p)[idx];
1171 return reader->obj->debug_str.ptr +
off;
1175debug_info_reader_read_addr_value_member(DebugInfoReader *reader, DebugInfoValue *v,
int size)
1178 set_uint_value(v, read_uint32(&reader->p));
1179 }
else if (size == 8) {
1180 set_uint_value(v, read_uint64(&reader->p));
1187#define debug_info_reader_read_addr_value(reader, v, mem) \
1188 if (!debug_info_reader_read_addr_value_member((reader), (v), (reader)->mem)) { \
1189 kprintf("unknown " #mem ":%d", (reader)->mem); \
1195debug_info_reader_read_value(DebugInfoReader *reader, uint64_t form, DebugInfoValue *v,
FILE *errout)
1199 debug_info_reader_read_addr_value(reader, v, address_size);
1201 case DW_FORM_block2:
1202 v->size = read_uint16(&reader->p);
1203 set_data_value(v, reader->p);
1204 reader->p += v->size;
1206 case DW_FORM_block4:
1207 v->size = read_uint32(&reader->p);
1208 set_data_value(v, reader->p);
1209 reader->p += v->size;
1212 set_uint_value(v, read_uint16(&reader->p));
1215 set_uint_value(v, read_uint32(&reader->p));
1218 set_uint_value(v, read_uint64(&reader->p));
1220 case DW_FORM_string:
1221 v->size = strlen(reader->p);
1222 set_cstr_value(v, reader->p);
1223 reader->p += v->size + 1;
1226 v->size = uleb128(&reader->p);
1227 set_data_value(v, reader->p);
1228 reader->p += v->size;
1230 case DW_FORM_block1:
1231 v->size = read_uint8(&reader->p);
1232 set_data_value(v, reader->p);
1233 reader->p += v->size;
1236 set_uint_value(v, read_uint8(&reader->p));
1239 set_uint_value(v, read_uint8(&reader->p));
1242 set_int_value(v, read_sleb128(reader));
1245 set_cstrp_value(v, reader->obj->debug_str.ptr, read_uint(reader));
1248 set_uint_value(v, read_uleb128(reader));
1250 case DW_FORM_ref_addr:
1251 if (reader->current_version <= 2) {
1254 debug_info_reader_read_addr_value(reader, v, address_size);
1256 debug_info_reader_read_addr_value(reader, v, format);
1260 set_uint_value(v, read_uint8(&reader->p));
1263 set_uint_value(v, read_uint16(&reader->p));
1266 set_uint_value(v, read_uint32(&reader->p));
1269 set_uint_value(v, read_uint64(&reader->p));
1271 case DW_FORM_ref_udata:
1272 set_uint_value(v, uleb128(&reader->p));
1274 case DW_FORM_indirect:
1276 set_uint_value(v, uleb128(&reader->p));
1278 case DW_FORM_sec_offset:
1279 set_uint_value(v, read_uint(reader));
1289 case DW_FORM_exprloc:
1290 v->size = (size_t)read_uleb128(reader);
1291 set_data_value(v, reader->p);
1292 reader->p += v->size;
1294 case DW_FORM_flag_present:
1295 set_uint_value(v, 1);
1298 set_cstr_value(v, resolve_strx(reader, uleb128(&reader->p)));
1301 set_addr_idx_value(v, uleb128(&reader->p));
1303 case DW_FORM_ref_sup4:
1304 set_uint_value(v, read_uint32(&reader->p));
1306 case DW_FORM_strp_sup:
1307 set_uint_value(v, read_uint(reader));
1310 case DW_FORM_data16:
1312 set_data_value(v, reader->p);
1313 reader->p += v->size;
1315 case DW_FORM_line_strp:
1316 set_cstrp_value(v, reader->obj->debug_line_str.ptr, read_uint(reader));
1318 case DW_FORM_ref_sig8:
1319 set_uint_value(v, read_uint64(&reader->p));
1321 case DW_FORM_implicit_const:
1322 set_int_value(v, sleb128(&reader->q));
1324 case DW_FORM_loclistx:
1325 set_uint_value(v, read_uleb128(reader));
1327 case DW_FORM_rnglistx:
1328 set_uint_value(v, read_uleb128(reader));
1330 case DW_FORM_ref_sup8:
1331 set_uint_value(v, read_uint64(&reader->p));
1334 set_cstr_value(v, resolve_strx(reader, read_uint8(&reader->p)));
1337 set_cstr_value(v, resolve_strx(reader, read_uint16(&reader->p)));
1340 set_cstr_value(v, resolve_strx(reader, read_uint24(&reader->p)));
1343 set_cstr_value(v, resolve_strx(reader, read_uint32(&reader->p)));
1345 case DW_FORM_addrx1:
1346 set_addr_idx_value(v, read_uint8(&reader->p));
1348 case DW_FORM_addrx2:
1349 set_addr_idx_value(v, read_uint16(&reader->p));
1351 case DW_FORM_addrx3:
1352 set_addr_idx_value(v, read_uint24(&reader->p));
1354 case DW_FORM_addrx4:
1355 set_addr_idx_value(v, read_uint32(&reader->p));
1360 case DW_FORM_GNU_ref_alt:
1361 case DW_FORM_GNU_strp_alt:
1363 set_uint_value(v, 0);
1372 kprintf(
"%d: unsupported form: %#"PRIx64
"\n", __LINE__, form);
1378di_find_abbrev(DebugInfoReader *reader, uint64_t abbrev_number,
FILE *errout)
1381 if (abbrev_number < ABBREV_TABLE_SIZE) {
1382 return reader->abbrev_table[abbrev_number];
1384 p = reader->abbrev_table[ABBREV_TABLE_SIZE-1];
1388 di_skip_die_attributes(&p);
1389 for (uint64_t n = uleb128(&p); abbrev_number != n; n = uleb128(&p)) {
1391 kprintf(
"%d: Abbrev Number %"PRId64
" not found\n",__LINE__, abbrev_number);
1396 di_skip_die_attributes(&p);
1403hexdump0(
const unsigned char *p,
size_t n,
FILE *errout)
1406 kprintf(
" 0 1 2 3 4 5 6 7 8 9 A B C D E F\n");
1407 for (i=0; i < n; i++){
1410 kprintf(
"%02" PRIdSIZE
": %02X ", i/16, p[i]);
1413 kprintf(
"%02X\n", p[i]);
1416 kprintf(
"%02X ", p[i]);
1420 if ((i & 15) != 15) {
1424#define hexdump(p,n,e) hexdump0((const unsigned char *)p, n, e)
1427div_inspect(DebugInfoValue *v,
FILE *errout)
1431 kprintf(
"%d: type:%d size:%" PRIxSIZE
" v:%"PRIx64
"\n",__LINE__,v->type,v->size,v->as.uint64);
1434 kprintf(
"%d: type:%d size:%" PRIxSIZE
" v:%"PRId64
"\n",__LINE__,v->type,v->size,(int64_t)v->as.uint64);
1437 kprintf(
"%d: type:%d size:%" PRIxSIZE
" v:'%s'\n",__LINE__,v->type,v->size,v->as.ptr);
1440 kprintf(
"%d: type:%d size:%" PRIxSIZE
" v:\n",__LINE__,v->type,v->size);
1441 hexdump(v->as.ptr, 16, errout);
1448di_read_die(DebugInfoReader *reader, DIE *die,
FILE *errout)
1450 uint64_t abbrev_number = uleb128(&reader->p);
1451 if (abbrev_number == 0) {
1456 if (!(reader->q = di_find_abbrev(reader, abbrev_number, errout)))
return NULL;
1458 die->pos = reader->p - reader->obj->debug_info.ptr - 1;
1459 die->tag = (int)uleb128(&reader->q);
1460 die->has_children = *reader->q++;
1461 if (die->has_children) {
1467static DebugInfoValue *
1468di_read_record(DebugInfoReader *reader, DebugInfoValue *vp,
FILE *errout)
1470 uint64_t at = uleb128(&reader->q);
1471 uint64_t form = uleb128(&reader->q);
1472 if (!at || !form)
return NULL;
1475 if (!debug_info_reader_read_value(reader, form, vp, errout))
return NULL;
1480di_skip_records(DebugInfoReader *reader,
FILE *errout)
1483 DebugInfoValue v = {{0}};
1484 uint64_t at = uleb128(&reader->q);
1485 uint64_t form = uleb128(&reader->q);
1486 if (!at || !form)
return true;
1487 if (!debug_info_reader_read_value(reader, form, &v, errout))
return false;
1491typedef struct addr_header {
1493 uint64_t unit_length;
1495 uint8_t address_size;
1500addr_header_init(obj_info_t *obj, addr_header_t *header,
FILE *errout)
1502 const char *p = obj->debug_addr.ptr;
1506 if (!p)
return true;
1508 header->unit_length = *(uint32_t *)p;
1509 p +=
sizeof(uint32_t);
1512 if (header->unit_length == 0xffffffff) {
1513 header->unit_length = *(uint64_t *)p;
1514 p +=
sizeof(uint64_t);
1519 header->address_size = *p++;
1520 if (header->address_size != 4 && header->address_size != 8) {
1521 kprintf(
"unknown address_size:%d", header->address_size);
1529read_addr(addr_header_t *header, uint64_t addr_base, uint64_t idx) {
1530 if (header->address_size == 4) {
1531 return ((uint32_t*)(header->ptr + addr_base))[idx];
1534 return ((uint64_t*)(header->ptr + addr_base))[idx];
1538typedef struct rnglists_header {
1539 uint64_t unit_length;
1541 uint8_t address_size;
1542 uint32_t offset_entry_count;
1546rnglists_header_init(obj_info_t *obj, rnglists_header_t *header,
FILE *errout)
1548 const char *p = obj->debug_rnglists.ptr;
1550 if (!p)
return true;
1552 header->unit_length = *(uint32_t *)p;
1553 p +=
sizeof(uint32_t);
1556 if (header->unit_length == 0xffffffff) {
1557 header->unit_length = *(uint64_t *)p;
1558 p +=
sizeof(uint64_t);
1563 header->address_size = *p++;
1564 if (header->address_size != 4 && header->address_size != 8) {
1565 kprintf(
"unknown address_size:%d", header->address_size);
1569 header->offset_entry_count = *(uint32_t *)p;
1583ranges_set(ranges_t *ptr, DebugInfoValue *v, addr_header_t *addr_header, uint64_t addr_base)
1586 if (v->type == VAL_uint) {
1589 else if (v->type == VAL_addr) {
1590 n = read_addr(addr_header, addr_base, v->as.addr_idx);
1595 ptr->low_pc_set =
true;
1598 if (v->form == DW_FORM_addr) {
1602 ptr->high_pc = ptr->low_pc + n;
1604 ptr->high_pc_set =
true;
1608 ptr->ranges_set =
true;
1614read_dw_form_addr(DebugInfoReader *reader,
const char **ptr,
FILE *errout)
1616 const char *p = *ptr;
1617 *ptr = p + reader->address_size;
1618 if (reader->address_size == 4) {
1619 return read_uint32(&p);
1621 return read_uint64(&p);
1626ranges_include(DebugInfoReader *reader, ranges_t *ptr, uint64_t addr, rnglists_header_t *rnglists_header,
FILE *errout)
1628 if (ptr->high_pc_set) {
1629 if (ptr->ranges_set || !ptr->low_pc_set) {
1632 if (ptr->low_pc <= addr && addr <= ptr->high_pc) {
1633 return (uintptr_t)ptr->low_pc;
1636 else if (ptr->ranges_set) {
1639 uint64_t base = ptr->low_pc_set ? ptr->low_pc : reader->current_low_pc;
1640 bool base_valid =
true;
1641 if (reader->current_version >= 5) {
1642 if (rnglists_header->offset_entry_count == 0) {
1644 p = reader->obj->debug_rnglists.ptr + ptr->ranges + reader->current_rnglists_base;
1648 const char *offset_array = reader->obj->debug_rnglists.ptr + reader->current_rnglists_base;
1649 if (rnglists_header->format == 4) {
1650 p = offset_array + ((uint32_t *)offset_array)[ptr->ranges];
1653 p = offset_array + ((uint64_t *)offset_array)[ptr->ranges];
1657 uint8_t rle = read_uint8(&p);
1658 uintptr_t from = 0, to = 0;
1659 if (rle == DW_RLE_end_of_list)
break;
1661 case DW_RLE_base_addressx:
1665 case DW_RLE_startx_endx:
1669 case DW_RLE_startx_length:
1673 case DW_RLE_offset_pair:
1674 if (!base_valid)
break;
1675 from = (uintptr_t)base + uleb128(&p);
1676 to = (uintptr_t)base + uleb128(&p);
1678 case DW_RLE_base_address:
1679 base = read_dw_form_addr(reader, &p, errout);
1682 case DW_RLE_start_end:
1683 from = (uintptr_t)read_dw_form_addr(reader, &p, errout);
1684 to = (uintptr_t)read_dw_form_addr(reader, &p, errout);
1686 case DW_RLE_start_length:
1687 from = (uintptr_t)read_dw_form_addr(reader, &p, errout);
1688 to = from + uleb128(&p);
1691 if (from <= addr && addr < to) {
1697 p = reader->obj->debug_ranges.ptr + ptr->ranges;
1699 uintptr_t from = read_uintptr(&p);
1700 uintptr_t to = read_uintptr(&p);
1701 if (!from && !to)
break;
1702 if (from == UINTPTR_MAX) {
1706 else if (base + from <= addr && addr < base + to) {
1707 return (uintptr_t)base + from;
1711 else if (ptr->low_pc_set) {
1712 if (ptr->low_pc == addr) {
1713 return (uintptr_t)ptr->low_pc;
1721ranges_inspect(DebugInfoReader *reader, ranges_t *ptr,
FILE *errout)
1723 if (ptr->high_pc_set) {
1724 if (ptr->ranges_set || !ptr->low_pc_set) {
1725 kprintf(
"low_pc_set:%d high_pc_set:%d ranges_set:%d\n",ptr->low_pc_set,ptr->high_pc_set,ptr->ranges_set);
1728 kprintf(
"low_pc:%"PRIx64
" high_pc:%"PRIx64
"\n",ptr->low_pc,ptr->high_pc);
1730 else if (ptr->ranges_set) {
1731 char *p = reader->obj->debug_ranges.ptr + ptr->ranges;
1732 kprintf(
"low_pc:%"PRIx64
" ranges:%"PRIx64
" %lx ",ptr->low_pc,ptr->ranges, p-reader->obj->mapped);
1734 uintptr_t from = read_uintptr(&p);
1735 uintptr_t to = read_uintptr(&p);
1736 if (!from && !to)
break;
1737 kprintf(
"%"PRIx64
"-%"PRIx64
" ",ptr->low_pc+from,ptr->low_pc+to);
1741 else if (ptr->low_pc_set) {
1742 kprintf(
"low_pc:%"PRIx64
"\n",ptr->low_pc);
1751di_read_cu(DebugInfoReader *reader,
FILE *errout)
1753 uint64_t unit_length;
1755 uint64_t debug_abbrev_offset;
1757 reader->current_cu = reader->p;
1758 unit_length = read_uint32(&reader->p);
1759 if (unit_length == 0xffffffff) {
1760 unit_length = read_uint64(&reader->p);
1763 reader->cu_end = reader->p + unit_length;
1764 version = read_uint16(&reader->p);
1765 reader->current_version = version;
1769 else if (version == 5) {
1770 read_uint8(&reader->p);
1771 reader->address_size = read_uint8(&reader->p);
1772 debug_abbrev_offset = read_uint(reader);
1775 debug_abbrev_offset = read_uint(reader);
1776 reader->address_size = read_uint8(&reader->p);
1778 if (reader->address_size != 4 && reader->address_size != 8) {
1779 kprintf(
"unknown address_size:%d", reader->address_size);
1782 reader->q0 = reader->obj->debug_abbrev.ptr + debug_abbrev_offset;
1785 di_read_debug_abbrev_cu(reader);
1786 if (di_read_debug_line_cu(reader, errout))
return -1;
1791 if (!di_read_die(reader, &die, errout))
continue;
1793 if (die.tag != DW_TAG_compile_unit) {
1794 if (!di_skip_records(reader, errout))
return -1;
1798 reader->current_str_offsets_base = 0;
1799 reader->current_addr_base = 0;
1800 reader->current_rnglists_base = 0;
1802 DebugInfoValue low_pc = {{0}};
1805 DebugInfoValue v = {{0}};
1806 if (!di_read_record(reader, &v, errout))
break;
1813 case DW_AT_str_offsets_base:
1814 reader->current_str_offsets_base = v.as.uint64;
1816 case DW_AT_addr_base:
1817 reader->current_addr_base = v.as.uint64;
1819 case DW_AT_rnglists_base:
1820 reader->current_rnglists_base = v.as.uint64;
1825 switch (low_pc.type) {
1827 reader->current_low_pc = low_pc.as.uint64;
1831 addr_header_t header = {0};
1832 if (!addr_header_init(reader->obj, &header, errout))
return -1;
1833 reader->current_low_pc = read_addr(&header, reader->current_addr_base, low_pc.as.addr_idx);
1843read_abstract_origin(DebugInfoReader *reader, uint64_t form, uint64_t abstract_origin, line_info_t *line,
FILE *errout)
1845 const char *p = reader->p;
1846 const char *q = reader->q;
1847 int level = reader->level;
1855 case DW_FORM_ref_udata:
1856 reader->p = reader->current_cu + abstract_origin;
1858 case DW_FORM_ref_addr:
1860 case DW_FORM_ref_sig8:
1862 case DW_FORM_ref_sup4:
1863 case DW_FORM_ref_sup8:
1868 if (!di_read_die(reader, &die, errout))
goto finish;
1872 DebugInfoValue v = {{0}};
1873 if (!di_read_record(reader, &v, errout))
break;
1876 line->sname = get_cstr_value(&v);
1884 reader->level = level;
1888debug_info_read(DebugInfoReader *reader,
int num_traces,
void **traces,
1889 line_info_t *lines,
int offset,
FILE *errout)
1892 addr_header_t addr_header = {0};
1893 if (!addr_header_init(reader->obj, &addr_header, errout))
return false;
1895 rnglists_header_t rnglists_header = {0};
1896 if (!rnglists_header_init(reader->obj, &rnglists_header, errout))
return false;
1898 while (reader->p < reader->cu_end) {
1900 ranges_t ranges = {0};
1901 line_info_t line = {0};
1903 if (!di_read_die(reader, &die, errout))
continue;
1906 if (die.tag != DW_TAG_subprogram && die.tag != DW_TAG_inlined_subroutine) {
1908 if (!di_skip_records(reader, errout))
return false;
1914 DebugInfoValue v = {{0}};
1916 if (!di_read_record(reader, &v, errout))
break;
1921 line.sname = get_cstr_value(&v);
1923 case DW_AT_call_file:
1924 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);
1926 case DW_AT_call_line:
1927 line.line = (int)v.as.uint64;
1932 ranges_set(&ranges, &v, &addr_header, reader->current_addr_base);
1934 case DW_AT_declaration:
1939 case DW_AT_abstract_origin:
1940 read_abstract_origin(reader, v.form, v.as.uint64, &line, errout);
1946 for (
int i=offset; i < num_traces; i++) {
1947 uintptr_t addr = (uintptr_t)traces[i];
1948 uintptr_t offset = addr - reader->obj->base_addr + reader->obj->vmaddr;
1949 uintptr_t saddr = ranges_include(reader, &ranges, offset, &rnglists_header, errout);
1950 if (saddr == UINTPTR_MAX)
return false;
1953 if (lines[i].sname) {
1954 line_info_t *lp = malloc(
sizeof(line_info_t));
1955 memcpy(lp, &lines[i],
sizeof(line_info_t));
1957 lp->dirname = line.dirname;
1958 lp->filename = line.filename;
1959 lp->line = line.line;
1962 lines[i].path = reader->obj->path;
1963 lines[i].base_addr = line.base_addr;
1964 lines[i].sname = line.sname;
1965 lines[i].saddr = saddr + reader->obj->base_addr - reader->obj->vmaddr;
1988parse_ver5_debug_line_header(
const char *p,
int idx, uint8_t format,
1989 obj_info_t *obj,
const char **out_path,
1990 uint64_t *out_directory_index,
FILE *errout)
1993 int entry_format_count = *(uint8_t *)p++;
1994 const char *entry_format = p;
1997 for (i = 0; i < entry_format_count * 2; i++) uleb128(&p);
1999 int entry_count = (int)uleb128(&p);
2001 DebugInfoReader reader = {0};
2002 debug_info_reader_init(&reader, obj);
2003 reader.format = format;
2005 for (j = 0; j < entry_count; j++) {
2006 const char *format = entry_format;
2007 for (i = 0; i < entry_format_count; i++) {
2008 DebugInfoValue v = {{0}};
2009 unsigned long dw_lnct = uleb128(&format);
2010 unsigned long dw_form = uleb128(&format);
2011 if (!debug_info_reader_read_value(&reader, dw_form, &v, errout))
return 0;
2012 if (dw_lnct == 1 && v.type == VAL_cstr && out_path)
2013 *out_path = v.as.ptr + v.off;
2014 if (dw_lnct == 2 && v.type == VAL_uint && out_directory_index)
2015 *out_directory_index = v.as.uint64;
2017 if (j == idx)
return 0;
2025uncompress_debug_section(ElfW(Shdr) *shdr,
char *file,
char **ptr)
2028#ifdef SUPPORT_COMPRESSED_DEBUG_LINE
2029 ElfW(Chdr) *chdr = (ElfW(Chdr) *)(file + shdr->sh_offset);
2030 unsigned long destsize = chdr->ch_size;
2033 if (chdr->ch_type != ELFCOMPRESS_ZLIB) {
2038 *ptr = malloc(destsize);
2039 if (!*ptr)
return 0;
2040 ret = uncompress((Bytef *)*ptr, &destsize,
2041 (
const Bytef*)chdr +
sizeof(ElfW(Chdr)),
2042 shdr->sh_size -
sizeof(ElfW(Chdr)));
2043 if (ret != Z_OK)
goto fail;
2055fill_lines(
int num_traces,
void **traces,
int check_debuglink,
2056 obj_info_t **objp, line_info_t *lines,
int offset,
FILE *errout)
2061 ElfW(Shdr) *shdr, *shstr_shdr;
2062 ElfW(Shdr) *gnu_debuglink_shdr = NULL;
2063 ElfW(Shdr) *note_gnu_build_id = NULL;
2067 ElfW(Shdr) *symtab_shdr = NULL, *strtab_shdr = NULL;
2068 ElfW(Shdr) *dynsym_shdr = NULL, *dynstr_shdr = NULL;
2069 obj_info_t *obj = *objp;
2070 uintptr_t dladdr_fbase = 0;
2072 fd = open(binary_filename, O_RDONLY);
2076 filesize = lseek(fd, 0, SEEK_END);
2080 kprintf(
"lseek: %s\n", strerror(e));
2083#if SIZEOF_OFF_T > SIZEOF_SIZE_T
2084 if (filesize > (off_t)SIZE_MAX) {
2086 kprintf(
"Too large file %s\n", binary_filename);
2090 lseek(fd, 0, SEEK_SET);
2092 file = (
char *)mmap(NULL, (
size_t)filesize, PROT_READ, MAP_SHARED, fd, 0);
2093 if (file == MAP_FAILED) {
2096 kprintf(
"mmap: %s\n", strerror(e));
2101 ehdr = (ElfW(Ehdr) *)file;
2102 if (memcmp(ehdr->e_ident,
"\177ELF", 4) != 0) {
2110 obj->mapped_size = (size_t)filesize;
2112 shdr = (ElfW(Shdr) *)(file + ehdr->e_shoff);
2114 shstr_shdr = shdr + ehdr->e_shstrndx;
2115 shstr = file + shstr_shdr->sh_offset;
2117 for (i = 0; i < ehdr->e_shnum; i++) {
2118 char *section_name = shstr + shdr[i].sh_name;
2119 switch (shdr[i].sh_type) {
2121 if (!strcmp(section_name,
".strtab")) {
2122 strtab_shdr = shdr + i;
2124 else if (!strcmp(section_name,
".dynstr")) {
2125 dynstr_shdr = shdr + i;
2130 symtab_shdr = shdr + i;
2134 dynsym_shdr = shdr + i;
2137 if (!strcmp(section_name,
".note.gnu.build-id")) {
2138 note_gnu_build_id = shdr + i;
2142 if (!strcmp(section_name,
".gnu_debuglink")) {
2143 gnu_debuglink_shdr = shdr + i;
2146 const char *debug_section_names[] = {
2151 ".debug_str_offsets",
2158 for (j=0; j < DWARF_SECTION_COUNT; j++) {
2159 struct dwarf_section *s = obj_dwarf_section_at(obj, j);
2161 if (strcmp(section_name, debug_section_names[j]) != 0)
2164 s->ptr = file + shdr[i].sh_offset;
2165 s->size = shdr[i].sh_size;
2166 s->flags = shdr[i].sh_flags;
2167 if (s->flags & SHF_COMPRESSED) {
2168 s->size = uncompress_debug_section(&shdr[i], file, &s->ptr);
2169 if (!s->size)
goto fail;
2181 if (dynsym_shdr && dynstr_shdr) {
2182 char *strtab = file + dynstr_shdr->sh_offset;
2183 ElfW(Sym) *symtab = (ElfW(Sym) *)(file + dynsym_shdr->sh_offset);
2184 int symtab_count = (int)(dynsym_shdr->sh_size /
sizeof(ElfW(Sym)));
2185 void *handle = dlopen(NULL, RTLD_NOW|RTLD_LOCAL);
2187 for (j = 0; j < symtab_count; j++) {
2188 ElfW(Sym) *sym = &symtab[j];
2191 if (ELF_ST_TYPE(sym->st_info) != STT_FUNC || sym->st_size == 0)
continue;
2192 s = dlsym(handle, strtab + sym->st_name);
2193 if (s && dladdr(s, &info)) {
2194 obj->base_addr = dladdr_fbase;
2195 dladdr_fbase = (uintptr_t)info.dli_fbase;
2201 if (ehdr->e_type == ET_EXEC) {
2206 obj->base_addr = dladdr_fbase;
2211 if (obj->debug_info.ptr && obj->debug_abbrev.ptr) {
2212 DebugInfoReader reader;
2213 debug_info_reader_init(&reader, obj);
2215 while (reader.p < reader.pend) {
2217 if (di_read_cu(&reader, errout))
goto use_symtab;
2218 if (!debug_info_read(&reader, num_traces, traces, lines, offset, errout))
2227 symtab_shdr = dynsym_shdr;
2228 strtab_shdr = dynstr_shdr;
2231 if (symtab_shdr && strtab_shdr) {
2232 char *strtab = file + strtab_shdr->sh_offset;
2233 ElfW(Sym) *symtab = (ElfW(Sym) *)(file + symtab_shdr->sh_offset);
2234 int symtab_count = (int)(symtab_shdr->sh_size /
sizeof(ElfW(Sym)));
2235 for (j = 0; j < symtab_count; j++) {
2236 ElfW(Sym) *sym = &symtab[j];
2237 uintptr_t saddr = (uintptr_t)sym->st_value + obj->base_addr;
2238 if (ELF_ST_TYPE(sym->st_info) != STT_FUNC)
continue;
2239 for (i = offset; i < num_traces; i++) {
2240 uintptr_t d = (uintptr_t)traces[i] - saddr;
2241 if (lines[i].line > 0 || d > (uintptr_t)sym->st_size)
2244 if (!lines[i].sname) lines[i].sname = strtab + sym->st_name;
2245 lines[i].saddr = saddr;
2246 lines[i].path = obj->path;
2247 lines[i].base_addr = obj->base_addr;
2253 if (!obj->debug_line.ptr) {
2256 if (gnu_debuglink_shdr && check_debuglink) {
2257 follow_debuglink(file + gnu_debuglink_shdr->sh_offset,
2259 objp, lines, offset, errout);
2261 if (note_gnu_build_id && check_debuglink) {
2262 ElfW(Nhdr) *nhdr = (ElfW(Nhdr)*) (file + note_gnu_build_id->sh_offset);
2263 const char *build_id = (
char *)(nhdr + 1) + nhdr->n_namesz;
2264 follow_debuglink_build_id(build_id, nhdr->n_descsz,
2266 objp, lines, offset, errout);
2271 if (parse_debug_line(num_traces, traces,
2272 obj->debug_line.ptr,
2273 obj->debug_line.size,
2274 obj, lines, offset, errout) == -1)
2278 return dladdr_fbase;
2280 return (uintptr_t)-1;
2285fill_lines(
int num_traces,
void **traces,
int check_debuglink,
2286 obj_info_t **objp, line_info_t *lines,
int offset,
FILE *errout)
2289# define LP(x) x##_64
2295 char *file, *p = NULL;
2296 obj_info_t *obj = *objp;
2297 struct LP(mach_header) *header;
2298 uintptr_t dladdr_fbase = 0;
2301 char *s = binary_filename;
2302 char *base = strrchr(binary_filename,
'/')+1;
2303 size_t max = PATH_MAX;
2304 size_t size = strlen(binary_filename);
2305 size_t basesize = size - (base - binary_filename);
2309 size = strlcpy(s,
".dSYM/Contents/Resources/DWARF/", max);
2310 if (size == 0)
goto fail;
2313 if (max <= basesize)
goto fail;
2314 memcpy(s, base, basesize);
2317 fd = open(binary_filename, O_RDONLY);
2320 fd = open(binary_filename, O_RDONLY);
2327 filesize = lseek(fd, 0, SEEK_END);
2331 kprintf(
"lseek: %s\n", strerror(e));
2334#if SIZEOF_OFF_T > SIZEOF_SIZE_T
2335 if (filesize > (off_t)SIZE_MAX) {
2337 kprintf(
"Too large file %s\n", binary_filename);
2341 lseek(fd, 0, SEEK_SET);
2343 file = (
char *)mmap(NULL, (
size_t)filesize, PROT_READ, MAP_SHARED, fd, 0);
2344 if (file == MAP_FAILED) {
2347 kprintf(
"mmap: %s\n", strerror(e));
2353 obj->mapped_size = (size_t)filesize;
2355 header = (
struct LP(mach_header) *)file;
2356 if (header->magic == LP(MH_MAGIC)) {
2360 else if (header->magic == FAT_CIGAM) {
2361 struct LP(mach_header) *mhp = _NSGetMachExecuteHeader();
2362 struct fat_header *fat = (
struct fat_header *)file;
2363 char *q = file +
sizeof(*fat);
2364 uint32_t nfat_arch = __builtin_bswap32(fat->nfat_arch);
2366 for (uint32_t i = 0; i < nfat_arch; i++) {
2367 struct fat_arch *arch = (
struct fat_arch *)q;
2368 cpu_type_t cputype = __builtin_bswap32(arch->cputype);
2369 cpu_subtype_t cpusubtype = __builtin_bswap32(arch->cpusubtype);
2370 uint32_t offset = __builtin_bswap32(arch->offset);
2372 if (mhp->cputype == cputype &&
2373 (cpu_subtype_t)(mhp->cpusubtype & ~CPU_SUBTYPE_MASK) == cpusubtype) {
2376 header = (
struct LP(mach_header) *)p;
2377 if (header->magic == LP(MH_MAGIC)) {
2378 goto found_mach_header;
2384 kprintf(
"'%s' is not a Mach-O universal binary file!\n",binary_filename);
2390# define bitsize "64"
2392# define bitsize "32"
2394 kprintf(
"'%s' is not a " bitsize
2395 "-bit Mach-O file!\n",binary_filename);
2401 p +=
sizeof(*header);
2403 for (uint32_t i = 0; i < (uint32_t)header->ncmds; i++) {
2404 struct load_command *lcmd = (
struct load_command *)p;
2405 switch (lcmd->cmd) {
2406 case LP(LC_SEGMENT):
2408 static const char *debug_section_names[] = {
2413 "__debug_str_offsets",
2419 struct LP(segment_command) *scmd = (
struct LP(segment_command) *)lcmd;
2420 if (strcmp(scmd->segname,
"__TEXT") == 0) {
2421 obj->vmaddr = scmd->vmaddr;
2423 else if (strcmp(scmd->segname,
"__DWARF") == 0) {
2424 p +=
sizeof(
struct LP(segment_command));
2425 for (uint64_t i = 0; i < scmd->nsects; i++) {
2426 struct LP(section) *sect = (
struct LP(section) *)p;
2427 p +=
sizeof(
struct LP(section));
2428 for (
int j=0; j < DWARF_SECTION_COUNT; j++) {
2429 struct dwarf_section *s = obj_dwarf_section_at(obj, j);
2431 if (strcmp(sect->sectname, debug_section_names[j]) != 0
2439 && strncmp(sect->sectname, debug_section_names[j], 16) != 0
2444 s->ptr = file + sect->offset;
2445 s->size = sect->size;
2446 s->flags = sect->flags;
2447 if (s->flags & SHF_COMPRESSED) {
2459 struct symtab_command *cmd = (
struct symtab_command *)lcmd;
2460 struct LP(nlist) *nl = (
struct LP(nlist) *)(file + cmd->symoff);
2461 char *strtab = file + cmd->stroff, *sname = 0;
2463 uintptr_t saddr = 0;
2465 for (j = 0; j < cmd->nsyms; j++) {
2466 uintptr_t symsize, d;
2467 struct LP(nlist) *e = &nl[j];
2469 if (e->n_type != N_FUN)
continue;
2471 saddr = (uintptr_t)e->n_value + obj->base_addr - obj->vmaddr;
2472 sname = strtab + e->n_un.n_strx;
2476 for (
int k = offset; k < num_traces; k++) {
2477 d = (uintptr_t)traces[k] - saddr;
2478 symsize = e->n_value;
2480 if (lines[k].line > 0 || d > (uintptr_t)symsize)
2483 if (!lines[k].sname) lines[k].sname = sname;
2484 lines[k].saddr = saddr;
2485 lines[k].path = obj->path;
2486 lines[k].base_addr = obj->base_addr;
2494 if (obj->debug_info.ptr && obj->debug_abbrev.ptr) {
2495 DebugInfoReader reader;
2496 debug_info_reader_init(&reader, obj);
2497 while (reader.p < reader.pend) {
2498 if (di_read_cu(&reader, errout))
goto fail;
2499 if (!debug_info_read(&reader, num_traces, traces, lines, offset, errout))
2504 if (parse_debug_line(num_traces, traces,
2505 obj->debug_line.ptr,
2506 obj->debug_line.size,
2507 obj, lines, offset, errout) == -1)
2510 return dladdr_fbase;
2512 return (uintptr_t)-1;
2516#define HAVE_MAIN_EXE_PATH
2517#if defined(__FreeBSD__) || defined(__DragonFly__)
2518# include <sys/sysctl.h>
2526#if defined(__linux__) || defined(__NetBSD__)
2528main_exe_path(
FILE *errout)
2530# if defined(__linux__)
2531# define PROC_SELF_EXE "/proc/self/exe"
2532# elif defined(__NetBSD__)
2533# define PROC_SELF_EXE "/proc/curproc/exe"
2535 ssize_t
len = readlink(PROC_SELF_EXE, binary_filename, PATH_MAX);
2536 if (
len < 0)
return 0;
2537 binary_filename[
len] = 0;
2540#elif defined(__FreeBSD__) || defined(__DragonFly__)
2542main_exe_path(
FILE *errout)
2544 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
2545 size_t len = PATH_MAX;
2546 int err = sysctl(mib, 4, binary_filename, &
len, NULL, 0);
2548 kprintf(
"Can't get the path of ruby");
2554#elif defined(HAVE_LIBPROC_H)
2556main_exe_path(
FILE *errout)
2558 int len = proc_pidpath(getpid(), binary_filename, PATH_MAX);
2559 if (
len == 0)
return 0;
2560 binary_filename[
len] = 0;
2564#undef HAVE_MAIN_EXE_PATH
2568print_line0(line_info_t *line,
void *address,
FILE *errout)
2570 uintptr_t addr = (uintptr_t)address;
2571 uintptr_t d = addr - line->saddr;
2574 if (line->dirname && line->dirname[0]) {
2575 kprintf(
"%s(%s) %s/%s:%d\n", line->path, line->sname, line->dirname, line->filename, line->line);
2578 kprintf(
"%s(%s) %s:%d\n", line->path, line->sname, line->filename, line->line);
2581 else if (!line->path) {
2582 kprintf(
"[0x%"PRIxPTR
"]\n", addr);
2584 else if (!line->sname) {
2585 kprintf(
"%s(0x%"PRIxPTR
") [0x%"PRIxPTR
"]\n", line->path, addr-line->base_addr, addr);
2587 else if (!line->saddr) {
2588 kprintf(
"%s(%s) [0x%"PRIxPTR
"]\n", line->path, line->sname, addr);
2590 else if (line->line <= 0) {
2591 kprintf(
"%s(%s+0x%"PRIxPTR
") [0x%"PRIxPTR
"]\n", line->path, line->sname,
2594 else if (!line->filename) {
2595 kprintf(
"%s(%s+0x%"PRIxPTR
") [0x%"PRIxPTR
"] ???:%d\n", line->path, line->sname,
2596 d, addr, line->line);
2598 else if (line->dirname && line->dirname[0]) {
2599 kprintf(
"%s(%s+0x%"PRIxPTR
") [0x%"PRIxPTR
"] %s/%s:%d\n", line->path, line->sname,
2600 d, addr, line->dirname, line->filename, line->line);
2603 kprintf(
"%s(%s+0x%"PRIxPTR
") [0x%"PRIxPTR
"] %s:%d\n", line->path, line->sname,
2604 d, addr, line->filename, line->line);
2609print_line(line_info_t *line,
void *address,
FILE *errout)
2611 print_line0(line, address, errout);
2613 print_line(line->next, NULL, errout);
2618rb_dump_backtrace_with_lines(
int num_traces,
void **traces,
FILE *errout)
2622 line_info_t *lines = (line_info_t *)calloc(num_traces,
sizeof(line_info_t));
2623 obj_info_t *obj = NULL;
2625 void **dladdr_fbases = (
void **)calloc(num_traces+2,
sizeof(
void *));
2627#ifdef HAVE_MAIN_EXE_PATH
2628 char *main_path = NULL;
2630 if ((
len = main_exe_path(errout)) > 0) {
2631 main_path = (
char *)alloca(
len + 1);
2634 memcpy(main_path, binary_filename,
len+1);
2636 obj->path = main_path;
2637 addr = fill_lines(num_traces, traces, 1, &obj, lines, 0, errout);
2638 if (addr != (uintptr_t)-1) {
2639 dladdr_fbases[0] = (
void *)addr;
2646 for (i = 0; i < num_traces; i++) {
2648 if (lines[i].line)
continue;
2649 if (dladdr(traces[i], &info)) {
2655 for (p=dladdr_fbases; *p; p++) {
2656 if (*p == info.dli_fbase) {
2657 if (info.dli_fname) lines[i].path = info.dli_fname;
2658 if (info.dli_sname) lines[i].sname = info.dli_sname;
2662 *p = info.dli_fbase;
2665 obj->base_addr = (uintptr_t)info.dli_fbase;
2666 path = info.dli_fname;
2668 if (path) lines[i].path = path;
2669 if (info.dli_sname) {
2670 lines[i].sname = info.dli_sname;
2671 lines[i].saddr = (uintptr_t)info.dli_saddr;
2673 strlcpy(binary_filename, path, PATH_MAX);
2674 if (fill_lines(num_traces, traces, 1, &obj, lines, i, errout) == (uintptr_t)-1)
2682 for (i = 0; i < num_traces; i++) {
2683 print_line(&lines[i], traces[i], errout);
2686 if (lines[i].sname && strcmp(
"main", lines[i].sname) == 0)
2692 obj_info_t *o = obj;
2693 for (i=0; i < DWARF_SECTION_COUNT; i++) {
2694 struct dwarf_section *s = obj_dwarf_section_at(obj, i);
2695 if (s->flags & SHF_COMPRESSED) {
2699 if (obj->mapped_size) {
2700 munmap(obj->mapped, obj->mapped_size);
2705 for (i = 0; i < num_traces; i++) {
2706 line_info_t *line = lines[i].next;
2708 line_info_t *l = line;
2714 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.