11 #if defined(__clang__)
12 #pragma clang diagnostic ignored "-Wgnu-empty-initializer"
13 #pragma clang diagnostic ignored "-Wgcc-compat"
16 #include "ruby/config.h"
34 #if defined(USE_ELF) || defined(HAVE_MACH_O_LOADER_H)
43 #include <sys/types.h>
50 # define alloca __builtin_alloca
70 #ifdef HAVE_MACH_O_LOADER_H
72 # include <mach-o/fat.h>
73 # include <mach-o/loader.h>
74 # include <mach-o/nlist.h>
75 # include <mach-o/stab.h>
86 # if SIZEOF_VOIDP == 8
87 # define ElfW(x) Elf64##_##x
89 # define ElfW(x) Elf32##_##x
93 # if SIZEOF_VOIDP == 8
94 # define ELF_ST_TYPE ELF64_ST_TYPE
96 # define ELF_ST_TYPE ELF32_ST_TYPE
101 #ifdef SHF_COMPRESSED
102 # if defined(ELFCOMPRESS_ZLIB) && defined(HAVE_LIBZ)
105 # define SUPPORT_COMPRESSED_DEBUG_LINE
108 # define SHF_COMPRESSED 0
112 #define PATH_MAX 4096
115 #define DW_LNS_copy 0x01
116 #define DW_LNS_advance_pc 0x02
117 #define DW_LNS_advance_line 0x03
118 #define DW_LNS_set_file 0x04
119 #define DW_LNS_set_column 0x05
120 #define DW_LNS_negate_stmt 0x06
121 #define DW_LNS_set_basic_block 0x07
122 #define DW_LNS_const_add_pc 0x08
123 #define DW_LNS_fixed_advance_pc 0x09
124 #define DW_LNS_set_prologue_end 0x0a
125 #define DW_LNS_set_epilogue_begin 0x0b
126 #define DW_LNS_set_isa 0x0c
129 #define DW_LNE_end_sequence 0x01
130 #define DW_LNE_set_address 0x02
131 #define DW_LNE_define_file 0x03
132 #define DW_LNE_set_discriminator 0x04
136 typedef struct line_info {
138 const char *filename;
146 struct line_info *next;
149 struct dwarf_section {
155 typedef struct obj_info {
162 struct dwarf_section debug_abbrev;
163 struct dwarf_section debug_info;
164 struct dwarf_section debug_line;
165 struct dwarf_section debug_ranges;
166 struct dwarf_section debug_str;
167 struct obj_info *next;
170 #define DWARF_SECTION_COUNT 5
172 static struct dwarf_section *
173 obj_dwarf_section_at(obj_info_t *
obj,
int n)
175 struct dwarf_section *ary[] = {
182 if (
n < 0 || DWARF_SECTION_COUNT <=
n) {
188 struct debug_section_definition {
190 struct dwarf_section *dwarf;
194 static char binary_filename[
PATH_MAX + 1];
202 unsigned char b = *(
unsigned char *)(*p)++;
204 r += (
unsigned long)b << s;
207 r += (b & 0x7f) << s;
219 unsigned char b = *(
unsigned char *)(*p)++;
222 r -= (0x80 - b) << s;
225 r += (b & 0x3f) << s;
229 r += (b & 0x7f) << s;
236 get_nth_dirname(
unsigned long dir,
char *p)
245 kprintf(
"Unexpected directory number %lu in %s\n",
246 dir, binary_filename);
254 fill_filename(
int file,
char *include_directories,
char *filenames, line_info_t *line, obj_info_t *
obj)
260 for (
i = 1;
i <= file;
i++) {
264 kprintf(
"Unexpected file number %d in %s at %tx\n",
265 file, binary_filename, filenames -
obj->mapped);
277 line->filename = filename;
278 line->dirname = get_nth_dirname(dir, include_directories);
284 fill_line(
int num_traces,
void **traces,
uintptr_t addr,
int file,
int line,
285 char *include_directories,
char *filenames,
286 obj_info_t *
obj, line_info_t *lines,
int offset)
289 addr +=
obj->base_addr -
obj->vmaddr;
290 for (
i = offset;
i < num_traces;
i++) {
294 if (addr < a && a < addr + 100) {
295 fill_filename(file, include_directories, filenames, &lines[
i],
obj);
296 lines[
i].line = line;
301 struct LineNumberProgramHeader {
306 uint8_t minimum_instruction_length;
307 uint8_t maximum_operations_per_instruction;
313 const char *include_directories;
314 const char *filenames;
315 const char *cu_start;
320 parse_debug_line_header(
const char **pp,
struct LineNumberProgramHeader *header)
323 header->unit_length = *(
uint32_t *)p;
327 if (header->unit_length == 0xffffffff) {
328 header->unit_length = *(
uint64_t *)p;
333 header->cu_end = p + header->unit_length;
337 if (header->version > 4)
return -1;
339 header->header_length = header->format == 4 ? *(
uint32_t *)p : *(
uint64_t *)p;
341 header->cu_start = p + header->header_length;
343 header->minimum_instruction_length = *(
uint8_t *)p++;
345 if (header->version >= 4) {
347 if (*p != 1)
return -1;
351 header->default_is_stmt = *(
uint8_t *)p++;
352 header->line_base = *(
int8_t *)p++;
353 header->line_range = *(
uint8_t *)p++;
354 header->opcode_base = *(
uint8_t *)p++;
356 p += header->opcode_base - 1;
358 header->include_directories = p;
361 if (p >= header->cu_end)
return -1;
365 p =
memchr(p,
'\0', header->cu_end - p);
371 header->filenames = p;
373 *pp = header->cu_start;
379 parse_debug_line_cu(
int num_traces,
void **traces,
char **debug_line,
380 obj_info_t *
obj, line_info_t *lines,
int offset)
382 const char *p = (
const char *)*debug_line;
383 struct LineNumberProgramHeader header;
386 unsigned long addr = 0;
387 unsigned int file = 1;
388 unsigned int line = 1;
397 if (parse_debug_line_header(&p, &header))
399 is_stmt = header.default_is_stmt;
401 #define FILL_LINE() \
403 fill_line(num_traces, traces, addr, file, line, \
404 (char *)header.include_directories, \
405 (char *)header.filenames, \
406 obj, lines, offset); \
410 while (p < header.cu_end) {
412 unsigned char op = *p++;
417 case DW_LNS_advance_pc:
418 a = uleb128((
char **)&p);
421 case DW_LNS_advance_line: {
422 long a = sleb128((
char **)&p);
426 case DW_LNS_set_file:
427 file = (
unsigned int)uleb128((
char **)&p);
429 case DW_LNS_set_column:
430 (
void)uleb128((
char **)&p);
432 case DW_LNS_negate_stmt:
435 case DW_LNS_set_basic_block:
438 case DW_LNS_const_add_pc:
439 a = ((255UL - header.opcode_base) / header.line_range) *
440 header.minimum_instruction_length;
443 case DW_LNS_fixed_advance_pc:
444 a = *(
unsigned char *)p++;
447 case DW_LNS_set_prologue_end:
450 case DW_LNS_set_epilogue_begin:
454 (
void)uleb128((
char **)&p);
457 a = *(
unsigned char *)p++;
460 case DW_LNE_end_sequence:
467 is_stmt = header.default_is_stmt;
471 case DW_LNE_set_address:
472 addr = *(
unsigned long *)p;
473 p +=
sizeof(
unsigned long);
475 case DW_LNE_define_file:
476 kprintf(
"Unsupported operation in %s\n",
479 case DW_LNE_set_discriminator:
481 uleb128((
char **)&p);
484 kprintf(
"Unknown extended opcode: %d in %s\n",
485 op, binary_filename);
489 uint8_t adjusted_opcode = op - header.opcode_base;
490 uint8_t operation_advance = adjusted_opcode / header.line_range;
492 addr += operation_advance * header.minimum_instruction_length;
493 line += header.line_base + (adjusted_opcode % header.line_range);
498 *debug_line = (
char *)p;
503 parse_debug_line(
int num_traces,
void **traces,
504 char *debug_line,
unsigned long size,
505 obj_info_t *
obj, line_info_t *lines,
int offset)
507 char *debug_line_end = debug_line +
size;
508 while (debug_line < debug_line_end) {
509 if (parse_debug_line_cu(num_traces, traces, &debug_line,
obj, lines, offset))
512 if (debug_line != debug_line_end) {
513 kprintf(
"Unexpected size of .debug_line in %s\n",
521 fill_lines(
int num_traces,
void **traces,
int check_debuglink,
522 obj_info_t **objp, line_info_t *lines,
int offset);
525 append_obj(obj_info_t **objp)
527 obj_info_t *newobj =
calloc(1,
sizeof(obj_info_t));
528 if (*objp) (*objp)->next = newobj;
534 follow_debuglink(
const char *debuglink,
int num_traces,
void **traces,
535 obj_info_t **objp, line_info_t *lines,
int offset)
540 static const char global_debug_dir[] =
"/usr/lib/debug";
541 const size_t global_debug_dir_len =
sizeof(global_debug_dir) - 1;
543 obj_info_t *
o1 = *objp, *
o2;
546 p =
strrchr(binary_filename,
'/');
555 memmove(binary_filename + global_debug_dir_len, binary_filename,
len);
556 memcpy(binary_filename, global_debug_dir, global_debug_dir_len);
557 len += global_debug_dir_len;
562 o2->base_addr =
o1->base_addr;
564 fill_lines(num_traces, traces, 0, objp, lines, offset);
570 DW_TAG_compile_unit = 0x11,
571 DW_TAG_inlined_subroutine = 0x1d,
572 DW_TAG_subprogram = 0x2e,
578 DW_AT_sibling = 0x01,
579 DW_AT_location = 0x02,
586 DW_AT_ordering = 0x09,
588 DW_AT_byte_size = 0x0b,
590 DW_AT_bit_size = 0x0d,
593 DW_AT_stmt_list = 0x10,
595 DW_AT_high_pc = 0x12,
596 DW_AT_language = 0x13,
599 DW_AT_discr_value = 0x16,
600 DW_AT_visibility = 0x17,
602 DW_AT_string_length = 0x19,
603 DW_AT_common_reference = 0x1a,
604 DW_AT_comp_dir = 0x1b,
605 DW_AT_const_value = 0x1c,
606 DW_AT_containing_type = 0x1d,
607 DW_AT_default_value = 0x1e,
610 DW_AT_is_optional = 0x21,
611 DW_AT_lower_bound = 0x22,
614 DW_AT_producer = 0x25,
616 DW_AT_prototyped = 0x27,
619 DW_AT_return_addr = 0x2a,
621 DW_AT_start_scope = 0x2c,
623 DW_AT_bit_stride = 0x2e,
624 DW_AT_upper_bound = 0x2f,
626 DW_AT_abstract_origin = 0x31,
627 DW_AT_accessibility = 0x32,
628 DW_AT_address_class = 0x33,
629 DW_AT_artificial = 0x34,
630 DW_AT_base_types = 0x35,
631 DW_AT_calling_convention = 0x36,
633 DW_AT_data_member_location = 0x38,
634 DW_AT_decl_column = 0x39,
635 DW_AT_decl_file = 0x3a,
636 DW_AT_decl_line = 0x3b,
637 DW_AT_declaration = 0x3c,
638 DW_AT_discr_list = 0x3d,
639 DW_AT_encoding = 0x3e,
640 DW_AT_external = 0x3f,
641 DW_AT_frame_base = 0x40,
643 DW_AT_identifier_case = 0x42,
645 DW_AT_namelist_item = 0x44,
646 DW_AT_priority = 0x45,
647 DW_AT_segment = 0x46,
648 DW_AT_specification = 0x47,
649 DW_AT_static_link = 0x48,
651 DW_AT_use_location = 0x4a,
652 DW_AT_variable_parameter = 0x4b,
653 DW_AT_virtuality = 0x4c,
654 DW_AT_vtable_elem_location = 0x4d,
655 DW_AT_allocated = 0x4e,
656 DW_AT_associated = 0x4f,
657 DW_AT_data_location = 0x50,
658 DW_AT_byte_stride = 0x51,
659 DW_AT_entry_pc = 0x52,
660 DW_AT_use_UTF8 = 0x53,
661 DW_AT_extension = 0x54,
663 DW_AT_trampoline = 0x56,
664 DW_AT_call_column = 0x57,
665 DW_AT_call_file = 0x58,
666 DW_AT_call_line = 0x59,
667 DW_AT_description = 0x5a,
668 DW_AT_binary_scale = 0x5b,
669 DW_AT_decimal_scale = 0x5c,
671 DW_AT_decimal_sign = 0x5e,
672 DW_AT_digit_count = 0x5f,
673 DW_AT_picture_string = 0x60,
674 DW_AT_mutable = 0x61,
675 DW_AT_threads_scaled = 0x62,
676 DW_AT_explicit = 0x63,
677 DW_AT_object_pointer = 0x64,
678 DW_AT_endianity = 0x65,
679 DW_AT_elemental = 0x66,
681 DW_AT_recursive = 0x68,
682 DW_AT_signature = 0x69,
683 DW_AT_main_subprogram = 0x6a,
684 DW_AT_data_bit_offset = 0x6b,
685 DW_AT_const_expr = 0x6c,
686 DW_AT_enum_class = 0x6d,
687 DW_AT_linkage_name = 0x6e,
688 DW_AT_string_length_bit_size = 0x6f,
689 DW_AT_string_length_byte_size = 0x70,
691 DW_AT_str_offsets_base = 0x72,
692 DW_AT_addr_base = 0x73,
693 DW_AT_rnglists_base = 0x74,
695 DW_AT_dwo_name = 0x76,
696 DW_AT_reference = 0x77,
697 DW_AT_rvalue_reference = 0x78,
699 DW_AT_call_all_calls = 0x7a,
700 DW_AT_call_all_source_calls = 0x7b,
701 DW_AT_call_all_tail_calls = 0x7c,
702 DW_AT_call_return_pc = 0x7d,
703 DW_AT_call_value = 0x7e,
704 DW_AT_call_origin = 0x7f,
705 DW_AT_call_parameter = 0x80,
706 DW_AT_call_pc = 0x81,
707 DW_AT_call_tail_call = 0x82,
708 DW_AT_call_target = 0x83,
709 DW_AT_call_target_clobbered = 0x84,
710 DW_AT_call_data_location = 0x85,
711 DW_AT_call_data_value = 0x86,
712 DW_AT_noreturn = 0x87,
713 DW_AT_alignment = 0x88,
714 DW_AT_export_symbols = 0x89,
715 DW_AT_deleted = 0x8a,
716 DW_AT_defaulted = 0x8b,
717 DW_AT_loclists_base = 0x8c,
718 DW_AT_lo_user = 0x2000,
719 DW_AT_hi_user = 0x3fff
727 DW_FORM_block2 = 0x03,
728 DW_FORM_block4 = 0x04,
729 DW_FORM_data2 = 0x05,
730 DW_FORM_data4 = 0x06,
731 DW_FORM_data8 = 0x07,
732 DW_FORM_string = 0x08,
733 DW_FORM_block = 0x09,
734 DW_FORM_block1 = 0x0a,
735 DW_FORM_data1 = 0x0b,
737 DW_FORM_sdata = 0x0d,
739 DW_FORM_udata = 0x0f,
740 DW_FORM_ref_addr = 0x10,
745 DW_FORM_ref_udata = 0x15,
746 DW_FORM_indirect = 0x16,
747 DW_FORM_sec_offset = 0x17,
748 DW_FORM_exprloc = 0x18,
749 DW_FORM_flag_present = 0x19,
751 DW_FORM_addrx = 0x1b,
752 DW_FORM_ref_sup4 = 0x1c,
753 DW_FORM_strp_sup = 0x1d,
754 DW_FORM_data16 = 0x1e,
755 DW_FORM_line_strp = 0x1f,
756 DW_FORM_ref_sig8 = 0x20,
757 DW_FORM_implicit_const = 0x21,
758 DW_FORM_loclistx = 0x22,
759 DW_FORM_rnglistx = 0x23,
760 DW_FORM_ref_sup8 = 0x24,
761 DW_FORM_strx1 = 0x25,
762 DW_FORM_strx2 = 0x26,
763 DW_FORM_strx3 = 0x27,
764 DW_FORM_strx4 = 0x28,
765 DW_FORM_addrx1 = 0x29,
766 DW_FORM_addrx2 = 0x2a,
767 DW_FORM_addrx3 = 0x2b,
768 DW_FORM_addrx4 = 0x2c
779 # define ABBREV_TABLE_SIZE 256
785 char *debug_line_cu_end;
786 char *debug_line_files;
787 char *debug_line_directories;
796 char *abbrev_table[ABBREV_TABLE_SIZE];
819 #define MERGE_2INTS(a,b,sz) (((uint64_t)(b)<<sz)|(a))
824 return (
uint16_t)MERGE_2INTS(p[0],p[1],8);
830 return (
uint32_t)MERGE_2INTS(get_uint16(p),get_uint16(p+2),16);
836 return MERGE_2INTS(get_uint32(p),get_uint32(p+4),32);
840 read_uint8(
char **
ptr)
842 const unsigned char *p = (
const unsigned char *)*
ptr;
843 *
ptr = (
char *)(p + 1);
848 read_uint16(
char **
ptr)
850 const unsigned char *p = (
const unsigned char *)*
ptr;
851 *
ptr = (
char *)(p + 2);
852 return get_uint16(p);
856 read_uint24(
char **
ptr)
858 const unsigned char *p = (
const unsigned char *)*
ptr;
859 *
ptr = (
char *)(p + 3);
860 return (*p << 16) | get_uint16(p+1);
864 read_uint32(
char **
ptr)
866 const unsigned char *p = (
const unsigned char *)*
ptr;
867 *
ptr = (
char *)(p + 4);
868 return get_uint32(p);
872 read_uint64(
char **
ptr)
874 const unsigned char *p = (
const unsigned char *)*
ptr;
875 *
ptr = (
char *)(p + 8);
876 return get_uint64(p);
880 read_uintptr(
char **
ptr)
882 const unsigned char *p = (
const unsigned char *)*
ptr;
884 #if SIZEOF_VOIDP == 8
885 return get_uint64(p);
887 return get_uint32(p);
892 read_uint(DebugInfoReader *reader)
894 if (reader->format == 4) {
895 return read_uint32(&reader->p);
897 return read_uint64(&reader->p);
902 read_uleb128(DebugInfoReader *reader)
904 return uleb128(&reader->p);
908 read_sleb128(DebugInfoReader *reader)
910 return sleb128(&reader->p);
914 debug_info_reader_init(DebugInfoReader *reader, obj_info_t *
obj)
916 reader->file =
obj->mapped;
918 reader->p =
obj->debug_info.ptr;
919 reader->pend =
obj->debug_info.ptr +
obj->debug_info.size;
920 reader->debug_line_cu_end =
obj->debug_line.ptr;
924 di_read_debug_abbrev_cu(DebugInfoReader *reader)
927 char *p = reader->q0;
929 uint64_t abbrev_number = uleb128(&p);
930 if (abbrev_number <= prev)
break;
931 if (abbrev_number < ABBREV_TABLE_SIZE) {
932 reader->abbrev_table[abbrev_number] = p;
934 prev = abbrev_number;
941 if (!at && !form)
break;
947 di_read_debug_line_cu(DebugInfoReader *reader)
950 struct LineNumberProgramHeader header;
952 p = (
const char *)reader->debug_line_cu_end;
953 if (parse_debug_line_header(&p, &header))
956 reader->debug_line_cu_end = (
char *)header.cu_end;
957 reader->debug_line_directories = (
char *)header.include_directories;
958 reader->debug_line_files = (
char *)header.filenames;
971 set_int_value(DebugInfoValue *
v,
int64_t n)
978 set_cstr_value(DebugInfoValue *
v,
char *s)
986 set_cstrp_value(DebugInfoValue *
v,
char *s,
uint64_t off)
994 set_data_value(DebugInfoValue *
v,
char *s)
1001 get_cstr_value(DebugInfoValue *
v)
1004 return v->as.ptr +
v->off;
1011 debug_info_reader_read_value(DebugInfoReader *reader,
uint64_t form, DebugInfoValue *
v)
1015 if (reader->address_size == 4) {
1016 set_uint_value(
v, read_uint32(&reader->p));
1017 }
else if (reader->address_size == 8) {
1018 set_uint_value(
v, read_uint64(&reader->p));
1020 fprintf(
stderr,
"unknown address_size:%d", reader->address_size);
1024 case DW_FORM_block2:
1025 v->size = read_uint16(&reader->p);
1026 set_data_value(
v, reader->p);
1027 reader->p +=
v->size;
1029 case DW_FORM_block4:
1030 v->size = read_uint32(&reader->p);
1031 set_data_value(
v, reader->p);
1032 reader->p +=
v->size;
1035 set_uint_value(
v, read_uint16(&reader->p));
1038 set_uint_value(
v, read_uint32(&reader->p));
1041 set_uint_value(
v, read_uint64(&reader->p));
1043 case DW_FORM_string:
1045 set_cstr_value(
v, reader->p);
1046 reader->p +=
v->size + 1;
1049 v->size = uleb128(&reader->p);
1050 set_data_value(
v, reader->p);
1051 reader->p +=
v->size;
1053 case DW_FORM_block1:
1054 v->size = read_uint8(&reader->p);
1055 set_data_value(
v, reader->p);
1056 reader->p +=
v->size;
1059 set_uint_value(
v, read_uint8(&reader->p));
1062 set_uint_value(
v, read_uint8(&reader->p));
1065 set_int_value(
v, read_sleb128(reader));
1068 set_cstrp_value(
v, reader->obj->debug_str.ptr, read_uint(reader));
1071 set_uint_value(
v, read_uleb128(reader));
1073 case DW_FORM_ref_addr:
1074 if (reader->address_size == 4) {
1075 set_uint_value(
v, read_uint32(&reader->p));
1076 }
else if (reader->address_size == 8) {
1077 set_uint_value(
v, read_uint64(&reader->p));
1079 fprintf(
stderr,
"unknown address_size:%d", reader->address_size);
1084 set_uint_value(
v, read_uint8(&reader->p));
1087 set_uint_value(
v, read_uint16(&reader->p));
1090 set_uint_value(
v, read_uint32(&reader->p));
1093 set_uint_value(
v, read_uint64(&reader->p));
1095 case DW_FORM_ref_udata:
1096 set_uint_value(
v, uleb128(&reader->p));
1098 case DW_FORM_indirect:
1100 set_uint_value(
v, uleb128(&reader->p));
1102 case DW_FORM_sec_offset:
1103 set_uint_value(
v, read_uint(reader));
1113 case DW_FORM_exprloc:
1114 v->size = (
size_t)read_uleb128(reader);
1115 set_data_value(
v, reader->p);
1116 reader->p +=
v->size;
1118 case DW_FORM_flag_present:
1119 set_uint_value(
v, 1);
1122 set_uint_value(
v, uleb128(&reader->p));
1126 set_uint_value(
v, uleb128(&reader->p));
1128 case DW_FORM_ref_sup4:
1129 set_uint_value(
v, read_uint32(&reader->p));
1131 case DW_FORM_strp_sup:
1132 set_uint_value(
v, read_uint(reader));
1135 case DW_FORM_data16:
1137 set_data_value(
v, reader->p);
1138 reader->p +=
v->size;
1140 case DW_FORM_line_strp:
1141 set_uint_value(
v, read_uint(reader));
1144 case DW_FORM_ref_sig8:
1145 set_uint_value(
v, read_uint64(&reader->p));
1147 case DW_FORM_implicit_const:
1148 set_int_value(
v, sleb128(&reader->q));
1150 case DW_FORM_loclistx:
1151 set_uint_value(
v, read_uleb128(reader));
1153 case DW_FORM_rnglistx:
1154 set_uint_value(
v, read_uleb128(reader));
1156 case DW_FORM_ref_sup8:
1157 set_uint_value(
v, read_uint64(&reader->p));
1160 set_uint_value(
v, read_uint8(&reader->p));
1163 set_uint_value(
v, read_uint16(&reader->p));
1166 set_uint_value(
v, read_uint24(&reader->p));
1169 set_uint_value(
v, read_uint32(&reader->p));
1171 case DW_FORM_addrx1:
1172 set_uint_value(
v, read_uint8(&reader->p));
1174 case DW_FORM_addrx2:
1175 set_uint_value(
v, read_uint16(&reader->p));
1177 case DW_FORM_addrx3:
1178 set_uint_value(
v, read_uint24(&reader->p));
1180 case DW_FORM_addrx4:
1181 set_uint_value(
v, read_uint32(&reader->p));
1196 di_find_abbrev(DebugInfoReader *reader,
uint64_t abbrev_number)
1199 if (abbrev_number < ABBREV_TABLE_SIZE) {
1200 return reader->abbrev_table[abbrev_number];
1202 p = reader->abbrev_table[ABBREV_TABLE_SIZE-1];
1210 if (!at && !form)
break;
1212 for (
uint64_t n = uleb128(&p); abbrev_number !=
n;
n = uleb128(&p)) {
1223 if (!at && !form)
break;
1231 hexdump0(
const unsigned char *p,
size_t n)
1235 for (
i=0;
i <
n;
i++){
1248 if ((
i & 15) != 15) {
1252 #define hexdump(p,n) hexdump0((const unsigned char *)p, n)
1255 div_inspect(DebugInfoValue *
v)
1259 fprintf(
stderr,
"%d: type:%d size:%zx v:%lx\n",__LINE__,
v->type,
v->size,
v->as.uint64);
1265 fprintf(
stderr,
"%d: type:%d size:%zx v:'%s'\n",__LINE__,
v->type,
v->size,
v->as.ptr);
1269 hexdump(
v->as.ptr, 16);
1276 di_read_die(DebugInfoReader *reader, DIE *die)
1278 uint64_t abbrev_number = uleb128(&reader->p);
1279 if (abbrev_number == 0) {
1284 reader->q = di_find_abbrev(reader, abbrev_number);
1286 die->pos = reader->p - reader->obj->debug_info.ptr - 1;
1287 die->tag = (
int)uleb128(&reader->q);
1288 die->has_children = *reader->q++;
1289 if (die->has_children) {
1295 static DebugInfoValue *
1296 di_read_record(DebugInfoReader *reader, DebugInfoValue *vp)
1299 uint64_t form = uleb128(&reader->q);
1300 if (!at || !form)
return NULL;
1303 debug_info_reader_read_value(reader, form, vp);
1308 di_skip_records(DebugInfoReader *reader)
1311 DebugInfoValue
v = {{}};
1313 uint64_t form = uleb128(&reader->q);
1314 if (!at || !form)
return;
1315 debug_info_reader_read_value(reader, form, &
v);
1329 ranges_set(ranges_t *
ptr, DebugInfoValue *
v)
1333 ptr->low_pc =
v->as.uint64;
1334 ptr->low_pc_set =
true;
1337 if (
v->form == DW_FORM_addr) {
1338 ptr->high_pc =
v->as.uint64;
1341 ptr->high_pc =
ptr->low_pc +
v->as.uint64;
1343 ptr->high_pc_set =
true;
1346 ptr->ranges =
v->as.uint64;
1347 ptr->ranges_set =
true;
1353 ranges_include(DebugInfoReader *reader, ranges_t *
ptr,
uint64_t addr)
1355 if (
ptr->high_pc_set) {
1356 if (
ptr->ranges_set || !
ptr->low_pc_set) {
1359 if (
ptr->low_pc <= addr && addr <= ptr->high_pc) {
1363 else if (
ptr->ranges_set) {
1365 char *p = reader->obj->debug_ranges.ptr +
ptr->ranges;
1366 uint64_t base =
ptr->low_pc_set ?
ptr->low_pc : reader->current_low_pc;
1370 if (!from && !to)
break;
1375 else if (base + from <= addr && addr < base + to) {
1380 else if (
ptr->low_pc_set) {
1381 if (
ptr->low_pc == addr) {
1390 ranges_inspect(DebugInfoReader *reader, ranges_t *
ptr)
1392 if (
ptr->high_pc_set) {
1393 if (
ptr->ranges_set || !
ptr->low_pc_set) {
1394 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);
1399 else if (
ptr->ranges_set) {
1400 char *p = reader->obj->debug_ranges.ptr +
ptr->ranges;
1405 if (!from && !to)
break;
1410 else if (
ptr->low_pc_set) {
1420 di_read_cu(DebugInfoReader *reader)
1426 reader->current_cu = reader->p;
1427 unit_length = read_uint32(&reader->p);
1428 if (unit_length == 0xffffffff) {
1429 unit_length = read_uint64(&reader->p);
1432 reader->cu_end = reader->p + unit_length;
1433 version = read_uint16(&reader->p);
1437 else if (version == 5) {
1438 read_uint8(&reader->p);
1439 reader->address_size = read_uint8(&reader->p);
1440 debug_abbrev_offset = read_uint(reader);
1443 debug_abbrev_offset = read_uint(reader);
1444 reader->address_size = read_uint8(&reader->p);
1446 reader->q0 = reader->obj->debug_abbrev.ptr + debug_abbrev_offset;
1449 di_read_debug_abbrev_cu(reader);
1450 if (di_read_debug_line_cu(reader))
return -1;
1452 #if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER_BUILD_DATE)
1459 if (!di_read_die(reader, &die))
continue;
1461 if (die.tag != DW_TAG_compile_unit) {
1462 di_skip_records(reader);
1468 DebugInfoValue
v = {{}};
1469 if (!di_read_record(reader, &
v))
break;
1472 reader->current_low_pc =
v.as.uint64;
1482 read_abstract_origin(DebugInfoReader *reader,
uint64_t abstract_origin, line_info_t *line)
1484 char *p = reader->p;
1485 char *q = reader->q;
1486 int level = reader->level;
1489 reader->p = reader->current_cu + abstract_origin;
1490 if (!di_read_die(reader, &die))
goto finish;
1494 DebugInfoValue
v = {{}};
1495 if (!di_read_record(reader, &
v))
break;
1498 line->sname = get_cstr_value(&
v);
1506 reader->level = level;
1510 debug_info_read(DebugInfoReader *reader,
int num_traces,
void **traces,
1511 line_info_t *lines,
int offset) {
1512 while (reader->p < reader->cu_end) {
1514 ranges_t ranges = {};
1515 line_info_t line = {};
1517 if (!di_read_die(reader, &die))
continue;
1520 if (die.tag != DW_TAG_subprogram && die.tag != DW_TAG_inlined_subroutine) {
1522 di_skip_records(reader);
1528 DebugInfoValue
v = {{}};
1530 if (!di_read_record(reader, &
v))
break;
1535 line.sname = get_cstr_value(&
v);
1537 case DW_AT_call_file:
1538 fill_filename((
int)
v.as.uint64, reader->debug_line_directories, reader->debug_line_files, &line, reader->obj);
1540 case DW_AT_call_line:
1541 line.line = (
int)
v.as.uint64;
1546 ranges_set(&ranges, &
v);
1548 case DW_AT_declaration:
1553 case DW_AT_abstract_origin:
1554 read_abstract_origin(reader,
v.as.uint64, &line);
1560 for (
int i=offset;
i < num_traces;
i++) {
1562 uintptr_t offset = addr - reader->obj->base_addr + reader->obj->vmaddr;
1563 uintptr_t saddr = ranges_include(reader, &ranges, offset);
1566 if (lines[
i].sname) {
1567 line_info_t *lp =
malloc(
sizeof(line_info_t));
1568 memcpy(lp, &lines[
i],
sizeof(line_info_t));
1570 lp->dirname = line.dirname;
1571 lp->filename = line.filename;
1572 lp->line = line.line;
1575 lines[
i].path = reader->obj->path;
1576 lines[
i].base_addr = line.base_addr;
1577 lines[
i].sname = line.sname;
1578 lines[
i].saddr = saddr + reader->obj->base_addr - reader->obj->vmaddr;
1585 static unsigned long
1586 uncompress_debug_section(ElfW(Shdr) *shdr,
char *file,
char **
ptr)
1588 #ifdef SUPPORT_COMPRESSED_DEBUG_LINE
1589 ElfW(Chdr) *chdr = (ElfW(Chdr) *)(file + shdr->sh_offset);
1590 unsigned long destsize = chdr->ch_size;
1593 if (chdr->ch_type != ELFCOMPRESS_ZLIB) {
1599 if (!*
ptr)
return 0;
1600 ret = uncompress((Bytef *)*
ptr, &destsize,
1601 (
const Bytef*)chdr +
sizeof(ElfW(Chdr)),
1602 shdr->sh_size -
sizeof(ElfW(Chdr)));
1603 if (ret != Z_OK)
goto fail;
1614 fill_lines(
int num_traces,
void **traces,
int check_debuglink,
1615 obj_info_t **objp, line_info_t *lines,
int offset)
1620 ElfW(Shdr) *shdr, *shstr_shdr;
1621 ElfW(Shdr) *gnu_debuglink_shdr =
NULL;
1625 ElfW(Shdr) *symtab_shdr =
NULL, *strtab_shdr =
NULL;
1626 ElfW(Shdr) *dynsym_shdr =
NULL, *dynstr_shdr =
NULL;
1627 obj_info_t *
obj = *objp;
1630 fd = open(binary_filename, O_RDONLY);
1638 kprintf(
"lseek: %s\n",
strerror(e));
1641 #if SIZEOF_OFF_T > SIZEOF_SIZE_T
1644 kprintf(
"Too large file %s\n", binary_filename);
1650 file = (
char *)mmap(
NULL, (
size_t)filesize, PROT_READ, MAP_SHARED, fd, 0);
1651 if (file == MAP_FAILED) {
1654 kprintf(
"mmap: %s\n",
strerror(e));
1659 ehdr = (ElfW(Ehdr) *)file;
1660 if (
memcmp(ehdr->e_ident,
"\177ELF", 4) != 0) {
1670 shdr = (ElfW(Shdr) *)(file + ehdr->e_shoff);
1672 shstr_shdr = shdr + ehdr->e_shstrndx;
1673 shstr = file + shstr_shdr->sh_offset;
1675 for (
i = 0;
i < ehdr->e_shnum;
i++) {
1676 char *section_name = shstr + shdr[
i].sh_name;
1677 switch (shdr[
i].sh_type) {
1679 if (!
strcmp(section_name,
".strtab")) {
1680 strtab_shdr = shdr +
i;
1682 else if (!
strcmp(section_name,
".dynstr")) {
1683 dynstr_shdr = shdr +
i;
1688 symtab_shdr = shdr +
i;
1692 dynsym_shdr = shdr +
i;
1695 if (!
strcmp(section_name,
".gnu_debuglink")) {
1696 gnu_debuglink_shdr = shdr +
i;
1699 const char *debug_section_names[] = {
1707 for (j=0; j < DWARF_SECTION_COUNT; j++) {
1708 struct dwarf_section *s = obj_dwarf_section_at(
obj, j);
1710 if (
strcmp(section_name, debug_section_names[j]) != 0)
1713 s->ptr = file + shdr[
i].sh_offset;
1714 s->size = shdr[
i].sh_size;
1715 s->flags = shdr[
i].sh_flags;
1716 if (s->flags & SHF_COMPRESSED) {
1717 s->size = uncompress_debug_section(&shdr[
i], file, &s->ptr);
1718 if (!s->size)
goto fail;
1730 if (dynsym_shdr && dynstr_shdr) {
1731 char *strtab = file + dynstr_shdr->sh_offset;
1732 ElfW(Sym) *symtab = (ElfW(Sym) *)(file + dynsym_shdr->sh_offset);
1733 int symtab_count = (
int)(dynsym_shdr->sh_size /
sizeof(ElfW(Sym)));
1734 void *handle = dlopen(
NULL, RTLD_NOW|RTLD_LOCAL);
1736 for (j = 0; j < symtab_count; j++) {
1737 ElfW(Sym) *
sym = &symtab[j];
1740 if (ELF_ST_TYPE(
sym->st_info) != STT_FUNC ||
sym->st_size == 0)
continue;
1741 s = dlsym(handle, strtab +
sym->st_name);
1742 if (s && dladdr(s, &info)) {
1743 obj->base_addr = dladdr_fbase;
1744 dladdr_fbase = (
uintptr_t)info.dli_fbase;
1750 if (ehdr->e_type == ET_EXEC) {
1755 obj->base_addr = dladdr_fbase;
1760 if (
obj->debug_info.ptr &&
obj->debug_abbrev.ptr) {
1761 DebugInfoReader reader;
1762 debug_info_reader_init(&reader,
obj);
1764 while (reader.p < reader.pend) {
1766 if (di_read_cu(&reader))
goto use_symtab;
1767 debug_info_read(&reader, num_traces, traces, lines, offset);
1775 symtab_shdr = dynsym_shdr;
1776 strtab_shdr = dynstr_shdr;
1779 if (symtab_shdr && strtab_shdr) {
1780 char *strtab = file + strtab_shdr->sh_offset;
1781 ElfW(Sym) *symtab = (ElfW(Sym) *)(file + symtab_shdr->sh_offset);
1782 int symtab_count = (
int)(symtab_shdr->sh_size /
sizeof(ElfW(Sym)));
1783 for (j = 0; j < symtab_count; j++) {
1784 ElfW(Sym) *
sym = &symtab[j];
1786 if (ELF_ST_TYPE(
sym->st_info) != STT_FUNC)
continue;
1787 for (
i = offset;
i < num_traces;
i++) {
1792 if (!lines[
i].sname) lines[
i].sname = strtab +
sym->st_name;
1793 lines[
i].saddr = saddr;
1794 lines[
i].path =
obj->path;
1795 lines[
i].base_addr =
obj->base_addr;
1801 if (!
obj->debug_line.ptr) {
1804 if (gnu_debuglink_shdr && check_debuglink) {
1805 follow_debuglink(file + gnu_debuglink_shdr->sh_offset,
1807 objp, lines, offset);
1812 if (parse_debug_line(num_traces, traces,
1813 obj->debug_line.ptr,
1814 obj->debug_line.size,
1815 obj, lines, offset) == -1)
1819 return dladdr_fbase;
1826 fill_lines(
int num_traces,
void **traces,
int check_debuglink,
1827 obj_info_t **objp, line_info_t *lines,
int offset)
1830 # define LP(x) x##_64
1836 char *file, *p =
NULL;
1837 obj_info_t *
obj = *objp;
1838 struct LP(mach_header) *header;
1842 char *s = binary_filename;
1843 char *base =
strrchr(binary_filename,
'/')+1;
1846 size_t basesize =
size - (base - binary_filename);
1850 size =
strlcpy(s,
".dSYM/Contents/Resources/DWARF/", max);
1854 if (max <= basesize)
goto fail;
1855 memcpy(s, base, basesize);
1858 fd = open(binary_filename, O_RDONLY);
1861 fd = open(binary_filename, O_RDONLY);
1872 kprintf(
"lseek: %s\n",
strerror(e));
1875 #if SIZEOF_OFF_T > SIZEOF_SIZE_T
1878 kprintf(
"Too large file %s\n", binary_filename);
1884 file = (
char *)mmap(
NULL, (
size_t)filesize, PROT_READ, MAP_SHARED, fd, 0);
1885 if (file == MAP_FAILED) {
1888 kprintf(
"mmap: %s\n",
strerror(e));
1896 header = (
struct LP(mach_header) *)file;
1897 if (header->magic == LP(MH_MAGIC)) {
1901 else if (header->magic == FAT_CIGAM) {
1902 struct LP(mach_header) *mhp = _NSGetMachExecuteHeader();
1903 struct fat_header *fat = (
struct fat_header *)file;
1904 char *q = file +
sizeof(*fat);
1905 uint32_t nfat_arch = __builtin_bswap32(fat->nfat_arch);
1908 struct fat_arch *arch = (
struct fat_arch *)q;
1909 cpu_type_t cputype = __builtin_bswap32(arch->cputype);
1910 cpu_subtype_t cpusubtype = __builtin_bswap32(arch->cpusubtype);
1911 uint32_t offset = __builtin_bswap32(arch->offset);
1913 if (mhp->cputype == cputype &&
1914 (cpu_subtype_t)(mhp->cpusubtype & ~CPU_SUBTYPE_MASK) == cpusubtype) {
1917 header = (
struct LP(mach_header) *)p;
1918 if (header->magic == LP(MH_MAGIC)) {
1919 goto found_mach_header;
1925 kprintf(
"'%s' is not a Mach-O universal binary file!\n",binary_filename);
1930 kprintf(
"'%s' is not a "
1936 "-bit Mach-O file!\n",binary_filename);
1941 p +=
sizeof(*header);
1944 struct load_command *lcmd = (
struct load_command *)p;
1945 switch (lcmd->cmd) {
1946 case LP(LC_SEGMENT):
1948 static const char *debug_section_names[] = {
1955 struct LP(segment_command) *scmd = (
struct LP(segment_command) *)lcmd;
1956 if (
strcmp(scmd->segname,
"__TEXT") == 0) {
1957 obj->vmaddr = scmd->vmaddr;
1959 else if (
strcmp(scmd->segname,
"__DWARF") == 0) {
1960 p +=
sizeof(
struct LP(segment_command));
1962 struct LP(section) *sect = (
struct LP(section) *)p;
1963 p +=
sizeof(
struct LP(section));
1964 for (
int j=0; j < DWARF_SECTION_COUNT; j++) {
1965 struct dwarf_section *s = obj_dwarf_section_at(
obj, j);
1967 if (
strcmp(sect->sectname, debug_section_names[j]) != 0)
1970 s->ptr = file + sect->offset;
1971 s->size = sect->size;
1972 s->flags = sect->flags;
1973 if (s->flags & SHF_COMPRESSED) {
1985 struct symtab_command *cmd = (
struct symtab_command *)lcmd;
1986 struct LP(nlist) *nl = (
struct LP(nlist) *)(file + cmd->symoff);
1987 char *strtab = file + cmd->stroff, *sname = 0;
1991 for (j = 0; j < cmd->nsyms; j++) {
1993 struct LP(nlist) *e = &nl[j];
1995 if (e->n_type != N_FUN)
continue;
1998 sname = strtab + e->n_un.n_strx;
2002 for (
int k = offset; k < num_traces; k++) {
2004 symsize = e->n_value;
2006 if (lines[k].line > 0 || d > (
uintptr_t)symsize)
2009 if (!lines[k].sname) lines[k].sname = sname;
2010 lines[k].saddr = saddr;
2011 lines[k].path =
obj->path;
2012 lines[k].base_addr =
obj->base_addr;
2020 if (
obj->debug_info.ptr &&
obj->debug_abbrev.ptr) {
2021 DebugInfoReader reader;
2022 debug_info_reader_init(&reader,
obj);
2023 while (reader.p < reader.pend) {
2024 if (di_read_cu(&reader))
goto fail;
2025 debug_info_read(&reader, num_traces, traces, lines, offset);
2029 if (parse_debug_line(num_traces, traces,
2030 obj->debug_line.ptr,
2031 obj->debug_line.size,
2032 obj, lines, offset) == -1)
2035 return dladdr_fbase;
2041 #define HAVE_MAIN_EXE_PATH
2042 #if defined(__FreeBSD__)
2043 # include <sys/sysctl.h>
2051 #if defined(__linux__)
2055 # define PROC_SELF_EXE "/proc/self/exe"
2057 if (
len < 0)
return 0;
2058 binary_filename[
len] = 0;
2061 #elif defined(__FreeBSD__)
2065 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
2067 int err = sysctl(mib, 4, binary_filename, &
len,
NULL, 0);
2069 kprintf(
"Can't get the path of ruby");
2075 #elif defined(HAVE_LIBPROC_H)
2080 if (
len == 0)
return 0;
2081 binary_filename[
len] = 0;
2085 #undef HAVE_MAIN_EXE_PATH
2089 print_line0(line_info_t *line,
void *address)
2095 if (line->dirname && line->dirname[0]) {
2096 kprintf(
"%s(%s) %s/%s:%d\n", line->path, line->sname, line->dirname, line->filename, line->line);
2099 kprintf(
"%s(%s) %s:%d\n", line->path, line->sname, line->filename, line->line);
2102 else if (!line->path) {
2103 kprintf(
"[0x%"PRIxPTR"]\n", addr);
2105 else if (!line->saddr || !line->sname) {
2106 kprintf(
"%s(0x%"PRIxPTR") [0x%"PRIxPTR"]\n", line->path, addr-line->base_addr, addr);
2108 else if (line->line <= 0) {
2109 kprintf(
"%s(%s+0x%"PRIxPTR") [0x%"PRIxPTR"]\n", line->path, line->sname,
2112 else if (!line->filename) {
2113 kprintf(
"%s(%s+0x%"PRIxPTR") [0x%"PRIxPTR"] ???:%d\n", line->path, line->sname,
2114 d, addr, line->line);
2116 else if (line->dirname && line->dirname[0]) {
2117 kprintf(
"%s(%s+0x%"PRIxPTR") [0x%"PRIxPTR"] %s/%s:%d\n", line->path, line->sname,
2118 d, addr, line->dirname, line->filename, line->line);
2121 kprintf(
"%s(%s+0x%"PRIxPTR") [0x%"PRIxPTR"] %s:%d\n", line->path, line->sname,
2122 d, addr, line->filename, line->line);
2127 print_line(line_info_t *line,
void *address)
2129 print_line0(line, address);
2131 print_line(line->next,
NULL);
2136 rb_dump_backtrace_with_lines(
int num_traces,
void **traces)
2140 line_info_t *lines = (line_info_t *)
calloc(num_traces,
sizeof(line_info_t));
2143 void **dladdr_fbases = (
void **)
calloc(num_traces+2,
sizeof(
void *));
2144 #ifdef HAVE_MAIN_EXE_PATH
2145 char *main_path =
NULL;
2147 if ((
len = main_exe_path()) > 0) {
2151 memcpy(main_path, binary_filename,
len+1);
2153 obj->path = main_path;
2154 addr = fill_lines(num_traces, traces, 1, &
obj, lines, -1);
2156 dladdr_fbases[0] = (
void *)addr;
2163 for (
i = 0;
i < num_traces;
i++) {
2165 if (lines[
i].line)
continue;
2166 if (dladdr(traces[
i], &info)) {
2172 for (p=dladdr_fbases; *p; p++) {
2173 if (*p == info.dli_fbase) {
2174 lines[
i].path = info.dli_fname;
2175 lines[
i].sname = info.dli_sname;
2179 *p = info.dli_fbase;
2183 path = info.dli_fname;
2185 lines[
i].path =
path;
2186 lines[
i].sname = info.dli_sname;
2189 if (fill_lines(num_traces, traces, 1, &
obj, lines,
i) == (
uintptr_t)-1)
2197 for (
i = 0;
i < num_traces;
i++) {
2198 print_line(&lines[
i], traces[
i]);
2201 if (lines[
i].sname &&
strcmp(
"main", lines[
i].sname) == 0)
2207 obj_info_t *o =
obj;
2208 for (
i=0;
i < DWARF_SECTION_COUNT;
i++) {
2209 struct dwarf_section *s = obj_dwarf_section_at(
obj,
i);
2210 if (s->flags & SHF_COMPRESSED) {
2214 if (
obj->mapped_size) {
2215 munmap(
obj->mapped,
obj->mapped_size);
2220 for (
i = 0;
i < num_traces;
i++) {
2221 line_info_t *line = lines[
i].next;
2223 line_info_t *l = line;
2229 free(dladdr_fbases);
2270 #define MAXNBUF (sizeof(intmax_t) * CHAR_BIT + 1)
2271 static inline int toupper(
int c) {
return (
'A' <= c && c <=
'Z') ? (c&0x5f) : c; }
2272 #define hex2ascii(hex) (hex2ascii_data[hex])
2273 static const char hex2ascii_data[] =
"0123456789abcdefghijklmnopqrstuvwxyz";
2274 static inline int imax(
int a,
int b) {
return (a > b ? a : b); }
2275 static int kvprintf(
char const *
fmt,
void (*func)(
int),
void *
arg,
int radix,
va_list ap);
2277 static void putce(
int c)
2283 ret =
write(2, s, 1);
2288 kprintf(
const char *
fmt, ...)
2294 retval = kvprintf(
fmt, putce,
NULL, 10, ap);
2306 ksprintn(
char *nbuf,
uintmax_t num,
int base,
int *lenp,
int upper)
2313 c = hex2ascii(num % base);
2314 *++p = upper ? toupper(c) : c;
2315 }
while (num /= base);
2317 *lenp = (
int)(p - nbuf);
2348 kvprintf(
char const *
fmt,
void (*func)(
int),
void *
arg,
int radix,
va_list ap)
2350 #define PCHAR(c) {int cc=(c); if (func) (*func)(cc); else *d++ = cc; retval++; }
2353 const char *p, *percent, *q;
2357 int base, lflag, qflag, tmp, width, ladjust, sharpflag,
neg, sign, dot;
2358 int cflag, hflag, jflag, tflag, zflag;
2361 int stop = 0, retval = 0;
2370 fmt =
"(fmt null)\n";
2372 if (radix < 2 || radix > 36)
2378 while ((ch = (
unsigned char)*
fmt++) !=
'%' || stop) {
2384 qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0;
neg = 0;
2385 sign = 0; dot = 0; dwidth = 0; upper = 0;
2386 cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
2387 reswitch:
switch (ch = (
unsigned char)*
fmt++) {
2411 dwidth =
va_arg(ap,
int);
2419 case '1':
case '2':
case '3':
case '4':
2420 case '5':
case '6':
case '7':
case '8':
case '9':
2421 for (
n = 0;; ++
fmt) {
2422 n =
n * 10 + ch -
'0';
2424 if (ch < '0' || ch >
'9')
2435 for (q = ksprintn(nbuf, num, *p++,
NULL, 0); *q;)
2441 for (tmp = 0; *p;) {
2443 if (num & (1 << (
n - 1))) {
2444 PCHAR(tmp ?
',' :
'<');
2445 for (; (
n = *p) >
' '; ++p)
2449 for (; *p >
' '; ++p)
2459 up =
va_arg(ap,
unsigned char *);
2464 PCHAR(hex2ascii(*up >> 4));
2465 PCHAR(hex2ascii(*up & 0x0f));
2500 *(
va_arg(ap,
long *)) = retval;
2502 *(
va_arg(ap,
size_t *)) = retval;
2504 *(
va_arg(ap,
short *)) = retval;
2506 *(
va_arg(ap,
char *)) = retval;
2508 *(
va_arg(ap,
int *)) = retval;
2515 sharpflag = (width == 0);
2534 for (
n = 0;
n < dwidth && p[
n];
n++)
2539 if (!ladjust && width > 0)
2544 if (ladjust && width > 0)
2575 num =
va_arg(ap,
unsigned long);
2577 num =
va_arg(ap,
size_t);
2583 num =
va_arg(ap,
unsigned int);
2607 p = ksprintn(nbuf, num, base, &
n, upper);
2609 if (sharpflag && num != 0) {
2612 else if (base == 16)
2618 if (!ladjust && padc ==
'0')
2619 dwidth = width - tmp;
2620 width -= tmp + imax(dwidth,
n);
2627 if (sharpflag && num != 0) {
2630 }
else if (base == 16) {
2635 while (dwidth-- > 0)
2647 while (percent <
fmt)
2662 #error not supported