Ruby  2.7.1p83(2020-03-31revisiona0c7c23c9cec0d0ffcba012279cd652d28ad5bf3)
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
strcmp
int strcmp(const char *, const char *)
i
uint32_t i
Definition: rb_mjit_min_header-2.7.1.h:5425
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.1.h:5703
abort
void abort(void) __attribute__((__noreturn__))
long
#define long
Definition: rb_mjit_min_header-2.7.1.h:2848
uintmax_t
__uintmax_t uintmax_t
Definition: rb_mjit_min_header-2.7.1.h:1182
uint64_t
#define uint64_t
Definition: siphash.h:15
n
const char size_t n
Definition: rb_mjit_min_header-2.7.1.h:5417
SIZE_MAX
#define SIZE_MAX
Definition: ruby.h:307
PRINTF_ARGS
#define PRINTF_ARGS(decl, string_index, first_to_check)
Definition: defines.h:114
PRIxPTR
#define PRIxPTR
Definition: ruby.h:148
fmt
const VALUE int int int int int int VALUE char * fmt
Definition: rb_mjit_min_header-2.7.1.h:6423
PRIx64
#define PRIx64
Definition: rb_mjit_min_header-2.7.1.h:3099
uint64_t
unsigned long long uint64_t
Definition: sha2.h:102
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.1.h:5562
getpid
pid_t getpid(void)
ptr
struct RIMemo * ptr
Definition: debug.c:74
int8_t
__int8_t int8_t
Definition: rb_mjit_min_header-2.7.1.h:1160
stdbool.h
uintptr_t
unsigned int uintptr_t
Definition: win32.h:106
NULL
#define NULL
Definition: _sdbm.c:101
char
#define char
Definition: rb_mjit_min_header-2.7.1.h:2844
uint32_t
unsigned int uint32_t
Definition: sha2.h:101
SIZEOF_VOIDP
#define SIZEOF_VOIDP
Definition: rb_mjit_min_header-2.7.1.h:90
strlen
size_t strlen(const char *)
off_t
__off_t off_t
Definition: rb_mjit_min_header-2.7.1.h:1312
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
void
void
Definition: rb_mjit_min_header-2.7.1.h:13198
va_start
#define va_start(v, l)
Definition: rb_mjit_min_header-2.7.1.h:3946
strerror
RUBY_EXTERN char * strerror(int)
Definition: strerror.c:11
sym
#define sym(x)
Definition: date_core.c:3716
va_list
__gnuc_va_list va_list
Definition: rb_mjit_min_header-2.7.1.h:831
va_arg
#define va_arg(v, l)
Definition: rb_mjit_min_header-2.7.1.h:3948
malloc
void * malloc(size_t) __attribute__((__malloc__)) __attribute__((__warn_unused_result__)) __attribute__((__alloc_size__(1)))
short
#define short
Definition: rb_mjit_min_header-2.7.1.h:2845
size_t
unsigned int size_t
Definition: rb_mjit_min_header-2.7.1.h:660
PRId64
#define PRId64
Definition: rb_mjit_min_header-2.7.1.h:3095
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
write
_ssize_t write(int __fd, const void *__buf, size_t __nbyte)
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
path
VALUE path
Definition: rb_mjit_min_header-2.7.1.h:7300
memchr
void * memchr(const void *, int, size_t)
crt_externs.h
neg
#define neg(x)
Definition: time.c:141
missing.h
strrchr
char * strrchr(const char *, const char)
ssize_t
_ssize_t ssize_t
Definition: rb_mjit_min_header-2.7.1.h:1324
close
int close(int __fildes)
int
__inline__ int
Definition: rb_mjit_min_header-2.7.1.h:2807
ptrdiff_t
int ptrdiff_t
Definition: rb_mjit_min_header-2.7.1.h:796
lseek
off_t lseek(int __fildes, off_t __offset, int __whence)
memcpy
void * memcpy(void *__restrict, const void *__restrict, size_t)
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
memmove
#define memmove(dst, src, len)
Definition: rb_mjit_min_header-2.7.1.h:2816
SEEK_SET
#define SEEK_SET
Definition: io.c:865
v
int VALUE v
Definition: rb_mjit_min_header-2.7.1.h:12257
errno
int errno
exit
void exit(int __status) __attribute__((__noreturn__))
len
uint8_t len
Definition: escape.c:17
addr2line.h
PATH_MAX
#define PATH_MAX
alloca
#define alloca(size)
Definition: rb_mjit_min_header-2.7.1.h:2455
uint16_t
__uint16_t uint16_t
Definition: rb_mjit_min_header-2.7.1.h:1167
int64_t
__int64_t int64_t
Definition: rb_mjit_min_header-2.7.1.h:1175
stderr
#define stderr
Definition: rb_mjit_min_header-2.7.1.h:1479
intmax_t
__intmax_t intmax_t
Definition: rb_mjit_min_header-2.7.1.h:1180
calloc
void * calloc(size_t, size_t) __attribute__((__malloc__)) __attribute__((__warn_unused_result__)) __attribute__((__alloc_size__(1
fprintf
int fprintf(FILE *__restrict, const char *__restrict,...) __attribute__((__format__(__printf__
ruby::backward::cxxanyargs::type
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:39
va_end
#define va_end(v)
Definition: rb_mjit_min_header-2.7.1.h:3947
name
const char * name
Definition: nkf.c:208