ELFDynamicLoader.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. #include <AK/StringBuilder.h>
  2. #include <LibELF/ELFDynamicLoader.h>
  3. #include <assert.h>
  4. #include <dlfcn.h>
  5. #include <mman.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #define DYNAMIC_LOAD_DEBUG
  9. //#define DYNAMIC_LOAD_VERBOSE
  10. #ifdef DYNAMIC_LOAD_VERBOSE
  11. # define VERBOSE(fmt, ...) dbgprintf(fmt, ##__VA_ARGS__)
  12. #else
  13. # define VERBOSE(fmt, ...) \
  14. do { \
  15. } while (0)
  16. #endif
  17. static bool s_always_bind_now = false;
  18. NonnullRefPtr<ELFDynamicLoader> ELFDynamicLoader::construct(const char* filename, int fd, size_t size)
  19. {
  20. return adopt(*new ELFDynamicLoader(filename, fd, size));
  21. }
  22. ELFDynamicLoader::ELFDynamicLoader(const char* filename, int fd, size_t size)
  23. : m_filename(filename)
  24. , m_file_size(size)
  25. , m_image_fd(fd)
  26. {
  27. String file_mmap_name = String::format("ELF_DYN: %s", m_filename.characters());
  28. m_file_mapping = mmap_with_name(nullptr, size, PROT_READ, MAP_PRIVATE, m_image_fd, 0, file_mmap_name.characters());
  29. if (MAP_FAILED == m_file_mapping) {
  30. m_valid = false;
  31. }
  32. }
  33. ELFDynamicLoader::~ELFDynamicLoader()
  34. {
  35. if (MAP_FAILED != m_file_mapping)
  36. munmap(m_file_mapping, m_file_size);
  37. }
  38. void* ELFDynamicLoader::symbol_for_name(const char* name)
  39. {
  40. auto symbol = m_dynamic_object->hash_section().lookup_symbol(name);
  41. if (symbol.is_undefined())
  42. return nullptr;
  43. return m_dynamic_object->base_address().offset(symbol.value()).as_ptr();
  44. }
  45. bool ELFDynamicLoader::load_from_image(unsigned flags)
  46. {
  47. ELFImage elf_image((u8*)m_file_mapping);
  48. m_valid = elf_image.is_valid() && elf_image.is_dynamic();
  49. if (!m_valid) {
  50. return false;
  51. }
  52. const ELFImage::DynamicSection probably_dynamic_section = elf_image.dynamic_section();
  53. if (StringView(".dynamic") != probably_dynamic_section.name() || probably_dynamic_section.type() != SHT_DYNAMIC) {
  54. m_valid = false;
  55. return false;
  56. }
  57. #ifdef DYNAMIC_LOAD_VERBOSE
  58. m_image->dump();
  59. #endif
  60. load_program_headers(elf_image);
  61. const ELFImage::DynamicSection image_dynamic_section = elf_image.dynamic_section();
  62. m_dynamic_object = AK::make<ELFDynamicObject>(m_text_segment_load_address, image_dynamic_section.offset());
  63. return load_stage_2(flags);
  64. }
  65. bool ELFDynamicLoader::load_stage_2(unsigned flags)
  66. {
  67. ASSERT(flags & RTLD_GLOBAL);
  68. ASSERT(flags & RTLD_LAZY);
  69. #ifdef DYNAMIC_LOAD_DEBUG
  70. m_dynamic_object->dump();
  71. #endif
  72. if (m_dynamic_object->has_text_relocations()) {
  73. ASSERT(m_text_segment_load_address.get() != 0);
  74. if (0 > mprotect(m_text_segment_load_address.as_ptr(), m_text_segment_size, PROT_READ | PROT_WRITE)) {
  75. perror("mprotect"); // FIXME: dlerror?
  76. return false;
  77. }
  78. }
  79. do_relocations();
  80. setup_plt_trampoline();
  81. // Clean up our setting of .text to PROT_READ | PROT_WRITE
  82. if (m_dynamic_object->has_text_relocations()) {
  83. if (0 > mprotect(m_text_segment_load_address.as_ptr(), m_text_segment_size, PROT_READ | PROT_EXEC)) {
  84. perror("mprotect"); // FIXME: dlerror?
  85. return false;
  86. }
  87. }
  88. call_object_init_functions();
  89. #ifdef DYNAMIC_LOAD_DEBUG
  90. dbgprintf("Loaded %s\n", m_filename.characters());
  91. #endif
  92. return true;
  93. }
  94. void ELFDynamicLoader::load_program_headers(const ELFImage& elf_image)
  95. {
  96. size_t total_required_allocation_size = 0; // NOTE: If we don't have any TEXTREL, we can keep RO data RO, which would be nice
  97. Vector<ProgramHeaderRegion> program_headers;
  98. ProgramHeaderRegion* text_region_ptr = nullptr;
  99. ProgramHeaderRegion* data_region_ptr = nullptr;
  100. ProgramHeaderRegion* tls_region_ptr = nullptr;
  101. elf_image.for_each_program_header([&](const ELFImage::ProgramHeader& program_header) {
  102. ProgramHeaderRegion new_region;
  103. new_region.set_program_header(program_header.raw_header());
  104. if (new_region.is_load())
  105. total_required_allocation_size += new_region.required_load_size();
  106. program_headers.append(move(new_region));
  107. auto& region = program_headers.last();
  108. if (region.is_tls_template())
  109. tls_region_ptr = &region;
  110. else if (region.is_load()) {
  111. if (region.is_executable())
  112. text_region_ptr = &region;
  113. else
  114. data_region_ptr = &region;
  115. }
  116. });
  117. ASSERT(text_region_ptr && data_region_ptr);
  118. // Process regions in order: .text, .data, .tls
  119. auto* region = text_region_ptr;
  120. void* text_segment_begin = mmap_with_name(nullptr, region->required_load_size(), region->mmap_prot(), MAP_PRIVATE, m_image_fd, region->offset(), String::format(".text: %s", m_filename.characters()).characters());
  121. if (MAP_FAILED == text_segment_begin) {
  122. ASSERT_NOT_REACHED();
  123. }
  124. m_text_segment_size = region->required_load_size();
  125. m_text_segment_load_address = VirtualAddress { (u32)text_segment_begin };
  126. region = data_region_ptr;
  127. void* data_segment_begin = mmap_with_name((u8*)text_segment_begin + m_text_segment_size, region->required_load_size(), region->mmap_prot(), MAP_ANONYMOUS | MAP_PRIVATE, 0, 0, String::format(".data: %s", m_filename.characters()).characters());
  128. if (MAP_FAILED == data_segment_begin) {
  129. ASSERT_NOT_REACHED();
  130. }
  131. VirtualAddress data_segment_actual_addr = region->desired_load_address().offset((u32)text_segment_begin);
  132. memcpy(data_segment_actual_addr.as_ptr(), (u8*)m_file_mapping + region->offset(), region->size_in_image());
  133. // FIXME: Do some kind of 'allocate TLS section' or some such from a per-application pool
  134. if (tls_region_ptr) {
  135. region = tls_region_ptr;
  136. // FIXME: This can't be right either. TLS needs some real work i'd say :)
  137. m_tls_segment_address = tls_region_ptr->desired_load_address();
  138. VirtualAddress tls_segment_actual_addr = region->desired_load_address().offset((u32)text_segment_begin);
  139. memcpy(tls_segment_actual_addr.as_ptr(), (u8*)m_file_mapping + region->offset(), region->size_in_image());
  140. }
  141. }
  142. void ELFDynamicLoader::do_relocations()
  143. {
  144. u32 load_base_address = m_dynamic_object->base_address().get();
  145. // FIXME: We should really bail on undefined symbols here.
  146. auto main_relocation_section = m_dynamic_object->relocation_section();
  147. main_relocation_section.for_each_relocation([&](const ELFDynamicObject::Relocation& relocation) {
  148. VERBOSE("====== RELOCATION %d: offset 0x%08X, type %d, symidx %08X\n", relocation.offset_in_section() / main_relocation_section.entry_size(), relocation.offset(), relocation.type(), relocation.symbol_index());
  149. u32* patch_ptr = (u32*)(load_base_address + relocation.offset());
  150. switch (relocation.type()) {
  151. case R_386_NONE:
  152. // Apparently most loaders will just skip these?
  153. // Seems if the 'link editor' generates one something is funky with your code
  154. VERBOSE("None relocation. No symbol, no nothin.\n");
  155. break;
  156. case R_386_32: {
  157. auto symbol = relocation.symbol();
  158. VERBOSE("Absolute relocation: name: '%s', value: %p\n", symbol.name(), symbol.value());
  159. u32 symbol_address = symbol.value() + load_base_address;
  160. *patch_ptr += symbol_address;
  161. VERBOSE(" Symbol address: %p\n", *patch_ptr);
  162. break;
  163. }
  164. case R_386_PC32: {
  165. auto symbol = relocation.symbol();
  166. VERBOSE("PC-relative relocation: '%s', value: %p\n", symbol.name(), symbol.value());
  167. u32 relative_offset = (symbol.value() - relocation.offset());
  168. *patch_ptr += relative_offset;
  169. VERBOSE(" Symbol address: %p\n", *patch_ptr);
  170. break;
  171. }
  172. case R_386_GLOB_DAT: {
  173. auto symbol = relocation.symbol();
  174. VERBOSE("Global data relocation: '%s', value: %p\n", symbol.name(), symbol.value());
  175. u32 symbol_location = load_base_address + symbol.value();
  176. *patch_ptr = symbol_location;
  177. VERBOSE(" Symbol address: %p\n", *patch_ptr);
  178. break;
  179. }
  180. case R_386_RELATIVE: {
  181. // FIXME: According to the spec, R_386_relative ones must be done first.
  182. // We could explicitly do them first using m_number_of_relocatoins from DT_RELCOUNT
  183. // However, our compiler is nice enough to put them at the front of the relocations for us :)
  184. VERBOSE("Load address relocation at offset %X\n", relocation.offset());
  185. VERBOSE(" patch ptr == %p, adding load base address (%p) to it and storing %p\n", *patch_ptr, load_base_address, *patch_ptr + load_base_address);
  186. *patch_ptr += load_base_address; // + addend for RelA (addend for Rel is stored at addr)
  187. break;
  188. }
  189. case R_386_TLS_TPOFF: {
  190. VERBOSE("Relocation type: R_386_TLS_TPOFF at offset %X\n", relocation.offset());
  191. // FIXME: this can't be right? I have no idea what "negative offset into TLS storage" means...
  192. // FIXME: Check m_has_static_tls and do something different for dynamic TLS
  193. *patch_ptr = relocation.offset() - (u32)m_tls_segment_address.as_ptr() - *patch_ptr;
  194. break;
  195. }
  196. default:
  197. // Raise the alarm! Someone needs to implement this relocation type
  198. dbgprintf("Found a new exciting relocation type %d\n", relocation.type());
  199. printf("ELFDynamicLoader: Found unknown relocation type %d\n", relocation.type());
  200. ASSERT_NOT_REACHED();
  201. break;
  202. }
  203. return IterationDecision::Continue;
  204. });
  205. // Handle PLT Global offset table relocations.
  206. m_dynamic_object->plt_relocation_section().for_each_relocation([&](const ELFDynamicObject::Relocation& relocation) {
  207. // FIXME: Or BIND_NOW flag passed in?
  208. if (m_dynamic_object->must_bind_now() || s_always_bind_now) {
  209. // Eagerly BIND_NOW the PLT entries, doing all the symbol looking goodness
  210. // The patch method returns the address for the LAZY fixup path, but we don't need it here
  211. (void)patch_plt_entry(relocation.offset_in_section());
  212. } else {
  213. // LAZY-ily bind the PLT slots by just adding the base address to the offsets stored there
  214. // This avoids doing symbol lookup, which might be expensive
  215. ASSERT(relocation.type() == R_386_JMP_SLOT);
  216. u8* relocation_address = relocation.address().as_ptr();
  217. *(u32*)relocation_address += load_base_address;
  218. }
  219. return IterationDecision::Continue;
  220. });
  221. #ifdef DYNAMIC_LOAD_DEBUG
  222. dbgprintf("Done relocating!\n");
  223. #endif
  224. }
  225. // Defined in <arch>/plt_trampoline.S
  226. extern "C" void _plt_trampoline(void) __attribute__((visibility("hidden")));
  227. void ELFDynamicLoader::setup_plt_trampoline()
  228. {
  229. VirtualAddress got_address = m_dynamic_object->plt_got_base_address();
  230. u32* got_u32_ptr = (u32*)got_address.as_ptr();
  231. got_u32_ptr[1] = (u32)this;
  232. got_u32_ptr[2] = (u32)&_plt_trampoline;
  233. #ifdef DYNAMIC_LOAD_DEBUG
  234. dbgprintf("Set GOT PLT entries at %p: [0] = %p [1] = %p, [2] = %p\n", got_u32_ptr, got_u32_ptr[0], got_u32_ptr[1], got_u32_ptr[2]);
  235. #endif
  236. }
  237. // Called from our ASM routine _plt_trampoline
  238. extern "C" Elf32_Addr _fixup_plt_entry(ELFDynamicLoader* object, u32 relocation_offset)
  239. {
  240. return object->patch_plt_entry(relocation_offset);
  241. }
  242. // offset is in PLT relocation table
  243. Elf32_Addr ELFDynamicLoader::patch_plt_entry(u32 relocation_offset)
  244. {
  245. auto relocation = m_dynamic_object->plt_relocation_section().relocation_at_offset(relocation_offset);
  246. ASSERT(relocation.type() == R_386_JMP_SLOT);
  247. auto sym = relocation.symbol();
  248. u8* relocation_address = relocation.address().as_ptr();
  249. u32 symbol_location = sym.address().get();
  250. VERBOSE("ELFDynamicLoader: Jump slot relocation: putting %s (%p) into PLT at %p\n", sym.name(), symbol_location, relocation_address);
  251. *(u32*)relocation_address = symbol_location;
  252. return symbol_location;
  253. }
  254. void ELFDynamicLoader::call_object_init_functions()
  255. {
  256. typedef void (*InitFunc)();
  257. auto init_function = (InitFunc)(m_dynamic_object->init_section().address().as_ptr());
  258. #ifdef DYNAMIC_LOAD_DEBUG
  259. dbgprintf("Calling DT_INIT at %p\n", init_function);
  260. #endif
  261. (init_function)();
  262. auto init_array_section = m_dynamic_object->init_array_section();
  263. InitFunc* init_begin = (InitFunc*)(init_array_section.address().as_ptr());
  264. InitFunc* init_end = init_begin + init_array_section.entry_count();
  265. while (init_begin != init_end) {
  266. // Android sources claim that these can be -1, to be ignored.
  267. // 0 definitely shows up. Apparently 0/-1 are valid? Confusing.
  268. if (!*init_begin || ((i32)*init_begin == -1))
  269. continue;
  270. #ifdef DYNAMIC_LOAD_DEBUG
  271. dbgprintf("Calling DT_INITARRAY entry at %p\n", *init_begin);
  272. #endif
  273. (*init_begin)();
  274. ++init_begin;
  275. }
  276. }
  277. u32 ELFDynamicLoader::ProgramHeaderRegion::mmap_prot() const
  278. {
  279. int prot = 0;
  280. prot |= is_executable() ? PROT_EXEC : 0;
  281. prot |= is_readable() ? PROT_READ : 0;
  282. prot |= is_writable() ? PROT_WRITE : 0;
  283. return prot;
  284. }