1 /* elf.c -- Get debug data from a Mach-O file for backtraces.
2 Copyright (C) 2020 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor, Google.
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
132 #define MACH_O_CPU_TYPE_X86_64 (MACH_O_CPU_TYPE_X86 | MACH_O_CPU_ARCH_ABI64)
133 #define MACH_O_CPU_TYPE_ARM64 (MACH_O_CPU_TYPE_ARM | MACH_O_CPU_ARCH_ABI64)
135 /* The header of a load command. */
137 struct macho_load_command
139 uint32_t cmd
; /* The type of load command */
140 uint32_t cmdsize
; /* Size in bytes of the entire command */
143 /* Values for the load_command cmd field. */
145 #define MACH_O_LC_SEGMENT 0x01
146 #define MACH_O_LC_SYMTAB 0x02
147 #define MACH_O_LC_SEGMENT_64 0x19
148 #define MACH_O_LC_UUID 0x1b
150 /* The length of a section of segment name. */
152 #define MACH_O_NAMELEN (16)
154 /* LC_SEGMENT load command. */
156 struct macho_segment_command
158 uint32_t cmd
; /* The type of load command (LC_SEGMENT) */
159 uint32_t cmdsize
; /* Size in bytes of the entire command */
160 char segname
[MACH_O_NAMELEN
]; /* Segment name */
161 uint32_t vmaddr
; /* Virtual memory address */
162 uint32_t vmsize
; /* Virtual memory size */
163 uint32_t fileoff
; /* Offset of data to be mapped */
164 uint32_t filesize
; /* Size of data in file */
165 uint32_t maxprot
; /* Maximum permitted virtual protection */
166 uint32_t initprot
; /* Initial virtual memory protection */
167 uint32_t nsects
; /* Number of sections in this segment */
168 uint32_t flags
; /* Flags */
171 /* LC_SEGMENT_64 load command. */
173 struct macho_segment_64_command
175 uint32_t cmd
; /* The type of load command (LC_SEGMENT) */
176 uint32_t cmdsize
; /* Size in bytes of the entire command */
177 char segname
[MACH_O_NAMELEN
]; /* Segment name */
178 uint64_t vmaddr
; /* Virtual memory address */
179 uint64_t vmsize
; /* Virtual memory size */
180 uint64_t fileoff
; /* Offset of data to be mapped */
181 uint64_t filesize
; /* Size of data in file */
182 uint32_t maxprot
; /* Maximum permitted virtual protection */
183 uint32_t initprot
; /* Initial virtual memory protection */
184 uint32_t nsects
; /* Number of sections in this segment */
185 uint32_t flags
; /* Flags */
188 /* LC_SYMTAB load command. */
190 struct macho_symtab_command
192 uint32_t cmd
; /* The type of load command (LC_SEGMENT) */
193 uint32_t cmdsize
; /* Size in bytes of the entire command */
194 uint32_t symoff
; /* File offset of symbol table */
195 uint32_t nsyms
; /* Number of symbols */
196 uint32_t stroff
; /* File offset of string table */
197 uint32_t strsize
; /* String table size */
200 /* The length of a Mach-O uuid. */
202 #define MACH_O_UUID_LEN (16)
204 /* LC_UUID load command. */
206 struct macho_uuid_command
208 uint32_t cmd
; /* Type of load command (LC_UUID) */
209 uint32_t cmdsize
; /* Size in bytes of command */
210 unsigned char uuid
[MACH_O_UUID_LEN
]; /* UUID */
213 /* 32-bit section header within a LC_SEGMENT segment. */
217 char sectname
[MACH_O_NAMELEN
]; /* Section name */
218 char segment
[MACH_O_NAMELEN
]; /* Segment of this section */
219 uint32_t addr
; /* Address in memory */
220 uint32_t size
; /* Section size */
221 uint32_t offset
; /* File offset */
222 uint32_t align
; /* Log2 of section alignment */
223 uint32_t reloff
; /* File offset of relocations */
224 uint32_t nreloc
; /* Number of relocs for this section */
225 uint32_t flags
; /* Flags */
230 /* 64-bit section header within a LC_SEGMENT_64 segment. */
232 struct macho_section_64
234 char sectname
[MACH_O_NAMELEN
]; /* Section name */
235 char segment
[MACH_O_NAMELEN
]; /* Segment of this section */
236 uint64_t addr
; /* Address in memory */
237 uint64_t size
; /* Section size */
238 uint32_t offset
; /* File offset */
239 uint32_t align
; /* Log2 of section alignment */
240 uint32_t reloff
; /* File offset of section relocations */
241 uint32_t nreloc
; /* Number of relocs for this section */
242 uint32_t flags
; /* Flags */
248 /* 32-bit symbol data. */
252 uint32_t n_strx
; /* Index of name in string table */
253 uint8_t n_type
; /* Type flag */
254 uint8_t n_sect
; /* Section number */
255 uint16_t n_desc
; /* Stabs description field */
256 uint32_t n_value
; /* Value */
259 /* 64-bit symbol data. */
261 struct macho_nlist_64
263 uint32_t n_strx
; /* Index of name in string table */
264 uint8_t n_type
; /* Type flag */
265 uint8_t n_sect
; /* Section number */
266 uint16_t n_desc
; /* Stabs description field */
267 uint64_t n_value
; /* Value */
270 /* Value found in nlist n_type field. */
272 #define MACH_O_N_EXT 0x01 /* Extern symbol */
273 #define MACH_O_N_ABS 0x02 /* Absolute symbol */
274 #define MACH_O_N_SECT 0x0e /* Defined in section */
276 #define MACH_O_N_TYPE 0x0e /* Mask for type bits */
277 #define MACH_O_N_STAB 0xe0 /* Stabs debugging symbol */
279 /* Information we keep for a Mach-O symbol. */
283 const char *name
; /* Symbol name */
284 uintptr_t address
; /* Symbol address */
287 /* Information to pass to macho_syminfo. */
289 struct macho_syminfo_data
291 struct macho_syminfo_data
*next
; /* Next module */
292 struct macho_symbol
*symbols
; /* Symbols sorted by address */
293 size_t count
; /* Number of symbols */
296 /* Names of sections, indexed by enum dwarf_section in internal.h. */
298 static const char * const dwarf_section_names
[DEBUG_MAX
] =
307 "", /* DEBUG_LINE_STR */
311 /* Forward declaration. */
313 static int macho_add (struct backtrace_state
*, const char *, int, off_t
,
314 const unsigned char *, uintptr_t, int,
315 backtrace_error_callback
, void *, fileline
*, int *);
317 /* A dummy callback function used when we can't find any debug info. */
320 macho_nodebug (struct backtrace_state
*state ATTRIBUTE_UNUSED
,
321 uintptr_t pc ATTRIBUTE_UNUSED
,
322 backtrace_full_callback callback ATTRIBUTE_UNUSED
,
323 backtrace_error_callback error_callback
, void *data
)
325 error_callback (data
, "no debug info in Mach-O executable", -1);
329 /* A dummy callback function used when we can't find a symbol
333 macho_nosyms (struct backtrace_state
*state ATTRIBUTE_UNUSED
,
334 uintptr_t addr ATTRIBUTE_UNUSED
,
335 backtrace_syminfo_callback callback ATTRIBUTE_UNUSED
,
336 backtrace_error_callback error_callback
, void *data
)
338 error_callback (data
, "no symbol table in Mach-O executable", -1);
341 /* Add a single DWARF section to DWARF_SECTIONS, if we need the
342 section. Returns 1 on success, 0 on failure. */
345 macho_add_dwarf_section (struct backtrace_state
*state
, int descriptor
,
346 const char *sectname
, uint32_t offset
, uint64_t size
,
347 backtrace_error_callback error_callback
, void *data
,
348 struct dwarf_sections
*dwarf_sections
)
352 for (i
= 0; i
< (int) DEBUG_MAX
; ++i
)
354 if (dwarf_section_names
[i
][0] != '\0'
355 && strncmp (sectname
, dwarf_section_names
[i
], MACH_O_NAMELEN
) == 0)
357 struct backtrace_view section_view
;
359 /* FIXME: Perhaps it would be better to try to use a single
360 view to read all the DWARF data, as we try to do for
363 if (!backtrace_get_view (state
, descriptor
, offset
, size
,
364 error_callback
, data
, §ion_view
))
366 dwarf_sections
->data
[i
] = (const unsigned char *) section_view
.data
;
367 dwarf_sections
->size
[i
] = size
;
374 /* Collect DWARF sections from a DWARF segment. Returns 1 on success,
378 macho_add_dwarf_segment (struct backtrace_state
*state
, int descriptor
,
379 off_t offset
, unsigned int cmd
, const char *psecs
,
380 size_t sizesecs
, unsigned int nsects
,
381 backtrace_error_callback error_callback
, void *data
,
382 struct dwarf_sections
*dwarf_sections
)
384 size_t sec_header_size
;
390 case MACH_O_LC_SEGMENT
:
391 sec_header_size
= sizeof (struct macho_section
);
393 case MACH_O_LC_SEGMENT_64
:
394 sec_header_size
= sizeof (struct macho_section_64
);
401 for (i
= 0; i
< nsects
; ++i
)
403 if (secoffset
+ sec_header_size
> sizesecs
)
405 error_callback (data
, "section overflow withing segment", 0);
411 case MACH_O_LC_SEGMENT
:
413 struct macho_section section
;
415 memcpy (§ion
, psecs
+ secoffset
, sizeof section
);
416 macho_add_dwarf_section (state
, descriptor
, section
.sectname
,
417 offset
+ section
.offset
, section
.size
,
418 error_callback
, data
, dwarf_sections
);
422 case MACH_O_LC_SEGMENT_64
:
424 struct macho_section_64 section
;
426 memcpy (§ion
, psecs
+ secoffset
, sizeof section
);
427 macho_add_dwarf_section (state
, descriptor
, section
.sectname
,
428 offset
+ section
.offset
, section
.size
,
429 error_callback
, data
, dwarf_sections
);
437 secoffset
+= sec_header_size
;
443 /* Compare struct macho_symbol for qsort. */
446 macho_symbol_compare (const void *v1
, const void *v2
)
448 const struct macho_symbol
*m1
= (const struct macho_symbol
*) v1
;
449 const struct macho_symbol
*m2
= (const struct macho_symbol
*) v2
;
451 if (m1
->address
< m2
->address
)
453 else if (m1
->address
> m2
->address
)
459 /* Compare an address against a macho_symbol for bsearch. We allocate
460 one extra entry in the array so that this can safely look at the
464 macho_symbol_search (const void *vkey
, const void *ventry
)
466 const uintptr_t *key
= (const uintptr_t *) vkey
;
467 const struct macho_symbol
*entry
= (const struct macho_symbol
*) ventry
;
471 if (addr
< entry
->address
)
473 else if (entry
->name
[0] == '\0'
474 && entry
->address
== ~(uintptr_t) 0)
476 else if ((entry
+ 1)->name
[0] == '\0'
477 && (entry
+ 1)->address
== ~(uintptr_t) 0)
479 else if (addr
>= (entry
+ 1)->address
)
485 /* Return whether the symbol type field indicates a symbol table entry
486 that we care about: a function or data symbol. */
489 macho_defined_symbol (uint8_t type
)
491 if ((type
& MACH_O_N_STAB
) != 0)
493 if ((type
& MACH_O_N_EXT
) != 0)
495 switch (type
& MACH_O_N_TYPE
)
506 /* Add symbol table information for a Mach-O file. */
509 macho_add_symtab (struct backtrace_state
*state
, int descriptor
,
510 uintptr_t base_address
, int is_64
,
511 off_t symoff
, unsigned int nsyms
, off_t stroff
,
512 unsigned int strsize
,
513 backtrace_error_callback error_callback
, void *data
)
516 struct backtrace_view sym_view
;
518 struct backtrace_view str_view
;
523 size_t macho_symbol_size
;
524 struct macho_symbol
*macho_symbols
;
526 struct macho_syminfo_data
*sdata
;
530 macho_symbol_size
= 0;
531 macho_symbols
= NULL
;
534 symsize
= sizeof (struct macho_nlist_64
);
536 symsize
= sizeof (struct macho_nlist
);
538 if (!backtrace_get_view (state
, descriptor
, symoff
, nsyms
* symsize
,
539 error_callback
, data
, &sym_view
))
543 if (!backtrace_get_view (state
, descriptor
, stroff
, strsize
,
544 error_callback
, data
, &str_view
))
550 for (i
= 0; i
< nsyms
; ++i
, symtaboff
+= symsize
)
554 struct macho_nlist_64 nlist
;
556 memcpy (&nlist
, (const char *) sym_view
.data
+ symtaboff
,
558 if (macho_defined_symbol (nlist
.n_type
))
563 struct macho_nlist nlist
;
565 memcpy (&nlist
, (const char *) sym_view
.data
+ symtaboff
,
567 if (macho_defined_symbol (nlist
.n_type
))
572 /* Add 1 to ndefs to make room for a sentinel. */
573 macho_symbol_size
= (ndefs
+ 1) * sizeof (struct macho_symbol
);
574 macho_symbols
= ((struct macho_symbol
*)
575 backtrace_alloc (state
, macho_symbol_size
, error_callback
,
577 if (macho_symbols
== NULL
)
582 for (i
= 0; i
< nsyms
; ++i
, symtaboff
+= symsize
)
592 struct macho_nlist_64 nlist
;
594 memcpy (&nlist
, (const char *) sym_view
.data
+ symtaboff
,
596 if (!macho_defined_symbol (nlist
.n_type
))
600 value
= nlist
.n_value
;
604 struct macho_nlist nlist
;
606 memcpy (&nlist
, (const char *) sym_view
.data
+ symtaboff
,
608 if (!macho_defined_symbol (nlist
.n_type
))
612 value
= nlist
.n_value
;
617 error_callback (data
, "symbol string index out of range", 0);
621 name
= (const char *) str_view
.data
+ strx
;
624 macho_symbols
[j
].name
= name
;
625 macho_symbols
[j
].address
= value
+ base_address
;
629 sdata
= ((struct macho_syminfo_data
*)
630 backtrace_alloc (state
, sizeof *sdata
, error_callback
, data
));
634 /* We need to keep the string table since it holds the names, but we
635 can release the symbol table. */
637 backtrace_release_view (state
, &sym_view
, error_callback
, data
);
641 /* Add a trailing sentinel symbol. */
642 macho_symbols
[j
].name
= "";
643 macho_symbols
[j
].address
= ~(uintptr_t) 0;
645 backtrace_qsort (macho_symbols
, ndefs
+ 1, sizeof (struct macho_symbol
),
646 macho_symbol_compare
);
649 sdata
->symbols
= macho_symbols
;
650 sdata
->count
= ndefs
;
652 if (!state
->threaded
)
654 struct macho_syminfo_data
**pp
;
656 for (pp
= (struct macho_syminfo_data
**) (void *) &state
->syminfo_data
;
666 struct macho_syminfo_data
**pp
;
668 pp
= (struct macho_syminfo_data
**) (void *) &state
->syminfo_data
;
672 struct macho_syminfo_data
*p
;
674 p
= backtrace_atomic_load_pointer (pp
);
682 if (__sync_bool_compare_and_swap (pp
, NULL
, sdata
))
690 if (macho_symbols
!= NULL
)
691 backtrace_free (state
, macho_symbols
, macho_symbol_size
,
692 error_callback
, data
);
694 backtrace_release_view (state
, &sym_view
, error_callback
, data
);
696 backtrace_release_view (state
, &str_view
, error_callback
, data
);
700 /* Return the symbol name and value for an ADDR. */
703 macho_syminfo (struct backtrace_state
*state
, uintptr_t addr
,
704 backtrace_syminfo_callback callback
,
705 backtrace_error_callback error_callback ATTRIBUTE_UNUSED
,
708 struct macho_syminfo_data
*sdata
;
709 struct macho_symbol
*sym
;
712 if (!state
->threaded
)
714 for (sdata
= (struct macho_syminfo_data
*) state
->syminfo_data
;
718 sym
= ((struct macho_symbol
*)
719 bsearch (&addr
, sdata
->symbols
, sdata
->count
,
720 sizeof (struct macho_symbol
), macho_symbol_search
));
727 struct macho_syminfo_data
**pp
;
729 pp
= (struct macho_syminfo_data
**) (void *) &state
->syminfo_data
;
732 sdata
= backtrace_atomic_load_pointer (pp
);
736 sym
= ((struct macho_symbol
*)
737 bsearch (&addr
, sdata
->symbols
, sdata
->count
,
738 sizeof (struct macho_symbol
), macho_symbol_search
));
747 callback (data
, addr
, NULL
, 0, 0);
749 callback (data
, addr
, sym
->name
, sym
->address
, 0);
752 /* Look through a fat file to find the relevant executable. Returns 1
753 on success, 0 on failure (in both cases descriptor is closed). */
756 macho_add_fat (struct backtrace_state
*state
, const char *filename
,
757 int descriptor
, int swapped
, off_t offset
,
758 const unsigned char *match_uuid
, uintptr_t base_address
,
759 int skip_symtab
, uint32_t nfat_arch
, int is_64
,
760 backtrace_error_callback error_callback
, void *data
,
761 fileline
*fileline_fn
, int *found_sym
)
764 unsigned int cputype
;
766 struct backtrace_view arch_view
;
771 #if defined (__x86_64__)
772 cputype
= MACH_O_CPU_TYPE_X86_64
;
773 #elif defined (__i386__)
774 cputype
= MACH_O_CPU_TYPE_X86
;
775 #elif defined (__aarch64__)
776 cputype
= MACH_O_CPU_TYPE_ARM64
;
777 #elif defined (__arm__)
778 cputype
= MACH_O_CPU_TYPE_ARM
;
780 error_callback (data
, "unknown Mach-O architecture", 0);
785 arch_size
= sizeof (struct macho_fat_arch_64
);
787 arch_size
= sizeof (struct macho_fat_arch
);
789 if (!backtrace_get_view (state
, descriptor
, offset
,
790 nfat_arch
* arch_size
,
791 error_callback
, data
, &arch_view
))
794 for (i
= 0; i
< nfat_arch
; ++i
)
796 struct macho_fat_arch_64 fat_arch
;
801 (const char *) arch_view
.data
+ i
* arch_size
,
805 struct macho_fat_arch fat_arch_32
;
807 memcpy (&fat_arch_32
,
808 (const char *) arch_view
.data
+ i
* arch_size
,
810 fat_arch
.cputype
= fat_arch_32
.cputype
;
811 fat_arch
.cpusubtype
= fat_arch_32
.cpusubtype
;
812 fat_arch
.offset
= (uint64_t) fat_arch_32
.offset
;
813 fat_arch
.size
= (uint64_t) fat_arch_32
.size
;
814 fat_arch
.align
= fat_arch_32
.align
;
815 fat_arch
.reserved
= 0;
818 fcputype
= fat_arch
.cputype
;
820 fcputype
= __builtin_bswap32 (fcputype
);
822 if (fcputype
== cputype
)
826 /* FIXME: What about cpusubtype? */
827 foffset
= fat_arch
.offset
;
829 foffset
= __builtin_bswap64 (foffset
);
830 backtrace_release_view (state
, &arch_view
, error_callback
, data
);
831 return macho_add (state
, filename
, descriptor
, foffset
, match_uuid
,
832 base_address
, skip_symtab
, error_callback
, data
,
833 fileline_fn
, found_sym
);
837 error_callback (data
, "could not find executable in fat file", 0);
841 backtrace_release_view (state
, &arch_view
, error_callback
, data
);
842 if (descriptor
!= -1)
843 backtrace_close (descriptor
, error_callback
, data
);
847 /* Look for the dsym file for FILENAME. This is called if FILENAME
848 does not have debug info or a symbol table. Returns 1 on success,
852 macho_add_dsym (struct backtrace_state
*state
, const char *filename
,
853 uintptr_t base_address
, const unsigned char *uuid
,
854 backtrace_error_callback error_callback
, void *data
,
855 fileline
* fileline_fn
)
861 const char *basename
;
863 const char *dsymsuffixdir
;
864 size_t dsymsuffixdirlen
;
877 p
= strrchr (filename
, '/');
883 basenamelen
= strlen (basename
);
888 dirnamelen
= p
- filename
;
889 diralc
= backtrace_alloc (state
, dirnamelen
+ 1, error_callback
, data
);
892 memcpy (diralc
, filename
, dirnamelen
);
893 diralc
[dirnamelen
] = '\0';
896 basenamelen
= strlen (basename
);
899 dsymsuffixdir
= ".dSYM/Contents/Resources/DWARF/";
900 dsymsuffixdirlen
= strlen (dsymsuffixdir
);
902 dsymlen
= (dirnamelen
907 dsym
= backtrace_alloc (state
, dsymlen
, error_callback
, data
);
912 memcpy (ps
, dirname
, dirnamelen
);
915 memcpy (ps
, basename
, basenamelen
);
917 memcpy (ps
, dsymsuffixdir
, dsymsuffixdirlen
);
918 ps
+= dsymsuffixdirlen
;
919 memcpy (ps
, basename
, basenamelen
);
925 backtrace_free (state
, diralc
, dirnamelen
, error_callback
, data
);
929 d
= backtrace_open (dsym
, error_callback
, data
, &does_not_exist
);
932 /* The file does not exist, so we can't read the debug info.
933 Just return success. */
934 backtrace_free (state
, dsym
, dsymlen
, error_callback
, data
);
938 if (!macho_add (state
, dsym
, d
, 0, uuid
, base_address
, 1,
939 error_callback
, data
, fileline_fn
, &dummy_found_sym
))
942 backtrace_free (state
, dsym
, dsymlen
, error_callback
, data
);
948 backtrace_free (state
, dsym
, dsymlen
, error_callback
, data
);
950 backtrace_free (state
, diralc
, dirnamelen
, error_callback
, data
);
954 /* Add the backtrace data for a Macho-O file. Returns 1 on success, 0
955 on failure (in both cases descriptor is closed).
957 FILENAME: the name of the executable.
958 DESCRIPTOR: an open descriptor for the executable, closed here.
959 OFFSET: the offset within the file of this executable, for fat files.
960 MATCH_UUID: if not NULL, UUID that must match.
961 BASE_ADDRESS: the load address of the executable.
962 SKIP_SYMTAB: if non-zero, ignore the symbol table; used for dSYM files.
963 FILELINE_FN: set to the fileline function, by backtrace_dwarf_add.
964 FOUND_SYM: set to non-zero if we found the symbol table.
968 macho_add (struct backtrace_state
*state
, const char *filename
, int descriptor
,
969 off_t offset
, const unsigned char *match_uuid
,
970 uintptr_t base_address
, int skip_symtab
,
971 backtrace_error_callback error_callback
, void *data
,
972 fileline
*fileline_fn
, int *found_sym
)
974 struct backtrace_view header_view
;
975 struct macho_header_32 header
;
978 struct backtrace_view cmds_view
;
980 struct dwarf_sections dwarf_sections
;
982 unsigned char uuid
[MACH_O_UUID_LEN
];
991 /* The 32-bit and 64-bit file headers start out the same, so we can
992 just always read the 32-bit version. A fat header is shorter but
993 it will always be followed by data, so it's OK to read extra. */
995 if (!backtrace_get_view (state
, descriptor
, offset
,
996 sizeof (struct macho_header_32
),
997 error_callback
, data
, &header_view
))
1000 memcpy (&header
, header_view
.data
, sizeof header
);
1002 backtrace_release_view (state
, &header_view
, error_callback
, data
);
1004 switch (header
.magic
)
1006 case MACH_O_MH_MAGIC_32
:
1008 hdroffset
= offset
+ sizeof (struct macho_header_32
);
1010 case MACH_O_MH_MAGIC_64
:
1012 hdroffset
= offset
+ sizeof (struct macho_header_64
);
1014 case MACH_O_MH_MAGIC_FAT
:
1015 case MACH_O_MH_MAGIC_FAT_64
:
1017 struct macho_header_fat fat_header
;
1019 hdroffset
= offset
+ sizeof (struct macho_header_fat
);
1020 memcpy (&fat_header
, &header
, sizeof fat_header
);
1021 return macho_add_fat (state
, filename
, descriptor
, 0, hdroffset
,
1022 match_uuid
, base_address
, skip_symtab
,
1023 fat_header
.nfat_arch
,
1024 header
.magic
== MACH_O_MH_MAGIC_FAT_64
,
1025 error_callback
, data
, fileline_fn
, found_sym
);
1027 case MACH_O_MH_CIGAM_FAT
:
1028 case MACH_O_MH_CIGAM_FAT_64
:
1030 struct macho_header_fat fat_header
;
1033 hdroffset
= offset
+ sizeof (struct macho_header_fat
);
1034 memcpy (&fat_header
, &header
, sizeof fat_header
);
1035 nfat_arch
= __builtin_bswap32 (fat_header
.nfat_arch
);
1036 return macho_add_fat (state
, filename
, descriptor
, 1, hdroffset
,
1037 match_uuid
, base_address
, skip_symtab
,
1039 header
.magic
== MACH_O_MH_CIGAM_FAT_64
,
1040 error_callback
, data
, fileline_fn
, found_sym
);
1043 error_callback (data
, "executable file is not in Mach-O format", 0);
1047 switch (header
.filetype
)
1049 case MACH_O_MH_EXECUTE
:
1050 case MACH_O_MH_DYLIB
:
1051 case MACH_O_MH_DSYM
:
1054 error_callback (data
, "executable file is not an executable", 0);
1058 if (!backtrace_get_view (state
, descriptor
, hdroffset
, header
.sizeofcmds
,
1059 error_callback
, data
, &cmds_view
))
1061 cmds_view_valid
= 1;
1063 memset (&dwarf_sections
, 0, sizeof dwarf_sections
);
1065 memset (&uuid
, 0, sizeof uuid
);
1069 for (i
= 0; i
< header
.ncmds
; ++i
)
1072 struct macho_load_command load_command
;
1074 if (cmdoffset
+ sizeof load_command
> header
.sizeofcmds
)
1077 pcmd
= (const char *) cmds_view
.data
+ cmdoffset
;
1078 memcpy (&load_command
, pcmd
, sizeof load_command
);
1080 switch (load_command
.cmd
)
1082 case MACH_O_LC_SEGMENT
:
1084 struct macho_segment_command segcmd
;
1086 memcpy (&segcmd
, pcmd
, sizeof segcmd
);
1087 if (memcmp (segcmd
.segname
,
1088 "__DWARF\0\0\0\0\0\0\0\0\0",
1089 MACH_O_NAMELEN
) == 0)
1091 if (!macho_add_dwarf_segment (state
, descriptor
, offset
,
1093 pcmd
+ sizeof segcmd
,
1094 (load_command
.cmdsize
1096 segcmd
.nsects
, error_callback
,
1097 data
, &dwarf_sections
))
1104 case MACH_O_LC_SEGMENT_64
:
1106 struct macho_segment_64_command segcmd
;
1108 memcpy (&segcmd
, pcmd
, sizeof segcmd
);
1109 if (memcmp (segcmd
.segname
,
1110 "__DWARF\0\0\0\0\0\0\0\0\0",
1111 MACH_O_NAMELEN
) == 0)
1113 if (!macho_add_dwarf_segment (state
, descriptor
, offset
,
1115 pcmd
+ sizeof segcmd
,
1116 (load_command
.cmdsize
1118 segcmd
.nsects
, error_callback
,
1119 data
, &dwarf_sections
))
1126 case MACH_O_LC_SYMTAB
:
1129 struct macho_symtab_command symcmd
;
1131 memcpy (&symcmd
, pcmd
, sizeof symcmd
);
1132 if (!macho_add_symtab (state
, descriptor
, base_address
, is_64
,
1133 offset
+ symcmd
.symoff
, symcmd
.nsyms
,
1134 offset
+ symcmd
.stroff
, symcmd
.strsize
,
1135 error_callback
, data
))
1142 case MACH_O_LC_UUID
:
1144 struct macho_uuid_command uuidcmd
;
1146 memcpy (&uuidcmd
, pcmd
, sizeof uuidcmd
);
1147 memcpy (&uuid
[0], &uuidcmd
.uuid
[0], MACH_O_UUID_LEN
);
1156 cmdoffset
+= load_command
.cmdsize
;
1159 if (!backtrace_close (descriptor
, error_callback
, data
))
1163 backtrace_release_view (state
, &cmds_view
, error_callback
, data
);
1164 cmds_view_valid
= 0;
1166 if (match_uuid
!= NULL
)
1168 /* If we don't have a UUID, or it doesn't match, just ignore
1171 || memcmp (match_uuid
, &uuid
[0], MACH_O_UUID_LEN
) != 0)
1180 #if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)
1181 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
1186 if (!backtrace_dwarf_add (state
, base_address
, &dwarf_sections
,
1187 is_big_endian
, NULL
, error_callback
, data
,
1192 if (!have_dwarf
&& have_uuid
)
1194 if (!macho_add_dsym (state
, filename
, base_address
, &uuid
[0],
1195 error_callback
, data
, fileline_fn
))
1202 if (cmds_view_valid
)
1203 backtrace_release_view (state
, &cmds_view
, error_callback
, data
);
1204 if (descriptor
!= -1)
1205 backtrace_close (descriptor
, error_callback
, data
);
1209 #ifdef HAVE_MACH_O_DYLD_H
1211 /* Initialize the backtrace data we need from a Mach-O executable
1212 using the dyld support functions. This closes descriptor. */
1215 backtrace_initialize (struct backtrace_state
*state
, const char *filename
,
1216 int descriptor
, backtrace_error_callback error_callback
,
1217 void *data
, fileline
*fileline_fn
)
1221 int closed_descriptor
;
1223 fileline macho_fileline_fn
;
1225 closed_descriptor
= 0;
1227 macho_fileline_fn
= macho_nodebug
;
1229 c
= _dyld_image_count ();
1230 for (i
= 0; i
< c
; ++i
)
1232 uintptr_t base_address
;
1238 name
= _dyld_get_image_name (i
);
1242 if (strcmp (name
, filename
) == 0 && !closed_descriptor
)
1245 closed_descriptor
= 1;
1251 d
= backtrace_open (name
, error_callback
, data
, &does_not_exist
);
1256 base_address
= _dyld_get_image_vmaddr_slide (i
);
1258 mff
= macho_nodebug
;
1259 if (!macho_add (state
, name
, d
, 0, NULL
, base_address
, 0,
1260 error_callback
, data
, &mff
, &mfs
))
1263 if (mff
!= macho_nodebug
)
1264 macho_fileline_fn
= mff
;
1269 if (!closed_descriptor
)
1270 backtrace_close (descriptor
, error_callback
, data
);
1272 if (!state
->threaded
)
1275 state
->syminfo_fn
= macho_syminfo
;
1276 else if (state
->syminfo_fn
== NULL
)
1277 state
->syminfo_fn
= macho_nosyms
;
1282 backtrace_atomic_store_pointer (&state
->syminfo_fn
, macho_syminfo
);
1284 (void) __sync_bool_compare_and_swap (&state
->syminfo_fn
, NULL
,
1288 if (!state
->threaded
)
1289 *fileline_fn
= state
->fileline_fn
;
1291 *fileline_fn
= backtrace_atomic_load_pointer (&state
->fileline_fn
);
1293 if (*fileline_fn
== NULL
|| *fileline_fn
== macho_nodebug
)
1294 *fileline_fn
= macho_fileline_fn
;
1299 #else /* !defined (HAVE_MACH_O_DYLD_H) */
1301 /* Initialize the backtrace data we need from a Mach-O executable
1302 without using the dyld support functions. This closes
1306 backtrace_initialize (struct backtrace_state
*state
, const char *filename
,
1307 int descriptor
, backtrace_error_callback error_callback
,
1308 void *data
, fileline
*fileline_fn
)
1310 fileline macho_fileline_fn
;
1313 macho_fileline_fn
= macho_nodebug
;
1314 if (!macho_add (state
, filename
, descriptor
, 0, NULL
, 0, 0,
1315 error_callback
, data
, &macho_fileline_fn
, &found_sym
))
1318 if (!state
->threaded
)
1321 state
->syminfo_fn
= macho_syminfo
;
1322 else if (state
->syminfo_fn
== NULL
)
1323 state
->syminfo_fn
= macho_nosyms
;
1328 backtrace_atomic_store_pointer (&state
->syminfo_fn
, macho_syminfo
);
1330 (void) __sync_bool_compare_and_swap (&state
->syminfo_fn
, NULL
,
1334 if (!state
->threaded
)
1335 *fileline_fn
= state
->fileline_fn
;
1337 *fileline_fn
= backtrace_atomic_load_pointer (&state
->fileline_fn
);
1339 if (*fileline_fn
== NULL
|| *fileline_fn
== macho_nodebug
)
1340 *fileline_fn
= macho_fileline_fn
;
1345 #endif /* !defined (HAVE_MACH_O_DYLD_H) */