#include "il2cpp-config.h" #include "utils/Memory.h" #if IL2CPP_TARGET_DARWIN #include "os/Image.h" #include #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; 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(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); strncpy(imageNameCopy, imageName, nameSize); return imageNameCopy; } #endif } } } #endif