Image.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #include "il2cpp-config.h"
  2. #include "utils/Memory.h"
  3. #if (IL2CPP_TARGET_JAVASCRIPT || IL2CPP_TARGET_LINUX || IL2CPP_TARGET_QNX && !RUNTIME_TINY) || 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. void* GetImageBase()
  28. {
  29. #if IL2CPP_TARGET_JAVASCRIPT
  30. 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.");
  31. return NULL;
  32. #else
  33. Dl_info info;
  34. void* const anySymbol = reinterpret_cast<void*>(&GetImageBase);
  35. if (dladdr(anySymbol, &info))
  36. return info.dli_fbase;
  37. else
  38. return NULL;
  39. #endif
  40. }
  41. static IL2CPP_METHOD_ATTR void NoGeneratedCodeWorkaround()
  42. {
  43. }
  44. void InitializeManagedSection()
  45. {
  46. NoGeneratedCodeWorkaround();
  47. // Since the native linker creates the __start_il2cpp and __stop_il2cpp
  48. // globals, we can only use them when IL2CPP_PLATFORM_SUPPORTS_CUSTOM_SECTIONS
  49. // is defined. Otherwise, they will not exist, and this usage of them will cause
  50. // an unresolved external error in the native linker. This should be the only
  51. // place in runtime code that IL2CPP_PLATFORM_SUPPORTS_CUSTOM_SECTIONS is used.
  52. #if IL2CPP_PLATFORM_SUPPORTS_CUSTOM_SECTIONS
  53. SetManagedSectionStartAndEnd(&__start_il2cpp, &__stop_il2cpp);
  54. #endif
  55. }
  56. void Initialize()
  57. {
  58. InitializeManagedSection();
  59. }
  60. #if IL2CPP_ENABLE_NATIVE_INSTRUCTION_POINTER_EMISSION
  61. #if IL2CPP_TARGET_ANDROID || IL2CPP_TARGET_LINUX
  62. char* GetELFImageBuildID()
  63. {
  64. size_t imageBase = (size_t)GetImageBase();
  65. ElfW(Ehdr) * ehdr = (ElfW(Ehdr) *)imageBase;
  66. ElfW(Phdr) * phdr = (ElfW(Phdr) *)(imageBase + ehdr->e_phoff);
  67. // Bug fix requires the lowest PT_LOAD address, not the lowest PT_LOAD offset
  68. // https://unix.stackexchange.com/questions/669237/how-to-tell-whether-the-p-vaddr-in-elf-program-header-is-the-real-memory-address
  69. ElfW(Addr) pt_load_low = SIZE_MAX; // Set the max value, if it's not changed, assume a zero offset
  70. for (int i = 0; i < ehdr->e_phnum; i++)
  71. {
  72. if (phdr[i].p_type == PT_LOAD && phdr[i].p_vaddr < pt_load_low)
  73. {
  74. pt_load_low = phdr[i].p_vaddr;
  75. }
  76. }
  77. pt_load_low = (pt_load_low == SIZE_MAX) ? 0 : pt_load_low;
  78. for (int i = 0; i < ehdr->e_phnum; i++)
  79. {
  80. if (phdr[i].p_type == PT_NOTE)
  81. {
  82. size_t nhdr_ptr = phdr[i].p_vaddr + imageBase - pt_load_low;
  83. size_t nhdr_end = nhdr_ptr + phdr[i].p_memsz;
  84. int j = 0;
  85. while (nhdr_ptr < nhdr_end)
  86. {
  87. ElfW(Nhdr) * nhdr = (ElfW(Nhdr) *)nhdr_ptr;
  88. if (nhdr->n_type == NT_GNU_BUILD_ID)
  89. {
  90. uint8_t* image_build_id = (uint8_t *)((size_t)nhdr + sizeof(ElfW(Nhdr)) + nhdr->n_namesz);
  91. char* build_id = static_cast<char*>(IL2CPP_MALLOC(41));
  92. for (int j = 0; j < nhdr->n_descsz; j++)
  93. {
  94. snprintf(&build_id[j * 2], 3, "%02x", image_build_id[j]);
  95. }
  96. return build_id;
  97. }
  98. nhdr_ptr += sizeof(ElfW(Nhdr)) + nhdr->n_descsz + nhdr->n_namesz;
  99. }
  100. break;
  101. }
  102. }
  103. return NULL;
  104. }
  105. #endif
  106. char* GetImageUUID()
  107. {
  108. #if IL2CPP_TARGET_ANDROID || IL2CPP_TARGET_LINUX
  109. return GetELFImageBuildID();
  110. #else
  111. #error Implement GetImageUUID for this platform
  112. #endif
  113. }
  114. char* GetImageName()
  115. {
  116. #if IL2CPP_TARGET_ANDROID || IL2CPP_TARGET_LINUX
  117. Dl_info info;
  118. void* const anySymbol = reinterpret_cast<void*>(&GetImageBase);
  119. if (dladdr(anySymbol, &info))
  120. {
  121. size_t nameSize = strlen(info.dli_fname);
  122. char* imageName = (char*)IL2CPP_MALLOC(nameSize);
  123. strncpy(imageName, info.dli_fname, nameSize);
  124. return imageName;
  125. }
  126. else
  127. return NULL;
  128. #else
  129. #error Implement GetImageName for this platform
  130. #endif
  131. }
  132. #endif
  133. }
  134. }
  135. }
  136. #endif