Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

addr2line.c
Go to the documentation of this file.
1 /**********************************************************************
2
3 addr2line.c -
4
5 $Author$
6
7 Copyright (C) 2010 Shinichiro Hamaji
8
9 **********************************************************************/
10
11 #if defined(__clang__)
12 #pragma clang diagnostic ignored "-Wgnu-empty-initializer"
13 #pragma clang diagnostic ignored "-Wgcc-compat"
14 #endif
15
16 #include "ruby/config.h"
17 #include "ruby/defines.h"
18 #include "ruby/missing.h"
19 #include "addr2line.h"
20
21 #include <stdio.h>
22 #include <errno.h>
23
24 #ifdef HAVE_LIBPROC_H
25 #include <libproc.h>
26 #endif
27
28 #ifdef HAVE_STDBOOL_H
29 #include <stdbool.h>
30 #else
31 #include "missing/stdbool.h"
32 #endif
33
34 #if defined(USE_ELF) || defined(HAVE_MACH_O_LOADER_H)
35
36 #include <fcntl.h>
37 #include <limits.h>
38 #include <stdio.h>
39 #include <stdint.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <sys/mman.h>
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 #include <unistd.h>
46
47 /* Make alloca work the best possible way. */
48 #ifdef __GNUC__
49 # ifndef alloca
50 # define alloca __builtin_alloca
51 # endif
52 #else
53 # ifdef HAVE_ALLOCA_H
54 # include <alloca.h>
55 # else
56 # ifdef _AIX
57 #pragma alloca
58 # else
59 # ifndef alloca /* predefined by HP cc +Olibcalls */
60 void *alloca();
61 # endif
62 # endif /* AIX */
63 # endif /* HAVE_ALLOCA_H */
64 #endif /* __GNUC__ */
65
66 #ifdef HAVE_DLADDR
67 # include <dlfcn.h>
68 #endif
69
70 #ifdef HAVE_MACH_O_LOADER_H
71 # include <crt_externs.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>
76 #endif
77
78 #ifdef USE_ELF
79 # ifdef __OpenBSD__
80 # include <elf_abi.h>
81 # else
82 # include <elf.h>
83 # endif
84
85 #ifndef ElfW
86 # if SIZEOF_VOIDP == 8
87 # define ElfW(x) Elf64##_##x
88 # else
89 # define ElfW(x) Elf32##_##x
90 # endif
91 #endif
92 #ifndef ELF_ST_TYPE
93 # if SIZEOF_VOIDP == 8
94 # define ELF_ST_TYPE ELF64_ST_TYPE
95 # else
96 # define ELF_ST_TYPE ELF32_ST_TYPE
97 # endif
98 #endif
99 #endif
100
101 #ifdef SHF_COMPRESSED
102 # if defined(ELFCOMPRESS_ZLIB) && defined(HAVE_LIBZ)
103 /* FreeBSD 11.0 lacks ELFCOMPRESS_ZLIB */
104 # include <zlib.h>
105 # define SUPPORT_COMPRESSED_DEBUG_LINE
106 # endif
107 #else /* compatibility with glibc < 2.22 */
108 # define SHF_COMPRESSED 0
109 #endif
110
111 #ifndef PATH_MAX
112 #define PATH_MAX 4096
113 #endif
114
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 /* DWARF3 */
125 #define DW_LNS_set_epilogue_begin 0x0b /* DWARF3 */
126 #define DW_LNS_set_isa 0x0c /* DWARF3 */
127
128 /* Line number extended opcode name. */
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 /* DWARF4 */
133
134 PRINTF_ARGS(static int kprintf(const char *fmt, ...), 1, 2);
135
136 typedef struct line_info {
137 const char *dirname;
138 const char *filename;
139 const char *path; /* object path */
140 int line;
141
142 uintptr_t base_addr;
143 uintptr_t saddr;
144 const char *sname; /* function name */
145
146 struct line_info *next;
147 } line_info_t;
148
149 struct dwarf_section {
150 char *ptr;
151 size_t size;
152 uint64_t flags;
153 };
154
155 typedef struct obj_info {
156 const char *path; /* object path */
157 char *mapped;
158 size_t mapped_size;
159 void *uncompressed;
160 uintptr_t base_addr;
161 uintptr_t vmaddr;
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;
168 } obj_info_t;
169
170 #define DWARF_SECTION_COUNT 5
171
172 static struct dwarf_section *
173 obj_dwarf_section_at(obj_info_t *obj, int n)
174 {
175 struct dwarf_section *ary[] = {
176 &obj->debug_abbrev,
177 &obj->debug_info,
178 &obj->debug_line,
179 &obj->debug_ranges,
180 &obj->debug_str
181 };
182 if (n < 0 || DWARF_SECTION_COUNT <= n) {
183 abort();
184 }
185 return ary[n];
186 }
187
188 struct debug_section_definition {
189 const char *name;
190 struct dwarf_section *dwarf;
191 };
192
193 /* Avoid consuming stack as this module may be used from signal handler */
194 static char binary_filename[PATH_MAX + 1];
195
196 static unsigned long
197 uleb128(char **p)
198 {
199 unsigned long r = 0;
200 int s = 0;
201 for (;;) {
202 unsigned char b = *(unsigned char *)(*p)++;
203 if (b < 0x80) {
204 r += (unsigned long)b << s;
205 break;
206 }
207 r += (b & 0x7f) << s;
208 s += 7;
209 }
210 return r;
211 }
212
213 static long
214 sleb128(char **p)
215 {
216 long r = 0;
217 int s = 0;
218 for (;;) {
219 unsigned char b = *(unsigned char *)(*p)++;
220 if (b < 0x80) {
221 if (b & 0x40) {
222 r -= (0x80 - b) << s;
223 }
224 else {
225 r += (b & 0x3f) << s;
226 }
227 break;
228 }
229 r += (b & 0x7f) << s;
230 s += 7;
231 }
232 return r;
233 }
234
235 static const char *
236 get_nth_dirname(unsigned long dir, char *p)
237 {
238 if (!dir--) {
239 return "";
240 }
241 while (dir--) {
242 while (*p) p++;
243 p++;
244 if (!*p) {
245 kprintf("Unexpected directory number %lu in %s\n",
246 dir, binary_filename);
247 return "";
248 }
249 }
250 return p;
251 }
252
253 static void
254 fill_filename(int file, char *include_directories, char *filenames, line_info_t *line, obj_info_t *obj)
255 {
256 int i;
257 char *p = filenames;
258 char *filename;
259 unsigned long dir;
260 for (i = 1; i <= file; i++) {
261 filename = p;
262 if (!*p) {
263 /* Need to output binary file name? */
264 kprintf("Unexpected file number %d in %s at %tx\n",
265 file, binary_filename, filenames - obj->mapped);
266 return;
267 }
268 while (*p) p++;
269 p++;
270 dir = uleb128(&p);
271 /* last modified. */
272 uleb128(&p);
273 /* size of the file. */
274 uleb128(&p);
275
276 if (i == file) {
277 line->filename = filename;
278 line->dirname = get_nth_dirname(dir, include_directories);
279 }
280 }
281 }
282
283 static void
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)
287 {
288 int i;
289 addr += obj->base_addr - obj->vmaddr;
290 for (i = offset; i < num_traces; i++) {
291 uintptr_t a = (uintptr_t)traces[i];
292 /* We assume one line code doesn't result >100 bytes of native code.
293 We may want more reliable way eventually... */
294 if (addr < a && a < addr + 100) {
295 fill_filename(file, include_directories, filenames, &lines[i], obj);
296 lines[i].line = line;
297 }
298 }
299 }
300
301 struct LineNumberProgramHeader {
302 uint64_t unit_length;
303 uint16_t version;
304 uint8_t format; /* 4 or 8 */
305 uint64_t header_length;
306 uint8_t minimum_instruction_length;
307 uint8_t maximum_operations_per_instruction;
308 uint8_t default_is_stmt;
309 int8_t line_base;
310 uint8_t line_range;
311 uint8_t opcode_base;
312 /* uint8_t standard_opcode_lengths[opcode_base-1]; */
313 const char *include_directories;
314 const char *filenames;
315 const char *cu_start;
316 const char *cu_end;
317 };
318
319 static int
320 parse_debug_line_header(const char **pp, struct LineNumberProgramHeader *header)
321 {
322 const char *p = *pp;
323 header->unit_length = *(uint32_t *)p;
324 p += sizeof(uint32_t);
325
326 header->format = 4;
327 if (header->unit_length == 0xffffffff) {
328 header->unit_length = *(uint64_t *)p;
329 p += sizeof(uint64_t);
330 header->format = 8;
331 }
332
333 header->cu_end = p + header->unit_length;
334
335 header->version = *(uint16_t *)p;
336 p += sizeof(uint16_t);
337 if (header->version > 4) return -1;
338
339 header->header_length = header->format == 4 ? *(uint32_t *)p : *(uint64_t *)p;
340 p += header->format;
341 header->cu_start = p + header->header_length;
342
343 header->minimum_instruction_length = *(uint8_t *)p++;
344
345 if (header->version >= 4) {
346 /* maximum_operations_per_instruction = *(uint8_t *)p; */
347 if (*p != 1) return -1; /* For non-VLIW architectures, this field is 1 */
348 p++;
349 }
350
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++;
355 /* header->standard_opcode_lengths = (uint8_t *)p - 1; */
356 p += header->opcode_base - 1;
357
358 header->include_directories = p;
359
360 /* temporary measure for compress-debug-sections */
361 if (p >= header->cu_end) return -1;
362
363 /* skip include directories */
364 while (*p) {
365 p = memchr(p, '\0', header->cu_end - p);
366 if (!p) return -1;
367 p++;
368 }
369 p++;
370
371 header->filenames = p;
372
373 *pp = header->cu_start;
374
375 return 0;
376 }
377
378 static int
379 parse_debug_line_cu(int num_traces, void **traces, char **debug_line,
380 obj_info_t *obj, line_info_t *lines, int offset)
381 {
382 const char *p = (const char *)*debug_line;
383 struct LineNumberProgramHeader header;
384
385 /* The registers. */
386 unsigned long addr = 0;
387 unsigned int file = 1;
388 unsigned int line = 1;
389 /* unsigned int column = 0; */
390 int is_stmt;
391 /* int basic_block = 0; */
392 /* int end_sequence = 0; */
393 /* int prologue_end = 0; */
394 /* int epilogue_begin = 0; */
395 /* unsigned int isa = 0; */
396
397 if (parse_debug_line_header(&p, &header))
398 return -1;
399 is_stmt = header.default_is_stmt;
400
401 #define FILL_LINE() \
402 do { \
403 fill_line(num_traces, traces, addr, file, line, \
404 (char *)header.include_directories, \
405 (char *)header.filenames, \
406 obj, lines, offset); \
407 /*basic_block = prologue_end = epilogue_begin = 0;*/ \
408 } while (0)
409
410 while (p < header.cu_end) {
411 unsigned long a;
412 unsigned char op = *p++;
413 switch (op) {
414 case DW_LNS_copy:
415 FILL_LINE();
416 break;
417 case DW_LNS_advance_pc:
418 a = uleb128((char **)&p);
419 addr += a;
420 break;
421 case DW_LNS_advance_line: {
422 long a = sleb128((char **)&p);
423 line += a;
424 break;
425 }
426 case DW_LNS_set_file:
427 file = (unsigned int)uleb128((char **)&p);
428 break;
429 case DW_LNS_set_column:
430 /*column = (unsigned int)*/(void)uleb128((char **)&p);
431 break;
432 case DW_LNS_negate_stmt:
433 is_stmt = !is_stmt;
434 break;
435 case DW_LNS_set_basic_block:
436 /*basic_block = 1; */
437 break;
438 case DW_LNS_const_add_pc:
439 a = ((255UL - header.opcode_base) / header.line_range) *
440 header.minimum_instruction_length;
441 addr += a;
442 break;
443 case DW_LNS_fixed_advance_pc:
444 a = *(unsigned char *)p++;
445 addr += a;
446 break;
447 case DW_LNS_set_prologue_end:
448 /* prologue_end = 1; */
449 break;
450 case DW_LNS_set_epilogue_begin:
451 /* epilogue_begin = 1; */
452 break;
453 case DW_LNS_set_isa:
454 /* isa = (unsigned int)*/(void)uleb128((char **)&p);
455 break;
456 case 0:
457 a = *(unsigned char *)p++;
458 op = *p++;
459 switch (op) {
460 case DW_LNE_end_sequence:
461 /* end_sequence = 1; */
462 FILL_LINE();
463 addr = 0;
464 file = 1;
465 line = 1;
466 /* column = 0; */
467 is_stmt = header.default_is_stmt;
468 /* end_sequence = 0; */
469 /* isa = 0; */
470 break;
471 case DW_LNE_set_address:
472 addr = *(unsigned long *)p;
473 p += sizeof(unsigned long);
474 break;
475 case DW_LNE_define_file:
476 kprintf("Unsupported operation in %s\n",
477 binary_filename);
478 break;
479 case DW_LNE_set_discriminator:
480 /* TODO:currently ignore */
481 uleb128((char **)&p);
482 break;
483 default:
484 kprintf("Unknown extended opcode: %d in %s\n",
485 op, binary_filename);
486 }
487 break;
488 default: {
489 uint8_t adjusted_opcode = op - header.opcode_base;
490 uint8_t operation_advance = adjusted_opcode / header.line_range;
491 /* NOTE: this code doesn't support VLIW */
492 addr += operation_advance * header.minimum_instruction_length;
493 line += header.line_base + (adjusted_opcode % header.line_range);
494 FILL_LINE();
495 }
496 }
497 }
498 *debug_line = (char *)p;
499 return 0;
500 }
501
502 static int
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)
506 {
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))
510 return -1;
511 }
512 if (debug_line != debug_line_end) {
513 kprintf("Unexpected size of .debug_line in %s\n",
514 binary_filename);
515 }
516 return 0;
517 }
518
519 /* read file and fill lines */
520 static uintptr_t
521 fill_lines(int num_traces, void **traces, int check_debuglink,
522 obj_info_t **objp, line_info_t *lines, int offset);
523
524 static void
525 append_obj(obj_info_t **objp)
526 {
527 obj_info_t *newobj = calloc(1, sizeof(obj_info_t));
528 if (*objp) (*objp)->next = newobj;
529 *objp = newobj;
530 }
531
532 #ifdef USE_ELF
533 static void
534 follow_debuglink(const char *debuglink, int num_traces, void **traces,
535 obj_info_t **objp, line_info_t *lines, int offset)
536 {
537 /* Ideally we should check 4 paths to follow gnu_debuglink,
538 but we handle only one case for now as this format is used
539 by some linux distributions. See GDB's info for detail. */
540 static const char global_debug_dir[] = "/usr/lib/debug";
541 const size_t global_debug_dir_len = sizeof(global_debug_dir) - 1;
542 char *p;
543 obj_info_t *o1 = *objp, *o2;
544 size_t len;
545
546 p = strrchr(binary_filename, '/');
547 if (!p) {
548 return;
549 }
550 p[1] = '\0';
551
552 len = strlen(binary_filename);
553 if (len >= PATH_MAX - global_debug_dir_len)
554 len = PATH_MAX - global_debug_dir_len - 1;
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;
558 strlcpy(binary_filename + len, debuglink, PATH_MAX - len);
559
560 append_obj(objp);
561 o2 = *objp;
562 o2->base_addr = o1->base_addr;
563 o2->path = o1->path;
564 fill_lines(num_traces, traces, 0, objp, lines, offset);
565 }
566 #endif
567
568 enum
569 {
570 DW_TAG_compile_unit = 0x11,
571 DW_TAG_inlined_subroutine = 0x1d,
572 DW_TAG_subprogram = 0x2e,
573 };
574
575 /* Attributes encodings */
576 enum
577 {
578 DW_AT_sibling = 0x01,
579 DW_AT_location = 0x02,
580 DW_AT_name = 0x03,
581 /* Reserved 0x04 */
582 /* Reserved 0x05 */
583 /* Reserved 0x06 */
584 /* Reserved 0x07 */
585 /* Reserved 0x08 */
586 DW_AT_ordering = 0x09,
587 /* Reserved 0x0a */
588 DW_AT_byte_size = 0x0b,
589 /* Reserved 0x0c */
590 DW_AT_bit_size = 0x0d,
591 /* Reserved 0x0e */
592 /* Reserved 0x0f */
593 DW_AT_stmt_list = 0x10,
594 DW_AT_low_pc = 0x11,
595 DW_AT_high_pc = 0x12,
596 DW_AT_language = 0x13,
597 /* Reserved 0x14 */
598 DW_AT_discr = 0x15,
599 DW_AT_discr_value = 0x16,
600 DW_AT_visibility = 0x17,
601 DW_AT_import = 0x18,
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,
608 /* Reserved 0x1f */
609 DW_AT_inline = 0x20,
610 DW_AT_is_optional = 0x21,
611 DW_AT_lower_bound = 0x22,
612 /* Reserved 0x23 */
613 /* Reserved 0x24 */
614 DW_AT_producer = 0x25,
615 /* Reserved 0x26 */
616 DW_AT_prototyped = 0x27,
617 /* Reserved 0x28 */
618 /* Reserved 0x29 */
619 DW_AT_return_addr = 0x2a,
620 /* Reserved 0x2b */
621 DW_AT_start_scope = 0x2c,
622 /* Reserved 0x2d */
623 DW_AT_bit_stride = 0x2e,
624 DW_AT_upper_bound = 0x2f,
625 /* Reserved 0x30 */
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,
632 DW_AT_count = 0x37,
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,
642 DW_AT_friend = 0x41,
643 DW_AT_identifier_case = 0x42,
644 /* Reserved 0x43 */
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,
650 DW_AT_type = 0x49,
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,
662 DW_AT_ranges = 0x55,
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,
670 DW_AT_small = 0x5d,
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,
680 DW_AT_pure = 0x67,
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,
690 DW_AT_rank = 0x71,
691 DW_AT_str_offsets_base = 0x72,
692 DW_AT_addr_base = 0x73,
693 DW_AT_rnglists_base = 0x74,
694 /* Reserved 0x75 */
695 DW_AT_dwo_name = 0x76,
696 DW_AT_reference = 0x77,
697 DW_AT_rvalue_reference = 0x78,
698 DW_AT_macros = 0x79,
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
720 };
721
722 /* Attribute form encodings */
723 enum
724 {
725 DW_FORM_addr = 0x01,
726 /* Reserved 0x02 */
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,
736 DW_FORM_flag = 0x0c,
737 DW_FORM_sdata = 0x0d,
738 DW_FORM_strp = 0x0e,
739 DW_FORM_udata = 0x0f,
740 DW_FORM_ref_addr = 0x10,
741 DW_FORM_ref1 = 0x11,
742 DW_FORM_ref2 = 0x12,
743 DW_FORM_ref4 = 0x13,
744 DW_FORM_ref8 = 0x14,
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,
750 DW_FORM_strx = 0x1a,
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
769 };
770
771 enum {
772 VAL_none = 0,
773 VAL_cstr = 1,
774 VAL_data = 2,
775 VAL_uint = 3,
776 VAL_int = 4
777 };
778
779 # define ABBREV_TABLE_SIZE 256
780 typedef struct {
781 obj_info_t *obj;
782 char *file;
783 char *current_cu;
784 uint64_t current_low_pc;
785 char *debug_line_cu_end;
786 char *debug_line_files;
787 char *debug_line_directories;
788 char *p;
789 char *cu_end;
790 char *pend;
791 char *q0;
792 char *q;
793 int format; // 4 or 8
794 uint8_t address_size;
795 int level;
796 char *abbrev_table[ABBREV_TABLE_SIZE];
797 } DebugInfoReader;
798
799 typedef struct {
800 ptrdiff_t pos;
801 int tag;
802 int has_children;
803 } DIE;
804
805 typedef struct {
806 union {
807 char *ptr;
808 uint64_t uint64;
809 int64_t int64;
810 } as;
811 uint64_t off;
812 uint64_t at;
813 uint64_t form;
814 size_t size;
815 int type;
816 } DebugInfoValue;
817
818 /* TODO: Big Endian */
819 #define MERGE_2INTS(a,b,sz) (((uint64_t)(b)<<sz)|(a))
820
821 static uint16_t
822 get_uint16(const uint8_t *p)
823 {
824 return (uint16_t)MERGE_2INTS(p[0],p[1],8);
825 }
826
827 static uint32_t
828 get_uint32(const uint8_t *p)
829 {
830 return (uint32_t)MERGE_2INTS(get_uint16(p),get_uint16(p+2),16);
831 }
832
833 static uint64_t
834 get_uint64(const uint8_t *p)
835 {
836 return MERGE_2INTS(get_uint32(p),get_uint32(p+4),32);
837 }
838
839 static uint8_t
840 read_uint8(char **ptr)
841 {
842 const unsigned char *p = (const unsigned char *)*ptr;
843 *ptr = (char *)(p + 1);
844 return *p;
845 }
846
847 static uint16_t
848 read_uint16(char **ptr)
849 {
850 const unsigned char *p = (const unsigned char *)*ptr;
851 *ptr = (char *)(p + 2);
852 return get_uint16(p);
853 }
854
855 static uint32_t
856 read_uint24(char **ptr)
857 {
858 const unsigned char *p = (const unsigned char *)*ptr;
859 *ptr = (char *)(p + 3);
860 return (*p << 16) | get_uint16(p+1);
861 }
862
863 static uint32_t
864 read_uint32(char **ptr)
865 {
866 const unsigned char *p = (const unsigned char *)*ptr;
867 *ptr = (char *)(p + 4);
868 return get_uint32(p);
869 }
870
871 static uint64_t
872 read_uint64(char **ptr)
873 {
874 const unsigned char *p = (const unsigned char *)*ptr;
875 *ptr = (char *)(p + 8);
876 return get_uint64(p);
877 }
878
879 static uintptr_t
880 read_uintptr(char **ptr)
881 {
882 const unsigned char *p = (const unsigned char *)*ptr;
883 *ptr = (char *)(p + SIZEOF_VOIDP);
884 #if SIZEOF_VOIDP == 8
885 return get_uint64(p);
886 #else
887 return get_uint32(p);
888 #endif
889 }
890
891 static uint64_t
892 read_uint(DebugInfoReader *reader)
893 {
894 if (reader->format == 4) {
895 return read_uint32(&reader->p);
896 } else { /* 64 bit */
897 return read_uint64(&reader->p);
898 }
899 }
900
901 static uint64_t
902 read_uleb128(DebugInfoReader *reader)
903 {
904 return uleb128(&reader->p);
905 }
906
907 static int64_t
908 read_sleb128(DebugInfoReader *reader)
909 {
910 return sleb128(&reader->p);
911 }
912
913 static void
914 debug_info_reader_init(DebugInfoReader *reader, obj_info_t *obj)
915 {
916 reader->file = obj->mapped;
917 reader->obj = obj;
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;
921 }
922
923 static void
924 di_read_debug_abbrev_cu(DebugInfoReader *reader)
925 {
926 uint64_t prev = 0;
927 char *p = reader->q0;
928 for (;;) {
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;
933 }
934 prev = abbrev_number;
935 uleb128(&p); /* tag */
936 p++; /* has_children */
937 /* skip content */
938 for (;;) {
939 uint64_t at = uleb128(&p);
940 uint64_t form = uleb128(&p);
941 if (!at && !form) break;
942 }
943 }
944 }
945
946 static int
947 di_read_debug_line_cu(DebugInfoReader *reader)
948 {
949 const char *p;
950 struct LineNumberProgramHeader header;
951
952 p = (const char *)reader->debug_line_cu_end;
953 if (parse_debug_line_header(&p, &header))
954 return -1;
955
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;
959
960 return 0;
961 }
962
963 static void
964 set_uint_value(DebugInfoValue *v, uint64_t n)
965 {
966 v->as.uint64 = n;
967 v->type = VAL_uint;
968 }
969
970 static void
971 set_int_value(DebugInfoValue *v, int64_t n)
972 {
973 v->as.int64 = n;
974 v->type = VAL_int;
975 }
976
977 static void
978 set_cstr_value(DebugInfoValue *v, char *s)
979 {
980 v->as.ptr = s;
981 v->off = 0;
982 v->type = VAL_cstr;
983 }
984
985 static void
986 set_cstrp_value(DebugInfoValue *v, char *s, uint64_t off)
987 {
988 v->as.ptr = s;
989 v->off = off;
990 v->type = VAL_cstr;
991 }
992
993 static void
994 set_data_value(DebugInfoValue *v, char *s)
995 {
996 v->as.ptr = s;
997 v->type = VAL_data;
998 }
999
1000 static const char *
1001 get_cstr_value(DebugInfoValue *v)
1002 {
1003 if (v->as.ptr) {
1004 return v->as.ptr + v->off;
1005 } else {
1006 return NULL;
1007 }
1008 }
1009
1010 static void
1011 debug_info_reader_read_value(DebugInfoReader *reader, uint64_t form, DebugInfoValue *v)
1012 {
1013 switch (form) {
1014 case DW_FORM_addr:
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));
1019 } else {
1020 fprintf(stderr,"unknown address_size:%d", reader->address_size);
1021 abort();
1022 }
1023 break;
1024 case DW_FORM_block2:
1025 v->size = read_uint16(&reader->p);
1026 set_data_value(v, reader->p);
1027 reader->p += v->size;
1028 break;
1029 case DW_FORM_block4:
1030 v->size = read_uint32(&reader->p);
1031 set_data_value(v, reader->p);
1032 reader->p += v->size;
1033 break;
1034 case DW_FORM_data2:
1035 set_uint_value(v, read_uint16(&reader->p));
1036 break;
1037 case DW_FORM_data4:
1038 set_uint_value(v, read_uint32(&reader->p));
1039 break;
1040 case DW_FORM_data8:
1041 set_uint_value(v, read_uint64(&reader->p));
1042 break;
1043 case DW_FORM_string:
1044 v->size = strlen(reader->p);
1045 set_cstr_value(v, reader->p);
1046 reader->p += v->size + 1;
1047 break;
1048 case DW_FORM_block:
1049 v->size = uleb128(&reader->p);
1050 set_data_value(v, reader->p);
1051 reader->p += v->size;
1052 break;
1053 case DW_FORM_block1:
1054 v->size = read_uint8(&reader->p);
1055 set_data_value(v, reader->p);
1056 reader->p += v->size;
1057 break;
1058 case DW_FORM_data1:
1059 set_uint_value(v, read_uint8(&reader->p));
1060 break;
1061 case DW_FORM_flag:
1062 set_uint_value(v, read_uint8(&reader->p));
1063 break;
1064 case DW_FORM_sdata:
1065 set_int_value(v, read_sleb128(reader));
1066 break;
1067 case DW_FORM_strp:
1068 set_cstrp_value(v, reader->obj->debug_str.ptr, read_uint(reader));
1069 break;
1070 case DW_FORM_udata:
1071 set_uint_value(v, read_uleb128(reader));
1072 break;
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));
1078 } else {
1079 fprintf(stderr,"unknown address_size:%d", reader->address_size);
1080 abort();
1081 }
1082 break;
1083 case DW_FORM_ref1:
1084 set_uint_value(v, read_uint8(&reader->p));
1085 break;
1086 case DW_FORM_ref2:
1087 set_uint_value(v, read_uint16(&reader->p));
1088 break;
1089 case DW_FORM_ref4:
1090 set_uint_value(v, read_uint32(&reader->p));
1091 break;
1092 case DW_FORM_ref8:
1093 set_uint_value(v, read_uint64(&reader->p));
1094 break;
1095 case DW_FORM_ref_udata:
1096 set_uint_value(v, uleb128(&reader->p));
1097 break;
1098 case DW_FORM_indirect:
1099 /* TODO: read the referred value */
1100 set_uint_value(v, uleb128(&reader->p));
1101 break;
1102 case DW_FORM_sec_offset:
1103 set_uint_value(v, read_uint(reader)); /* offset */
1104 /* addrptr: debug_addr */
1105 /* lineptr: debug_line */
1106 /* loclist: debug_loclists */
1107 /* loclistptr: debug_loclists */
1108 /* macptr: debug_macro */
1109 /* rnglist: debug_rnglists */
1110 /* rnglistptr: debug_rnglists */
1111 /* stroffsetsptr: debug_str_offsets */
1112 break;
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;
1117 break;
1118 case DW_FORM_flag_present:
1119 set_uint_value(v, 1);
1120 break;
1121 case DW_FORM_strx:
1122 set_uint_value(v, uleb128(&reader->p));
1123 break;
1124 case DW_FORM_addrx:
1125 /* TODO: read .debug_addr */
1126 set_uint_value(v, uleb128(&reader->p));
1127 break;
1128 case DW_FORM_ref_sup4:
1129 set_uint_value(v, read_uint32(&reader->p));
1130 break;
1131 case DW_FORM_strp_sup:
1132 set_uint_value(v, read_uint(reader));
1133 /* *p = reader->sup_file + reader->sup_str->sh_offset + ret; */
1134 break;
1135 case DW_FORM_data16:
1136 v->size = 16;
1137 set_data_value(v, reader->p);
1138 reader->p += v->size;
1139 break;
1140 case DW_FORM_line_strp:
1141 set_uint_value(v, read_uint(reader));
1142 /* *p = reader->file + reader->line->sh_offset + ret; */
1143 break;
1144 case DW_FORM_ref_sig8:
1145 set_uint_value(v, read_uint64(&reader->p));
1146 break;
1147 case DW_FORM_implicit_const:
1148 set_int_value(v, sleb128(&reader->q));
1149 break;
1150 case DW_FORM_loclistx:
1151 set_uint_value(v, read_uleb128(reader));
1152 break;
1153 case DW_FORM_rnglistx:
1154 set_uint_value(v, read_uleb128(reader));
1155 break;
1156 case DW_FORM_ref_sup8:
1157 set_uint_value(v, read_uint64(&reader->p));
1158 break;
1159 case DW_FORM_strx1:
1160 set_uint_value(v, read_uint8(&reader->p));
1161 break;
1162 case DW_FORM_strx2:
1163 set_uint_value(v, read_uint16(&reader->p));
1164 break;
1165 case DW_FORM_strx3:
1166 set_uint_value(v, read_uint24(&reader->p));
1167 break;
1168 case DW_FORM_strx4:
1169 set_uint_value(v, read_uint32(&reader->p));
1170 break;
1171 case DW_FORM_addrx1:
1172 set_uint_value(v, read_uint8(&reader->p));
1173 break;
1174 case DW_FORM_addrx2:
1175 set_uint_value(v, read_uint16(&reader->p));
1176 break;
1177 case DW_FORM_addrx3:
1178 set_uint_value(v, read_uint24(&reader->p));
1179 break;
1180 case DW_FORM_addrx4:
1181 set_uint_value(v, read_uint32(&reader->p));
1182 break;
1183 case 0:
1184 goto fail;
1185 break;
1186 }
1187 return;
1188
1189 fail:
1190 fprintf(stderr, "%d: unsupported form: %#"PRIx64"\n", __LINE__, form);
1191 exit(1);
1192 }
1193
1194 /* find abbrev in current compilation unit */
1195 static char *
1196 di_find_abbrev(DebugInfoReader *reader, uint64_t abbrev_number)
1197 {
1198 char *p;
1199 if (abbrev_number < ABBREV_TABLE_SIZE) {
1200 return reader->abbrev_table[abbrev_number];
1201 }
1202 p = reader->abbrev_table[ABBREV_TABLE_SIZE-1];
1203 /* skip 255th record */
1204 uleb128(&p); /* tag */
1205 p++; /* has_children */
1206 /* skip content */
1207 for (;;) {
1208 uint64_t at = uleb128(&p);
1209 uint64_t form = uleb128(&p);
1210 if (!at && !form) break;
1211 }
1212 for (uint64_t n = uleb128(&p); abbrev_number != n; n = uleb128(&p)) {
1213 if (n == 0) {
1214 fprintf(stderr,"%d: Abbrev Number %"PRId64" not found\n",__LINE__, abbrev_number);
1215 exit(1);
1216 }
1217 uleb128(&p); /* tag */
1218 p++; /* has_children */
1219 /* skip content */
1220 for (;;) {
1221 uint64_t at = uleb128(&p);
1222 uint64_t form = uleb128(&p);
1223 if (!at && !form) break;
1224 }
1225 }
1226 return p;
1227 }
1228
1229 #if 0
1230 static void
1231 hexdump0(const unsigned char *p, size_t n)
1232 {
1233 size_t i;
1234 fprintf(stderr, " 0 1 2 3 4 5 6 7 8 9 A B C D E F\n");
1235 for (i=0; i < n; i++){
1236 switch (i & 15) {
1237 case 0:
1238 fprintf(stderr, "%02zd: %02X ", i/16, p[i]);
1239 break;
1240 case 15:
1241 fprintf(stderr, "%02X\n", p[i]);
1242 break;
1243 default:
1244 fprintf(stderr, "%02X ", p[i]);
1245 break;
1246 }
1247 }
1248 if ((i & 15) != 15) {
1249 fprintf(stderr, "\n");
1250 }
1251 }
1252 #define hexdump(p,n) hexdump0((const unsigned char *)p, n)
1253
1254 static void
1255 div_inspect(DebugInfoValue *v)
1256 {
1257 switch (v->type) {
1258 case VAL_uint:
1259 fprintf(stderr,"%d: type:%d size:%zx v:%lx\n",__LINE__,v->type,v->size,v->as.uint64);
1260 break;
1261 case VAL_int:
1262 fprintf(stderr,"%d: type:%d size:%zx v:%ld\n",__LINE__,v->type,v->size,(int64_t)v->as.uint64);
1263 break;
1264 case VAL_cstr:
1265 fprintf(stderr,"%d: type:%d size:%zx v:'%s'\n",__LINE__,v->type,v->size,v->as.ptr);
1266 break;
1267 case VAL_data:
1268 fprintf(stderr,"%d: type:%d size:%zx v:\n",__LINE__,v->type,v->size);
1269 hexdump(v->as.ptr, 16);
1270 break;
1271 }
1272 }
1273 #endif
1274
1275 static DIE *
1276 di_read_die(DebugInfoReader *reader, DIE *die)
1277 {
1278 uint64_t abbrev_number = uleb128(&reader->p);
1279 if (abbrev_number == 0) {
1280 reader->level--;
1281 return NULL;
1282 }
1283
1284 reader->q = di_find_abbrev(reader, abbrev_number);
1285
1286 die->pos = reader->p - reader->obj->debug_info.ptr - 1;
1287 die->tag = (int)uleb128(&reader->q); /* tag */
1288 die->has_children = *reader->q++; /* has_children */
1289 if (die->has_children) {
1290 reader->level++;
1291 }
1292 return die;
1293 }
1294
1295 static DebugInfoValue *
1296 di_read_record(DebugInfoReader *reader, DebugInfoValue *vp)
1297 {
1298 uint64_t at = uleb128(&reader->q);
1299 uint64_t form = uleb128(&reader->q);
1300 if (!at || !form) return NULL;
1301 vp->at = at;
1302 vp->form = form;
1303 debug_info_reader_read_value(reader, form, vp);
1304 return vp;
1305 }
1306
1307 static void
1308 di_skip_records(DebugInfoReader *reader)
1309 {
1310 for (;;) {
1311 DebugInfoValue v = {{}};
1312 uint64_t at = uleb128(&reader->q);
1313 uint64_t form = uleb128(&reader->q);
1314 if (!at || !form) return;
1315 debug_info_reader_read_value(reader, form, &v);
1316 }
1317 }
1318
1319 typedef struct {
1320 uint64_t low_pc;
1321 uint64_t high_pc;
1322 uint64_t ranges;
1323 bool low_pc_set;
1324 bool high_pc_set;
1325 bool ranges_set;
1326 } ranges_t;
1327
1328 static void
1329 ranges_set(ranges_t *ptr, DebugInfoValue *v)
1330 {
1331 switch (v->at) {
1332 case DW_AT_low_pc:
1333 ptr->low_pc = v->as.uint64;
1334 ptr->low_pc_set = true;
1335 break;
1336 case DW_AT_high_pc:
1337 if (v->form == DW_FORM_addr) {
1338 ptr->high_pc = v->as.uint64;
1339 }
1340 else {
1341 ptr->high_pc = ptr->low_pc + v->as.uint64;
1342 }
1343 ptr->high_pc_set = true;
1344 break;
1345 case DW_AT_ranges:
1346 ptr->ranges = v->as.uint64;
1347 ptr->ranges_set = true;
1348 break;
1349 }
1350 }
1351
1352 static uintptr_t
1353 ranges_include(DebugInfoReader *reader, ranges_t *ptr, uint64_t addr)
1354 {
1355 if (ptr->high_pc_set) {
1356 if (ptr->ranges_set || !ptr->low_pc_set) {
1357 exit(1);
1358 }
1359 if (ptr->low_pc <= addr && addr <= ptr->high_pc) {
1360 return (uintptr_t)ptr->low_pc;
1361 }
1362 }
1363 else if (ptr->ranges_set) {
1364 /* TODO: support base address selection entry */
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;
1367 for (;;) {
1368 uintptr_t from = read_uintptr(&p);
1369 uintptr_t to = read_uintptr(&p);
1370 if (!from && !to) break;
1371 if (from == UINTPTR_MAX) {
1372 /* base address selection entry */
1373 base = to;
1374 }
1375 else if (base + from <= addr && addr < base + to) {
1376 return from;
1377 }
1378 }
1379 }
1380 else if (ptr->low_pc_set) {
1381 if (ptr->low_pc == addr) {
1382 return (uintptr_t)ptr->low_pc;
1383 }
1384 }
1385 return false;
1386 }
1387
1388 #if 0
1389 static void
1390 ranges_inspect(DebugInfoReader *reader, ranges_t *ptr)
1391 {
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);
1395 exit(1);
1396 }
1397 fprintf(stderr,"low_pc:%"PRIx64" high_pc:%"PRIx64"\n",ptr->low_pc,ptr->high_pc);
1398 }
1399 else if (ptr->ranges_set) {
1400 char *p = reader->obj->debug_ranges.ptr + ptr->ranges;
1401 fprintf(stderr,"low_pc:%"PRIx64" ranges:%"PRIx64" %lx ",ptr->low_pc,ptr->ranges, p-reader->obj->mapped);
1402 for (;;) {
1403 uintptr_t from = read_uintptr(&p);
1404 uintptr_t to = read_uintptr(&p);
1405 if (!from && !to) break;
1406 fprintf(stderr,"%"PRIx64"-%"PRIx64" ",ptr->low_pc+from,ptr->low_pc+to);
1407 }
1408 fprintf(stderr,"\n");
1409 }
1410 else if (ptr->low_pc_set) {
1411 fprintf(stderr,"low_pc:%"PRIx64"\n",ptr->low_pc);
1412 }
1413 else {
1414 fprintf(stderr,"empty\n");
1415 }
1416 }
1417 #endif
1418
1419 static int
1420 di_read_cu(DebugInfoReader *reader)
1421 {
1422 uint64_t unit_length;
1423 uint16_t version;
1424 uint64_t debug_abbrev_offset;
1425 reader->format = 4;
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);
1430 reader->format = 8;
1431 }
1432 reader->cu_end = reader->p + unit_length;
1433 version = read_uint16(&reader->p);
1434 if (version > 5) {
1435 return -1;
1436 }
1437 else if (version == 5) {
1438 /* unit_type = */ read_uint8(&reader->p);
1439 reader->address_size = read_uint8(&reader->p);
1440 debug_abbrev_offset = read_uint(reader);
1441 }
1442 else {
1443 debug_abbrev_offset = read_uint(reader);
1444 reader->address_size = read_uint8(&reader->p);
1445 }
1446 reader->q0 = reader->obj->debug_abbrev.ptr + debug_abbrev_offset;
1447
1448 reader->level = 0;
1449 di_read_debug_abbrev_cu(reader);
1450 if (di_read_debug_line_cu(reader)) return -1;
1451
1452 #if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER_BUILD_DATE)
1453 /* Though DWARF specifies "the applicable base address defaults to the base
1454 address of the compilation unit", but GCC seems to use zero as default */
1455 #else
1456 do {
1457 DIE die;
1458
1459 if (!di_read_die(reader, &die)) continue;
1460
1461 if (die.tag != DW_TAG_compile_unit) {
1462 di_skip_records(reader);
1463 break;
1464 }
1465
1466 /* enumerate abbrev */
1467 for (;;) {
1468 DebugInfoValue v = {{}};
1469 if (!di_read_record(reader, &v)) break;
1470 switch (v.at) {
1471 case DW_AT_low_pc:
1472 reader->current_low_pc = v.as.uint64;
1473 break;
1474 }
1475 }
1476 } while (0);
1477 #endif
1478 return 0;
1479 }
1480
1481 static void
1482 read_abstract_origin(DebugInfoReader *reader, uint64_t abstract_origin, line_info_t *line)
1483 {
1484 char *p = reader->p;
1485 char *q = reader->q;
1486 int level = reader->level;
1487 DIE die;
1488
1489 reader->p = reader->current_cu + abstract_origin;
1490 if (!di_read_die(reader, &die)) goto finish;
1491
1492 /* enumerate abbrev */
1493 for (;;) {
1494 DebugInfoValue v = {{}};
1495 if (!di_read_record(reader, &v)) break;
1496 switch (v.at) {
1497 case DW_AT_name:
1498 line->sname = get_cstr_value(&v);
1499 break;
1500 }
1501 }
1502
1503 finish:
1504 reader->p = p;
1505 reader->q = q;
1506 reader->level = level;
1507 }
1508
1509 static void
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) {
1513 DIE die;
1514 ranges_t ranges = {};
1515 line_info_t line = {};
1516
1517 if (!di_read_die(reader, &die)) continue;
1518 /* fprintf(stderr,"%d:%tx: <%d>\n",__LINE__,die.pos,reader->level,die.tag); */
1519
1520 if (die.tag != DW_TAG_subprogram && die.tag != DW_TAG_inlined_subroutine) {
1521 skip_die:
1522 di_skip_records(reader);
1523 continue;
1524 }
1525
1526 /* enumerate abbrev */
1527 for (;;) {
1528 DebugInfoValue v = {{}};
1529 /* ptrdiff_t pos = reader->p - reader->p0; */
1530 if (!di_read_record(reader, &v)) break;
1531 /* fprintf(stderr,"\n%d:%tx: AT:%lx FORM:%lx\n",__LINE__,pos,v.at,v.form); */
1532 /* div_inspect(&v); */
1533 switch (v.at) {
1534 case DW_AT_name:
1535 line.sname = get_cstr_value(&v);
1536 break;
1537 case DW_AT_call_file:
1538 fill_filename((int)v.as.uint64, reader->debug_line_directories, reader->debug_line_files, &line, reader->obj);
1539 break;
1540 case DW_AT_call_line:
1541 line.line = (int)v.as.uint64;
1542 break;
1543 case DW_AT_low_pc:
1544 case DW_AT_high_pc:
1545 case DW_AT_ranges:
1546 ranges_set(&ranges, &v);
1547 break;
1548 case DW_AT_declaration:
1549 goto skip_die;
1550 case DW_AT_inline:
1551 /* 1 or 3 */
1552 break; /* goto skip_die; */
1553 case DW_AT_abstract_origin:
1554 read_abstract_origin(reader, v.as.uint64, &line);
1555 break; /* goto skip_die; */
1556 }
1557 }
1558 /* ranges_inspect(reader, &ranges); */
1559 /* fprintf(stderr,"%d:%tx: %x ",__LINE__,diepos,die.tag); */
1560 for (int i=offset; i < num_traces; i++) {
1561 uintptr_t addr = (uintptr_t)traces[i];
1562 uintptr_t offset = addr - reader->obj->base_addr + reader->obj->vmaddr;
1563 uintptr_t saddr = ranges_include(reader, &ranges, offset);
1564 if (saddr) {
1565 /* fprintf(stderr, "%d:%tx: %d %lx->%lx %x %s: %s/%s %d %s %s %s\n",__LINE__,die.pos, i,addr,offset, die.tag,line.sname,line.dirname,line.filename,line.line,reader->obj->path,line.sname,lines[i].sname); */
1566 if (lines[i].sname) {
1567 line_info_t *lp = malloc(sizeof(line_info_t));
1568 memcpy(lp, &lines[i], sizeof(line_info_t));
1569 lines[i].next = lp;
1570 lp->dirname = line.dirname;
1571 lp->filename = line.filename;
1572 lp->line = line.line;
1573 lp->saddr = 0;
1574 }
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;
1579 }
1580 }
1581 }
1582 }
1583
1584 #ifdef USE_ELF
1585 static unsigned long
1586 uncompress_debug_section(ElfW(Shdr) *shdr, char *file, char **ptr)
1587 {
1588 #ifdef SUPPORT_COMPRESSED_DEBUG_LINE
1589 ElfW(Chdr) *chdr = (ElfW(Chdr) *)(file + shdr->sh_offset);
1590 unsigned long destsize = chdr->ch_size;
1591 int ret = 0;
1592
1593 if (chdr->ch_type != ELFCOMPRESS_ZLIB) {
1594 /* unsupported compression type */
1595 return 0;
1596 }
1597
1598 *ptr = malloc(destsize);
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;
1604 return destsize;
1605
1606 fail:
1607 free(*ptr);
1608 #endif
1609 return 0;
1610 }
1611
1612 /* read file and fill lines */
1613 static uintptr_t
1614 fill_lines(int num_traces, void **traces, int check_debuglink,
1615 obj_info_t **objp, line_info_t *lines, int offset)
1616 {
1617 int i, j;
1618 char *shstr;
1619 ElfW(Ehdr) *ehdr;
1620 ElfW(Shdr) *shdr, *shstr_shdr;
1621 ElfW(Shdr) *gnu_debuglink_shdr = NULL;
1622 int fd;
1623 off_t filesize;
1624 char *file;
1625 ElfW(Shdr) *symtab_shdr = NULL, *strtab_shdr = NULL;
1626 ElfW(Shdr) *dynsym_shdr = NULL, *dynstr_shdr = NULL;
1627 obj_info_t *obj = *objp;
1628 uintptr_t dladdr_fbase = 0;
1629
1630 fd = open(binary_filename, O_RDONLY);
1631 if (fd < 0) {
1632 goto fail;
1633 }
1634 filesize = lseek(fd, 0, SEEK_END);
1635 if (filesize < 0) {
1636 int e = errno;
1637 close(fd);
1638 kprintf("lseek: %s\n", strerror(e));
1639 goto fail;
1640 }
1641 #if SIZEOF_OFF_T > SIZEOF_SIZE_T
1642 if (filesize > (off_t)SIZE_MAX) {
1643 close(fd);
1644 kprintf("Too large file %s\n", binary_filename);
1645 goto fail;
1646 }
1647 #endif
1648 lseek(fd, 0, SEEK_SET);
1649 /* async-signal unsafe */
1650 file = (char *)mmap(NULL, (size_t)filesize, PROT_READ, MAP_SHARED, fd, 0);
1651 if (file == MAP_FAILED) {
1652 int e = errno;
1653 close(fd);
1654 kprintf("mmap: %s\n", strerror(e));
1655 goto fail;
1656 }
1657 close(fd);
1658
1659 ehdr = (ElfW(Ehdr) *)file;
1660 if (memcmp(ehdr->e_ident, "\177ELF", 4) != 0) {
1661 /*
1662 * Huh? Maybe filename was overridden by setproctitle() and
1663 * it match non-elf file.
1664 */
1665 goto fail;
1666 }
1667 obj->mapped = file;
1668 obj->mapped_size = (size_t)filesize;
1669
1670 shdr = (ElfW(Shdr) *)(file + ehdr->e_shoff);
1671
1672 shstr_shdr = shdr + ehdr->e_shstrndx;
1673 shstr = file + shstr_shdr->sh_offset;
1674
1675 for (i = 0; i < ehdr->e_shnum; i++) {
1676 char *section_name = shstr + shdr[i].sh_name;
1677 switch (shdr[i].sh_type) {
1678 case SHT_STRTAB:
1679 if (!strcmp(section_name, ".strtab")) {
1680 strtab_shdr = shdr + i;
1681 }
1682 else if (!strcmp(section_name, ".dynstr")) {
1683 dynstr_shdr = shdr + i;
1684 }
1685 break;
1686 case SHT_SYMTAB:
1687 /* if (!strcmp(section_name, ".symtab")) */
1688 symtab_shdr = shdr + i;
1689 break;
1690 case SHT_DYNSYM:
1691 /* if (!strcmp(section_name, ".dynsym")) */
1692 dynsym_shdr = shdr + i;
1693 break;
1694 case SHT_PROGBITS:
1695 if (!strcmp(section_name, ".gnu_debuglink")) {
1696 gnu_debuglink_shdr = shdr + i;
1697 }
1698 else {
1699 const char *debug_section_names[] = {
1700 ".debug_abbrev",
1701 ".debug_info",
1702 ".debug_line",
1703 ".debug_ranges",
1704 ".debug_str"
1705 };
1706
1707 for (j=0; j < DWARF_SECTION_COUNT; j++) {
1708 struct dwarf_section *s = obj_dwarf_section_at(obj, j);
1709
1710 if (strcmp(section_name, debug_section_names[j]) != 0)
1711 continue;
1712
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;
1719 }
1720 break;
1721 }
1722 }
1723 break;
1724 }
1725 }
1726
1727 if (offset == -1) {
1728 /* main executable */
1729 offset = 0;
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);
1735 if (handle) {
1736 for (j = 0; j < symtab_count; j++) {
1737 ElfW(Sym) *sym = &symtab[j];
1738 Dl_info info;
1739 void *s;
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;
1745 break;
1746 }
1747 }
1748 dlclose(handle);
1749 }
1750 if (ehdr->e_type == ET_EXEC) {
1751 obj->base_addr = 0;
1752 }
1753 else {
1754 /* PIE (position-independent executable) */
1755 obj->base_addr = dladdr_fbase;
1756 }
1757 }
1758 }
1759
1760 if (obj->debug_info.ptr && obj->debug_abbrev.ptr) {
1761 DebugInfoReader reader;
1762 debug_info_reader_init(&reader, obj);
1763 i = 0;
1764 while (reader.p < reader.pend) {
1765 /* fprintf(stderr, "%d:%tx: CU[%d]\n", __LINE__, reader.p - reader.obj->debug_info.ptr, i++); */
1766 if (di_read_cu(&reader)) goto use_symtab;
1767 debug_info_read(&reader, num_traces, traces, lines, offset);
1768 }
1769 }
1770 else {
1771 /* This file doesn't have dwarf, use symtab or dynsym */
1772 use_symtab:
1773 if (!symtab_shdr) {
1774 /* This file doesn't have symtab, use dynsym instead */
1775 symtab_shdr = dynsym_shdr;
1776 strtab_shdr = dynstr_shdr;
1777 }
1778
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];
1785 uintptr_t saddr = (uintptr_t)sym->st_value + obj->base_addr;
1786 if (ELF_ST_TYPE(sym->st_info) != STT_FUNC) continue;
1787 for (i = offset; i < num_traces; i++) {
1788 uintptr_t d = (uintptr_t)traces[i] - saddr;
1789 if (lines[i].line > 0 || d > (uintptr_t)sym->st_size)
1790 continue;
1791 /* fill symbol name and addr from .symtab */
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;
1796 }
1797 }
1798 }
1799 }
1800
1801 if (!obj->debug_line.ptr) {
1802 /* This file doesn't have .debug_line section,
1803 let's check .gnu_debuglink section instead. */
1804 if (gnu_debuglink_shdr && check_debuglink) {
1805 follow_debuglink(file + gnu_debuglink_shdr->sh_offset,
1806 num_traces, traces,
1807 objp, lines, offset);
1808 }
1809 goto finish;
1810 }
1811
1812 if (parse_debug_line(num_traces, traces,
1813 obj->debug_line.ptr,
1814 obj->debug_line.size,
1815 obj, lines, offset) == -1)
1816 goto fail;
1817
1818 finish:
1819 return dladdr_fbase;
1820 fail:
1821 return (uintptr_t)-1;
1822 }
1823 #else /* Mach-O */
1824 /* read file and fill lines */
1825 static uintptr_t
1826 fill_lines(int num_traces, void **traces, int check_debuglink,
1827 obj_info_t **objp, line_info_t *lines, int offset)
1828 {
1829 # ifdef __LP64__
1830 # define LP(x) x##_64
1831 # else
1832 # define LP(x) x
1833 # endif
1834 int fd;
1835 off_t filesize;
1836 char *file, *p = NULL;
1837 obj_info_t *obj = *objp;
1838 struct LP(mach_header) *header;
1839 uintptr_t dladdr_fbase = 0;
1840
1841 {
1842 char *s = binary_filename;
1843 char *base = strrchr(binary_filename, '/')+1;
1844 size_t max = PATH_MAX;
1845 size_t size = strlen(binary_filename);
1846 size_t basesize = size - (base - binary_filename);
1847 s += size;
1848 max -= size;
1849 p = s;
1850 size = strlcpy(s, ".dSYM/Contents/Resources/DWARF/", max);
1851 if (size == 0) goto fail;
1852 s += size;
1853 max -= size;
1854 if (max <= basesize) goto fail;
1855 memcpy(s, base, basesize);
1856 s[basesize] = 0;
1857
1858 fd = open(binary_filename, O_RDONLY);
1859 if (fd < 0) {
1860 *p = 0; /* binary_filename becomes original file name */
1861 fd = open(binary_filename, O_RDONLY);
1862 if (fd < 0) {
1863 goto fail;
1864 }
1865 }
1866 }
1867
1868 filesize = lseek(fd, 0, SEEK_END);
1869 if (filesize < 0) {
1870 int e = errno;
1871 close(fd);
1872 kprintf("lseek: %s\n", strerror(e));
1873 goto fail;
1874 }
1875 #if SIZEOF_OFF_T > SIZEOF_SIZE_T
1876 if (filesize > (off_t)SIZE_MAX) {
1877 close(fd);
1878 kprintf("Too large file %s\n", binary_filename);
1879 goto fail;
1880 }
1881 #endif
1882 lseek(fd, 0, SEEK_SET);
1883 /* async-signal unsafe */
1884 file = (char *)mmap(NULL, (size_t)filesize, PROT_READ, MAP_SHARED, fd, 0);
1885 if (file == MAP_FAILED) {
1886 int e = errno;
1887 close(fd);
1888 kprintf("mmap: %s\n", strerror(e));
1889 goto fail;
1890 }
1891 close(fd);
1892
1893 obj->mapped = file;
1894 obj->mapped_size = (size_t)filesize;
1895
1896 header = (struct LP(mach_header) *)file;
1897 if (header->magic == LP(MH_MAGIC)) {
1898 /* non universal binary */
1899 p = file;
1900 }
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);
1906 /* fprintf(stderr,"%d: fat:%s %d\n",__LINE__, binary_filename,nfat_arch); */
1907 for (uint32_t i = 0; i < nfat_arch; i++) {
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);
1912 /* fprintf(stderr,"%d: fat %d %x/%x %x/%x\n",__LINE__, i, mhp->cputype,mhp->cpusubtype, cputype,cpusubtype); */
1913 if (mhp->cputype == cputype &&
1914 (cpu_subtype_t)(mhp->cpusubtype & ~CPU_SUBTYPE_MASK) == cpusubtype) {
1915 p = file + offset;
1916 file = p;
1917 header = (struct LP(mach_header) *)p;
1918 if (header->magic == LP(MH_MAGIC)) {
1919 goto found_mach_header;
1920 }
1921 break;
1922 }
1923 q += sizeof(*arch);
1924 }
1925 kprintf("'%s' is not a Mach-O universal binary file!\n",binary_filename);
1926 close(fd);
1927 goto fail;
1928 }
1929 else {
1930 kprintf("'%s' is not a "
1931 # ifdef __LP64__
1932 "64"
1933 # else
1934 "32"
1935 # endif
1936 "-bit Mach-O file!\n",binary_filename);
1937 close(fd);
1938 goto fail;
1939 }
1940 found_mach_header:
1941 p += sizeof(*header);
1942
1943 for (uint32_t i = 0; i < (uint32_t)header->ncmds; i++) {
1944 struct load_command *lcmd = (struct load_command *)p;
1945 switch (lcmd->cmd) {
1946 case LP(LC_SEGMENT):
1947 {
1948 static const char *debug_section_names[] = {
1949 "__debug_abbrev",
1950 "__debug_info",
1951 "__debug_line",
1952 "__debug_ranges",
1953 "__debug_str"
1954 };
1955 struct LP(segment_command) *scmd = (struct LP(segment_command) *)lcmd;
1956 if (strcmp(scmd->segname, "__TEXT") == 0) {
1957 obj->vmaddr = scmd->vmaddr;
1958 }
1959 else if (strcmp(scmd->segname, "__DWARF") == 0) {
1960 p += sizeof(struct LP(segment_command));
1961 for (uint64_t i = 0; i < scmd->nsects; i++) {
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);
1966
1967 if (strcmp(sect->sectname, debug_section_names[j]) != 0)
1968 continue;
1969
1970 s->ptr = file + sect->offset;
1971 s->size = sect->size;
1972 s->flags = sect->flags;
1973 if (s->flags & SHF_COMPRESSED) {
1974 goto fail;
1975 }
1976 break;
1977 }
1978 }
1979 }
1980 }
1981 break;
1982
1983 case LC_SYMTAB:
1984 {
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;
1988 uint32_t j;
1989 uintptr_t saddr = 0;
1990 /* kprintf("[%2d]: %x/symtab %p\n", i, cmd->cmd, p); */
1991 for (j = 0; j < cmd->nsyms; j++) {
1992 uintptr_t symsize, d;
1993 struct LP(nlist) *e = &nl[j];
1994 /* kprintf("[%2d][%4d]: %02x/%x/%x: %s %llx\n", i, j, e->n_type,e->n_sect,e->n_desc,strtab+e->n_un.n_strx,e->n_value); */
1995 if (e->n_type != N_FUN) continue;
1996 if (e->n_sect) {
1997 saddr = (uintptr_t)e->n_value + obj->base_addr - obj->vmaddr;
1998 sname = strtab + e->n_un.n_strx;
1999 /* kprintf("[%2d][%4d]: %02x/%x/%x: %s %llx\n", i, j, e->n_type,e->n_sect,e->n_desc,strtab+e->n_un.n_strx,e->n_value); */
2000 continue;
2001 }
2002 for (int k = offset; k < num_traces; k++) {
2003 d = (uintptr_t)traces[k] - saddr;
2004 symsize = e->n_value;
2005 /* kprintf("%lx %lx %lx\n",saddr,symsize,traces[k]); */
2006 if (lines[k].line > 0 || d > (uintptr_t)symsize)
2007 continue;
2008 /* fill symbol name and addr from .symtab */
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;
2013 }
2014 }
2015 }
2016 }
2017 p += lcmd->cmdsize;
2018 }
2019
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);
2026 }
2027 }
2028
2029 if (parse_debug_line(num_traces, traces,
2030 obj->debug_line.ptr,
2031 obj->debug_line.size,
2032 obj, lines, offset) == -1)
2033 goto fail;
2034
2035 return dladdr_fbase;
2036 fail:
2037 return (uintptr_t)-1;
2038 }
2039 #endif
2040
2041 #define HAVE_MAIN_EXE_PATH
2042 #if defined(__FreeBSD__)
2043 # include <sys/sysctl.h>
2044 #endif
2045 /* ssize_t main_exe_path(void)
2046 *
2047 * store the path of the main executable to `binary_filename`,
2048 * and returns strlen(binary_filename).
2049 * it is NUL terminated.
2050 */
2051 #if defined(__linux__)
2052 static ssize_t
2053 main_exe_path(void)
2054 {
2055 # define PROC_SELF_EXE "/proc/self/exe"
2056 ssize_t len = readlink(PROC_SELF_EXE, binary_filename, PATH_MAX);
2057 if (len < 0) return 0;
2058 binary_filename[len] = 0;
2059 return len;
2060 }
2061 #elif defined(__FreeBSD__)
2062 static ssize_t
2063 main_exe_path(void)
2064 {
2065 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
2066 size_t len = PATH_MAX;
2067 int err = sysctl(mib, 4, binary_filename, &len, NULL, 0);
2068 if (err) {
2069 kprintf("Can't get the path of ruby");
2070 return -1;
2071 }
2072 len--; /* sysctl sets strlen+1 */
2073 return len;
2074 }
2075 #elif defined(HAVE_LIBPROC_H)
2076 static ssize_t
2077 main_exe_path(void)
2078 {
2079 int len = proc_pidpath(getpid(), binary_filename, PATH_MAX);
2080 if (len == 0) return 0;
2081 binary_filename[len] = 0;
2082 return len;
2083 }
2084 #else
2085 #undef HAVE_MAIN_EXE_PATH
2086 #endif
2087
2088 static void
2089 print_line0(line_info_t *line, void *address)
2090 {
2091 uintptr_t addr = (uintptr_t)address;
2092 uintptr_t d = addr - line->saddr;
2093 if (!address) {
2094 /* inlined */
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);
2097 }
2098 else {
2099 kprintf("%s(%s) %s:%d\n", line->path, line->sname, line->filename, line->line);
2100 }
2101 }
2102 else if (!line->path) {
2103 kprintf("[0x%"PRIxPTR"]\n", addr);
2104 }
2105 else if (!line->saddr || !line->sname) {
2106 kprintf("%s(0x%"PRIxPTR") [0x%"PRIxPTR"]\n", line->path, addr-line->base_addr, addr);
2107 }
2108 else if (line->line <= 0) {
2109 kprintf("%s(%s+0x%"PRIxPTR") [0x%"PRIxPTR"]\n", line->path, line->sname,
2110 d, addr);
2111 }
2112 else if (!line->filename) {
2113 kprintf("%s(%s+0x%"PRIxPTR") [0x%"PRIxPTR"] ???:%d\n", line->path, line->sname,
2114 d, addr, line->line);
2115 }
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);
2119 }
2120 else {
2121 kprintf("%s(%s+0x%"PRIxPTR") [0x%"PRIxPTR"] %s:%d\n", line->path, line->sname,
2122 d, addr, line->filename, line->line);
2123 }
2124 }
2125
2126 static void
2127 print_line(line_info_t *line, void *address)
2128 {
2129 print_line0(line, address);
2130 if (line->next) {
2131 print_line(line->next, NULL);
2132 }
2133 }
2134
2135 void
2136 rb_dump_backtrace_with_lines(int num_traces, void **traces)
2137 {
2138 int i;
2139 /* async-signal unsafe */
2140 line_info_t *lines = (line_info_t *)calloc(num_traces, sizeof(line_info_t));
2141 obj_info_t *obj = NULL;
2142 /* 2 is NULL + main executable */
2143 void **dladdr_fbases = (void **)calloc(num_traces+2, sizeof(void *));
2144 #ifdef HAVE_MAIN_EXE_PATH
2145 char *main_path = NULL; /* used on printing backtrace */
2146 ssize_t len;
2147 if ((len = main_exe_path()) > 0) {
2148 main_path = (char *)alloca(len + 1);
2149 if (main_path) {
2150 uintptr_t addr;
2151 memcpy(main_path, binary_filename, len+1);
2152 append_obj(&obj);
2153 obj->path = main_path;
2154 addr = fill_lines(num_traces, traces, 1, &obj, lines, -1);
2155 if (addr != (uintptr_t)-1) {
2156 dladdr_fbases[0] = (void *)addr;
2157 }
2158 }
2159 }
2160 #endif
2161
2162 /* fill source lines by reading dwarf */
2163 for (i = 0; i < num_traces; i++) {
2164 Dl_info info;
2165 if (lines[i].line) continue;
2166 if (dladdr(traces[i], &info)) {
2167 const char *path;
2168 void **p;
2169
2170 /* skip symbols which is in already checked objects */
2171 /* if the binary is strip-ed, this may effect */
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;
2176 goto next_line;
2177 }
2178 }
2179 *p = info.dli_fbase;
2180
2181 append_obj(&obj);
2182 obj->base_addr = (uintptr_t)info.dli_fbase;
2183 path = info.dli_fname;
2184 obj->path = path;
2185 lines[i].path = path;
2186 lines[i].sname = info.dli_sname;
2187 lines[i].saddr = (uintptr_t)info.dli_saddr;
2188 strlcpy(binary_filename, path, PATH_MAX);
2189 if (fill_lines(num_traces, traces, 1, &obj, lines, i) == (uintptr_t)-1)
2190 break;
2191 }
2192 next_line:
2193 continue;
2194 }
2195
2196 /* output */
2197 for (i = 0; i < num_traces; i++) {
2198 print_line(&lines[i], traces[i]);
2199
2200 /* FreeBSD's backtrace may show _start and so on */
2201 if (lines[i].sname && strcmp("main", lines[i].sname) == 0)
2202 break;
2203 }
2204
2205 /* free */
2206 while (obj) {
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) {
2211 free(s->ptr);
2212 }
2213 }
2214 if (obj->mapped_size) {
2215 munmap(obj->mapped, obj->mapped_size);
2216 }
2217 obj = o->next;
2218 free(o);
2219 }
2220 for (i = 0; i < num_traces; i++) {
2221 line_info_t *line = lines[i].next;
2222 while (line) {
2223 line_info_t *l = line;
2224 line = line->next;
2225 free(l);
2226 }
2227 }
2228 free(lines);
2229 free(dladdr_fbases);
2230 }
2231
2232 /* From FreeBSD's lib/libstand/printf.c */
2233 /*-
2234 * Copyright (c) 1986, 1988, 1991, 1993
2235 * The Regents of the University of California. All rights reserved.
2236 * (c) UNIX System Laboratories, Inc.
2237 * All or some portions of this file are derived from material licensed
2238 * to the University of California by American Telephone and Telegraph
2239 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
2240 * the permission of UNIX System Laboratories, Inc.
2241 *
2242 * Redistribution and use in source and binary forms, with or without
2243 * modification, are permitted provided that the following conditions
2244 * are met:
2245 * 1. Redistributions of source code must retain the above copyright
2246 * notice, this list of conditions and the following disclaimer.
2247 * 2. Redistributions in binary form must reproduce the above copyright
2248 * notice, this list of conditions and the following disclaimer in the
2249 * documentation and/or other materials provided with the distribution.
2250 * 4. Neither the name of the University nor the names of its contributors
2251 * may be used to endorse or promote products derived from this software
2252 * without specific prior written permission.
2253 *
2254 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2255 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2256 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2257 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2258 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2259 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2260 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2261 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2262 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2263 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2264 * SUCH DAMAGE.
2265 *
2266 * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94
2267 */
2268
2269 #include <stdarg.h>
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);
2276
2277 static void putce(int c)
2278 {
2279 char s[1];
2280 ssize_t ret;
2281
2282 s[0] = (char)c;
2283 ret = write(2, s, 1);
2284 (void)ret;
2285 }
2286
2287 static int
2288 kprintf(const char *fmt, ...)
2289 {
2290 va_list ap;
2291 int retval;
2292
2293 va_start(ap, fmt);
2294 retval = kvprintf(fmt, putce, NULL, 10, ap);
2295 va_end(ap);
2296 return retval;
2297 }
2298
2299 /*
2300 * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
2301 * order; return an optional length and a pointer to the last character
2302 * written in the buffer (i.e., the first character of the string).
2303 * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
2304 */
2305 static char *
2306 ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
2307 {
2308 char *p, c;
2309
2310 p = nbuf;
2311 *p = '\0';
2312 do {
2313 c = hex2ascii(num % base);
2314 *++p = upper ? toupper(c) : c;
2315 } while (num /= base);
2316 if (lenp)
2317 *lenp = (int)(p - nbuf);
2318 return (p);
2319 }
2320
2321 /*
2322 * Scaled down version of printf(3).
2323 *
2324 * Two additional formats:
2325 *
2326 * The format %b is supported to decode error registers.
2327 * Its usage is:
2328 *
2329 * printf("reg=%b\n", regval, "<base><arg>*");
2330 *
2331 * where <base> is the output base expressed as a control character, e.g.
2332 * \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
2333 * the first of which gives the bit number to be inspected (origin 1), and
2334 * the next characters (up to a control character, i.e. a character <= 32),
2335 * give the name of the register. Thus:
2336 *
2337 * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
2338 *
2339 * would produce output:
2340 *
2341 * reg=3<BITTWO,BITONE>
2342 *
2343 * XXX: %D -- Hexdump, takes pointer and separator string:
2344 * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX
2345 * ("%*D", len, ptr, " " -> XX XX XX XX ...
2346 */
2347 static int
2348 kvprintf(char const *fmt, void (*func)(int), void *arg, int radix, va_list ap)
2349 {
2350 #define PCHAR(c) {int cc=(c); if (func) (*func)(cc); else *d++ = cc; retval++; }
2351 char nbuf[MAXNBUF];
2352 char *d;
2353 const char *p, *percent, *q;
2354 unsigned char *up;
2355 int ch, n;
2356 uintmax_t num;
2357 int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
2358 int cflag, hflag, jflag, tflag, zflag;
2359 int dwidth, upper;
2360 char padc;
2361 int stop = 0, retval = 0;
2362
2363 num = 0;
2364 if (!func)
2365 d = (char *) arg;
2366 else
2367 d = NULL;
2368
2369 if (fmt == NULL)
2370 fmt = "(fmt null)\n";
2371
2372 if (radix < 2 || radix > 36)
2373 radix = 10;
2374
2375 for (;;) {
2376 padc = ' ';
2377 width = 0;
2378 while ((ch = (unsigned char)*fmt++) != '%' || stop) {
2379 if (ch == '\0')
2380 return (retval);
2381 PCHAR(ch);
2382 }
2383 percent = fmt - 1;
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++) {
2388 case '.':
2389 dot = 1;
2390 goto reswitch;
2391 case '#':
2392 sharpflag = 1;
2393 goto reswitch;
2394 case '+':
2395 sign = 1;
2396 goto reswitch;
2397 case '-':
2398 ladjust = 1;
2399 goto reswitch;
2400 case '%':
2401 PCHAR(ch);
2402 break;
2403 case '*':
2404 if (!dot) {
2405 width = va_arg(ap, int);
2406 if (width < 0) {
2407 ladjust = !ladjust;
2408 width = -width;
2409 }
2410 } else {
2411 dwidth = va_arg(ap, int);
2412 }
2413 goto reswitch;
2414 case '0':
2415 if (!dot) {
2416 padc = '0';
2417 goto reswitch;
2418 }
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';
2423 ch = *fmt;
2424 if (ch < '0' || ch > '9')
2425 break;
2426 }
2427 if (dot)
2428 dwidth = n;
2429 else
2430 width = n;
2431 goto reswitch;
2432 case 'b':
2433 num = (unsigned int)va_arg(ap, int);
2434 p = va_arg(ap, char *);
2435 for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
2436 PCHAR(*q--);
2437
2438 if (num == 0)
2439 break;
2440
2441 for (tmp = 0; *p;) {
2442 n = *p++;
2443 if (num & (1 << (n - 1))) {
2444 PCHAR(tmp ? ',' : '<');
2445 for (; (n = *p) > ' '; ++p)
2446 PCHAR(n);
2447 tmp = 1;
2448 } else
2449 for (; *p > ' '; ++p)
2450 continue;
2451 }
2452 if (tmp)
2453 PCHAR('>');
2454 break;
2455 case 'c':
2456 PCHAR(va_arg(ap, int));
2457 break;
2458 case 'D':
2459 up = va_arg(ap, unsigned char *);
2460 p = va_arg(ap, char *);
2461 if (!width)
2462 width = 16;
2463 while(width--) {
2464 PCHAR(hex2ascii(*up >> 4));
2465 PCHAR(hex2ascii(*up & 0x0f));
2466 up++;
2467 if (width)
2468 for (q=p;*q;q++)
2469 PCHAR(*q);
2470 }
2471 break;
2472 case 'd':
2473 case 'i':
2474 base = 10;
2475 sign = 1;
2476 goto handle_sign;
2477 case 'h':
2478 if (hflag) {
2479 hflag = 0;
2480 cflag = 1;
2481 } else
2482 hflag = 1;
2483 goto reswitch;
2484 case 'j':
2485 jflag = 1;
2486 goto reswitch;
2487 case 'l':
2488 if (lflag) {
2489 lflag = 0;
2490 qflag = 1;
2491 } else
2492 lflag = 1;
2493 goto reswitch;
2494 case 'n':
2495 if (jflag)
2496 *(va_arg(ap, intmax_t *)) = retval;
2497 else if (qflag)
2498 *(va_arg(ap, int64_t *)) = retval;
2499 else if (lflag)
2500 *(va_arg(ap, long *)) = retval;
2501 else if (zflag)
2502 *(va_arg(ap, size_t *)) = retval;
2503 else if (hflag)
2504 *(va_arg(ap, short *)) = retval;
2505 else if (cflag)
2506 *(va_arg(ap, char *)) = retval;
2507 else
2508 *(va_arg(ap, int *)) = retval;
2509 break;
2510 case 'o':
2511 base = 8;
2512 goto handle_nosign;
2513 case 'p':
2514 base = 16;
2515 sharpflag = (width == 0);
2516 sign = 0;
2517 num = (uintptr_t)va_arg(ap, void *);
2518 goto number;
2519 case 'q':
2520 qflag = 1;
2521 goto reswitch;
2522 case 'r':
2523 base = radix;
2524 if (sign)
2525 goto handle_sign;
2526 goto handle_nosign;
2527 case 's':
2528 p = va_arg(ap, char *);
2529 if (p == NULL)
2530 p = "(null)";
2531 if (!dot)
2532 n = (int)strlen (p);
2533 else
2534 for (n = 0; n < dwidth && p[n]; n++)
2535 continue;
2536
2537 width -= n;
2538
2539 if (!ladjust && width > 0)
2540 while (width--)
2541 PCHAR(padc);
2542 while (n--)
2543 PCHAR(*p++);
2544 if (ladjust && width > 0)
2545 while (width--)
2546 PCHAR(padc);
2547 break;
2548 case 't':
2549 tflag = 1;
2550 goto reswitch;
2551 case 'u':
2552 base = 10;
2553 goto handle_nosign;
2554 case 'X':
2555 upper = 1;
2556 case 'x':
2557 base = 16;
2558 goto handle_nosign;
2559 case 'y':
2560 base = 16;
2561 sign = 1;
2562 goto handle_sign;
2563 case 'z':
2564 zflag = 1;
2565 goto reswitch;
2566 handle_nosign:
2567 sign = 0;
2568 if (jflag)
2569 num = va_arg(ap, uintmax_t);
2570 else if (qflag)
2571 num = va_arg(ap, uint64_t);
2572 else if (tflag)
2573 num = va_arg(ap, ptrdiff_t);
2574 else if (lflag)
2575 num = va_arg(ap, unsigned long);
2576 else if (zflag)
2577 num = va_arg(ap, size_t);
2578 else if (hflag)
2579 num = (unsigned short)va_arg(ap, int);
2580 else if (cflag)
2581 num = (unsigned char)va_arg(ap, int);
2582 else
2583 num = va_arg(ap, unsigned int);
2584 goto number;
2585 handle_sign:
2586 if (jflag)
2587 num = va_arg(ap, intmax_t);
2588 else if (qflag)
2589 num = va_arg(ap, int64_t);
2590 else if (tflag)
2591 num = va_arg(ap, ptrdiff_t);
2592 else if (lflag)
2593 num = va_arg(ap, long);
2594 else if (zflag)
2595 num = va_arg(ap, ssize_t);
2596 else if (hflag)
2597 num = (short)va_arg(ap, int);
2598 else if (cflag)
2599 num = (char)va_arg(ap, int);
2600 else
2601 num = va_arg(ap, int);
2602 number:
2603 if (sign && (intmax_t)num < 0) {
2604 neg = 1;
2605 num = -(intmax_t)num;
2606 }
2607 p = ksprintn(nbuf, num, base, &n, upper);
2608 tmp = 0;
2609 if (sharpflag && num != 0) {
2610 if (base == 8)
2611 tmp++;
2612 else if (base == 16)
2613 tmp += 2;
2614 }
2615 if (neg)
2616 tmp++;
2617
2618 if (!ladjust && padc == '0')
2619 dwidth = width - tmp;
2620 width -= tmp + imax(dwidth, n);
2621 dwidth -= n;
2622 if (!ladjust)
2623 while (width-- > 0)
2624 PCHAR(' ');
2625 if (neg)
2626 PCHAR('-');
2627 if (sharpflag && num != 0) {
2628 if (base == 8) {
2629 PCHAR('0');
2630 } else if (base == 16) {
2631 PCHAR('0');
2632 PCHAR('x');
2633 }
2634 }
2635 while (dwidth-- > 0)
2636 PCHAR('0');
2637
2638 while (*p)
2639 PCHAR(*p--);
2640
2641 if (ladjust)
2642 while (width-- > 0)
2643 PCHAR(' ');
2644
2645 break;
2646 default:
2647 while (percent < fmt)
2648 PCHAR(*percent++);
2649 /*
2650 * Since we ignore an formatting argument it is no
2651 * longer safe to obey the remaining formatting
2652 * arguments as the arguments will no longer match
2653 * the format specs.
2654 */
2655 stop = 1;
2656 break;
2657 }
2658 }
2659 #undef PCHAR
2660 }
2661 #else /* defined(USE_ELF) */
2662 #error not supported
2663 #endif
void
void
Definition: rb_mjit_min_header-2.7.0.h:13273
va_arg
#define va_arg(v, l)
Definition: rb_mjit_min_header-2.7.0.h:3980
close
int close(int __fildes)
path
VALUE path
Definition: rb_mjit_min_header-2.7.0.h:7351
uint64_t
#define uint64_t
Definition: siphash.h:15
size_t
long unsigned int size_t
Definition: rb_mjit_min_header-2.7.0.h:666
short
#define short
Definition: rb_mjit_min_header-2.7.0.h:2877
SIZE_MAX
#define SIZE_MAX
Definition: ruby.h:307
PRINTF_ARGS
#define PRINTF_ARGS(decl, string_index, first_to_check)
Definition: defines.h:114
malloc
void * malloc(size_t) __attribute__((__malloc__)) __attribute__((__warn_unused_result__)) __attribute__((__alloc_size__(1)))
PRIxPTR
#define PRIxPTR
Definition: ruby.h:148
int
__inline__ int
Definition: rb_mjit_min_header-2.7.0.h:2839
uint64_t
unsigned long long uint64_t
Definition: sha2.h:102
ptr
struct RIMemo * ptr
Definition: debug.c:74
intmax_t
__intmax_t intmax_t
Definition: rb_mjit_min_header-2.7.0.h:1185
stdbool.h
uintptr_t
unsigned int uintptr_t
Definition: win32.h:106
ssize_t
_ssize_t ssize_t
Definition: rb_mjit_min_header-2.7.0.h:1329
NULL
#define NULL
Definition: _sdbm.c:101
exit
void exit(int __status) __attribute__((__noreturn__))
uint32_t
unsigned int uint32_t
Definition: sha2.h:101
int64_t
__int64_t int64_t
Definition: rb_mjit_min_header-2.7.0.h:1180
strlen
size_t strlen(const char *)
v
int VALUE v
Definition: rb_mjit_min_header-2.7.0.h:12332
o1
#define o1(b1)
Definition: transcode_data.h:48
UINTPTR_MAX
#define UINTPTR_MAX
Definition: win32.h:114
defines.h
if
if((ID)(DISPID) nameid !=nameid)
Definition: win32ole.c:357
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.0.h:5742
lseek
off_t lseek(int __fildes, off_t __offset, int __whence)
memcpy
void * memcpy(void *__restrict, const void *__restrict, size_t)
uint16_t
__uint16_t uint16_t
Definition: rb_mjit_min_header-2.7.0.h:1172
calloc
void * calloc(size_t, size_t) __attribute__((__malloc__)) __attribute__((__warn_unused_result__)) __attribute__((__alloc_size__(1
strerror
RUBY_EXTERN char * strerror(int)
Definition: strerror.c:11
fprintf
int fprintf(FILE *__restrict, const char *__restrict,...) __attribute__((__format__(__printf__
memmove
#define memmove(dst, src, len)
Definition: rb_mjit_min_header-2.7.0.h:2848
i
uint32_t i
Definition: rb_mjit_min_header-2.7.0.h:5464
sym
#define sym(x)
Definition: date_core.c:3716
long
#define long
Definition: rb_mjit_min_header-2.7.0.h:2880
uintmax_t
__uintmax_t uintmax_t
Definition: rb_mjit_min_header-2.7.0.h:1187
alloca
#define alloca(size)
Definition: rb_mjit_min_header-2.7.0.h:2487
va_end
#define va_end(v)
Definition: rb_mjit_min_header-2.7.0.h:3979
stderr
#define stderr
Definition: rb_mjit_min_header-2.7.0.h:1485
size
int size
Definition: encoding.c:58
strlcpy
RUBY_EXTERN size_t strlcpy(char *, const char *, size_t)
Definition: strlcpy.c:29
uint8_t
unsigned char uint8_t
Definition: sha2.h:100
SEEK_END
#define SEEK_END
Definition: io.c:867
memcmp
int memcmp(const void *s1, const void *s2, size_t len)
Definition: memcmp.c:7
o2
#define o2(b1, b2)
Definition: transcode_data.h:49
getpid
pid_t getpid(void)
fmt
const VALUE int int int int int int VALUE char * fmt
Definition: rb_mjit_min_header-2.7.0.h:6462
strcmp
int strcmp(const char *, const char *)
crt_externs.h
neg
#define neg(x)
Definition: time.c:141
char
#define char
Definition: rb_mjit_min_header-2.7.0.h:2876
n
const char size_t n
Definition: rb_mjit_min_header-2.7.0.h:5456
missing.h
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.0.h:5601
abort
void abort(void) __attribute__((__noreturn__))
strrchr
char * strrchr(const char *, const char)
SIZEOF_VOIDP
#define SIZEOF_VOIDP
Definition: rb_mjit_min_header-2.7.0.h:90
PRIx64
#define PRIx64
Definition: rb_mjit_min_header-2.7.0.h:3131
fail
#define fail()
Definition: date_strptime.c:123
readlink
ssize_t readlink(const char *, char *, size_t)
Definition: win32.c:5099
free
#define free(x)
Definition: dln.c:52
err
int err
Definition: win32.c:135
SEEK_SET
#define SEEK_SET
Definition: io.c:865
int8_t
__int8_t int8_t
Definition: rb_mjit_min_header-2.7.0.h:1165
errno
int errno
len
uint8_t len
Definition: escape.c:17
addr2line.h
PATH_MAX
#define PATH_MAX
va_start
#define va_start(v, l)
Definition: rb_mjit_min_header-2.7.0.h:3978
va_list
__gnuc_va_list va_list
Definition: rb_mjit_min_header-2.7.0.h:836
PRId64
#define PRId64
Definition: rb_mjit_min_header-2.7.0.h:3127
write
_ssize_t write(int __fd, const void *__buf, size_t __nbyte)
ptrdiff_t
long int ptrdiff_t
Definition: rb_mjit_min_header-2.7.0.h:802
ruby::backward::cxxanyargs::type
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:39
off_t
__off_t off_t
Definition: rb_mjit_min_header-2.7.0.h:1317
memchr
void * memchr(const void *, int, size_t)
name
const char * name
Definition: nkf.c:208