Image.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice, this
  9. * list of conditions and the following disclaimer.
  10. *
  11. * 2. Redistributions in binary form must reproduce the above copyright notice,
  12. * this list of conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  19. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  21. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  22. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  23. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  24. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include <AK/Memory.h>
  27. #include <AK/StringBuilder.h>
  28. #include <AK/StringView.h>
  29. #include <LibELF/Image.h>
  30. #include <LibELF/Validation.h>
  31. namespace ELF {
  32. Image::Image(const u8* buffer, size_t size, bool verbose_logging)
  33. : m_buffer(buffer)
  34. , m_size(size)
  35. , m_verbose_logging(verbose_logging)
  36. {
  37. parse();
  38. }
  39. Image::~Image()
  40. {
  41. }
  42. static const char* object_file_type_to_string(Elf32_Half type)
  43. {
  44. switch (type) {
  45. case ET_NONE:
  46. return "None";
  47. case ET_REL:
  48. return "Relocatable";
  49. case ET_EXEC:
  50. return "Executable";
  51. case ET_DYN:
  52. return "Shared object";
  53. case ET_CORE:
  54. return "Core";
  55. default:
  56. return "(?)";
  57. }
  58. }
  59. StringView Image::section_index_to_string(unsigned index) const
  60. {
  61. ASSERT(m_valid);
  62. if (index == SHN_UNDEF)
  63. return "Undefined";
  64. if (index >= SHN_LORESERVE)
  65. return "Reserved";
  66. return section(index).name();
  67. }
  68. unsigned Image::symbol_count() const
  69. {
  70. ASSERT(m_valid);
  71. return section(m_symbol_table_section_index).entry_count();
  72. }
  73. void Image::dump() const
  74. {
  75. dbgprintf("Image{%p} {\n", this);
  76. dbgprintf(" is_valid: %u\n", is_valid());
  77. if (!is_valid()) {
  78. dbgprintf("}\n");
  79. return;
  80. }
  81. dbgprintf(" type: %s\n", object_file_type_to_string(header().e_type));
  82. dbgprintf(" machine: %u\n", header().e_machine);
  83. dbgprintf(" entry: %x\n", header().e_entry);
  84. dbgprintf(" shoff: %u\n", header().e_shoff);
  85. dbgprintf(" shnum: %u\n", header().e_shnum);
  86. dbgprintf(" phoff: %u\n", header().e_phoff);
  87. dbgprintf(" phnum: %u\n", header().e_phnum);
  88. dbgprintf(" shstrndx: %u\n", header().e_shstrndx);
  89. for_each_program_header([&](const ProgramHeader& program_header) {
  90. dbgprintf(" Program Header %d: {\n", program_header.index());
  91. dbgprintf(" type: %x\n", program_header.type());
  92. dbgprintf(" offset: %x\n", program_header.offset());
  93. dbgprintf(" flags: %x\n", program_header.flags());
  94. dbgprintf(" \n");
  95. dbgprintf(" }\n");
  96. });
  97. for (unsigned i = 0; i < header().e_shnum; ++i) {
  98. auto& section = this->section(i);
  99. dbgprintf(" Section %u: {\n", i);
  100. dbgprintf(" name: %.*s\n", (int)section.name().length(), section.name().characters_without_null_termination());
  101. dbgprintf(" type: %x\n", section.type());
  102. dbgprintf(" offset: %x\n", section.offset());
  103. dbgprintf(" size: %u\n", section.size());
  104. dbgprintf(" \n");
  105. dbgprintf(" }\n");
  106. }
  107. dbgprintf("Symbol count: %u (table is %u)\n", symbol_count(), m_symbol_table_section_index);
  108. for (unsigned i = 1; i < symbol_count(); ++i) {
  109. auto& sym = symbol(i);
  110. dbgprintf("Symbol @%u:\n", i);
  111. dbgprintf(" Name: %.*s\n", (int)sym.name().length(), sym.name().characters_without_null_termination());
  112. StringView section_index_string = section_index_to_string(sym.section_index());
  113. dbgprintf(" In section: %.*s\n", (int)section_index_string.length(), section_index_string.characters_without_null_termination());
  114. dbgprintf(" Value: %x\n", sym.value());
  115. dbgprintf(" Size: %u\n", sym.size());
  116. }
  117. dbgprintf("}\n");
  118. }
  119. unsigned Image::section_count() const
  120. {
  121. ASSERT(m_valid);
  122. return header().e_shnum;
  123. }
  124. unsigned Image::program_header_count() const
  125. {
  126. ASSERT(m_valid);
  127. return header().e_phnum;
  128. }
  129. bool Image::parse()
  130. {
  131. if (m_size < sizeof(Elf32_Ehdr) || !validate_elf_header(header(), m_size, m_verbose_logging)) {
  132. if (m_verbose_logging)
  133. dbgputstr("Image::parse(): ELF Header not valid\n");
  134. return m_valid = false;
  135. }
  136. m_valid = true;
  137. // First locate the string tables.
  138. for (unsigned i = 0; i < section_count(); ++i) {
  139. auto& sh = section_header(i);
  140. if (sh.sh_type == SHT_SYMTAB) {
  141. if (m_symbol_table_section_index && m_symbol_table_section_index != i)
  142. return m_valid = false;
  143. m_symbol_table_section_index = i;
  144. }
  145. if (sh.sh_type == SHT_STRTAB && i != header().e_shstrndx) {
  146. if (section_header_table_string(sh.sh_name) == ELF_STRTAB)
  147. m_string_table_section_index = i;
  148. }
  149. }
  150. // Then create a name-to-index map.
  151. for (unsigned i = 0; i < section_count(); ++i) {
  152. auto& section = this->section(i);
  153. m_sections.set(section.name(), move(i));
  154. }
  155. return m_valid;
  156. }
  157. StringView Image::table_string(unsigned table_index, unsigned offset) const
  158. {
  159. ASSERT(m_valid);
  160. auto& sh = section_header(table_index);
  161. if (sh.sh_type != SHT_STRTAB)
  162. return nullptr;
  163. size_t computed_offset = sh.sh_offset + offset;
  164. if (computed_offset >= m_size) {
  165. if (m_verbose_logging)
  166. dbgprintf("SHENANIGANS! Image::table_string() computed offset outside image.\n");
  167. return {};
  168. }
  169. size_t max_length = m_size - computed_offset;
  170. size_t length = strnlen(raw_data(sh.sh_offset + offset), max_length);
  171. return { raw_data(sh.sh_offset + offset), length };
  172. }
  173. StringView Image::section_header_table_string(unsigned offset) const
  174. {
  175. ASSERT(m_valid);
  176. return table_string(header().e_shstrndx, offset);
  177. }
  178. StringView Image::table_string(unsigned offset) const
  179. {
  180. ASSERT(m_valid);
  181. return table_string(m_string_table_section_index, offset);
  182. }
  183. const char* Image::raw_data(unsigned offset) const
  184. {
  185. ASSERT(offset < m_size); // Callers must check indices into raw_data()'s result are also in bounds.
  186. return reinterpret_cast<const char*>(m_buffer) + offset;
  187. }
  188. const Elf32_Ehdr& Image::header() const
  189. {
  190. ASSERT(m_size >= sizeof(Elf32_Ehdr));
  191. return *reinterpret_cast<const Elf32_Ehdr*>(raw_data(0));
  192. }
  193. const Elf32_Phdr& Image::program_header_internal(unsigned index) const
  194. {
  195. ASSERT(m_valid);
  196. ASSERT(index < header().e_phnum);
  197. return *reinterpret_cast<const Elf32_Phdr*>(raw_data(header().e_phoff + (index * sizeof(Elf32_Phdr))));
  198. }
  199. const Elf32_Shdr& Image::section_header(unsigned index) const
  200. {
  201. ASSERT(m_valid);
  202. ASSERT(index < header().e_shnum);
  203. return *reinterpret_cast<const Elf32_Shdr*>(raw_data(header().e_shoff + (index * header().e_shentsize)));
  204. }
  205. const Image::Symbol Image::symbol(unsigned index) const
  206. {
  207. ASSERT(m_valid);
  208. ASSERT(index < symbol_count());
  209. auto* raw_syms = reinterpret_cast<const Elf32_Sym*>(raw_data(section(m_symbol_table_section_index).offset()));
  210. return Symbol(*this, index, raw_syms[index]);
  211. }
  212. const Image::Section Image::section(unsigned index) const
  213. {
  214. ASSERT(m_valid);
  215. ASSERT(index < section_count());
  216. return Section(*this, index);
  217. }
  218. const Image::ProgramHeader Image::program_header(unsigned index) const
  219. {
  220. ASSERT(m_valid);
  221. ASSERT(index < program_header_count());
  222. return ProgramHeader(*this, index);
  223. }
  224. const Image::Relocation Image::RelocationSection::relocation(unsigned index) const
  225. {
  226. ASSERT(index < relocation_count());
  227. auto* rels = reinterpret_cast<const Elf32_Rel*>(m_image.raw_data(offset()));
  228. return Relocation(m_image, rels[index]);
  229. }
  230. const Image::RelocationSection Image::Section::relocations() const
  231. {
  232. StringBuilder builder;
  233. builder.append(".rel");
  234. builder.append(name());
  235. auto relocation_section = m_image.lookup_section(builder.to_string());
  236. if (relocation_section.type() != SHT_REL)
  237. return static_cast<const RelocationSection>(m_image.section(0));
  238. #ifdef Image_DEBUG
  239. dbgprintf("Found relocations for %s in %s\n", name(), relocation_section.name());
  240. #endif
  241. return static_cast<const RelocationSection>(relocation_section);
  242. }
  243. const Image::Section Image::lookup_section(const String& name) const
  244. {
  245. ASSERT(m_valid);
  246. if (auto it = m_sections.find(name); it != m_sections.end())
  247. return section((*it).value);
  248. return section(0);
  249. }
  250. StringView Image::Symbol::raw_data() const
  251. {
  252. auto& section = this->section();
  253. return { section.raw_data() + (value() - section.address()), size() };
  254. }
  255. } // end namespace ELF