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