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_FAT) */
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
89 /* Value for the header filetype field. */
91 #define MACH_O_MH_EXECUTE 0x02
92 #define MACH_O_MH_DYLIB 0x06
93 #define MACH_O_MH_DSYM 0x0a
95 /* A component of a fat file. A fat file starts with a
96 macho_header_fat followed by nfat_arch instances of this
101 uint32_t cputype
; /* CPU type */
102 uint32_t cpusubtype
; /* CPU subtype */
103 uint32_t offset
; /* File offset of this entry */
104 uint32_t size
; /* Size of this entry */
105 uint32_t align
; /* Alignment of this entry */
108 /* Values for the fat_arch cputype field (and the header cputype
111 #define MACH_O_CPU_ARCH_ABI64 0x01000000
113 #define MACH_O_CPU_TYPE_X86 7
114 #define MACH_O_CPU_TYPE_ARM 12
116 #define MACH_O_CPU_TYPE_X86_64 (MACH_O_CPU_TYPE_X86 | MACH_O_CPU_ARCH_ABI64)
117 #define MACH_O_CPU_TYPE_ARM64 (MACH_O_CPU_TYPE_ARM | MACH_O_CPU_ARCH_ABI64)
119 /* The header of a load command. */
121 struct macho_load_command
123 uint32_t cmd
; /* The type of load command */
124 uint32_t cmdsize
; /* Size in bytes of the entire command */
127 /* Values for the load_command cmd field. */
129 #define MACH_O_LC_SEGMENT 0x01
130 #define MACH_O_LC_SYMTAB 0x02
131 #define MACH_O_LC_SEGMENT_64 0x19
132 #define MACH_O_LC_UUID 0x1b
134 /* The length of a section of segment name. */
136 #define MACH_O_NAMELEN (16)
138 /* LC_SEGMENT load command. */
140 struct macho_segment_command
142 uint32_t cmd
; /* The type of load command (LC_SEGMENT) */
143 uint32_t cmdsize
; /* Size in bytes of the entire command */
144 char segname
[MACH_O_NAMELEN
]; /* Segment name */
145 uint32_t vmaddr
; /* Virtual memory address */
146 uint32_t vmsize
; /* Virtual memory size */
147 uint32_t fileoff
; /* Offset of data to be mapped */
148 uint32_t filesize
; /* Size of data in file */
149 uint32_t maxprot
; /* Maximum permitted virtual protection */
150 uint32_t initprot
; /* Initial virtual memory protection */
151 uint32_t nsects
; /* Number of sections in this segment */
152 uint32_t flags
; /* Flags */
155 /* LC_SEGMENT_64 load command. */
157 struct macho_segment_64_command
159 uint32_t cmd
; /* The type of load command (LC_SEGMENT) */
160 uint32_t cmdsize
; /* Size in bytes of the entire command */
161 char segname
[MACH_O_NAMELEN
]; /* Segment name */
162 uint64_t vmaddr
; /* Virtual memory address */
163 uint64_t vmsize
; /* Virtual memory size */
164 uint64_t fileoff
; /* Offset of data to be mapped */
165 uint64_t filesize
; /* Size of data in file */
166 uint32_t maxprot
; /* Maximum permitted virtual protection */
167 uint32_t initprot
; /* Initial virtual memory protection */
168 uint32_t nsects
; /* Number of sections in this segment */
169 uint32_t flags
; /* Flags */
172 /* LC_SYMTAB load command. */
174 struct macho_symtab_command
176 uint32_t cmd
; /* The type of load command (LC_SEGMENT) */
177 uint32_t cmdsize
; /* Size in bytes of the entire command */
178 uint32_t symoff
; /* File offset of symbol table */
179 uint32_t nsyms
; /* Number of symbols */
180 uint32_t stroff
; /* File offset of string table */
181 uint32_t strsize
; /* String table size */
184 /* The length of a Mach-O uuid. */
186 #define MACH_O_UUID_LEN (16)
188 /* LC_UUID load command. */
190 struct macho_uuid_command
192 uint32_t cmd
; /* Type of load command (LC_UUID) */
193 uint32_t cmdsize
; /* Size in bytes of command */
194 unsigned char uuid
[MACH_O_UUID_LEN
]; /* UUID */
197 /* 32-bit section header within a LC_SEGMENT segment. */
201 char sectname
[MACH_O_NAMELEN
]; /* Section name */
202 char segment
[MACH_O_NAMELEN
]; /* Segment of this section */
203 uint32_t addr
; /* Address in memory */
204 uint32_t size
; /* Section size */
205 uint32_t offset
; /* File offset */
206 uint32_t align
; /* Log2 of section alignment */
207 uint32_t reloff
; /* File offset of relocations */
208 uint32_t nreloc
; /* Number of relocs for this section */
209 uint32_t flags
; /* Flags */
214 /* 64-bit section header within a LC_SEGMENT_64 segment. */
216 struct macho_section_64
218 char sectname
[MACH_O_NAMELEN
]; /* Section name */
219 char segment
[MACH_O_NAMELEN
]; /* Segment of this section */
220 uint64_t addr
; /* Address in memory */
221 uint64_t size
; /* Section size */
222 uint32_t offset
; /* File offset */
223 uint32_t align
; /* Log2 of section alignment */
224 uint32_t reloff
; /* File offset of section relocations */
225 uint32_t nreloc
; /* Number of relocs for this section */
226 uint32_t flags
; /* Flags */
232 /* 32-bit symbol data. */
236 uint32_t n_strx
; /* Index of name in string table */
237 uint8_t n_type
; /* Type flag */
238 uint8_t n_sect
; /* Section number */
239 uint16_t n_desc
; /* Stabs description field */
240 uint32_t n_value
; /* Value */
243 /* 64-bit symbol data. */
245 struct macho_nlist_64
247 uint32_t n_strx
; /* Index of name in string table */
248 uint8_t n_type
; /* Type flag */
249 uint8_t n_sect
; /* Section number */
250 uint16_t n_desc
; /* Stabs description field */
251 uint64_t n_value
; /* Value */
254 /* Value found in nlist n_type field. */
256 #define MACH_O_N_EXT 0x01 /* Extern symbol */
257 #define MACH_O_N_ABS 0x02 /* Absolute symbol */
258 #define MACH_O_N_SECT 0x0e /* Defined in section */
260 #define MACH_O_N_TYPE 0x0e /* Mask for type bits */
261 #define MACH_O_N_STAB 0xe0 /* Stabs debugging symbol */
263 /* Information we keep for a Mach-O symbol. */
267 const char *name
; /* Symbol name */
268 uintptr_t address
; /* Symbol address */
271 /* Information to pass to macho_syminfo. */
273 struct macho_syminfo_data
275 struct macho_syminfo_data
*next
; /* Next module */
276 struct macho_symbol
*symbols
; /* Symbols sorted by address */
277 size_t count
; /* Number of symbols */
280 /* Names of sections, indexed by enum dwarf_section in internal.h. */
282 static const char * const dwarf_section_names
[DEBUG_MAX
] =
291 "", /* DEBUG_LINE_STR */
295 /* Forward declaration. */
297 static int macho_add (struct backtrace_state
*, const char *, int, off_t
,
298 const unsigned char *, uintptr_t, int,
299 backtrace_error_callback
, void *, fileline
*, int *);
301 /* A dummy callback function used when we can't find any debug info. */
304 macho_nodebug (struct backtrace_state
*state ATTRIBUTE_UNUSED
,
305 uintptr_t pc ATTRIBUTE_UNUSED
,
306 backtrace_full_callback callback ATTRIBUTE_UNUSED
,
307 backtrace_error_callback error_callback
, void *data
)
309 error_callback (data
, "no debug info in Mach-O executable", -1);
313 /* A dummy callback function used when we can't find a symbol
317 macho_nosyms (struct backtrace_state
*state ATTRIBUTE_UNUSED
,
318 uintptr_t addr ATTRIBUTE_UNUSED
,
319 backtrace_syminfo_callback callback ATTRIBUTE_UNUSED
,
320 backtrace_error_callback error_callback
, void *data
)
322 error_callback (data
, "no symbol table in Mach-O executable", -1);
325 /* Add a single DWARF section to DWARF_SECTIONS, if we need the
326 section. Returns 1 on success, 0 on failure. */
329 macho_add_dwarf_section (struct backtrace_state
*state
, int descriptor
,
330 const char *sectname
, uint32_t offset
, uint64_t size
,
331 backtrace_error_callback error_callback
, void *data
,
332 struct dwarf_sections
*dwarf_sections
)
336 for (i
= 0; i
< (int) DEBUG_MAX
; ++i
)
338 if (dwarf_section_names
[i
][0] != '\0'
339 && strncmp (sectname
, dwarf_section_names
[i
], MACH_O_NAMELEN
) == 0)
341 struct backtrace_view section_view
;
343 /* FIXME: Perhaps it would be better to try to use a single
344 view to read all the DWARF data, as we try to do for
347 if (!backtrace_get_view (state
, descriptor
, offset
, size
,
348 error_callback
, data
, §ion_view
))
350 dwarf_sections
->data
[i
] = (const unsigned char *) section_view
.data
;
351 dwarf_sections
->size
[i
] = size
;
358 /* Collect DWARF sections from a DWARF segment. Returns 1 on success,
362 macho_add_dwarf_segment (struct backtrace_state
*state
, int descriptor
,
363 off_t offset
, unsigned int cmd
, const char *psecs
,
364 size_t sizesecs
, unsigned int nsects
,
365 backtrace_error_callback error_callback
, void *data
,
366 struct dwarf_sections
*dwarf_sections
)
368 size_t sec_header_size
;
374 case MACH_O_LC_SEGMENT
:
375 sec_header_size
= sizeof (struct macho_section
);
377 case MACH_O_LC_SEGMENT_64
:
378 sec_header_size
= sizeof (struct macho_section_64
);
385 for (i
= 0; i
< nsects
; ++i
)
387 if (secoffset
+ sec_header_size
> sizesecs
)
389 error_callback (data
, "section overflow withing segment", 0);
395 case MACH_O_LC_SEGMENT
:
397 struct macho_section section
;
399 memcpy (§ion
, psecs
+ secoffset
, sizeof section
);
400 macho_add_dwarf_section (state
, descriptor
, section
.sectname
,
401 offset
+ section
.offset
, section
.size
,
402 error_callback
, data
, dwarf_sections
);
406 case MACH_O_LC_SEGMENT_64
:
408 struct macho_section_64 section
;
410 memcpy (§ion
, psecs
+ secoffset
, sizeof section
);
411 macho_add_dwarf_section (state
, descriptor
, section
.sectname
,
412 offset
+ section
.offset
, section
.size
,
413 error_callback
, data
, dwarf_sections
);
421 secoffset
+= sec_header_size
;
427 /* Compare struct macho_symbol for qsort. */
430 macho_symbol_compare (const void *v1
, const void *v2
)
432 const struct macho_symbol
*m1
= (const struct macho_symbol
*) v1
;
433 const struct macho_symbol
*m2
= (const struct macho_symbol
*) v2
;
435 if (m1
->address
< m2
->address
)
437 else if (m1
->address
> m2
->address
)
443 /* Compare an address against a macho_symbol for bsearch. We allocate
444 one extra entry in the array so that this can safely look at the
448 macho_symbol_search (const void *vkey
, const void *ventry
)
450 const uintptr_t *key
= (const uintptr_t *) vkey
;
451 const struct macho_symbol
*entry
= (const struct macho_symbol
*) ventry
;
455 if (addr
< entry
->address
)
457 else if (entry
->name
[0] == '\0'
458 && entry
->address
== ~(uintptr_t) 0)
460 else if ((entry
+ 1)->name
[0] == '\0'
461 && (entry
+ 1)->address
== ~(uintptr_t) 0)
463 else if (addr
>= (entry
+ 1)->address
)
469 /* Return whether the symbol type field indicates a symbol table entry
470 that we care about: a function or data symbol. */
473 macho_defined_symbol (uint8_t type
)
475 if ((type
& MACH_O_N_STAB
) != 0)
477 if ((type
& MACH_O_N_EXT
) != 0)
479 switch (type
& MACH_O_N_TYPE
)
490 /* Add symbol table information for a Mach-O file. */
493 macho_add_symtab (struct backtrace_state
*state
, int descriptor
,
494 uintptr_t base_address
, int is_64
,
495 off_t symoff
, unsigned int nsyms
, off_t stroff
,
496 unsigned int strsize
,
497 backtrace_error_callback error_callback
, void *data
)
500 struct backtrace_view sym_view
;
502 struct backtrace_view str_view
;
507 size_t macho_symbol_size
;
508 struct macho_symbol
*macho_symbols
;
510 struct macho_syminfo_data
*sdata
;
514 macho_symbol_size
= 0;
515 macho_symbols
= NULL
;
518 symsize
= sizeof (struct macho_nlist_64
);
520 symsize
= sizeof (struct macho_nlist
);
522 if (!backtrace_get_view (state
, descriptor
, symoff
, nsyms
* symsize
,
523 error_callback
, data
, &sym_view
))
527 if (!backtrace_get_view (state
, descriptor
, stroff
, strsize
,
528 error_callback
, data
, &str_view
))
534 for (i
= 0; i
< nsyms
; ++i
, symtaboff
+= symsize
)
538 struct macho_nlist_64 nlist
;
540 memcpy (&nlist
, (const char *) sym_view
.data
+ symtaboff
,
542 if (macho_defined_symbol (nlist
.n_type
))
547 struct macho_nlist nlist
;
549 memcpy (&nlist
, (const char *) sym_view
.data
+ symtaboff
,
551 if (macho_defined_symbol (nlist
.n_type
))
556 /* Add 1 to ndefs to make room for a sentinel. */
557 macho_symbol_size
= (ndefs
+ 1) * sizeof (struct macho_symbol
);
558 macho_symbols
= ((struct macho_symbol
*)
559 backtrace_alloc (state
, macho_symbol_size
, error_callback
,
561 if (macho_symbols
== NULL
)
566 for (i
= 0; i
< nsyms
; ++i
, symtaboff
+= symsize
)
576 struct macho_nlist_64 nlist
;
578 memcpy (&nlist
, (const char *) sym_view
.data
+ symtaboff
,
580 if (!macho_defined_symbol (nlist
.n_type
))
584 value
= nlist
.n_value
;
588 struct macho_nlist nlist
;
590 memcpy (&nlist
, (const char *) sym_view
.data
+ symtaboff
,
592 if (!macho_defined_symbol (nlist
.n_type
))
596 value
= nlist
.n_value
;
601 error_callback (data
, "symbol string index out of range", 0);
605 name
= (const char *) str_view
.data
+ strx
;
608 macho_symbols
[j
].name
= name
;
609 macho_symbols
[j
].address
= value
+ base_address
;
613 sdata
= ((struct macho_syminfo_data
*)
614 backtrace_alloc (state
, sizeof *sdata
, error_callback
, data
));
618 /* We need to keep the string table since it holds the names, but we
619 can release the symbol table. */
621 backtrace_release_view (state
, &sym_view
, error_callback
, data
);
625 /* Add a trailing sentinel symbol. */
626 macho_symbols
[j
].name
= "";
627 macho_symbols
[j
].address
= ~(uintptr_t) 0;
629 backtrace_qsort (macho_symbols
, ndefs
+ 1, sizeof (struct macho_symbol
),
630 macho_symbol_compare
);
633 sdata
->symbols
= macho_symbols
;
634 sdata
->count
= ndefs
;
636 if (!state
->threaded
)
638 struct macho_syminfo_data
**pp
;
640 for (pp
= (struct macho_syminfo_data
**) (void *) &state
->syminfo_data
;
650 struct macho_syminfo_data
**pp
;
652 pp
= (struct macho_syminfo_data
**) (void *) &state
->syminfo_data
;
656 struct macho_syminfo_data
*p
;
658 p
= backtrace_atomic_load_pointer (pp
);
666 if (__sync_bool_compare_and_swap (pp
, NULL
, sdata
))
674 if (macho_symbols
!= NULL
)
675 backtrace_free (state
, macho_symbols
, macho_symbol_size
,
676 error_callback
, data
);
678 backtrace_release_view (state
, &sym_view
, error_callback
, data
);
680 backtrace_release_view (state
, &str_view
, error_callback
, data
);
684 /* Return the symbol name and value for an ADDR. */
687 macho_syminfo (struct backtrace_state
*state
, uintptr_t addr
,
688 backtrace_syminfo_callback callback
,
689 backtrace_error_callback error_callback ATTRIBUTE_UNUSED
,
692 struct macho_syminfo_data
*sdata
;
693 struct macho_symbol
*sym
;
696 if (!state
->threaded
)
698 for (sdata
= (struct macho_syminfo_data
*) state
->syminfo_data
;
702 sym
= ((struct macho_symbol
*)
703 bsearch (&addr
, sdata
->symbols
, sdata
->count
,
704 sizeof (struct macho_symbol
), macho_symbol_search
));
711 struct macho_syminfo_data
**pp
;
713 pp
= (struct macho_syminfo_data
**) (void *) &state
->syminfo_data
;
716 sdata
= backtrace_atomic_load_pointer (pp
);
720 sym
= ((struct macho_symbol
*)
721 bsearch (&addr
, sdata
->symbols
, sdata
->count
,
722 sizeof (struct macho_symbol
), macho_symbol_search
));
731 callback (data
, addr
, NULL
, 0, 0);
733 callback (data
, addr
, sym
->name
, sym
->address
, 0);
736 /* Look through a fat file to find the relevant executable. Returns 1
737 on success, 0 on failure (in both cases descriptor is closed). */
740 macho_add_fat (struct backtrace_state
*state
, const char *filename
,
741 int descriptor
, int swapped
, off_t offset
,
742 const unsigned char *match_uuid
, uintptr_t base_address
,
743 int skip_symtab
, uint32_t nfat_arch
,
744 backtrace_error_callback error_callback
, void *data
,
745 fileline
*fileline_fn
, int *found_sym
)
748 unsigned int cputype
;
749 struct backtrace_view arch_view
;
755 #if defined (__x86_64__)
756 cputype
= MACH_O_CPU_TYPE_X86_64
;
757 #elif defined (__i386__)
758 cputype
= MACH_O_CPU_TYPE_X86
;
759 #elif defined (__aarch64__)
760 cputype
= MACH_O_CPU_TYPE_ARM64
;
761 #elif defined (__arm__)
762 cputype
= MACH_O_CPU_TYPE_ARM
;
764 error_callback (data
, "unknown Mach-O architecture", 0);
768 if (!backtrace_get_view (state
, descriptor
, offset
,
769 nfat_arch
* sizeof (struct macho_fat_arch
),
770 error_callback
, data
, &arch_view
))
774 for (i
= 0; i
< nfat_arch
; ++i
)
776 struct macho_fat_arch fat_arch
;
780 ((const char *) arch_view
.data
781 + i
* sizeof (struct macho_fat_arch
)),
784 fcputype
= fat_arch
.cputype
;
786 fcputype
= __builtin_bswap32 (fcputype
);
788 if (fcputype
== cputype
)
792 /* FIXME: What about cpusubtype? */
793 foffset
= fat_arch
.offset
;
795 foffset
= __builtin_bswap32 (foffset
);
796 backtrace_release_view (state
, &arch_view
, error_callback
, data
);
797 return macho_add (state
, filename
, descriptor
, foffset
, match_uuid
,
798 base_address
, skip_symtab
, error_callback
, data
,
799 fileline_fn
, found_sym
);
802 archoffset
+= sizeof (struct macho_fat_arch
);
805 error_callback (data
, "could not find executable in fat file", 0);
809 backtrace_release_view (state
, &arch_view
, error_callback
, data
);
810 if (descriptor
!= -1)
811 backtrace_close (descriptor
, error_callback
, data
);
815 /* Look for the dsym file for FILENAME. This is called if FILENAME
816 does not have debug info or a symbol table. Returns 1 on success,
820 macho_add_dsym (struct backtrace_state
*state
, const char *filename
,
821 uintptr_t base_address
, const unsigned char *uuid
,
822 backtrace_error_callback error_callback
, void *data
,
823 fileline
* fileline_fn
)
829 const char *basename
;
831 const char *dsymsuffixdir
;
832 size_t dsymsuffixdirlen
;
845 p
= strrchr (filename
, '/');
851 basenamelen
= strlen (basename
);
856 dirnamelen
= p
- filename
;
857 diralc
= backtrace_alloc (state
, dirnamelen
+ 1, error_callback
, data
);
860 memcpy (diralc
, filename
, dirnamelen
);
861 diralc
[dirnamelen
] = '\0';
864 basenamelen
= strlen (basename
);
867 dsymsuffixdir
= ".dSYM/Contents/Resources/DWARF/";
868 dsymsuffixdirlen
= strlen (dsymsuffixdir
);
870 dsymlen
= (dirnamelen
875 dsym
= backtrace_alloc (state
, dsymlen
, error_callback
, data
);
880 memcpy (ps
, dirname
, dirnamelen
);
883 memcpy (ps
, basename
, basenamelen
);
885 memcpy (ps
, dsymsuffixdir
, dsymsuffixdirlen
);
886 ps
+= dsymsuffixdirlen
;
887 memcpy (ps
, basename
, basenamelen
);
893 backtrace_free (state
, diralc
, dirnamelen
, error_callback
, data
);
897 d
= backtrace_open (dsym
, error_callback
, data
, &does_not_exist
);
900 /* The file does not exist, so we can't read the debug info.
901 Just return success. */
902 backtrace_free (state
, dsym
, dsymlen
, error_callback
, data
);
906 if (!macho_add (state
, dsym
, d
, 0, uuid
, base_address
, 1,
907 error_callback
, data
, fileline_fn
, &dummy_found_sym
))
910 backtrace_free (state
, dsym
, dsymlen
, error_callback
, data
);
916 backtrace_free (state
, dsym
, dsymlen
, error_callback
, data
);
918 backtrace_free (state
, diralc
, dirnamelen
, error_callback
, data
);
922 /* Add the backtrace data for a Macho-O file. Returns 1 on success, 0
923 on failure (in both cases descriptor is closed).
925 FILENAME: the name of the executable.
926 DESCRIPTOR: an open descriptor for the executable, closed here.
927 OFFSET: the offset within the file of this executable, for fat files.
928 MATCH_UUID: if not NULL, UUID that must match.
929 BASE_ADDRESS: the load address of the executable.
930 SKIP_SYMTAB: if non-zero, ignore the symbol table; used for dSYM files.
931 FILELINE_FN: set to the fileline function, by backtrace_dwarf_add.
932 FOUND_SYM: set to non-zero if we found the symbol table.
936 macho_add (struct backtrace_state
*state
, const char *filename
, int descriptor
,
937 off_t offset
, const unsigned char *match_uuid
,
938 uintptr_t base_address
, int skip_symtab
,
939 backtrace_error_callback error_callback
, void *data
,
940 fileline
*fileline_fn
, int *found_sym
)
942 struct backtrace_view header_view
;
943 struct macho_header_32 header
;
946 struct backtrace_view cmds_view
;
948 struct dwarf_sections dwarf_sections
;
950 unsigned char uuid
[MACH_O_UUID_LEN
];
959 /* The 32-bit and 64-bit file headers start out the same, so we can
960 just always read the 32-bit version. A fat header is shorter but
961 it will always be followed by data, so it's OK to read extra. */
963 if (!backtrace_get_view (state
, descriptor
, offset
,
964 sizeof (struct macho_header_32
),
965 error_callback
, data
, &header_view
))
968 memcpy (&header
, header_view
.data
, sizeof header
);
970 backtrace_release_view (state
, &header_view
, error_callback
, data
);
972 switch (header
.magic
)
974 case MACH_O_MH_MAGIC_32
:
976 hdroffset
= offset
+ sizeof (struct macho_header_32
);
978 case MACH_O_MH_MAGIC_64
:
980 hdroffset
= offset
+ sizeof (struct macho_header_64
);
982 case MACH_O_MH_MAGIC_FAT
:
984 struct macho_header_fat fat_header
;
986 hdroffset
= offset
+ sizeof (struct macho_header_fat
);
987 memcpy (&fat_header
, &header
, sizeof fat_header
);
988 return macho_add_fat (state
, filename
, descriptor
, 0, hdroffset
,
989 match_uuid
, base_address
, skip_symtab
,
990 fat_header
.nfat_arch
, error_callback
, data
,
991 fileline_fn
, found_sym
);
993 case MACH_O_MH_CIGAM_FAT
:
995 struct macho_header_fat fat_header
;
998 hdroffset
= offset
+ sizeof (struct macho_header_fat
);
999 memcpy (&fat_header
, &header
, sizeof fat_header
);
1000 nfat_arch
= __builtin_bswap32 (fat_header
.nfat_arch
);
1001 return macho_add_fat (state
, filename
, descriptor
, 1, hdroffset
,
1002 match_uuid
, base_address
, skip_symtab
,
1003 nfat_arch
, error_callback
, data
,
1004 fileline_fn
, found_sym
);
1007 error_callback (data
, "executable file is not in Mach-O format", 0);
1011 switch (header
.filetype
)
1013 case MACH_O_MH_EXECUTE
:
1014 case MACH_O_MH_DYLIB
:
1015 case MACH_O_MH_DSYM
:
1018 error_callback (data
, "executable file is not an executable", 0);
1022 if (!backtrace_get_view (state
, descriptor
, hdroffset
, header
.sizeofcmds
,
1023 error_callback
, data
, &cmds_view
))
1025 cmds_view_valid
= 1;
1027 memset (&dwarf_sections
, 0, sizeof dwarf_sections
);
1029 memset (&uuid
, 0, sizeof uuid
);
1033 for (i
= 0; i
< header
.ncmds
; ++i
)
1036 struct macho_load_command load_command
;
1038 if (cmdoffset
+ sizeof load_command
> header
.sizeofcmds
)
1041 pcmd
= (const char *) cmds_view
.data
+ cmdoffset
;
1042 memcpy (&load_command
, pcmd
, sizeof load_command
);
1044 switch (load_command
.cmd
)
1046 case MACH_O_LC_SEGMENT
:
1048 struct macho_segment_command segcmd
;
1050 memcpy (&segcmd
, pcmd
, sizeof segcmd
);
1051 if (memcmp (segcmd
.segname
,
1052 "__DWARF\0\0\0\0\0\0\0\0\0",
1053 MACH_O_NAMELEN
) == 0)
1055 if (!macho_add_dwarf_segment (state
, descriptor
, offset
,
1057 pcmd
+ sizeof segcmd
,
1058 (load_command
.cmdsize
1060 segcmd
.nsects
, error_callback
,
1061 data
, &dwarf_sections
))
1068 case MACH_O_LC_SEGMENT_64
:
1070 struct macho_segment_64_command segcmd
;
1072 memcpy (&segcmd
, pcmd
, sizeof segcmd
);
1073 if (memcmp (segcmd
.segname
,
1074 "__DWARF\0\0\0\0\0\0\0\0\0",
1075 MACH_O_NAMELEN
) == 0)
1077 if (!macho_add_dwarf_segment (state
, descriptor
, offset
,
1079 pcmd
+ sizeof segcmd
,
1080 (load_command
.cmdsize
1082 segcmd
.nsects
, error_callback
,
1083 data
, &dwarf_sections
))
1090 case MACH_O_LC_SYMTAB
:
1093 struct macho_symtab_command symcmd
;
1095 memcpy (&symcmd
, pcmd
, sizeof symcmd
);
1096 if (!macho_add_symtab (state
, descriptor
, base_address
, is_64
,
1097 offset
+ symcmd
.symoff
, symcmd
.nsyms
,
1098 offset
+ symcmd
.stroff
, symcmd
.strsize
,
1099 error_callback
, data
))
1106 case MACH_O_LC_UUID
:
1108 struct macho_uuid_command uuidcmd
;
1110 memcpy (&uuidcmd
, pcmd
, sizeof uuidcmd
);
1111 memcpy (&uuid
[0], &uuidcmd
.uuid
[0], MACH_O_UUID_LEN
);
1120 cmdoffset
+= load_command
.cmdsize
;
1123 if (!backtrace_close (descriptor
, error_callback
, data
))
1127 backtrace_release_view (state
, &cmds_view
, error_callback
, data
);
1128 cmds_view_valid
= 0;
1130 if (match_uuid
!= NULL
)
1132 /* If we don't have a UUID, or it doesn't match, just ignore
1135 || memcmp (match_uuid
, &uuid
[0], MACH_O_UUID_LEN
) != 0)
1144 #if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)
1145 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
1150 if (!backtrace_dwarf_add (state
, base_address
, &dwarf_sections
,
1151 is_big_endian
, NULL
, error_callback
, data
,
1156 if (!have_dwarf
&& have_uuid
)
1158 if (!macho_add_dsym (state
, filename
, base_address
, &uuid
[0],
1159 error_callback
, data
, fileline_fn
))
1166 if (cmds_view_valid
)
1167 backtrace_release_view (state
, &cmds_view
, error_callback
, data
);
1168 if (descriptor
!= -1)
1169 backtrace_close (descriptor
, error_callback
, data
);
1173 #ifdef HAVE_MACH_O_DYLD_H
1175 /* Initialize the backtrace data we need from a Mach-O executable
1176 using the dyld support functions. This closes descriptor. */
1179 backtrace_initialize (struct backtrace_state
*state
, const char *filename
,
1180 int descriptor
, backtrace_error_callback error_callback
,
1181 void *data
, fileline
*fileline_fn
)
1185 int closed_descriptor
;
1187 fileline macho_fileline_fn
;
1189 closed_descriptor
= 0;
1191 macho_fileline_fn
= macho_nodebug
;
1193 c
= _dyld_image_count ();
1194 for (i
= 0; i
< c
; ++i
)
1196 uintptr_t base_address
;
1202 name
= _dyld_get_image_name (i
);
1206 if (strcmp (name
, filename
) == 0 && !closed_descriptor
)
1209 closed_descriptor
= 1;
1215 d
= backtrace_open (name
, error_callback
, data
, &does_not_exist
);
1220 base_address
= _dyld_get_image_vmaddr_slide (i
);
1222 mff
= macho_nodebug
;
1223 if (!macho_add (state
, name
, d
, 0, NULL
, base_address
, 0,
1224 error_callback
, data
, &mff
, &mfs
))
1227 if (mff
!= macho_nodebug
)
1228 macho_fileline_fn
= mff
;
1233 if (!closed_descriptor
)
1234 backtrace_close (descriptor
, error_callback
, data
);
1236 if (!state
->threaded
)
1239 state
->syminfo_fn
= macho_syminfo
;
1240 else if (state
->syminfo_fn
== NULL
)
1241 state
->syminfo_fn
= macho_nosyms
;
1246 backtrace_atomic_store_pointer (&state
->syminfo_fn
, macho_syminfo
);
1248 (void) __sync_bool_compare_and_swap (&state
->syminfo_fn
, NULL
,
1252 if (!state
->threaded
)
1253 *fileline_fn
= state
->fileline_fn
;
1255 *fileline_fn
= backtrace_atomic_load_pointer (&state
->fileline_fn
);
1257 if (*fileline_fn
== NULL
|| *fileline_fn
== macho_nodebug
)
1258 *fileline_fn
= macho_fileline_fn
;
1263 #else /* !defined (HAVE_MACH_O_DYLD_H) */
1265 /* Initialize the backtrace data we need from a Mach-O executable
1266 without using the dyld support functions. This closes
1270 backtrace_initialize (struct backtrace_state
*state
, const char *filename
,
1271 int descriptor
, backtrace_error_callback error_callback
,
1272 void *data
, fileline
*fileline_fn
)
1274 fileline macho_fileline_fn
;
1277 macho_fileline_fn
= macho_nodebug
;
1278 if (!macho_add (state
, filename
, descriptor
, 0, NULL
, 0, 0,
1279 error_callback
, data
, &macho_fileline_fn
, &found_sym
))
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 #endif /* !defined (HAVE_MACH_O_DYLD_H) */