ELFLoader.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. #include "ELFLoader.h"
  2. #include <AK/kstdio.h>
  3. //#define ELFLOADER_DEBUG
  4. #ifdef SERENITY
  5. ELFLoader::ELFLoader(ExecSpace& execSpace, ByteBuffer&& file)
  6. #else
  7. ELFLoader::ELFLoader(ExecSpace& execSpace, MappedFile&& file)
  8. #endif
  9. : m_execSpace(execSpace)
  10. {
  11. m_image = make<ELFImage>(move(file));
  12. }
  13. ELFLoader::~ELFLoader()
  14. {
  15. }
  16. bool ELFLoader::load()
  17. {
  18. #ifdef ELFLOADER_DEBUG
  19. m_image->dump();
  20. #endif
  21. if (!m_image->isValid())
  22. return false;
  23. if (!layout())
  24. return false;
  25. exportSymbols();
  26. if (!performRelocations())
  27. return false;
  28. return true;
  29. }
  30. bool ELFLoader::layout()
  31. {
  32. #ifdef ELFLOADER_DEBUG
  33. kprintf("ELFLoader: Layout\n");
  34. #endif
  35. bool failed = false;
  36. m_image->for_each_program_header([&] (const ELFImage::ProgramHeader& program_header) {
  37. if (program_header.type() != PT_LOAD)
  38. return;
  39. #ifdef ELFLOADER_DEBUG
  40. 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());
  41. #endif
  42. m_execSpace.allocate_section(program_header.laddr(), program_header.size_in_memory(), program_header.alignment(), program_header.is_readable(), program_header.is_writable());
  43. });
  44. m_image->forEachSectionOfType(SHT_PROGBITS, [this, &failed] (const ELFImage::Section& section) {
  45. #ifdef ELFLOADER_DEBUG
  46. kprintf("ELFLoader: Copying progbits section: %s\n", section.name());
  47. #endif
  48. if (!section.size())
  49. return true;
  50. char* ptr = (char*)section.address();
  51. if (!ptr) {
  52. kprintf("ELFLoader: failed to allocate section '%s'\n", section.name());
  53. failed = true;
  54. return false;
  55. }
  56. memcpy(ptr, section.rawData(), section.size());
  57. m_sections.set(section.name(), move(ptr));
  58. return true;
  59. });
  60. m_image->forEachSectionOfType(SHT_NOBITS, [this, &failed] (const ELFImage::Section& section) {
  61. #ifdef ELFLOADER_DEBUG
  62. kprintf("ELFLoader: Copying nobits section: %s\n", section.name());
  63. #endif
  64. if (!section.size())
  65. return true;
  66. char* ptr = (char*)section.address();
  67. if (!ptr) {
  68. kprintf("ELFLoader: failed to allocate section '%s'\n", section.name());
  69. failed = true;
  70. return false;
  71. }
  72. memset(ptr, 0, section.size());
  73. m_sections.set(section.name(), move(ptr));
  74. return true;
  75. });
  76. return !failed;
  77. }
  78. void* ELFLoader::lookup(const ELFImage::Symbol& symbol)
  79. {
  80. if (symbol.section().isUndefined())
  81. return m_execSpace.symbolPtr(symbol.name());
  82. return areaForSection(symbol.section()) + symbol.value();
  83. }
  84. char* ELFLoader::areaForSection(const ELFImage::Section& section)
  85. {
  86. return areaForSectionName(section.name());
  87. }
  88. char* ELFLoader::areaForSectionName(const char* name)
  89. {
  90. if (auto it = m_sections.find(name); it != m_sections.end())
  91. return (*it).value;
  92. ASSERT_NOT_REACHED();
  93. return nullptr;
  94. }
  95. bool ELFLoader::performRelocations()
  96. {
  97. #ifdef ELFLOADER_DEBUG
  98. kprintf("ELFLoader: Performing relocations\n");
  99. #endif
  100. bool failed = false;
  101. m_image->forEachSectionOfType(SHT_PROGBITS, [this, &failed] (const ELFImage::Section& section) -> bool {
  102. auto& relocations = section.relocations();
  103. if (relocations.isUndefined())
  104. return true;
  105. relocations.forEachRelocation([this, section, &failed] (const ELFImage::Relocation& relocation) {
  106. auto symbol = relocation.symbol();
  107. auto& patchPtr = *reinterpret_cast<ptrdiff_t*>(areaForSection(section) + relocation.offset());
  108. switch (relocation.type()) {
  109. case R_386_PC32: {
  110. char* targetPtr = (char*)lookup(symbol);
  111. if (!targetPtr) {
  112. kprintf("ELFLoader: unresolved symbol '%s'\n", symbol.name());
  113. failed = true;
  114. return false;
  115. }
  116. ptrdiff_t relativeOffset = (char*)targetPtr - ((char*)&patchPtr + 4);
  117. #ifdef ELFLOADER_DEBUG
  118. kprintf("ELFLoader: Relocate PC32: offset=%x, symbol=%u(%s) value=%x target=%p, offset=%d\n",
  119. relocation.offset(),
  120. symbol.index(),
  121. symbol.name(),
  122. symbol.value(),
  123. targetPtr,
  124. relativeOffset
  125. );
  126. #endif
  127. patchPtr = relativeOffset;
  128. break;
  129. }
  130. case R_386_32: {
  131. #ifdef ELFLOADER_DEBUG
  132. kprintf("ELFLoader: Relocate Abs32: symbol=%u(%s), value=%x, section=%s\n",
  133. symbol.index(),
  134. symbol.name(),
  135. symbol.value(),
  136. symbol.section().name()
  137. );
  138. #endif
  139. char* targetPtr = areaForSection(symbol.section()) + symbol.value();
  140. patchPtr += (ptrdiff_t)targetPtr;
  141. break;
  142. }
  143. default:
  144. ASSERT_NOT_REACHED();
  145. break;
  146. }
  147. return true;
  148. });
  149. return !failed;
  150. });
  151. return !failed;
  152. }
  153. void ELFLoader::exportSymbols()
  154. {
  155. m_image->forEachSymbol([&] (const ELFImage::Symbol symbol) {
  156. #ifdef ELFLOADER_DEBUG
  157. kprintf("symbol: %u, type=%u, name=%s, section=%u\n", symbol.index(), symbol.type(), symbol.name(), symbol.sectionIndex());
  158. #endif
  159. if (symbol.type() == STT_FUNC) {
  160. char* ptr;
  161. if (m_image->isExecutable())
  162. ptr = (char*)symbol.value();
  163. else if (m_image->isRelocatable())
  164. ptr = areaForSection(symbol.section()) + symbol.value();
  165. else
  166. ASSERT_NOT_REACHED();
  167. m_execSpace.addSymbol(symbol.name(), ptr, symbol.size());
  168. }
  169. // FIXME: What about other symbol types?
  170. return true;
  171. });
  172. }