12#pragma clang diagnostic ignored "-Wgnu-empty-initializer"
13#pragma clang diagnostic ignored "-Wgcc-compat"
30#if defined(USE_ELF) || defined(HAVE_MACH_O_LOADER_H)
46# define alloca __builtin_alloca
66#ifdef HAVE_MACH_O_LOADER_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 {
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;
163 struct obj_info *next;
166#define DWARF_SECTION_COUNT 5
168static struct dwarf_section *
169obj_dwarf_section_at(obj_info_t *obj,
int n)
171 struct dwarf_section *ary[] = {
178 if (n < 0 || DWARF_SECTION_COUNT <= n) {
184struct debug_section_definition {
186 struct dwarf_section *dwarf;
190static char binary_filename[
PATH_MAX + 1];
198 unsigned char b = *(
unsigned char *)(*p)++;
200 r += (
unsigned long)b << s;
203 r += (b & 0x7f) << s;
215 unsigned char b = *(
unsigned char *)(*p)++;
218 r -= (0x80 - b) << s;
221 r += (b & 0x3f) << s;
225 r += (b & 0x7f) << s;
232get_nth_dirname(
unsigned long dir,
char *p)
241 kprintf(
"Unexpected directory number %lu in %s\n",
242 dir, binary_filename);
250fill_filename(
int file,
char *include_directories,
char *filenames, line_info_t *line, obj_info_t *obj)
256 for (i = 1; i <=
file; i++) {
260 kprintf(
"Unexpected file number %d in %s at %tx\n",
261 file, binary_filename, filenames - obj->mapped);
274 line->dirname = get_nth_dirname(dir, include_directories);
280fill_line(
int num_traces,
void **traces,
uintptr_t addr,
int file,
int line,
281 char *include_directories,
char *filenames,
282 obj_info_t *obj, line_info_t *lines,
int offset)
285 addr += obj->base_addr - obj->vmaddr;
286 for (i =
offset; i < num_traces; i++) {
290 if (addr < a && a < addr + 100) {
291 fill_filename(
file, include_directories, filenames, &lines[i], obj);
292 lines[i].line = line;
297struct LineNumberProgramHeader {
302 uint8_t minimum_instruction_length;
303 uint8_t maximum_operations_per_instruction;
309 const char *include_directories;
310 const char *filenames;
311 const char *cu_start;
316parse_debug_line_header(
const char **pp,
struct LineNumberProgramHeader *header)
319 header->unit_length = *(
uint32_t *)p;
323 if (header->unit_length == 0xffffffff) {
324 header->unit_length = *(
uint64_t *)p;
329 header->cu_end = p + header->unit_length;
331 header->version = *(uint16_t *)p;
332 p +=
sizeof(uint16_t);
333 if (header->version > 4)
return -1;
335 header->header_length = header->format == 4 ? *(
uint32_t *)p : *(
uint64_t *)p;
337 header->cu_start = p + header->header_length;
339 header->minimum_instruction_length = *(
uint8_t *)p++;
341 if (header->version >= 4) {
343 if (*p != 1)
return -1;
347 header->default_is_stmt = *(
uint8_t *)p++;
348 header->line_base = *(int8_t *)p++;
349 header->line_range = *(
uint8_t *)p++;
350 header->opcode_base = *(
uint8_t *)p++;
352 p += header->opcode_base - 1;
354 header->include_directories = p;
357 if (p >= header->cu_end)
return -1;
361 p = memchr(p,
'\0', header->cu_end - p);
367 header->filenames = p;
369 *pp = header->cu_start;
375parse_debug_line_cu(
int num_traces,
void **traces,
char **debug_line,
376 obj_info_t *obj, line_info_t *lines,
int offset)
378 const char *p = (
const char *)*debug_line;
379 struct LineNumberProgramHeader header;
382 unsigned long addr = 0;
383 unsigned int file = 1;
384 unsigned int line = 1;
393 if (parse_debug_line_header(&p, &header))
395 is_stmt = header.default_is_stmt;
399 fill_line(num_traces, traces, addr, file, line, \
400 (char *)header.include_directories, \
401 (char *)header.filenames, \
402 obj, lines, offset); \
406 while (p < header.cu_end) {
408 unsigned char op = *p++;
413 case DW_LNS_advance_pc:
414 a = uleb128((
char **)&p);
417 case DW_LNS_advance_line: {
418 long a = sleb128((
char **)&p);
422 case DW_LNS_set_file:
423 file = (
unsigned int)uleb128((
char **)&p);
425 case DW_LNS_set_column:
426 (void)uleb128((
char **)&p);
428 case DW_LNS_negate_stmt:
431 case DW_LNS_set_basic_block:
434 case DW_LNS_const_add_pc:
435 a = ((255UL - header.opcode_base) / header.line_range) *
436 header.minimum_instruction_length;
439 case DW_LNS_fixed_advance_pc:
441 p +=
sizeof(uint16_t);
444 case DW_LNS_set_prologue_end:
447 case DW_LNS_set_epilogue_begin:
451 (void)uleb128((
char **)&p);
454 a = *(
unsigned char *)p++;
457 case DW_LNE_end_sequence:
464 is_stmt = header.default_is_stmt;
468 case DW_LNE_set_address:
469 addr = *(
unsigned long *)p;
470 p +=
sizeof(
unsigned long);
472 case DW_LNE_define_file:
473 kprintf(
"Unsupported operation in %s\n",
476 case DW_LNE_set_discriminator:
478 uleb128((
char **)&p);
481 kprintf(
"Unknown extended opcode: %d in %s\n",
482 op, binary_filename);
486 uint8_t adjusted_opcode = op - header.opcode_base;
487 uint8_t operation_advance = adjusted_opcode / header.line_range;
489 addr += operation_advance * header.minimum_instruction_length;
490 line += header.line_base + (adjusted_opcode % header.line_range);
495 *debug_line = (
char *)p;
500parse_debug_line(
int num_traces,
void **traces,
501 char *debug_line,
unsigned long size,
502 obj_info_t *obj, line_info_t *lines,
int offset)
504 char *debug_line_end = debug_line +
size;
505 while (debug_line < debug_line_end) {
506 if (parse_debug_line_cu(num_traces, traces, &debug_line, obj, lines,
offset))
509 if (debug_line != debug_line_end) {
510 kprintf(
"Unexpected size of .debug_line in %s\n",
518fill_lines(
int num_traces,
void **traces,
int check_debuglink,
519 obj_info_t **objp, line_info_t *lines,
int offset);
522append_obj(obj_info_t **objp)
524 obj_info_t *newobj =
calloc(1,
sizeof(obj_info_t));
525 if (*objp) (*objp)->next = newobj;
546follow_debuglink(
const char *debuglink,
int num_traces,
void **traces,
547 obj_info_t **objp, line_info_t *lines,
int offset)
549 static const char global_debug_dir[] =
"/usr/lib/debug";
550 const size_t global_debug_dir_len =
sizeof(global_debug_dir) - 1;
552 obj_info_t *
o1 = *objp, *
o2;
555 p =
strrchr(binary_filename,
'/');
564 memmove(binary_filename + global_debug_dir_len, binary_filename,
len);
565 memcpy(binary_filename, global_debug_dir, global_debug_dir_len);
566 len += global_debug_dir_len;
571 o2->base_addr =
o1->base_addr;
573 fill_lines(num_traces, traces, 0, objp, lines,
offset);
578follow_debuglink_build_id(
const char *build_id,
size_t build_id_size,
int num_traces,
void **traces,
579 obj_info_t **objp, line_info_t *lines,
int offset)
581 static const char global_debug_dir[] =
"/usr/lib/debug/.build-id/";
582 const size_t global_debug_dir_len =
sizeof(global_debug_dir) - 1;
584 obj_info_t *
o1 = *objp, *
o2;
587 if (
PATH_MAX < global_debug_dir_len + 1 + build_id_size * 2 + 6)
return;
589 memcpy(binary_filename, global_debug_dir, global_debug_dir_len);
590 p = binary_filename + global_debug_dir_len;
591 for (i = 0; i < build_id_size; i++) {
592 static const char tbl[] =
"0123456789abcdef";
593 unsigned char n = build_id[i];
596 if (i == 0) *p++ =
'/';
602 o2->base_addr =
o1->base_addr;
604 fill_lines(num_traces, traces, 0, objp, lines,
offset);
610 DW_TAG_compile_unit = 0x11,
611 DW_TAG_inlined_subroutine = 0x1d,
612 DW_TAG_subprogram = 0x2e,
618 DW_AT_sibling = 0x01,
619 DW_AT_location = 0x02,
626 DW_AT_ordering = 0x09,
628 DW_AT_byte_size = 0x0b,
630 DW_AT_bit_size = 0x0d,
633 DW_AT_stmt_list = 0x10,
635 DW_AT_high_pc = 0x12,
636 DW_AT_language = 0x13,
639 DW_AT_discr_value = 0x16,
640 DW_AT_visibility = 0x17,
642 DW_AT_string_length = 0x19,
643 DW_AT_common_reference = 0x1a,
644 DW_AT_comp_dir = 0x1b,
645 DW_AT_const_value = 0x1c,
646 DW_AT_containing_type = 0x1d,
647 DW_AT_default_value = 0x1e,
650 DW_AT_is_optional = 0x21,
651 DW_AT_lower_bound = 0x22,
654 DW_AT_producer = 0x25,
656 DW_AT_prototyped = 0x27,
659 DW_AT_return_addr = 0x2a,
661 DW_AT_start_scope = 0x2c,
663 DW_AT_bit_stride = 0x2e,
664 DW_AT_upper_bound = 0x2f,
666 DW_AT_abstract_origin = 0x31,
667 DW_AT_accessibility = 0x32,
668 DW_AT_address_class = 0x33,
669 DW_AT_artificial = 0x34,
670 DW_AT_base_types = 0x35,
671 DW_AT_calling_convention = 0x36,
673 DW_AT_data_member_location = 0x38,
674 DW_AT_decl_column = 0x39,
675 DW_AT_decl_file = 0x3a,
676 DW_AT_decl_line = 0x3b,
677 DW_AT_declaration = 0x3c,
678 DW_AT_discr_list = 0x3d,
679 DW_AT_encoding = 0x3e,
680 DW_AT_external = 0x3f,
681 DW_AT_frame_base = 0x40,
683 DW_AT_identifier_case = 0x42,
685 DW_AT_namelist_item = 0x44,
686 DW_AT_priority = 0x45,
687 DW_AT_segment = 0x46,
688 DW_AT_specification = 0x47,
689 DW_AT_static_link = 0x48,
691 DW_AT_use_location = 0x4a,
692 DW_AT_variable_parameter = 0x4b,
693 DW_AT_virtuality = 0x4c,
694 DW_AT_vtable_elem_location = 0x4d,
695 DW_AT_allocated = 0x4e,
696 DW_AT_associated = 0x4f,
697 DW_AT_data_location = 0x50,
698 DW_AT_byte_stride = 0x51,
699 DW_AT_entry_pc = 0x52,
700 DW_AT_use_UTF8 = 0x53,
701 DW_AT_extension = 0x54,
703 DW_AT_trampoline = 0x56,
704 DW_AT_call_column = 0x57,
705 DW_AT_call_file = 0x58,
706 DW_AT_call_line = 0x59,
707 DW_AT_description = 0x5a,
708 DW_AT_binary_scale = 0x5b,
709 DW_AT_decimal_scale = 0x5c,
711 DW_AT_decimal_sign = 0x5e,
712 DW_AT_digit_count = 0x5f,
713 DW_AT_picture_string = 0x60,
714 DW_AT_mutable = 0x61,
715 DW_AT_threads_scaled = 0x62,
716 DW_AT_explicit = 0x63,
717 DW_AT_object_pointer = 0x64,
718 DW_AT_endianity = 0x65,
719 DW_AT_elemental = 0x66,
721 DW_AT_recursive = 0x68,
722 DW_AT_signature = 0x69,
723 DW_AT_main_subprogram = 0x6a,
724 DW_AT_data_bit_offset = 0x6b,
725 DW_AT_const_expr = 0x6c,
726 DW_AT_enum_class = 0x6d,
727 DW_AT_linkage_name = 0x6e,
728 DW_AT_string_length_bit_size = 0x6f,
729 DW_AT_string_length_byte_size = 0x70,
731 DW_AT_str_offsets_base = 0x72,
732 DW_AT_addr_base = 0x73,
733 DW_AT_rnglists_base = 0x74,
735 DW_AT_dwo_name = 0x76,
736 DW_AT_reference = 0x77,
737 DW_AT_rvalue_reference = 0x78,
739 DW_AT_call_all_calls = 0x7a,
740 DW_AT_call_all_source_calls = 0x7b,
741 DW_AT_call_all_tail_calls = 0x7c,
742 DW_AT_call_return_pc = 0x7d,
743 DW_AT_call_value = 0x7e,
744 DW_AT_call_origin = 0x7f,
745 DW_AT_call_parameter = 0x80,
746 DW_AT_call_pc = 0x81,
747 DW_AT_call_tail_call = 0x82,
748 DW_AT_call_target = 0x83,
749 DW_AT_call_target_clobbered = 0x84,
750 DW_AT_call_data_location = 0x85,
751 DW_AT_call_data_value = 0x86,
752 DW_AT_noreturn = 0x87,
753 DW_AT_alignment = 0x88,
754 DW_AT_export_symbols = 0x89,
755 DW_AT_deleted = 0x8a,
756 DW_AT_defaulted = 0x8b,
757 DW_AT_loclists_base = 0x8c,
758 DW_AT_lo_user = 0x2000,
759 DW_AT_hi_user = 0x3fff
767 DW_FORM_block2 = 0x03,
768 DW_FORM_block4 = 0x04,
769 DW_FORM_data2 = 0x05,
770 DW_FORM_data4 = 0x06,
771 DW_FORM_data8 = 0x07,
772 DW_FORM_string = 0x08,
773 DW_FORM_block = 0x09,
774 DW_FORM_block1 = 0x0a,
775 DW_FORM_data1 = 0x0b,
777 DW_FORM_sdata = 0x0d,
779 DW_FORM_udata = 0x0f,
780 DW_FORM_ref_addr = 0x10,
785 DW_FORM_ref_udata = 0x15,
786 DW_FORM_indirect = 0x16,
787 DW_FORM_sec_offset = 0x17,
788 DW_FORM_exprloc = 0x18,
789 DW_FORM_flag_present = 0x19,
791 DW_FORM_addrx = 0x1b,
792 DW_FORM_ref_sup4 = 0x1c,
793 DW_FORM_strp_sup = 0x1d,
794 DW_FORM_data16 = 0x1e,
795 DW_FORM_line_strp = 0x1f,
796 DW_FORM_ref_sig8 = 0x20,
797 DW_FORM_implicit_const = 0x21,
798 DW_FORM_loclistx = 0x22,
799 DW_FORM_rnglistx = 0x23,
800 DW_FORM_ref_sup8 = 0x24,
801 DW_FORM_strx1 = 0x25,
802 DW_FORM_strx2 = 0x26,
803 DW_FORM_strx3 = 0x27,
804 DW_FORM_strx4 = 0x28,
805 DW_FORM_addrx1 = 0x29,
806 DW_FORM_addrx2 = 0x2a,
807 DW_FORM_addrx3 = 0x2b,
808 DW_FORM_addrx4 = 0x2c
819# define ABBREV_TABLE_SIZE 256
825 char *debug_line_cu_end;
826 char *debug_line_files;
827 char *debug_line_directories;
836 char *abbrev_table[ABBREV_TABLE_SIZE];
859#define MERGE_2INTS(a,b,sz) (((uint64_t)(b)<<sz)|(a))
864 return (uint16_t)MERGE_2INTS(p[0],p[1],8);
870 return (
uint32_t)MERGE_2INTS(get_uint16(p),get_uint16(p+2),16);
876 return MERGE_2INTS(get_uint32(p),get_uint32(p+4),32);
880read_uint8(
char **
ptr)
882 const unsigned char *p = (
const unsigned char *)*
ptr;
883 *
ptr = (
char *)(p + 1);
888read_uint16(
char **
ptr)
890 const unsigned char *p = (
const unsigned char *)*
ptr;
891 *
ptr = (
char *)(p + 2);
892 return get_uint16(p);
896read_uint24(
char **
ptr)
898 const unsigned char *p = (
const unsigned char *)*
ptr;
899 *
ptr = (
char *)(p + 3);
900 return (*p << 16) | get_uint16(p+1);
904read_uint32(
char **
ptr)
906 const unsigned char *p = (
const unsigned char *)*
ptr;
907 *
ptr = (
char *)(p + 4);
908 return get_uint32(p);
912read_uint64(
char **
ptr)
914 const unsigned char *p = (
const unsigned char *)*
ptr;
915 *
ptr = (
char *)(p + 8);
916 return get_uint64(p);
920read_uintptr(
char **
ptr)
922 const unsigned char *p = (
const unsigned char *)*
ptr;
923 *
ptr = (
char *)(p + SIZEOF_VOIDP);
925 return get_uint64(p);
927 return get_uint32(p);
932read_uint(DebugInfoReader *reader)
934 if (reader->format == 4) {
935 return read_uint32(&reader->p);
937 return read_uint64(&reader->p);
942read_uleb128(DebugInfoReader *reader)
944 return uleb128(&reader->p);
948read_sleb128(DebugInfoReader *reader)
950 return sleb128(&reader->p);
954debug_info_reader_init(DebugInfoReader *reader, obj_info_t *obj)
956 reader->file = obj->mapped;
958 reader->p = obj->debug_info.ptr;
959 reader->pend = obj->debug_info.ptr + obj->debug_info.size;
960 reader->debug_line_cu_end = obj->debug_line.ptr;
961 reader->current_low_pc = 0;
965di_read_debug_abbrev_cu(DebugInfoReader *reader)
968 char *p = reader->q0;
970 uint64_t abbrev_number = uleb128(&p);
971 if (abbrev_number <= prev)
break;
972 if (abbrev_number < ABBREV_TABLE_SIZE) {
973 reader->abbrev_table[abbrev_number] = p;
975 prev = abbrev_number;
982 if (!at && !form)
break;
988di_read_debug_line_cu(DebugInfoReader *reader)
991 struct LineNumberProgramHeader header;
993 p = (
const char *)reader->debug_line_cu_end;
994 if (parse_debug_line_header(&p, &header))
997 reader->debug_line_cu_end = (
char *)header.cu_end;
998 reader->debug_line_directories = (
char *)header.include_directories;
999 reader->debug_line_files = (
char *)header.filenames;
1005set_uint_value(DebugInfoValue *v,
uint64_t n)
1012set_int_value(DebugInfoValue *v, int64_t n)
1019set_cstr_value(DebugInfoValue *v,
char *s)
1027set_cstrp_value(DebugInfoValue *v,
char *s,
uint64_t off)
1035set_data_value(DebugInfoValue *v,
char *s)
1042get_cstr_value(DebugInfoValue *v)
1045 return v->as.ptr + v->off;
1052debug_info_reader_read_value(DebugInfoReader *reader,
uint64_t form, DebugInfoValue *v)
1056 if (reader->address_size == 4) {
1057 set_uint_value(v, read_uint32(&reader->p));
1058 }
else if (reader->address_size == 8) {
1059 set_uint_value(v, read_uint64(&reader->p));
1061 fprintf(stderr,
"unknown address_size:%d", reader->address_size);
1065 case DW_FORM_block2:
1066 v->size = read_uint16(&reader->p);
1067 set_data_value(v, reader->p);
1068 reader->p += v->size;
1070 case DW_FORM_block4:
1071 v->size = read_uint32(&reader->p);
1072 set_data_value(v, reader->p);
1073 reader->p += v->size;
1076 set_uint_value(v, read_uint16(&reader->p));
1079 set_uint_value(v, read_uint32(&reader->p));
1082 set_uint_value(v, read_uint64(&reader->p));
1084 case DW_FORM_string:
1085 v->size =
strlen(reader->p);
1086 set_cstr_value(v, reader->p);
1087 reader->p += v->size + 1;
1090 v->size = uleb128(&reader->p);
1091 set_data_value(v, reader->p);
1092 reader->p += v->size;
1094 case DW_FORM_block1:
1095 v->size = read_uint8(&reader->p);
1096 set_data_value(v, reader->p);
1097 reader->p += v->size;
1100 set_uint_value(v, read_uint8(&reader->p));
1103 set_uint_value(v, read_uint8(&reader->p));
1106 set_int_value(v, read_sleb128(reader));
1109 set_cstrp_value(v, reader->obj->debug_str.ptr, read_uint(reader));
1112 set_uint_value(v, read_uleb128(reader));
1114 case DW_FORM_ref_addr:
1115 if (reader->address_size == 4) {
1116 set_uint_value(v, read_uint32(&reader->p));
1117 }
else if (reader->address_size == 8) {
1118 set_uint_value(v, read_uint64(&reader->p));
1120 fprintf(stderr,
"unknown address_size:%d", reader->address_size);
1125 set_uint_value(v, read_uint8(&reader->p));
1128 set_uint_value(v, read_uint16(&reader->p));
1131 set_uint_value(v, read_uint32(&reader->p));
1134 set_uint_value(v, read_uint64(&reader->p));
1136 case DW_FORM_ref_udata:
1137 set_uint_value(v, uleb128(&reader->p));
1139 case DW_FORM_indirect:
1141 set_uint_value(v, uleb128(&reader->p));
1143 case DW_FORM_sec_offset:
1144 set_uint_value(v, read_uint(reader));
1154 case DW_FORM_exprloc:
1155 v->size = (size_t)read_uleb128(reader);
1156 set_data_value(v, reader->p);
1157 reader->p += v->size;
1159 case DW_FORM_flag_present:
1160 set_uint_value(v, 1);
1163 set_uint_value(v, uleb128(&reader->p));
1167 set_uint_value(v, uleb128(&reader->p));
1169 case DW_FORM_ref_sup4:
1170 set_uint_value(v, read_uint32(&reader->p));
1172 case DW_FORM_strp_sup:
1173 set_uint_value(v, read_uint(reader));
1176 case DW_FORM_data16:
1178 set_data_value(v, reader->p);
1179 reader->p += v->size;
1181 case DW_FORM_line_strp:
1182 set_uint_value(v, read_uint(reader));
1185 case DW_FORM_ref_sig8:
1186 set_uint_value(v, read_uint64(&reader->p));
1188 case DW_FORM_implicit_const:
1189 set_int_value(v, sleb128(&reader->q));
1191 case DW_FORM_loclistx:
1192 set_uint_value(v, read_uleb128(reader));
1194 case DW_FORM_rnglistx:
1195 set_uint_value(v, read_uleb128(reader));
1197 case DW_FORM_ref_sup8:
1198 set_uint_value(v, read_uint64(&reader->p));
1201 set_uint_value(v, read_uint8(&reader->p));
1204 set_uint_value(v, read_uint16(&reader->p));
1207 set_uint_value(v, read_uint24(&reader->p));
1210 set_uint_value(v, read_uint32(&reader->p));
1212 case DW_FORM_addrx1:
1213 set_uint_value(v, read_uint8(&reader->p));
1215 case DW_FORM_addrx2:
1216 set_uint_value(v, read_uint16(&reader->p));
1218 case DW_FORM_addrx3:
1219 set_uint_value(v, read_uint24(&reader->p));
1221 case DW_FORM_addrx4:
1222 set_uint_value(v, read_uint32(&reader->p));
1231 fprintf(stderr,
"%d: unsupported form: %#"PRIx64
"\n", __LINE__, form);
1237di_find_abbrev(DebugInfoReader *reader,
uint64_t abbrev_number)
1240 if (abbrev_number < ABBREV_TABLE_SIZE) {
1241 return reader->abbrev_table[abbrev_number];
1243 p = reader->abbrev_table[ABBREV_TABLE_SIZE-1];
1251 if (!at && !form)
break;
1253 for (
uint64_t n = uleb128(&p); abbrev_number != n; n = uleb128(&p)) {
1255 fprintf(stderr,
"%d: Abbrev Number %"PRId64" not found\n",__LINE__, abbrev_number);
1264 if (!at && !form)
break;
1272hexdump0(
const unsigned char *p,
size_t n)
1275 fprintf(stderr,
" 0 1 2 3 4 5 6 7 8 9 A B C D E F\n");
1276 for (i=0; i < n; i++){
1279 fprintf(stderr,
"%02zd: %02X ", i/16, p[i]);
1282 fprintf(stderr,
"%02X\n", p[i]);
1285 fprintf(stderr,
"%02X ", p[i]);
1289 if ((i & 15) != 15) {
1290 fprintf(stderr,
"\n");
1293#define hexdump(p,n) hexdump0((const unsigned char *)p, n)
1296div_inspect(DebugInfoValue *v)
1300 fprintf(stderr,
"%d: type:%d size:%zx v:%lx\n",__LINE__,v->type,v->size,v->as.uint64);
1303 fprintf(stderr,
"%d: type:%d size:%zx v:%ld\n",__LINE__,v->type,v->size,(int64_t)v->as.uint64);
1306 fprintf(stderr,
"%d: type:%d size:%zx v:'%s'\n",__LINE__,v->type,v->size,v->as.ptr);
1309 fprintf(stderr,
"%d: type:%d size:%zx v:\n",__LINE__,v->type,v->size);
1310 hexdump(v->as.ptr, 16);
1317di_read_die(DebugInfoReader *reader, DIE *die)
1319 uint64_t abbrev_number = uleb128(&reader->p);
1320 if (abbrev_number == 0) {
1325 reader->q = di_find_abbrev(reader, abbrev_number);
1327 die->pos = reader->p - reader->obj->debug_info.ptr - 1;
1328 die->tag = (
int)uleb128(&reader->q);
1329 die->has_children = *reader->q++;
1330 if (die->has_children) {
1336static DebugInfoValue *
1337di_read_record(DebugInfoReader *reader, DebugInfoValue *vp)
1340 uint64_t form = uleb128(&reader->q);
1341 if (!at || !form)
return NULL;
1344 debug_info_reader_read_value(reader, form, vp);
1349di_skip_records(DebugInfoReader *reader)
1352 DebugInfoValue v = {{}};
1354 uint64_t form = uleb128(&reader->q);
1355 if (!at || !form)
return;
1356 debug_info_reader_read_value(reader, form, &v);
1370ranges_set(ranges_t *
ptr, DebugInfoValue *v)
1374 ptr->low_pc = v->as.uint64;
1375 ptr->low_pc_set =
true;
1378 if (v->form == DW_FORM_addr) {
1379 ptr->high_pc = v->as.uint64;
1382 ptr->high_pc =
ptr->low_pc + v->as.uint64;
1384 ptr->high_pc_set =
true;
1387 ptr->ranges = v->as.uint64;
1388 ptr->ranges_set =
true;
1394ranges_include(DebugInfoReader *reader, ranges_t *
ptr,
uint64_t addr)
1396 if (
ptr->high_pc_set) {
1397 if (
ptr->ranges_set || !
ptr->low_pc_set) {
1400 if (
ptr->low_pc <= addr && addr <= ptr->high_pc) {
1404 else if (
ptr->ranges_set) {
1406 char *p = reader->obj->debug_ranges.ptr +
ptr->ranges;
1407 uint64_t base =
ptr->low_pc_set ?
ptr->low_pc : reader->current_low_pc;
1411 if (!from && !to)
break;
1416 else if (base + from <= addr && addr < base + to) {
1421 else if (
ptr->low_pc_set) {
1422 if (
ptr->low_pc == addr) {
1431ranges_inspect(DebugInfoReader *reader, ranges_t *
ptr)
1433 if (
ptr->high_pc_set) {
1434 if (
ptr->ranges_set || !
ptr->low_pc_set) {
1435 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);
1438 fprintf(stderr,
"low_pc:%"PRIx64
" high_pc:%"PRIx64
"\n",
ptr->low_pc,
ptr->high_pc);
1440 else if (
ptr->ranges_set) {
1441 char *p = reader->obj->debug_ranges.ptr +
ptr->ranges;
1442 fprintf(stderr,
"low_pc:%"PRIx64
" ranges:%"PRIx64
" %lx ",
ptr->low_pc,
ptr->ranges, p-reader->obj->mapped);
1446 if (!from && !to)
break;
1447 fprintf(stderr,
"%"PRIx64
"-%"PRIx64
" ",
ptr->low_pc+from,
ptr->low_pc+to);
1449 fprintf(stderr,
"\n");
1451 else if (
ptr->low_pc_set) {
1452 fprintf(stderr,
"low_pc:%"PRIx64
"\n",
ptr->low_pc);
1455 fprintf(stderr,
"empty\n");
1461di_read_cu(DebugInfoReader *reader)
1467 reader->current_cu = reader->p;
1468 unit_length = read_uint32(&reader->p);
1469 if (unit_length == 0xffffffff) {
1470 unit_length = read_uint64(&reader->p);
1473 reader->cu_end = reader->p + unit_length;
1474 version = read_uint16(&reader->p);
1478 else if (version == 5) {
1479 read_uint8(&reader->p);
1480 reader->address_size = read_uint8(&reader->p);
1481 debug_abbrev_offset = read_uint(reader);
1484 debug_abbrev_offset = read_uint(reader);
1485 reader->address_size = read_uint8(&reader->p);
1487 reader->q0 = reader->obj->debug_abbrev.ptr + debug_abbrev_offset;
1490 di_read_debug_abbrev_cu(reader);
1491 if (di_read_debug_line_cu(reader))
return -1;
1493#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER_BUILD_DATE)
1500 if (!di_read_die(reader, &die))
continue;
1502 if (die.tag != DW_TAG_compile_unit) {
1503 di_skip_records(reader);
1509 DebugInfoValue v = {{}};
1510 if (!di_read_record(reader, &v))
break;
1513 reader->current_low_pc = v.as.uint64;
1523read_abstract_origin(DebugInfoReader *reader,
uint64_t abstract_origin, line_info_t *line)
1525 char *p = reader->p;
1526 char *q = reader->q;
1527 int level = reader->level;
1530 reader->p = reader->current_cu + abstract_origin;
1531 if (!di_read_die(reader, &die))
goto finish;
1535 DebugInfoValue v = {{}};
1536 if (!di_read_record(reader, &v))
break;
1539 line->sname = get_cstr_value(&v);
1547 reader->level = level;
1551debug_info_read(DebugInfoReader *reader,
int num_traces,
void **traces,
1552 line_info_t *lines,
int offset) {
1553 while (reader->p < reader->cu_end) {
1555 ranges_t ranges = {};
1556 line_info_t line = {};
1558 if (!di_read_die(reader, &die))
continue;
1561 if (die.tag != DW_TAG_subprogram && die.tag != DW_TAG_inlined_subroutine) {
1563 di_skip_records(reader);
1569 DebugInfoValue v = {{}};
1571 if (!di_read_record(reader, &v))
break;
1576 line.sname = get_cstr_value(&v);
1578 case DW_AT_call_file:
1579 fill_filename((
int)v.as.uint64, reader->debug_line_directories, reader->debug_line_files, &line, reader->obj);
1581 case DW_AT_call_line:
1582 line.line = (
int)v.as.uint64;
1587 ranges_set(&ranges, &v);
1589 case DW_AT_declaration:
1594 case DW_AT_abstract_origin:
1595 read_abstract_origin(reader, v.as.uint64, &line);
1601 for (
int i=
offset; i < num_traces; i++) {
1603 uintptr_t offset = addr - reader->obj->base_addr + reader->obj->vmaddr;
1607 if (lines[i].sname) {
1608 line_info_t *lp =
malloc(
sizeof(line_info_t));
1609 memcpy(lp, &lines[i],
sizeof(line_info_t));
1611 lp->dirname = line.dirname;
1612 lp->filename = line.filename;
1613 lp->line = line.line;
1616 lines[i].path = reader->obj->path;
1617 lines[i].base_addr = line.base_addr;
1618 lines[i].sname = line.sname;
1619 lines[i].saddr = saddr + reader->obj->base_addr - reader->obj->vmaddr;
1627uncompress_debug_section(ElfW(Shdr) *shdr,
char *
file,
char **
ptr)
1630#ifdef SUPPORT_COMPRESSED_DEBUG_LINE
1631 ElfW(Chdr) *chdr = (ElfW(Chdr) *)(
file + shdr->sh_offset);
1632 unsigned long destsize = chdr->ch_size;
1635 if (chdr->ch_type != ELFCOMPRESS_ZLIB) {
1641 if (!*
ptr)
return 0;
1643 (
const Bytef*)chdr +
sizeof(ElfW(Chdr)),
1644 shdr->sh_size -
sizeof(ElfW(Chdr)));
1657fill_lines(
int num_traces,
void **traces,
int check_debuglink,
1658 obj_info_t **objp, line_info_t *lines,
int offset)
1663 ElfW(Shdr) *shdr, *shstr_shdr;
1664 ElfW(Shdr) *gnu_debuglink_shdr =
NULL;
1665 ElfW(Shdr) *note_gnu_build_id =
NULL;
1669 ElfW(Shdr) *symtab_shdr =
NULL, *strtab_shdr =
NULL;
1670 ElfW(Shdr) *dynsym_shdr =
NULL, *dynstr_shdr =
NULL;
1671 obj_info_t *obj = *objp;
1674 fd = open(binary_filename, O_RDONLY);
1682 kprintf(
"lseek: %s\n",
strerror(e));
1685#if SIZEOF_OFF_T > SIZEOF_SIZE_T
1688 kprintf(
"Too large file %s\n", binary_filename);
1694 file = (
char *)mmap(
NULL, (
size_t)filesize, PROT_READ, MAP_SHARED, fd, 0);
1695 if (
file == MAP_FAILED) {
1698 kprintf(
"mmap: %s\n",
strerror(e));
1703 ehdr = (ElfW(Ehdr) *)
file;
1704 if (
memcmp(ehdr->e_ident,
"\177ELF", 4) != 0) {
1712 obj->mapped_size = (size_t)filesize;
1714 shdr = (ElfW(Shdr) *)(
file + ehdr->e_shoff);
1716 shstr_shdr = shdr + ehdr->e_shstrndx;
1717 shstr =
file + shstr_shdr->sh_offset;
1719 for (i = 0; i < ehdr->e_shnum; i++) {
1720 char *section_name = shstr + shdr[i].sh_name;
1721 switch (shdr[i].sh_type) {
1723 if (!strcmp(section_name,
".strtab")) {
1724 strtab_shdr = shdr + i;
1726 else if (!strcmp(section_name,
".dynstr")) {
1727 dynstr_shdr = shdr + i;
1732 symtab_shdr = shdr + i;
1736 dynsym_shdr = shdr + i;
1739 if (!strcmp(section_name,
".note.gnu.build-id")) {
1740 note_gnu_build_id = shdr + i;
1744 if (!strcmp(section_name,
".gnu_debuglink")) {
1745 gnu_debuglink_shdr = shdr + i;
1748 const char *debug_section_names[] = {
1756 for (j=0; j < DWARF_SECTION_COUNT; j++) {
1757 struct dwarf_section *s = obj_dwarf_section_at(obj, j);
1759 if (strcmp(section_name, debug_section_names[j]) != 0)
1762 s->ptr =
file + shdr[i].sh_offset;
1763 s->
size = shdr[i].sh_size;
1764 s->flags = shdr[i].sh_flags;
1765 if (s->flags & SHF_COMPRESSED) {
1766 s->size = uncompress_debug_section(&shdr[i],
file, &s->ptr);
1767 if (!s->size)
goto fail;
1779 if (dynsym_shdr && dynstr_shdr) {
1780 char *strtab =
file + dynstr_shdr->sh_offset;
1781 ElfW(Sym) *symtab = (ElfW(Sym) *)(
file + dynsym_shdr->sh_offset);
1782 int symtab_count = (
int)(dynsym_shdr->sh_size /
sizeof(ElfW(Sym)));
1783 void *handle = dlopen(
NULL, RTLD_NOW|RTLD_LOCAL);
1785 for (j = 0; j < symtab_count; j++) {
1786 ElfW(Sym) *
sym = &symtab[j];
1789 if (ELF_ST_TYPE(
sym->st_info) != STT_FUNC ||
sym->st_size == 0)
continue;
1790 s = dlsym(handle, strtab +
sym->st_name);
1791 if (s && dladdr(s, &info)) {
1792 obj->base_addr = dladdr_fbase;
1793 dladdr_fbase = (
uintptr_t)info.dli_fbase;
1799 if (ehdr->e_type == ET_EXEC) {
1804 obj->base_addr = dladdr_fbase;
1809 if (obj->debug_info.ptr && obj->debug_abbrev.ptr) {
1810 DebugInfoReader reader;
1811 debug_info_reader_init(&reader, obj);
1813 while (reader.p < reader.pend) {
1815 if (di_read_cu(&reader))
goto use_symtab;
1816 debug_info_read(&reader, num_traces, traces, lines,
offset);
1824 symtab_shdr = dynsym_shdr;
1825 strtab_shdr = dynstr_shdr;
1828 if (symtab_shdr && strtab_shdr) {
1829 char *strtab =
file + strtab_shdr->sh_offset;
1830 ElfW(Sym) *symtab = (ElfW(Sym) *)(
file + symtab_shdr->sh_offset);
1831 int symtab_count = (
int)(symtab_shdr->sh_size /
sizeof(ElfW(Sym)));
1832 for (j = 0; j < symtab_count; j++) {
1833 ElfW(Sym) *
sym = &symtab[j];
1835 if (ELF_ST_TYPE(
sym->st_info) != STT_FUNC)
continue;
1836 for (i =
offset; i < num_traces; i++) {
1841 if (!lines[i].sname) lines[i].sname = strtab +
sym->st_name;
1842 lines[i].saddr = saddr;
1843 lines[i].path = obj->path;
1844 lines[i].base_addr = obj->base_addr;
1850 if (!obj->debug_line.ptr) {
1853 if (gnu_debuglink_shdr && check_debuglink) {
1854 follow_debuglink(
file + gnu_debuglink_shdr->sh_offset,
1858 if (note_gnu_build_id && check_debuglink) {
1859 ElfW(Nhdr) *nhdr = (ElfW(Nhdr)*) (
file + note_gnu_build_id->sh_offset);
1860 const char *build_id = (
char *)(nhdr + 1) + nhdr->n_namesz;
1861 follow_debuglink_build_id(build_id, nhdr->n_descsz,
1868 if (parse_debug_line(num_traces, traces,
1869 obj->debug_line.ptr,
1870 obj->debug_line.size,
1871 obj, lines,
offset) == -1)
1875 return dladdr_fbase;
1882fill_lines(
int num_traces,
void **traces,
int check_debuglink,
1883 obj_info_t **objp, line_info_t *lines,
int offset)
1886# define LP(x) x##_64
1893 obj_info_t *obj = *objp;
1894 struct LP(mach_header) *header;
1898 char *s = binary_filename;
1899 char *base =
strrchr(binary_filename,
'/')+1;
1902 size_t basesize =
size - (base - binary_filename);
1910 if (
max <= basesize)
goto fail;
1911 memcpy(s, base, basesize);
1914 fd = open(binary_filename, O_RDONLY);
1917 fd = open(binary_filename, O_RDONLY);
1928 kprintf(
"lseek: %s\n",
strerror(e));
1931#if SIZEOF_OFF_T > SIZEOF_SIZE_T
1934 kprintf(
"Too large file %s\n", binary_filename);
1940 file = (
char *)mmap(
NULL, (
size_t)filesize, PROT_READ, MAP_SHARED, fd, 0);
1941 if (
file == MAP_FAILED) {
1944 kprintf(
"mmap: %s\n",
strerror(e));
1950 obj->mapped_size = (size_t)filesize;
1952 header = (
struct LP(mach_header) *)
file;
1953 if (header->magic == LP(MH_MAGIC)) {
1957 else if (header->magic == FAT_CIGAM) {
1958 struct LP(mach_header) *mhp = _NSGetMachExecuteHeader();
1959 struct fat_header *fat = (
struct fat_header *)
file;
1960 char *q =
file +
sizeof(*fat);
1961 uint32_t nfat_arch = __builtin_bswap32(fat->nfat_arch);
1963 for (
uint32_t i = 0; i < nfat_arch; i++) {
1964 struct fat_arch *arch = (
struct fat_arch *)q;
1965 cpu_type_t cputype = __builtin_bswap32(arch->cputype);
1966 cpu_subtype_t cpusubtype = __builtin_bswap32(arch->cpusubtype);
1969 if (mhp->cputype == cputype &&
1970 (cpu_subtype_t)(mhp->cpusubtype & ~CPU_SUBTYPE_MASK) == cpusubtype) {
1973 header = (
struct LP(mach_header) *)p;
1974 if (header->magic == LP(MH_MAGIC)) {
1975 goto found_mach_header;
1981 kprintf(
"'%s' is not a Mach-O universal binary file!\n",binary_filename);
1986 kprintf(
"'%s' is not a "
1992 "-bit Mach-O file!\n",binary_filename);
1997 p +=
sizeof(*header);
2000 struct load_command *lcmd = (
struct load_command *)p;
2001 switch (lcmd->cmd) {
2002 case LP(LC_SEGMENT):
2004 static const char *debug_section_names[] = {
2011 struct LP(segment_command) *scmd = (
struct LP(segment_command) *)lcmd;
2012 if (strcmp(scmd->segname,
"__TEXT") == 0) {
2013 obj->vmaddr = scmd->vmaddr;
2015 else if (strcmp(scmd->segname,
"__DWARF") == 0) {
2016 p +=
sizeof(
struct LP(segment_command));
2017 for (
uint64_t i = 0; i < scmd->nsects; i++) {
2018 struct LP(section) *sect = (
struct LP(section) *)p;
2019 p +=
sizeof(
struct LP(section));
2020 for (
int j=0; j < DWARF_SECTION_COUNT; j++) {
2021 struct dwarf_section *s = obj_dwarf_section_at(obj, j);
2023 if (strcmp(sect->sectname, debug_section_names[j]) != 0)
2026 s->ptr =
file + sect->offset;
2027 s->
size = sect->size;
2028 s->flags = sect->flags;
2029 if (s->flags & SHF_COMPRESSED) {
2041 struct symtab_command *cmd = (
struct symtab_command *)lcmd;
2042 struct LP(nlist) *nl = (
struct LP(nlist) *)(
file + cmd->symoff);
2043 char *strtab =
file + cmd->stroff, *sname = 0;
2047 for (j = 0; j < cmd->nsyms; j++) {
2049 struct LP(nlist) *e = &nl[j];
2051 if (e->n_type != N_FUN)
continue;
2053 saddr = (
uintptr_t)e->n_value + obj->base_addr - obj->vmaddr;
2054 sname = strtab + e->n_un.n_strx;
2058 for (
int k =
offset; k < num_traces; k++) {
2060 symsize = e->n_value;
2062 if (lines[k].line > 0 || d > (
uintptr_t)symsize)
2065 if (!lines[k].sname) lines[k].sname = sname;
2066 lines[k].saddr = saddr;
2067 lines[k].path = obj->path;
2068 lines[k].base_addr = obj->base_addr;
2076 if (obj->debug_info.ptr && obj->debug_abbrev.ptr) {
2077 DebugInfoReader reader;
2078 debug_info_reader_init(&reader, obj);
2079 while (reader.p < reader.pend) {
2080 if (di_read_cu(&reader))
goto fail;
2081 debug_info_read(&reader, num_traces, traces, lines,
offset);
2085 if (parse_debug_line(num_traces, traces,
2086 obj->debug_line.ptr,
2087 obj->debug_line.size,
2088 obj, lines,
offset) == -1)
2091 return dladdr_fbase;
2097#define HAVE_MAIN_EXE_PATH
2098#if defined(__FreeBSD__)
2099# include <sys/sysctl.h>
2107#if defined(__linux__) || defined(__NetBSD__)
2111# if defined(__linux__)
2112# define PROC_SELF_EXE "/proc/self/exe"
2113# elif defined(__NetBSD__)
2114# define PROC_SELF_EXE "/proc/curproc/exe"
2117 if (
len < 0)
return 0;
2118 binary_filename[
len] = 0;
2121#elif defined(__FreeBSD__)
2125 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
2127 int err = sysctl(mib, 4, binary_filename, &
len,
NULL, 0);
2129 kprintf(
"Can't get the path of ruby");
2135#elif defined(HAVE_LIBPROC_H)
2139 int len = proc_pidpath(getpid(), binary_filename,
PATH_MAX);
2140 if (
len == 0)
return 0;
2141 binary_filename[
len] = 0;
2145#undef HAVE_MAIN_EXE_PATH
2149print_line0(line_info_t *line,
void *address)
2155 if (line->dirname && line->dirname[0]) {
2156 kprintf(
"%s(%s) %s/%s:%d\n", line->path, line->sname, line->dirname, line->filename, line->line);
2159 kprintf(
"%s(%s) %s:%d\n", line->path, line->sname, line->filename, line->line);
2162 else if (!line->path) {
2163 kprintf(
"[0x%"PRIxPTR"]\n", addr);
2165 else if (!line->saddr || !line->sname) {
2166 kprintf(
"%s(0x%"PRIxPTR") [0x%"PRIxPTR"]\n", line->path, addr-line->base_addr, addr);
2168 else if (line->line <= 0) {
2169 kprintf(
"%s(%s+0x%"PRIxPTR") [0x%"PRIxPTR"]\n", line->path, line->sname,
2172 else if (!line->filename) {
2173 kprintf(
"%s(%s+0x%"PRIxPTR") [0x%"PRIxPTR"] ???:%d\n", line->path, line->sname,
2174 d, addr, line->line);
2176 else if (line->dirname && line->dirname[0]) {
2177 kprintf(
"%s(%s+0x%"PRIxPTR") [0x%"PRIxPTR"] %s/%s:%d\n", line->path, line->sname,
2178 d, addr, line->dirname, line->filename, line->line);
2181 kprintf(
"%s(%s+0x%"PRIxPTR") [0x%"PRIxPTR"] %s:%d\n", line->path, line->sname,
2182 d, addr, line->filename, line->line);
2187print_line(line_info_t *line,
void *address)
2189 print_line0(line, address);
2191 print_line(line->next,
NULL);
2196rb_dump_backtrace_with_lines(
int num_traces,
void **traces)
2200 line_info_t *lines = (line_info_t *)
calloc(num_traces,
sizeof(line_info_t));
2201 obj_info_t *obj =
NULL;
2203 void **dladdr_fbases = (
void **)
calloc(num_traces+2,
sizeof(
void *));
2204#ifdef HAVE_MAIN_EXE_PATH
2205 char *main_path =
NULL;
2207 if ((
len = main_exe_path()) > 0) {
2211 memcpy(main_path, binary_filename,
len+1);
2213 obj->path = main_path;
2214 addr = fill_lines(num_traces, traces, 1, &obj, lines, -1);
2216 dladdr_fbases[0] = (
void *)addr;
2223 for (i = 0; i < num_traces; i++) {
2225 if (lines[i].line)
continue;
2226 if (dladdr(traces[i], &info)) {
2232 for (p=dladdr_fbases; *p; p++) {
2233 if (*p == info.dli_fbase) {
2234 lines[i].path = info.dli_fname;
2235 lines[i].sname = info.dli_sname;
2239 *p = info.dli_fbase;
2242 obj->base_addr = (
uintptr_t)info.dli_fbase;
2243 path = info.dli_fname;
2245 lines[i].path = path;
2246 lines[i].sname = info.dli_sname;
2247 lines[i].saddr = (
uintptr_t)info.dli_saddr;
2249 if (fill_lines(num_traces, traces, 1, &obj, lines, i) == (
uintptr_t)-1)
2257 for (i = 0; i < num_traces; i++) {
2258 print_line(&lines[i], traces[i]);
2261 if (lines[i].sname && strcmp(
"main", lines[i].sname) == 0)
2267 obj_info_t *o = obj;
2268 for (i=0; i < DWARF_SECTION_COUNT; i++) {
2269 struct dwarf_section *s = obj_dwarf_section_at(obj, i);
2270 if (s->flags & SHF_COMPRESSED) {
2274 if (obj->mapped_size) {
2275 munmap(obj->mapped, obj->mapped_size);
2280 for (i = 0; i < num_traces; i++) {
2281 line_info_t *line = lines[i].next;
2283 line_info_t *l = line;
2289 free(dladdr_fbases);
2330#define MAXNBUF (sizeof(intmax_t) * CHAR_BIT + 1)
2331static inline int toupper(
int c) {
return (
'A' <= c && c <=
'Z') ? (c&0x5f) : c; }
2332#define hex2ascii(hex) (hex2ascii_data[hex])
2333static const char hex2ascii_data[] =
"0123456789abcdefghijklmnopqrstuvwxyz";
2334static inline int imax(
int a,
int b) {
return (a > b ? a : b); }
2335static int kvprintf(
char const *fmt,
void (*func)(
int),
void *arg,
int radix, va_list ap);
2337static void putce(
int c)
2343 ret =
write(2, s, 1);
2348kprintf(
const char *fmt, ...)
2354 retval = kvprintf(fmt, putce,
NULL, 10, ap);
2366ksprintn(
char *nbuf, uintmax_t
num,
int base,
int *lenp,
int upper)
2373 c = hex2ascii(
num % base);
2374 *++p = upper ? toupper(c) : c;
2375 }
while (
num /= base);
2377 *lenp = (
int)(p - nbuf);
2408kvprintf(
char const *fmt,
void (*func)(
int),
void *arg,
int radix, va_list ap)
2410#define PCHAR(c) {int cc=(c); if (func) (*func)(cc); else *d++ = cc; retval++; }
2413 const char *p, *percent, *q;
2417 int base, lflag, qflag, tmp, width, ladjust, sharpflag,
neg, sign, dot;
2418 int cflag, hflag, jflag, tflag, zflag;
2421 int stop = 0, retval = 0;
2430 fmt =
"(fmt null)\n";
2432 if (radix < 2 || radix > 36)
2438 while ((ch = (
unsigned char)*fmt++) !=
'%' || stop) {
2444 qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0;
neg = 0;
2445 sign = 0; dot = 0; dwidth = 0; upper = 0;
2446 cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
2447reswitch:
switch (ch = (
unsigned char)*fmt++) {
2465 width = va_arg(ap,
int);
2471 dwidth = va_arg(ap,
int);
2479 case '1':
case '2':
case '3':
case '4':
2480 case '5':
case '6':
case '7':
case '8':
case '9':
2481 for (n = 0;; ++fmt) {
2482 n = n * 10 + ch -
'0';
2484 if (ch < '0' || ch >
'9')
2493 num = (
unsigned int)va_arg(ap,
int);
2494 p = va_arg(ap,
char *);
2495 for (q = ksprintn(nbuf,
num, *p++,
NULL, 0); *q;)
2501 for (tmp = 0; *p;) {
2503 if (
num & (1 << (n - 1))) {
2504 PCHAR(tmp ?
',' :
'<');
2505 for (; (n = *p) >
' '; ++p)
2509 for (; *p >
' '; ++p)
2516 PCHAR(va_arg(ap,
int));
2519 up = va_arg(ap,
unsigned char *);
2520 p = va_arg(ap,
char *);
2524 PCHAR(hex2ascii(*up >> 4));
2525 PCHAR(hex2ascii(*up & 0x0f));
2556 *(va_arg(ap, intmax_t *)) = retval;
2558 *(va_arg(ap, int64_t *)) = retval;
2560 *(va_arg(ap,
long *)) = retval;
2562 *(va_arg(ap,
size_t *)) = retval;
2564 *(va_arg(ap,
short *)) = retval;
2566 *(va_arg(ap,
char *)) = retval;
2568 *(va_arg(ap,
int *)) = retval;
2575 sharpflag = (width == 0);
2588 p = va_arg(ap,
char *);
2594 for (n = 0; n < dwidth && p[n]; n++)
2599 if (!ladjust && width > 0)
2604 if (ladjust && width > 0)
2629 num = va_arg(ap, uintmax_t);
2633 num = va_arg(ap, ptrdiff_t);
2635 num = va_arg(ap,
unsigned long);
2637 num = va_arg(ap,
size_t);
2639 num = (
unsigned short)va_arg(ap,
int);
2641 num = (
unsigned char)va_arg(ap,
int);
2643 num = va_arg(ap,
unsigned int);
2647 num = va_arg(ap, intmax_t);
2649 num = va_arg(ap, int64_t);
2651 num = va_arg(ap, ptrdiff_t);
2653 num = va_arg(ap,
long);
2655 num = va_arg(ap, ssize_t);
2657 num = (short)va_arg(ap,
int);
2659 num = (char)va_arg(ap,
int);
2661 num = va_arg(ap,
int);
2663 if (sign && (intmax_t)
num < 0) {
2667 p = ksprintn(nbuf,
num, base, &n, upper);
2669 if (sharpflag &&
num != 0) {
2672 else if (base == 16)
2678 if (!ladjust && padc ==
'0')
2679 dwidth = width - tmp;
2680 width -= tmp + imax(dwidth, n);
2687 if (sharpflag &&
num != 0) {
2690 }
else if (base == 16) {
2695 while (dwidth-- > 0)
2707 while (percent < fmt)
#define PRINTF_ARGS(decl, string_index, first_to_check)
char * strrchr(const char *, const char)
Thin wrapper to ruby/config.h.
Prototype for *.c in ./missing, and for missing timeval struct.
size_t strlcpy(char *, const char *, size_t)
void * memmove(void *, const void *, size_t)
typedef long(ZCALLBACK *tell_file_func) OF((voidpf opaque
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
Historical shim for <limits.h>.
int memcmp(const void *s1, const void *s2, size_t len)
VALUE type(ANYARGS)
ANYARGS-ed function type.
unsigned long long uint64_t
size_t strlen(const char *)
int ZEXPORT uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)
ssize_t readlink(const char *, char *, size_t)
if((ID)(DISPID) nameid !=nameid)
int write(ozstream &zs, const T *x, Items items)