Image.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. #include "il2cpp-config.h"
  2. #include "utils/Memory.h"
  3. #if IL2CPP_TARGET_DARWIN
  4. #include "os/Image.h"
  5. #include <mach-o/dyld.h>
  6. #include <mach-o/getsect.h>
  7. #include <mach-o/ldsyms.h>
  8. #include <dlfcn.h>
  9. #include <vector>
  10. namespace il2cpp
  11. {
  12. namespace os
  13. {
  14. namespace Image
  15. {
  16. static void* s_ImageBase = NULL;
  17. static int GetImageIndex()
  18. {
  19. // OSX/iOS uses ASLR (address space layout randomization), so
  20. // find where the image is loaded. This is usually zero in the
  21. // debugger for an executable, but non-zero when a debugger is not
  22. // present.
  23. std::vector<char> path;
  24. uint32_t size = 0;
  25. int error = _NSGetExecutablePath(NULL, &size);
  26. IL2CPP_ASSERT(error == -1);
  27. if (error != -1)
  28. return -1;
  29. path.resize(size);
  30. error = _NSGetExecutablePath(&path[0], &size);
  31. IL2CPP_ASSERT(error == 0);
  32. if (error != 0)
  33. return -1;
  34. int gameAssemblyImageIndex = -1;
  35. int executableImageIndex = -1;
  36. int numberOfImages = _dyld_image_count();
  37. for (uint32_t i = 0; i < numberOfImages; i++)
  38. {
  39. const char* imageName = _dyld_get_image_name(i);
  40. if (strstr(imageName, "GameAssembly.dylib") != NULL || strstr(imageName, "UnityFramework.framework/UnityFramework") != NULL)
  41. {
  42. gameAssemblyImageIndex = i;
  43. break;
  44. }
  45. else if (strstr(imageName, &path[0]) != NULL)
  46. {
  47. executableImageIndex = i;
  48. }
  49. }
  50. if (gameAssemblyImageIndex != -1)
  51. return gameAssemblyImageIndex;
  52. else if (executableImageIndex != -1)
  53. return executableImageIndex;
  54. return -1;
  55. }
  56. static void InitializeImageBase()
  57. {
  58. // Gets info about the image containing InitializeImageBase
  59. Dl_info info;
  60. memset(&info, 0, sizeof(info));
  61. int error = dladdr((void*)&InitializeImageBase, &info);
  62. IL2CPP_ASSERT(error != 0);
  63. if (error == 0)
  64. return;
  65. s_ImageBase = info.dli_fbase;
  66. }
  67. #if IL2CPP_SIZEOF_VOID_P == 8
  68. typedef struct mach_header_64 arch_header_t;
  69. #else
  70. typedef struct mach_header arch_header_t;
  71. #endif
  72. static uint8_t* SectionDataFor(int imageIndex, unsigned long* size)
  73. {
  74. return getsectiondata((const arch_header_t*)_dyld_get_image_header(imageIndex), "__TEXT", IL2CPP_BINARY_SECTION_NAME, size);
  75. }
  76. static void InitializeManagedSection()
  77. {
  78. int imageIndex = GetImageIndex();
  79. if (imageIndex == -1)
  80. return;
  81. unsigned long sectionSize = 0;
  82. uint8_t* sectionData = SectionDataFor(imageIndex, &sectionSize);
  83. if (sectionData == NULL)
  84. {
  85. // We did not find the managed section of the binary in the image where we
  86. // think it should live. Maybe Unity is being embedded in another application.
  87. // Let's search all of the images and find the first one that has our section
  88. // in the binary.
  89. //
  90. // This won't work correctly if more than one Unity binary is embedded, but we
  91. // don't support that case yet.
  92. int numberOfImages = _dyld_image_count();
  93. imageIndex = 0;
  94. while (sectionData == NULL && imageIndex < numberOfImages)
  95. {
  96. sectionData = SectionDataFor(imageIndex, &sectionSize);
  97. imageIndex++;
  98. }
  99. }
  100. if (sectionData != NULL)
  101. {
  102. void* start = (void*)sectionData;
  103. void* end = (uint8_t*)start + sectionSize;
  104. SetManagedSectionStartAndEnd(start, end);
  105. }
  106. }
  107. void Initialize()
  108. {
  109. InitializeImageBase();
  110. InitializeManagedSection();
  111. }
  112. void* GetImageBase()
  113. {
  114. return s_ImageBase;
  115. }
  116. #if IL2CPP_ENABLE_NATIVE_INSTRUCTION_POINTER_EMISSION
  117. char* GetImageUUID()
  118. {
  119. int imageIndex = GetImageIndex();
  120. if (imageIndex == -1)
  121. return NULL;
  122. const struct mach_header_64* header = (mach_header_64*)_dyld_get_image_header(imageIndex);
  123. const uint8_t *command = (const uint8_t *)(header + 1);
  124. for (uint32_t idx = 0; idx < header->ncmds; ++idx)
  125. {
  126. if (((const struct load_command *)command)->cmd == LC_UUID)
  127. {
  128. command += sizeof(struct load_command);
  129. char* uuid = static_cast<char*>(IL2CPP_MALLOC(33));
  130. snprintf(uuid, 33, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
  131. command[0], command[1], command[2], command[3],
  132. command[4], command[5], command[6], command[7],
  133. command[8], command[9], command[10], command[11],
  134. command[12], command[13], command[14], command[15]);
  135. return uuid;
  136. }
  137. else
  138. {
  139. command += ((const struct load_command *)command)->cmdsize;
  140. }
  141. }
  142. return NULL;
  143. }
  144. char* GetImageName()
  145. {
  146. const char* imageName = _dyld_get_image_name(GetImageIndex());
  147. size_t nameSize = strlen(imageName);
  148. char* imageNameCopy = (char*)IL2CPP_MALLOC(nameSize);
  149. strncpy(imageNameCopy, imageName, nameSize);
  150. return imageNameCopy;
  151. }
  152. #endif
  153. }
  154. }
  155. }
  156. #endif