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
)
801 struct macho_fat_arch_64 fat_arch_64
;
803 memcpy (&fat_arch_64
,
804 (const char *) arch_view
.data
+ i
* arch_size
,
806 fcputype
= fat_arch_64
.cputype
;
807 foffset
= fat_arch_64
.offset
;
810 fcputype
= __builtin_bswap32 (fcputype
);
811 foffset
= __builtin_bswap64 (foffset
);
816 struct macho_fat_arch fat_arch_32
;
818 memcpy (&fat_arch_32
,
819 (const char *) arch_view
.data
+ i
* arch_size
,
821 fcputype
= fat_arch_32
.cputype
;
822 foffset
= (uint64_t) fat_arch_32
.offset
;
825 fcputype
= __builtin_bswap32 (fcputype
);
826 foffset
= (uint64_t) __builtin_bswap32 ((uint32_t) foffset
);
830 if (fcputype
== cputype
)
832 /* FIXME: What about cpusubtype? */
833 backtrace_release_view (state
, &arch_view
, error_callback
, data
);
834 return macho_add (state
, filename
, descriptor
, foffset
, match_uuid
,
835 base_address
, skip_symtab
, error_callback
, data
,
836 fileline_fn
, found_sym
);
840 error_callback (data
, "could not find executable in fat file", 0);
844 backtrace_release_view (state
, &arch_view
, error_callback
, data
);
845 if (descriptor
!= -1)
846 backtrace_close (descriptor
, error_callback
, data
);
850 /* Look for the dsym file for FILENAME. This is called if FILENAME
851 does not have debug info or a symbol table. Returns 1 on success,
855 macho_add_dsym (struct backtrace_state
*state
, const char *filename
,
856 uintptr_t base_address
, const unsigned char *uuid
,
857 backtrace_error_callback error_callback
, void *data
,
858 fileline
* fileline_fn
)
864 const char *basename
;
866 const char *dsymsuffixdir
;
867 size_t dsymsuffixdirlen
;
880 p
= strrchr (filename
, '/');
886 basenamelen
= strlen (basename
);
891 dirnamelen
= p
- filename
;
892 diralc
= backtrace_alloc (state
, dirnamelen
+ 1, error_callback
, data
);
895 memcpy (diralc
, filename
, dirnamelen
);
896 diralc
[dirnamelen
] = '\0';
899 basenamelen
= strlen (basename
);
902 dsymsuffixdir
= ".dSYM/Contents/Resources/DWARF/";
903 dsymsuffixdirlen
= strlen (dsymsuffixdir
);
905 dsymlen
= (dirnamelen
910 dsym
= backtrace_alloc (state
, dsymlen
, error_callback
, data
);
915 memcpy (ps
, dirname
, dirnamelen
);
918 memcpy (ps
, basename
, basenamelen
);
920 memcpy (ps
, dsymsuffixdir
, dsymsuffixdirlen
);
921 ps
+= dsymsuffixdirlen
;
922 memcpy (ps
, basename
, basenamelen
);
928 backtrace_free (state
, diralc
, dirnamelen
, error_callback
, data
);
932 d
= backtrace_open (dsym
, error_callback
, data
, &does_not_exist
);
935 /* The file does not exist, so we can't read the debug info.
936 Just return success. */
937 backtrace_free (state
, dsym
, dsymlen
, error_callback
, data
);
941 if (!macho_add (state
, dsym
, d
, 0, uuid
, base_address
, 1,
942 error_callback
, data
, fileline_fn
, &dummy_found_sym
))
945 backtrace_free (state
, dsym
, dsymlen
, error_callback
, data
);
951 backtrace_free (state
, dsym
, dsymlen
, error_callback
, data
);
953 backtrace_free (state
, diralc
, dirnamelen
, error_callback
, data
);
957 /* Add the backtrace data for a Macho-O file. Returns 1 on success, 0
958 on failure (in both cases descriptor is closed).
960 FILENAME: the name of the executable.
961 DESCRIPTOR: an open descriptor for the executable, closed here.
962 OFFSET: the offset within the file of this executable, for fat files.
963 MATCH_UUID: if not NULL, UUID that must match.
964 BASE_ADDRESS: the load address of the executable.
965 SKIP_SYMTAB: if non-zero, ignore the symbol table; used for dSYM files.
966 FILELINE_FN: set to the fileline function, by backtrace_dwarf_add.
967 FOUND_SYM: set to non-zero if we found the symbol table.
971 macho_add (struct backtrace_state
*state
, const char *filename
, int descriptor
,
972 off_t offset
, const unsigned char *match_uuid
,
973 uintptr_t base_address
, int skip_symtab
,
974 backtrace_error_callback error_callback
, void *data
,
975 fileline
*fileline_fn
, int *found_sym
)
977 struct backtrace_view header_view
;
978 struct macho_header_32 header
;
981 struct backtrace_view cmds_view
;
983 struct dwarf_sections dwarf_sections
;
985 unsigned char uuid
[MACH_O_UUID_LEN
];
994 /* The 32-bit and 64-bit file headers start out the same, so we can
995 just always read the 32-bit version. A fat header is shorter but
996 it will always be followed by data, so it's OK to read extra. */
998 if (!backtrace_get_view (state
, descriptor
, offset
,
999 sizeof (struct macho_header_32
),
1000 error_callback
, data
, &header_view
))
1003 memcpy (&header
, header_view
.data
, sizeof header
);
1005 backtrace_release_view (state
, &header_view
, error_callback
, data
);
1007 switch (header
.magic
)
1009 case MACH_O_MH_MAGIC_32
:
1011 hdroffset
= offset
+ sizeof (struct macho_header_32
);
1013 case MACH_O_MH_MAGIC_64
:
1015 hdroffset
= offset
+ sizeof (struct macho_header_64
);
1017 case MACH_O_MH_MAGIC_FAT
:
1018 case MACH_O_MH_MAGIC_FAT_64
:
1020 struct macho_header_fat fat_header
;
1022 hdroffset
= offset
+ sizeof (struct macho_header_fat
);
1023 memcpy (&fat_header
, &header
, sizeof fat_header
);
1024 return macho_add_fat (state
, filename
, descriptor
, 0, hdroffset
,
1025 match_uuid
, base_address
, skip_symtab
,
1026 fat_header
.nfat_arch
,
1027 header
.magic
== MACH_O_MH_MAGIC_FAT_64
,
1028 error_callback
, data
, fileline_fn
, found_sym
);
1030 case MACH_O_MH_CIGAM_FAT
:
1031 case MACH_O_MH_CIGAM_FAT_64
:
1033 struct macho_header_fat fat_header
;
1036 hdroffset
= offset
+ sizeof (struct macho_header_fat
);
1037 memcpy (&fat_header
, &header
, sizeof fat_header
);
1038 nfat_arch
= __builtin_bswap32 (fat_header
.nfat_arch
);
1039 return macho_add_fat (state
, filename
, descriptor
, 1, hdroffset
,
1040 match_uuid
, base_address
, skip_symtab
,
1042 header
.magic
== MACH_O_MH_CIGAM_FAT_64
,
1043 error_callback
, data
, fileline_fn
, found_sym
);
1046 error_callback (data
, "executable file is not in Mach-O format", 0);
1050 switch (header
.filetype
)
1052 case MACH_O_MH_EXECUTE
:
1053 case MACH_O_MH_DYLIB
:
1054 case MACH_O_MH_DSYM
:
1057 error_callback (data
, "executable file is not an executable", 0);
1061 if (!backtrace_get_view (state
, descriptor
, hdroffset
, header
.sizeofcmds
,
1062 error_callback
, data
, &cmds_view
))
1064 cmds_view_valid
= 1;
1066 memset (&dwarf_sections
, 0, sizeof dwarf_sections
);
1068 memset (&uuid
, 0, sizeof uuid
);
1072 for (i
= 0; i
< header
.ncmds
; ++i
)
1075 struct macho_load_command load_command
;
1077 if (cmdoffset
+ sizeof load_command
> header
.sizeofcmds
)
1080 pcmd
= (const char *) cmds_view
.data
+ cmdoffset
;
1081 memcpy (&load_command
, pcmd
, sizeof load_command
);
1083 switch (load_command
.cmd
)
1085 case MACH_O_LC_SEGMENT
:
1087 struct macho_segment_command segcmd
;
1089 memcpy (&segcmd
, pcmd
, sizeof segcmd
);
1090 if (memcmp (segcmd
.segname
,
1091 "__DWARF\0\0\0\0\0\0\0\0\0",
1092 MACH_O_NAMELEN
) == 0)
1094 if (!macho_add_dwarf_segment (state
, descriptor
, offset
,
1096 pcmd
+ sizeof segcmd
,
1097 (load_command
.cmdsize
1099 segcmd
.nsects
, error_callback
,
1100 data
, &dwarf_sections
))
1107 case MACH_O_LC_SEGMENT_64
:
1109 struct macho_segment_64_command segcmd
;
1111 memcpy (&segcmd
, pcmd
, sizeof segcmd
);
1112 if (memcmp (segcmd
.segname
,
1113 "__DWARF\0\0\0\0\0\0\0\0\0",
1114 MACH_O_NAMELEN
) == 0)
1116 if (!macho_add_dwarf_segment (state
, descriptor
, offset
,
1118 pcmd
+ sizeof segcmd
,
1119 (load_command
.cmdsize
1121 segcmd
.nsects
, error_callback
,
1122 data
, &dwarf_sections
))
1129 case MACH_O_LC_SYMTAB
:
1132 struct macho_symtab_command symcmd
;
1134 memcpy (&symcmd
, pcmd
, sizeof symcmd
);
1135 if (!macho_add_symtab (state
, descriptor
, base_address
, is_64
,
1136 offset
+ symcmd
.symoff
, symcmd
.nsyms
,
1137 offset
+ symcmd
.stroff
, symcmd
.strsize
,
1138 error_callback
, data
))
1145 case MACH_O_LC_UUID
:
1147 struct macho_uuid_command uuidcmd
;
1149 memcpy (&uuidcmd
, pcmd
, sizeof uuidcmd
);
1150 memcpy (&uuid
[0], &uuidcmd
.uuid
[0], MACH_O_UUID_LEN
);
1159 cmdoffset
+= load_command
.cmdsize
;
1162 if (!backtrace_close (descriptor
, error_callback
, data
))
1166 backtrace_release_view (state
, &cmds_view
, error_callback
, data
);
1167 cmds_view_valid
= 0;
1169 if (match_uuid
!= NULL
)
1171 /* If we don't have a UUID, or it doesn't match, just ignore
1174 || memcmp (match_uuid
, &uuid
[0], MACH_O_UUID_LEN
) != 0)
1183 #if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)
1184 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
1189 if (!backtrace_dwarf_add (state
, base_address
, &dwarf_sections
,
1190 is_big_endian
, NULL
, error_callback
, data
,
1195 if (!have_dwarf
&& have_uuid
)
1197 if (!macho_add_dsym (state
, filename
, base_address
, &uuid
[0],
1198 error_callback
, data
, fileline_fn
))
1205 if (cmds_view_valid
)
1206 backtrace_release_view (state
, &cmds_view
, error_callback
, data
);
1207 if (descriptor
!= -1)
1208 backtrace_close (descriptor
, error_callback
, data
);
1212 #ifdef HAVE_MACH_O_DYLD_H
1214 /* Initialize the backtrace data we need from a Mach-O executable
1215 using the dyld support functions. This closes descriptor. */
1218 backtrace_initialize (struct backtrace_state
*state
, const char *filename
,
1219 int descriptor
, backtrace_error_callback error_callback
,
1220 void *data
, fileline
*fileline_fn
)
1224 int closed_descriptor
;
1226 fileline macho_fileline_fn
;
1228 closed_descriptor
= 0;
1230 macho_fileline_fn
= macho_nodebug
;
1232 c
= _dyld_image_count ();
1233 for (i
= 0; i
< c
; ++i
)
1235 uintptr_t base_address
;
1241 name
= _dyld_get_image_name (i
);
1245 if (strcmp (name
, filename
) == 0 && !closed_descriptor
)
1248 closed_descriptor
= 1;
1254 d
= backtrace_open (name
, error_callback
, data
, &does_not_exist
);
1259 base_address
= _dyld_get_image_vmaddr_slide (i
);
1261 mff
= macho_nodebug
;
1262 if (!macho_add (state
, name
, d
, 0, NULL
, base_address
, 0,
1263 error_callback
, data
, &mff
, &mfs
))
1266 if (mff
!= macho_nodebug
)
1267 macho_fileline_fn
= mff
;
1272 if (!closed_descriptor
)
1273 backtrace_close (descriptor
, error_callback
, data
);
1275 if (!state
->threaded
)
1278 state
->syminfo_fn
= macho_syminfo
;
1279 else if (state
->syminfo_fn
== NULL
)
1280 state
->syminfo_fn
= macho_nosyms
;
1285 backtrace_atomic_store_pointer (&state
->syminfo_fn
, macho_syminfo
);
1287 (void) __sync_bool_compare_and_swap (&state
->syminfo_fn
, NULL
,
1291 if (!state
->threaded
)
1292 *fileline_fn
= state
->fileline_fn
;
1294 *fileline_fn
= backtrace_atomic_load_pointer (&state
->fileline_fn
);
1296 if (*fileline_fn
== NULL
|| *fileline_fn
== macho_nodebug
)
1297 *fileline_fn
= macho_fileline_fn
;
1302 #else /* !defined (HAVE_MACH_O_DYLD_H) */
1304 /* Initialize the backtrace data we need from a Mach-O executable
1305 without using the dyld support functions. This closes
1309 backtrace_initialize (struct backtrace_state
*state
, const char *filename
,
1310 int descriptor
, backtrace_error_callback error_callback
,
1311 void *data
, fileline
*fileline_fn
)
1313 fileline macho_fileline_fn
;
1316 macho_fileline_fn
= macho_nodebug
;
1317 if (!macho_add (state
, filename
, descriptor
, 0, NULL
, 0, 0,
1318 error_callback
, data
, &macho_fileline_fn
, &found_sym
))
1321 if (!state
->threaded
)
1324 state
->syminfo_fn
= macho_syminfo
;
1325 else if (state
->syminfo_fn
== NULL
)
1326 state
->syminfo_fn
= macho_nosyms
;
1331 backtrace_atomic_store_pointer (&state
->syminfo_fn
, macho_syminfo
);
1333 (void) __sync_bool_compare_and_swap (&state
->syminfo_fn
, NULL
,
1337 if (!state
->threaded
)
1338 *fileline_fn
= state
->fileline_fn
;
1340 *fileline_fn
= backtrace_atomic_load_pointer (&state
->fileline_fn
);
1342 if (*fileline_fn
== NULL
|| *fileline_fn
== macho_nodebug
)
1343 *fileline_fn
= macho_fileline_fn
;
1348 #endif /* !defined (HAVE_MACH_O_DYLD_H) */