libbacktrace: correctly swap Mach-O 32-bit file offset
[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 uint32_t fcputype;
797 uint64_t foffset;
798
799 if (is_64)
800 {
801 struct macho_fat_arch_64 fat_arch_64;
802
803 memcpy (&fat_arch_64,
804 (const char *) arch_view.data + i * arch_size,
805 arch_size);
806 fcputype = fat_arch_64.cputype;
807 foffset = fat_arch_64.offset;
808 if (swapped)
809 {
810 fcputype = __builtin_bswap32 (fcputype);
811 foffset = __builtin_bswap64 (foffset);
812 }
813 }
814 else
815 {
816 struct macho_fat_arch fat_arch_32;
817
818 memcpy (&fat_arch_32,
819 (const char *) arch_view.data + i * arch_size,
820 arch_size);
821 fcputype = fat_arch_32.cputype;
822 foffset = (uint64_t) fat_arch_32.offset;
823 if (swapped)
824 {
825 fcputype = __builtin_bswap32 (fcputype);
826 foffset = (uint64_t) __builtin_bswap32 ((uint32_t) foffset);
827 }
828 }
829
830 if (fcputype == cputype)
831 {
832 /* FIXME: What about cpusubtype? */
833 backtrace_release_view (state, &arch_view, error_callback, data);
834 return macho_add (state, filename, descriptor, foffset, match_uuid,
835 base_address, skip_symtab, error_callback, data,
836 fileline_fn, found_sym);
837 }
838 }
839
840 error_callback (data, "could not find executable in fat file", 0);
841
842 fail:
843 if (arch_view_valid)
844 backtrace_release_view (state, &arch_view, error_callback, data);
845 if (descriptor != -1)
846 backtrace_close (descriptor, error_callback, data);
847 return 0;
848 }
849
850 /* Look for the dsym file for FILENAME. This is called if FILENAME
851 does not have debug info or a symbol table. Returns 1 on success,
852 0 on failure. */
853
854 static int
855 macho_add_dsym (struct backtrace_state *state, const char *filename,
856 uintptr_t base_address, const unsigned char *uuid,
857 backtrace_error_callback error_callback, void *data,
858 fileline* fileline_fn)
859 {
860 const char *p;
861 const char *dirname;
862 char *diralc;
863 size_t dirnamelen;
864 const char *basename;
865 size_t basenamelen;
866 const char *dsymsuffixdir;
867 size_t dsymsuffixdirlen;
868 size_t dsymlen;
869 char *dsym;
870 char *ps;
871 int d;
872 int does_not_exist;
873 int dummy_found_sym;
874
875 diralc = NULL;
876 dirnamelen = 0;
877 dsym = NULL;
878 dsymlen = 0;
879
880 p = strrchr (filename, '/');
881 if (p == NULL)
882 {
883 dirname = ".";
884 dirnamelen = 1;
885 basename = filename;
886 basenamelen = strlen (basename);
887 diralc = NULL;
888 }
889 else
890 {
891 dirnamelen = p - filename;
892 diralc = backtrace_alloc (state, dirnamelen + 1, error_callback, data);
893 if (diralc == NULL)
894 goto fail;
895 memcpy (diralc, filename, dirnamelen);
896 diralc[dirnamelen] = '\0';
897 dirname = diralc;
898 basename = p + 1;
899 basenamelen = strlen (basename);
900 }
901
902 dsymsuffixdir = ".dSYM/Contents/Resources/DWARF/";
903 dsymsuffixdirlen = strlen (dsymsuffixdir);
904
905 dsymlen = (dirnamelen
906 + basenamelen
907 + dsymsuffixdirlen
908 + basenamelen
909 + 1);
910 dsym = backtrace_alloc (state, dsymlen, error_callback, data);
911 if (dsym == NULL)
912 goto fail;
913
914 ps = dsym;
915 memcpy (ps, dirname, dirnamelen);
916 ps += dirnamelen;
917 *ps++ = '/';
918 memcpy (ps, basename, basenamelen);
919 ps += basenamelen;
920 memcpy (ps, dsymsuffixdir, dsymsuffixdirlen);
921 ps += dsymsuffixdirlen;
922 memcpy (ps, basename, basenamelen);
923 ps += basenamelen;
924 *ps = '\0';
925
926 if (diralc != NULL)
927 {
928 backtrace_free (state, diralc, dirnamelen, error_callback, data);
929 diralc = NULL;
930 }
931
932 d = backtrace_open (dsym, error_callback, data, &does_not_exist);
933 if (d < 0)
934 {
935 /* The file does not exist, so we can't read the debug info.
936 Just return success. */
937 backtrace_free (state, dsym, dsymlen, error_callback, data);
938 return 1;
939 }
940
941 if (!macho_add (state, dsym, d, 0, uuid, base_address, 1,
942 error_callback, data, fileline_fn, &dummy_found_sym))
943 goto fail;
944
945 backtrace_free (state, dsym, dsymlen, error_callback, data);
946
947 return 1;
948
949 fail:
950 if (dsym != NULL)
951 backtrace_free (state, dsym, dsymlen, error_callback, data);
952 if (diralc != NULL)
953 backtrace_free (state, diralc, dirnamelen, error_callback, data);
954 return 0;
955 }
956
957 /* Add the backtrace data for a Macho-O file. Returns 1 on success, 0
958 on failure (in both cases descriptor is closed).
959
960 FILENAME: the name of the executable.
961 DESCRIPTOR: an open descriptor for the executable, closed here.
962 OFFSET: the offset within the file of this executable, for fat files.
963 MATCH_UUID: if not NULL, UUID that must match.
964 BASE_ADDRESS: the load address of the executable.
965 SKIP_SYMTAB: if non-zero, ignore the symbol table; used for dSYM files.
966 FILELINE_FN: set to the fileline function, by backtrace_dwarf_add.
967 FOUND_SYM: set to non-zero if we found the symbol table.
968 */
969
970 static int
971 macho_add (struct backtrace_state *state, const char *filename, int descriptor,
972 off_t offset, const unsigned char *match_uuid,
973 uintptr_t base_address, int skip_symtab,
974 backtrace_error_callback error_callback, void *data,
975 fileline *fileline_fn, int *found_sym)
976 {
977 struct backtrace_view header_view;
978 struct macho_header_32 header;
979 off_t hdroffset;
980 int is_64;
981 struct backtrace_view cmds_view;
982 int cmds_view_valid;
983 struct dwarf_sections dwarf_sections;
984 int have_dwarf;
985 unsigned char uuid[MACH_O_UUID_LEN];
986 int have_uuid;
987 size_t cmdoffset;
988 unsigned int i;
989
990 *found_sym = 0;
991
992 cmds_view_valid = 0;
993
994 /* The 32-bit and 64-bit file headers start out the same, so we can
995 just always read the 32-bit version. A fat header is shorter but
996 it will always be followed by data, so it's OK to read extra. */
997
998 if (!backtrace_get_view (state, descriptor, offset,
999 sizeof (struct macho_header_32),
1000 error_callback, data, &header_view))
1001 goto fail;
1002
1003 memcpy (&header, header_view.data, sizeof header);
1004
1005 backtrace_release_view (state, &header_view, error_callback, data);
1006
1007 switch (header.magic)
1008 {
1009 case MACH_O_MH_MAGIC_32:
1010 is_64 = 0;
1011 hdroffset = offset + sizeof (struct macho_header_32);
1012 break;
1013 case MACH_O_MH_MAGIC_64:
1014 is_64 = 1;
1015 hdroffset = offset + sizeof (struct macho_header_64);
1016 break;
1017 case MACH_O_MH_MAGIC_FAT:
1018 case MACH_O_MH_MAGIC_FAT_64:
1019 {
1020 struct macho_header_fat fat_header;
1021
1022 hdroffset = offset + sizeof (struct macho_header_fat);
1023 memcpy (&fat_header, &header, sizeof fat_header);
1024 return macho_add_fat (state, filename, descriptor, 0, hdroffset,
1025 match_uuid, base_address, skip_symtab,
1026 fat_header.nfat_arch,
1027 header.magic == MACH_O_MH_MAGIC_FAT_64,
1028 error_callback, data, fileline_fn, found_sym);
1029 }
1030 case MACH_O_MH_CIGAM_FAT:
1031 case MACH_O_MH_CIGAM_FAT_64:
1032 {
1033 struct macho_header_fat fat_header;
1034 uint32_t nfat_arch;
1035
1036 hdroffset = offset + sizeof (struct macho_header_fat);
1037 memcpy (&fat_header, &header, sizeof fat_header);
1038 nfat_arch = __builtin_bswap32 (fat_header.nfat_arch);
1039 return macho_add_fat (state, filename, descriptor, 1, hdroffset,
1040 match_uuid, base_address, skip_symtab,
1041 nfat_arch,
1042 header.magic == MACH_O_MH_CIGAM_FAT_64,
1043 error_callback, data, fileline_fn, found_sym);
1044 }
1045 default:
1046 error_callback (data, "executable file is not in Mach-O format", 0);
1047 goto fail;
1048 }
1049
1050 switch (header.filetype)
1051 {
1052 case MACH_O_MH_EXECUTE:
1053 case MACH_O_MH_DYLIB:
1054 case MACH_O_MH_DSYM:
1055 break;
1056 default:
1057 error_callback (data, "executable file is not an executable", 0);
1058 goto fail;
1059 }
1060
1061 if (!backtrace_get_view (state, descriptor, hdroffset, header.sizeofcmds,
1062 error_callback, data, &cmds_view))
1063 goto fail;
1064 cmds_view_valid = 1;
1065
1066 memset (&dwarf_sections, 0, sizeof dwarf_sections);
1067 have_dwarf = 0;
1068 memset (&uuid, 0, sizeof uuid);
1069 have_uuid = 0;
1070
1071 cmdoffset = 0;
1072 for (i = 0; i < header.ncmds; ++i)
1073 {
1074 const char *pcmd;
1075 struct macho_load_command load_command;
1076
1077 if (cmdoffset + sizeof load_command > header.sizeofcmds)
1078 break;
1079
1080 pcmd = (const char *) cmds_view.data + cmdoffset;
1081 memcpy (&load_command, pcmd, sizeof load_command);
1082
1083 switch (load_command.cmd)
1084 {
1085 case MACH_O_LC_SEGMENT:
1086 {
1087 struct macho_segment_command segcmd;
1088
1089 memcpy (&segcmd, pcmd, sizeof segcmd);
1090 if (memcmp (segcmd.segname,
1091 "__DWARF\0\0\0\0\0\0\0\0\0",
1092 MACH_O_NAMELEN) == 0)
1093 {
1094 if (!macho_add_dwarf_segment (state, descriptor, offset,
1095 load_command.cmd,
1096 pcmd + sizeof segcmd,
1097 (load_command.cmdsize
1098 - sizeof segcmd),
1099 segcmd.nsects, error_callback,
1100 data, &dwarf_sections))
1101 goto fail;
1102 have_dwarf = 1;
1103 }
1104 }
1105 break;
1106
1107 case MACH_O_LC_SEGMENT_64:
1108 {
1109 struct macho_segment_64_command segcmd;
1110
1111 memcpy (&segcmd, pcmd, sizeof segcmd);
1112 if (memcmp (segcmd.segname,
1113 "__DWARF\0\0\0\0\0\0\0\0\0",
1114 MACH_O_NAMELEN) == 0)
1115 {
1116 if (!macho_add_dwarf_segment (state, descriptor, offset,
1117 load_command.cmd,
1118 pcmd + sizeof segcmd,
1119 (load_command.cmdsize
1120 - sizeof segcmd),
1121 segcmd.nsects, error_callback,
1122 data, &dwarf_sections))
1123 goto fail;
1124 have_dwarf = 1;
1125 }
1126 }
1127 break;
1128
1129 case MACH_O_LC_SYMTAB:
1130 if (!skip_symtab)
1131 {
1132 struct macho_symtab_command symcmd;
1133
1134 memcpy (&symcmd, pcmd, sizeof symcmd);
1135 if (!macho_add_symtab (state, descriptor, base_address, is_64,
1136 offset + symcmd.symoff, symcmd.nsyms,
1137 offset + symcmd.stroff, symcmd.strsize,
1138 error_callback, data))
1139 goto fail;
1140
1141 *found_sym = 1;
1142 }
1143 break;
1144
1145 case MACH_O_LC_UUID:
1146 {
1147 struct macho_uuid_command uuidcmd;
1148
1149 memcpy (&uuidcmd, pcmd, sizeof uuidcmd);
1150 memcpy (&uuid[0], &uuidcmd.uuid[0], MACH_O_UUID_LEN);
1151 have_uuid = 1;
1152 }
1153 break;
1154
1155 default:
1156 break;
1157 }
1158
1159 cmdoffset += load_command.cmdsize;
1160 }
1161
1162 if (!backtrace_close (descriptor, error_callback, data))
1163 goto fail;
1164 descriptor = -1;
1165
1166 backtrace_release_view (state, &cmds_view, error_callback, data);
1167 cmds_view_valid = 0;
1168
1169 if (match_uuid != NULL)
1170 {
1171 /* If we don't have a UUID, or it doesn't match, just ignore
1172 this file. */
1173 if (!have_uuid
1174 || memcmp (match_uuid, &uuid[0], MACH_O_UUID_LEN) != 0)
1175 return 1;
1176 }
1177
1178 if (have_dwarf)
1179 {
1180 int is_big_endian;
1181
1182 is_big_endian = 0;
1183 #if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)
1184 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
1185 is_big_endian = 1;
1186 #endif
1187 #endif
1188
1189 if (!backtrace_dwarf_add (state, base_address, &dwarf_sections,
1190 is_big_endian, NULL, error_callback, data,
1191 fileline_fn, NULL))
1192 goto fail;
1193 }
1194
1195 if (!have_dwarf && have_uuid)
1196 {
1197 if (!macho_add_dsym (state, filename, base_address, &uuid[0],
1198 error_callback, data, fileline_fn))
1199 goto fail;
1200 }
1201
1202 return 1;
1203
1204 fail:
1205 if (cmds_view_valid)
1206 backtrace_release_view (state, &cmds_view, error_callback, data);
1207 if (descriptor != -1)
1208 backtrace_close (descriptor, error_callback, data);
1209 return 0;
1210 }
1211
1212 #ifdef HAVE_MACH_O_DYLD_H
1213
1214 /* Initialize the backtrace data we need from a Mach-O executable
1215 using the dyld support functions. This closes descriptor. */
1216
1217 int
1218 backtrace_initialize (struct backtrace_state *state, const char *filename,
1219 int descriptor, backtrace_error_callback error_callback,
1220 void *data, fileline *fileline_fn)
1221 {
1222 uint32_t c;
1223 uint32_t i;
1224 int closed_descriptor;
1225 int found_sym;
1226 fileline macho_fileline_fn;
1227
1228 closed_descriptor = 0;
1229 found_sym = 0;
1230 macho_fileline_fn = macho_nodebug;
1231
1232 c = _dyld_image_count ();
1233 for (i = 0; i < c; ++i)
1234 {
1235 uintptr_t base_address;
1236 const char *name;
1237 int d;
1238 fileline mff;
1239 int mfs;
1240
1241 name = _dyld_get_image_name (i);
1242 if (name == NULL)
1243 continue;
1244
1245 if (strcmp (name, filename) == 0 && !closed_descriptor)
1246 {
1247 d = descriptor;
1248 closed_descriptor = 1;
1249 }
1250 else
1251 {
1252 int does_not_exist;
1253
1254 d = backtrace_open (name, error_callback, data, &does_not_exist);
1255 if (d < 0)
1256 continue;
1257 }
1258
1259 base_address = _dyld_get_image_vmaddr_slide (i);
1260
1261 mff = macho_nodebug;
1262 if (!macho_add (state, name, d, 0, NULL, base_address, 0,
1263 error_callback, data, &mff, &mfs))
1264 return 0;
1265
1266 if (mff != macho_nodebug)
1267 macho_fileline_fn = mff;
1268 if (mfs)
1269 found_sym = 1;
1270 }
1271
1272 if (!closed_descriptor)
1273 backtrace_close (descriptor, error_callback, data);
1274
1275 if (!state->threaded)
1276 {
1277 if (found_sym)
1278 state->syminfo_fn = macho_syminfo;
1279 else if (state->syminfo_fn == NULL)
1280 state->syminfo_fn = macho_nosyms;
1281 }
1282 else
1283 {
1284 if (found_sym)
1285 backtrace_atomic_store_pointer (&state->syminfo_fn, macho_syminfo);
1286 else
1287 (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
1288 macho_nosyms);
1289 }
1290
1291 if (!state->threaded)
1292 *fileline_fn = state->fileline_fn;
1293 else
1294 *fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
1295
1296 if (*fileline_fn == NULL || *fileline_fn == macho_nodebug)
1297 *fileline_fn = macho_fileline_fn;
1298
1299 return 1;
1300 }
1301
1302 #else /* !defined (HAVE_MACH_O_DYLD_H) */
1303
1304 /* Initialize the backtrace data we need from a Mach-O executable
1305 without using the dyld support functions. This closes
1306 descriptor. */
1307
1308 int
1309 backtrace_initialize (struct backtrace_state *state, const char *filename,
1310 int descriptor, backtrace_error_callback error_callback,
1311 void *data, fileline *fileline_fn)
1312 {
1313 fileline macho_fileline_fn;
1314 int found_sym;
1315
1316 macho_fileline_fn = macho_nodebug;
1317 if (!macho_add (state, filename, descriptor, 0, NULL, 0, 0,
1318 error_callback, data, &macho_fileline_fn, &found_sym))
1319 return 0;
1320
1321 if (!state->threaded)
1322 {
1323 if (found_sym)
1324 state->syminfo_fn = macho_syminfo;
1325 else if (state->syminfo_fn == NULL)
1326 state->syminfo_fn = macho_nosyms;
1327 }
1328 else
1329 {
1330 if (found_sym)
1331 backtrace_atomic_store_pointer (&state->syminfo_fn, macho_syminfo);
1332 else
1333 (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
1334 macho_nosyms);
1335 }
1336
1337 if (!state->threaded)
1338 *fileline_fn = state->fileline_fn;
1339 else
1340 *fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
1341
1342 if (*fileline_fn == NULL || *fileline_fn == macho_nodebug)
1343 *fileline_fn = macho_fileline_fn;
1344
1345 return 1;
1346 }
1347
1348 #endif /* !defined (HAVE_MACH_O_DYLD_H) */