Image.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. /*
  2. * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2022, the SerenityOS developers.
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <AK/BinarySearch.h>
  8. #include <AK/Debug.h>
  9. #include <AK/Demangle.h>
  10. #include <AK/QuickSort.h>
  11. #include <AK/StringBuilder.h>
  12. #include <AK/StringView.h>
  13. #include <Kernel/API/serenity_limits.h>
  14. #include <LibELF/Image.h>
  15. #include <LibELF/Validation.h>
  16. #ifdef KERNEL
  17. # include <Kernel/Library/StdLib.h>
  18. #else
  19. # include <string.h>
  20. #endif
  21. namespace ELF {
  22. Image::Image(ReadonlyBytes bytes, bool verbose_logging)
  23. : m_buffer(bytes.data())
  24. , m_size(bytes.size())
  25. , m_verbose_logging(verbose_logging)
  26. {
  27. parse();
  28. }
  29. Image::Image(u8 const* buffer, size_t size, bool verbose_logging)
  30. : Image(ReadonlyBytes { buffer, size }, verbose_logging)
  31. {
  32. }
  33. StringView Image::section_index_to_string(unsigned index) const
  34. {
  35. VERIFY(m_valid);
  36. if (index == SHN_UNDEF)
  37. return "Undefined"sv;
  38. if (index >= SHN_LORESERVE)
  39. return "Reserved"sv;
  40. return section(index).name();
  41. }
  42. unsigned Image::symbol_count() const
  43. {
  44. VERIFY(m_valid);
  45. if (!section_count())
  46. return 0;
  47. return section(m_symbol_table_section_index).entry_count();
  48. }
  49. void Image::dump() const
  50. {
  51. #if ELF_IMAGE_DEBUG
  52. dbgln("ELF::Image({:p}) {{", this);
  53. dbgln(" is_valid: {}", is_valid());
  54. if (!is_valid()) {
  55. dbgln("}}");
  56. return;
  57. }
  58. dbgln(" type: {}", ELF::Image::object_file_type_to_string(header().e_type).value_or("(?)"sv));
  59. dbgln(" machine: {}", header().e_machine);
  60. dbgln(" entry: {:x}", header().e_entry);
  61. dbgln(" shoff: {}", header().e_shoff);
  62. dbgln(" shnum: {}", header().e_shnum);
  63. dbgln(" phoff: {}", header().e_phoff);
  64. dbgln(" phnum: {}", header().e_phnum);
  65. dbgln(" shstrndx: {}", header().e_shstrndx);
  66. for_each_program_header([&](ProgramHeader const& program_header) {
  67. dbgln(" Program Header {}: {{", program_header.index());
  68. dbgln(" type: {:x}", program_header.type());
  69. dbgln(" offset: {:x}", program_header.offset());
  70. dbgln(" flags: {:x}", program_header.flags());
  71. dbgln(" }}");
  72. });
  73. for (unsigned i = 0; i < header().e_shnum; ++i) {
  74. auto const& section = this->section(i);
  75. dbgln(" Section {}: {{", i);
  76. dbgln(" name: {}", section.name());
  77. dbgln(" type: {:x}", section.type());
  78. dbgln(" offset: {:x}", section.offset());
  79. dbgln(" size: {}", section.size());
  80. dbgln(" ");
  81. dbgln(" }}");
  82. }
  83. dbgln("Symbol count: {} (table is {})", symbol_count(), m_symbol_table_section_index);
  84. for (unsigned i = 1; i < symbol_count(); ++i) {
  85. auto const& sym = symbol(i);
  86. dbgln("Symbol @{}:", i);
  87. dbgln(" Name: {}", sym.name());
  88. dbgln(" In section: {}", section_index_to_string(sym.section_index()));
  89. dbgln(" Value: {}", sym.value());
  90. dbgln(" Size: {}", sym.size());
  91. }
  92. dbgln("}}");
  93. #endif
  94. }
  95. unsigned Image::section_count() const
  96. {
  97. VERIFY(m_valid);
  98. return header().e_shnum;
  99. }
  100. unsigned Image::program_header_count() const
  101. {
  102. VERIFY(m_valid);
  103. return header().e_phnum;
  104. }
  105. bool Image::parse()
  106. {
  107. if (m_size < sizeof(ElfW(Ehdr)) || !validate_elf_header(header(), m_size, m_verbose_logging)) {
  108. if (m_verbose_logging)
  109. dbgln("ELF::Image::parse(): ELF Header not valid");
  110. m_valid = false;
  111. return false;
  112. }
  113. auto result_or_error = validate_program_headers(header(), m_size, { m_buffer, m_size }, nullptr, nullptr, m_verbose_logging);
  114. if (result_or_error.is_error()) {
  115. if (m_verbose_logging)
  116. dbgln("ELF::Image::parse(): Failed validating ELF Program Headers");
  117. m_valid = false;
  118. return false;
  119. }
  120. if (!result_or_error.value()) {
  121. if (m_verbose_logging)
  122. dbgln("ELF::Image::parse(): ELF Program Headers not valid");
  123. m_valid = false;
  124. return false;
  125. }
  126. m_valid = true;
  127. // First locate the string tables.
  128. for (unsigned i = 0; i < section_count(); ++i) {
  129. auto& sh = section_header(i);
  130. if (sh.sh_type == SHT_SYMTAB) {
  131. if (m_symbol_table_section_index && m_symbol_table_section_index != i) {
  132. m_valid = false;
  133. return false;
  134. }
  135. m_symbol_table_section_index = i;
  136. }
  137. if (sh.sh_type == SHT_STRTAB && i != header().e_shstrndx) {
  138. if (section_header_table_string(sh.sh_name) == ELF_STRTAB)
  139. m_string_table_section_index = i;
  140. }
  141. }
  142. return m_valid;
  143. }
  144. StringView Image::table_string(unsigned table_index, unsigned offset) const
  145. {
  146. VERIFY(m_valid);
  147. auto& sh = section_header(table_index);
  148. if (sh.sh_type != SHT_STRTAB)
  149. return {};
  150. size_t computed_offset = sh.sh_offset + offset;
  151. if (computed_offset >= m_size) {
  152. if (m_verbose_logging)
  153. dbgln("SHENANIGANS! Image::table_string() computed offset outside image.");
  154. return {};
  155. }
  156. size_t max_length = min(m_size - computed_offset, (size_t)PAGE_SIZE);
  157. size_t length = strnlen(raw_data(sh.sh_offset + offset), max_length);
  158. return { raw_data(sh.sh_offset + offset), length };
  159. }
  160. StringView Image::section_header_table_string(unsigned offset) const
  161. {
  162. VERIFY(m_valid);
  163. return table_string(header().e_shstrndx, offset);
  164. }
  165. StringView Image::table_string(unsigned offset) const
  166. {
  167. VERIFY(m_valid);
  168. return table_string(m_string_table_section_index, offset);
  169. }
  170. char const* Image::raw_data(unsigned offset) const
  171. {
  172. VERIFY(offset < m_size); // Callers must check indices into raw_data()'s result are also in bounds.
  173. return reinterpret_cast<char const*>(m_buffer) + offset;
  174. }
  175. const ElfW(Ehdr) & Image::header() const
  176. {
  177. VERIFY(m_size >= sizeof(ElfW(Ehdr)));
  178. return *reinterpret_cast<const ElfW(Ehdr)*>(raw_data(0));
  179. }
  180. const ElfW(Phdr) & Image::program_header_internal(unsigned index) const
  181. {
  182. VERIFY(m_valid);
  183. VERIFY(index < header().e_phnum);
  184. return *reinterpret_cast<const ElfW(Phdr)*>(raw_data(header().e_phoff + (index * sizeof(ElfW(Phdr)))));
  185. }
  186. const ElfW(Shdr) & Image::section_header(unsigned index) const
  187. {
  188. VERIFY(m_valid);
  189. VERIFY(index < header().e_shnum);
  190. return *reinterpret_cast<const ElfW(Shdr)*>(raw_data(header().e_shoff + (index * header().e_shentsize)));
  191. }
  192. Image::Symbol Image::symbol(unsigned index) const
  193. {
  194. VERIFY(m_valid);
  195. VERIFY(index < symbol_count());
  196. auto* raw_syms = reinterpret_cast<const ElfW(Sym)*>(raw_data(section(m_symbol_table_section_index).offset()));
  197. return Symbol(*this, index, raw_syms[index]);
  198. }
  199. Image::Section Image::section(unsigned index) const
  200. {
  201. VERIFY(m_valid);
  202. VERIFY(index < section_count());
  203. return Section(*this, index);
  204. }
  205. Image::ProgramHeader Image::program_header(unsigned index) const
  206. {
  207. VERIFY(m_valid);
  208. VERIFY(index < program_header_count());
  209. return ProgramHeader(*this, index);
  210. }
  211. Image::Relocation Image::RelocationSection::relocation(unsigned index) const
  212. {
  213. VERIFY(index < relocation_count());
  214. auto* rels = reinterpret_cast<const ElfW(Rel)*>(m_image.raw_data(offset()));
  215. return Relocation(m_image, rels[index]);
  216. }
  217. Optional<Image::RelocationSection> Image::Section::relocations() const
  218. {
  219. StringBuilder builder;
  220. builder.append(".rel"sv);
  221. builder.append(name());
  222. auto relocation_section = m_image.lookup_section(builder.string_view());
  223. if (!relocation_section.has_value())
  224. return {};
  225. dbgln_if(ELF_IMAGE_DEBUG, "Found relocations for {} in {}", name(), relocation_section.value().name());
  226. return static_cast<RelocationSection>(relocation_section.value());
  227. }
  228. Optional<Image::Section> Image::lookup_section(StringView name) const
  229. {
  230. VERIFY(m_valid);
  231. for (unsigned i = 0; i < section_count(); ++i) {
  232. auto section = this->section(i);
  233. if (section.name() == name)
  234. return section;
  235. }
  236. return {};
  237. }
  238. Optional<StringView> Image::object_file_type_to_string(ElfW(Half) type)
  239. {
  240. switch (type) {
  241. case ET_NONE:
  242. return "None"sv;
  243. case ET_REL:
  244. return "Relocatable"sv;
  245. case ET_EXEC:
  246. return "Executable"sv;
  247. case ET_DYN:
  248. return "Shared object"sv;
  249. case ET_CORE:
  250. return "Core"sv;
  251. default:
  252. return {};
  253. }
  254. }
  255. Optional<StringView> Image::object_machine_type_to_string(ElfW(Half) type)
  256. {
  257. switch (type) {
  258. case ET_NONE:
  259. return "None"sv;
  260. case EM_M32:
  261. return "AT&T WE 32100"sv;
  262. case EM_SPARC:
  263. return "SPARC"sv;
  264. case EM_386:
  265. return "Intel 80386"sv;
  266. case EM_68K:
  267. return "Motorola 68000"sv;
  268. case EM_88K:
  269. return "Motorola 88000"sv;
  270. case EM_486:
  271. return "Intel 80486"sv;
  272. case EM_860:
  273. return "Intel 80860"sv;
  274. case EM_MIPS:
  275. return "MIPS R3000 Big-Endian only"sv;
  276. case EM_X86_64:
  277. return "x86_64"sv;
  278. default:
  279. return {};
  280. }
  281. }
  282. Optional<StringView> Image::object_abi_type_to_string(Elf_Byte type)
  283. {
  284. switch (type) {
  285. case ELFOSABI_SYSV:
  286. return "SYSV"sv;
  287. case ELFOSABI_HPUX:
  288. return "HP-UX"sv;
  289. case ELFOSABI_NETBSD:
  290. return "NetBSD"sv;
  291. case ELFOSABI_LINUX:
  292. return "Linux"sv;
  293. case ELFOSABI_HURD:
  294. return "GNU Hurd"sv;
  295. case ELFOSABI_86OPEN:
  296. return "86Open"sv;
  297. case ELFOSABI_SOLARIS:
  298. return "Solaris"sv;
  299. case ELFOSABI_MONTEREY:
  300. return "AIX"sv;
  301. case ELFOSABI_IRIX:
  302. return "IRIX"sv;
  303. case ELFOSABI_FREEBSD:
  304. return "FreeBSD"sv;
  305. case ELFOSABI_TRU64:
  306. return "Tru64"sv;
  307. case ELFOSABI_MODESTO:
  308. return "Novell Modesto"sv;
  309. case ELFOSABI_OPENBSD:
  310. return "OpenBSD"sv;
  311. case ELFOSABI_ARM:
  312. return "ARM"sv;
  313. case ELFOSABI_STANDALONE:
  314. return "Standalone"sv;
  315. default:
  316. return {};
  317. }
  318. }
  319. StringView Image::Symbol::raw_data() const
  320. {
  321. auto section = this->section();
  322. return { section.raw_data() + (value() - section.address()), size() };
  323. }
  324. #ifndef KERNEL
  325. Optional<Image::Symbol> Image::find_demangled_function(StringView name) const
  326. {
  327. Optional<Image::Symbol> found;
  328. for_each_symbol([&](Image::Symbol const& symbol) {
  329. if (symbol.type() != STT_FUNC && symbol.type() != STT_GNU_IFUNC)
  330. return IterationDecision::Continue;
  331. if (symbol.is_undefined())
  332. return IterationDecision::Continue;
  333. auto demangled = demangle(symbol.name());
  334. auto index_of_paren = demangled.find('(');
  335. if (index_of_paren.has_value()) {
  336. demangled = demangled.substring(0, index_of_paren.value());
  337. }
  338. if (demangled != name)
  339. return IterationDecision::Continue;
  340. found = symbol;
  341. return IterationDecision::Break;
  342. });
  343. return found;
  344. }
  345. Image::SortedSymbol* Image::find_sorted_symbol(FlatPtr address) const
  346. {
  347. if (m_sorted_symbols.is_empty())
  348. sort_symbols();
  349. size_t index = 0;
  350. binary_search(m_sorted_symbols, nullptr, &index, [&address](auto, auto& candidate) {
  351. if (address < candidate.address)
  352. return -1;
  353. else if (address > candidate.address)
  354. return 1;
  355. else
  356. return 0;
  357. });
  358. // FIXME: The error path here feels strange, index == 0 means error but what about symbol #0?
  359. if (index == 0)
  360. return nullptr;
  361. return &m_sorted_symbols[index];
  362. }
  363. Optional<Image::Symbol> Image::find_symbol(FlatPtr address, u32* out_offset) const
  364. {
  365. auto symbol_count = this->symbol_count();
  366. if (!symbol_count)
  367. return {};
  368. auto* symbol = find_sorted_symbol(address);
  369. if (!symbol)
  370. return {};
  371. if (out_offset)
  372. *out_offset = address - symbol->address;
  373. return symbol->symbol;
  374. }
  375. NEVER_INLINE void Image::sort_symbols() const
  376. {
  377. m_sorted_symbols.ensure_capacity(symbol_count());
  378. bool const is_aarch64 = header().e_machine == EM_AARCH64;
  379. for_each_symbol([this, is_aarch64](auto const& symbol) {
  380. // The AArch64 ABI marks the boundaries of literal pools in a function with $x/$d.
  381. // https://github.com/ARM-software/abi-aa/blob/2023q1-release/aaelf64/aaelf64.rst#mapping-symbols
  382. // Skip them so we don't accidentally print these instead of function names.
  383. if (is_aarch64 && (symbol.name().starts_with("$x"sv) || symbol.name().starts_with("$d"sv)))
  384. return;
  385. // STT_SECTION has the same address as the first function in the section, but shows up as the empty string.
  386. if (symbol.type() == STT_SECTION)
  387. return;
  388. m_sorted_symbols.append({ symbol.value(), symbol.name(), {}, symbol });
  389. });
  390. quick_sort(m_sorted_symbols, [](auto& a, auto& b) {
  391. return a.address < b.address;
  392. });
  393. }
  394. DeprecatedString Image::symbolicate(FlatPtr address, u32* out_offset) const
  395. {
  396. auto symbol_count = this->symbol_count();
  397. if (!symbol_count) {
  398. if (out_offset)
  399. *out_offset = 0;
  400. return "??";
  401. }
  402. auto* symbol = find_sorted_symbol(address);
  403. if (!symbol) {
  404. if (out_offset)
  405. *out_offset = 0;
  406. return "??";
  407. }
  408. auto& demangled_name = symbol->demangled_name;
  409. if (demangled_name.is_empty())
  410. demangled_name = demangle(symbol->name);
  411. if (out_offset) {
  412. *out_offset = address - symbol->address;
  413. return demangled_name;
  414. }
  415. return DeprecatedString::formatted("{} +{:#x}", demangled_name, address - symbol->address);
  416. }
  417. #endif
  418. } // end namespace ELF