ELFLoader.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. #include "ELFLoader.h"
  2. #include <AK/kstdio.h>
  3. #include <AK/QuickSort.h>
  4. //#define ELFLOADER_DEBUG
  5. //#define SUPPORT_RELOCATIONS
  6. ELFLoader::ELFLoader(const byte* buffer)
  7. : m_image(buffer)
  8. {
  9. }
  10. ELFLoader::~ELFLoader()
  11. {
  12. }
  13. bool ELFLoader::load()
  14. {
  15. #ifdef ELFLOADER_DEBUG
  16. m_image.dump();
  17. #endif
  18. if (!m_image.is_valid())
  19. return false;
  20. if (!layout())
  21. return false;
  22. #ifdef SUPPORT_RELOCATIONS
  23. if (!perform_relocations())
  24. return false;
  25. #endif
  26. return true;
  27. }
  28. bool ELFLoader::layout()
  29. {
  30. #ifdef ELFLOADER_DEBUG
  31. kprintf("ELFLoader: Layout\n");
  32. #endif
  33. bool failed = false;
  34. m_image.for_each_program_header([&] (const ELFImage::ProgramHeader& program_header) {
  35. if (program_header.type() != PT_LOAD)
  36. return;
  37. #ifdef ELFLOADER_DEBUG
  38. kprintf("PH: L%x %u r:%u w:%u\n", program_header.laddr().get(), program_header.size_in_memory(), program_header.is_readable(), program_header.is_writable());
  39. #endif
  40. if (program_header.is_writable()) {
  41. alloc_section_hook(
  42. program_header.laddr(),
  43. program_header.size_in_memory(),
  44. program_header.alignment(),
  45. program_header.is_readable(),
  46. program_header.is_writable(),
  47. String::format("elf-alloc-%s%s", program_header.is_readable() ? "r" : "", program_header.is_writable() ? "w" : "")
  48. );
  49. memcpy(program_header.laddr().as_ptr(), program_header.raw_data(), program_header.size_in_image());
  50. } else {
  51. map_section_hook(
  52. program_header.laddr(),
  53. program_header.size_in_memory(),
  54. program_header.alignment(),
  55. program_header.offset(),
  56. program_header.is_readable(),
  57. program_header.is_writable(),
  58. String::format("elf-map-%s%s", program_header.is_readable() ? "r" : "", program_header.is_writable() ? "w" : "")
  59. );
  60. }
  61. });
  62. return !failed;
  63. }
  64. #ifdef SUPPORT_RELOCATIONS
  65. void* ELFLoader::lookup(const ELFImage::Symbol& symbol)
  66. {
  67. if (symbol.section().is_undefined())
  68. return symbol_ptr(symbol.name());
  69. return area_for_section(symbol.section()) + symbol.value();
  70. }
  71. #endif
  72. #ifdef SUPPORT_RELOCATIONS
  73. char* ELFLoader::area_for_section(const ELFImage::Section& section)
  74. {
  75. return area_for_section_name(section.name());
  76. }
  77. char* ELFLoader::area_for_section_name(const char* name)
  78. {
  79. if (auto it = m_sections.find(name); it != m_sections.end())
  80. return (*it).value;
  81. ASSERT_NOT_REACHED();
  82. return nullptr;
  83. }
  84. #endif
  85. #ifdef SUPPORT_RELOCATIONS
  86. bool ELFLoader::perform_relocations()
  87. {
  88. #ifdef ELFLOADER_DEBUG
  89. kprintf("ELFLoader: Performing relocations\n");
  90. #endif
  91. bool failed = false;
  92. m_image.for_each_section_of_type(SHT_PROGBITS, [this, &failed] (const ELFImage::Section& section) -> bool {
  93. auto& relocations = section.relocations();
  94. if (relocations.is_undefined())
  95. return true;
  96. relocations.for_each_relocation([this, section, &failed] (const ELFImage::Relocation& relocation) {
  97. auto symbol = relocation.symbol();
  98. auto& patch_ptr = *reinterpret_cast<ptrdiff_t*>(area_for_section(section) + relocation.offset());
  99. switch (relocation.type()) {
  100. case R_386_PC32: {
  101. char* target_ptr = (char*)lookup(symbol);
  102. if (!target_ptr) {
  103. kprintf("ELFLoader: unresolved symbol '%s'\n", symbol.name());
  104. failed = true;
  105. return false;
  106. }
  107. ptrdiff_t relative_offset = (char*)target_ptr - ((char*)&patch_ptr + 4);
  108. #ifdef ELFLOADER_DEBUG
  109. kprintf("ELFLoader: Relocate PC32: offset=%x, symbol=%u(%s) value=%x target=%p, offset=%d\n",
  110. relocation.offset(),
  111. symbol.index(),
  112. symbol.name(),
  113. symbol.value(),
  114. target_ptr,
  115. relative_offset
  116. );
  117. #endif
  118. patch_ptr = relative_offset;
  119. break;
  120. }
  121. case R_386_32: {
  122. #ifdef ELFLOADER_DEBUG
  123. kprintf("ELFLoader: Relocate Abs32: symbol=%u(%s), value=%x, section=%s\n",
  124. symbol.index(),
  125. symbol.name(),
  126. symbol.value(),
  127. symbol.section().name()
  128. );
  129. #endif
  130. char* target_ptr = area_for_section(symbol.section()) + symbol.value();
  131. patch_ptr += (ptrdiff_t)target_ptr;
  132. break;
  133. }
  134. default:
  135. ASSERT_NOT_REACHED();
  136. break;
  137. }
  138. return true;
  139. });
  140. return !failed;
  141. });
  142. return !failed;
  143. }
  144. #endif
  145. char* ELFLoader::symbol_ptr(const char* name)
  146. {
  147. char* found_ptr = nullptr;
  148. m_image.for_each_symbol([&] (const ELFImage::Symbol symbol) {
  149. if (symbol.type() != STT_FUNC)
  150. return IterationDecision::Continue;
  151. if (strcmp(symbol.name(), name))
  152. return IterationDecision::Continue;
  153. if (m_image.is_executable())
  154. found_ptr = (char*)symbol.value();
  155. #ifdef SUPPORT_RELOCATIONS
  156. else if (m_image.is_relocatable())
  157. found_ptr = area_for_section(symbol.section()) + symbol.value();
  158. #endif
  159. else
  160. ASSERT_NOT_REACHED();
  161. return IterationDecision::Abort;
  162. });
  163. return found_ptr;
  164. }
  165. String ELFLoader::symbolicate(dword address) const
  166. {
  167. if (m_sorted_symbols.is_empty()) {
  168. m_sorted_symbols.ensure_capacity(m_image.symbol_count());
  169. m_image.for_each_symbol([this] (auto& symbol) {
  170. m_sorted_symbols.append({ symbol.value(), symbol.name() });
  171. return IterationDecision::Continue;
  172. });
  173. quick_sort(m_sorted_symbols.begin(), m_sorted_symbols.end(), [] (auto& a, auto& b) {
  174. return a.address < b.address;
  175. });
  176. }
  177. for (int i = 0; i < m_sorted_symbols.size(); ++i) {
  178. if (m_sorted_symbols[i].address > address) {
  179. if (i == 0)
  180. return "!!";
  181. auto& symbol = m_sorted_symbols[i - 1];
  182. return String::format("%s +%u", symbol.name, address - symbol.address);
  183. }
  184. }
  185. return "??";
  186. }