184 lines
5.3 KiB
C++
184 lines
5.3 KiB
C++
#include "il2cpp-config.h"
|
|||
|
|
#include "utils/Memory.h"
|
||
|
|
|
||
|
|
#if IL2CPP_TARGET_DARWIN
|
||
|
|
|
||
|
|
#include "os/Image.h"
|
||
|
|
|
||
|
|
#include <mach-o/dyld.h>
|
||
|
|
#include <mach-o/getsect.h>
|
||
|
|
#include <mach-o/ldsyms.h>
|
||
|
|
#include <dlfcn.h>
|
||
|
|
#include <vector>
|
||
|
|
|
||
|
|
namespace il2cpp
|
||
|
|
{
|
||
|
|
namespace os
|
||
|
|
{
|
||
|
|
namespace Image
|
||
|
|
{
|
||
|
|
static void* s_ImageBase = NULL;
|
||
|
|
|
||
|
|
static int GetImageIndex()
|
||
|
|
{
|
||
|
|
// OSX/iOS uses ASLR (address space layout randomization), so
|
||
|
|
// find where the image is loaded. This is usually zero in the
|
||
|
|
// debugger for an executable, but non-zero when a debugger is not
|
||
|
|
// present.
|
||
|
|
std::vector<char> path;
|
||
|
|
uint32_t size = 0;
|
||
|
|
int error = _NSGetExecutablePath(NULL, &size);
|
||
|
|
IL2CPP_ASSERT(error == -1);
|
||
|
|
if (error != -1)
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
path.resize(size);
|
||
|
|
error = _NSGetExecutablePath(&path[0], &size);
|
||
|
|
IL2CPP_ASSERT(error == 0);
|
||
|
|
if (error != 0)
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
int gameAssemblyImageIndex = -1;
|
||
|
|
int executableImageIndex = -1;
|
||
|
|
int numberOfImages = _dyld_image_count();
|
||
|
|
for (uint32_t i = 0; i < numberOfImages; i++)
|
||
|
|
{
|
||
|
|
const char* imageName = _dyld_get_image_name(i);
|
||
|
|
if (strstr(imageName, "GameAssembly.dylib") != NULL || strstr(imageName, "UnityFramework.framework/UnityFramework") != NULL)
|
||
|
|
{
|
||
|
|
gameAssemblyImageIndex = i;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
else if (strstr(imageName, &path[0]) != NULL)
|
||
|
|
{
|
||
|
|
executableImageIndex = i;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (gameAssemblyImageIndex != -1)
|
||
|
|
return gameAssemblyImageIndex;
|
||
|
|
else if (executableImageIndex != -1)
|
||
|
|
return executableImageIndex;
|
||
|
|
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void InitializeImageBase()
|
||
|
|
{
|
||
|
|
// Gets info about the image containing InitializeImageBase
|
||
|
|
Dl_info info;
|
||
|
|
memset(&info, 0, sizeof(info));
|
||
|
|
int error = dladdr((void*)&InitializeImageBase, &info);
|
||
|
|
|
||
|
|
IL2CPP_ASSERT(error != 0);
|
||
|
|
if (error == 0)
|
||
|
|
return;
|
||
|
|
|
||
|
|
s_ImageBase = info.dli_fbase;
|
||
|
|
}
|
||
|
|
|
||
|
|
#if IL2CPP_SIZEOF_VOID_P == 8
|
||
|
|
typedef struct mach_header_64 arch_header_t;
|
||
|
|
#else
|
||
|
|
typedef struct mach_header arch_header_t;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
static uint8_t* SectionDataFor(int imageIndex, unsigned long* size)
|
||
|
|
{
|
||
|
|
return getsectiondata((const arch_header_t*)_dyld_get_image_header(imageIndex), "__TEXT", IL2CPP_BINARY_SECTION_NAME, size);
|
||
|
|
}
|
||
|
|
|
||
|
|
static void InitializeManagedSection()
|
||
|
|
{
|
||
|
|
int imageIndex = GetImageIndex();
|
||
|
|
if (imageIndex == -1)
|
||
|
|
return;
|
||
|
|
|
||
|
|
unsigned long sectionSize = 0;
|
||
|
|
uint8_t* sectionData = SectionDataFor(imageIndex, §ionSize);
|
||
|
|
if (sectionData == NULL)
|
||
|
|
{
|
||
|
|
// We did not find the managed section of the binary in the image where we
|
||
|
|
// think it should live. Maybe Unity is being embedded in another application.
|
||
|
|
// Let's search all of the images and find the first one that has our section
|
||
|
|
// in the binary.
|
||
|
|
//
|
||
|
|
// This won't work correctly if more than one Unity binary is embedded, but we
|
||
|
|
// don't support that case yet.
|
||
|
|
int numberOfImages = _dyld_image_count();
|
||
|
|
imageIndex = 0;
|
||
|
|
while (sectionData == NULL && imageIndex < numberOfImages)
|
||
|
|
{
|
||
|
|
sectionData = SectionDataFor(imageIndex, §ionSize);
|
||
|
|
imageIndex++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (sectionData != NULL)
|
||
|
|
{
|
||
|
|
void* start = (void*)sectionData;
|
||
|
|
void* end = (uint8_t*)start + sectionSize;
|
||
|
|
|
||
|
|
SetManagedSectionStartAndEnd(start, end);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Initialize()
|
||
|
|
{
|
||
|
|
InitializeImageBase();
|
||
|
|
InitializeManagedSection();
|
||
|
|
}
|
||
|
|
|
||
|
|
void* GetImageBase()
|
||
|
|
{
|
||
|
|
return s_ImageBase;
|
||
|
|
}
|
||
|
|
|
||
|
|
#if IL2CPP_ENABLE_NATIVE_INSTRUCTION_POINTER_EMISSION
|
||
|
|
char* GetImageUUID()
|
||
|
|
{
|
||
|
|
int imageIndex = GetImageIndex();
|
||
|
|
if (imageIndex == -1)
|
||
|
|
return NULL;
|
||
|
|
|
||
|
|
const struct mach_header_64* header = (mach_header_64*)_dyld_get_image_header(imageIndex);
|
||
|
|
const uint8_t *command = (const uint8_t *)(header + 1);
|
||
|
|
|
||
|
|
for (uint32_t idx = 0; idx < header->ncmds; ++idx)
|
||
|
|
{
|
||
|
|
if (((const struct load_command *)command)->cmd == LC_UUID)
|
||
|
|
{
|
||
|
|
command += sizeof(struct load_command);
|
||
|
|
char* uuid = static_cast<char*>(IL2CPP_MALLOC(33));
|
||
|
|
snprintf(uuid, 33, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||
|
|
command[0], command[1], command[2], command[3],
|
||
|
|
command[4], command[5], command[6], command[7],
|
||
|
|
command[8], command[9], command[10], command[11],
|
||
|
|
command[12], command[13], command[14], command[15]);
|
||
|
|
return uuid;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
command += ((const struct load_command *)command)->cmdsize;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
char* GetImageName()
|
||
|
|
{
|
||
|
|
const char* imageName = _dyld_get_image_name(GetImageIndex());
|
||
|
|
size_t nameSize = strlen(imageName);
|
||
|
|
char* imageNameCopy = (char*)IL2CPP_MALLOC(nameSize + 1);
|
||
|
|
strncpy(imageNameCopy, imageName, nameSize + 1);
|
||
|
|
return imageNameCopy;
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif
|