ELFLoader.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. #include "ELFLoader.h"
  2. #include <AK/Demangle.h>
  3. #include <AK/QuickSort.h>
  4. #include <AK/kstdio.h>
  5. #ifdef KERNEL
  6. #include <Kernel/VM/MemoryManager.h>
  7. #define do_memcpy copy_to_user
  8. #else
  9. #define do_memcpy memcpy
  10. #endif
  11. //#define ELFLOADER_DEBUG
  12. ELFLoader::ELFLoader(const u8* buffer, size_t size)
  13. : m_image(buffer, size)
  14. {
  15. }
  16. ELFLoader::~ELFLoader()
  17. {
  18. }
  19. bool ELFLoader::load()
  20. {
  21. #ifdef ELFLOADER_DEBUG
  22. m_image.dump();
  23. #endif
  24. if (!m_image.is_valid())
  25. return false;
  26. if (!layout())
  27. return false;
  28. return true;
  29. }
  30. bool ELFLoader::layout()
  31. {
  32. bool failed = false;
  33. m_image.for_each_program_header([&](const ELFImage::ProgramHeader& program_header) {
  34. if (program_header.type() == PT_TLS) {
  35. #ifdef KERNEL
  36. auto* tls_image = tls_section_hook(program_header.size_in_memory(), program_header.alignment());
  37. if (!tls_image) {
  38. failed = true;
  39. return;
  40. }
  41. if (!m_image.is_within_image(program_header.raw_data(), program_header.size_in_image())) {
  42. dbg() << "Shenanigans! ELF PT_TLS header sneaks outside of executable.";
  43. failed = true;
  44. return;
  45. }
  46. do_memcpy(tls_image, program_header.raw_data(), program_header.size_in_image());
  47. #endif
  48. return;
  49. }
  50. if (program_header.type() != PT_LOAD)
  51. return;
  52. #ifdef ELFLOADER_DEBUG
  53. kprintf("PH: V%p %u r:%u w:%u\n", program_header.vaddr().get(), program_header.size_in_memory(), program_header.is_readable(), program_header.is_writable());
  54. #endif
  55. #ifdef KERNEL
  56. if (program_header.is_writable()) {
  57. auto* allocated_section = alloc_section_hook(
  58. program_header.vaddr(),
  59. program_header.size_in_memory(),
  60. program_header.alignment(),
  61. program_header.is_readable(),
  62. program_header.is_writable(),
  63. String::format("elf-alloc-%s%s", program_header.is_readable() ? "r" : "", program_header.is_writable() ? "w" : ""));
  64. if (!allocated_section) {
  65. failed = true;
  66. return;
  67. }
  68. if (!m_image.is_within_image(program_header.raw_data(), program_header.size_in_image())) {
  69. dbg() << "Shenanigans! Writable ELF PT_LOAD header sneaks outside of executable.";
  70. failed = true;
  71. return;
  72. }
  73. // It's not always the case with PIE executables (and very well shouldn't be) that the
  74. // virtual address in the program header matches the one we end up giving the process.
  75. // In order to copy the data image correctly into memory, we need to copy the data starting at
  76. // the right initial page offset into the pages allocated for the elf_alloc-XX section.
  77. // FIXME: There's an opportunity to munmap, or at least mprotect, the padding space between
  78. // the .text and .data PT_LOAD sections of the executable.
  79. // Accessing it would definitely be a bug.
  80. auto page_offset = program_header.vaddr();
  81. page_offset.mask(~PAGE_MASK);
  82. do_memcpy((u8*)allocated_section + page_offset.get(), program_header.raw_data(), program_header.size_in_image());
  83. } else {
  84. auto* mapped_section = map_section_hook(
  85. program_header.vaddr(),
  86. program_header.size_in_memory(),
  87. program_header.alignment(),
  88. program_header.offset(),
  89. program_header.is_readable(),
  90. program_header.is_writable(),
  91. program_header.is_executable(),
  92. String::format("elf-map-%s%s%s", program_header.is_readable() ? "r" : "", program_header.is_writable() ? "w" : "", program_header.is_executable() ? "x" : ""));
  93. if (!mapped_section) {
  94. failed = true;
  95. }
  96. }
  97. #endif
  98. });
  99. return !failed;
  100. }
  101. char* ELFLoader::symbol_ptr(const char* name)
  102. {
  103. char* found_ptr = nullptr;
  104. m_image.for_each_symbol([&](const ELFImage::Symbol symbol) {
  105. if (symbol.type() != STT_FUNC)
  106. return IterationDecision::Continue;
  107. if (symbol.name() == name)
  108. return IterationDecision::Continue;
  109. if (m_image.is_executable())
  110. found_ptr = (char*)(size_t)symbol.value();
  111. else
  112. ASSERT_NOT_REACHED();
  113. return IterationDecision::Break;
  114. });
  115. return found_ptr;
  116. }
  117. String ELFLoader::symbolicate(u32 address, u32* out_offset) const
  118. {
  119. SortedSymbol* sorted_symbols = nullptr;
  120. #ifdef KERNEL
  121. if (!m_sorted_symbols_region) {
  122. m_sorted_symbols_region = MM.allocate_kernel_region(PAGE_ROUND_UP(m_image.symbol_count() * sizeof(SortedSymbol)), "Sorted symbols", Region::Access::Read | Region::Access::Write);
  123. sorted_symbols = (SortedSymbol*)m_sorted_symbols_region->vaddr().as_ptr();
  124. size_t index = 0;
  125. m_image.for_each_symbol([&](auto& symbol) {
  126. sorted_symbols[index++] = { symbol.value(), symbol.name() };
  127. return IterationDecision::Continue;
  128. });
  129. quick_sort(sorted_symbols, sorted_symbols + m_image.symbol_count(), [](auto& a, auto& b) {
  130. return a.address < b.address;
  131. });
  132. } else {
  133. sorted_symbols = (SortedSymbol*)m_sorted_symbols_region->vaddr().as_ptr();
  134. }
  135. #else
  136. if (m_sorted_symbols.is_empty()) {
  137. m_sorted_symbols.ensure_capacity(m_image.symbol_count());
  138. m_image.for_each_symbol([this](auto& symbol) {
  139. m_sorted_symbols.append({ symbol.value(), symbol.name() });
  140. return IterationDecision::Continue;
  141. });
  142. quick_sort(m_sorted_symbols.begin(), m_sorted_symbols.end(), [](auto& a, auto& b) {
  143. return a.address < b.address;
  144. });
  145. }
  146. sorted_symbols = m_sorted_symbols.data();
  147. #endif
  148. for (size_t i = 0; i < m_image.symbol_count(); ++i) {
  149. if (sorted_symbols[i].address > address) {
  150. if (i == 0)
  151. return "!!";
  152. auto& symbol = sorted_symbols[i - 1];
  153. if (out_offset) {
  154. *out_offset = address - symbol.address;
  155. return demangle(symbol.name);
  156. }
  157. return String::format("%s +%u", demangle(symbol.name).characters(), address - symbol.address);
  158. }
  159. }
  160. return "??";
  161. }