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_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. */
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
] =
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
*,
322 /* A dummy callback function used when we can't find any debug info. */
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);
334 /* A dummy callback function used when we can't find a symbol
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. */
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
)
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
368 if (!backtrace_get_view (state
, descriptor
, offset
, size
,
369 error_callback
, data
, §ion_view
))
371 dwarf_sections
->data
[i
] = (const unsigned char *) section_view
.data
;
372 dwarf_sections
->size
[i
] = size
;
379 /* Collect DWARF sections from a DWARF segment. Returns 1 on success,
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
;
395 case MACH_O_LC_SEGMENT
:
396 sec_header_size
= sizeof (struct macho_section
);
398 case MACH_O_LC_SEGMENT_64
:
399 sec_header_size
= sizeof (struct macho_section_64
);
406 for (i
= 0; i
< nsects
; ++i
)
408 if (secoffset
+ sec_header_size
> sizesecs
)
410 error_callback (data
, "section overflow withing segment", 0);
416 case MACH_O_LC_SEGMENT
:
418 struct macho_section section
;
420 memcpy (§ion
, 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
);
427 case MACH_O_LC_SEGMENT_64
:
429 struct macho_section_64 section
;
431 memcpy (§ion
, 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
);
442 secoffset
+= sec_header_size
;
448 /* Compare struct macho_symbol for qsort. */
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
)
458 else if (m1
->address
> m2
->address
)
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
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
;
476 if (addr
< entry
->address
)
478 else if (entry
->name
[0] == '\0'
479 && entry
->address
== ~(uintptr_t) 0)
481 else if ((entry
+ 1)->name
[0] == '\0'
482 && (entry
+ 1)->address
== ~(uintptr_t) 0)
484 else if (addr
>= (entry
+ 1)->address
)
490 /* Return whether the symbol type field indicates a symbol table entry
491 that we care about: a function or data symbol. */
494 macho_defined_symbol (uint8_t type
)
496 if ((type
& MACH_O_N_STAB
) != 0)
498 switch (type
& MACH_O_N_TYPE
)
511 /* Add symbol table information for a Mach-O file. */
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
)
521 struct backtrace_view sym_view
;
523 struct backtrace_view str_view
;
528 size_t macho_symbol_size
;
529 struct macho_symbol
*macho_symbols
;
531 struct macho_syminfo_data
*sdata
;
535 macho_symbol_size
= 0;
536 macho_symbols
= NULL
;
539 symsize
= sizeof (struct macho_nlist_64
);
541 symsize
= sizeof (struct macho_nlist
);
543 if (!backtrace_get_view (state
, descriptor
, symoff
, nsyms
* symsize
,
544 error_callback
, data
, &sym_view
))
548 if (!backtrace_get_view (state
, descriptor
, stroff
, strsize
,
549 error_callback
, data
, &str_view
))
555 for (i
= 0; i
< nsyms
; ++i
, symtaboff
+= symsize
)
559 struct macho_nlist_64 nlist
;
561 memcpy (&nlist
, (const char *) sym_view
.data
+ symtaboff
,
563 if (macho_defined_symbol (nlist
.n_type
))
568 struct macho_nlist nlist
;
570 memcpy (&nlist
, (const char *) sym_view
.data
+ symtaboff
,
572 if (macho_defined_symbol (nlist
.n_type
))
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
,
582 if (macho_symbols
== NULL
)
587 for (i
= 0; i
< nsyms
; ++i
, symtaboff
+= symsize
)
597 struct macho_nlist_64 nlist
;
599 memcpy (&nlist
, (const char *) sym_view
.data
+ symtaboff
,
601 if (!macho_defined_symbol (nlist
.n_type
))
605 value
= nlist
.n_value
;
609 struct macho_nlist nlist
;
611 memcpy (&nlist
, (const char *) sym_view
.data
+ symtaboff
,
613 if (!macho_defined_symbol (nlist
.n_type
))
617 value
= nlist
.n_value
;
622 error_callback (data
, "symbol string index out of range", 0);
626 name
= (const char *) str_view
.data
+ strx
;
629 macho_symbols
[j
].name
= name
;
630 macho_symbols
[j
].address
= libbacktrace_add_base (value
, base_address
);
634 sdata
= ((struct macho_syminfo_data
*)
635 backtrace_alloc (state
, sizeof *sdata
, error_callback
, data
));
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
);
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
);
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
;
671 struct macho_syminfo_data
**pp
;
673 pp
= (struct macho_syminfo_data
**) (void *) &state
->syminfo_data
;
677 struct macho_syminfo_data
*p
;
679 p
= backtrace_atomic_load_pointer (pp
);
686 if (__sync_bool_compare_and_swap (pp
, NULL
, sdata
))
694 if (macho_symbols
!= NULL
)
695 backtrace_free (state
, macho_symbols
, macho_symbol_size
,
696 error_callback
, data
);
698 backtrace_release_view (state
, &sym_view
, error_callback
, data
);
700 backtrace_release_view (state
, &str_view
, error_callback
, data
);
704 /* Return the symbol name and value for an ADDR. */
707 macho_syminfo (struct backtrace_state
*state
, uintptr_t addr
,
708 backtrace_syminfo_callback callback
,
709 backtrace_error_callback error_callback ATTRIBUTE_UNUSED
,
712 struct macho_syminfo_data
*sdata
;
713 struct macho_symbol
*sym
;
716 if (!state
->threaded
)
718 for (sdata
= (struct macho_syminfo_data
*) state
->syminfo_data
;
722 sym
= ((struct macho_symbol
*)
723 bsearch (&addr
, sdata
->symbols
, sdata
->count
,
724 sizeof (struct macho_symbol
), macho_symbol_search
));
731 struct macho_syminfo_data
**pp
;
733 pp
= (struct macho_syminfo_data
**) (void *) &state
->syminfo_data
;
736 sdata
= backtrace_atomic_load_pointer (pp
);
740 sym
= ((struct macho_symbol
*)
741 bsearch (&addr
, sdata
->symbols
, sdata
->count
,
742 sizeof (struct macho_symbol
), macho_symbol_search
));
751 callback (data
, addr
, NULL
, 0, 0);
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). */
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
)
769 unsigned int cputype
;
771 struct backtrace_view arch_view
;
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
;
789 error_callback (data
, "unknown Mach-O architecture", 0);
794 arch_size
= sizeof (struct macho_fat_arch_64
);
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
))
803 for (i
= 0; i
< nfat_arch
; ++i
)
810 struct macho_fat_arch_64 fat_arch_64
;
812 memcpy (&fat_arch_64
,
813 (const char *) arch_view
.data
+ i
* arch_size
,
815 fcputype
= fat_arch_64
.cputype
;
816 foffset
= fat_arch_64
.offset
;
819 fcputype
= __builtin_bswap32 (fcputype
);
820 foffset
= __builtin_bswap64 (foffset
);
825 struct macho_fat_arch fat_arch_32
;
827 memcpy (&fat_arch_32
,
828 (const char *) arch_view
.data
+ i
* arch_size
,
830 fcputype
= fat_arch_32
.cputype
;
831 foffset
= (uint64_t) fat_arch_32
.offset
;
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);
853 backtrace_release_view (state
, &arch_view
, error_callback
, data
);
854 if (descriptor
!= -1)
855 backtrace_close (descriptor
, error_callback
, data
);
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,
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
)
874 const char *basename
;
876 const char *dsymsuffixdir
;
877 size_t dsymsuffixdirlen
;
890 p
= strrchr (filename
, '/');
896 basenamelen
= strlen (basename
);
901 dirnamelen
= p
- filename
;
902 diralc
= backtrace_alloc (state
, dirnamelen
+ 1, error_callback
, data
);
905 memcpy (diralc
, filename
, dirnamelen
);
906 diralc
[dirnamelen
] = '\0';
909 basenamelen
= strlen (basename
);
912 dsymsuffixdir
= ".dSYM/Contents/Resources/DWARF/";
913 dsymsuffixdirlen
= strlen (dsymsuffixdir
);
915 dsymlen
= (dirnamelen
921 dsym
= backtrace_alloc (state
, dsymlen
, error_callback
, data
);
926 memcpy (ps
, dirname
, dirnamelen
);
929 memcpy (ps
, basename
, basenamelen
);
931 memcpy (ps
, dsymsuffixdir
, dsymsuffixdirlen
);
932 ps
+= dsymsuffixdirlen
;
933 memcpy (ps
, basename
, basenamelen
);
939 backtrace_free (state
, diralc
, dirnamelen
+ 1, error_callback
, data
);
943 d
= backtrace_open (dsym
, error_callback
, data
, &does_not_exist
);
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
);
952 if (!macho_add (state
, dsym
, d
, 0, uuid
, base_address
, 1,
953 error_callback
, data
, fileline_fn
, &dummy_found_sym
))
956 backtrace_free (state
, dsym
, dsymlen
, error_callback
, data
);
962 backtrace_free (state
, dsym
, dsymlen
, error_callback
, data
);
964 backtrace_free (state
, diralc
, dirnamelen
, error_callback
, data
);
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.
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
;
992 struct backtrace_view cmds_view
;
994 struct dwarf_sections dwarf_sections
;
996 unsigned char uuid
[MACH_O_UUID_LEN
];
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
))
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
:
1022 hdroffset
= offset
+ sizeof (struct macho_header_32
);
1024 case MACH_O_MH_MAGIC_64
:
1026 hdroffset
= offset
+ sizeof (struct macho_header_64
);
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
;
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
,
1053 header
.magic
== MACH_O_MH_CIGAM_FAT_64
,
1054 error_callback
, data
, fileline_fn
, found_sym
);
1057 error_callback (data
, "executable file is not in Mach-O format", 0);
1061 switch (header
.filetype
)
1063 case MACH_O_MH_EXECUTE
:
1064 case MACH_O_MH_DYLIB
:
1065 case MACH_O_MH_DSYM
:
1068 error_callback (data
, "executable file is not an executable", 0);
1072 if (!backtrace_get_view (state
, descriptor
, hdroffset
, header
.sizeofcmds
,
1073 error_callback
, data
, &cmds_view
))
1075 cmds_view_valid
= 1;
1077 memset (&dwarf_sections
, 0, sizeof dwarf_sections
);
1079 memset (&uuid
, 0, sizeof uuid
);
1083 for (i
= 0; i
< header
.ncmds
; ++i
)
1086 struct macho_load_command load_command
;
1088 if (cmdoffset
+ sizeof load_command
> header
.sizeofcmds
)
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
,
1107 pcmd
+ sizeof segcmd
,
1108 (load_command
.cmdsize
1110 segcmd
.nsects
, error_callback
,
1111 data
, &dwarf_sections
))
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
,
1129 pcmd
+ sizeof segcmd
,
1130 (load_command
.cmdsize
1132 segcmd
.nsects
, error_callback
,
1133 data
, &dwarf_sections
))
1140 case MACH_O_LC_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
))
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
);
1170 cmdoffset
+= load_command
.cmdsize
;
1173 if (!backtrace_close (descriptor
, error_callback
, data
))
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
1185 || memcmp (match_uuid
, &uuid
[0], MACH_O_UUID_LEN
) != 0)
1194 #if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)
1195 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
1200 if (!backtrace_dwarf_add (state
, base_address
, &dwarf_sections
,
1201 is_big_endian
, NULL
, error_callback
, data
,
1206 if (!have_dwarf
&& have_uuid
)
1208 if (!macho_add_dsym (state
, filename
, base_address
, &uuid
[0],
1209 error_callback
, data
, fileline_fn
))
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
);
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
)
1235 int closed_descriptor
;
1237 fileline macho_fileline_fn
;
1239 closed_descriptor
= 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
;
1252 name
= _dyld_get_image_name (i
);
1256 if (strcmp (name
, filename
) == 0 && !closed_descriptor
)
1259 closed_descriptor
= 1;
1265 d
= backtrace_open (name
, error_callback
, data
, &does_not_exist
);
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
))
1277 if (mff
!= macho_nodebug
)
1278 macho_fileline_fn
= mff
;
1283 if (!closed_descriptor
)
1284 backtrace_close (descriptor
, error_callback
, data
);
1286 if (!state
->threaded
)
1289 state
->syminfo_fn
= macho_syminfo
;
1290 else if (state
->syminfo_fn
== NULL
)
1291 state
->syminfo_fn
= macho_nosyms
;
1296 backtrace_atomic_store_pointer (&state
->syminfo_fn
, macho_syminfo
);
1298 (void) __sync_bool_compare_and_swap (&state
->syminfo_fn
, NULL
,
1302 if (!state
->threaded
)
1303 *fileline_fn
= state
->fileline_fn
;
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
;
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
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
;
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
))
1334 if (!state
->threaded
)
1337 state
->syminfo_fn
= macho_syminfo
;
1338 else if (state
->syminfo_fn
== NULL
)
1339 state
->syminfo_fn
= macho_nosyms
;
1344 backtrace_atomic_store_pointer (&state
->syminfo_fn
, macho_syminfo
);
1346 (void) __sync_bool_compare_and_swap (&state
->syminfo_fn
, NULL
,
1350 if (!state
->threaded
)
1351 *fileline_fn
= state
->fileline_fn
;
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
;
1361 #endif /* !defined (HAVE_MACH_O_DYLD_H) */