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