40#ifdef HAVE_MACH_O_DYLD_H
41#include <mach-o/dyld.h>
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
93#define MACH_O_MH_EXECUTE 0x02
94#define MACH_O_MH_DYLIB 0x06
95#define MACH_O_MH_DSYM 0x0a
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)
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
154#define MACH_O_NAMELEN (16)
204#define MACH_O_UUID_LEN (16)
274#define MACH_O_N_STAB 0xe0
275#define MACH_O_N_TYPE 0x0e
278#define MACH_O_N_UNDF 0x00
279#define MACH_O_N_ABS 0x02
280#define MACH_O_N_SECT 0x0e
330 error_callback (
data,
"no debug info in Mach-O executable (make sure to compile with -g; may need to run dsymutil)", -1);
351 const char *sectname,
uint32_t offset, uint64_t size,
384 off_t offset,
unsigned int cmd,
const char *psecs,
385 size_t sizesecs,
unsigned int nsects,
389 size_t sec_header_size;
406 for (i = 0; i < nsects; ++i)
408 if (secoffset + sec_header_size > sizesecs)
420 memcpy (§ion, psecs + secoffset,
sizeof section);
431 memcpy (§ion, psecs + secoffset,
sizeof section);
442 secoffset += sec_header_size;
471 const uintptr_t *key = (
const uintptr_t *) vkey;
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)
516 off_t symoff,
unsigned int nsyms,
off_t stroff,
517 unsigned int strsize,
528 size_t macho_symbol_size;
535 macho_symbol_size = 0;
536 macho_symbols = NULL;
555 for (i = 0; i < nsyms; ++i, symtaboff += symsize)
561 memcpy (&nlist, (
const char *) sym_view.
data + symtaboff,
570 memcpy (&nlist, (
const char *) sym_view.
data + symtaboff,
578 macho_symbol_size = (ndefs + 1) *
sizeof (
struct macho_symbol);
582 if (macho_symbols == NULL)
587 for (i = 0; i < nsyms; ++i, symtaboff += symsize)
599 memcpy (&nlist, (
const char *) sym_view.
data + symtaboff,
611 memcpy (&nlist, (
const char *) sym_view.
data + symtaboff,
626 name = (
const char *) str_view.
data + strx;
647 macho_symbols[j].
name =
"";
648 macho_symbols[j].
address = ~(uintptr_t) 0;
654 sdata->symbols = macho_symbols;
655 sdata->count = ndefs;
657 if (!
state->threaded)
694 if (macho_symbols != NULL)
716 if (!
state->threaded)
751 callback (
data, addr, NULL, 0, 0);
761 int descriptor,
int swapped,
off_t offset,
762 const unsigned char *match_uuid,
764 int skip_symtab,
uint32_t nfat_arch,
int is_64,
766 fileline *fileline_fn,
int *found_sym)
769 unsigned int cputype;
776#if defined (__x86_64__)
778#elif defined (__i386__)
780#elif defined (__aarch64__)
782#elif defined (__arm__)
784#elif defined (__ppc__)
786#elif defined (__ppc64__)
799 nfat_arch * arch_size,
803 for (i = 0; i < nfat_arch; ++i)
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);
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);
843 return macho_add (
state, filename, descriptor, foffset, match_uuid,
845 fileline_fn, found_sym);
854 if (descriptor != -1)
866 const unsigned char *uuid,
874 const char *basename;
876 const char *dsymsuffixdir;
877 size_t dsymsuffixdirlen;
890 p = strrchr (filename,
'/');
896 basenamelen = strlen (basename);
901 dirnamelen = p - filename;
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
926 memcpy (ps, dirname, dirnamelen);
929 memcpy (ps, basename, basenamelen);
931 memcpy (ps, dsymsuffixdir, dsymsuffixdirlen);
932 ps += dsymsuffixdirlen;
933 memcpy (ps, basename, basenamelen);
986 fileline *fileline_fn,
int *found_sym)
1003 cmds_view_valid = 0;
1014 memcpy (&header, header_view.
data,
sizeof header);
1018 switch (header.
magic)
1034 memcpy (&fat_header, &header,
sizeof fat_header);
1036 match_uuid, base_address, skip_symtab,
1048 memcpy (&fat_header, &header,
sizeof fat_header);
1051 match_uuid, base_address, skip_symtab,
1075 cmds_view_valid = 1;
1079 memset (&uuid, 0,
sizeof uuid);
1083 for (i = 0; i < header.
ncmds; ++i)
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)
1100 memcpy (&segcmd, pcmd,
sizeof segcmd);
1102 "__DWARF\0\0\0\0\0\0\0\0\0",
1107 pcmd +
sizeof segcmd,
1122 memcpy (&segcmd, pcmd,
sizeof segcmd);
1124 "__DWARF\0\0\0\0\0\0\0\0\0",
1129 pcmd +
sizeof segcmd,
1145 memcpy (&symcmd, pcmd,
sizeof symcmd);
1160 memcpy (&uuidcmd, pcmd,
sizeof uuidcmd);
1170 cmdoffset += load_command.
cmdsize;
1178 cmds_view_valid = 0;
1180 if (match_uuid != NULL)
1194#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)
1195#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
1206 if (!have_dwarf && have_uuid)
1216 if (cmds_view_valid)
1218 if (descriptor != -1)
1223#ifdef HAVE_MACH_O_DYLD_H
1235 int closed_descriptor;
1239 closed_descriptor = 0;
1243 c = _dyld_image_count ();
1244 for (i = 0; i < c; ++i)
1252 name = _dyld_get_image_name (i);
1256 if (strcmp (
name, filename) == 0 && !closed_descriptor)
1259 closed_descriptor = 1;
1270 base_address.m = _dyld_get_image_vmaddr_slide (i);
1278 macho_fileline_fn = mff;
1283 if (!closed_descriptor)
1286 if (!
state->threaded)
1290 else if (
state->syminfo_fn == NULL)
1302 if (!
state->threaded)
1303 *fileline_fn =
state->fileline_fn;
1308 *fileline_fn = macho_fileline_fn;
1329 memset (&zero_base_address, 0,
sizeof zero_base_address);
1330 if (!
macho_add (
state, filename, descriptor, 0, NULL, zero_base_address, 0,
1334 if (!
state->threaded)
1338 else if (
state->syminfo_fn == NULL)
1350 if (!
state->threaded)
1351 *fileline_fn =
state->fileline_fn;
1356 *fileline_fn = macho_fileline_fn;
void * backtrace_alloc(struct backtrace_state *state ATTRIBUTE_UNUSED, size_t size, backtrace_error_callback error_callback, void *data)
void backtrace_free(struct backtrace_state *state ATTRIBUTE_UNUSED, void *p, size_t size ATTRIBUTE_UNUSED, backtrace_error_callback error_callback ATTRIBUTE_UNUSED, void *data ATTRIBUTE_UNUSED)
void(* backtrace_syminfo_callback)(void *data, uintptr_t pc, const char *symname, uintptr_t symval, uintptr_t symsize)
void(* backtrace_error_callback)(void *data, const char *msg, int errnum)
int(* backtrace_full_callback)(void *data, uintptr_t pc, const char *filename, int lineno, const char *function)
static void error_callback(void *data, const char *msg, int errnum)
int backtrace_dwarf_add(struct backtrace_state *state, struct libbacktrace_base_address base_address, const struct dwarf_sections *dwarf_sections, int is_bigendian, struct dwarf_data *fileline_altlink, backtrace_error_callback error_callback, void *data, fileline *fileline_fn, struct dwarf_data **fileline_entry)
void backtrace_qsort(void *base, size_t count, size_t size, int(*compar)(const void *, const void *))
void backtrace_release_view(struct backtrace_state *state, struct backtrace_view *view, backtrace_error_callback error_callback, void *data)
#define backtrace_atomic_load_pointer(p)
int(* fileline)(struct backtrace_state *state, uintptr_t pc, backtrace_full_callback callback, backtrace_error_callback error_callback, void *data)
#define libbacktrace_add_base(pc, base)
const unsigned char * data[DEBUG_MAX]
int backtrace_close(int descriptor, backtrace_error_callback error_callback, void *data)
#define backtrace_atomic_store_pointer(p, v)
int backtrace_get_view(struct backtrace_state *state, int descriptor, off_t offset, uint64_t size, backtrace_error_callback error_callback, void *data, struct backtrace_view *view)
int backtrace_open(const char *filename, backtrace_error_callback error_callback, void *data, int *does_not_exist)
#define __sync_bool_compare_and_swap(A, B, C)
static int macho_add_dwarf_segment(struct backtrace_state *state, int descriptor, off_t offset, unsigned int cmd, const char *psecs, size_t sizesecs, unsigned int nsects, backtrace_error_callback error_callback, void *data, struct dwarf_sections *dwarf_sections)
#define MACH_O_CPU_TYPE_ARM64
char sectname[MACH_O_NAMELEN]
static int macho_symbol_compare(const void *v1, const void *v2)
#define MACH_O_CPU_TYPE_PPC
unsigned char uuid[MACH_O_UUID_LEN]
#define MACH_O_MH_MAGIC_FAT_64
static void macho_nosyms(struct backtrace_state *state ATTRIBUTE_UNUSED, uintptr_t addr ATTRIBUTE_UNUSED, backtrace_syminfo_callback callback ATTRIBUTE_UNUSED, backtrace_error_callback error_callback, void *data)
static void macho_syminfo(struct backtrace_state *state, uintptr_t addr, backtrace_syminfo_callback callback, backtrace_error_callback error_callback ATTRIBUTE_UNUSED, void *data)
#define MACH_O_CPU_TYPE_PPC64
static int macho_add_symtab(struct backtrace_state *state, int descriptor, struct libbacktrace_base_address base_address, int is_64, off_t symoff, unsigned int nsyms, off_t stroff, unsigned int strsize, backtrace_error_callback error_callback, void *data)
#define MACH_O_CPU_TYPE_ARM
#define MACH_O_LC_SEGMENT
#define MACH_O_MH_CIGAM_FAT
#define MACH_O_CPU_TYPE_X86
char sectname[MACH_O_NAMELEN]
#define MACH_O_LC_SEGMENT_64
char segname[MACH_O_NAMELEN]
char segment[MACH_O_NAMELEN]
static const char *const dwarf_section_names[DEBUG_MAX]
struct macho_syminfo_data * next
struct macho_symbol * symbols
static int macho_add_dsym(struct backtrace_state *state, const char *filename, struct libbacktrace_base_address base_address, const unsigned char *uuid, backtrace_error_callback error_callback, void *data, fileline *fileline_fn)
char segment[MACH_O_NAMELEN]
static int macho_add_fat(struct backtrace_state *state, const char *filename, int descriptor, int swapped, off_t offset, const unsigned char *match_uuid, struct libbacktrace_base_address base_address, int skip_symtab, uint32_t nfat_arch, int is_64, backtrace_error_callback error_callback, void *data, fileline *fileline_fn, int *found_sym)
char segname[MACH_O_NAMELEN]
static int macho_add_dwarf_section(struct backtrace_state *state, int descriptor, const char *sectname, uint32_t offset, uint64_t size, backtrace_error_callback error_callback, void *data, struct dwarf_sections *dwarf_sections)
#define MACH_O_MH_EXECUTE
#define MACH_O_MH_MAGIC_64
#define MACH_O_CPU_TYPE_X86_64
static int macho_nodebug(struct backtrace_state *state ATTRIBUTE_UNUSED, uintptr_t pc ATTRIBUTE_UNUSED, backtrace_full_callback callback ATTRIBUTE_UNUSED, backtrace_error_callback error_callback, void *data)
static int macho_add(struct backtrace_state *, const char *, int, off_t, const unsigned char *, struct libbacktrace_base_address, int, backtrace_error_callback, void *, fileline *, int *)
static int macho_symbol_search(const void *vkey, const void *ventry)
int backtrace_initialize(struct backtrace_state *state, const char *filename, int descriptor, backtrace_error_callback error_callback, void *data, fileline *fileline_fn)
#define MACH_O_MH_MAGIC_32
static int macho_defined_symbol(uint8_t type)
#define MACH_O_MH_MAGIC_FAT
#define MACH_O_MH_CIGAM_FAT_64
fr_aka_sim_id_type_t type
Functions to help with cleanup.