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