#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <mach-o/loader.h>
#define KEYMGR_API_MAJOR_GCC3 3
#define KEYMGR_GCC3_LIVE_IMAGE_LIST 301
#define KEYMGR_GCC3_DW2_OBJ_LIST 302
#define KEYMGR_EH_GLOBALS_KEY 13
struct live_images {
unsigned long this_size;
struct mach_header *mh;
unsigned long vm_slide;
void (*destructor)(struct live_images *);
struct live_images *next;
unsigned int examined_p;
void *fde;
void *object_info;
unsigned long info[2];
};
static struct live_images sDyldImage; static void* sObjectList = NULL;
#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ >= 4))
static void* sEHGlobals = NULL;
#endif
void dyld_exceptions_init(struct mach_header *mh, uintptr_t slide)
{
sDyldImage.this_size = sizeof(struct live_images);
sDyldImage.mh = mh;
sDyldImage.vm_slide = slide;
}
#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ >= 4))
typedef struct Sinfo_Node {
uint32_t size;
uint16_t major_version;
uint16_t minor_version;
} Tinfo_Node;
static const Tinfo_Node keymgr_info = { sizeof (Tinfo_Node), KEYMGR_API_MAJOR_GCC3, 0 };
const Tinfo_Node* __keymgr_global[3] = { NULL, NULL, &keymgr_info };
#endif
static __attribute__((noreturn))
void dyld_abort()
{
fprintf(stderr, "internal dyld error\n");
abort();
}
void* _keymgr_get_and_lock_processwide_ptr(unsigned int key)
{
if ( key == KEYMGR_GCC3_LIVE_IMAGE_LIST ) {
return &sDyldImage;
}
else if ( key == KEYMGR_GCC3_DW2_OBJ_LIST ) {
return sObjectList;
}
dyld_abort();
}
void _keymgr_set_and_unlock_processwide_ptr(unsigned int key, void* value)
{
if ( key == KEYMGR_GCC3_DW2_OBJ_LIST ) {
sObjectList = value;
return;
}
dyld_abort();
}
void _keymgr_unlock_processwide_ptr(unsigned int key)
{
if ( key == KEYMGR_GCC3_LIVE_IMAGE_LIST ) {
return;
}
dyld_abort();
}
void* _keymgr_get_per_thread_data(unsigned int key)
{
#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ >= 4))
if ( key == KEYMGR_EH_GLOBALS_KEY )
return sEHGlobals;
#endif
dyld_abort();
}
void _keymgr_set_per_thread_data(unsigned int key, void *keydata)
{
#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ >= 4))
if ( key == KEYMGR_EH_GLOBALS_KEY ) {
sEHGlobals = keydata;
return;
}
#endif
dyld_abort();
}
#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
const void* getsectdatafromheader(struct mach_header* mh, const char* segname, const char* sectname, unsigned long* size)
{
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, segname) == 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, sectname) == 0 ) {
*size = sect[j].size;
return (void*)(sect[j].addr);
}
}
}
}
cmd = (struct load_command*)( (char*)cmd + cmd->cmdsize );
}
return NULL;
}
#if __ppc64__
#undef getsectdatafromheader
const void* getsectdatafromheader(struct mach_header* mh, const char* segname, const char* sectname, unsigned long* size)
{
return getsectdatafromheader_64(mh, segname, sectname, size);
}
#endif