No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Image.cpp 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. #include "il2cpp-config.h"
  2. #include "utils/Memory.h"
  3. #if (IL2CPP_TARGET_JAVASCRIPT || IL2CPP_TARGET_LINUX || IL2CPP_TARGET_QNX) || IL2CPP_TARGET_ANDROID
  4. #include "os/Image.h"
  5. #if IL2CPP_TARGET_JAVASCRIPT
  6. #include <emscripten/emscripten.h>
  7. #else
  8. #include <dlfcn.h>
  9. #endif
  10. #if IL2CPP_ENABLE_NATIVE_INSTRUCTION_POINTER_EMISSION && (IL2CPP_TARGET_ANDROID || IL2CPP_TARGET_LINUX || IL2CPP_TARGET_QNX)
  11. #include <elf.h>
  12. #if __x86_64__ || __aarch64__
  13. # define ElfW(type) Elf64_##type
  14. #else
  15. # define ElfW(type) Elf32_##type
  16. #endif
  17. #endif
  18. #include <cstdio>
  19. extern char __start_il2cpp;
  20. extern char __stop_il2cpp;
  21. namespace il2cpp
  22. {
  23. namespace os
  24. {
  25. namespace Image
  26. {
  27. static void* s_ImageBase = NULL;
  28. void* GetImageBase()
  29. {
  30. #if IL2CPP_TARGET_JAVASCRIPT
  31. emscripten_log(EM_LOG_NO_PATHS | EM_LOG_CONSOLE | EM_LOG_ERROR | EM_LOG_JS_STACK, "Warning: libil2cpp/os/Posix/Image.cpp: GetImageBase() called, but dynamic libraries are not available.");
  32. return NULL;
  33. #else
  34. return s_ImageBase;
  35. #endif
  36. }
  37. static IL2CPP_METHOD_ATTR void NoGeneratedCodeWorkaround()
  38. {
  39. }
  40. static void InitializeImageBase()
  41. {
  42. #if !IL2CPP_TARGET_JAVASCRIPT
  43. // Gets info about the image containing InitializeImageBase
  44. Dl_info info;
  45. memset(&info, 0, sizeof(info));
  46. int error = dladdr((void*)&InitializeImageBase, &info);
  47. IL2CPP_ASSERT(error != 0);
  48. if (error == 0)
  49. return;
  50. s_ImageBase = info.dli_fbase;
  51. #endif
  52. }
  53. void InitializeManagedSection()
  54. {
  55. NoGeneratedCodeWorkaround();
  56. // Since the native linker creates the __start_il2cpp and __stop_il2cpp
  57. // globals, we can only use them when IL2CPP_PLATFORM_SUPPORTS_CUSTOM_SECTIONS
  58. // is defined. Otherwise, they will not exist, and this usage of them will cause
  59. // an unresolved external error in the native linker. This should be the only
  60. // place in runtime code that IL2CPP_PLATFORM_SUPPORTS_CUSTOM_SECTIONS is used.
  61. #if IL2CPP_PLATFORM_SUPPORTS_CUSTOM_SECTIONS
  62. SetManagedSectionStartAndEnd(&__start_il2cpp, &__stop_il2cpp);
  63. #endif
  64. }
  65. void Initialize()
  66. {
  67. InitializeImageBase();
  68. InitializeManagedSection();
  69. }
  70. #if IL2CPP_ENABLE_NATIVE_INSTRUCTION_POINTER_EMISSION
  71. #if IL2CPP_TARGET_ANDROID || IL2CPP_TARGET_LINUX
  72. char* GetELFImageBuildID()
  73. {
  74. size_t imageBase = (size_t)GetImageBase();
  75. ElfW(Ehdr) * ehdr = (ElfW(Ehdr) *)imageBase;
  76. ElfW(Phdr) * phdr = (ElfW(Phdr) *)(imageBase + ehdr->e_phoff);
  77. // Bug fix requires the lowest PT_LOAD address, not the lowest PT_LOAD offset
  78. // https://unix.stackexchange.com/questions/669237/how-to-tell-whether-the-p-vaddr-in-elf-program-header-is-the-real-memory-address
  79. ElfW(Addr) pt_load_low = SIZE_MAX; // Set the max value, if it's not changed, assume a zero offset
  80. for (int i = 0; i < ehdr->e_phnum; i++)
  81. {
  82. if (phdr[i].p_type == PT_LOAD && phdr[i].p_vaddr < pt_load_low)
  83. {
  84. pt_load_low = phdr[i].p_vaddr;
  85. }
  86. }
  87. pt_load_low = (pt_load_low == SIZE_MAX) ? 0 : pt_load_low;
  88. for (int i = 0; i < ehdr->e_phnum; i++)
  89. {
  90. if (phdr[i].p_type == PT_NOTE)
  91. {
  92. size_t nhdr_ptr = phdr[i].p_vaddr + imageBase - pt_load_low;
  93. size_t nhdr_end = nhdr_ptr + phdr[i].p_memsz;
  94. int j = 0;
  95. while (nhdr_ptr < nhdr_end)
  96. {
  97. ElfW(Nhdr) * nhdr = (ElfW(Nhdr) *)nhdr_ptr;
  98. if (nhdr->n_type == NT_GNU_BUILD_ID)
  99. {
  100. uint8_t* image_build_id = (uint8_t *)((size_t)nhdr + sizeof(ElfW(Nhdr)) + nhdr->n_namesz);
  101. char* build_id = static_cast<char*>(IL2CPP_MALLOC(41));
  102. for (int j = 0; j < nhdr->n_descsz; j++)
  103. {
  104. snprintf(&build_id[j * 2], 3, "%02x", image_build_id[j]);
  105. }
  106. return build_id;
  107. }
  108. nhdr_ptr += sizeof(ElfW(Nhdr)) + nhdr->n_descsz + nhdr->n_namesz;
  109. }
  110. break;
  111. }
  112. }
  113. return NULL;
  114. }
  115. #endif
  116. char* GetImageUUID()
  117. {
  118. #if IL2CPP_TARGET_ANDROID || IL2CPP_TARGET_LINUX
  119. return GetELFImageBuildID();
  120. #else
  121. #error Implement GetImageUUID for this platform
  122. #endif
  123. }
  124. char* GetImageName()
  125. {
  126. #if IL2CPP_TARGET_ANDROID || IL2CPP_TARGET_LINUX
  127. Dl_info info;
  128. void* const anySymbol = reinterpret_cast<void*>(&GetImageBase);
  129. if (dladdr(anySymbol, &info))
  130. {
  131. size_t nameSize = strlen(info.dli_fname);
  132. char* imageName = (char*)IL2CPP_MALLOC(nameSize);
  133. strncpy(imageName, info.dli_fname, nameSize);
  134. return imageName;
  135. }
  136. else
  137. return NULL;
  138. #else
  139. #error Implement GetImageName for this platform
  140. #endif
  141. }
  142. #endif
  143. }
  144. }
  145. }
  146. #endif