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
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
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. */
35 #include <sys/types.h>
40 #ifdef HAVE_MACH_O_DYLD_H
41 #include <mach-o/dyld.h>
44 #include "backtrace.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
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
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. */
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 */
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 */
250 /* 32-bit symbol data. */
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_EXT 0x01 /* Extern symbol */
275 #define MACH_O_N_ABS 0x02 /* Absolute symbol */
276 #define MACH_O_N_SECT 0x0e /* Defined in section */
278 #define MACH_O_N_TYPE 0x0e /* Mask for type bits */
279 #define MACH_O_N_STAB 0xe0 /* Stabs debugging symbol */
281 /* Information we keep for a Mach-O symbol. */
285 const char *name
; /* Symbol name */
286 uintptr_t address
; /* Symbol address */
289 /* Information to pass to macho_syminfo. */
291 struct macho_syminfo_data
293 struct macho_syminfo_data
*next
; /* Next module */
294 struct macho_symbol
*symbols
; /* Symbols sorted by address */
295 size_t count
; /* Number of symbols */
298 /* Names of sections, indexed by enum dwarf_section in internal.h. */
300 static const char * const dwarf_section_names
[DEBUG_MAX
] =
309 "", /* DEBUG_LINE_STR */
313 /* Forward declaration. */
315 static int macho_add (struct backtrace_state
*, const char *, int, off_t
,
316 const unsigned char *, uintptr_t, int,
317 backtrace_error_callback
, void *, fileline
*, int *);
319 /* A dummy callback function used when we can't find any debug info. */
322 macho_nodebug (struct backtrace_state
*state ATTRIBUTE_UNUSED
,
323 uintptr_t pc ATTRIBUTE_UNUSED
,
324 backtrace_full_callback callback ATTRIBUTE_UNUSED
,
325 backtrace_error_callback error_callback
, void *data
)
327 error_callback (data
, "no debug info in Mach-O executable", -1);
331 /* A dummy callback function used when we can't find a symbol
335 macho_nosyms (struct backtrace_state
*state ATTRIBUTE_UNUSED
,
336 uintptr_t addr ATTRIBUTE_UNUSED
,
337 backtrace_syminfo_callback callback ATTRIBUTE_UNUSED
,
338 backtrace_error_callback error_callback
, void *data
)
340 error_callback (data
, "no symbol table in Mach-O executable", -1);
343 /* Add a single DWARF section to DWARF_SECTIONS, if we need the
344 section. Returns 1 on success, 0 on failure. */
347 macho_add_dwarf_section (struct backtrace_state
*state
, int descriptor
,
348 const char *sectname
, uint32_t offset
, uint64_t size
,
349 backtrace_error_callback error_callback
, void *data
,
350 struct dwarf_sections
*dwarf_sections
)
354 for (i
= 0; i
< (int) DEBUG_MAX
; ++i
)
356 if (dwarf_section_names
[i
][0] != '\0'
357 && strncmp (sectname
, dwarf_section_names
[i
], MACH_O_NAMELEN
) == 0)
359 struct backtrace_view section_view
;
361 /* FIXME: Perhaps it would be better to try to use a single
362 view to read all the DWARF data, as we try to do for
365 if (!backtrace_get_view (state
, descriptor
, offset
, size
,
366 error_callback
, data
, §ion_view
))
368 dwarf_sections
->data
[i
] = (const unsigned char *) section_view
.data
;
369 dwarf_sections
->size
[i
] = size
;
376 /* Collect DWARF sections from a DWARF segment. Returns 1 on success,
380 macho_add_dwarf_segment (struct backtrace_state
*state
, int descriptor
,
381 off_t offset
, unsigned int cmd
, const char *psecs
,
382 size_t sizesecs
, unsigned int nsects
,
383 backtrace_error_callback error_callback
, void *data
,
384 struct dwarf_sections
*dwarf_sections
)
386 size_t sec_header_size
;
392 case MACH_O_LC_SEGMENT
:
393 sec_header_size
= sizeof (struct macho_section
);
395 case MACH_O_LC_SEGMENT_64
:
396 sec_header_size
= sizeof (struct macho_section_64
);
403 for (i
= 0; i
< nsects
; ++i
)
405 if (secoffset
+ sec_header_size
> sizesecs
)
407 error_callback (data
, "section overflow withing segment", 0);
413 case MACH_O_LC_SEGMENT
:
415 struct macho_section section
;
417 memcpy (§ion
, psecs
+ secoffset
, sizeof section
);
418 macho_add_dwarf_section (state
, descriptor
, section
.sectname
,
419 offset
+ section
.offset
, section
.size
,
420 error_callback
, data
, dwarf_sections
);
424 case MACH_O_LC_SEGMENT_64
:
426 struct macho_section_64 section
;
428 memcpy (§ion
, psecs
+ secoffset
, sizeof section
);
429 macho_add_dwarf_section (state
, descriptor
, section
.sectname
,
430 offset
+ section
.offset
, section
.size
,
431 error_callback
, data
, dwarf_sections
);
439 secoffset
+= sec_header_size
;
445 /* Compare struct macho_symbol for qsort. */
448 macho_symbol_compare (const void *v1
, const void *v2
)
450 const struct macho_symbol
*m1
= (const struct macho_symbol
*) v1
;
451 const struct macho_symbol
*m2
= (const struct macho_symbol
*) v2
;
453 if (m1
->address
< m2
->address
)
455 else if (m1
->address
> m2
->address
)
461 /* Compare an address against a macho_symbol for bsearch. We allocate
462 one extra entry in the array so that this can safely look at the
466 macho_symbol_search (const void *vkey
, const void *ventry
)
468 const uintptr_t *key
= (const uintptr_t *) vkey
;
469 const struct macho_symbol
*entry
= (const struct macho_symbol
*) ventry
;
473 if (addr
< entry
->address
)
475 else if (entry
->name
[0] == '\0'
476 && entry
->address
== ~(uintptr_t) 0)
478 else if ((entry
+ 1)->name
[0] == '\0'
479 && (entry
+ 1)->address
== ~(uintptr_t) 0)
481 else if (addr
>= (entry
+ 1)->address
)
487 /* Return whether the symbol type field indicates a symbol table entry
488 that we care about: a function or data symbol. */
491 macho_defined_symbol (uint8_t type
)
493 if ((type
& MACH_O_N_STAB
) != 0)
495 if ((type
& MACH_O_N_EXT
) != 0)
497 switch (type
& MACH_O_N_TYPE
)
508 /* Add symbol table information for a Mach-O file. */
511 macho_add_symtab (struct backtrace_state
*state
, int descriptor
,
512 uintptr_t base_address
, int is_64
,
513 off_t symoff
, unsigned int nsyms
, off_t stroff
,
514 unsigned int strsize
,
515 backtrace_error_callback error_callback
, void *data
)
518 struct backtrace_view sym_view
;
520 struct backtrace_view str_view
;
525 size_t macho_symbol_size
;
526 struct macho_symbol
*macho_symbols
;
528 struct macho_syminfo_data
*sdata
;
532 macho_symbol_size
= 0;
533 macho_symbols
= NULL
;
536 symsize
= sizeof (struct macho_nlist_64
);
538 symsize
= sizeof (struct macho_nlist
);
540 if (!backtrace_get_view (state
, descriptor
, symoff
, nsyms
* symsize
,
541 error_callback
, data
, &sym_view
))
545 if (!backtrace_get_view (state
, descriptor
, stroff
, strsize
,
546 error_callback
, data
, &str_view
))
552 for (i
= 0; i
< nsyms
; ++i
, symtaboff
+= symsize
)
556 struct macho_nlist_64 nlist
;
558 memcpy (&nlist
, (const char *) sym_view
.data
+ symtaboff
,
560 if (macho_defined_symbol (nlist
.n_type
))
565 struct macho_nlist nlist
;
567 memcpy (&nlist
, (const char *) sym_view
.data
+ symtaboff
,
569 if (macho_defined_symbol (nlist
.n_type
))
574 /* Add 1 to ndefs to make room for a sentinel. */
575 macho_symbol_size
= (ndefs
+ 1) * sizeof (struct macho_symbol
);
576 macho_symbols
= ((struct macho_symbol
*)
577 backtrace_alloc (state
, macho_symbol_size
, error_callback
,
579 if (macho_symbols
== NULL
)
584 for (i
= 0; i
< nsyms
; ++i
, symtaboff
+= symsize
)
594 struct macho_nlist_64 nlist
;
596 memcpy (&nlist
, (const char *) sym_view
.data
+ symtaboff
,
598 if (!macho_defined_symbol (nlist
.n_type
))
602 value
= nlist
.n_value
;
606 struct macho_nlist nlist
;
608 memcpy (&nlist
, (const char *) sym_view
.data
+ symtaboff
,
610 if (!macho_defined_symbol (nlist
.n_type
))
614 value
= nlist
.n_value
;
619 error_callback (data
, "symbol string index out of range", 0);
623 name
= (const char *) str_view
.data
+ strx
;
626 macho_symbols
[j
].name
= name
;
627 macho_symbols
[j
].address
= value
+ base_address
;
631 sdata
= ((struct macho_syminfo_data
*)
632 backtrace_alloc (state
, sizeof *sdata
, error_callback
, data
));
636 /* We need to keep the string table since it holds the names, but we
637 can release the symbol table. */
639 backtrace_release_view (state
, &sym_view
, error_callback
, data
);
643 /* Add a trailing sentinel symbol. */
644 macho_symbols
[j
].name
= "";
645 macho_symbols
[j
].address
= ~(uintptr_t) 0;
647 backtrace_qsort (macho_symbols
, ndefs
+ 1, sizeof (struct macho_symbol
),
648 macho_symbol_compare
);
651 sdata
->symbols
= macho_symbols
;
652 sdata
->count
= ndefs
;
654 if (!state
->threaded
)
656 struct macho_syminfo_data
**pp
;
658 for (pp
= (struct macho_syminfo_data
**) (void *) &state
->syminfo_data
;
668 struct macho_syminfo_data
**pp
;
670 pp
= (struct macho_syminfo_data
**) (void *) &state
->syminfo_data
;
674 struct macho_syminfo_data
*p
;
676 p
= backtrace_atomic_load_pointer (pp
);
684 if (__sync_bool_compare_and_swap (pp
, NULL
, sdata
))
692 if (macho_symbols
!= NULL
)
693 backtrace_free (state
, macho_symbols
, macho_symbol_size
,
694 error_callback
, data
);
696 backtrace_release_view (state
, &sym_view
, error_callback
, data
);
698 backtrace_release_view (state
, &str_view
, error_callback
, data
);
702 /* Return the symbol name and value for an ADDR. */
705 macho_syminfo (struct backtrace_state
*state
, uintptr_t addr
,
706 backtrace_syminfo_callback callback
,
707 backtrace_error_callback error_callback ATTRIBUTE_UNUSED
,
710 struct macho_syminfo_data
*sdata
;
711 struct macho_symbol
*sym
;
714 if (!state
->threaded
)
716 for (sdata
= (struct macho_syminfo_data
*) state
->syminfo_data
;
720 sym
= ((struct macho_symbol
*)
721 bsearch (&addr
, sdata
->symbols
, sdata
->count
,
722 sizeof (struct macho_symbol
), macho_symbol_search
));
729 struct macho_syminfo_data
**pp
;
731 pp
= (struct macho_syminfo_data
**) (void *) &state
->syminfo_data
;
734 sdata
= backtrace_atomic_load_pointer (pp
);
738 sym
= ((struct macho_symbol
*)
739 bsearch (&addr
, sdata
->symbols
, sdata
->count
,
740 sizeof (struct macho_symbol
), macho_symbol_search
));
749 callback (data
, addr
, NULL
, 0, 0);
751 callback (data
, addr
, sym
->name
, sym
->address
, 0);
754 /* Look through a fat file to find the relevant executable. Returns 1
755 on success, 0 on failure (in both cases descriptor is closed). */
758 macho_add_fat (struct backtrace_state
*state
, const char *filename
,
759 int descriptor
, int swapped
, off_t offset
,
760 const unsigned char *match_uuid
, uintptr_t base_address
,
761 int skip_symtab
, uint32_t nfat_arch
, int is_64
,
762 backtrace_error_callback error_callback
, void *data
,
763 fileline
*fileline_fn
, int *found_sym
)
766 unsigned int cputype
;
768 struct backtrace_view arch_view
;
773 #if defined (__x86_64__)
774 cputype
= MACH_O_CPU_TYPE_X86_64
;
775 #elif defined (__i386__)
776 cputype
= MACH_O_CPU_TYPE_X86
;
777 #elif defined (__aarch64__)
778 cputype
= MACH_O_CPU_TYPE_ARM64
;
779 #elif defined (__arm__)
780 cputype
= MACH_O_CPU_TYPE_ARM
;
781 #elif defined (__ppc__)
782 cputype
= MACH_O_CPU_TYPE_PPC
;
783 #elif defined (__ppc64__)
784 cputype
= MACH_O_CPU_TYPE_PPC64
;
786 error_callback (data
, "unknown Mach-O architecture", 0);
791 arch_size
= sizeof (struct macho_fat_arch_64
);
793 arch_size
= sizeof (struct macho_fat_arch
);
795 if (!backtrace_get_view (state
, descriptor
, offset
,
796 nfat_arch
* arch_size
,
797 error_callback
, data
, &arch_view
))
800 for (i
= 0; i
< nfat_arch
; ++i
)
807 struct macho_fat_arch_64 fat_arch_64
;
809 memcpy (&fat_arch_64
,
810 (const char *) arch_view
.data
+ i
* arch_size
,
812 fcputype
= fat_arch_64
.cputype
;
813 foffset
= fat_arch_64
.offset
;
816 fcputype
= __builtin_bswap32 (fcputype
);
817 foffset
= __builtin_bswap64 (foffset
);
822 struct macho_fat_arch fat_arch_32
;
824 memcpy (&fat_arch_32
,
825 (const char *) arch_view
.data
+ i
* arch_size
,
827 fcputype
= fat_arch_32
.cputype
;
828 foffset
= (uint64_t) fat_arch_32
.offset
;
831 fcputype
= __builtin_bswap32 (fcputype
);
832 foffset
= (uint64_t) __builtin_bswap32 ((uint32_t) foffset
);
836 if (fcputype
== cputype
)
838 /* FIXME: What about cpusubtype? */
839 backtrace_release_view (state
, &arch_view
, error_callback
, data
);
840 return macho_add (state
, filename
, descriptor
, foffset
, match_uuid
,
841 base_address
, skip_symtab
, error_callback
, data
,
842 fileline_fn
, found_sym
);
846 error_callback (data
, "could not find executable in fat file", 0);
850 backtrace_release_view (state
, &arch_view
, error_callback
, data
);
851 if (descriptor
!= -1)
852 backtrace_close (descriptor
, error_callback
, data
);
856 /* Look for the dsym file for FILENAME. This is called if FILENAME
857 does not have debug info or a symbol table. Returns 1 on success,
861 macho_add_dsym (struct backtrace_state
*state
, const char *filename
,
862 uintptr_t base_address
, const unsigned char *uuid
,
863 backtrace_error_callback error_callback
, void *data
,
864 fileline
* fileline_fn
)
870 const char *basename
;
872 const char *dsymsuffixdir
;
873 size_t dsymsuffixdirlen
;
886 p
= strrchr (filename
, '/');
892 basenamelen
= strlen (basename
);
897 dirnamelen
= p
- filename
;
898 diralc
= backtrace_alloc (state
, dirnamelen
+ 1, error_callback
, data
);
901 memcpy (diralc
, filename
, dirnamelen
);
902 diralc
[dirnamelen
] = '\0';
905 basenamelen
= strlen (basename
);
908 dsymsuffixdir
= ".dSYM/Contents/Resources/DWARF/";
909 dsymsuffixdirlen
= strlen (dsymsuffixdir
);
911 dsymlen
= (dirnamelen
917 dsym
= backtrace_alloc (state
, dsymlen
, error_callback
, data
);
922 memcpy (ps
, dirname
, dirnamelen
);
925 memcpy (ps
, basename
, basenamelen
);
927 memcpy (ps
, dsymsuffixdir
, dsymsuffixdirlen
);
928 ps
+= dsymsuffixdirlen
;
929 memcpy (ps
, basename
, basenamelen
);
935 backtrace_free (state
, diralc
, dirnamelen
+ 1, error_callback
, data
);
939 d
= backtrace_open (dsym
, error_callback
, data
, &does_not_exist
);
942 /* The file does not exist, so we can't read the debug info.
943 Just return success. */
944 backtrace_free (state
, dsym
, dsymlen
, error_callback
, data
);
948 if (!macho_add (state
, dsym
, d
, 0, uuid
, base_address
, 1,
949 error_callback
, data
, fileline_fn
, &dummy_found_sym
))
952 backtrace_free (state
, dsym
, dsymlen
, error_callback
, data
);
958 backtrace_free (state
, dsym
, dsymlen
, error_callback
, data
);
960 backtrace_free (state
, diralc
, dirnamelen
, error_callback
, data
);
964 /* Add the backtrace data for a Macho-O file. Returns 1 on success, 0
965 on failure (in both cases descriptor is closed).
967 FILENAME: the name of the executable.
968 DESCRIPTOR: an open descriptor for the executable, closed here.
969 OFFSET: the offset within the file of this executable, for fat files.
970 MATCH_UUID: if not NULL, UUID that must match.
971 BASE_ADDRESS: the load address of the executable.
972 SKIP_SYMTAB: if non-zero, ignore the symbol table; used for dSYM files.
973 FILELINE_FN: set to the fileline function, by backtrace_dwarf_add.
974 FOUND_SYM: set to non-zero if we found the symbol table.
978 macho_add (struct backtrace_state
*state
, const char *filename
, int descriptor
,
979 off_t offset
, const unsigned char *match_uuid
,
980 uintptr_t base_address
, int skip_symtab
,
981 backtrace_error_callback error_callback
, void *data
,
982 fileline
*fileline_fn
, int *found_sym
)
984 struct backtrace_view header_view
;
985 struct macho_header_32 header
;
988 struct backtrace_view cmds_view
;
990 struct dwarf_sections dwarf_sections
;
992 unsigned char uuid
[MACH_O_UUID_LEN
];
1001 /* The 32-bit and 64-bit file headers start out the same, so we can
1002 just always read the 32-bit version. A fat header is shorter but
1003 it will always be followed by data, so it's OK to read extra. */
1005 if (!backtrace_get_view (state
, descriptor
, offset
,
1006 sizeof (struct macho_header_32
),
1007 error_callback
, data
, &header_view
))
1010 memcpy (&header
, header_view
.data
, sizeof header
);
1012 backtrace_release_view (state
, &header_view
, error_callback
, data
);
1014 switch (header
.magic
)
1016 case MACH_O_MH_MAGIC_32
:
1018 hdroffset
= offset
+ sizeof (struct macho_header_32
);
1020 case MACH_O_MH_MAGIC_64
:
1022 hdroffset
= offset
+ sizeof (struct macho_header_64
);
1024 case MACH_O_MH_MAGIC_FAT
:
1025 case MACH_O_MH_MAGIC_FAT_64
:
1027 struct macho_header_fat fat_header
;
1029 hdroffset
= offset
+ sizeof (struct macho_header_fat
);
1030 memcpy (&fat_header
, &header
, sizeof fat_header
);
1031 return macho_add_fat (state
, filename
, descriptor
, 0, hdroffset
,
1032 match_uuid
, base_address
, skip_symtab
,
1033 fat_header
.nfat_arch
,
1034 header
.magic
== MACH_O_MH_MAGIC_FAT_64
,
1035 error_callback
, data
, fileline_fn
, found_sym
);
1037 case MACH_O_MH_CIGAM_FAT
:
1038 case MACH_O_MH_CIGAM_FAT_64
:
1040 struct macho_header_fat fat_header
;
1043 hdroffset
= offset
+ sizeof (struct macho_header_fat
);
1044 memcpy (&fat_header
, &header
, sizeof fat_header
);
1045 nfat_arch
= __builtin_bswap32 (fat_header
.nfat_arch
);
1046 return macho_add_fat (state
, filename
, descriptor
, 1, hdroffset
,
1047 match_uuid
, base_address
, skip_symtab
,
1049 header
.magic
== MACH_O_MH_CIGAM_FAT_64
,
1050 error_callback
, data
, fileline_fn
, found_sym
);
1053 error_callback (data
, "executable file is not in Mach-O format", 0);
1057 switch (header
.filetype
)
1059 case MACH_O_MH_EXECUTE
:
1060 case MACH_O_MH_DYLIB
:
1061 case MACH_O_MH_DSYM
:
1064 error_callback (data
, "executable file is not an executable", 0);
1068 if (!backtrace_get_view (state
, descriptor
, hdroffset
, header
.sizeofcmds
,
1069 error_callback
, data
, &cmds_view
))
1071 cmds_view_valid
= 1;
1073 memset (&dwarf_sections
, 0, sizeof dwarf_sections
);
1075 memset (&uuid
, 0, sizeof uuid
);
1079 for (i
= 0; i
< header
.ncmds
; ++i
)
1082 struct macho_load_command load_command
;
1084 if (cmdoffset
+ sizeof load_command
> header
.sizeofcmds
)
1087 pcmd
= (const char *) cmds_view
.data
+ cmdoffset
;
1088 memcpy (&load_command
, pcmd
, sizeof load_command
);
1090 switch (load_command
.cmd
)
1092 case MACH_O_LC_SEGMENT
:
1094 struct macho_segment_command segcmd
;
1096 memcpy (&segcmd
, pcmd
, sizeof segcmd
);
1097 if (memcmp (segcmd
.segname
,
1098 "__DWARF\0\0\0\0\0\0\0\0\0",
1099 MACH_O_NAMELEN
) == 0)
1101 if (!macho_add_dwarf_segment (state
, descriptor
, offset
,
1103 pcmd
+ sizeof segcmd
,
1104 (load_command
.cmdsize
1106 segcmd
.nsects
, error_callback
,
1107 data
, &dwarf_sections
))
1114 case MACH_O_LC_SEGMENT_64
:
1116 struct macho_segment_64_command segcmd
;
1118 memcpy (&segcmd
, pcmd
, sizeof segcmd
);
1119 if (memcmp (segcmd
.segname
,
1120 "__DWARF\0\0\0\0\0\0\0\0\0",
1121 MACH_O_NAMELEN
) == 0)
1123 if (!macho_add_dwarf_segment (state
, descriptor
, offset
,
1125 pcmd
+ sizeof segcmd
,
1126 (load_command
.cmdsize
1128 segcmd
.nsects
, error_callback
,
1129 data
, &dwarf_sections
))
1136 case MACH_O_LC_SYMTAB
:
1139 struct macho_symtab_command symcmd
;
1141 memcpy (&symcmd
, pcmd
, sizeof symcmd
);
1142 if (!macho_add_symtab (state
, descriptor
, base_address
, is_64
,
1143 offset
+ symcmd
.symoff
, symcmd
.nsyms
,
1144 offset
+ symcmd
.stroff
, symcmd
.strsize
,
1145 error_callback
, data
))
1152 case MACH_O_LC_UUID
:
1154 struct macho_uuid_command uuidcmd
;
1156 memcpy (&uuidcmd
, pcmd
, sizeof uuidcmd
);
1157 memcpy (&uuid
[0], &uuidcmd
.uuid
[0], MACH_O_UUID_LEN
);
1166 cmdoffset
+= load_command
.cmdsize
;
1169 if (!backtrace_close (descriptor
, error_callback
, data
))
1173 backtrace_release_view (state
, &cmds_view
, error_callback
, data
);
1174 cmds_view_valid
= 0;
1176 if (match_uuid
!= NULL
)
1178 /* If we don't have a UUID, or it doesn't match, just ignore
1181 || memcmp (match_uuid
, &uuid
[0], MACH_O_UUID_LEN
) != 0)
1190 #if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)
1191 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
1196 if (!backtrace_dwarf_add (state
, base_address
, &dwarf_sections
,
1197 is_big_endian
, NULL
, error_callback
, data
,
1202 if (!have_dwarf
&& have_uuid
)
1204 if (!macho_add_dsym (state
, filename
, base_address
, &uuid
[0],
1205 error_callback
, data
, fileline_fn
))
1212 if (cmds_view_valid
)
1213 backtrace_release_view (state
, &cmds_view
, error_callback
, data
);
1214 if (descriptor
!= -1)
1215 backtrace_close (descriptor
, error_callback
, data
);
1219 #ifdef HAVE_MACH_O_DYLD_H
1221 /* Initialize the backtrace data we need from a Mach-O executable
1222 using the dyld support functions. This closes descriptor. */
1225 backtrace_initialize (struct backtrace_state
*state
, const char *filename
,
1226 int descriptor
, backtrace_error_callback error_callback
,
1227 void *data
, fileline
*fileline_fn
)
1231 int closed_descriptor
;
1233 fileline macho_fileline_fn
;
1235 closed_descriptor
= 0;
1237 macho_fileline_fn
= macho_nodebug
;
1239 c
= _dyld_image_count ();
1240 for (i
= 0; i
< c
; ++i
)
1242 uintptr_t base_address
;
1248 name
= _dyld_get_image_name (i
);
1252 if (strcmp (name
, filename
) == 0 && !closed_descriptor
)
1255 closed_descriptor
= 1;
1261 d
= backtrace_open (name
, error_callback
, data
, &does_not_exist
);
1266 base_address
= _dyld_get_image_vmaddr_slide (i
);
1268 mff
= macho_nodebug
;
1269 if (!macho_add (state
, name
, d
, 0, NULL
, base_address
, 0,
1270 error_callback
, data
, &mff
, &mfs
))
1273 if (mff
!= macho_nodebug
)
1274 macho_fileline_fn
= mff
;
1279 if (!closed_descriptor
)
1280 backtrace_close (descriptor
, error_callback
, data
);
1282 if (!state
->threaded
)
1285 state
->syminfo_fn
= macho_syminfo
;
1286 else if (state
->syminfo_fn
== NULL
)
1287 state
->syminfo_fn
= macho_nosyms
;
1292 backtrace_atomic_store_pointer (&state
->syminfo_fn
, macho_syminfo
);
1294 (void) __sync_bool_compare_and_swap (&state
->syminfo_fn
, NULL
,
1298 if (!state
->threaded
)
1299 *fileline_fn
= state
->fileline_fn
;
1301 *fileline_fn
= backtrace_atomic_load_pointer (&state
->fileline_fn
);
1303 if (*fileline_fn
== NULL
|| *fileline_fn
== macho_nodebug
)
1304 *fileline_fn
= macho_fileline_fn
;
1309 #else /* !defined (HAVE_MACH_O_DYLD_H) */
1311 /* Initialize the backtrace data we need from a Mach-O executable
1312 without using the dyld support functions. This closes
1316 backtrace_initialize (struct backtrace_state
*state
, const char *filename
,
1317 int descriptor
, backtrace_error_callback error_callback
,
1318 void *data
, fileline
*fileline_fn
)
1320 fileline macho_fileline_fn
;
1323 macho_fileline_fn
= macho_nodebug
;
1324 if (!macho_add (state
, filename
, descriptor
, 0, NULL
, 0, 0,
1325 error_callback
, data
, &macho_fileline_fn
, &found_sym
))
1328 if (!state
->threaded
)
1331 state
->syminfo_fn
= macho_syminfo
;
1332 else if (state
->syminfo_fn
== NULL
)
1333 state
->syminfo_fn
= macho_nosyms
;
1338 backtrace_atomic_store_pointer (&state
->syminfo_fn
, macho_syminfo
);
1340 (void) __sync_bool_compare_and_swap (&state
->syminfo_fn
, NULL
,
1344 if (!state
->threaded
)
1345 *fileline_fn
= state
->fileline_fn
;
1347 *fileline_fn
= backtrace_atomic_load_pointer (&state
->fileline_fn
);
1349 if (*fileline_fn
== NULL
|| *fileline_fn
== macho_nodebug
)
1350 *fileline_fn
= macho_fileline_fn
;
1355 #endif /* !defined (HAVE_MACH_O_DYLD_H) */