Compare commits

...

1 Commits

6 changed files with 472 additions and 24 deletions

View File

@ -0,0 +1,138 @@
#ifndef ELF_DEFS_HPP
#define ELF_DEFS_HPP
#include <cstdint>
namespace cpptrace {
namespace detail {
// https://man7.org/linux/man-pages/man5/elf.5.html
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/elf.h
/* 32-bit ELF base types. */
typedef std::uint32_t Elf32_Addr;
typedef std::uint16_t Elf32_Half;
typedef std::uint32_t Elf32_Off;
typedef std::int32_t Elf32_Sword;
typedef std::uint32_t Elf32_Word;
/* 64-bit ELF base types. */
typedef std::uint64_t Elf64_Addr;
typedef std::uint16_t Elf64_Half;
typedef std::int16_t Elf64_SHalf;
typedef std::uint64_t Elf64_Off;
typedef std::int32_t Elf64_Sword;
typedef std::uint32_t Elf64_Word;
typedef std::uint64_t Elf64_Xword;
typedef std::int64_t Elf64_Sxword;
#define PT_PHDR 6
#define EI_NIDENT 16
#define SHT_SYMTAB 2
#define SHT_STRTAB 3
#define SHT_DYNAMIC 6
typedef struct {
std::uint32_t p_type;
Elf32_Off p_offset;
Elf32_Addr p_vaddr;
Elf32_Addr p_paddr;
std::uint32_t p_filesz;
std::uint32_t p_memsz;
std::uint32_t p_flags;
std::uint32_t p_align;
} Elf32_Phdr;
typedef struct {
std::uint32_t p_type;
std::uint32_t p_flags;
Elf64_Off p_offset;
Elf64_Addr p_vaddr;
Elf64_Addr p_paddr;
std::uint64_t p_filesz;
std::uint64_t p_memsz;
std::uint64_t p_align;
} Elf64_Phdr;
typedef struct elf32_hdr {
unsigned char e_ident[EI_NIDENT];
Elf32_Half e_type;
Elf32_Half e_machine;
Elf32_Word e_version;
Elf32_Addr e_entry; /* Entry point */
Elf32_Off e_phoff;
Elf32_Off e_shoff;
Elf32_Word e_flags;
Elf32_Half e_ehsize;
Elf32_Half e_phentsize;
Elf32_Half e_phnum;
Elf32_Half e_shentsize;
Elf32_Half e_shnum;
Elf32_Half e_shstrndx;
} Elf32_Ehdr;
typedef struct elf64_hdr {
unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */
Elf64_Half e_type;
Elf64_Half e_machine;
Elf64_Word e_version;
Elf64_Addr e_entry; /* Entry point virtual address */
Elf64_Off e_phoff; /* Program header table file offset */
Elf64_Off e_shoff; /* Section header table file offset */
Elf64_Word e_flags;
Elf64_Half e_ehsize;
Elf64_Half e_phentsize;
Elf64_Half e_phnum;
Elf64_Half e_shentsize;
Elf64_Half e_shnum;
Elf64_Half e_shstrndx;
} Elf64_Ehdr;
typedef struct elf32_shdr {
Elf32_Word sh_name;
Elf32_Word sh_type;
Elf32_Word sh_flags;
Elf32_Addr sh_addr;
Elf32_Off sh_offset;
Elf32_Word sh_size;
Elf32_Word sh_link;
Elf32_Word sh_info;
Elf32_Word sh_addralign;
Elf32_Word sh_entsize;
} Elf32_Shdr;
typedef struct elf64_shdr {
Elf64_Word sh_name; /* Section name, index in string tbl */
Elf64_Word sh_type; /* Type of section */
Elf64_Xword sh_flags; /* Miscellaneous section attributes */
Elf64_Addr sh_addr; /* Section virtual addr at execution */
Elf64_Off sh_offset; /* Section file offset */
Elf64_Xword sh_size; /* Size of section in bytes */
Elf64_Word sh_link; /* Index of another section */
Elf64_Word sh_info; /* Additional section information */
Elf64_Xword sh_addralign; /* Section alignment */
Elf64_Xword sh_entsize; /* Entry size if section holds table */
} Elf64_Shdr;
typedef struct elf32_sym {
Elf32_Word st_name;
Elf32_Addr st_value;
Elf32_Word st_size;
unsigned char st_info;
unsigned char st_other;
Elf32_Half st_shndx;
} Elf32_Sym;
typedef struct elf64_sym {
Elf64_Word st_name; /* Symbol name, index in string tbl */
unsigned char st_info; /* Type and binding attributes */
unsigned char st_other; /* No defined meaning, 0 */
Elf64_Half st_shndx; /* Associated section index */
Elf64_Addr st_value; /* Value of the symbol */
Elf64_Xword st_size; /* Associated symbol size */
} Elf64_Sym;
}
}
#endif

