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
89# ifdef HAVE_CRT_EXTERNS_H
90# include <crt_externs.h>
92# include "missing/crt_externs.h"
93extern struct LP(mach_header) *_NSGetMachExecuteHeader(
void);
95# include <mach-o/fat.h>
96# include <mach-o/loader.h>
97# include <mach-o/nlist.h>
98# include <mach-o/stab.h>
109# if SIZEOF_VOIDP == 8
110# define ElfW(x) Elf64##_##x
112# define ElfW(x) Elf32##_##x
116# if SIZEOF_VOIDP == 8
117# define ELF_ST_TYPE ELF64_ST_TYPE
119# define ELF_ST_TYPE ELF32_ST_TYPE
125# if defined(ELFCOMPRESS_ZLIB) && defined(HAVE_LIBZ)
128# define SUPPORT_COMPRESSED_DEBUG_LINE
131# define SHF_COMPRESSED 0
138#define DW_LNS_copy 0x01
139#define DW_LNS_advance_pc 0x02
140#define DW_LNS_advance_line 0x03
141#define DW_LNS_set_file 0x04
142#define DW_LNS_set_column 0x05
143#define DW_LNS_negate_stmt 0x06
144#define DW_LNS_set_basic_block 0x07
145#define DW_LNS_const_add_pc 0x08
146#define DW_LNS_fixed_advance_pc 0x09
147#define DW_LNS_set_prologue_end 0x0a
148#define DW_LNS_set_epilogue_begin 0x0b
149#define DW_LNS_set_isa 0x0c
152#define DW_LNE_end_sequence 0x01
153#define DW_LNE_set_address 0x02
154#define DW_LNE_define_file 0x03
155#define DW_LNE_set_discriminator 0x04
157#define kprintf(...) fprintf(errout, "" __VA_ARGS__)
159typedef struct line_info {
161 const char *filename;
169 struct line_info *next;
172struct dwarf_section {
178typedef struct obj_info {
185 struct dwarf_section debug_abbrev;
186 struct dwarf_section debug_info;
187 struct dwarf_section debug_line;
188 struct dwarf_section debug_ranges;
189 struct dwarf_section debug_str_offsets;
190 struct dwarf_section debug_addr;
191 struct dwarf_section debug_rnglists;
192 struct dwarf_section debug_str;
193 struct dwarf_section debug_line_str;
194 struct obj_info *next;
197#define DWARF_SECTION_COUNT 9
199static struct dwarf_section *
200obj_dwarf_section_at(obj_info_t *obj,
int n)
202 struct dwarf_section *ary[] = {
207 &obj->debug_str_offsets,
209 &obj->debug_rnglists,
213 if (n < 0 || DWARF_SECTION_COUNT <= n) {
219struct debug_section_definition {
221 struct dwarf_section *dwarf;
225static char binary_filename[PATH_MAX + 1];
228uleb128(
const char **p)
233 unsigned char b = (
unsigned char)*(*p)++;
235 r += (
unsigned long)b << s;
238 r += (b & 0x7f) << s;
245sleb128(
const char **p)
250 unsigned char b = (
unsigned char)*(*p)++;
253 r -= (0x80 - b) << s;
256 r += (b & 0x3f) << s;
260 r += (b & 0x7f) << s;
267get_nth_dirname(
unsigned long dir,
const char *p,
FILE *errout)
276 kprintf(
"Unexpected directory number %lu in %s\n",
277 dir, binary_filename);
284static const char *parse_ver5_debug_line_header(
285 const char *p,
int idx, uint8_t format,
286 obj_info_t *obj,
const char **out_path,
287 uint64_t *out_directory_index,
FILE *errout);
290fill_filename(
int file, uint8_t format, uint16_t version,
const char *include_directories,
291 const char *filenames, line_info_t *line, obj_info_t *obj,
FILE *errout)
294 const char *p = filenames;
295 const char *filename;
299 uint64_t directory_index = -1;
300 parse_ver5_debug_line_header(filenames, file, format, obj, &path, &directory_index, errout);
301 line->filename = path;
302 parse_ver5_debug_line_header(include_directories, (
int)directory_index, format, obj, &path, NULL, errout);
303 line->dirname = path;
306 for (i = 1; i <= file; i++) {
311 kprintf(
"Unexpected file number %d in %s at %tx\n",
312 file, binary_filename, filenames - obj->mapped);
325 line->filename = filename;
326 line->dirname = get_nth_dirname(dir, include_directories, errout);
333fill_line(
int num_traces,
void **traces, uintptr_t addr,
int file,
int line,
334 uint8_t format, uint16_t version,
const char *include_directories,
const char *filenames,
335 obj_info_t *obj, line_info_t *lines,
int offset,
FILE *errout)
338 addr += obj->base_addr - obj->vmaddr;
339 for (i = offset; i < num_traces; i++) {
340 uintptr_t a = (uintptr_t)traces[i];
343 if (addr < a && a < addr + 100) {
344 fill_filename(file, format, version, include_directories, filenames, &lines[i], obj, errout);
345 lines[i].line = line;
350struct LineNumberProgramHeader {
351 uint64_t unit_length;
354 uint64_t header_length;
355 uint8_t minimum_instruction_length;
356 uint8_t maximum_operations_per_instruction;
357 uint8_t default_is_stmt;
362 const char *include_directories;
363 const char *filenames;
364 const char *cu_start;
369parse_debug_line_header(obj_info_t *obj,
const char **pp,
struct LineNumberProgramHeader *header,
FILE *errout)
372 header->unit_length = *(uint32_t *)p;
373 p +=
sizeof(uint32_t);
376 if (header->unit_length == 0xffffffff) {
377 header->unit_length = *(uint64_t *)p;
378 p +=
sizeof(uint64_t);
382 header->cu_end = p + header->unit_length;
384 header->version = *(uint16_t *)p;
385 p +=
sizeof(uint16_t);
386 if (header->version > 5)
return -1;
388 if (header->version >= 5) {
394 header->header_length = header->format == 4 ? *(uint32_t *)p : *(uint64_t *)p;
396 header->cu_start = p + header->header_length;
398 header->minimum_instruction_length = *(uint8_t *)p++;
400 if (header->version >= 4) {
402 if (*p != 1)
return -1;
406 header->default_is_stmt = *(uint8_t *)p++;
407 header->line_base = *(int8_t *)p++;
408 header->line_range = *(uint8_t *)p++;
409 header->opcode_base = *(uint8_t *)p++;
411 p += header->opcode_base - 1;
413 if (header->version >= 5) {
414 header->include_directories = p;
415 p = parse_ver5_debug_line_header(p, -1, header->format, obj, NULL, NULL, errout);
416 header->filenames = p;
419 header->include_directories = p;
422 if (p >= header->cu_end)
return -1;
426 p = memchr(p,
'\0', header->cu_end - p);
432 header->filenames = p;
435 *pp = header->cu_start;
441parse_debug_line_cu(
int num_traces,
void **traces,
const char **debug_line,
442 obj_info_t *obj, line_info_t *lines,
int offset,
FILE *errout)
444 const char *p = (
const char *)*debug_line;
445 struct LineNumberProgramHeader header;
448 unsigned long addr = 0;
449 unsigned int file = 1;
450 unsigned int line = 1;
459 if (parse_debug_line_header(obj, &p, &header, errout))
461 is_stmt = header.default_is_stmt;
465 fill_line(num_traces, traces, addr, file, line, \
468 header.include_directories, \
470 obj, lines, offset, errout); \
474 while (p < header.cu_end) {
476 unsigned char op = *p++;
481 case DW_LNS_advance_pc:
482 a = uleb128(&p) * header.minimum_instruction_length;
485 case DW_LNS_advance_line: {
486 long a = sleb128(&p);
490 case DW_LNS_set_file:
491 file = (
unsigned int)uleb128(&p);
493 case DW_LNS_set_column:
496 case DW_LNS_negate_stmt:
499 case DW_LNS_set_basic_block:
502 case DW_LNS_const_add_pc:
503 a = ((255UL - header.opcode_base) / header.line_range) *
504 header.minimum_instruction_length;
507 case DW_LNS_fixed_advance_pc:
509 p +=
sizeof(uint16_t);
512 case DW_LNS_set_prologue_end:
515 case DW_LNS_set_epilogue_begin:
525 case DW_LNE_end_sequence:
532 is_stmt = header.default_is_stmt;
536 case DW_LNE_set_address:
537 addr = *(
unsigned long *)p;
538 p +=
sizeof(
unsigned long);
540 case DW_LNE_define_file:
541 kprintf(
"Unsupported operation in %s\n",
544 case DW_LNE_set_discriminator:
549 kprintf(
"Unknown extended opcode: %d in %s\n",
550 op, binary_filename);
554 uint8_t adjusted_opcode = op - header.opcode_base;
555 uint8_t operation_advance = adjusted_opcode / header.line_range;
557 addr += operation_advance * header.minimum_instruction_length;
558 line += header.line_base + (adjusted_opcode % header.line_range);
563 *debug_line = (
char *)p;
568parse_debug_line(
int num_traces,
void **traces,
569 const char *debug_line,
unsigned long size,
570 obj_info_t *obj, line_info_t *lines,
int offset,
FILE *errout)
572 const char *debug_line_end = debug_line + size;
573 while (debug_line < debug_line_end) {
574 if (parse_debug_line_cu(num_traces, traces, &debug_line, obj, lines, offset, errout))
577 if (debug_line != debug_line_end) {
578 kprintf(
"Unexpected size of .debug_line in %s\n",
586fill_lines(
int num_traces,
void **traces,
int check_debuglink,
587 obj_info_t **objp, line_info_t *lines,
int offset,
FILE *errout);
590append_obj(obj_info_t **objp)
592 obj_info_t *newobj = calloc(1,
sizeof(obj_info_t));
593 if (*objp) (*objp)->next = newobj;
614follow_debuglink(
const char *debuglink,
int num_traces,
void **traces,
615 obj_info_t **objp, line_info_t *lines,
int offset,
FILE *errout)
617 static const char global_debug_dir[] =
"/usr/lib/debug";
618 const size_t global_debug_dir_len =
sizeof(global_debug_dir) - 1;
620 obj_info_t *o1 = *objp, *o2;
623 p = strrchr(binary_filename,
'/');
629 len = strlen(binary_filename);
630 if (
len >= PATH_MAX - global_debug_dir_len)
631 len = PATH_MAX - global_debug_dir_len - 1;
632 memmove(binary_filename + global_debug_dir_len, binary_filename,
len);
633 memcpy(binary_filename, global_debug_dir, global_debug_dir_len);
634 len += global_debug_dir_len;
635 strlcpy(binary_filename +
len, debuglink, PATH_MAX -
len);
639 o2->base_addr = o1->base_addr;
641 fill_lines(num_traces, traces, 0, objp, lines, offset, errout);
646follow_debuglink_build_id(
const char *build_id,
size_t build_id_size,
int num_traces,
void **traces,
647 obj_info_t **objp, line_info_t *lines,
int offset,
FILE *errout)
649 static const char global_debug_dir[] =
"/usr/lib/debug/.build-id/";
650 static const char debug_suffix[] =
".debug";
651 const size_t global_debug_dir_len =
sizeof(global_debug_dir) - 1;
653 obj_info_t *o1 = *objp, *o2;
656 if (PATH_MAX < global_debug_dir_len + build_id_size * 2 +
sizeof(debug_suffix))
return;
658 memcpy(binary_filename, global_debug_dir, global_debug_dir_len);
659 p = binary_filename + global_debug_dir_len;
660 for (i = 0; i < build_id_size; i++) {
661 static const char tbl[] =
"0123456789abcdef";
662 unsigned char n = build_id[i];
665 if (i == 0) *p++ =
'/';
667 memcpy(p, debug_suffix,
sizeof(debug_suffix));
671 o2->base_addr = o1->base_addr;
673 fill_lines(num_traces, traces, 0, objp, lines, offset, errout);
679 DW_TAG_compile_unit = 0x11,
680 DW_TAG_inlined_subroutine = 0x1d,
681 DW_TAG_subprogram = 0x2e,
687 DW_AT_sibling = 0x01,
688 DW_AT_location = 0x02,
695 DW_AT_ordering = 0x09,
697 DW_AT_byte_size = 0x0b,
699 DW_AT_bit_size = 0x0d,
702 DW_AT_stmt_list = 0x10,
704 DW_AT_high_pc = 0x12,
705 DW_AT_language = 0x13,
708 DW_AT_discr_value = 0x16,
709 DW_AT_visibility = 0x17,
711 DW_AT_string_length = 0x19,
712 DW_AT_common_reference = 0x1a,
713 DW_AT_comp_dir = 0x1b,
714 DW_AT_const_value = 0x1c,
715 DW_AT_containing_type = 0x1d,
716 DW_AT_default_value = 0x1e,
719 DW_AT_is_optional = 0x21,
720 DW_AT_lower_bound = 0x22,
723 DW_AT_producer = 0x25,
725 DW_AT_prototyped = 0x27,
728 DW_AT_return_addr = 0x2a,
730 DW_AT_start_scope = 0x2c,
732 DW_AT_bit_stride = 0x2e,
733 DW_AT_upper_bound = 0x2f,
735 DW_AT_abstract_origin = 0x31,
736 DW_AT_accessibility = 0x32,
737 DW_AT_address_class = 0x33,
738 DW_AT_artificial = 0x34,
739 DW_AT_base_types = 0x35,
740 DW_AT_calling_convention = 0x36,
742 DW_AT_data_member_location = 0x38,
743 DW_AT_decl_column = 0x39,
744 DW_AT_decl_file = 0x3a,
745 DW_AT_decl_line = 0x3b,
746 DW_AT_declaration = 0x3c,
747 DW_AT_discr_list = 0x3d,
748 DW_AT_encoding = 0x3e,
749 DW_AT_external = 0x3f,
750 DW_AT_frame_base = 0x40,
752 DW_AT_identifier_case = 0x42,
754 DW_AT_namelist_item = 0x44,
755 DW_AT_priority = 0x45,
756 DW_AT_segment = 0x46,
757 DW_AT_specification = 0x47,
758 DW_AT_static_link = 0x48,
760 DW_AT_use_location = 0x4a,
761 DW_AT_variable_parameter = 0x4b,
762 DW_AT_virtuality = 0x4c,
763 DW_AT_vtable_elem_location = 0x4d,
764 DW_AT_allocated = 0x4e,
765 DW_AT_associated = 0x4f,
766 DW_AT_data_location = 0x50,
767 DW_AT_byte_stride = 0x51,
768 DW_AT_entry_pc = 0x52,
769 DW_AT_use_UTF8 = 0x53,
770 DW_AT_extension = 0x54,
772 DW_AT_trampoline = 0x56,
773 DW_AT_call_column = 0x57,
774 DW_AT_call_file = 0x58,
775 DW_AT_call_line = 0x59,
776 DW_AT_description = 0x5a,
777 DW_AT_binary_scale = 0x5b,
778 DW_AT_decimal_scale = 0x5c,
780 DW_AT_decimal_sign = 0x5e,
781 DW_AT_digit_count = 0x5f,
782 DW_AT_picture_string = 0x60,
783 DW_AT_mutable = 0x61,
784 DW_AT_threads_scaled = 0x62,
785 DW_AT_explicit = 0x63,
786 DW_AT_object_pointer = 0x64,
787 DW_AT_endianity = 0x65,
788 DW_AT_elemental = 0x66,
790 DW_AT_recursive = 0x68,
791 DW_AT_signature = 0x69,
792 DW_AT_main_subprogram = 0x6a,
793 DW_AT_data_bit_offset = 0x6b,
794 DW_AT_const_expr = 0x6c,
795 DW_AT_enum_class = 0x6d,
796 DW_AT_linkage_name = 0x6e,
797 DW_AT_string_length_bit_size = 0x6f,
798 DW_AT_string_length_byte_size = 0x70,
800 DW_AT_str_offsets_base = 0x72,
801 DW_AT_addr_base = 0x73,
802 DW_AT_rnglists_base = 0x74,
804 DW_AT_dwo_name = 0x76,
805 DW_AT_reference = 0x77,
806 DW_AT_rvalue_reference = 0x78,
808 DW_AT_call_all_calls = 0x7a,
809 DW_AT_call_all_source_calls = 0x7b,
810 DW_AT_call_all_tail_calls = 0x7c,
811 DW_AT_call_return_pc = 0x7d,
812 DW_AT_call_value = 0x7e,
813 DW_AT_call_origin = 0x7f,
814 DW_AT_call_parameter = 0x80,
815 DW_AT_call_pc = 0x81,
816 DW_AT_call_tail_call = 0x82,
817 DW_AT_call_target = 0x83,
818 DW_AT_call_target_clobbered = 0x84,
819 DW_AT_call_data_location = 0x85,
820 DW_AT_call_data_value = 0x86,
821 DW_AT_noreturn = 0x87,
822 DW_AT_alignment = 0x88,
823 DW_AT_export_symbols = 0x89,
824 DW_AT_deleted = 0x8a,
825 DW_AT_defaulted = 0x8b,
826 DW_AT_loclists_base = 0x8c,
827 DW_AT_lo_user = 0x2000,
828 DW_AT_hi_user = 0x3fff
836 DW_FORM_block2 = 0x03,
837 DW_FORM_block4 = 0x04,
838 DW_FORM_data2 = 0x05,
839 DW_FORM_data4 = 0x06,
840 DW_FORM_data8 = 0x07,
841 DW_FORM_string = 0x08,
842 DW_FORM_block = 0x09,
843 DW_FORM_block1 = 0x0a,
844 DW_FORM_data1 = 0x0b,
846 DW_FORM_sdata = 0x0d,
848 DW_FORM_udata = 0x0f,
849 DW_FORM_ref_addr = 0x10,
854 DW_FORM_ref_udata = 0x15,
855 DW_FORM_indirect = 0x16,
856 DW_FORM_sec_offset = 0x17,
857 DW_FORM_exprloc = 0x18,
858 DW_FORM_flag_present = 0x19,
860 DW_FORM_addrx = 0x1b,
861 DW_FORM_ref_sup4 = 0x1c,
862 DW_FORM_strp_sup = 0x1d,
863 DW_FORM_data16 = 0x1e,
864 DW_FORM_line_strp = 0x1f,
865 DW_FORM_ref_sig8 = 0x20,
866 DW_FORM_implicit_const = 0x21,
867 DW_FORM_loclistx = 0x22,
868 DW_FORM_rnglistx = 0x23,
869 DW_FORM_ref_sup8 = 0x24,
870 DW_FORM_strx1 = 0x25,
871 DW_FORM_strx2 = 0x26,
872 DW_FORM_strx3 = 0x27,
873 DW_FORM_strx4 = 0x28,
874 DW_FORM_addrx1 = 0x29,
875 DW_FORM_addrx2 = 0x2a,
876 DW_FORM_addrx3 = 0x2b,
877 DW_FORM_addrx4 = 0x2c,
880 DW_FORM_GNU_ref_alt = 0x1f20,
881 DW_FORM_GNU_strp_alt = 0x1f21
886 DW_RLE_end_of_list = 0x00,
887 DW_RLE_base_addressx = 0x01,
888 DW_RLE_startx_endx = 0x02,
889 DW_RLE_startx_length = 0x03,
890 DW_RLE_offset_pair = 0x04,
891 DW_RLE_base_address = 0x05,
892 DW_RLE_start_end = 0x06,
893 DW_RLE_start_length = 0x07
905# define ABBREV_TABLE_SIZE 256
909 uint8_t current_version;
910 const char *current_cu;
911 uint64_t current_low_pc;
912 uint64_t current_str_offsets_base;
913 uint64_t current_addr_base;
914 uint64_t current_rnglists_base;
915 const char *debug_line_cu_end;
916 uint8_t debug_line_format;
917 uint16_t debug_line_version;
918 const char *debug_line_files;
919 const char *debug_line_directories;
926 uint8_t address_size;
928 const char *abbrev_table[ABBREV_TABLE_SIZE];
951#if defined(WORDS_BIGENDIAN)
952#define MERGE_2INTS(a,b,sz) (((uint64_t)(a)<<sz)|(b))
954#define MERGE_2INTS(a,b,sz) (((uint64_t)(b)<<sz)|(a))
958get_uint16(
const uint8_t *p)
960 return (uint16_t)MERGE_2INTS(p[0],p[1],8);
964get_uint32(
const uint8_t *p)
966 return (uint32_t)MERGE_2INTS(get_uint16(p),get_uint16(p+2),16);
970get_uint64(
const uint8_t *p)
972 return MERGE_2INTS(get_uint32(p),get_uint32(p+4),32);
976read_uint8(
const char **ptr)
978 const char *p = *ptr;
984read_uint16(
const char **ptr)
986 const char *p = *ptr;
988 return get_uint16((
const uint8_t *)p);
992read_uint24(
const char **ptr)
994 const char *p = *ptr;
996 return ((uint8_t)*p << 16) | get_uint16((
const uint8_t *)p+1);
1000read_uint32(
const char **ptr)
1002 const char *p = *ptr;
1004 return get_uint32((
const uint8_t *)p);
1008read_uint64(
const char **ptr)
1010 const unsigned char *p = (
const unsigned char *)*ptr;
1011 *ptr = (
char *)(p + 8);
1012 return get_uint64(p);
1016read_uintptr(
const char **ptr)
1018 const unsigned char *p = (
const unsigned char *)*ptr;
1019 *ptr = (
char *)(p + SIZEOF_VOIDP);
1020#if SIZEOF_VOIDP == 8
1021 return get_uint64(p);
1023 return get_uint32(p);
1028read_uint(DebugInfoReader *reader)
1030 if (reader->format == 4) {
1031 return read_uint32(&reader->p);
1033 return read_uint64(&reader->p);
1038read_uleb128(DebugInfoReader *reader)
1040 return uleb128(&reader->p);
1044read_sleb128(DebugInfoReader *reader)
1046 return sleb128(&reader->p);
1050debug_info_reader_init(DebugInfoReader *reader, obj_info_t *obj)
1052 reader->file = obj->mapped;
1054 reader->p = obj->debug_info.ptr;
1055 reader->pend = obj->debug_info.ptr + obj->debug_info.size;
1056 reader->debug_line_cu_end = obj->debug_line.ptr;
1057 reader->current_low_pc = 0;
1058 reader->current_str_offsets_base = 0;
1059 reader->current_addr_base = 0;
1060 reader->current_rnglists_base = 0;
1064di_skip_die_attributes(
const char **p)
1067 uint64_t at = uleb128(p);
1068 uint64_t form = uleb128(p);
1069 if (!at && !form)
break;
1073 case DW_FORM_implicit_const:
1081di_read_debug_abbrev_cu(DebugInfoReader *reader)
1084 const char *p = reader->q0;
1086 uint64_t abbrev_number = uleb128(&p);
1087 if (abbrev_number <= prev)
break;
1088 if (abbrev_number < ABBREV_TABLE_SIZE) {
1089 reader->abbrev_table[abbrev_number] = p;
1091 prev = abbrev_number;
1094 di_skip_die_attributes(&p);
1099di_read_debug_line_cu(DebugInfoReader *reader,
FILE *errout)
1102 struct LineNumberProgramHeader header;
1104 p = (
const char *)reader->debug_line_cu_end;
1105 if (parse_debug_line_header(reader->obj, &p, &header, errout))
1108 reader->debug_line_cu_end = (
char *)header.cu_end;
1109 reader->debug_line_format = header.format;
1110 reader->debug_line_version = header.version;
1111 reader->debug_line_directories = (
char *)header.include_directories;
1112 reader->debug_line_files = (
char *)header.filenames;
1118set_addr_idx_value(DebugInfoValue *v, uint64_t n)
1125set_uint_value(DebugInfoValue *v, uint64_t n)
1132set_int_value(DebugInfoValue *v, int64_t n)
1139set_cstr_value(DebugInfoValue *v,
const char *s)
1147set_cstrp_value(DebugInfoValue *v,
const char *s, uint64_t
off)
1155set_data_value(DebugInfoValue *v,
const char *s)
1162get_cstr_value(DebugInfoValue *v)
1165 return v->as.ptr + v->off;
1172resolve_strx(DebugInfoReader *reader, uint64_t idx)
1174 const char *p = reader->obj->debug_str_offsets.ptr + reader->current_str_offsets_base;
1176 if (reader->format == 4) {
1177 off = ((uint32_t *)p)[idx];
1180 off = ((uint64_t *)p)[idx];
1182 return reader->obj->debug_str.ptr +
off;
1186debug_info_reader_read_addr_value_member(DebugInfoReader *reader, DebugInfoValue *v,
int size)
1189 set_uint_value(v, read_uint32(&reader->p));
1190 }
else if (size == 8) {
1191 set_uint_value(v, read_uint64(&reader->p));
1198#define debug_info_reader_read_addr_value(reader, v, mem) \
1199 if (!debug_info_reader_read_addr_value_member((reader), (v), (reader)->mem)) { \
1200 kprintf("unknown " #mem ":%d", (reader)->mem); \
1206debug_info_reader_read_value(DebugInfoReader *reader, uint64_t form, DebugInfoValue *v,
FILE *errout)
1210 debug_info_reader_read_addr_value(reader, v, address_size);
1212 case DW_FORM_block2:
1213 v->size = read_uint16(&reader->p);
1214 set_data_value(v, reader->p);
1215 reader->p += v->size;
1217 case DW_FORM_block4:
1218 v->size = read_uint32(&reader->p);
1219 set_data_value(v, reader->p);
1220 reader->p += v->size;
1223 set_uint_value(v, read_uint16(&reader->p));
1226 set_uint_value(v, read_uint32(&reader->p));
1229 set_uint_value(v, read_uint64(&reader->p));
1231 case DW_FORM_string:
1232 v->size = strlen(reader->p);
1233 set_cstr_value(v, reader->p);
1234 reader->p += v->size + 1;
1237 v->size = uleb128(&reader->p);
1238 set_data_value(v, reader->p);
1239 reader->p += v->size;
1241 case DW_FORM_block1:
1242 v->size = read_uint8(&reader->p);
1243 set_data_value(v, reader->p);
1244 reader->p += v->size;
1247 set_uint_value(v, read_uint8(&reader->p));
1250 set_uint_value(v, read_uint8(&reader->p));
1253 set_int_value(v, read_sleb128(reader));
1256 set_cstrp_value(v, reader->obj->debug_str.ptr, read_uint(reader));
1259 set_uint_value(v, read_uleb128(reader));
1261 case DW_FORM_ref_addr:
1262 if (reader->current_version <= 2) {
1265 debug_info_reader_read_addr_value(reader, v, address_size);
1267 debug_info_reader_read_addr_value(reader, v, format);
1271 set_uint_value(v, read_uint8(&reader->p));
1274 set_uint_value(v, read_uint16(&reader->p));
1277 set_uint_value(v, read_uint32(&reader->p));
1280 set_uint_value(v, read_uint64(&reader->p));
1282 case DW_FORM_ref_udata:
1283 set_uint_value(v, uleb128(&reader->p));
1285 case DW_FORM_indirect:
1287 set_uint_value(v, uleb128(&reader->p));
1289 case DW_FORM_sec_offset:
1290 set_uint_value(v, read_uint(reader));
1300 case DW_FORM_exprloc:
1301 v->size = (size_t)read_uleb128(reader);
1302 set_data_value(v, reader->p);
1303 reader->p += v->size;
1305 case DW_FORM_flag_present:
1306 set_uint_value(v, 1);
1309 set_cstr_value(v, resolve_strx(reader, uleb128(&reader->p)));
1312 set_addr_idx_value(v, uleb128(&reader->p));
1314 case DW_FORM_ref_sup4:
1315 set_uint_value(v, read_uint32(&reader->p));
1317 case DW_FORM_strp_sup:
1318 set_uint_value(v, read_uint(reader));
1321 case DW_FORM_data16:
1323 set_data_value(v, reader->p);
1324 reader->p += v->size;
1326 case DW_FORM_line_strp:
1327 set_cstrp_value(v, reader->obj->debug_line_str.ptr, read_uint(reader));
1329 case DW_FORM_ref_sig8:
1330 set_uint_value(v, read_uint64(&reader->p));
1332 case DW_FORM_implicit_const:
1333 set_int_value(v, sleb128(&reader->q));
1335 case DW_FORM_loclistx:
1336 set_uint_value(v, read_uleb128(reader));
1338 case DW_FORM_rnglistx:
1339 set_uint_value(v, read_uleb128(reader));
1341 case DW_FORM_ref_sup8:
1342 set_uint_value(v, read_uint64(&reader->p));
1345 set_cstr_value(v, resolve_strx(reader, read_uint8(&reader->p)));
1348 set_cstr_value(v, resolve_strx(reader, read_uint16(&reader->p)));
1351 set_cstr_value(v, resolve_strx(reader, read_uint24(&reader->p)));
1354 set_cstr_value(v, resolve_strx(reader, read_uint32(&reader->p)));
1356 case DW_FORM_addrx1:
1357 set_addr_idx_value(v, read_uint8(&reader->p));
1359 case DW_FORM_addrx2:
1360 set_addr_idx_value(v, read_uint16(&reader->p));
1362 case DW_FORM_addrx3:
1363 set_addr_idx_value(v, read_uint24(&reader->p));
1365 case DW_FORM_addrx4:
1366 set_addr_idx_value(v, read_uint32(&reader->p));
1371 case DW_FORM_GNU_ref_alt:
1372 case DW_FORM_GNU_strp_alt:
1374 set_uint_value(v, 0);
1383 kprintf(
"%d: unsupported form: %#"PRIx64
"\n", __LINE__, form);
1389di_find_abbrev(DebugInfoReader *reader, uint64_t abbrev_number,
FILE *errout)
1392 if (abbrev_number < ABBREV_TABLE_SIZE) {
1393 return reader->abbrev_table[abbrev_number];
1395 p = reader->abbrev_table[ABBREV_TABLE_SIZE-1];
1399 di_skip_die_attributes(&p);
1400 for (uint64_t n = uleb128(&p); abbrev_number != n; n = uleb128(&p)) {
1402 kprintf(
"%d: Abbrev Number %"PRId64
" not found\n",__LINE__, abbrev_number);
1407 di_skip_die_attributes(&p);
1414hexdump0(
const unsigned char *p,
size_t n,
FILE *errout)
1417 kprintf(
" 0 1 2 3 4 5 6 7 8 9 A B C D E F\n");
1418 for (i=0; i < n; i++){
1421 kprintf(
"%02" PRIdSIZE
": %02X ", i/16, p[i]);
1424 kprintf(
"%02X\n", p[i]);
1427 kprintf(
"%02X ", p[i]);
1431 if ((i & 15) != 15) {
1435#define hexdump(p,n,e) hexdump0((const unsigned char *)p, n, e)
1438div_inspect(DebugInfoValue *v,
FILE *errout)
1442 kprintf(
"%d: type:%d size:%" PRIxSIZE
" v:%"PRIx64
"\n",__LINE__,v->type,v->size,v->as.uint64);
1445 kprintf(
"%d: type:%d size:%" PRIxSIZE
" v:%"PRId64
"\n",__LINE__,v->type,v->size,(int64_t)v->as.uint64);
1448 kprintf(
"%d: type:%d size:%" PRIxSIZE
" v:'%s'\n",__LINE__,v->type,v->size,v->as.ptr);
1451 kprintf(
"%d: type:%d size:%" PRIxSIZE
" v:\n",__LINE__,v->type,v->size);
1452 hexdump(v->as.ptr, 16, errout);
1459di_read_die(DebugInfoReader *reader, DIE *die,
FILE *errout)
1461 uint64_t abbrev_number = uleb128(&reader->p);
1462 if (abbrev_number == 0) {
1467 if (!(reader->q = di_find_abbrev(reader, abbrev_number, errout)))
return NULL;
1469 die->pos = reader->p - reader->obj->debug_info.ptr - 1;
1470 die->tag = (int)uleb128(&reader->q);
1471 die->has_children = *reader->q++;
1472 if (die->has_children) {
1478static DebugInfoValue *
1479di_read_record(DebugInfoReader *reader, DebugInfoValue *vp,
FILE *errout)
1481 uint64_t at = uleb128(&reader->q);
1482 uint64_t form = uleb128(&reader->q);
1483 if (!at || !form)
return NULL;
1486 if (!debug_info_reader_read_value(reader, form, vp, errout))
return NULL;
1491di_skip_records(DebugInfoReader *reader,
FILE *errout)
1494 DebugInfoValue v = {{0}};
1495 uint64_t at = uleb128(&reader->q);
1496 uint64_t form = uleb128(&reader->q);
1497 if (!at || !form)
return true;
1498 if (!debug_info_reader_read_value(reader, form, &v, errout))
return false;
1502typedef struct addr_header {
1504 uint64_t unit_length;
1506 uint8_t address_size;
1511addr_header_init(obj_info_t *obj, addr_header_t *header,
FILE *errout)
1513 const char *p = obj->debug_addr.ptr;
1517 if (!p)
return true;
1519 header->unit_length = *(uint32_t *)p;
1520 p +=
sizeof(uint32_t);
1523 if (header->unit_length == 0xffffffff) {
1524 header->unit_length = *(uint64_t *)p;
1525 p +=
sizeof(uint64_t);
1530 header->address_size = *p++;
1531 if (header->address_size != 4 && header->address_size != 8) {
1532 kprintf(
"unknown address_size:%d", header->address_size);
1540read_addr(addr_header_t *header, uint64_t addr_base, uint64_t idx) {
1541 if (header->address_size == 4) {
1542 return ((uint32_t*)(header->ptr + addr_base))[idx];
1545 return ((uint64_t*)(header->ptr + addr_base))[idx];
1549typedef struct rnglists_header {
1550 uint64_t unit_length;
1552 uint8_t address_size;
1553 uint32_t offset_entry_count;
1557rnglists_header_init(obj_info_t *obj, rnglists_header_t *header,
FILE *errout)
1559 const char *p = obj->debug_rnglists.ptr;
1561 if (!p)
return true;
1563 header->unit_length = *(uint32_t *)p;
1564 p +=
sizeof(uint32_t);
1567 if (header->unit_length == 0xffffffff) {
1568 header->unit_length = *(uint64_t *)p;
1569 p +=
sizeof(uint64_t);
1574 header->address_size = *p++;
1575 if (header->address_size != 4 && header->address_size != 8) {
1576 kprintf(
"unknown address_size:%d", header->address_size);
1580 header->offset_entry_count = *(uint32_t *)p;
1594ranges_set(ranges_t *ptr, DebugInfoValue *v, addr_header_t *addr_header, uint64_t addr_base)
1597 if (v->type == VAL_uint) {
1600 else if (v->type == VAL_addr) {
1601 n = read_addr(addr_header, addr_base, v->as.addr_idx);
1606 ptr->low_pc_set =
true;
1609 if (v->form == DW_FORM_addr) {
1613 ptr->high_pc = ptr->low_pc + n;
1615 ptr->high_pc_set =
true;
1619 ptr->ranges_set =
true;
1625read_dw_form_addr(DebugInfoReader *reader,
const char **ptr,
FILE *errout)
1627 const char *p = *ptr;
1628 *ptr = p + reader->address_size;
1629 if (reader->address_size == 4) {
1630 return read_uint32(&p);
1632 return read_uint64(&p);
1637ranges_include(DebugInfoReader *reader, ranges_t *ptr, uint64_t addr, rnglists_header_t *rnglists_header,
FILE *errout)
1639 if (ptr->high_pc_set) {
1640 if (ptr->ranges_set || !ptr->low_pc_set) {
1643 if (ptr->low_pc <= addr && addr <= ptr->high_pc) {
1644 return (uintptr_t)ptr->low_pc;
1647 else if (ptr->ranges_set) {
1650 uint64_t base = ptr->low_pc_set ? ptr->low_pc : reader->current_low_pc;
1651 bool base_valid =
true;
1652 if (reader->current_version >= 5) {
1653 if (rnglists_header->offset_entry_count == 0) {
1655 p = reader->obj->debug_rnglists.ptr + ptr->ranges + reader->current_rnglists_base;
1659 const char *offset_array = reader->obj->debug_rnglists.ptr + reader->current_rnglists_base;
1660 if (rnglists_header->format == 4) {
1661 p = offset_array + ((uint32_t *)offset_array)[ptr->ranges];
1664 p = offset_array + ((uint64_t *)offset_array)[ptr->ranges];
1668 uint8_t rle = read_uint8(&p);
1669 uintptr_t from = 0, to = 0;
1670 if (rle == DW_RLE_end_of_list)
break;
1672 case DW_RLE_base_addressx:
1676 case DW_RLE_startx_endx:
1680 case DW_RLE_startx_length:
1684 case DW_RLE_offset_pair:
1685 if (!base_valid)
break;
1686 from = (uintptr_t)base + uleb128(&p);
1687 to = (uintptr_t)base + uleb128(&p);
1689 case DW_RLE_base_address:
1690 base = read_dw_form_addr(reader, &p, errout);
1693 case DW_RLE_start_end:
1694 from = (uintptr_t)read_dw_form_addr(reader, &p, errout);
1695 to = (uintptr_t)read_dw_form_addr(reader, &p, errout);
1697 case DW_RLE_start_length:
1698 from = (uintptr_t)read_dw_form_addr(reader, &p, errout);
1699 to = from + uleb128(&p);
1702 if (from <= addr && addr < to) {
1708 p = reader->obj->debug_ranges.ptr + ptr->ranges;
1710 uintptr_t from = read_uintptr(&p);
1711 uintptr_t to = read_uintptr(&p);
1712 if (!from && !to)
break;
1713 if (from == UINTPTR_MAX) {
1717 else if (base + from <= addr && addr < base + to) {
1718 return (uintptr_t)base + from;
1722 else if (ptr->low_pc_set) {
1723 if (ptr->low_pc == addr) {
1724 return (uintptr_t)ptr->low_pc;
1732ranges_inspect(DebugInfoReader *reader, ranges_t *ptr,
FILE *errout)
1734 if (ptr->high_pc_set) {
1735 if (ptr->ranges_set || !ptr->low_pc_set) {
1736 kprintf(
"low_pc_set:%d high_pc_set:%d ranges_set:%d\n",ptr->low_pc_set,ptr->high_pc_set,ptr->ranges_set);
1739 kprintf(
"low_pc:%"PRIx64
" high_pc:%"PRIx64
"\n",ptr->low_pc,ptr->high_pc);
1741 else if (ptr->ranges_set) {
1742 char *p = reader->obj->debug_ranges.ptr + ptr->ranges;
1743 kprintf(
"low_pc:%"PRIx64
" ranges:%"PRIx64
" %lx ",ptr->low_pc,ptr->ranges, p-reader->obj->mapped);
1745 uintptr_t from = read_uintptr(&p);
1746 uintptr_t to = read_uintptr(&p);
1747 if (!from && !to)
break;
1748 kprintf(
"%"PRIx64
"-%"PRIx64
" ",ptr->low_pc+from,ptr->low_pc+to);
1752 else if (ptr->low_pc_set) {
1753 kprintf(
"low_pc:%"PRIx64
"\n",ptr->low_pc);
1762di_read_cu_context(DebugInfoReader *reader,
FILE *errout)
1764 uint64_t unit_length;
1766 uint64_t debug_abbrev_offset;
1768 reader->current_cu = reader->p;
1769 unit_length = read_uint32(&reader->p);
1770 if (unit_length == 0xffffffff) {
1771 unit_length = read_uint64(&reader->p);
1774 reader->cu_end = reader->p + unit_length;
1775 version = read_uint16(&reader->p);
1776 reader->current_version = version;
1780 else if (version == 5) {
1781 read_uint8(&reader->p);
1782 reader->address_size = read_uint8(&reader->p);
1783 debug_abbrev_offset = read_uint(reader);
1786 debug_abbrev_offset = read_uint(reader);
1787 reader->address_size = read_uint8(&reader->p);
1789 if (reader->address_size != 4 && reader->address_size != 8) {
1790 kprintf(
"unknown address_size:%d", reader->address_size);
1793 reader->q0 = reader->obj->debug_abbrev.ptr + debug_abbrev_offset;
1796 di_read_debug_abbrev_cu(reader);
1801 if (!di_read_die(reader, &die, errout))
continue;
1803 if (die.tag != DW_TAG_compile_unit) {
1804 if (!di_skip_records(reader, errout))
return -1;
1808 reader->current_str_offsets_base = 0;
1809 reader->current_addr_base = 0;
1810 reader->current_rnglists_base = 0;
1812 DebugInfoValue low_pc = {{0}};
1815 DebugInfoValue v = {{0}};
1816 if (!di_read_record(reader, &v, errout))
break;
1823 case DW_AT_str_offsets_base:
1824 reader->current_str_offsets_base = v.as.uint64;
1826 case DW_AT_addr_base:
1827 reader->current_addr_base = v.as.uint64;
1829 case DW_AT_rnglists_base:
1830 reader->current_rnglists_base = v.as.uint64;
1835 switch (low_pc.type) {
1837 reader->current_low_pc = low_pc.as.uint64;
1841 addr_header_t header = {0};
1842 if (!addr_header_init(reader->obj, &header, errout))
return -1;
1843 reader->current_low_pc = read_addr(&header, reader->current_addr_base, low_pc.as.addr_idx);
1853di_read_cu(DebugInfoReader *reader,
FILE *errout)
1857 if (di_read_cu_context(reader, errout))
return -1;
1858 if (di_read_debug_line_cu(reader, errout))
return -1;
1867di_read_cu_at(DebugInfoReader *reader, uint64_t die_offset,
FILE *errout)
1869 const uint64_t debug_info_size = reader->obj->debug_info.size;
1870 if (die_offset >= debug_info_size)
return false;
1872 const char *
const info = reader->obj->debug_info.ptr;
1873 const char *
const pend = reader->pend;
1874 const char *
const target = info + die_offset;
1875 const char *cu = info;
1877 while (pend - cu >= 4) {
1878 const char *hp = cu;
1879 uint64_t unit_length = read_uint32(&hp);
1881 if (unit_length == 0xffffffff) {
1882 if (pend - hp < 8)
return false;
1883 unit_length = read_uint64(&hp);
1885 if (unit_length == 0 || unit_length > (uint64_t)(pend - hp))
return false;
1887 const char *cu_end = hp + unit_length;
1888 if (target >= cu && target < cu_end) {
1890 if (di_read_cu_context(reader, errout))
return false;
1900read_abstract_origin(DebugInfoReader *reader, uint64_t form, uint64_t abstract_origin, line_info_t *line,
FILE *errout)
1902 DebugInfoReader saved = *reader;
1910 case DW_FORM_ref_udata:
1911 reader->p = reader->current_cu + abstract_origin;
1913 case DW_FORM_ref_addr:
1917 if (!di_read_cu_at(reader, abstract_origin, errout))
goto finish;
1919 case DW_FORM_ref_sig8:
1921 case DW_FORM_ref_sup4:
1922 case DW_FORM_ref_sup8:
1927 if (!di_read_die(reader, &die, errout))
goto finish;
1931 DebugInfoValue v = {{0}};
1932 if (!di_read_record(reader, &v, errout))
break;
1935 line->sname = get_cstr_value(&v);
1945debug_info_read(DebugInfoReader *reader,
int num_traces,
void **traces,
1946 line_info_t *lines,
int offset,
FILE *errout)
1949 addr_header_t addr_header = {0};
1950 if (!addr_header_init(reader->obj, &addr_header, errout))
return false;
1952 rnglists_header_t rnglists_header = {0};
1953 if (!rnglists_header_init(reader->obj, &rnglists_header, errout))
return false;
1955 while (reader->p < reader->cu_end) {
1957 ranges_t ranges = {0};
1958 line_info_t line = {0};
1960 if (!di_read_die(reader, &die, errout))
continue;
1963 if (die.tag != DW_TAG_subprogram && die.tag != DW_TAG_inlined_subroutine) {
1965 if (!di_skip_records(reader, errout))
return false;
1971 DebugInfoValue v = {{0}};
1973 if (!di_read_record(reader, &v, errout))
break;
1978 line.sname = get_cstr_value(&v);
1980 case DW_AT_call_file:
1981 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);
1983 case DW_AT_call_line:
1984 line.line = (int)v.as.uint64;
1989 ranges_set(&ranges, &v, &addr_header, reader->current_addr_base);
1991 case DW_AT_declaration:
1996 case DW_AT_abstract_origin:
1997 read_abstract_origin(reader, v.form, v.as.uint64, &line, errout);
2003 for (
int i=offset; i < num_traces; i++) {
2004 uintptr_t addr = (uintptr_t)traces[i];
2005 uintptr_t offset = addr - reader->obj->base_addr + reader->obj->vmaddr;
2006 uintptr_t saddr = ranges_include(reader, &ranges, offset, &rnglists_header, errout);
2007 if (saddr == UINTPTR_MAX)
return false;
2010 if (lines[i].sname) {
2011 line_info_t *lp = malloc(
sizeof(line_info_t));
2012 memcpy(lp, &lines[i],
sizeof(line_info_t));
2014 lp->dirname = line.dirname;
2015 lp->filename = line.filename;
2016 lp->line = line.line;
2019 lines[i].path = reader->obj->path;
2020 lines[i].base_addr = line.base_addr;
2021 lines[i].sname = line.sname;
2022 lines[i].saddr = saddr + reader->obj->base_addr - reader->obj->vmaddr;
2045parse_ver5_debug_line_header(
const char *p,
int idx, uint8_t format,
2046 obj_info_t *obj,
const char **out_path,
2047 uint64_t *out_directory_index,
FILE *errout)
2050 int entry_format_count = *(uint8_t *)p++;
2051 const char *entry_format = p;
2054 for (i = 0; i < entry_format_count * 2; i++) uleb128(&p);
2056 int entry_count = (int)uleb128(&p);
2058 DebugInfoReader reader = {0};
2059 debug_info_reader_init(&reader, obj);
2060 reader.format = format;
2062 for (j = 0; j < entry_count; j++) {
2063 const char *format = entry_format;
2064 for (i = 0; i < entry_format_count; i++) {
2065 DebugInfoValue v = {{0}};
2066 unsigned long dw_lnct = uleb128(&format);
2067 unsigned long dw_form = uleb128(&format);
2068 if (!debug_info_reader_read_value(&reader, dw_form, &v, errout))
return 0;
2069 if (dw_lnct == 1 && v.type == VAL_cstr && out_path)
2070 *out_path = v.as.ptr + v.off;
2071 if (dw_lnct == 2 && v.type == VAL_uint && out_directory_index)
2072 *out_directory_index = v.as.uint64;
2074 if (j == idx)
return 0;
2082uncompress_debug_section(ElfW(Shdr) *shdr,
char *file,
char **ptr)
2085#ifdef SUPPORT_COMPRESSED_DEBUG_LINE
2086 ElfW(Chdr) *chdr = (ElfW(Chdr) *)(file + shdr->sh_offset);
2087 unsigned long destsize = chdr->ch_size;
2090 if (chdr->ch_type != ELFCOMPRESS_ZLIB) {
2095 *ptr = malloc(destsize);
2096 if (!*ptr)
return 0;
2097 ret = uncompress((Bytef *)*ptr, &destsize,
2098 (
const Bytef*)chdr +
sizeof(ElfW(Chdr)),
2099 shdr->sh_size -
sizeof(ElfW(Chdr)));
2100 if (ret != Z_OK)
goto fail;
2112fill_lines(
int num_traces,
void **traces,
int check_debuglink,
2113 obj_info_t **objp, line_info_t *lines,
int offset,
FILE *errout)
2118 ElfW(Shdr) *shdr, *shstr_shdr;
2119 ElfW(Shdr) *gnu_debuglink_shdr = NULL;
2120 ElfW(Shdr) *note_gnu_build_id = NULL;
2124 ElfW(Shdr) *symtab_shdr = NULL, *strtab_shdr = NULL;
2125 ElfW(Shdr) *dynsym_shdr = NULL, *dynstr_shdr = NULL;
2126 obj_info_t *obj = *objp;
2127 uintptr_t dladdr_fbase = 0;
2129 fd = open(binary_filename, O_RDONLY);
2133 filesize = lseek(fd, 0, SEEK_END);
2137 kprintf(
"lseek: %s\n", strerror(e));
2140#if SIZEOF_OFF_T > SIZEOF_SIZE_T
2141 if (filesize > (off_t)SIZE_MAX) {
2143 kprintf(
"Too large file %s\n", binary_filename);
2147 lseek(fd, 0, SEEK_SET);
2149 file = (
char *)mmap(NULL, (
size_t)filesize, PROT_READ, MAP_SHARED, fd, 0);
2150 if (file == MAP_FAILED) {
2153 kprintf(
"mmap: %s\n", strerror(e));
2158 ehdr = (ElfW(Ehdr) *)file;
2159 if (memcmp(ehdr->e_ident,
"\177ELF", 4) != 0) {
2167 obj->mapped_size = (size_t)filesize;
2169 shdr = (ElfW(Shdr) *)(file + ehdr->e_shoff);
2171 shstr_shdr = shdr + ehdr->e_shstrndx;
2172 shstr = file + shstr_shdr->sh_offset;
2174 for (i = 0; i < ehdr->e_shnum; i++) {
2175 char *section_name = shstr + shdr[i].sh_name;
2176 switch (shdr[i].sh_type) {
2178 if (!strcmp(section_name,
".strtab")) {
2179 strtab_shdr = shdr + i;
2181 else if (!strcmp(section_name,
".dynstr")) {
2182 dynstr_shdr = shdr + i;
2187 symtab_shdr = shdr + i;
2191 dynsym_shdr = shdr + i;
2194 if (!strcmp(section_name,
".note.gnu.build-id")) {
2195 note_gnu_build_id = shdr + i;
2199 if (!strcmp(section_name,
".gnu_debuglink")) {
2200 gnu_debuglink_shdr = shdr + i;
2203 const char *debug_section_names[] = {
2208 ".debug_str_offsets",
2215 for (j=0; j < DWARF_SECTION_COUNT; j++) {
2216 struct dwarf_section *s = obj_dwarf_section_at(obj, j);
2218 if (strcmp(section_name, debug_section_names[j]) != 0)
2221 s->ptr = file + shdr[i].sh_offset;
2222 s->size = shdr[i].sh_size;
2223 s->flags = shdr[i].sh_flags;
2224 if (s->flags & SHF_COMPRESSED) {
2225 s->size = uncompress_debug_section(&shdr[i], file, &s->ptr);
2226 if (!s->size)
goto fail;
2237 if (dynsym_shdr && dynstr_shdr) {
2238 char *strtab = file + dynstr_shdr->sh_offset;
2239 ElfW(Sym) *symtab = (ElfW(Sym) *)(file + dynsym_shdr->sh_offset);
2240 int symtab_count = (int)(dynsym_shdr->sh_size /
sizeof(ElfW(Sym)));
2241 void *handle = dlopen(NULL, RTLD_NOW|RTLD_LOCAL);
2243 for (j = 0; j < symtab_count; j++) {
2244 ElfW(Sym) *sym = &symtab[j];
2247 if (ELF_ST_TYPE(sym->st_info) != STT_FUNC || sym->st_size == 0)
continue;
2248 s = dlsym(handle, strtab + sym->st_name);
2249 if (s && dladdr(s, &info)) {
2250 obj->base_addr = dladdr_fbase;
2251 dladdr_fbase = (uintptr_t)info.dli_fbase;
2257 if (ehdr->e_type == ET_EXEC) {
2262 obj->base_addr = dladdr_fbase;
2267 if (obj->debug_info.ptr && obj->debug_abbrev.ptr) {
2273 static DebugInfoReader reader;
2274 debug_info_reader_init(&reader, obj);
2276 while (reader.p < reader.pend) {
2278 if (di_read_cu(&reader, errout))
goto use_symtab;
2279 if (!debug_info_read(&reader, num_traces, traces, lines, offset, errout))
2288 symtab_shdr = dynsym_shdr;
2289 strtab_shdr = dynstr_shdr;
2292 if (symtab_shdr && strtab_shdr) {
2293 char *strtab = file + strtab_shdr->sh_offset;
2294 ElfW(Sym) *symtab = (ElfW(Sym) *)(file + symtab_shdr->sh_offset);
2295 int symtab_count = (int)(symtab_shdr->sh_size /
sizeof(ElfW(Sym)));
2296 for (j = 0; j < symtab_count; j++) {
2297 ElfW(Sym) *sym = &symtab[j];
2298 uintptr_t saddr = (uintptr_t)sym->st_value + obj->base_addr;
2299 if (ELF_ST_TYPE(sym->st_info) != STT_FUNC)
continue;
2300 for (i = offset; i < num_traces; i++) {
2301 uintptr_t d = (uintptr_t)traces[i] - saddr;
2302 if (lines[i].line > 0 || d > (uintptr_t)sym->st_size)
2305 if (!lines[i].sname) lines[i].sname = strtab + sym->st_name;
2306 lines[i].saddr = saddr;
2307 lines[i].path = obj->path;
2308 lines[i].base_addr = obj->base_addr;
2314 if (!obj->debug_line.ptr) {
2317 if (gnu_debuglink_shdr && check_debuglink) {
2318 follow_debuglink(file + gnu_debuglink_shdr->sh_offset,
2320 objp, lines, offset, errout);
2322 if (note_gnu_build_id && check_debuglink) {
2323 ElfW(Nhdr) *nhdr = (ElfW(Nhdr)*) (file + note_gnu_build_id->sh_offset);
2324 const char *build_id = (
char *)(nhdr + 1) + nhdr->n_namesz;
2325 follow_debuglink_build_id(build_id, nhdr->n_descsz,
2327 objp, lines, offset, errout);
2332 if (parse_debug_line(num_traces, traces,
2333 obj->debug_line.ptr,
2334 obj->debug_line.size,
2335 obj, lines, offset, errout) == -1)
2339 return dladdr_fbase;
2341 return (uintptr_t)-1;
2346fill_lines(
int num_traces,
void **traces,
int check_debuglink,
2347 obj_info_t **objp, line_info_t *lines,
int offset,
FILE *errout)
2351 char *file, *p = NULL;
2352 obj_info_t *obj = *objp;
2353 struct LP(mach_header) *header;
2354 uintptr_t dladdr_fbase = 0;
2357 char *s = binary_filename;
2358 char *base = strrchr(binary_filename,
'/')+1;
2359 size_t max = PATH_MAX;
2360 size_t size = strlen(binary_filename);
2361 size_t basesize = size - (base - binary_filename);
2365 size = strlcpy(s,
".dSYM/Contents/Resources/DWARF/", max);
2366 if (size == 0)
goto fail;
2369 if (max <= basesize)
goto fail;
2370 memcpy(s, base, basesize);
2373 fd = open(binary_filename, O_RDONLY);
2376 fd = open(binary_filename, O_RDONLY);
2383 filesize = lseek(fd, 0, SEEK_END);
2387 kprintf(
"lseek: %s\n", strerror(e));
2390#if SIZEOF_OFF_T > SIZEOF_SIZE_T
2391 if (filesize > (off_t)SIZE_MAX) {
2393 kprintf(
"Too large file %s\n", binary_filename);
2397 lseek(fd, 0, SEEK_SET);
2399 file = (
char *)mmap(NULL, (
size_t)filesize, PROT_READ, MAP_SHARED, fd, 0);
2400 if (file == MAP_FAILED) {
2403 kprintf(
"mmap: %s\n", strerror(e));
2409 obj->mapped_size = (size_t)filesize;
2411 header = (
struct LP(mach_header) *)file;
2412 if (header->magic == LP(MH_MAGIC)) {
2416 else if (header->magic == FAT_CIGAM) {
2417 struct LP(mach_header) *mhp = _NSGetMachExecuteHeader();
2418 struct fat_header *fat = (
struct fat_header *)file;
2419 char *q = file +
sizeof(*fat);
2420 uint32_t nfat_arch = __builtin_bswap32(fat->nfat_arch);
2422 for (uint32_t i = 0; i < nfat_arch; i++) {
2423 struct fat_arch *arch = (
struct fat_arch *)q;
2424 cpu_type_t cputype = __builtin_bswap32(arch->cputype);
2425 cpu_subtype_t cpusubtype = __builtin_bswap32(arch->cpusubtype);
2426 uint32_t offset = __builtin_bswap32(arch->offset);
2428 if (mhp->cputype == cputype &&
2429 (cpu_subtype_t)(mhp->cpusubtype & ~CPU_SUBTYPE_MASK) == cpusubtype) {
2432 header = (
struct LP(mach_header) *)p;
2433 if (header->magic == LP(MH_MAGIC)) {
2434 goto found_mach_header;
2440 kprintf(
"'%s' is not a Mach-O universal binary file!\n",binary_filename);
2446# define bitsize "64"
2448# define bitsize "32"
2450 kprintf(
"'%s' is not a " bitsize
2451 "-bit Mach-O file!\n",binary_filename);
2457 p +=
sizeof(*header);
2459 for (uint32_t i = 0; i < (uint32_t)header->ncmds; i++) {
2460 struct load_command *lcmd = (
struct load_command *)p;
2461 switch (lcmd->cmd) {
2462 case LP(LC_SEGMENT):
2464 static const char *debug_section_names[] = {
2469 "__debug_str_offsets",
2475 struct LP(segment_command) *scmd = (
struct LP(segment_command) *)lcmd;
2476 if (strcmp(scmd->segname,
"__TEXT") == 0) {
2477 obj->vmaddr = scmd->vmaddr;
2479 else if (strcmp(scmd->segname,
"__DWARF") == 0) {
2480 p +=
sizeof(
struct LP(segment_command));
2481 for (uint64_t i = 0; i < scmd->nsects; i++) {
2482 struct LP(section) *sect = (
struct LP(section) *)p;
2483 p +=
sizeof(
struct LP(section));
2484 for (
int j=0; j < DWARF_SECTION_COUNT; j++) {
2485 struct dwarf_section *s = obj_dwarf_section_at(obj, j);
2487 if (strcmp(sect->sectname, debug_section_names[j]) != 0
2495 && strncmp(sect->sectname, debug_section_names[j], 16) != 0
2500 s->ptr = file + sect->offset;
2501 s->size = sect->size;
2502 s->flags = sect->flags;
2503 if (s->flags & SHF_COMPRESSED) {
2515 struct symtab_command *cmd = (
struct symtab_command *)lcmd;
2516 struct LP(nlist) *nl = (
struct LP(nlist) *)(file + cmd->symoff);
2517 char *strtab = file + cmd->stroff, *sname = 0;
2519 uintptr_t saddr = 0;
2521 for (j = 0; j < cmd->nsyms; j++) {
2522 uintptr_t symsize, d;
2523 struct LP(nlist) *e = &nl[j];
2525 if (e->n_type != N_FUN)
continue;
2527 saddr = (uintptr_t)e->n_value + obj->base_addr - obj->vmaddr;
2528 sname = strtab + e->n_un.n_strx;
2532 for (
int k = offset; k < num_traces; k++) {
2533 d = (uintptr_t)traces[k] - saddr;
2534 symsize = e->n_value;
2536 if (lines[k].line > 0 || d > (uintptr_t)symsize)
2539 if (!lines[k].sname) lines[k].sname = sname;
2540 lines[k].saddr = saddr;
2541 lines[k].path = obj->path;
2542 lines[k].base_addr = obj->base_addr;
2550 if (obj->debug_info.ptr && obj->debug_abbrev.ptr) {
2552 static DebugInfoReader reader;
2553 debug_info_reader_init(&reader, obj);
2554 while (reader.p < reader.pend) {
2555 if (di_read_cu(&reader, errout))
goto fail;
2556 if (!debug_info_read(&reader, num_traces, traces, lines, offset, errout))
2561 if (parse_debug_line(num_traces, traces,
2562 obj->debug_line.ptr,
2563 obj->debug_line.size,
2564 obj, lines, offset, errout) == -1)
2567 return dladdr_fbase;
2569 return (uintptr_t)-1;
2573#define HAVE_MAIN_EXE_PATH
2574#if defined(__FreeBSD__) || defined(__DragonFly__)
2575# include <sys/sysctl.h>
2583#if defined(__linux__) || defined(__NetBSD__)
2585main_exe_path(
FILE *errout)
2587# if defined(__linux__)
2588# define PROC_SELF_EXE "/proc/self/exe"
2589# elif defined(__NetBSD__)
2590# define PROC_SELF_EXE "/proc/curproc/exe"
2592 ssize_t
len = readlink(PROC_SELF_EXE, binary_filename, PATH_MAX);
2593 if (
len < 0)
return 0;
2594 binary_filename[
len] = 0;
2597#elif defined(__FreeBSD__) || defined(__DragonFly__)
2599main_exe_path(
FILE *errout)
2601 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
2602 size_t len = PATH_MAX;
2603 int err = sysctl(mib, 4, binary_filename, &
len, NULL, 0);
2605 kprintf(
"Can't get the path of ruby");
2611#elif defined(HAVE_LIBPROC_H)
2613main_exe_path(
FILE *errout)
2615 int len = proc_pidpath(getpid(), binary_filename, PATH_MAX);
2616 if (
len == 0)
return 0;
2617 binary_filename[
len] = 0;
2621#undef HAVE_MAIN_EXE_PATH
2625print_line0(line_info_t *line,
void *address,
FILE *errout)
2627 uintptr_t addr = (uintptr_t)address;
2628 uintptr_t d = addr - line->saddr;
2631 if (line->dirname && line->dirname[0]) {
2632 kprintf(
"%s(%s) %s/%s:%d\n", line->path, line->sname, line->dirname, line->filename, line->line);
2635 kprintf(
"%s(%s) %s:%d\n", line->path, line->sname, line->filename, line->line);
2638 else if (!line->path) {
2639 kprintf(
"[0x%"PRIxPTR
"]\n", addr);
2641 else if (!line->sname) {
2642 kprintf(
"%s(0x%"PRIxPTR
") [0x%"PRIxPTR
"]\n", line->path, addr-line->base_addr, addr);
2644 else if (!line->saddr) {
2645 kprintf(
"%s(%s) [0x%"PRIxPTR
"]\n", line->path, line->sname, addr);
2647 else if (line->line <= 0) {
2648 kprintf(
"%s(%s+0x%"PRIxPTR
") [0x%"PRIxPTR
"]\n", line->path, line->sname,
2651 else if (!line->filename) {
2652 kprintf(
"%s(%s+0x%"PRIxPTR
") [0x%"PRIxPTR
"] ???:%d\n", line->path, line->sname,
2653 d, addr, line->line);
2655 else if (line->dirname && line->dirname[0]) {
2656 kprintf(
"%s(%s+0x%"PRIxPTR
") [0x%"PRIxPTR
"] %s/%s:%d\n", line->path, line->sname,
2657 d, addr, line->dirname, line->filename, line->line);
2660 kprintf(
"%s(%s+0x%"PRIxPTR
") [0x%"PRIxPTR
"] %s:%d\n", line->path, line->sname,
2661 d, addr, line->filename, line->line);
2666print_line(line_info_t *line,
void *address,
FILE *errout)
2668 print_line0(line, address, errout);
2670 print_line(line->next, NULL, errout);
2675rb_dump_backtrace_with_lines(
int num_traces,
void **traces,
FILE *errout)
2679 line_info_t *lines = (line_info_t *)calloc(num_traces,
sizeof(line_info_t));
2680 obj_info_t *obj = NULL;
2682 void **dladdr_fbases = (
void **)calloc(num_traces+2,
sizeof(
void *));
2684#ifdef HAVE_MAIN_EXE_PATH
2685 char *main_path = NULL;
2687 if ((
len = main_exe_path(errout)) > 0) {
2688 main_path = (
char *)alloca(
len + 1);
2691 memcpy(main_path, binary_filename,
len+1);
2693 obj->path = main_path;
2694 addr = fill_lines(num_traces, traces, 1, &obj, lines, 0, errout);
2695 if (addr != (uintptr_t)-1) {
2696 dladdr_fbases[0] = (
void *)addr;
2703 for (i = 0; i < num_traces; i++) {
2705 if (lines[i].line)
continue;
2706 if (dladdr(traces[i], &info)) {
2712 for (p=dladdr_fbases; *p; p++) {
2713 if (*p == info.dli_fbase) {
2714 if (info.dli_fname) lines[i].path = info.dli_fname;
2715 if (info.dli_sname) lines[i].sname = info.dli_sname;
2719 *p = info.dli_fbase;
2722 obj->base_addr = (uintptr_t)info.dli_fbase;
2723 path = info.dli_fname;
2725 if (path) lines[i].path = path;
2726 if (info.dli_sname) {
2727 lines[i].sname = info.dli_sname;
2728 lines[i].saddr = (uintptr_t)info.dli_saddr;
2730 strlcpy(binary_filename, path, PATH_MAX);
2731 if (fill_lines(num_traces, traces, 1, &obj, lines, i, errout) == (uintptr_t)-1)
2739 for (i = 0; i < num_traces; i++) {
2740 print_line(&lines[i], traces[i], errout);
2743 if (lines[i].sname && strcmp(
"main", lines[i].sname) == 0)
2749 obj_info_t *o = obj;
2750 for (i=0; i < DWARF_SECTION_COUNT; i++) {
2751 struct dwarf_section *s = obj_dwarf_section_at(obj, i);
2752 if (s->flags & SHF_COMPRESSED) {
2756 if (obj->mapped_size) {
2757 munmap(obj->mapped, obj->mapped_size);
2762 for (i = 0; i < num_traces; i++) {
2763 line_info_t *line = lines[i].next;
2765 line_info_t *l = line;
2771 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.