#include "il2cpp-config.h" #if IL2CPP_TARGET_DARWIN #include "os/Image.h" #include #include #include #include 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 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; else if (strcmp(imageName, &path[0]) == 0) executableImageIndex = i; } if (gameAssemblyImageIndex != -1) return gameAssemblyImageIndex; else if (executableImageIndex != -1) return executableImageIndex; return -1; } static void InitializeImageBase() { int imageIndex = GetImageIndex(); if (imageIndex != -1) s_ImageBase = (void*)_dyld_get_image_vmaddr_slide(imageIndex); else s_ImageBase = NULL; } #if IL2CPP_SIZEOF_VOID_P == 8 typedef section_64 archSectionData_t; #else typedef section archSectionData_t; #endif static const archSectionData_t* SectionDataFor(int imageIndex) { const struct mach_header* header = _dyld_get_image_header(imageIndex); #if IL2CPP_SIZEOF_VOID_P == 8 return getsectbynamefromheader_64((const struct mach_header_64*)header, "__TEXT", IL2CPP_BINARY_SECTION_NAME); #else return getsectbynamefromheader(header, "__TEXT", IL2CPP_BINARY_SECTION_NAME); #endif } static void InitializeManagedSection() { int imageIndex = GetImageIndex(); if (imageIndex == -1) return; const archSectionData_t* sectionData = SectionDataFor(imageIndex); 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); imageIndex++; } } if (sectionData != NULL) { void* start = (void*)((intptr_t)sectionData->addr + (intptr_t)s_ImageBase); void* end = (uint8_t*)start + sectionData->size; SetManagedSectionStartAndEnd(start, end); } } void Initialize() { InitializeImageBase(); InitializeManagedSection(); } void* GetImageBase() { return s_ImageBase; } } } } #endif