View File

@ -0,0 +1,242 @@
#ifndef MACH_O_DEFS_HPP
#define MACH_O_DEFS_HPP
#include <cstdint>
// This file contains definitons from various apple headers licensed under APSL
// https://opensource.apple.com/apsl/
typedef int32_t integer_t; // https://developer.apple.com/documentation/driverkit/integer_t
typedef integer_t cpu_type_t; // https://developer.apple.com/documentation/kernel/cpu_type_t
typedef integer_t cpu_subtype_t; // https://developer.apple.com/documentation/kernel/cpu_subtype_t
// https://github.com/apple-oss-distributions/xnu/blob/8d741a5de7ff4191bf97d57b9f54c2f6d4a15585/osfmk/mach/vm_prot.h#L75
typedef int vm_prot_t; // https://developer.apple.com/documentation/kernel/vm_prot_t
// https://github.com/apple-oss-distributions/xnu/blob/8d741a5de7ff4191bf97d57b9f54c2f6d4a15585/EXTERNAL_HEADERS/mach-o/loader.h#L65
#define MH_MAGIC 0xfeedface /* the mach magic number */
#define MH_CIGAM 0xcefaedfe /* NXSwapInt(MH_MAGIC) */
struct mach_header {
uint32_t magic; /* mach magic number identifier */
cpu_type_t cputype; /* cpu specifier */
cpu_subtype_t cpusubtype; /* machine specifier */
uint32_t filetype; /* type of file */
uint32_t ncmds; /* number of load commands */
uint32_t sizeofcmds; /* the size of all the load commands */
uint32_t flags; /* flags */
};
/* Constant for the magic field of the mach_header_64 (64-bit architectures) */
#define MH_MAGIC_64 0xfeedfacf /* the 64-bit mach magic number */
#define MH_CIGAM_64 0xcffaedfe /* NXSwapInt(MH_MAGIC_64) */
struct mach_header_64 {
uint32_t magic; /* mach magic number identifier */
cpu_type_t cputype; /* cpu specifier */
cpu_subtype_t cpusubtype; /* machine specifier */
uint32_t filetype; /* type of file */
uint32_t ncmds; /* number of load commands */
uint32_t sizeofcmds; /* the size of all the load commands */
uint32_t flags; /* flags */
uint32_t reserved; /* reserved */
};
// https://github.com/apple-oss-distributions/xnu/blob/8d741a5de7ff4191bf97d57b9f54c2f6d4a15585/EXTERNAL_HEADERS/mach-o/loader.h#L247C1-L250C3
struct load_command {
uint32_t cmd; /* type of load command */
uint32_t cmdsize; /* total size of command in bytes */
};
// https://github.com/apple-oss-distributions/xnu/blob/8d741a5de7ff4191bf97d57b9f54c2f6d4a15585/EXTERNAL_HEADERS/mach-o/fat.h#L48
#define FAT_MAGIC 0xcafebabe
#define FAT_CIGAM 0xbebafeca /* NXSwapLong(FAT_MAGIC) */
#define FAT_MAGIC_64 0xcafebabf
#define FAT_CIGAM_64 0xbfbafeca /* NXSwapLong(FAT_MAGIC_64) */
struct fat_header {
uint32_t magic; /* FAT_MAGIC */
uint32_t nfat_arch; /* number of structs that follow */
};
struct fat_arch {
cpu_type_t cputype; /* cpu specifier (int) */
cpu_subtype_t cpusubtype; /* machine specifier (int) */
uint32_t offset; /* file offset to this object file */
uint32_t size; /* size of this object file */
uint32_t align; /* alignment as a power of 2 */
};
struct fat_arch_64 {
cpu_type_t cputype; /* cpu specifier (int) */
cpu_subtype_t cpusubtype; /* machine specifier (int) */
uint64_t offset; /* file offset to this object file */
uint64_t size; /* size of this object file */
uint32_t align; /* alignment as a power of 2 */
uint32_t reserved; /* reserved */
};
// https://github.com/apple-oss-distributions/xnu/blob/8d741a5de7ff4191bf97d57b9f54c2f6d4a15585/EXTERNAL_HEADERS/mach-o/loader.h#L355
struct segment_command { /* for 32-bit architectures */
uint32_t cmd; /* LC_SEGMENT */
uint32_t cmdsize; /* includes sizeof section structs */
char segname[16]; /* segment name */
uint32_t vmaddr; /* memory address of this segment */
uint32_t vmsize; /* memory size of this segment */
uint32_t fileoff; /* file offset of this segment */
uint32_t filesize; /* amount to map from the file */
vm_prot_t maxprot; /* maximum VM protection */
vm_prot_t initprot; /* initial VM protection */
uint32_t nsects; /* number of sections in segment */
uint32_t flags; /* flags */
};
struct segment_command_64 { /* for 64-bit architectures */
uint32_t cmd; /* LC_SEGMENT_64 */
uint32_t cmdsize; /* includes sizeof section_64 structs */
char segname[16]; /* segment name */
uint64_t vmaddr; /* memory address of this segment */
uint64_t vmsize; /* memory size of this segment */
uint64_t fileoff; /* file offset of this segment */
uint64_t filesize; /* amount to map from the file */
vm_prot_t maxprot; /* maximum VM protection */
vm_prot_t initprot; /* initial VM protection */
uint32_t nsects; /* number of sections in segment */
uint32_t flags; /* flags */
};
// https://github.com/apple-oss-distributions/xnu/blob/8d741a5de7ff4191bf97d57b9f54c2f6d4a15585/EXTERNAL_HEADERS/mach-o/loader.h#L868
struct symtab_command {
uint32_t cmd; /* LC_SYMTAB */
uint32_t cmdsize; /* sizeof(struct symtab_command) */
uint32_t symoff; /* symbol table offset */
uint32_t nsyms; /* number of symbol table entries */
uint32_t stroff; /* string table offset */
uint32_t strsize; /* string table size in bytes */
};
// https://github.com/apple-oss-distributions/xnu/blob/8d741a5de7ff4191bf97d57b9f54c2f6d4a15585/EXTERNAL_HEADERS/mach-o/nlist.h#L92
struct nlist {
union {
// #ifndef __LP64__
// char *n_name; /* for use when in-core */
// #endif
uint32_t n_strx; /* index into the string table */
} n_un;
uint8_t n_type; /* type flag, see below */
uint8_t n_sect; /* section number or NO_SECT */
int16_t n_desc; /* see <mach-o/stab.h> */
uint32_t n_value; /* value of this symbol (or stab offset) */
};
struct nlist_64 {
union {
uint32_t n_strx; /* index into the string table */
} n_un;
uint8_t n_type; /* type flag, see below */
uint8_t n_sect; /* section number or NO_SECT */
uint16_t n_desc; /* see <mach-o/stab.h> */
uint64_t n_value; /* value of this symbol (or stab offset) */
};
// https://github.com/apple-oss-distributions/xnu/blob/8d741a5de7ff4191bf97d57b9f54c2f6d4a15585/EXTERNAL_HEADERS/mach-o/loader.h#L263
/* Constants for the cmd field of all load commands, the type */
#define LC_SEGMENT 0x1 /* segment of this file to be mapped */
#define LC_SYMTAB 0x2 /* link-edit stab symbol table info */
#define LC_SYMSEG 0x3 /* link-edit gdb symbol table info (obsolete) */
#define LC_THREAD 0x4 /* thread */
#define LC_UNIXTHREAD 0x5 /* unix thread (includes a stack) */
#define LC_LOADFVMLIB 0x6 /* load a specified fixed VM shared library */
#define LC_IDFVMLIB 0x7 /* fixed VM shared library identification */
#define LC_IDENT 0x8 /* object identification info (obsolete) */
#define LC_FVMFILE 0x9 /* fixed VM file inclusion (internal use) */
#define LC_PREPAGE 0xa /* prepage command (internal use) */
#define LC_DYSYMTAB 0xb /* dynamic link-edit symbol table info */
#define LC_LOAD_DYLIB 0xc /* load a dynamically linked shared library */
#define LC_ID_DYLIB 0xd /* dynamically linked shared lib ident */
#define LC_LOAD_DYLINKER 0xe /* load a dynamic linker */
#define LC_ID_DYLINKER 0xf /* dynamic linker identification */
#define LC_PREBOUND_DYLIB 0x10 /* modules prebound for a dynamically */
/* linked shared library */
#define LC_ROUTINES 0x11 /* image routines */
#define LC_SUB_FRAMEWORK 0x12 /* sub framework */
#define LC_SUB_UMBRELLA 0x13 /* sub umbrella */
#define LC_SUB_CLIENT 0x14 /* sub client */
#define LC_SUB_LIBRARY 0x15 /* sub library */
#define LC_TWOLEVEL_HINTS 0x16 /* two-level namespace lookup hints */
#define LC_PREBIND_CKSUM 0x17 /* prebind checksum */
#define LC_SEGMENT_64 0x19 /* 64-bit segment of this file to be */
#define LC_ROUTINES_64 0x1a /* 64-bit image routines */
#define LC_UUID 0x1b /* the uuid */
// https://github.com/apple-oss-distributions/xnu/blob/8d741a5de7ff4191bf97d57b9f54c2f6d4a15585/EXTERNAL_HEADERS/mach-o/nlist.h#L117
#define N_STAB 0xe0 /* if any of these bits set, a symbolic debugging entry */
#define N_PEXT 0x10 /* private external symbol bit */
#define N_TYPE 0x0e /* mask for the type bits */
#define N_EXT 0x01 /* external symbol bit, set for external symbols */
#define N_UNDF 0x0 /* undefined, n_sect == NO_SECT */
#define N_ABS 0x2 /* absolute, n_sect == NO_SECT */
#define N_SECT 0xe /* defined in section number n_sect */
#define N_PBUD 0xc /* prebound undefined (defined in a dylib) */
#define N_INDR 0xa /* indirect */
// https://github.com/apple-oss-distributions/xnu/blob/8d741a5de7ff4191bf97d57b9f54c2f6d4a15585/EXTERNAL_HEADERS/mach-o/stab.h#L87C1-L116C68
#define N_GSYM 0x20 /* global symbol: name,,NO_SECT,type,0 */
#define N_FNAME 0x22 /* procedure name (f77 kludge): name,,NO_SECT,0,0 */
#define N_FUN 0x24 /* procedure: name,,n_sect,linenumber,address */
#define N_STSYM 0x26 /* static symbol: name,,n_sect,type,address */
#define N_LCSYM 0x28 /* .lcomm symbol: name,,n_sect,type,address */
#define N_BNSYM 0x2e /* begin nsect sym: 0,,n_sect,0,address */
#define N_AST 0x32 /* AST file path: name,,NO_SECT,0,0 */
#define N_OPT 0x3c /* emitted with gcc2_compiled and in gcc source */
#define N_RSYM 0x40 /* register sym: name,,NO_SECT,type,register */
#define N_SLINE 0x44 /* src line: 0,,n_sect,linenumber,address */
#define N_ENSYM 0x4e /* end nsect sym: 0,,n_sect,0,address */
#define N_SSYM 0x60 /* structure elt: name,,NO_SECT,type,struct_offset */
#define N_SO 0x64 /* source file name: name,,n_sect,0,address */
#define N_OSO 0x66 /* object file name: name,,0,0,st_mtime */
#define N_LSYM 0x80 /* local sym: name,,NO_SECT,type,offset */
#define N_BINCL 0x82 /* include file beginning: name,,NO_SECT,0,sum */
#define N_SOL 0x84 /* #included file name: name,,n_sect,0,address */
#define N_PARAMS 0x86 /* compiler parameters: name,,NO_SECT,0,0 */
#define N_VERSION 0x88 /* compiler version: name,,NO_SECT,0,0 */
#define N_OLEVEL 0x8A /* compiler -O level: name,,NO_SECT,0,0 */
#define N_PSYM 0xa0 /* parameter: name,,NO_SECT,type,offset */
#define N_EINCL 0xa2 /* include file end: name,,NO_SECT,0,0 */
#define N_ENTRY 0xa4 /* alternate entry: name,,n_sect,linenumber,address */
#define N_LBRAC 0xc0 /* left bracket: 0,,NO_SECT,nesting level,address */
#define N_EXCL 0xc2 /* deleted include file: name,,NO_SECT,0,sum */
#define N_RBRAC 0xe0 /* right bracket: 0,,NO_SECT,nesting level,address */
#define N_BCOMM 0xe2 /* begin common: name,,NO_SECT,0,0 */
#define N_ECOMM 0xe4 /* end common: name,,n_sect,0,0 */
#define N_ECOML 0xe8 /* end common (local name): 0,,n_sect,0,address */
#define N_LENG 0xfe /* second stab entry with length information */
extern "C" {
// There is exceedingly little evidence that this function actually exists. I think I discovered it through
// https://github.com/ruby/ruby/blob/ff64806ae51c2813f0c6334c0c52082b027c255c/addr2line.c#L2359.
// from MacOSX13.1.sdk/usr/include/crt_externs.h
#ifdef __LP64__
extern struct mach_header_64* _NSGetMachExecuteHeader(void);
#else /* !__LP64__ */
extern struct mach_header* _NSGetMachExecuteHeader(void);
#endif /* __LP64__ */
// MacOSX13.1.sdk/usr/include/mach-o/arch.h
extern struct fat_arch* NXFindBestFatArch(
cpu_type_t cputype,
cpu_subtype_t cpusubtype,
struct fat_arch* fat_archs,
uint32_t nfat_archs
);
extern struct fat_arch_64* NXFindBestFatArch_64(
cpu_type_t cputype,
cpu_subtype_t cpusubtype,
struct fat_arch_64* fat_archs64,
uint32_t nfat_archs
); // __CCTOOLS_DEPRECATED_MSG("use macho_best_slice()")
}
#endif

