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