1 /* elf.c -- Get debug data from a Mach-O file for backtraces.
2    Copyright (C) 2020 Free Software Foundation, Inc.
3    Written by Ian Lance Taylor, Google.
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8 
9     (1) Redistributions of source code must retain the above copyright
10     notice, this list of conditions and the following disclaimer.
11 
12     (2) Redistributions in binary form must reproduce the above copyright
13     notice, this list of conditions and the following disclaimer in
14     the documentation and/or other materials provided with the
15     distribution.
16 
17     (3) The name of the author may not be used to
18     endorse or promote products derived from this software without
19     specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30 IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 POSSIBILITY OF SUCH DAMAGE.  */
32 
33 #include "config.h"
34 
35 #include <sys/types.h>
36 #include <dirent.h>
37 #include <stdlib.h>
38 #include <string.h>
39 
40 #ifdef HAVE_MACH_O_DYLD_H
41 #include <mach-o/dyld.h>
42 #endif
43 
44 #include "backtrace.h"
45 #include "internal.h"
46 
47 /* Mach-O file header for a 32-bit executable.  */
48 
49 struct macho_header_32
50 {
51   uint32_t magic;	/* Magic number (MACH_O_MAGIC_32) */
52   uint32_t cputype;	/* CPU type */
53   uint32_t cpusubtype;	/* CPU subtype */
54   uint32_t filetype;	/* Type of file (object, executable) */
55   uint32_t ncmds;	/* Number of load commands */
56   uint32_t sizeofcmds;	/* Total size of load commands */
57   uint32_t flags;	/* Flags for special features */
58 };
59 
60 /* Mach-O file header for a 64-bit executable.  */
61 
62 struct macho_header_64
63 {
64   uint32_t magic;	/* Magic number (MACH_O_MAGIC_64) */
65   uint32_t cputype;	/* CPU type */
66   uint32_t cpusubtype;	/* CPU subtype */
67   uint32_t filetype;	/* Type of file (object, executable) */
68   uint32_t ncmds;	/* Number of load commands */
69   uint32_t sizeofcmds;	/* Total size of load commands */
70   uint32_t flags;	/* Flags for special features */
71   uint32_t reserved;	/* Reserved */
72 };
73 
74 /* Mach-O file header for a fat executable.  */
75 
76 struct macho_header_fat
77 {
78   uint32_t magic;	/* Magic number (MACH_O_MH_MAGIC_FAT) */
79   uint32_t nfat_arch;   /* Number of components */
80 };
81 
82 /* Values for the header magic field.  */
83 
84 #define MACH_O_MH_MAGIC_32	0xfeedface
85 #define MACH_O_MH_MAGIC_64	0xfeedfacf
86 #define MACH_O_MH_MAGIC_FAT	0xcafebabe
87 #define MACH_O_MH_CIGAM_FAT	0xbebafeca
88 
89 /* Value for the header filetype field.  */
90 
91 #define MACH_O_MH_EXECUTE	0x02
92 #define MACH_O_MH_DYLIB		0x06
93 #define MACH_O_MH_DSYM		0x0a
94 
95 /* A component of a fat file.  A fat file starts with a
96    macho_header_fat followed by nfat_arch instances of this
97    struct.  */
98 
99 struct macho_fat_arch
100 {
101   uint32_t cputype;	/* CPU type */
102   uint32_t cpusubtype;	/* CPU subtype */
103   uint32_t offset;	/* File offset of this entry */
104   uint32_t size;	/* Size of this entry */
105   uint32_t align;	/* Alignment of this entry */
106 };
107 
108 /* Values for the fat_arch cputype field (and the header cputype
109    field).  */
110 
111 #define MACH_O_CPU_ARCH_ABI64 0x01000000
112 
113 #define MACH_O_CPU_TYPE_X86 7
114 #define MACH_O_CPU_TYPE_ARM 12
115 
116 #define MACH_O_CPU_TYPE_X86_64 (MACH_O_CPU_TYPE_X86 | MACH_O_CPU_ARCH_ABI64)
117 #define MACH_O_CPU_TYPE_ARM64  (MACH_O_CPU_TYPE_ARM | MACH_O_CPU_ARCH_ABI64)
118 
119 /* The header of a load command.  */
120 
121 struct macho_load_command
122 {
123   uint32_t cmd;		/* The type of load command */
124   uint32_t cmdsize;	/* Size in bytes of the entire command */
125 };
126 
127 /* Values for the load_command cmd field.  */
128 
129 #define MACH_O_LC_SEGMENT	0x01
130 #define MACH_O_LC_SYMTAB	0x02
131 #define MACH_O_LC_SEGMENT_64	0x19
132 #define MACH_O_LC_UUID		0x1b
133 
134 /* The length of a section of segment name.  */
135 
136 #define MACH_O_NAMELEN (16)
137 
138 /* LC_SEGMENT load command.  */
139 
140 struct macho_segment_command
141 {
142   uint32_t cmd;			/* The type of load command (LC_SEGMENT) */
143   uint32_t cmdsize;		/* Size in bytes of the entire command */
144   char segname[MACH_O_NAMELEN];	/* Segment name */
145   uint32_t vmaddr;		/* Virtual memory address */
146   uint32_t vmsize;		/* Virtual memory size */
147   uint32_t fileoff;		/* Offset of data to be mapped */
148   uint32_t filesize;		/* Size of data in file */
149   uint32_t maxprot;		/* Maximum permitted virtual protection */
150   uint32_t initprot;		/* Initial virtual memory protection */
151   uint32_t nsects;		/* Number of sections in this segment */
152   uint32_t flags;		/* Flags */
153 };
154 
155 /* LC_SEGMENT_64 load command.  */
156 
157 struct macho_segment_64_command
158 {
159   uint32_t cmd;			/* The type of load command (LC_SEGMENT) */
160   uint32_t cmdsize;		/* Size in bytes of the entire command */
161   char segname[MACH_O_NAMELEN];	/* Segment name */
162   uint64_t vmaddr;		/* Virtual memory address */
163   uint64_t vmsize;		/* Virtual memory size */
164   uint64_t fileoff;		/* Offset of data to be mapped */
165   uint64_t filesize;		/* Size of data in file */
166   uint32_t maxprot;		/* Maximum permitted virtual protection */
167   uint32_t initprot;		/* Initial virtual memory protection */
168   uint32_t nsects;		/* Number of sections in this segment */
169   uint32_t flags;		/* Flags */
170 };
171 
172 /* LC_SYMTAB load command.  */
173 
174 struct macho_symtab_command
175 {
176   uint32_t cmd;		/* The type of load command (LC_SEGMENT) */
177   uint32_t cmdsize;	/* Size in bytes of the entire command */
178   uint32_t symoff;	/* File offset of symbol table */
179   uint32_t nsyms;	/* Number of symbols */
180   uint32_t stroff;	/* File offset of string table */
181   uint32_t strsize;	/* String table size */
182 };
183 
184 /* The length of a Mach-O uuid.  */
185 
186 #define MACH_O_UUID_LEN (16)
187 
188 /* LC_UUID load command.  */
189 
190 struct macho_uuid_command
191 {
192   uint32_t cmd;				/* Type of load command (LC_UUID) */
193   uint32_t cmdsize;			/* Size in bytes of command */
194   unsigned char uuid[MACH_O_UUID_LEN];	/* UUID */
195 };
196 
197 /* 32-bit section header within a LC_SEGMENT segment.  */
198 
199 struct macho_section
200 {
201   char sectname[MACH_O_NAMELEN];	/* Section name */
202   char segment[MACH_O_NAMELEN];		/* Segment of this section */
203   uint32_t addr;			/* Address in memory */
204   uint32_t size;			/* Section size */
205   uint32_t offset;			/* File offset */
206   uint32_t align;			/* Log2 of section alignment */
207   uint32_t reloff;			/* File offset of relocations */
208   uint32_t nreloc;			/* Number of relocs for this section */
209   uint32_t flags;			/* Flags */
210   uint32_t reserved1;
211   uint32_t reserved2;
212 };
213 
214 /* 64-bit section header within a LC_SEGMENT_64 segment.   */
215 
216 struct macho_section_64
217 {
218   char sectname[MACH_O_NAMELEN];	/* Section name */
219   char segment[MACH_O_NAMELEN];		/* Segment of this section */
220   uint64_t addr;			/* Address in memory */
221   uint64_t size;			/* Section size */
222   uint32_t offset;			/* File offset */
223   uint32_t align;			/* Log2 of section alignment */
224   uint32_t reloff;			/* File offset of section relocations */
225   uint32_t nreloc;			/* Number of relocs for this section */
226   uint32_t flags;			/* Flags */
227   uint32_t reserved1;
228   uint32_t reserved2;
229   uint32_t reserved3;
230 };
231 
232 /* 32-bit symbol data.  */
233 
234 struct macho_nlist
235 {
236   uint32_t n_strx;	/* Index of name in string table */
237   uint8_t n_type;	/* Type flag */
238   uint8_t n_sect;	/* Section number */
239   uint16_t n_desc;	/* Stabs description field */
240   uint32_t n_value;	/* Value */
241 };
242 
243 /* 64-bit symbol data.  */
244 
245 struct macho_nlist_64
246 {
247   uint32_t n_strx;	/* Index of name in string table */
248   uint8_t n_type;	/* Type flag */
249   uint8_t n_sect;	/* Section number */
250   uint16_t n_desc;	/* Stabs description field */
251   uint64_t n_value;	/* Value */
252 };
253 
254 /* Value found in nlist n_type field.  */
255 
256 #define MACH_O_N_EXT	0x01	/* Extern symbol */
257 #define MACH_O_N_ABS	0x02	/* Absolute symbol */
258 #define MACH_O_N_SECT	0x0e	/* Defined in section */
259 
260 #define MACH_O_N_TYPE	0x0e	/* Mask for type bits */
261 #define MACH_O_N_STAB	0xe0	/* Stabs debugging symbol */
262 
263 /* Information we keep for a Mach-O symbol.  */
264 
265 struct macho_symbol
266 {
267   const char *name;	/* Symbol name */
268   uintptr_t address;	/* Symbol address */
269 };
270 
271 /* Information to pass to macho_syminfo.  */
272 
273 struct macho_syminfo_data
274 {
275   struct macho_syminfo_data *next;	/* Next module */
276   struct macho_symbol *symbols;		/* Symbols sorted by address */
277   size_t count;				/* Number of symbols */
278 };
279 
280 /* Names of sections, indexed by enum dwarf_section in internal.h.  */
281 
282 static const char * const dwarf_section_names[DEBUG_MAX] =
283 {
284   "__debug_info",
285   "__debug_line",
286   "__debug_abbrev",
287   "__debug_ranges",
288   "__debug_str",
289   "", /* DEBUG_ADDR */
290   "__debug_str_offs",
291   "", /* DEBUG_LINE_STR */
292   "__debug_rnglists"
293 };
294 
295 /* Forward declaration.  */
296 
297 static int macho_add (struct backtrace_state *, const char *, int, off_t,
298 		      const unsigned char *, uintptr_t, int,
299 		      backtrace_error_callback, void *, fileline *, int *);
300 
301 /* A dummy callback function used when we can't find any debug info.  */
302 
303 static int
304 macho_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
305 	       uintptr_t pc ATTRIBUTE_UNUSED,
306 	       backtrace_full_callback callback ATTRIBUTE_UNUSED,
307 	       backtrace_error_callback error_callback, void *data)
308 {
309   error_callback (data, "no debug info in Mach-O executable", -1);
310   return 0;
311 }
312 
313 /* A dummy callback function used when we can't find a symbol
314    table.  */
315 
316 static void
317 macho_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,
318 	      uintptr_t addr ATTRIBUTE_UNUSED,
319 	      backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,
320 	      backtrace_error_callback error_callback, void *data)
321 {
322   error_callback (data, "no symbol table in Mach-O executable", -1);
323 }
324 
325 /* Add a single DWARF section to DWARF_SECTIONS, if we need the
326    section.  Returns 1 on success, 0 on failure.  */
327 
328 static int
329 macho_add_dwarf_section (struct backtrace_state *state, int descriptor,
330 			 const char *sectname, uint32_t offset, uint64_t size,
331 			 backtrace_error_callback error_callback, void *data,
332 			 struct dwarf_sections *dwarf_sections)
333 {
334   int i;
335 
336   for (i = 0; i < (int) DEBUG_MAX; ++i)
337     {
338       if (dwarf_section_names[i][0] != '\0'
339 	  && strncmp (sectname, dwarf_section_names[i], MACH_O_NAMELEN) == 0)
340 	{
341 	  struct backtrace_view section_view;
342 
343 	  /* FIXME: Perhaps it would be better to try to use a single
344 	     view to read all the DWARF data, as we try to do for
345 	     ELF.  */
346 
347 	  if (!backtrace_get_view (state, descriptor, offset, size,
348 				   error_callback, data, &section_view))
349 	    return 0;
350 	  dwarf_sections->data[i] = (const unsigned char *) section_view.data;
351 	  dwarf_sections->size[i] = size;
352 	  break;
353 	}
354     }
355   return 1;
356 }
357 
358 /* Collect DWARF sections from a DWARF segment.  Returns 1 on success,
359    0 on failure.  */
360 
361 static int
362 macho_add_dwarf_segment (struct backtrace_state *state, int descriptor,
363 			 off_t offset, unsigned int cmd, const char *psecs,
364 			 size_t sizesecs, unsigned int nsects,
365 			 backtrace_error_callback error_callback, void *data,
366 			 struct dwarf_sections *dwarf_sections)
367 {
368   size_t sec_header_size;
369   size_t secoffset;
370   unsigned int i;
371 
372   switch (cmd)
373     {
374     case MACH_O_LC_SEGMENT:
375       sec_header_size = sizeof (struct macho_section);
376       break;
377     case MACH_O_LC_SEGMENT_64:
378       sec_header_size = sizeof (struct macho_section_64);
379       break;
380     default:
381       abort ();
382     }
383 
384   secoffset = 0;
385   for (i = 0; i < nsects; ++i)
386     {
387       if (secoffset + sec_header_size > sizesecs)
388 	{
389 	  error_callback (data, "section overflow withing segment", 0);
390 	  return 0;
391 	}
392 
393       switch (cmd)
394 	{
395 	case MACH_O_LC_SEGMENT:
396 	  {
397 	    struct macho_section section;
398 
399 	    memcpy (&section, psecs + secoffset, sizeof section);
400 	    macho_add_dwarf_section (state, descriptor, section.sectname,
401 				     offset + section.offset, section.size,
402 				     error_callback, data, dwarf_sections);
403 	  }
404 	  break;
405 
406 	case MACH_O_LC_SEGMENT_64:
407 	  {
408 	    struct macho_section_64 section;
409 
410 	    memcpy (&section, psecs + secoffset, sizeof section);
411 	    macho_add_dwarf_section (state, descriptor, section.sectname,
412 				     offset + section.offset, section.size,
413 				     error_callback, data, dwarf_sections);
414 	  }
415 	  break;
416 
417 	default:
418 	  abort ();
419 	}
420 
421       secoffset += sec_header_size;
422     }
423 
424   return 1;
425 }
426 
427 /* Compare struct macho_symbol for qsort.  */
428 
429 static int
430 macho_symbol_compare (const void *v1, const void *v2)
431 {
432   const struct macho_symbol *m1 = (const struct macho_symbol *) v1;
433   const struct macho_symbol *m2 = (const struct macho_symbol *) v2;
434 
435   if (m1->address < m2->address)
436     return -1;
437   else if (m1->address > m2->address)
438     return 1;
439   else
440     return 0;
441 }
442 
443 /* Compare an address against a macho_symbol for bsearch.  We allocate
444    one extra entry in the array so that this can safely look at the
445    next entry.  */
446 
447 static int
448 macho_symbol_search (const void *vkey, const void *ventry)
449 {
450   const uintptr_t *key = (const uintptr_t *) vkey;
451   const struct macho_symbol *entry = (const struct macho_symbol *) ventry;
452   uintptr_t addr;
453 
454   addr = *key;
455   if (addr < entry->address)
456     return -1;
457   else if (entry->name[0] == '\0'
458 	   && entry->address == ~(uintptr_t) 0)
459     return -1;
460   else if ((entry + 1)->name[0] == '\0'
461 	   && (entry + 1)->address == ~(uintptr_t) 0)
462     return -1;
463   else if (addr >= (entry + 1)->address)
464     return 1;
465   else
466     return 0;
467 }
468 
469 /* Return whether the symbol type field indicates a symbol table entry
470    that we care about: a function or data symbol.  */
471 
472 static int
473 macho_defined_symbol (uint8_t type)
474 {
475   if ((type & MACH_O_N_STAB) != 0)
476     return 0;
477   switch (type & MACH_O_N_TYPE)
478     {
479     case MACH_O_N_ABS:
480       return 1;
481     case MACH_O_N_SECT:
482       return 1;
483     default:
484       return 0;
485     }
486 }
487 
488 /* Add symbol table information for a Mach-O file.  */
489 
490 static int
491 macho_add_symtab (struct backtrace_state *state, int descriptor,
492 		  uintptr_t base_address, int is_64,
493 		  off_t symoff, unsigned int nsyms, off_t stroff,
494 		  unsigned int strsize,
495 		  backtrace_error_callback error_callback, void *data)
496 {
497   size_t symsize;
498   struct backtrace_view sym_view;
499   int sym_view_valid;
500   struct backtrace_view str_view;
501   int str_view_valid;
502   size_t ndefs;
503   size_t symtaboff;
504   unsigned int i;
505   size_t macho_symbol_size;
506   struct macho_symbol *macho_symbols;
507   unsigned int j;
508   struct macho_syminfo_data *sdata;
509 
510   sym_view_valid = 0;
511   str_view_valid = 0;
512   macho_symbol_size = 0;
513   macho_symbols = NULL;
514 
515   if (is_64)
516     symsize = sizeof (struct macho_nlist_64);
517   else
518     symsize = sizeof (struct macho_nlist);
519 
520   if (!backtrace_get_view (state, descriptor, symoff, nsyms * symsize,
521 			   error_callback, data, &sym_view))
522     goto fail;
523   sym_view_valid = 1;
524 
525   if (!backtrace_get_view (state, descriptor, stroff, strsize,
526 			   error_callback, data, &str_view))
527     return 0;
528   str_view_valid = 1;
529 
530   ndefs = 0;
531   symtaboff = 0;
532   for (i = 0; i < nsyms; ++i, symtaboff += symsize)
533     {
534       if (is_64)
535 	{
536 	  struct macho_nlist_64 nlist;
537 
538 	  memcpy (&nlist, (const char *) sym_view.data + symtaboff,
539 		  sizeof nlist);
540 	  if (macho_defined_symbol (nlist.n_type))
541 	    ++ndefs;
542 	}
s3backer_get_config(int argc,char ** argv)543       else
544 	{
545 	  struct macho_nlist nlist;
546 
547 	  memcpy (&nlist, (const char *) sym_view.data + symtaboff,
548 		  sizeof nlist);
549 	  if (macho_defined_symbol (nlist.n_type))
550 	    ++ndefs;
551 	}
552     }
553 
554   /* Add 1 to ndefs to make room for a sentinel.  */
555   macho_symbol_size = (ndefs + 1) * sizeof (struct macho_symbol);
556   macho_symbols = ((struct macho_symbol *)
557 		   backtrace_alloc (state, macho_symbol_size, error_callback,
558 				    data));
559   if (macho_symbols == NULL)
560     goto fail;
561 
562   j = 0;
563   symtaboff = 0;
564   for (i = 0; i < nsyms; ++i, symtaboff += symsize)
565     {
566       uint32_t strx;
567       uint64_t value;
568       const char *name;
569 
570       strx = 0;
571       value = 0;
572       if (is_64)
573 	{
574 	  struct macho_nlist_64 nlist;
575 
576 	  memcpy (&nlist, (const char *) sym_view.data + symtaboff,
577 		  sizeof nlist);
578 	  if (!macho_defined_symbol (nlist.n_type))
579 	    continue;
580 
581 	  strx = nlist.n_strx;
582 	  value = nlist.n_value;
583 	}
584       else
585 	{
586 	  struct macho_nlist nlist;
587 
588 	  memcpy (&nlist, (const char *) sym_view.data + symtaboff,
589 		  sizeof nlist);
590 	  if (!macho_defined_symbol (nlist.n_type))
591 	    continue;
592 
593 	  strx = nlist.n_strx;
594 	  value = nlist.n_value;
595 	}
596 
597       if (strx >= strsize)
598 	{
599 	  error_callback (data, "symbol string index out of range", 0);
600 	  goto fail;
601 	}
602 
603       name = (const char *) str_view.data + strx;
604       if (name[0] == '_')
605 	++name;
606       macho_symbols[j].name = name;
s3backer_create_store(struct s3b_config * conf)607       macho_symbols[j].address = value + base_address;
608       ++j;
609     }
610 
611   sdata = ((struct macho_syminfo_data *)
612 	   backtrace_alloc (state, sizeof *sdata, error_callback, data));
613   if (sdata == NULL)
614     goto fail;
615 
616   /* We need to keep the string table since it holds the names, but we
617      can release the symbol table.  */
618 
619   backtrace_release_view (state, &sym_view, error_callback, data);
620   sym_view_valid = 0;
621   str_view_valid = 0;
622 
623   /* Add a trailing sentinel symbol.  */
624   macho_symbols[j].name = "";
625   macho_symbols[j].address = ~(uintptr_t) 0;
626 
627   backtrace_qsort (macho_symbols, ndefs + 1, sizeof (struct macho_symbol),
628 		   macho_symbol_compare);
629 
630   sdata->next = NULL;
631   sdata->symbols = macho_symbols;
632   sdata->count = ndefs;
633 
634   if (!state->threaded)
635     {
636       struct macho_syminfo_data **pp;
637 
638       for (pp = (struct macho_syminfo_data **) (void *) &state->syminfo_data;
639 	   *pp != NULL;
640 	   pp = &(*pp)->next)
641 	;
642       *pp = sdata;
643     }
644   else
645     {
646       while (1)
647 	{
648 	  struct macho_syminfo_data **pp;
649 
650 	  pp = (struct macho_syminfo_data **) (void *) &state->syminfo_data;
651 
652 	  while (1)
653 	    {
654 	      struct macho_syminfo_data *p;
655 
656 	      p = backtrace_atomic_load_pointer (pp);
657 
658 	      if (p == NULL)
659 		break;
660 
661 	      pp = &p->next;
662 	    }
663 
664 	  if (__sync_bool_compare_and_swap (pp, NULL, sdata))
665 	    break;
666 	}
667     }
668 
669   return 1;
670 
671  fail:
672   if (macho_symbols != NULL)
673     backtrace_free (state, macho_symbols, macho_symbol_size,
674 		    error_callback, data);
675   if (sym_view_valid)
676     backtrace_release_view (state, &sym_view, error_callback, data);
677   if (str_view_valid)
678     backtrace_release_view (state, &str_view, error_callback, data);
679   return 0;
680 }
681 
682 /* Return the symbol name and value for an ADDR.  */
683 
684 static void
685 macho_syminfo (struct backtrace_state *state, uintptr_t addr,
686 	       backtrace_syminfo_callback callback,
687 	       backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
688 	       void *data)
s3b_config_print_stats(void * prarg,printer_t * printer)689 {
690   struct macho_syminfo_data *sdata;
691   struct macho_symbol *sym;
692 
693   sym = NULL;
694   if (!state->threaded)
695     {
696       for (sdata = (struct macho_syminfo_data *) state->syminfo_data;
697 	   sdata != NULL;
698 	   sdata = sdata->next)
699 	{
700 	  sym = ((struct macho_symbol *)
701 		 bsearch (&addr, sdata->symbols, sdata->count,
702 			  sizeof (struct macho_symbol), macho_symbol_search));
703 	  if (sym != NULL)
704 	    break;
705 	}
706     }
707   else
708     {
709       struct macho_syminfo_data **pp;
710 
711       pp = (struct macho_syminfo_data **) (void *) &state->syminfo_data;
712       while (1)
713 	{
714 	  sdata = backtrace_atomic_load_pointer (pp);
715 	  if (sdata == NULL)
716 	    break;
717 
718 	  sym = ((struct macho_symbol *)
719 		 bsearch (&addr, sdata->symbols, sdata->count,
720 			  sizeof (struct macho_symbol), macho_symbol_search));
721 	  if (sym != NULL)
722 	    break;
723 
724 	  pp = &sdata->next;
725 	}
726     }
727 
728   if (sym == NULL)
729     callback (data, addr, NULL, 0, 0);
730   else
731     callback (data, addr, sym->name, sym->address, 0);
732 }
733 
734 /* Look through a fat file to find the relevant executable.  Returns 1
735    on success, 0 on failure (in both cases descriptor is closed).  */
736 
737 static int
738 macho_add_fat (struct backtrace_state *state, const char *filename,
739 	       int descriptor, int swapped, off_t offset,
740 	       const unsigned char *match_uuid, uintptr_t base_address,
741 	       int skip_symtab, uint32_t nfat_arch,
742 	       backtrace_error_callback error_callback, void *data,
743 	       fileline *fileline_fn, int *found_sym)
744 {
745   int arch_view_valid;
746   unsigned int cputype;
747   struct backtrace_view arch_view;
748   size_t archoffset;
749   unsigned int i;
750 
751   arch_view_valid = 0;
752 
753 #if defined (__x86_64__)
754   cputype = MACH_O_CPU_TYPE_X86_64;
755 #elif defined (__i386__)
756   cputype = MACH_O_CPU_TYPE_X86;
757 #elif defined (__aarch64__)
758   cputype = MACH_O_CPU_TYPE_ARM64;
759 #elif defined (__arm__)
760   cputype = MACH_O_CPU_TYPE_ARM;
761 #else
762   error_callback (data, "unknown Mach-O architecture", 0);
763   goto fail;
764 #endif
765 
766   if (!backtrace_get_view (state, descriptor, offset,
767 			   nfat_arch * sizeof (struct macho_fat_arch),
768 			   error_callback, data, &arch_view))
769     goto fail;
770 
771   archoffset = 0;
772   for (i = 0; i < nfat_arch; ++i)
773     {
774       struct macho_fat_arch fat_arch;
775       uint32_t fcputype;
776 
777       memcpy (&fat_arch,
778 	      ((const char *) arch_view.data
779 	       + i * sizeof (struct macho_fat_arch)),
780 	      sizeof fat_arch);
781 
782       fcputype = fat_arch.cputype;
783       if (swapped)
784 	fcputype = __builtin_bswap32 (fcputype);
785 
786       if (fcputype == cputype)
787 	{
788 	  uint32_t foffset;
789 
s3b_config_clear_stats(void)790 	  /* FIXME: What about cpusubtype?  */
791 	  foffset = fat_arch.offset;
792 	  if (swapped)
793 	    foffset = __builtin_bswap32 (foffset);
794 	  backtrace_release_view (state, &arch_view, error_callback, data);
795 	  return macho_add (state, filename, descriptor, foffset, match_uuid,
796 			    base_address, skip_symtab, error_callback, data,
797 			    fileline_fn, found_sym);
798 	}
799 
800       archoffset += sizeof (struct macho_fat_arch);
801     }
802 
803   error_callback (data, "could not find executable in fat file", 0);
804 
805  fail:
parse_size_string(const char * s,uintmax_t * valp)806   if (arch_view_valid)
807     backtrace_release_view (state, &arch_view, error_callback, data);
808   if (descriptor != -1)
809     backtrace_close (descriptor, error_callback, data);
810   return 0;
811 }
812 
813 /* Look for the dsym file for FILENAME.  This is called if FILENAME
814    does not have debug info or a symbol table.  Returns 1 on success,
815    0 on failure.  */
816 
817 static int
818 macho_add_dsym (struct backtrace_state *state, const char *filename,
819 		uintptr_t base_address, const unsigned char *uuid,
820 		backtrace_error_callback error_callback, void *data,
821 		fileline* fileline_fn)
822 {
823   const char *p;
824   const char *dirname;
825   char *diralc;
826   size_t dirnamelen;
827   const char *basename;
828   size_t basenamelen;
829   const char *dsymsuffixdir;
830   size_t dsymsuffixdirlen;
831   size_t dsymlen;
832   char *dsym;
833   char *ps;
834   int d;
835   int does_not_exist;
unparse_size_string(char * buf,size_t bmax,uintmax_t value)836   int dummy_found_sym;
837 
838   diralc = NULL;
839   dirnamelen = 0;
840   dsym = NULL;
841   dsymlen = 0;
842 
843   p = strrchr (filename, '/');
844   if (p == NULL)
845     {
846       dirname = ".";
847       dirnamelen = 1;
848       basename = filename;
849       basenamelen = strlen (basename);
850       diralc = NULL;
851     }
852   else
853     {
854       dirnamelen = p - filename;
855       diralc = backtrace_alloc (state, dirnamelen + 1, error_callback, data);
856       if (diralc == NULL)
857 	goto fail;
858       memcpy (diralc, filename, dirnamelen);
859       diralc[dirnamelen] = '\0';
860       dirname = diralc;
861       basename = p + 1;
862       basenamelen = strlen (basename);
handle_unknown_option(void * data,const char * arg,int key,struct fuse_args * outargs)863     }
864 
865   dsymsuffixdir = ".dSYM/Contents/Resources/DWARF/";
866   dsymsuffixdirlen = strlen (dsymsuffixdir);
867 
868   dsymlen = (dirnamelen
869 	     + basenamelen
870 	     + dsymsuffixdirlen
871 	     + basenamelen
872 	     + 1);
873   dsym = backtrace_alloc (state, dsymlen, error_callback, data);
874   if (dsym == NULL)
875     goto fail;
876 
877   ps = dsym;
878   memcpy (ps, dirname, dirnamelen);
879   ps += dirnamelen;
880   *ps++ = '/';
881   memcpy (ps, basename, basenamelen);
882   ps += basenamelen;
883   memcpy (ps, dsymsuffixdir, dsymsuffixdirlen);
884   ps += dsymsuffixdirlen;
885   memcpy (ps, basename, basenamelen);
886   ps += basenamelen;
887   *ps = '\0';
888 
889   if (diralc != NULL)
890     {
891       backtrace_free (state, diralc, dirnamelen, error_callback, data);
892       diralc = NULL;
893     }
894 
895   d = backtrace_open (dsym, error_callback, data, &does_not_exist);
896   if (d < 0)
897     {
898       /* The file does not exist, so we can't read the debug info.
899 	 Just return success.  */
900       backtrace_free (state, dsym, dsymlen, error_callback, data);
901       return 1;
902     }
903 
904   if (!macho_add (state, dsym, d, 0, uuid, base_address, 1,
905 		  error_callback, data, fileline_fn, &dummy_found_sym))
906     goto fail;
907 
908   backtrace_free (state, dsym, dsymlen, error_callback, data);
909 
910   return 1;
911 
search_access_for(const char * file,const char * accessId,char ** idptr,char ** pwptr)912  fail:
913   if (dsym != NULL)
914     backtrace_free (state, dsym, dsymlen, error_callback, data);
915   if (diralc != NULL)
916     backtrace_free (state, diralc, dirnamelen, error_callback, data);
917   return 0;
918 }
919 
920 /* Add the backtrace data for a Macho-O file.  Returns 1 on success, 0
921    on failure (in both cases descriptor is closed).
922 
923    FILENAME: the name of the executable.
924    DESCRIPTOR: an open descriptor for the executable, closed here.
925    OFFSET: the offset within the file of this executable, for fat files.
926    MATCH_UUID: if not NULL, UUID that must match.
927    BASE_ADDRESS: the load address of the executable.
928    SKIP_SYMTAB: if non-zero, ignore the symbol table; used for dSYM files.
929    FILELINE_FN: set to the fileline function, by backtrace_dwarf_add.
930    FOUND_SYM: set to non-zero if we found the symbol table.
931 */
932 
933 static int
934 macho_add (struct backtrace_state *state, const char *filename, int descriptor,
935 	   off_t offset, const unsigned char *match_uuid,
936 	   uintptr_t base_address, int skip_symtab,
937 	   backtrace_error_callback error_callback, void *data,
938 	   fileline *fileline_fn, int *found_sym)
939 {
940   struct backtrace_view header_view;
941   struct macho_header_32 header;
942   off_t hdroffset;
943   int is_64;
944   struct backtrace_view cmds_view;
validate_config(void)945   int cmds_view_valid;
946   struct dwarf_sections dwarf_sections;
947   int have_dwarf;
948   unsigned char uuid[MACH_O_UUID_LEN];
949   int have_uuid;
950   size_t cmdoffset;
951   unsigned int i;
952 
953   *found_sym = 0;
954 
955   cmds_view_valid = 0;
956 
957   /* The 32-bit and 64-bit file headers start out the same, so we can
958      just always read the 32-bit version.  A fat header is shorter but
959      it will always be followed by data, so it's OK to read extra.  */
960 
961   if (!backtrace_get_view (state, descriptor, offset,
962 			   sizeof (struct macho_header_32),
963 			   error_callback, data, &header_view))
964     goto fail;
965 
966   memcpy (&header, header_view.data, sizeof header);
967 
968   backtrace_release_view (state, &header_view, error_callback, data);
969 
970   switch (header.magic)
971     {
972     case MACH_O_MH_MAGIC_32:
973       is_64 = 0;
974       hdroffset = offset + sizeof (struct macho_header_32);
975       break;
976     case MACH_O_MH_MAGIC_64:
977       is_64 = 1;
978       hdroffset = offset + sizeof (struct macho_header_64);
979       break;
980     case MACH_O_MH_MAGIC_FAT:
981       {
982 	struct macho_header_fat fat_header;
983 
984 	hdroffset = offset + sizeof (struct macho_header_fat);
985 	memcpy (&fat_header, &header, sizeof fat_header);
986 	return macho_add_fat (state, filename, descriptor, 0, hdroffset,
987 			      match_uuid, base_address, skip_symtab,
988 			      fat_header.nfat_arch, error_callback, data,
989 			      fileline_fn, found_sym);
990       }
991     case MACH_O_MH_CIGAM_FAT:
992       {
993 	struct macho_header_fat fat_header;
994 	uint32_t nfat_arch;
995 
996 	hdroffset = offset + sizeof (struct macho_header_fat);
997 	memcpy (&fat_header, &header, sizeof fat_header);
998 	nfat_arch = __builtin_bswap32 (fat_header.nfat_arch);
999 	return macho_add_fat (state, filename, descriptor, 1, hdroffset,
1000 			      match_uuid, base_address, skip_symtab,
1001 			      nfat_arch, error_callback, data,
1002 			      fileline_fn, found_sym);
1003       }
1004     default:
1005       error_callback (data, "executable file is not in Mach-O format", 0);
1006       goto fail;
1007     }
1008 
1009   switch (header.filetype)
1010     {
1011     case MACH_O_MH_EXECUTE:
1012     case MACH_O_MH_DYLIB:
1013     case MACH_O_MH_DSYM:
1014       break;
1015     default:
1016       error_callback (data, "executable file is not an executable", 0);
1017       goto fail;
1018     }
1019 
1020   if (!backtrace_get_view (state, descriptor, hdroffset, header.sizeofcmds,
1021 			   error_callback, data, &cmds_view))
1022     goto fail;
1023   cmds_view_valid = 1;
1024 
1025   memset (&dwarf_sections, 0, sizeof dwarf_sections);
1026   have_dwarf = 0;
1027   memset (&uuid, 0, sizeof uuid);
1028   have_uuid = 0;
1029 
1030   cmdoffset = 0;
1031   for (i = 0; i < header.ncmds; ++i)
1032     {
1033       const char *pcmd;
1034       struct macho_load_command load_command;
1035 
1036       if (cmdoffset + sizeof load_command > header.sizeofcmds)
1037 	break;
1038 
1039       pcmd = (const char *) cmds_view.data + cmdoffset;
1040       memcpy (&load_command, pcmd, sizeof load_command);
1041 
1042       switch (load_command.cmd)
1043 	{
1044 	case MACH_O_LC_SEGMENT:
1045 	  {
1046 	    struct macho_segment_command segcmd;
1047 
1048 	    memcpy (&segcmd, pcmd, sizeof segcmd);
1049 	    if (memcmp (segcmd.segname,
1050 			"__DWARF\0\0\0\0\0\0\0\0\0",
1051 			MACH_O_NAMELEN) == 0)
1052 	      {
1053 		if (!macho_add_dwarf_segment (state, descriptor, offset,
1054 					      load_command.cmd,
1055 					      pcmd + sizeof segcmd,
1056 					      (load_command.cmdsize
1057 					       - sizeof segcmd),
1058 					      segcmd.nsects, error_callback,
1059 					      data, &dwarf_sections))
1060 		  goto fail;
1061 		have_dwarf = 1;
1062 	      }
1063 	  }
1064 	  break;
1065 
1066 	case MACH_O_LC_SEGMENT_64:
1067 	  {
1068 	    struct macho_segment_64_command segcmd;
1069 
1070 	    memcpy (&segcmd, pcmd, sizeof segcmd);
1071 	    if (memcmp (segcmd.segname,
1072 			"__DWARF\0\0\0\0\0\0\0\0\0",
1073 			MACH_O_NAMELEN) == 0)
1074 	      {
1075 		if (!macho_add_dwarf_segment (state, descriptor, offset,
1076 					      load_command.cmd,
1077 					      pcmd + sizeof segcmd,
1078 					      (load_command.cmdsize
1079 					       - sizeof segcmd),
1080 					      segcmd.nsects, error_callback,
1081 					      data, &dwarf_sections))
1082 		  goto fail;
1083 		have_dwarf = 1;
1084 	      }
1085 	  }
1086 	  break;
1087 
1088 	case MACH_O_LC_SYMTAB:
1089 	  if (!skip_symtab)
1090 	    {
1091 	      struct macho_symtab_command symcmd;
1092 
1093 	      memcpy (&symcmd, pcmd, sizeof symcmd);
1094 	      if (!macho_add_symtab (state, descriptor, base_address, is_64,
1095 				     offset + symcmd.symoff, symcmd.nsyms,
1096 				     offset + symcmd.stroff, symcmd.strsize,
1097 				     error_callback, data))
1098 		goto fail;
1099 
1100 	      *found_sym = 1;
1101 	    }
1102 	  break;
1103 
1104 	case MACH_O_LC_UUID:
1105 	  {
1106 	    struct macho_uuid_command uuidcmd;
1107 
1108 	    memcpy (&uuidcmd, pcmd, sizeof uuidcmd);
1109 	    memcpy (&uuid[0], &uuidcmd.uuid[0], MACH_O_UUID_LEN);
1110 	    have_uuid = 1;
1111 	  }
1112 	  break;
1113 
1114 	default:
1115 	  break;
1116 	}
1117 
1118       cmdoffset += load_command.cmdsize;
1119     }
1120 
1121   if (!backtrace_close (descriptor, error_callback, data))
1122     goto fail;
1123   descriptor = -1;
1124 
1125   backtrace_release_view (state, &cmds_view, error_callback, data);
1126   cmds_view_valid = 0;
1127 
1128   if (match_uuid != NULL)
1129     {
1130       /* If we don't have a UUID, or it doesn't match, just ignore
1131 	 this file.  */
1132       if (!have_uuid
1133 	  || memcmp (match_uuid, &uuid[0], MACH_O_UUID_LEN) != 0)
1134 	return 1;
1135     }
1136 
1137   if (have_dwarf)
1138     {
1139       int is_big_endian;
1140 
1141       is_big_endian = 0;
1142 #if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)
1143 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
1144       is_big_endian = 1;
1145 #endif
1146 #endif
1147 
1148       if (!backtrace_dwarf_add (state, base_address, &dwarf_sections,
1149 				is_big_endian, NULL, error_callback, data,
1150 				fileline_fn, NULL))
1151 	goto fail;
1152     }
1153 
1154   if (!have_dwarf && have_uuid)
1155     {
1156       if (!macho_add_dsym (state, filename, base_address, &uuid[0],
1157 			   error_callback, data, fileline_fn))
1158 	goto fail;
1159     }
1160 
1161   return 1;
1162 
1163  fail:
1164   if (cmds_view_valid)
1165     backtrace_release_view (state, &cmds_view, error_callback, data);
1166   if (descriptor != -1)
1167     backtrace_close (descriptor, error_callback, data);
1168   return 0;
1169 }
1170 
1171 #ifdef HAVE_MACH_O_DYLD_H
1172 
1173 /* Initialize the backtrace data we need from a Mach-O executable
1174    using the dyld support functions.  This closes descriptor.  */
1175 
1176 int
1177 backtrace_initialize (struct backtrace_state *state, const char *filename,
1178 		      int descriptor, backtrace_error_callback error_callback,
1179 		      void *data, fileline *fileline_fn)
1180 {
1181   uint32_t c;
1182   uint32_t i;
1183   int closed_descriptor;
1184   int found_sym;
1185   fileline macho_fileline_fn;
1186 
1187   closed_descriptor = 0;
1188   found_sym = 0;
1189   macho_fileline_fn = macho_nodebug;
1190 
1191   c = _dyld_image_count ();
1192   for (i = 0; i < c; ++i)
1193     {
1194       uintptr_t base_address;
1195       const char *name;
1196       int d;
1197       fileline mff;
1198       int mfs;
1199 
1200       name = _dyld_get_image_name (i);
1201       if (name == NULL)
1202 	continue;
1203 
1204       if (strcmp (name, filename) == 0 && !closed_descriptor)
1205 	{
1206 	  d = descriptor;
1207 	  closed_descriptor = 1;
1208 	}
1209       else
1210 	{
1211 	  int does_not_exist;
1212 
1213 	  d = backtrace_open (name, error_callback, data, &does_not_exist);
1214 	  if (d < 0)
1215 	    continue;
1216 	}
1217 
1218       base_address = _dyld_get_image_vmaddr_slide (i);
1219 
1220       mff = macho_nodebug;
1221       if (!macho_add (state, name, d, 0, NULL, base_address, 0,
1222 		      error_callback, data, &mff, &mfs))
1223 	return 0;
1224 
1225       if (mff != macho_nodebug)
1226 	macho_fileline_fn = mff;
1227       if (mfs)
1228 	found_sym = 1;
1229     }
1230 
1231   if (!closed_descriptor)
1232     backtrace_close (descriptor, error_callback, data);
1233 
1234   if (!state->threaded)
1235     {
1236       if (found_sym)
1237 	state->syminfo_fn = macho_syminfo;
1238       else if (state->syminfo_fn == NULL)
1239 	state->syminfo_fn = macho_nosyms;
1240     }
1241   else
1242     {
1243       if (found_sym)
1244 	backtrace_atomic_store_pointer (&state->syminfo_fn, macho_syminfo);
1245       else
1246 	(void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
1247 					     macho_nosyms);
1248     }
1249 
1250   if (!state->threaded)
1251     *fileline_fn = state->fileline_fn;
1252   else
1253     *fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
1254 
1255   if (*fileline_fn == NULL || *fileline_fn == macho_nodebug)
1256     *fileline_fn = macho_fileline_fn;
1257 
1258   return 1;
1259 }
1260 
1261 #else /* !defined (HAVE_MACH_O_DYLD_H) */
1262 
1263 /* Initialize the backtrace data we need from a Mach-O executable
1264    without using the dyld support functions.  This closes
1265    descriptor.  */
1266 
1267 int
1268 backtrace_initialize (struct backtrace_state *state, const char *filename,
1269 		      int descriptor, backtrace_error_callback error_callback,
1270 		      void *data, fileline *fileline_fn)
1271 {
1272   fileline macho_fileline_fn;
1273   int found_sym;
1274 
1275   macho_fileline_fn = macho_nodebug;
1276   if (!macho_add (state, filename, descriptor, 0, NULL, 0, 0,
1277 		  error_callback, data, &macho_fileline_fn, &found_sym))
1278     return 0;
1279 
1280   if (!state->threaded)
1281     {
1282       if (found_sym)
1283 	state->syminfo_fn = macho_syminfo;
1284       else if (state->syminfo_fn == NULL)
1285 	state->syminfo_fn = macho_nosyms;
1286     }
1287   else
1288     {
1289       if (found_sym)
1290 	backtrace_atomic_store_pointer (&state->syminfo_fn, macho_syminfo);
1291       else
1292 	(void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
1293 					     macho_nosyms);
1294     }
1295 
1296   if (!state->threaded)
1297     *fileline_fn = state->fileline_fn;
1298   else
1299     *fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
1300 
1301   if (*fileline_fn == NULL || *fileline_fn == macho_nodebug)
1302     *fileline_fn = macho_fileline_fn;
1303 
1304   return 1;
1305 }
1306 
1307 #endif /* !defined (HAVE_MACH_O_DYLD_H) */
1308