View File

@ -8,7 +8,7 @@
#include <cstring>
#include <type_traits>
#include <elf.h>
#include "binary/defs/elf_defs.hpp"
namespace cpptrace {
namespace detail {

View File

@ -19,16 +19,20 @@
#include <iostream>
#include <iomanip>
#include <mach-o/loader.h>
#include <mach-o/swap.h>
#include <mach-o/fat.h>
#include <crt_externs.h>
#include <mach-o/nlist.h>
#include <mach-o/stab.h>
#include <mach-o/arch.h>
#include "binary/defs/mach-o-defs.hpp"
// #include <mach-o/loader.h>
// #include <mach-o/swap.h>
// #include <mach-o/fat.h>
// #include <crt_externs.h>
// #include <mach-o/nlist.h>
// #include <mach-o/stab.h>
// #include <mach-o/arch.h>
namespace cpptrace {
namespace detail {
// TODO: 64-bit fat??
bool is_mach_o(std::uint32_t magic) {
switch(magic) {
case FAT_MAGIC:
@ -71,27 +75,89 @@ namespace detail {
}
void swap_mach_header(mach_header_64& header) {
swap_mach_header_64(&header, NX_UnknownByteOrder);
header.magic = byteswap(header.magic);
header.cputype = byteswap(header.cputype);
header.cpusubtype = byteswap(header.cpusubtype);
header.filetype = byteswap(header.filetype);
header.ncmds = byteswap(header.ncmds);
header.sizeofcmds = byteswap(header.sizeofcmds);
header.flags = byteswap(header.flags);
header.reserved = byteswap(header.reserved);
}
void swap_mach_header(mach_header& header) {
swap_mach_header(&header, NX_UnknownByteOrder);
header.magic = byteswap(header.magic);
header.cputype = byteswap(header.cputype);
header.cpusubtype = byteswap(header.cpusubtype);
header.filetype = byteswap(header.filetype);
header.ncmds = byteswap(header.ncmds);
header.sizeofcmds = byteswap(header.sizeofcmds);
header.flags = byteswap(header.flags);
}
void swap_segment_command(segment_command_64& segment) {
swap_segment_command_64(&segment, NX_UnknownByteOrder);
segment.cmd = byteswap(segment.cmd);
segment.cmdsize = byteswap(segment.cmdsize);
segment.vmaddr = byteswap(segment.vmaddr);
segment.vmsize = byteswap(segment.vmsize);
segment.fileoff = byteswap(segment.fileoff);
segment.filesize = byteswap(segment.filesize);
segment.maxprot = byteswap(segment.maxprot);
segment.initprot = byteswap(segment.initprot);
segment.nsects = byteswap(segment.nsects);
segment.flags = byteswap(segment.flags);
}
void swap_segment_command(segment_command& segment) {
swap_segment_command(&segment, NX_UnknownByteOrder);
segment.cmd = byteswap(segment.cmd);
segment.cmdsize = byteswap(segment.cmdsize);
segment.vmaddr = byteswap(segment.vmaddr);
segment.vmsize = byteswap(segment.vmsize);
segment.fileoff = byteswap(segment.fileoff);
segment.filesize = byteswap(segment.filesize);
segment.maxprot = byteswap(segment.maxprot);
segment.initprot = byteswap(segment.initprot);
segment.nsects = byteswap(segment.nsects);
segment.flags = byteswap(segment.flags);
}
void swap_nlist(struct nlist& entry) {
swap_nlist(&entry, 1, NX_UnknownByteOrder);
void swap_symtab_command(symtab_command& symtab) {
symtab.cmd = byteswap(symtab.cmd);
symtab.cmdsize = byteswap(symtab.cmdsize);
symtab.symoff = byteswap(symtab.symoff);
symtab.nsyms = byteswap(symtab.nsyms);
symtab.stroff = byteswap(symtab.stroff);
symtab.strsize = byteswap(symtab.strsize);
}
void swap_nlist(struct nlist_64& entry) {
swap_nlist_64(&entry, 1, NX_UnknownByteOrder);
void swap_nlist(nlist& entry) {
entry.n_un.n_strx = byteswap(entry.n_un.n_strx);
entry.n_desc = byteswap(entry.n_desc);
entry.n_value = byteswap(entry.n_value);
}
void swap_nlist(nlist_64& entry) {
entry.n_un.n_strx = byteswap(entry.n_un.n_strx);
entry.n_desc = byteswap(entry.n_desc);
entry.n_value = byteswap(entry.n_value);
}
void swap_load_command(load_command& command) {
command.cmd = byteswap(command.cmd);
command.cmdsize = byteswap(command.cmdsize);
}
void swap_fat_header(fat_header& header) {
header.magic = byteswap(header.magic);
header.nfat_arch = byteswap(header.nfat_arch);
}
void swap_fat_arch(fat_arch& arch) {
arch.cputype = byteswap(arch.cputype);
arch.cpusubtype = byteswap(arch.cpusubtype);
arch.offset = byteswap(arch.offset);
arch.size = byteswap(arch.size);
arch.align = byteswap(arch.align);
}
#ifdef __LP64__
@ -491,7 +557,7 @@ namespace detail {
}
load_command& cmd = load_cmd.unwrap_value();
if(should_swap()) {
swap_load_command(&cmd, NX_UnknownByteOrder);
swap_load_command(cmd);
}
load_commands.push_back({ actual_offset, cmd.cmd, cmd.cmdsize });
actual_offset += cmd.cmdsize;
@ -508,7 +574,7 @@ namespace detail {
}
fat_header& header = load_header.unwrap_value();
if(should_swap()) {
swap_fat_header(&header, NX_UnknownByteOrder);
swap_fat_header(header);
}
// thread_local static struct LP(mach_header)* mhp = _NSGetMachExecuteHeader();
// off_t arch_offset = (off_t)header_size;
@ -546,7 +612,7 @@ namespace detail {
}
fat_arch& arch = load_arch.unwrap_value();
if(should_swap()) {
swap_fat_arch(&arch, 1, NX_UnknownByteOrder);
swap_fat_arch(arch);
}
fat_arches.push_back(arch);
arch_offset += arch_size;
@ -614,7 +680,7 @@ namespace detail {
symtab_command& symtab = load_symtab.unwrap_value();
ASSERT(symtab.cmd == LC_SYMTAB);
if(should_swap()) {
swap_symtab_command(&symtab, NX_UnknownByteOrder);
swap_symtab_command(symtab);
}
return symtab;
}

View File

@ -13,9 +13,7 @@
#include <unordered_map>
#include <vector>
#include <mach-o/arch.h>
#include <mach-o/loader.h>
#include <mach-o/nlist.h>
#include "binary/defs/mach-o-defs.hpp"
namespace cpptrace {
namespace detail {

View File

@ -39,9 +39,13 @@ namespace detail {
#elif IS_APPLE
#include <cstdint>
#include <mach-o/dyld.h>
// #include <mach-o/dyld.h>
#include <sys/syslimits.h>
// https://github.com/opensource-apple/dyld/blob/3f928f32597888c5eac6003b9199d972d49857b5/include/mach-o/dyld.h#L92C1-L92C62
// https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dyld.3.html
extern int _NSGetExecutablePath(char* buf, uint32_t* bufsize);
#define CPPTRACE_MAX_PATH CPPTRACE_PATH_MAX
namespace cpptrace {