phiopt: Reset the number of iterations information of a loop when changing an exit...
[gcc-git-mirror.git] / libbacktrace / macho.c
blob9f8738dd7844792f21163c72d73eb3cdfb15fd95
1 /* elf.c -- Get debug data from a Mach-O file for backtraces.
2 Copyright (C) 2020-2024 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor, Google.
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
9 (1) Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
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.
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.
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. */
33 #include "config.h"
35 #include <sys/types.h>
36 #include <dirent.h>
37 #include <stdlib.h>
38 #include <string.h>
40 #ifdef HAVE_MACH_O_DYLD_H
41 #include <mach-o/dyld.h>
42 #endif
44 #include "backtrace.h"
45 #include "internal.h"
47 /* Mach-O file header for a 32-bit executable. */
49 struct macho_header_32
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 */
60 /* Mach-O file header for a 64-bit executable. */
62 struct macho_header_64
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 */
74 /* Mach-O file header for a fat executable. */
76 struct macho_header_fat
78 uint32_t magic; /* Magic number (MACH_O_MH_(MAGIC|CIGAM)_FAT(_64)?) */
79 uint32_t nfat_arch; /* Number of components */
82 /* Values for the header magic field. */
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
91 /* Value for the header filetype field. */
93 #define MACH_O_MH_EXECUTE 0x02
94 #define MACH_O_MH_DYLIB 0x06
95 #define MACH_O_MH_DSYM 0x0a
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. */
101 struct macho_fat_arch
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 */
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. */
114 struct macho_fat_arch_64
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 */
124 /* Values for the fat_arch cputype field (and the header cputype
125 field). */
127 #define MACH_O_CPU_ARCH_ABI64 0x01000000
129 #define MACH_O_CPU_TYPE_X86 7
130 #define MACH_O_CPU_TYPE_ARM 12
131 #define MACH_O_CPU_TYPE_PPC 18
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)
137 /* The header of a load command. */
139 struct macho_load_command
141 uint32_t cmd; /* The type of load command */
142 uint32_t cmdsize; /* Size in bytes of the entire command */
145 /* Values for the load_command cmd field. */
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
152 /* The length of a section of segment name. */
154 #define MACH_O_NAMELEN (16)
156 /* LC_SEGMENT load command. */
158 struct macho_segment_command
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 */
173 /* LC_SEGMENT_64 load command. */
175 struct macho_segment_64_command
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 */
190 /* LC_SYMTAB load command. */
192 struct macho_symtab_command
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 */
202 /* The length of a Mach-O uuid. */
204 #define MACH_O_UUID_LEN (16)
206 /* LC_UUID load command. */
208 struct macho_uuid_command
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 */
215 /* 32-bit section header within a LC_SEGMENT segment. */
217 struct macho_section
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;
232 /* 64-bit section header within a LC_SEGMENT_64 segment. */
234 struct macho_section_64
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;
250 /* 32-bit symbol data. */
252 struct macho_nlist
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 */
261 /* 64-bit symbol data. */
263 struct macho_nlist_64
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 */
272 /* Value found in nlist n_type field. */
274 #define MACH_O_N_STAB 0xe0 /* Stabs debugging symbol */
275 #define MACH_O_N_TYPE 0x0e /* Mask for type bits */
277 /* Values found after masking with MACH_O_N_TYPE. */
278 #define MACH_O_N_UNDF 0x00 /* Undefined symbol */
279 #define MACH_O_N_ABS 0x02 /* Absolute symbol */
280 #define MACH_O_N_SECT 0x0e /* Defined in section from n_sect field */
283 /* Information we keep for a Mach-O symbol. */
285 struct macho_symbol
287 const char *name; /* Symbol name */
288 uintptr_t address; /* Symbol address */
291 /* Information to pass to macho_syminfo. */
293 struct macho_syminfo_data
295 struct macho_syminfo_data *next; /* Next module */
296 struct macho_symbol *symbols; /* Symbols sorted by address */
297 size_t count; /* Number of symbols */
300 /* Names of sections, indexed by enum dwarf_section in internal.h. */
302 static const char * const dwarf_section_names[DEBUG_MAX] =
304 "__debug_info",
305 "__debug_line",
306 "__debug_abbrev",
307 "__debug_ranges",
308 "__debug_str",
309 "__debug_addr",
310 "__debug_str_offs",
311 "__debug_line_str",
312 "__debug_rnglists"
315 /* Forward declaration. */
317 static int macho_add (struct backtrace_state *, const char *, int, off_t,
318 const unsigned char *, struct libbacktrace_base_address,
319 int, backtrace_error_callback, void *, fileline *,
320 int *);
322 /* A dummy callback function used when we can't find any debug info. */
324 static int
325 macho_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
326 uintptr_t pc ATTRIBUTE_UNUSED,
327 backtrace_full_callback callback ATTRIBUTE_UNUSED,
328 backtrace_error_callback error_callback, void *data)
330 error_callback (data, "no debug info in Mach-O executable (make sure to compile with -g; may need to run dsymutil)", -1);
331 return 0;
334 /* A dummy callback function used when we can't find a symbol
335 table. */
337 static void
338 macho_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,
339 uintptr_t addr ATTRIBUTE_UNUSED,
340 backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,
341 backtrace_error_callback error_callback, void *data)
343 error_callback (data, "no symbol table in Mach-O executable", -1);
346 /* Add a single DWARF section to DWARF_SECTIONS, if we need the
347 section. Returns 1 on success, 0 on failure. */
349 static int
350 macho_add_dwarf_section (struct backtrace_state *state, int descriptor,
351 const char *sectname, uint32_t offset, uint64_t size,
352 backtrace_error_callback error_callback, void *data,
353 struct dwarf_sections *dwarf_sections)
355 int i;
357 for (i = 0; i < (int) DEBUG_MAX; ++i)
359 if (dwarf_section_names[i][0] != '\0'
360 && strncmp (sectname, dwarf_section_names[i], MACH_O_NAMELEN) == 0)
362 struct backtrace_view section_view;
364 /* FIXME: Perhaps it would be better to try to use a single
365 view to read all the DWARF data, as we try to do for
366 ELF. */
368 if (!backtrace_get_view (state, descriptor, offset, size,
369 error_callback, data, &section_view))
370 return 0;
371 dwarf_sections->data[i] = (const unsigned char *) section_view.data;
372 dwarf_sections->size[i] = size;
373 break;
376 return 1;
379 /* Collect DWARF sections from a DWARF segment. Returns 1 on success,
380 0 on failure. */
382 static int
383 macho_add_dwarf_segment (struct backtrace_state *state, int descriptor,
384 off_t offset, unsigned int cmd, const char *psecs,
385 size_t sizesecs, unsigned int nsects,
386 backtrace_error_callback error_callback, void *data,
387 struct dwarf_sections *dwarf_sections)
389 size_t sec_header_size;
390 size_t secoffset;
391 unsigned int i;
393 switch (cmd)
395 case MACH_O_LC_SEGMENT:
396 sec_header_size = sizeof (struct macho_section);
397 break;
398 case MACH_O_LC_SEGMENT_64:
399 sec_header_size = sizeof (struct macho_section_64);
400 break;
401 default:
402 abort ();
405 secoffset = 0;
406 for (i = 0; i < nsects; ++i)
408 if (secoffset + sec_header_size > sizesecs)
410 error_callback (data, "section overflow withing segment", 0);
411 return 0;
414 switch (cmd)
416 case MACH_O_LC_SEGMENT:
418 struct macho_section section;
420 memcpy (&section, psecs + secoffset, sizeof section);
421 macho_add_dwarf_section (state, descriptor, section.sectname,
422 offset + section.offset, section.size,
423 error_callback, data, dwarf_sections);
425 break;
427 case MACH_O_LC_SEGMENT_64:
429 struct macho_section_64 section;
431 memcpy (&section, psecs + secoffset, sizeof section);
432 macho_add_dwarf_section (state, descriptor, section.sectname,
433 offset + section.offset, section.size,
434 error_callback, data, dwarf_sections);
436 break;
438 default:
439 abort ();
442 secoffset += sec_header_size;
445 return 1;
448 /* Compare struct macho_symbol for qsort. */
450 static int
451 macho_symbol_compare (const void *v1, const void *v2)
453 const struct macho_symbol *m1 = (const struct macho_symbol *) v1;
454 const struct macho_symbol *m2 = (const struct macho_symbol *) v2;
456 if (m1->address < m2->address)
457 return -1;
458 else if (m1->address > m2->address)
459 return 1;
460 else
461 return 0;
464 /* Compare an address against a macho_symbol for bsearch. We allocate
465 one extra entry in the array so that this can safely look at the
466 next entry. */
468 static int
469 macho_symbol_search (const void *vkey, const void *ventry)
471 const uintptr_t *key = (const uintptr_t *) vkey;
472 const struct macho_symbol *entry = (const struct macho_symbol *) ventry;
473 uintptr_t addr;
475 addr = *key;
476 if (addr < entry->address)
477 return -1;
478 else if (entry->name[0] == '\0'
479 && entry->address == ~(uintptr_t) 0)
480 return -1;
481 else if ((entry + 1)->name[0] == '\0'
482 && (entry + 1)->address == ~(uintptr_t) 0)
483 return -1;
484 else if (addr >= (entry + 1)->address)
485 return 1;
486 else
487 return 0;
490 /* Return whether the symbol type field indicates a symbol table entry
491 that we care about: a function or data symbol. */
493 static int
494 macho_defined_symbol (uint8_t type)
496 if ((type & MACH_O_N_STAB) != 0)
497 return 0;
498 switch (type & MACH_O_N_TYPE)
500 case MACH_O_N_UNDF:
501 return 0;
502 case MACH_O_N_ABS:
503 return 1;
504 case MACH_O_N_SECT:
505 return 1;
506 default:
507 return 0;
511 /* Add symbol table information for a Mach-O file. */
513 static int
514 macho_add_symtab (struct backtrace_state *state, int descriptor,
515 struct libbacktrace_base_address base_address, int is_64,
516 off_t symoff, unsigned int nsyms, off_t stroff,
517 unsigned int strsize,
518 backtrace_error_callback error_callback, void *data)
520 size_t symsize;
521 struct backtrace_view sym_view;
522 int sym_view_valid;
523 struct backtrace_view str_view;
524 int str_view_valid;
525 size_t ndefs;
526 size_t symtaboff;
527 unsigned int i;
528 size_t macho_symbol_size;
529 struct macho_symbol *macho_symbols;
530 unsigned int j;
531 struct macho_syminfo_data *sdata;
533 sym_view_valid = 0;
534 str_view_valid = 0;
535 macho_symbol_size = 0;
536 macho_symbols = NULL;
538 if (is_64)
539 symsize = sizeof (struct macho_nlist_64);
540 else
541 symsize = sizeof (struct macho_nlist);
543 if (!backtrace_get_view (state, descriptor, symoff, nsyms * symsize,
544 error_callback, data, &sym_view))
545 goto fail;
546 sym_view_valid = 1;
548 if (!backtrace_get_view (state, descriptor, stroff, strsize,
549 error_callback, data, &str_view))
550 return 0;
551 str_view_valid = 1;
553 ndefs = 0;
554 symtaboff = 0;
555 for (i = 0; i < nsyms; ++i, symtaboff += symsize)
557 if (is_64)
559 struct macho_nlist_64 nlist;
561 memcpy (&nlist, (const char *) sym_view.data + symtaboff,
562 sizeof nlist);
563 if (macho_defined_symbol (nlist.n_type))
564 ++ndefs;
566 else
568 struct macho_nlist nlist;
570 memcpy (&nlist, (const char *) sym_view.data + symtaboff,
571 sizeof nlist);
572 if (macho_defined_symbol (nlist.n_type))
573 ++ndefs;
577 /* Add 1 to ndefs to make room for a sentinel. */
578 macho_symbol_size = (ndefs + 1) * sizeof (struct macho_symbol);
579 macho_symbols = ((struct macho_symbol *)
580 backtrace_alloc (state, macho_symbol_size, error_callback,
581 data));
582 if (macho_symbols == NULL)
583 goto fail;
585 j = 0;
586 symtaboff = 0;
587 for (i = 0; i < nsyms; ++i, symtaboff += symsize)
589 uint32_t strx;
590 uint64_t value;
591 const char *name;
593 strx = 0;
594 value = 0;
595 if (is_64)
597 struct macho_nlist_64 nlist;
599 memcpy (&nlist, (const char *) sym_view.data + symtaboff,
600 sizeof nlist);
601 if (!macho_defined_symbol (nlist.n_type))
602 continue;
604 strx = nlist.n_strx;
605 value = nlist.n_value;
607 else
609 struct macho_nlist nlist;
611 memcpy (&nlist, (const char *) sym_view.data + symtaboff,
612 sizeof nlist);
613 if (!macho_defined_symbol (nlist.n_type))
614 continue;
616 strx = nlist.n_strx;
617 value = nlist.n_value;
620 if (strx >= strsize)
622 error_callback (data, "symbol string index out of range", 0);
623 goto fail;
626 name = (const char *) str_view.data + strx;
627 if (name[0] == '_')
628 ++name;
629 macho_symbols[j].name = name;
630 macho_symbols[j].address = libbacktrace_add_base (value, base_address);
631 ++j;
634 sdata = ((struct macho_syminfo_data *)
635 backtrace_alloc (state, sizeof *sdata, error_callback, data));
636 if (sdata == NULL)
637 goto fail;
639 /* We need to keep the string table since it holds the names, but we
640 can release the symbol table. */
642 backtrace_release_view (state, &sym_view, error_callback, data);
643 sym_view_valid = 0;
644 str_view_valid = 0;
646 /* Add a trailing sentinel symbol. */
647 macho_symbols[j].name = "";
648 macho_symbols[j].address = ~(uintptr_t) 0;
650 backtrace_qsort (macho_symbols, ndefs + 1, sizeof (struct macho_symbol),
651 macho_symbol_compare);
653 sdata->next = NULL;
654 sdata->symbols = macho_symbols;
655 sdata->count = ndefs;
657 if (!state->threaded)
659 struct macho_syminfo_data **pp;
661 for (pp = (struct macho_syminfo_data **) (void *) &state->syminfo_data;
662 *pp != NULL;
663 pp = &(*pp)->next)
665 *pp = sdata;
667 else
669 while (1)
671 struct macho_syminfo_data **pp;
673 pp = (struct macho_syminfo_data **) (void *) &state->syminfo_data;
675 while (1)
677 struct macho_syminfo_data *p;
679 p = backtrace_atomic_load_pointer (pp);
680 if (p == NULL)
681 break;
683 pp = &p->next;
686 if (__sync_bool_compare_and_swap (pp, NULL, sdata))
687 break;
691 return 1;
693 fail:
694 if (macho_symbols != NULL)
695 backtrace_free (state, macho_symbols, macho_symbol_size,
696 error_callback, data);
697 if (sym_view_valid)
698 backtrace_release_view (state, &sym_view, error_callback, data);
699 if (str_view_valid)
700 backtrace_release_view (state, &str_view, error_callback, data);
701 return 0;
704 /* Return the symbol name and value for an ADDR. */
706 static void
707 macho_syminfo (struct backtrace_state *state, uintptr_t addr,
708 backtrace_syminfo_callback callback,
709 backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
710 void *data)
712 struct macho_syminfo_data *sdata;
713 struct macho_symbol *sym;
715 sym = NULL;
716 if (!state->threaded)
718 for (sdata = (struct macho_syminfo_data *) state->syminfo_data;
719 sdata != NULL;
720 sdata = sdata->next)
722 sym = ((struct macho_symbol *)
723 bsearch (&addr, sdata->symbols, sdata->count,
724 sizeof (struct macho_symbol), macho_symbol_search));
725 if (sym != NULL)
726 break;
729 else
731 struct macho_syminfo_data **pp;
733 pp = (struct macho_syminfo_data **) (void *) &state->syminfo_data;
734 while (1)
736 sdata = backtrace_atomic_load_pointer (pp);
737 if (sdata == NULL)
738 break;
740 sym = ((struct macho_symbol *)
741 bsearch (&addr, sdata->symbols, sdata->count,
742 sizeof (struct macho_symbol), macho_symbol_search));
743 if (sym != NULL)
744 break;
746 pp = &sdata->next;
750 if (sym == NULL)
751 callback (data, addr, NULL, 0, 0);
752 else
753 callback (data, addr, sym->name, sym->address, 0);
756 /* Look through a fat file to find the relevant executable. Returns 1
757 on success, 0 on failure (in both cases descriptor is closed). */
759 static int
760 macho_add_fat (struct backtrace_state *state, const char *filename,
761 int descriptor, int swapped, off_t offset,
762 const unsigned char *match_uuid,
763 struct libbacktrace_base_address base_address,
764 int skip_symtab, uint32_t nfat_arch, int is_64,
765 backtrace_error_callback error_callback, void *data,
766 fileline *fileline_fn, int *found_sym)
768 int arch_view_valid;
769 unsigned int cputype;
770 size_t arch_size;
771 struct backtrace_view arch_view;
772 unsigned int i;
774 arch_view_valid = 0;
776 #if defined (__x86_64__)
777 cputype = MACH_O_CPU_TYPE_X86_64;
778 #elif defined (__i386__)
779 cputype = MACH_O_CPU_TYPE_X86;
780 #elif defined (__aarch64__)
781 cputype = MACH_O_CPU_TYPE_ARM64;
782 #elif defined (__arm__)
783 cputype = MACH_O_CPU_TYPE_ARM;
784 #elif defined (__ppc__)
785 cputype = MACH_O_CPU_TYPE_PPC;
786 #elif defined (__ppc64__)
787 cputype = MACH_O_CPU_TYPE_PPC64;
788 #else
789 error_callback (data, "unknown Mach-O architecture", 0);
790 goto fail;
791 #endif
793 if (is_64)
794 arch_size = sizeof (struct macho_fat_arch_64);
795 else
796 arch_size = sizeof (struct macho_fat_arch);
798 if (!backtrace_get_view (state, descriptor, offset,
799 nfat_arch * arch_size,
800 error_callback, data, &arch_view))
801 goto fail;
803 for (i = 0; i < nfat_arch; ++i)
805 uint32_t fcputype;
806 uint64_t foffset;
808 if (is_64)
810 struct macho_fat_arch_64 fat_arch_64;
812 memcpy (&fat_arch_64,
813 (const char *) arch_view.data + i * arch_size,
814 arch_size);
815 fcputype = fat_arch_64.cputype;
816 foffset = fat_arch_64.offset;
817 if (swapped)
819 fcputype = __builtin_bswap32 (fcputype);
820 foffset = __builtin_bswap64 (foffset);
823 else
825 struct macho_fat_arch fat_arch_32;
827 memcpy (&fat_arch_32,
828 (const char *) arch_view.data + i * arch_size,
829 arch_size);
830 fcputype = fat_arch_32.cputype;
831 foffset = (uint64_t) fat_arch_32.offset;
832 if (swapped)
834 fcputype = __builtin_bswap32 (fcputype);
835 foffset = (uint64_t) __builtin_bswap32 ((uint32_t) foffset);
839 if (fcputype == cputype)
841 /* FIXME: What about cpusubtype? */
842 backtrace_release_view (state, &arch_view, error_callback, data);
843 return macho_add (state, filename, descriptor, foffset, match_uuid,
844 base_address, skip_symtab, error_callback, data,
845 fileline_fn, found_sym);
849 error_callback (data, "could not find executable in fat file", 0);
851 fail:
852 if (arch_view_valid)
853 backtrace_release_view (state, &arch_view, error_callback, data);
854 if (descriptor != -1)
855 backtrace_close (descriptor, error_callback, data);
856 return 0;
859 /* Look for the dsym file for FILENAME. This is called if FILENAME
860 does not have debug info or a symbol table. Returns 1 on success,
861 0 on failure. */
863 static int
864 macho_add_dsym (struct backtrace_state *state, const char *filename,
865 struct libbacktrace_base_address base_address,
866 const unsigned char *uuid,
867 backtrace_error_callback error_callback, void *data,
868 fileline* fileline_fn)
870 const char *p;
871 const char *dirname;
872 char *diralc;
873 size_t dirnamelen;
874 const char *basename;
875 size_t basenamelen;
876 const char *dsymsuffixdir;
877 size_t dsymsuffixdirlen;
878 size_t dsymlen;
879 char *dsym;
880 char *ps;
881 int d;
882 int does_not_exist;
883 int dummy_found_sym;
885 diralc = NULL;
886 dirnamelen = 0;
887 dsym = NULL;
888 dsymlen = 0;
890 p = strrchr (filename, '/');
891 if (p == NULL)
893 dirname = ".";
894 dirnamelen = 1;
895 basename = filename;
896 basenamelen = strlen (basename);
897 diralc = NULL;
899 else
901 dirnamelen = p - filename;
902 diralc = backtrace_alloc (state, dirnamelen + 1, error_callback, data);
903 if (diralc == NULL)
904 goto fail;
905 memcpy (diralc, filename, dirnamelen);
906 diralc[dirnamelen] = '\0';
907 dirname = diralc;
908 basename = p + 1;
909 basenamelen = strlen (basename);
912 dsymsuffixdir = ".dSYM/Contents/Resources/DWARF/";
913 dsymsuffixdirlen = strlen (dsymsuffixdir);
915 dsymlen = (dirnamelen
917 + basenamelen
918 + dsymsuffixdirlen
919 + basenamelen
920 + 1);
921 dsym = backtrace_alloc (state, dsymlen, error_callback, data);
922 if (dsym == NULL)
923 goto fail;
925 ps = dsym;
926 memcpy (ps, dirname, dirnamelen);
927 ps += dirnamelen;
928 *ps++ = '/';
929 memcpy (ps, basename, basenamelen);
930 ps += basenamelen;
931 memcpy (ps, dsymsuffixdir, dsymsuffixdirlen);
932 ps += dsymsuffixdirlen;
933 memcpy (ps, basename, basenamelen);
934 ps += basenamelen;
935 *ps = '\0';
937 if (diralc != NULL)
939 backtrace_free (state, diralc, dirnamelen + 1, error_callback, data);
940 diralc = NULL;
943 d = backtrace_open (dsym, error_callback, data, &does_not_exist);
944 if (d < 0)
946 /* The file does not exist, so we can't read the debug info.
947 Just return success. */
948 backtrace_free (state, dsym, dsymlen, error_callback, data);
949 return 1;
952 if (!macho_add (state, dsym, d, 0, uuid, base_address, 1,
953 error_callback, data, fileline_fn, &dummy_found_sym))
954 goto fail;
956 backtrace_free (state, dsym, dsymlen, error_callback, data);
958 return 1;
960 fail:
961 if (dsym != NULL)
962 backtrace_free (state, dsym, dsymlen, error_callback, data);
963 if (diralc != NULL)
964 backtrace_free (state, diralc, dirnamelen, error_callback, data);
965 return 0;
968 /* Add the backtrace data for a Macho-O file. Returns 1 on success, 0
969 on failure (in both cases descriptor is closed).
971 FILENAME: the name of the executable.
972 DESCRIPTOR: an open descriptor for the executable, closed here.
973 OFFSET: the offset within the file of this executable, for fat files.
974 MATCH_UUID: if not NULL, UUID that must match.
975 BASE_ADDRESS: the load address of the executable.
976 SKIP_SYMTAB: if non-zero, ignore the symbol table; used for dSYM files.
977 FILELINE_FN: set to the fileline function, by backtrace_dwarf_add.
978 FOUND_SYM: set to non-zero if we found the symbol table.
981 static int
982 macho_add (struct backtrace_state *state, const char *filename, int descriptor,
983 off_t offset, const unsigned char *match_uuid,
984 struct libbacktrace_base_address base_address, int skip_symtab,
985 backtrace_error_callback error_callback, void *data,
986 fileline *fileline_fn, int *found_sym)
988 struct backtrace_view header_view;
989 struct macho_header_32 header;
990 off_t hdroffset;
991 int is_64;
992 struct backtrace_view cmds_view;
993 int cmds_view_valid;
994 struct dwarf_sections dwarf_sections;
995 int have_dwarf;
996 unsigned char uuid[MACH_O_UUID_LEN];
997 int have_uuid;
998 size_t cmdoffset;
999 unsigned int i;
1001 *found_sym = 0;
1003 cmds_view_valid = 0;
1005 /* The 32-bit and 64-bit file headers start out the same, so we can
1006 just always read the 32-bit version. A fat header is shorter but
1007 it will always be followed by data, so it's OK to read extra. */
1009 if (!backtrace_get_view (state, descriptor, offset,
1010 sizeof (struct macho_header_32),
1011 error_callback, data, &header_view))
1012 goto fail;
1014 memcpy (&header, header_view.data, sizeof header);
1016 backtrace_release_view (state, &header_view, error_callback, data);
1018 switch (header.magic)
1020 case MACH_O_MH_MAGIC_32:
1021 is_64 = 0;
1022 hdroffset = offset + sizeof (struct macho_header_32);
1023 break;
1024 case MACH_O_MH_MAGIC_64:
1025 is_64 = 1;
1026 hdroffset = offset + sizeof (struct macho_header_64);
1027 break;
1028 case MACH_O_MH_MAGIC_FAT:
1029 case MACH_O_MH_MAGIC_FAT_64:
1031 struct macho_header_fat fat_header;
1033 hdroffset = offset + sizeof (struct macho_header_fat);
1034 memcpy (&fat_header, &header, sizeof fat_header);
1035 return macho_add_fat (state, filename, descriptor, 0, hdroffset,
1036 match_uuid, base_address, skip_symtab,
1037 fat_header.nfat_arch,
1038 header.magic == MACH_O_MH_MAGIC_FAT_64,
1039 error_callback, data, fileline_fn, found_sym);
1041 case MACH_O_MH_CIGAM_FAT:
1042 case MACH_O_MH_CIGAM_FAT_64:
1044 struct macho_header_fat fat_header;
1045 uint32_t nfat_arch;
1047 hdroffset = offset + sizeof (struct macho_header_fat);
1048 memcpy (&fat_header, &header, sizeof fat_header);
1049 nfat_arch = __builtin_bswap32 (fat_header.nfat_arch);
1050 return macho_add_fat (state, filename, descriptor, 1, hdroffset,
1051 match_uuid, base_address, skip_symtab,
1052 nfat_arch,
1053 header.magic == MACH_O_MH_CIGAM_FAT_64,
1054 error_callback, data, fileline_fn, found_sym);
1056 default:
1057 error_callback (data, "executable file is not in Mach-O format", 0);
1058 goto fail;
1061 switch (header.filetype)
1063 case MACH_O_MH_EXECUTE:
1064 case MACH_O_MH_DYLIB:
1065 case MACH_O_MH_DSYM:
1066 break;
1067 default:
1068 error_callback (data, "executable file is not an executable", 0);
1069 goto fail;
1072 if (!backtrace_get_view (state, descriptor, hdroffset, header.sizeofcmds,
1073 error_callback, data, &cmds_view))
1074 goto fail;
1075 cmds_view_valid = 1;
1077 memset (&dwarf_sections, 0, sizeof dwarf_sections);
1078 have_dwarf = 0;
1079 memset (&uuid, 0, sizeof uuid);
1080 have_uuid = 0;
1082 cmdoffset = 0;
1083 for (i = 0; i < header.ncmds; ++i)
1085 const char *pcmd;
1086 struct macho_load_command load_command;
1088 if (cmdoffset + sizeof load_command > header.sizeofcmds)
1089 break;
1091 pcmd = (const char *) cmds_view.data + cmdoffset;
1092 memcpy (&load_command, pcmd, sizeof load_command);
1094 switch (load_command.cmd)
1096 case MACH_O_LC_SEGMENT:
1098 struct macho_segment_command segcmd;
1100 memcpy (&segcmd, pcmd, sizeof segcmd);
1101 if (memcmp (segcmd.segname,
1102 "__DWARF\0\0\0\0\0\0\0\0\0",
1103 MACH_O_NAMELEN) == 0)
1105 if (!macho_add_dwarf_segment (state, descriptor, offset,
1106 load_command.cmd,
1107 pcmd + sizeof segcmd,
1108 (load_command.cmdsize
1109 - sizeof segcmd),
1110 segcmd.nsects, error_callback,
1111 data, &dwarf_sections))
1112 goto fail;
1113 have_dwarf = 1;
1116 break;
1118 case MACH_O_LC_SEGMENT_64:
1120 struct macho_segment_64_command segcmd;
1122 memcpy (&segcmd, pcmd, sizeof segcmd);
1123 if (memcmp (segcmd.segname,
1124 "__DWARF\0\0\0\0\0\0\0\0\0",
1125 MACH_O_NAMELEN) == 0)
1127 if (!macho_add_dwarf_segment (state, descriptor, offset,
1128 load_command.cmd,
1129 pcmd + sizeof segcmd,
1130 (load_command.cmdsize
1131 - sizeof segcmd),
1132 segcmd.nsects, error_callback,
1133 data, &dwarf_sections))
1134 goto fail;
1135 have_dwarf = 1;
1138 break;
1140 case MACH_O_LC_SYMTAB:
1141 if (!skip_symtab)
1143 struct macho_symtab_command symcmd;
1145 memcpy (&symcmd, pcmd, sizeof symcmd);
1146 if (!macho_add_symtab (state, descriptor, base_address, is_64,
1147 offset + symcmd.symoff, symcmd.nsyms,
1148 offset + symcmd.stroff, symcmd.strsize,
1149 error_callback, data))
1150 goto fail;
1152 *found_sym = 1;
1154 break;
1156 case MACH_O_LC_UUID:
1158 struct macho_uuid_command uuidcmd;
1160 memcpy (&uuidcmd, pcmd, sizeof uuidcmd);
1161 memcpy (&uuid[0], &uuidcmd.uuid[0], MACH_O_UUID_LEN);
1162 have_uuid = 1;
1164 break;
1166 default:
1167 break;
1170 cmdoffset += load_command.cmdsize;
1173 if (!backtrace_close (descriptor, error_callback, data))
1174 goto fail;
1175 descriptor = -1;
1177 backtrace_release_view (state, &cmds_view, error_callback, data);
1178 cmds_view_valid = 0;
1180 if (match_uuid != NULL)
1182 /* If we don't have a UUID, or it doesn't match, just ignore
1183 this file. */
1184 if (!have_uuid
1185 || memcmp (match_uuid, &uuid[0], MACH_O_UUID_LEN) != 0)
1186 return 1;
1189 if (have_dwarf)
1191 int is_big_endian;
1193 is_big_endian = 0;
1194 #if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)
1195 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
1196 is_big_endian = 1;
1197 #endif
1198 #endif
1200 if (!backtrace_dwarf_add (state, base_address, &dwarf_sections,
1201 is_big_endian, NULL, error_callback, data,
1202 fileline_fn, NULL))
1203 goto fail;
1206 if (!have_dwarf && have_uuid)
1208 if (!macho_add_dsym (state, filename, base_address, &uuid[0],
1209 error_callback, data, fileline_fn))
1210 goto fail;
1213 return 1;
1215 fail:
1216 if (cmds_view_valid)
1217 backtrace_release_view (state, &cmds_view, error_callback, data);
1218 if (descriptor != -1)
1219 backtrace_close (descriptor, error_callback, data);
1220 return 0;
1223 #ifdef HAVE_MACH_O_DYLD_H
1225 /* Initialize the backtrace data we need from a Mach-O executable
1226 using the dyld support functions. This closes descriptor. */
1229 backtrace_initialize (struct backtrace_state *state, const char *filename,
1230 int descriptor, backtrace_error_callback error_callback,
1231 void *data, fileline *fileline_fn)
1233 uint32_t c;
1234 uint32_t i;
1235 int closed_descriptor;
1236 int found_sym;
1237 fileline macho_fileline_fn;
1239 closed_descriptor = 0;
1240 found_sym = 0;
1241 macho_fileline_fn = macho_nodebug;
1243 c = _dyld_image_count ();
1244 for (i = 0; i < c; ++i)
1246 struct libbacktrace_base_address base_address;
1247 const char *name;
1248 int d;
1249 fileline mff;
1250 int mfs;
1252 name = _dyld_get_image_name (i);
1253 if (name == NULL)
1254 continue;
1256 if (strcmp (name, filename) == 0 && !closed_descriptor)
1258 d = descriptor;
1259 closed_descriptor = 1;
1261 else
1263 int does_not_exist;
1265 d = backtrace_open (name, error_callback, data, &does_not_exist);
1266 if (d < 0)
1267 continue;
1270 base_address.m = _dyld_get_image_vmaddr_slide (i);
1272 mff = macho_nodebug;
1273 if (!macho_add (state, name, d, 0, NULL, base_address, 0,
1274 error_callback, data, &mff, &mfs))
1275 continue;
1277 if (mff != macho_nodebug)
1278 macho_fileline_fn = mff;
1279 if (mfs)
1280 found_sym = 1;
1283 if (!closed_descriptor)
1284 backtrace_close (descriptor, error_callback, data);
1286 if (!state->threaded)
1288 if (found_sym)
1289 state->syminfo_fn = macho_syminfo;
1290 else if (state->syminfo_fn == NULL)
1291 state->syminfo_fn = macho_nosyms;
1293 else
1295 if (found_sym)
1296 backtrace_atomic_store_pointer (&state->syminfo_fn, macho_syminfo);
1297 else
1298 (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
1299 macho_nosyms);
1302 if (!state->threaded)
1303 *fileline_fn = state->fileline_fn;
1304 else
1305 *fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
1307 if (*fileline_fn == NULL || *fileline_fn == macho_nodebug)
1308 *fileline_fn = macho_fileline_fn;
1310 return 1;
1313 #else /* !defined (HAVE_MACH_O_DYLD_H) */
1315 /* Initialize the backtrace data we need from a Mach-O executable
1316 without using the dyld support functions. This closes
1317 descriptor. */
1320 backtrace_initialize (struct backtrace_state *state, const char *filename,
1321 int descriptor, backtrace_error_callback error_callback,
1322 void *data, fileline *fileline_fn)
1324 fileline macho_fileline_fn;
1325 struct libbacktrace_base_address zero_base_address;
1326 int found_sym;
1328 macho_fileline_fn = macho_nodebug;
1329 memset (&zero_base_address, 0, sizeof zero_base_address);
1330 if (!macho_add (state, filename, descriptor, 0, NULL, zero_base_address, 0,
1331 error_callback, data, &macho_fileline_fn, &found_sym))
1332 return 0;
1334 if (!state->threaded)
1336 if (found_sym)
1337 state->syminfo_fn = macho_syminfo;
1338 else if (state->syminfo_fn == NULL)
1339 state->syminfo_fn = macho_nosyms;
1341 else
1343 if (found_sym)
1344 backtrace_atomic_store_pointer (&state->syminfo_fn, macho_syminfo);
1345 else
1346 (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
1347 macho_nosyms);
1350 if (!state->threaded)
1351 *fileline_fn = state->fileline_fn;
1352 else
1353 *fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
1355 if (*fileline_fn == NULL || *fileline_fn == macho_nodebug)
1356 *fileline_fn = macho_fileline_fn;
1358 return 1;
1361 #endif /* !defined (HAVE_MACH_O_DYLD_H) */