12#pragma clang diagnostic ignored "-Wgnu-empty-initializer"
13#pragma clang diagnostic ignored "-Wgcc-compat"
16#include "ruby/internal/config.h"
18#include "ruby/missing.h"
30#if defined(USE_ELF) || defined(HAVE_MACH_O_LOADER_H)
46# define alloca __builtin_alloca
66#ifdef HAVE_MACH_O_LOADER_H
67# include <crt_externs.h>
68# include <mach-o/fat.h>
69# include <mach-o/loader.h>
70# include <mach-o/nlist.h>
71# include <mach-o/stab.h>
83# define ElfW(x) Elf64##_##x
85# define ElfW(x) Elf32##_##x
90# define ELF_ST_TYPE ELF64_ST_TYPE
92# define ELF_ST_TYPE ELF32_ST_TYPE
98# if defined(ELFCOMPRESS_ZLIB) && defined(HAVE_LIBZ)
101# define SUPPORT_COMPRESSED_DEBUG_LINE
104# define SHF_COMPRESSED 0
111#define DW_LNS_copy 0x01
112#define DW_LNS_advance_pc 0x02
113#define DW_LNS_advance_line 0x03
114#define DW_LNS_set_file 0x04
115#define DW_LNS_set_column 0x05
116#define DW_LNS_negate_stmt 0x06
117#define DW_LNS_set_basic_block 0x07
118#define DW_LNS_const_add_pc 0x08
119#define DW_LNS_fixed_advance_pc 0x09
120#define DW_LNS_set_prologue_end 0x0a
121#define DW_LNS_set_epilogue_begin 0x0b
122#define DW_LNS_set_isa 0x0c
125#define DW_LNE_end_sequence 0x01
126#define DW_LNE_set_address 0x02
127#define DW_LNE_define_file 0x03
128#define DW_LNE_set_discriminator 0x04
130PRINTF_ARGS(
static int kprintf(
const char *fmt, ...), 1, 2);
132typedef struct line_info {
134 const char *filename;
142 struct line_info *next;
145struct dwarf_section {
151typedef struct obj_info {
158 struct dwarf_section debug_abbrev;
159 struct dwarf_section debug_info;
160 struct dwarf_section debug_line;
161 struct dwarf_section debug_ranges;
162 struct dwarf_section debug_str_offsets;
163 struct dwarf_section debug_addr;
164 struct dwarf_section debug_rnglists;
165 struct dwarf_section debug_str;
166 struct dwarf_section debug_line_str;
167 struct obj_info *next;
170#define DWARF_SECTION_COUNT 9
172static struct dwarf_section *
173obj_dwarf_section_at(obj_info_t *obj,
int n)
175 struct dwarf_section *ary[] = {
180 &obj->debug_str_offsets,
182 &obj->debug_rnglists,
186 if (n < 0 || DWARF_SECTION_COUNT <= n) {
192struct debug_section_definition {
194 struct dwarf_section *dwarf;
198static char binary_filename[PATH_MAX + 1];
201uleb128(
const char **p)
206 unsigned char b = (
unsigned char)*(*p)++;
208 r += (
unsigned long)b << s;
211 r += (b & 0x7f) << s;
218sleb128(
const char **p)
223 unsigned char b = (
unsigned char)*(*p)++;
226 r -= (0x80 - b) << s;
229 r += (b & 0x3f) << s;
233 r += (b & 0x7f) << s;
240get_nth_dirname(
unsigned long dir,
const char *p)
249 kprintf(
"Unexpected directory number %lu in %s\n",
250 dir, binary_filename);
257static const char *parse_ver5_debug_line_header(
const char *p,
int idx, uint8_t format, obj_info_t *obj,
const char **out_path, uint64_t *out_directory_index);
260fill_filename(
int file, uint8_t format, uint16_t version,
const char *include_directories,
const char *filenames, line_info_t *line, obj_info_t *obj)
263 const char *p = filenames;
264 const char *filename;
268 uint64_t directory_index = -1;
269 parse_ver5_debug_line_header(filenames, file, format, obj, &path, &directory_index);
270 line->filename = path;
271 parse_ver5_debug_line_header(include_directories, (
int)directory_index, format, obj, &path, NULL);
272 line->dirname = path;
275 for (i = 1; i <= file; i++) {
279 kprintf(
"Unexpected file number %d in %s at %tx\n",
280 file, binary_filename, filenames - obj->mapped);
292 line->filename = filename;
293 line->dirname = get_nth_dirname(dir, include_directories);
300fill_line(
int num_traces,
void **traces, uintptr_t addr,
int file,
int line,
301 uint8_t format, uint16_t version,
const char *include_directories,
const char *filenames,
302 obj_info_t *obj, line_info_t *lines,
int offset)
305 addr += obj->base_addr - obj->vmaddr;
306 for (i = offset; i < num_traces; i++) {
307 uintptr_t a = (uintptr_t)traces[i];
310 if (addr < a && a < addr + 100) {
311 fill_filename(file, format, version, include_directories, filenames, &lines[i], obj);
312 lines[i].line = line;
317struct LineNumberProgramHeader {
318 uint64_t unit_length;
321 uint64_t header_length;
322 uint8_t minimum_instruction_length;
323 uint8_t maximum_operations_per_instruction;
324 uint8_t default_is_stmt;
329 const char *include_directories;
330 const char *filenames;
331 const char *cu_start;
336parse_debug_line_header(obj_info_t *obj,
const char **pp,
struct LineNumberProgramHeader *header)
339 header->unit_length = *(uint32_t *)p;
340 p +=
sizeof(uint32_t);
343 if (header->unit_length == 0xffffffff) {
344 header->unit_length = *(uint64_t *)p;
345 p +=
sizeof(uint64_t);
349 header->cu_end = p + header->unit_length;
351 header->version = *(uint16_t *)p;
352 p +=
sizeof(uint16_t);
353 if (header->version > 5)
return -1;
355 if (header->version >= 5) {
361 header->header_length = header->format == 4 ? *(uint32_t *)p : *(uint64_t *)p;
363 header->cu_start = p + header->header_length;
365 header->minimum_instruction_length = *(uint8_t *)p++;
367 if (header->version >= 4) {
369 if (*p != 1)
return -1;
373 header->default_is_stmt = *(uint8_t *)p++;
374 header->line_base = *(int8_t *)p++;
375 header->line_range = *(uint8_t *)p++;
376 header->opcode_base = *(uint8_t *)p++;
378 p += header->opcode_base - 1;
380 if (header->version >= 5) {
381 header->include_directories = p;
382 p = parse_ver5_debug_line_header(p, -1, header->format, obj, NULL, NULL);
383 header->filenames = p;
386 header->include_directories = p;
389 if (p >= header->cu_end)
return -1;
393 p = memchr(p,
'\0', header->cu_end - p);
399 header->filenames = p;
402 *pp = header->cu_start;
408parse_debug_line_cu(
int num_traces,
void **traces,
const char **debug_line,
409 obj_info_t *obj, line_info_t *lines,
int offset)
411 const char *p = (
const char *)*debug_line;
412 struct LineNumberProgramHeader header;
415 unsigned long addr = 0;
416 unsigned int file = 1;
417 unsigned int line = 1;
426 if (parse_debug_line_header(obj, &p, &header))
428 is_stmt = header.default_is_stmt;
432 fill_line(num_traces, traces, addr, file, line, \
435 header.include_directories, \
437 obj, lines, offset); \
441 while (p < header.cu_end) {
443 unsigned char op = *p++;
448 case DW_LNS_advance_pc:
449 a = uleb128(&p) * header.minimum_instruction_length;
452 case DW_LNS_advance_line: {
453 long a = sleb128(&p);
457 case DW_LNS_set_file:
458 file = (
unsigned int)uleb128(&p);
460 case DW_LNS_set_column:
463 case DW_LNS_negate_stmt:
466 case DW_LNS_set_basic_block:
469 case DW_LNS_const_add_pc:
470 a = ((255UL - header.opcode_base) / header.line_range) *
471 header.minimum_instruction_length;
474 case DW_LNS_fixed_advance_pc:
476 p +=
sizeof(uint16_t);
479 case DW_LNS_set_prologue_end:
482 case DW_LNS_set_epilogue_begin:
492 case DW_LNE_end_sequence:
499 is_stmt = header.default_is_stmt;
503 case DW_LNE_set_address:
504 addr = *(
unsigned long *)p;
505 p +=
sizeof(
unsigned long);
507 case DW_LNE_define_file:
508 kprintf(
"Unsupported operation in %s\n",
511 case DW_LNE_set_discriminator:
516 kprintf(
"Unknown extended opcode: %d in %s\n",
517 op, binary_filename);
521 uint8_t adjusted_opcode = op - header.opcode_base;
522 uint8_t operation_advance = adjusted_opcode / header.line_range;
524 addr += operation_advance * header.minimum_instruction_length;
525 line += header.line_base + (adjusted_opcode % header.line_range);
530 *debug_line = (
char *)p;
535parse_debug_line(
int num_traces,
void **traces,
536 const char *debug_line,
unsigned long size,
537 obj_info_t *obj, line_info_t *lines,
int offset)
539 const char *debug_line_end = debug_line + size;
540 while (debug_line < debug_line_end) {
541 if (parse_debug_line_cu(num_traces, traces, &debug_line, obj, lines, offset))
544 if (debug_line != debug_line_end) {
545 kprintf(
"Unexpected size of .debug_line in %s\n",
553fill_lines(
int num_traces,
void **traces,
int check_debuglink,
554 obj_info_t **objp, line_info_t *lines,
int offset);
557append_obj(obj_info_t **objp)
559 obj_info_t *newobj = calloc(1,
sizeof(obj_info_t));
560 if (*objp) (*objp)->next = newobj;
581follow_debuglink(
const char *debuglink,
int num_traces,
void **traces,
582 obj_info_t **objp, line_info_t *lines,
int offset)
584 static const char global_debug_dir[] =
"/usr/lib/debug";
585 const size_t global_debug_dir_len =
sizeof(global_debug_dir) - 1;
587 obj_info_t *o1 = *objp, *o2;
590 p = strrchr(binary_filename,
'/');
596 len = strlen(binary_filename);
597 if (len >= PATH_MAX - global_debug_dir_len)
598 len = PATH_MAX - global_debug_dir_len - 1;
599 memmove(binary_filename + global_debug_dir_len, binary_filename, len);
600 memcpy(binary_filename, global_debug_dir, global_debug_dir_len);
601 len += global_debug_dir_len;
602 strlcpy(binary_filename + len, debuglink, PATH_MAX - len);
606 o2->base_addr = o1->base_addr;
608 fill_lines(num_traces, traces, 0, objp, lines, offset);
613follow_debuglink_build_id(
const char *build_id,
size_t build_id_size,
int num_traces,
void **traces,
614 obj_info_t **objp, line_info_t *lines,
int offset)
616 static const char global_debug_dir[] =
"/usr/lib/debug/.build-id/";
617 const size_t global_debug_dir_len =
sizeof(global_debug_dir) - 1;
619 obj_info_t *o1 = *objp, *o2;
622 if (PATH_MAX < global_debug_dir_len + 1 + build_id_size * 2 + 6)
return;
624 memcpy(binary_filename, global_debug_dir, global_debug_dir_len);
625 p = binary_filename + global_debug_dir_len;
626 for (i = 0; i < build_id_size; i++) {
627 static const char tbl[] =
"0123456789abcdef";
628 unsigned char n = build_id[i];
631 if (i == 0) *p++ =
'/';
637 o2->base_addr = o1->base_addr;
639 fill_lines(num_traces, traces, 0, objp, lines, offset);
645 DW_TAG_compile_unit = 0x11,
646 DW_TAG_inlined_subroutine = 0x1d,
647 DW_TAG_subprogram = 0x2e,
653 DW_AT_sibling = 0x01,
654 DW_AT_location = 0x02,
661 DW_AT_ordering = 0x09,
663 DW_AT_byte_size = 0x0b,
665 DW_AT_bit_size = 0x0d,
668 DW_AT_stmt_list = 0x10,
670 DW_AT_high_pc = 0x12,
671 DW_AT_language = 0x13,
674 DW_AT_discr_value = 0x16,
675 DW_AT_visibility = 0x17,
677 DW_AT_string_length = 0x19,
678 DW_AT_common_reference = 0x1a,
679 DW_AT_comp_dir = 0x1b,
680 DW_AT_const_value = 0x1c,
681 DW_AT_containing_type = 0x1d,
682 DW_AT_default_value = 0x1e,
685 DW_AT_is_optional = 0x21,
686 DW_AT_lower_bound = 0x22,
689 DW_AT_producer = 0x25,
691 DW_AT_prototyped = 0x27,
694 DW_AT_return_addr = 0x2a,
696 DW_AT_start_scope = 0x2c,
698 DW_AT_bit_stride = 0x2e,
699 DW_AT_upper_bound = 0x2f,
701 DW_AT_abstract_origin = 0x31,
702 DW_AT_accessibility = 0x32,
703 DW_AT_address_class = 0x33,
704 DW_AT_artificial = 0x34,
705 DW_AT_base_types = 0x35,
706 DW_AT_calling_convention = 0x36,
708 DW_AT_data_member_location = 0x38,
709 DW_AT_decl_column = 0x39,
710 DW_AT_decl_file = 0x3a,
711 DW_AT_decl_line = 0x3b,
712 DW_AT_declaration = 0x3c,
713 DW_AT_discr_list = 0x3d,
714 DW_AT_encoding = 0x3e,
715 DW_AT_external = 0x3f,
716 DW_AT_frame_base = 0x40,
718 DW_AT_identifier_case = 0x42,
720 DW_AT_namelist_item = 0x44,
721 DW_AT_priority = 0x45,
722 DW_AT_segment = 0x46,
723 DW_AT_specification = 0x47,
724 DW_AT_static_link = 0x48,
726 DW_AT_use_location = 0x4a,
727 DW_AT_variable_parameter = 0x4b,
728 DW_AT_virtuality = 0x4c,
729 DW_AT_vtable_elem_location = 0x4d,
730 DW_AT_allocated = 0x4e,
731 DW_AT_associated = 0x4f,
732 DW_AT_data_location = 0x50,
733 DW_AT_byte_stride = 0x51,
734 DW_AT_entry_pc = 0x52,
735 DW_AT_use_UTF8 = 0x53,
736 DW_AT_extension = 0x54,
738 DW_AT_trampoline = 0x56,
739 DW_AT_call_column = 0x57,
740 DW_AT_call_file = 0x58,
741 DW_AT_call_line = 0x59,
742 DW_AT_description = 0x5a,
743 DW_AT_binary_scale = 0x5b,
744 DW_AT_decimal_scale = 0x5c,
746 DW_AT_decimal_sign = 0x5e,
747 DW_AT_digit_count = 0x5f,
748 DW_AT_picture_string = 0x60,
749 DW_AT_mutable = 0x61,
750 DW_AT_threads_scaled = 0x62,
751 DW_AT_explicit = 0x63,
752 DW_AT_object_pointer = 0x64,
753 DW_AT_endianity = 0x65,
754 DW_AT_elemental = 0x66,
756 DW_AT_recursive = 0x68,
757 DW_AT_signature = 0x69,
758 DW_AT_main_subprogram = 0x6a,
759 DW_AT_data_bit_offset = 0x6b,
760 DW_AT_const_expr = 0x6c,
761 DW_AT_enum_class = 0x6d,
762 DW_AT_linkage_name = 0x6e,
763 DW_AT_string_length_bit_size = 0x6f,
764 DW_AT_string_length_byte_size = 0x70,
766 DW_AT_str_offsets_base = 0x72,
767 DW_AT_addr_base = 0x73,
768 DW_AT_rnglists_base = 0x74,
770 DW_AT_dwo_name = 0x76,
771 DW_AT_reference = 0x77,
772 DW_AT_rvalue_reference = 0x78,
774 DW_AT_call_all_calls = 0x7a,
775 DW_AT_call_all_source_calls = 0x7b,
776 DW_AT_call_all_tail_calls = 0x7c,
777 DW_AT_call_return_pc = 0x7d,
778 DW_AT_call_value = 0x7e,
779 DW_AT_call_origin = 0x7f,
780 DW_AT_call_parameter = 0x80,
781 DW_AT_call_pc = 0x81,
782 DW_AT_call_tail_call = 0x82,
783 DW_AT_call_target = 0x83,
784 DW_AT_call_target_clobbered = 0x84,
785 DW_AT_call_data_location = 0x85,
786 DW_AT_call_data_value = 0x86,
787 DW_AT_noreturn = 0x87,
788 DW_AT_alignment = 0x88,
789 DW_AT_export_symbols = 0x89,
790 DW_AT_deleted = 0x8a,
791 DW_AT_defaulted = 0x8b,
792 DW_AT_loclists_base = 0x8c,
793 DW_AT_lo_user = 0x2000,
794 DW_AT_hi_user = 0x3fff
802 DW_FORM_block2 = 0x03,
803 DW_FORM_block4 = 0x04,
804 DW_FORM_data2 = 0x05,
805 DW_FORM_data4 = 0x06,
806 DW_FORM_data8 = 0x07,
807 DW_FORM_string = 0x08,
808 DW_FORM_block = 0x09,
809 DW_FORM_block1 = 0x0a,
810 DW_FORM_data1 = 0x0b,
812 DW_FORM_sdata = 0x0d,
814 DW_FORM_udata = 0x0f,
815 DW_FORM_ref_addr = 0x10,
820 DW_FORM_ref_udata = 0x15,
821 DW_FORM_indirect = 0x16,
822 DW_FORM_sec_offset = 0x17,
823 DW_FORM_exprloc = 0x18,
824 DW_FORM_flag_present = 0x19,
826 DW_FORM_addrx = 0x1b,
827 DW_FORM_ref_sup4 = 0x1c,
828 DW_FORM_strp_sup = 0x1d,
829 DW_FORM_data16 = 0x1e,
830 DW_FORM_line_strp = 0x1f,
831 DW_FORM_ref_sig8 = 0x20,
832 DW_FORM_implicit_const = 0x21,
833 DW_FORM_loclistx = 0x22,
834 DW_FORM_rnglistx = 0x23,
835 DW_FORM_ref_sup8 = 0x24,
836 DW_FORM_strx1 = 0x25,
837 DW_FORM_strx2 = 0x26,
838 DW_FORM_strx3 = 0x27,
839 DW_FORM_strx4 = 0x28,
840 DW_FORM_addrx1 = 0x29,
841 DW_FORM_addrx2 = 0x2a,
842 DW_FORM_addrx3 = 0x2b,
843 DW_FORM_addrx4 = 0x2c
848 DW_RLE_end_of_list = 0x00,
849 DW_RLE_base_addressx = 0x01,
850 DW_RLE_startx_endx = 0x02,
851 DW_RLE_startx_length = 0x03,
852 DW_RLE_offset_pair = 0x04,
853 DW_RLE_base_address = 0x05,
854 DW_RLE_start_end = 0x06,
855 DW_RLE_start_length = 0x07
867# define ABBREV_TABLE_SIZE 256
871 uint8_t current_version;
872 const char *current_cu;
873 uint64_t current_low_pc;
874 uint64_t current_str_offsets_base;
875 uint64_t current_addr_base;
876 uint64_t current_rnglists_base;
877 const char *debug_line_cu_end;
878 uint8_t debug_line_format;
879 uint16_t debug_line_version;
880 const char *debug_line_files;
881 const char *debug_line_directories;
888 uint8_t address_size;
890 const char *abbrev_table[ABBREV_TABLE_SIZE];
913#if defined(WORDS_BIGENDIAN)
914#define MERGE_2INTS(a,b,sz) (((uint64_t)(a)<<sz)|(b))
916#define MERGE_2INTS(a,b,sz) (((uint64_t)(b)<<sz)|(a))
920get_uint16(
const uint8_t *p)
922 return (uint16_t)MERGE_2INTS(p[0],p[1],8);
926get_uint32(
const uint8_t *p)
928 return (uint32_t)MERGE_2INTS(get_uint16(p),get_uint16(p+2),16);
932get_uint64(
const uint8_t *p)
934 return MERGE_2INTS(get_uint32(p),get_uint32(p+4),32);
938read_uint8(
const char **ptr)
940 const char *p = *ptr;
946read_uint16(
const char **ptr)
948 const char *p = *ptr;
950 return get_uint16((
const uint8_t *)p);
954read_uint24(
const char **ptr)
956 const char *p = *ptr;
958 return ((uint8_t)*p << 16) | get_uint16((
const uint8_t *)p+1);
962read_uint32(
const char **ptr)
964 const char *p = *ptr;
966 return get_uint32((
const uint8_t *)p);
970read_uint64(
const char **ptr)
972 const unsigned char *p = (
const unsigned char *)*ptr;
973 *ptr = (
char *)(p + 8);
974 return get_uint64(p);
978read_uintptr(
const char **ptr)
980 const unsigned char *p = (
const unsigned char *)*ptr;
981 *ptr = (
char *)(p + SIZEOF_VOIDP);
983 return get_uint64(p);
985 return get_uint32(p);
990read_uint(DebugInfoReader *reader)
992 if (reader->format == 4) {
993 return read_uint32(&reader->p);
995 return read_uint64(&reader->p);
1000read_uleb128(DebugInfoReader *reader)
1002 return uleb128(&reader->p);
1006read_sleb128(DebugInfoReader *reader)
1008 return sleb128(&reader->p);
1012debug_info_reader_init(DebugInfoReader *reader, obj_info_t *obj)
1014 reader->file = obj->mapped;
1016 reader->p = obj->debug_info.ptr;
1017 reader->pend = obj->debug_info.ptr + obj->debug_info.size;
1018 reader->debug_line_cu_end = obj->debug_line.ptr;
1019 reader->current_low_pc = 0;
1020 reader->current_str_offsets_base = 0;
1021 reader->current_addr_base = 0;
1022 reader->current_rnglists_base = 0;
1026di_skip_die_attributes(
const char **p)
1029 uint64_t at = uleb128(p);
1030 uint64_t form = uleb128(p);
1031 if (!at && !form)
break;
1035 case DW_FORM_implicit_const:
1043di_read_debug_abbrev_cu(DebugInfoReader *reader)
1046 const char *p = reader->q0;
1048 uint64_t abbrev_number = uleb128(&p);
1049 if (abbrev_number <= prev)
break;
1050 if (abbrev_number < ABBREV_TABLE_SIZE) {
1051 reader->abbrev_table[abbrev_number] = p;
1053 prev = abbrev_number;
1056 di_skip_die_attributes(&p);
1061di_read_debug_line_cu(DebugInfoReader *reader)
1064 struct LineNumberProgramHeader header;
1066 p = (
const char *)reader->debug_line_cu_end;
1067 if (parse_debug_line_header(reader->obj, &p, &header))
1070 reader->debug_line_cu_end = (
char *)header.cu_end;
1071 reader->debug_line_format = header.format;
1072 reader->debug_line_version = header.version;
1073 reader->debug_line_directories = (
char *)header.include_directories;
1074 reader->debug_line_files = (
char *)header.filenames;
1080set_addr_idx_value(DebugInfoValue *v, uint64_t n)
1087set_uint_value(DebugInfoValue *v, uint64_t n)
1094set_int_value(DebugInfoValue *v, int64_t n)
1101set_cstr_value(DebugInfoValue *v,
const char *s)
1109set_cstrp_value(DebugInfoValue *v,
const char *s, uint64_t off)
1117set_data_value(DebugInfoValue *v,
const char *s)
1124get_cstr_value(DebugInfoValue *v)
1127 return v->as.ptr + v->off;
1134resolve_strx(DebugInfoReader *reader, uint64_t idx)
1136 const char *p = reader->obj->debug_str_offsets.ptr + reader->current_str_offsets_base;
1138 if (reader->format == 4) {
1139 off = ((uint32_t *)p)[idx];
1142 off = ((uint64_t *)p)[idx];
1144 return reader->obj->debug_str.ptr + off;
1148debug_info_reader_read_value(DebugInfoReader *reader, uint64_t form, DebugInfoValue *v)
1152 if (reader->address_size == 4) {
1153 set_uint_value(v, read_uint32(&reader->p));
1154 }
else if (reader->address_size == 8) {
1155 set_uint_value(v, read_uint64(&reader->p));
1157 fprintf(stderr,
"unknown address_size:%d", reader->address_size);
1161 case DW_FORM_block2:
1162 v->size = read_uint16(&reader->p);
1163 set_data_value(v, reader->p);
1164 reader->p += v->size;
1166 case DW_FORM_block4:
1167 v->size = read_uint32(&reader->p);
1168 set_data_value(v, reader->p);
1169 reader->p += v->size;
1172 set_uint_value(v, read_uint16(&reader->p));
1175 set_uint_value(v, read_uint32(&reader->p));
1178 set_uint_value(v, read_uint64(&reader->p));
1180 case DW_FORM_string:
1181 v->size = strlen(reader->p);
1182 set_cstr_value(v, reader->p);
1183 reader->p += v->size + 1;
1186 v->size = uleb128(&reader->p);
1187 set_data_value(v, reader->p);
1188 reader->p += v->size;
1190 case DW_FORM_block1:
1191 v->size = read_uint8(&reader->p);
1192 set_data_value(v, reader->p);
1193 reader->p += v->size;
1196 set_uint_value(v, read_uint8(&reader->p));
1199 set_uint_value(v, read_uint8(&reader->p));
1202 set_int_value(v, read_sleb128(reader));
1205 set_cstrp_value(v, reader->obj->debug_str.ptr, read_uint(reader));
1208 set_uint_value(v, read_uleb128(reader));
1210 case DW_FORM_ref_addr:
1211 if (reader->format == 4) {
1212 set_uint_value(v, read_uint32(&reader->p));
1213 }
else if (reader->format == 8) {
1214 set_uint_value(v, read_uint64(&reader->p));
1216 fprintf(stderr,
"unknown format:%d", reader->format);
1221 set_uint_value(v, read_uint8(&reader->p));
1224 set_uint_value(v, read_uint16(&reader->p));
1227 set_uint_value(v, read_uint32(&reader->p));
1230 set_uint_value(v, read_uint64(&reader->p));
1232 case DW_FORM_ref_udata:
1233 set_uint_value(v, uleb128(&reader->p));
1235 case DW_FORM_indirect:
1237 set_uint_value(v, uleb128(&reader->p));
1239 case DW_FORM_sec_offset:
1240 set_uint_value(v, read_uint(reader));
1250 case DW_FORM_exprloc:
1251 v->size = (size_t)read_uleb128(reader);
1252 set_data_value(v, reader->p);
1253 reader->p += v->size;
1255 case DW_FORM_flag_present:
1256 set_uint_value(v, 1);
1259 set_cstr_value(v, resolve_strx(reader, uleb128(&reader->p)));
1262 set_addr_idx_value(v, uleb128(&reader->p));
1264 case DW_FORM_ref_sup4:
1265 set_uint_value(v, read_uint32(&reader->p));
1267 case DW_FORM_strp_sup:
1268 set_uint_value(v, read_uint(reader));
1271 case DW_FORM_data16:
1273 set_data_value(v, reader->p);
1274 reader->p += v->size;
1276 case DW_FORM_line_strp:
1277 set_cstrp_value(v, reader->obj->debug_line_str.ptr, read_uint(reader));
1279 case DW_FORM_ref_sig8:
1280 set_uint_value(v, read_uint64(&reader->p));
1282 case DW_FORM_implicit_const:
1283 set_int_value(v, sleb128(&reader->q));
1285 case DW_FORM_loclistx:
1286 set_uint_value(v, read_uleb128(reader));
1288 case DW_FORM_rnglistx:
1289 set_uint_value(v, read_uleb128(reader));
1291 case DW_FORM_ref_sup8:
1292 set_uint_value(v, read_uint64(&reader->p));
1295 set_cstr_value(v, resolve_strx(reader, read_uint8(&reader->p)));
1298 set_cstr_value(v, resolve_strx(reader, read_uint16(&reader->p)));
1301 set_cstr_value(v, resolve_strx(reader, read_uint24(&reader->p)));
1304 set_cstr_value(v, resolve_strx(reader, read_uint32(&reader->p)));
1306 case DW_FORM_addrx1:
1307 set_addr_idx_value(v, read_uint8(&reader->p));
1309 case DW_FORM_addrx2:
1310 set_addr_idx_value(v, read_uint16(&reader->p));
1312 case DW_FORM_addrx3:
1313 set_addr_idx_value(v, read_uint24(&reader->p));
1315 case DW_FORM_addrx4:
1316 set_addr_idx_value(v, read_uint32(&reader->p));
1325 fprintf(stderr,
"%d: unsupported form: %#"PRIx64
"\n", __LINE__, form);
1331di_find_abbrev(DebugInfoReader *reader, uint64_t abbrev_number)
1334 if (abbrev_number < ABBREV_TABLE_SIZE) {
1335 return reader->abbrev_table[abbrev_number];
1337 p = reader->abbrev_table[ABBREV_TABLE_SIZE-1];
1341 di_skip_die_attributes(&p);
1342 for (uint64_t n = uleb128(&p); abbrev_number != n; n = uleb128(&p)) {
1344 fprintf(stderr,
"%d: Abbrev Number %"PRId64
" not found\n",__LINE__, abbrev_number);
1349 di_skip_die_attributes(&p);
1356hexdump0(
const unsigned char *p,
size_t n)
1359 fprintf(stderr,
" 0 1 2 3 4 5 6 7 8 9 A B C D E F\n");
1360 for (i=0; i < n; i++){
1363 fprintf(stderr,
"%02" PRIdSIZE
": %02X ", i/16, p[i]);
1366 fprintf(stderr,
"%02X\n", p[i]);
1369 fprintf(stderr,
"%02X ", p[i]);
1373 if ((i & 15) != 15) {
1374 fprintf(stderr,
"\n");
1377#define hexdump(p,n) hexdump0((const unsigned char *)p, n)
1380div_inspect(DebugInfoValue *v)
1384 fprintf(stderr,
"%d: type:%d size:%" PRIxSIZE
" v:%"PRIx64
"\n",__LINE__,v->type,v->size,v->as.uint64);
1387 fprintf(stderr,
"%d: type:%d size:%" PRIxSIZE
" v:%"PRId64
"\n",__LINE__,v->type,v->size,(int64_t)v->as.uint64);
1390 fprintf(stderr,
"%d: type:%d size:%" PRIxSIZE
" v:'%s'\n",__LINE__,v->type,v->size,v->as.ptr);
1393 fprintf(stderr,
"%d: type:%d size:%" PRIxSIZE
" v:\n",__LINE__,v->type,v->size);
1394 hexdump(v->as.ptr, 16);
1401di_read_die(DebugInfoReader *reader, DIE *die)
1403 uint64_t abbrev_number = uleb128(&reader->p);
1404 if (abbrev_number == 0) {
1409 reader->q = di_find_abbrev(reader, abbrev_number);
1411 die->pos = reader->p - reader->obj->debug_info.ptr - 1;
1412 die->tag = (int)uleb128(&reader->q);
1413 die->has_children = *reader->q++;
1414 if (die->has_children) {
1420static DebugInfoValue *
1421di_read_record(DebugInfoReader *reader, DebugInfoValue *vp)
1423 uint64_t at = uleb128(&reader->q);
1424 uint64_t form = uleb128(&reader->q);
1425 if (!at || !form)
return NULL;
1428 debug_info_reader_read_value(reader, form, vp);
1433di_skip_records(DebugInfoReader *reader)
1436 DebugInfoValue v = {{}};
1437 uint64_t at = uleb128(&reader->q);
1438 uint64_t form = uleb128(&reader->q);
1439 if (!at || !form)
return;
1440 debug_info_reader_read_value(reader, form, &v);
1444typedef struct addr_header {
1446 uint64_t unit_length;
1448 uint8_t address_size;
1453addr_header_init(obj_info_t *obj, addr_header_t *header) {
1454 const char *p = obj->debug_addr.ptr;
1460 header->unit_length = *(uint32_t *)p;
1461 p +=
sizeof(uint32_t);
1464 if (header->unit_length == 0xffffffff) {
1465 header->unit_length = *(uint64_t *)p;
1466 p +=
sizeof(uint64_t);
1471 header->address_size = *p++;
1476read_addr(addr_header_t *header, uint64_t addr_base, uint64_t idx) {
1477 if (header->address_size == 4) {
1478 return ((uint32_t*)(header->ptr + addr_base))[idx];
1481 return ((uint64_t*)(header->ptr + addr_base))[idx];
1485typedef struct rnglists_header {
1486 uint64_t unit_length;
1488 uint8_t address_size;
1489 uint32_t offset_entry_count;
1493rnglists_header_init(obj_info_t *obj, rnglists_header_t *header) {
1494 const char *p = obj->debug_rnglists.ptr;
1498 header->unit_length = *(uint32_t *)p;
1499 p +=
sizeof(uint32_t);
1502 if (header->unit_length == 0xffffffff) {
1503 header->unit_length = *(uint64_t *)p;
1504 p +=
sizeof(uint64_t);
1509 header->address_size = *p++;
1511 header->offset_entry_count = *(uint32_t *)p;
1524ranges_set(ranges_t *ptr, DebugInfoValue *v, addr_header_t *addr_header, uint64_t addr_base)
1527 if (v->type == VAL_uint) {
1530 else if (v->type == VAL_addr) {
1531 n = read_addr(addr_header, addr_base, v->as.addr_idx);
1536 ptr->low_pc_set =
true;
1539 if (v->form == DW_FORM_addr) {
1543 ptr->high_pc = ptr->low_pc + n;
1545 ptr->high_pc_set =
true;
1549 ptr->ranges_set =
true;
1555read_dw_form_addr(DebugInfoReader *reader,
const char **ptr)
1557 const char *p = *ptr;
1558 *ptr = p + reader->address_size;
1559 if (reader->address_size == 4) {
1560 return read_uint32(&p);
1561 }
else if (reader->address_size == 8) {
1562 return read_uint64(&p);
1564 fprintf(stderr,
"unknown address_size:%d", reader->address_size);
1570ranges_include(DebugInfoReader *reader, ranges_t *ptr, uint64_t addr, rnglists_header_t *rnglists_header)
1572 if (ptr->high_pc_set) {
1573 if (ptr->ranges_set || !ptr->low_pc_set) {
1576 if (ptr->low_pc <= addr && addr <= ptr->high_pc) {
1577 return (uintptr_t)ptr->low_pc;
1580 else if (ptr->ranges_set) {
1583 uint64_t base = ptr->low_pc_set ? ptr->low_pc : reader->current_low_pc;
1584 bool base_valid =
true;
1585 if (reader->current_version >= 5) {
1586 if (rnglists_header->offset_entry_count == 0) {
1588 p = reader->obj->debug_rnglists.ptr + ptr->ranges + reader->current_rnglists_base;
1592 const char *offset_array = reader->obj->debug_rnglists.ptr + reader->current_rnglists_base;
1593 if (rnglists_header->format == 4) {
1594 p = offset_array + ((uint32_t *)offset_array)[ptr->ranges];
1597 p = offset_array + ((uint64_t *)offset_array)[ptr->ranges];
1601 uint8_t rle = read_uint8(&p);
1602 uintptr_t from = 0, to = 0;
1603 if (rle == DW_RLE_end_of_list)
break;
1605 case DW_RLE_base_addressx:
1609 case DW_RLE_startx_endx:
1613 case DW_RLE_startx_length:
1617 case DW_RLE_offset_pair:
1618 if (!base_valid)
break;
1619 from = (uintptr_t)base + uleb128(&p);
1620 to = (uintptr_t)base + uleb128(&p);
1622 case DW_RLE_base_address:
1623 base = read_dw_form_addr(reader, &p);
1626 case DW_RLE_start_end:
1627 from = (uintptr_t)read_dw_form_addr(reader, &p);
1628 to = (uintptr_t)read_dw_form_addr(reader, &p);
1630 case DW_RLE_start_length:
1631 from = (uintptr_t)read_dw_form_addr(reader, &p);
1632 to = from + uleb128(&p);
1635 if (from <= addr && addr < to) {
1641 p = reader->obj->debug_ranges.ptr + ptr->ranges;
1643 uintptr_t from = read_uintptr(&p);
1644 uintptr_t to = read_uintptr(&p);
1645 if (!from && !to)
break;
1646 if (from == UINTPTR_MAX) {
1650 else if (base + from <= addr && addr < base + to) {
1651 return (uintptr_t)base + from;
1655 else if (ptr->low_pc_set) {
1656 if (ptr->low_pc == addr) {
1657 return (uintptr_t)ptr->low_pc;
1665ranges_inspect(DebugInfoReader *reader, ranges_t *ptr)
1667 if (ptr->high_pc_set) {
1668 if (ptr->ranges_set || !ptr->low_pc_set) {
1669 fprintf(stderr,
"low_pc_set:%d high_pc_set:%d ranges_set:%d\n",ptr->low_pc_set,ptr->high_pc_set,ptr->ranges_set);
1672 fprintf(stderr,
"low_pc:%"PRIx64
" high_pc:%"PRIx64
"\n",ptr->low_pc,ptr->high_pc);
1674 else if (ptr->ranges_set) {
1675 char *p = reader->obj->debug_ranges.ptr + ptr->ranges;
1676 fprintf(stderr,
"low_pc:%"PRIx64
" ranges:%"PRIx64
" %lx ",ptr->low_pc,ptr->ranges, p-reader->obj->mapped);
1678 uintptr_t from = read_uintptr(&p);
1679 uintptr_t to = read_uintptr(&p);
1680 if (!from && !to)
break;
1681 fprintf(stderr,
"%"PRIx64
"-%"PRIx64
" ",ptr->low_pc+from,ptr->low_pc+to);
1683 fprintf(stderr,
"\n");
1685 else if (ptr->low_pc_set) {
1686 fprintf(stderr,
"low_pc:%"PRIx64
"\n",ptr->low_pc);
1689 fprintf(stderr,
"empty\n");
1695di_read_cu(DebugInfoReader *reader)
1697 uint64_t unit_length;
1699 uint64_t debug_abbrev_offset;
1701 reader->current_cu = reader->p;
1702 unit_length = read_uint32(&reader->p);
1703 if (unit_length == 0xffffffff) {
1704 unit_length = read_uint64(&reader->p);
1707 reader->cu_end = reader->p + unit_length;
1708 version = read_uint16(&reader->p);
1709 reader->current_version = version;
1713 else if (version == 5) {
1714 read_uint8(&reader->p);
1715 reader->address_size = read_uint8(&reader->p);
1716 debug_abbrev_offset = read_uint(reader);
1719 debug_abbrev_offset = read_uint(reader);
1720 reader->address_size = read_uint8(&reader->p);
1722 reader->q0 = reader->obj->debug_abbrev.ptr + debug_abbrev_offset;
1725 di_read_debug_abbrev_cu(reader);
1726 if (di_read_debug_line_cu(reader))
return -1;
1728#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER_BUILD_DATE)
1735 if (!di_read_die(reader, &die))
continue;
1737 if (die.tag != DW_TAG_compile_unit) {
1738 di_skip_records(reader);
1742 reader->current_str_offsets_base = 0;
1743 reader->current_addr_base = 0;
1744 reader->current_rnglists_base = 0;
1746 DebugInfoValue low_pc = {{}};
1749 DebugInfoValue v = {{}};
1750 if (!di_read_record(reader, &v))
break;
1757 case DW_AT_str_offsets_base:
1758 reader->current_str_offsets_base = v.as.uint64;
1760 case DW_AT_addr_base:
1761 reader->current_addr_base = v.as.uint64;
1763 case DW_AT_rnglists_base:
1764 reader->current_rnglists_base = v.as.uint64;
1769 switch (low_pc.type) {
1771 reader->current_low_pc = low_pc.as.uint64;
1775 addr_header_t header;
1776 addr_header_init(reader->obj, &header);
1777 reader->current_low_pc = read_addr(&header, reader->current_addr_base, low_pc.as.addr_idx);
1787read_abstract_origin(DebugInfoReader *reader, uint64_t form, uint64_t abstract_origin, line_info_t *line)
1789 const char *p = reader->p;
1790 const char *q = reader->q;
1791 int level = reader->level;
1799 case DW_FORM_ref_udata:
1800 reader->p = reader->current_cu + abstract_origin;
1802 case DW_FORM_ref_addr:
1804 case DW_FORM_ref_sig8:
1806 case DW_FORM_ref_sup4:
1807 case DW_FORM_ref_sup8:
1812 if (!di_read_die(reader, &die))
goto finish;
1816 DebugInfoValue v = {{}};
1817 if (!di_read_record(reader, &v))
break;
1820 line->sname = get_cstr_value(&v);
1828 reader->level = level;
1832debug_info_read(DebugInfoReader *reader,
int num_traces,
void **traces,
1833 line_info_t *lines,
int offset) {
1835 addr_header_t addr_header = {};
1836 addr_header_init(reader->obj, &addr_header);
1838 rnglists_header_t rnglists_header = {};
1839 rnglists_header_init(reader->obj, &rnglists_header);
1841 while (reader->p < reader->cu_end) {
1843 ranges_t ranges = {};
1844 line_info_t line = {};
1846 if (!di_read_die(reader, &die))
continue;
1849 if (die.tag != DW_TAG_subprogram && die.tag != DW_TAG_inlined_subroutine) {
1851 di_skip_records(reader);
1857 DebugInfoValue v = {{}};
1859 if (!di_read_record(reader, &v))
break;
1864 line.sname = get_cstr_value(&v);
1866 case DW_AT_call_file:
1867 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);
1869 case DW_AT_call_line:
1870 line.line = (int)v.as.uint64;
1875 ranges_set(&ranges, &v, &addr_header, reader->current_addr_base);
1877 case DW_AT_declaration:
1882 case DW_AT_abstract_origin:
1883 read_abstract_origin(reader, v.form, v.as.uint64, &line);
1889 for (
int i=offset; i < num_traces; i++) {
1890 uintptr_t addr = (uintptr_t)traces[i];
1891 uintptr_t offset = addr - reader->obj->base_addr + reader->obj->vmaddr;
1892 uintptr_t saddr = ranges_include(reader, &ranges, offset, &rnglists_header);
1895 if (lines[i].sname) {
1896 line_info_t *lp = malloc(
sizeof(line_info_t));
1897 memcpy(lp, &lines[i],
sizeof(line_info_t));
1899 lp->dirname = line.dirname;
1900 lp->filename = line.filename;
1901 lp->line = line.line;
1904 lines[i].path = reader->obj->path;
1905 lines[i].base_addr = line.base_addr;
1906 lines[i].sname = line.sname;
1907 lines[i].saddr = saddr + reader->obj->base_addr - reader->obj->vmaddr;
1929parse_ver5_debug_line_header(
const char *p,
int idx, uint8_t format, obj_info_t *obj,
const char **out_path, uint64_t *out_directory_index) {
1931 int entry_format_count = *(uint8_t *)p++;
1932 const char *entry_format = p;
1935 for (i = 0; i < entry_format_count * 2; i++) uleb128(&p);
1937 int entry_count = (int)uleb128(&p);
1939 DebugInfoReader reader;
1940 debug_info_reader_init(&reader, obj);
1941 reader.format = format;
1943 for (j = 0; j < entry_count; j++) {
1944 const char *format = entry_format;
1945 for (i = 0; i < entry_format_count; i++) {
1946 DebugInfoValue v = {{}};
1947 unsigned long dw_lnct = uleb128(&format);
1948 unsigned long dw_form = uleb128(&format);
1949 debug_info_reader_read_value(&reader, dw_form, &v);
1950 if (dw_lnct == 1 && v.type == VAL_cstr && out_path)
1951 *out_path = v.as.ptr + v.off;
1952 if (dw_lnct == 2 && v.type == VAL_uint && out_directory_index)
1953 *out_directory_index = v.as.uint64;
1955 if (j == idx)
return 0;
1963uncompress_debug_section(ElfW(Shdr) *shdr,
char *file,
char **ptr)
1966#ifdef SUPPORT_COMPRESSED_DEBUG_LINE
1967 ElfW(Chdr) *chdr = (ElfW(Chdr) *)(file + shdr->sh_offset);
1968 unsigned long destsize = chdr->ch_size;
1971 if (chdr->ch_type != ELFCOMPRESS_ZLIB) {
1976 *ptr = malloc(destsize);
1977 if (!*ptr)
return 0;
1978 ret = uncompress((Bytef *)*ptr, &destsize,
1979 (
const Bytef*)chdr +
sizeof(ElfW(Chdr)),
1980 shdr->sh_size -
sizeof(ElfW(Chdr)));
1981 if (ret != Z_OK)
goto fail;
1993fill_lines(
int num_traces,
void **traces,
int check_debuglink,
1994 obj_info_t **objp, line_info_t *lines,
int offset)
1999 ElfW(Shdr) *shdr, *shstr_shdr;
2000 ElfW(Shdr) *gnu_debuglink_shdr = NULL;
2001 ElfW(Shdr) *note_gnu_build_id = NULL;
2005 ElfW(Shdr) *symtab_shdr = NULL, *strtab_shdr = NULL;
2006 ElfW(Shdr) *dynsym_shdr = NULL, *dynstr_shdr = NULL;
2007 obj_info_t *obj = *objp;
2008 uintptr_t dladdr_fbase = 0;
2010 fd = open(binary_filename, O_RDONLY);
2014 filesize = lseek(fd, 0, SEEK_END);
2018 kprintf(
"lseek: %s\n", strerror(e));
2021#if SIZEOF_OFF_T > SIZEOF_SIZE_T
2022 if (filesize > (off_t)SIZE_MAX) {
2024 kprintf(
"Too large file %s\n", binary_filename);
2028 lseek(fd, 0, SEEK_SET);
2030 file = (
char *)mmap(NULL, (
size_t)filesize, PROT_READ, MAP_SHARED, fd, 0);
2031 if (file == MAP_FAILED) {
2034 kprintf(
"mmap: %s\n", strerror(e));
2039 ehdr = (ElfW(Ehdr) *)file;
2040 if (memcmp(ehdr->e_ident,
"\177ELF", 4) != 0) {
2048 obj->mapped_size = (size_t)filesize;
2050 shdr = (ElfW(Shdr) *)(file + ehdr->e_shoff);
2052 shstr_shdr = shdr + ehdr->e_shstrndx;
2053 shstr = file + shstr_shdr->sh_offset;
2055 for (i = 0; i < ehdr->e_shnum; i++) {
2056 char *section_name = shstr + shdr[i].sh_name;
2057 switch (shdr[i].sh_type) {
2059 if (!strcmp(section_name,
".strtab")) {
2060 strtab_shdr = shdr + i;
2062 else if (!strcmp(section_name,
".dynstr")) {
2063 dynstr_shdr = shdr + i;
2068 symtab_shdr = shdr + i;
2072 dynsym_shdr = shdr + i;
2075 if (!strcmp(section_name,
".note.gnu.build-id")) {
2076 note_gnu_build_id = shdr + i;
2080 if (!strcmp(section_name,
".gnu_debuglink")) {
2081 gnu_debuglink_shdr = shdr + i;
2084 const char *debug_section_names[] = {
2089 ".debug_str_offsets",
2096 for (j=0; j < DWARF_SECTION_COUNT; j++) {
2097 struct dwarf_section *s = obj_dwarf_section_at(obj, j);
2099 if (strcmp(section_name, debug_section_names[j]) != 0)
2102 s->ptr = file + shdr[i].sh_offset;
2103 s->size = shdr[i].sh_size;
2104 s->flags = shdr[i].sh_flags;
2105 if (s->flags & SHF_COMPRESSED) {
2106 s->size = uncompress_debug_section(&shdr[i], file, &s->ptr);
2107 if (!s->size)
goto fail;
2119 if (dynsym_shdr && dynstr_shdr) {
2120 char *strtab = file + dynstr_shdr->sh_offset;
2121 ElfW(Sym) *symtab = (ElfW(Sym) *)(file + dynsym_shdr->sh_offset);
2122 int symtab_count = (int)(dynsym_shdr->sh_size /
sizeof(ElfW(Sym)));
2123 void *handle = dlopen(NULL, RTLD_NOW|RTLD_LOCAL);
2125 for (j = 0; j < symtab_count; j++) {
2126 ElfW(Sym) *sym = &symtab[j];
2129 if (ELF_ST_TYPE(sym->st_info) != STT_FUNC || sym->st_size == 0)
continue;
2130 s = dlsym(handle, strtab + sym->st_name);
2131 if (s && dladdr(s, &info)) {
2132 obj->base_addr = dladdr_fbase;
2133 dladdr_fbase = (uintptr_t)info.dli_fbase;
2139 if (ehdr->e_type == ET_EXEC) {
2144 obj->base_addr = dladdr_fbase;
2149 if (obj->debug_info.ptr && obj->debug_abbrev.ptr) {
2150 DebugInfoReader reader;
2151 debug_info_reader_init(&reader, obj);
2153 while (reader.p < reader.pend) {
2155 if (di_read_cu(&reader))
goto use_symtab;
2156 debug_info_read(&reader, num_traces, traces, lines, offset);
2164 symtab_shdr = dynsym_shdr;
2165 strtab_shdr = dynstr_shdr;
2168 if (symtab_shdr && strtab_shdr) {
2169 char *strtab = file + strtab_shdr->sh_offset;
2170 ElfW(Sym) *symtab = (ElfW(Sym) *)(file + symtab_shdr->sh_offset);
2171 int symtab_count = (int)(symtab_shdr->sh_size /
sizeof(ElfW(Sym)));
2172 for (j = 0; j < symtab_count; j++) {
2173 ElfW(Sym) *sym = &symtab[j];
2174 uintptr_t saddr = (uintptr_t)sym->st_value + obj->base_addr;
2175 if (ELF_ST_TYPE(sym->st_info) != STT_FUNC)
continue;
2176 for (i = offset; i < num_traces; i++) {
2177 uintptr_t d = (uintptr_t)traces[i] - saddr;
2178 if (lines[i].line > 0 || d > (uintptr_t)sym->st_size)
2181 if (!lines[i].sname) lines[i].sname = strtab + sym->st_name;
2182 lines[i].saddr = saddr;
2183 lines[i].path = obj->path;
2184 lines[i].base_addr = obj->base_addr;
2190 if (!obj->debug_line.ptr) {
2193 if (gnu_debuglink_shdr && check_debuglink) {
2194 follow_debuglink(file + gnu_debuglink_shdr->sh_offset,
2196 objp, lines, offset);
2198 if (note_gnu_build_id && check_debuglink) {
2199 ElfW(Nhdr) *nhdr = (ElfW(Nhdr)*) (file + note_gnu_build_id->sh_offset);
2200 const char *build_id = (
char *)(nhdr + 1) + nhdr->n_namesz;
2201 follow_debuglink_build_id(build_id, nhdr->n_descsz,
2203 objp, lines, offset);
2208 if (parse_debug_line(num_traces, traces,
2209 obj->debug_line.ptr,
2210 obj->debug_line.size,
2211 obj, lines, offset) == -1)
2215 return dladdr_fbase;
2217 return (uintptr_t)-1;
2222fill_lines(
int num_traces,
void **traces,
int check_debuglink,
2223 obj_info_t **objp, line_info_t *lines,
int offset)
2226# define LP(x) x##_64
2232 char *file, *p = NULL;
2233 obj_info_t *obj = *objp;
2234 struct LP(mach_header) *header;
2235 uintptr_t dladdr_fbase = 0;
2238 char *s = binary_filename;
2239 char *base = strrchr(binary_filename,
'/')+1;
2240 size_t max = PATH_MAX;
2241 size_t size = strlen(binary_filename);
2242 size_t basesize = size - (base - binary_filename);
2246 size = strlcpy(s,
".dSYM/Contents/Resources/DWARF/", max);
2247 if (size == 0)
goto fail;
2250 if (max <= basesize)
goto fail;
2251 memcpy(s, base, basesize);
2254 fd = open(binary_filename, O_RDONLY);
2257 fd = open(binary_filename, O_RDONLY);
2264 filesize = lseek(fd, 0, SEEK_END);
2268 kprintf(
"lseek: %s\n", strerror(e));
2271#if SIZEOF_OFF_T > SIZEOF_SIZE_T
2272 if (filesize > (off_t)SIZE_MAX) {
2274 kprintf(
"Too large file %s\n", binary_filename);
2278 lseek(fd, 0, SEEK_SET);
2280 file = (
char *)mmap(NULL, (
size_t)filesize, PROT_READ, MAP_SHARED, fd, 0);
2281 if (file == MAP_FAILED) {
2284 kprintf(
"mmap: %s\n", strerror(e));
2290 obj->mapped_size = (size_t)filesize;
2292 header = (
struct LP(mach_header) *)file;
2293 if (header->magic == LP(MH_MAGIC)) {
2297 else if (header->magic == FAT_CIGAM) {
2298 struct LP(mach_header) *mhp = _NSGetMachExecuteHeader();
2299 struct fat_header *fat = (
struct fat_header *)file;
2300 char *q = file +
sizeof(*fat);
2301 uint32_t nfat_arch = __builtin_bswap32(fat->nfat_arch);
2303 for (uint32_t i = 0; i < nfat_arch; i++) {
2304 struct fat_arch *arch = (
struct fat_arch *)q;
2305 cpu_type_t cputype = __builtin_bswap32(arch->cputype);
2306 cpu_subtype_t cpusubtype = __builtin_bswap32(arch->cpusubtype);
2307 uint32_t offset = __builtin_bswap32(arch->offset);
2309 if (mhp->cputype == cputype &&
2310 (cpu_subtype_t)(mhp->cpusubtype & ~CPU_SUBTYPE_MASK) == cpusubtype) {
2313 header = (
struct LP(mach_header) *)p;
2314 if (header->magic == LP(MH_MAGIC)) {
2315 goto found_mach_header;
2321 kprintf(
"'%s' is not a Mach-O universal binary file!\n",binary_filename);
2326 kprintf(
"'%s' is not a "
2332 "-bit Mach-O file!\n",binary_filename);
2337 p +=
sizeof(*header);
2339 for (uint32_t i = 0; i < (uint32_t)header->ncmds; i++) {
2340 struct load_command *lcmd = (
struct load_command *)p;
2341 switch (lcmd->cmd) {
2342 case LP(LC_SEGMENT):
2344 static const char *debug_section_names[] = {
2349 "__debug_str_offsets",
2355 struct LP(segment_command) *scmd = (
struct LP(segment_command) *)lcmd;
2356 if (strcmp(scmd->segname,
"__TEXT") == 0) {
2357 obj->vmaddr = scmd->vmaddr;
2359 else if (strcmp(scmd->segname,
"__DWARF") == 0) {
2360 p +=
sizeof(
struct LP(segment_command));
2361 for (uint64_t i = 0; i < scmd->nsects; i++) {
2362 struct LP(section) *sect = (
struct LP(section) *)p;
2363 p +=
sizeof(
struct LP(section));
2364 for (
int j=0; j < DWARF_SECTION_COUNT; j++) {
2365 struct dwarf_section *s = obj_dwarf_section_at(obj, j);
2367 if (strcmp(sect->sectname, debug_section_names[j]) != 0)
2370 s->ptr = file + sect->offset;
2371 s->size = sect->size;
2372 s->flags = sect->flags;
2373 if (s->flags & SHF_COMPRESSED) {
2385 struct symtab_command *cmd = (
struct symtab_command *)lcmd;
2386 struct LP(nlist) *nl = (
struct LP(nlist) *)(file + cmd->symoff);
2387 char *strtab = file + cmd->stroff, *sname = 0;
2389 uintptr_t saddr = 0;
2391 for (j = 0; j < cmd->nsyms; j++) {
2392 uintptr_t symsize, d;
2393 struct LP(nlist) *e = &nl[j];
2395 if (e->n_type != N_FUN)
continue;
2397 saddr = (uintptr_t)e->n_value + obj->base_addr - obj->vmaddr;
2398 sname = strtab + e->n_un.n_strx;
2402 for (
int k = offset; k < num_traces; k++) {
2403 d = (uintptr_t)traces[k] - saddr;
2404 symsize = e->n_value;
2406 if (lines[k].line > 0 || d > (uintptr_t)symsize)
2409 if (!lines[k].sname) lines[k].sname = sname;
2410 lines[k].saddr = saddr;
2411 lines[k].path = obj->path;
2412 lines[k].base_addr = obj->base_addr;
2420 if (obj->debug_info.ptr && obj->debug_abbrev.ptr) {
2421 DebugInfoReader reader;
2422 debug_info_reader_init(&reader, obj);
2423 while (reader.p < reader.pend) {
2424 if (di_read_cu(&reader))
goto fail;
2425 debug_info_read(&reader, num_traces, traces, lines, offset);
2429 if (parse_debug_line(num_traces, traces,
2430 obj->debug_line.ptr,
2431 obj->debug_line.size,
2432 obj, lines, offset) == -1)
2435 return dladdr_fbase;
2437 return (uintptr_t)-1;
2441#define HAVE_MAIN_EXE_PATH
2442#if defined(__FreeBSD__) || defined(__DragonFly__)
2443# include <sys/sysctl.h>
2451#if defined(__linux__) || defined(__NetBSD__)
2455# if defined(__linux__)
2456# define PROC_SELF_EXE "/proc/self/exe"
2457# elif defined(__NetBSD__)
2458# define PROC_SELF_EXE "/proc/curproc/exe"
2460 ssize_t len = readlink(PROC_SELF_EXE, binary_filename, PATH_MAX);
2461 if (len < 0)
return 0;
2462 binary_filename[len] = 0;
2465#elif defined(__FreeBSD__) || defined(__DragonFly__)
2469 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
2470 size_t len = PATH_MAX;
2471 int err = sysctl(mib, 4, binary_filename, &len, NULL, 0);
2473 kprintf(
"Can't get the path of ruby");
2479#elif defined(HAVE_LIBPROC_H)
2483 int len = proc_pidpath(getpid(), binary_filename, PATH_MAX);
2484 if (len == 0)
return 0;
2485 binary_filename[len] = 0;
2489#undef HAVE_MAIN_EXE_PATH
2493print_line0(line_info_t *line,
void *address)
2495 uintptr_t addr = (uintptr_t)address;
2496 uintptr_t d = addr - line->saddr;
2499 if (line->dirname && line->dirname[0]) {
2500 kprintf(
"%s(%s) %s/%s:%d\n", line->path, line->sname, line->dirname, line->filename, line->line);
2503 kprintf(
"%s(%s) %s:%d\n", line->path, line->sname, line->filename, line->line);
2506 else if (!line->path) {
2507 kprintf(
"[0x%"PRIxPTR
"]\n", addr);
2509 else if (!line->sname) {
2510 kprintf(
"%s(0x%"PRIxPTR
") [0x%"PRIxPTR
"]\n", line->path, addr-line->base_addr, addr);
2512 else if (!line->saddr) {
2513 kprintf(
"%s(%s) [0x%"PRIxPTR
"]\n", line->path, line->sname, addr);
2515 else if (line->line <= 0) {
2516 kprintf(
"%s(%s+0x%"PRIxPTR
") [0x%"PRIxPTR
"]\n", line->path, line->sname,
2519 else if (!line->filename) {
2520 kprintf(
"%s(%s+0x%"PRIxPTR
") [0x%"PRIxPTR
"] ???:%d\n", line->path, line->sname,
2521 d, addr, line->line);
2523 else if (line->dirname && line->dirname[0]) {
2524 kprintf(
"%s(%s+0x%"PRIxPTR
") [0x%"PRIxPTR
"] %s/%s:%d\n", line->path, line->sname,
2525 d, addr, line->dirname, line->filename, line->line);
2528 kprintf(
"%s(%s+0x%"PRIxPTR
") [0x%"PRIxPTR
"] %s:%d\n", line->path, line->sname,
2529 d, addr, line->filename, line->line);
2534print_line(line_info_t *line,
void *address)
2536 print_line0(line, address);
2538 print_line(line->next, NULL);
2543rb_dump_backtrace_with_lines(
int num_traces,
void **traces)
2547 line_info_t *lines = (line_info_t *)calloc(num_traces,
sizeof(line_info_t));
2548 obj_info_t *obj = NULL;
2550 void **dladdr_fbases = (
void **)calloc(num_traces+2,
sizeof(
void *));
2552#ifdef HAVE_MAIN_EXE_PATH
2553 char *main_path = NULL;
2555 if ((len = main_exe_path()) > 0) {
2556 main_path = (
char *)alloca(len + 1);
2559 memcpy(main_path, binary_filename, len+1);
2561 obj->path = main_path;
2562 addr = fill_lines(num_traces, traces, 1, &obj, lines, -1);
2563 if (addr != (uintptr_t)-1) {
2564 dladdr_fbases[0] = (
void *)addr;
2571 for (i = 0; i < num_traces; i++) {
2573 if (lines[i].line)
continue;
2574 if (dladdr(traces[i], &info)) {
2580 for (p=dladdr_fbases; *p; p++) {
2581 if (*p == info.dli_fbase) {
2582 if (info.dli_fname) lines[i].path = info.dli_fname;
2583 if (info.dli_sname) lines[i].sname = info.dli_sname;
2587 *p = info.dli_fbase;
2590 obj->base_addr = (uintptr_t)info.dli_fbase;
2591 path = info.dli_fname;
2593 if (path) lines[i].path = path;
2594 if (info.dli_sname) {
2595 lines[i].sname = info.dli_sname;
2596 lines[i].saddr = (uintptr_t)info.dli_saddr;
2598 strlcpy(binary_filename, path, PATH_MAX);
2599 if (fill_lines(num_traces, traces, 1, &obj, lines, i) == (uintptr_t)-1)
2607 for (i = 0; i < num_traces; i++) {
2608 print_line(&lines[i], traces[i]);
2611 if (lines[i].sname && strcmp(
"main", lines[i].sname) == 0)
2617 obj_info_t *o = obj;
2618 for (i=0; i < DWARF_SECTION_COUNT; i++) {
2619 struct dwarf_section *s = obj_dwarf_section_at(obj, i);
2620 if (s->flags & SHF_COMPRESSED) {
2624 if (obj->mapped_size) {
2625 munmap(obj->mapped, obj->mapped_size);
2630 for (i = 0; i < num_traces; i++) {
2631 line_info_t *line = lines[i].next;
2633 line_info_t *l = line;
2639 free(dladdr_fbases);
2680#define MAXNBUF (sizeof(intmax_t) * CHAR_BIT + 1)
2681static inline int toupper(
int c) {
return (
'A' <= c && c <=
'Z') ? (c&0x5f) : c; }
2682#define hex2ascii(hex) (hex2ascii_data[hex])
2683static const char hex2ascii_data[] =
"0123456789abcdefghijklmnopqrstuvwxyz";
2684static inline int imax(
int a,
int b) {
return (a > b ? a : b); }
2685static int kvprintf(
char const *fmt,
void (*func)(
int),
void *arg,
int radix, va_list ap);
2687static void putce(
int c)
2693 ret = write(2, s, 1);
2698kprintf(
const char *fmt, ...)
2704 retval = kvprintf(fmt, putce, NULL, 10, ap);
2716ksprintn(
char *nbuf, uintmax_t num,
int base,
int *lenp,
int upper)
2723 c = hex2ascii(num % base);
2724 *++p = upper ? toupper(c) : c;
2725 }
while (num /= base);
2727 *lenp = (int)(p - nbuf);
2758kvprintf(
char const *fmt,
void (*func)(
int),
void *arg,
int radix, va_list ap)
2760#define PCHAR(c) {int cc=(c); if (func) (*func)(cc); else *d++ = cc; retval++; }
2763 const char *p, *percent, *q;
2767 int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
2768 int cflag, hflag, jflag, tflag, zflag;
2771 int stop = 0, retval = 0;
2780 fmt =
"(fmt null)\n";
2782 if (radix < 2 || radix > 36)
2788 while ((ch = (
unsigned char)*fmt++) !=
'%' || stop) {
2794 qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
2795 sign = 0; dot = 0; dwidth = 0; upper = 0;
2796 cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
2797reswitch:
switch (ch = (
unsigned char)*fmt++) {
2815 width = va_arg(ap,
int);
2821 dwidth = va_arg(ap,
int);
2829 case '1':
case '2':
case '3':
case '4':
2830 case '5':
case '6':
case '7':
case '8':
case '9':
2831 for (n = 0;; ++fmt) {
2832 n = n * 10 + ch -
'0';
2834 if (ch <
'0' || ch >
'9')
2843 num = (
unsigned int)va_arg(ap,
int);
2844 p = va_arg(ap,
char *);
2845 for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
2851 for (tmp = 0; *p;) {
2853 if (num & (1 << (n - 1))) {
2854 PCHAR(tmp ?
',' :
'<');
2855 for (; (n = *p) >
' '; ++p)
2859 for (; *p >
' '; ++p)
2866 PCHAR(va_arg(ap,
int));
2869 up = va_arg(ap,
unsigned char *);
2870 p = va_arg(ap,
char *);
2874 PCHAR(hex2ascii(*up >> 4));
2875 PCHAR(hex2ascii(*up & 0x0f));
2906 *(va_arg(ap, intmax_t *)) = retval;
2908 *(va_arg(ap, int64_t *)) = retval;
2910 *(va_arg(ap,
long *)) = retval;
2912 *(va_arg(ap,
size_t *)) = retval;
2914 *(va_arg(ap,
short *)) = retval;
2916 *(va_arg(ap,
char *)) = retval;
2918 *(va_arg(ap,
int *)) = retval;
2925 sharpflag = (width == 0);
2927 num = (uintptr_t)va_arg(ap,
void *);
2938 p = va_arg(ap,
char *);
2942 n = (int)strlen (p);
2944 for (n = 0; n < dwidth && p[n]; n++)
2949 if (!ladjust && width > 0)
2954 if (ladjust && width > 0)
2979 num = va_arg(ap, uintmax_t);
2981 num = va_arg(ap, uint64_t);
2983 num = va_arg(ap, ptrdiff_t);
2985 num = va_arg(ap,
unsigned long);
2987 num = va_arg(ap,
size_t);
2989 num = (
unsigned short)va_arg(ap,
int);
2991 num = (
unsigned char)va_arg(ap,
int);
2993 num = va_arg(ap,
unsigned int);
2997 num = va_arg(ap, intmax_t);
2999 num = va_arg(ap, int64_t);
3001 num = va_arg(ap, ptrdiff_t);
3003 num = va_arg(ap,
long);
3005 num = va_arg(ap, ssize_t);
3007 num = (short)va_arg(ap,
int);
3009 num = (char)va_arg(ap,
int);
3011 num = va_arg(ap,
int);
3013 if (sign && (intmax_t)num < 0) {
3015 num = -(intmax_t)num;
3017 p = ksprintn(nbuf, num, base, &n, upper);
3019 if (sharpflag && num != 0) {
3022 else if (base == 16)
3028 if (!ladjust && padc ==
'0')
3029 dwidth = width - tmp;
3030 width -= tmp + imax(dwidth, n);
3037 if (sharpflag && num != 0) {
3040 }
else if (base == 16) {
3045 while (dwidth-- > 0)
3057 while (percent < fmt)
VALUE type(ANYARGS)
ANYARGS-ed function type.