#include <stdlib.h>
#include <string.h>
#include <mach-o/loader.h>
#include <unistd.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdarg.h>
#include <pthread.h>
#include <Availability.h>
#include "mach-o/dyld_priv.h"
#include "dyldLibSystemInterface.h"
extern void _ZN4dyld3logEPKcz(const char*, ...);
extern struct LibSystemHelpers* _ZN4dyld17gLibSystemHelpersE;
#if __LP64__
#define LC_SEGMENT_COMMAND LC_SEGMENT_64
#define macho_header mach_header_64
#define macho_segment_command segment_command_64
#define macho_section section_64
#define getsectdatafromheader getsectdatafromheader_64
#else
#define LC_SEGMENT_COMMAND LC_SEGMENT
#define macho_header mach_header
#define macho_segment_command segment_command
#define macho_section section
#endif
static pthread_key_t sCxaKey = 0;
static char sPreMainCxaGlobals[2*sizeof(long)];
char* __cxa_get_globals()
{
if ( (_ZN4dyld17gLibSystemHelpersE == NULL) || (_ZN4dyld17gLibSystemHelpersE->version < 5) )
return sPreMainCxaGlobals;
if ( sCxaKey == 0 ) {
_ZN4dyld17gLibSystemHelpersE->pthread_key_create(&sCxaKey, &free);
}
char* data = (char*)pthread_getspecific(sCxaKey);
if ( data == NULL ) {
data = calloc(2,sizeof(void*));
_ZN4dyld17gLibSystemHelpersE->pthread_setspecific(sCxaKey, data);
}
return data;
}
char* __cxa_get_globals_fast()
{
if ( (_ZN4dyld17gLibSystemHelpersE == NULL) || (_ZN4dyld17gLibSystemHelpersE->version < 5) )
return sPreMainCxaGlobals;
return pthread_getspecific(sCxaKey);
}
#if __x86_64__ || __i386__ || __ppc__
static struct dyld_unwind_sections sDyldInfo;
static void* sDyldTextEnd;
void dyld_exceptions_init(struct mach_header* mh, intptr_t slide)
{
sDyldInfo.mh = mh;
const struct load_command* cmd;
unsigned long i;
cmd = (struct load_command*) ((char *)mh + sizeof(struct macho_header));
for(i = 0; i < mh->ncmds; i++) {
if ( cmd->cmd == LC_SEGMENT_COMMAND ) {
const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
if ( strcmp(seg->segname, "__TEXT") == 0 ) {
const struct macho_section* sect = (struct macho_section*)( (char*)seg + sizeof(struct macho_segment_command) );
unsigned long j;
for (j = 0; j < seg->nsects; j++) {
if ( strcmp(sect[j].sectname, "__eh_frame") == 0 ) {
sDyldInfo.dwarf_section = (void*)(sect[j].addr + slide);
sDyldInfo.dwarf_section_length = sect[j].size;
}
else if ( strcmp(sect[j].sectname, "__unwind_info") == 0 ) {
sDyldInfo.compact_unwind_section = (void*)(sect[j].addr + slide);
sDyldInfo.compact_unwind_section_length = sect[j].size;
}
}
sDyldTextEnd = (void*)(seg->vmaddr + seg->vmsize + slide);
}
}
cmd = (struct load_command*)( (char*)cmd + cmd->cmdsize );
}
}
bool _dyld_find_unwind_sections(void* addr, struct dyld_unwind_sections* info)
{
if ( ((void*)sDyldInfo.mh < addr) && (addr < sDyldTextEnd) ) {
*info = sDyldInfo;
return true;
}
else {
return false;
}
}
#if __ppc__
void* _Znwm(size_t size) { return malloc(size); }
#endif
#endif // __MAC_OS_X_VERSION_MIN_REQUIRED
#if __arm__
struct _Unwind_FunctionContext
{
struct _Unwind_FunctionContext* prev;
};
void dyld_exceptions_init(struct mach_header *mh, uintptr_t slide)
{
}
static pthread_key_t sThreadChainKey = 0;
static struct _Unwind_FunctionContext* sStaticThreadChain = NULL;
void __Unwind_SjLj_SetThreadKey(pthread_key_t key)
{
sThreadChainKey = key;
_ZN4dyld17gLibSystemHelpersE->pthread_setspecific(sThreadChainKey, sStaticThreadChain);
sStaticThreadChain = NULL;
}
struct _Unwind_FunctionContext* __Unwind_SjLj_GetTopOfFunctionStack()
{
if ( sThreadChainKey != 0 ) {
return (struct _Unwind_FunctionContext*)pthread_getspecific(sThreadChainKey);
}
else {
return sStaticThreadChain;
}
}
void __Unwind_SjLj_SetTopOfFunctionStack(struct _Unwind_FunctionContext* fc)
{
if ( sThreadChainKey != 0 )
_ZN4dyld17gLibSystemHelpersE->pthread_setspecific(sThreadChainKey, fc);
else
sStaticThreadChain = fc;
}
#endif