Image.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Concepts.h>
  8. #include <AK/String.h>
  9. #include <AK/Vector.h>
  10. #include <Kernel/VirtualAddress.h>
  11. #include <LibC/elf.h>
  12. namespace ELF {
  13. class Image {
  14. public:
  15. explicit Image(ReadonlyBytes, bool verbose_logging = true);
  16. explicit Image(const u8*, size_t, bool verbose_logging = true);
  17. ~Image();
  18. void dump() const;
  19. bool is_valid() const { return m_valid; }
  20. bool parse();
  21. bool is_within_image(const void* address, size_t size) const
  22. {
  23. if (address < m_buffer)
  24. return false;
  25. if (((const u8*)address + size) > m_buffer + m_size)
  26. return false;
  27. return true;
  28. }
  29. class Section;
  30. class RelocationSection;
  31. class Symbol;
  32. class Relocation;
  33. class Symbol {
  34. public:
  35. Symbol(const Image& image, unsigned index, const ElfW(Sym) & sym)
  36. : m_image(image)
  37. , m_sym(sym)
  38. , m_index(index)
  39. {
  40. }
  41. ~Symbol() { }
  42. StringView name() const { return m_image.table_string(m_sym.st_name); }
  43. unsigned section_index() const { return m_sym.st_shndx; }
  44. unsigned value() const { return m_sym.st_value; }
  45. unsigned size() const { return m_sym.st_size; }
  46. unsigned index() const { return m_index; }
  47. #if ARCH(I386)
  48. unsigned type() const
  49. {
  50. return ELF32_ST_TYPE(m_sym.st_info);
  51. }
  52. unsigned bind() const { return ELF32_ST_BIND(m_sym.st_info); }
  53. #else
  54. unsigned type() const
  55. {
  56. return ELF64_ST_TYPE(m_sym.st_info);
  57. }
  58. unsigned bind() const { return ELF64_ST_BIND(m_sym.st_info); }
  59. #endif
  60. Section section() const
  61. {
  62. return m_image.section(section_index());
  63. }
  64. bool is_undefined() const { return section_index() == 0; }
  65. StringView raw_data() const;
  66. private:
  67. const Image& m_image;
  68. const ElfW(Sym) & m_sym;
  69. const unsigned m_index;
  70. };
  71. class ProgramHeader {
  72. public:
  73. ProgramHeader(const Image& image, unsigned program_header_index)
  74. : m_image(image)
  75. , m_program_header(image.program_header_internal(program_header_index))
  76. , m_program_header_index(program_header_index)
  77. {
  78. }
  79. ~ProgramHeader() { }
  80. unsigned index() const { return m_program_header_index; }
  81. u32 type() const { return m_program_header.p_type; }
  82. u32 flags() const { return m_program_header.p_flags; }
  83. u32 offset() const { return m_program_header.p_offset; }
  84. VirtualAddress vaddr() const { return VirtualAddress(m_program_header.p_vaddr); }
  85. u32 size_in_memory() const { return m_program_header.p_memsz; }
  86. u32 size_in_image() const { return m_program_header.p_filesz; }
  87. u32 alignment() const { return m_program_header.p_align; }
  88. bool is_readable() const { return flags() & PF_R; }
  89. bool is_writable() const { return flags() & PF_W; }
  90. bool is_executable() const { return flags() & PF_X; }
  91. const char* raw_data() const { return m_image.raw_data(m_program_header.p_offset); }
  92. ElfW(Phdr) raw_header() const { return m_program_header; }
  93. private:
  94. const Image& m_image;
  95. const ElfW(Phdr) & m_program_header;
  96. unsigned m_program_header_index { 0 };
  97. };
  98. class Section {
  99. public:
  100. Section(const Image& image, unsigned sectionIndex)
  101. : m_image(image)
  102. , m_section_header(image.section_header(sectionIndex))
  103. , m_section_index(sectionIndex)
  104. {
  105. }
  106. ~Section() { }
  107. StringView name() const { return m_image.section_header_table_string(m_section_header.sh_name); }
  108. unsigned type() const { return m_section_header.sh_type; }
  109. unsigned offset() const { return m_section_header.sh_offset; }
  110. unsigned size() const { return m_section_header.sh_size; }
  111. unsigned entry_size() const { return m_section_header.sh_entsize; }
  112. unsigned entry_count() const { return !entry_size() ? 0 : size() / entry_size(); }
  113. u32 address() const { return m_section_header.sh_addr; }
  114. const char* raw_data() const { return m_image.raw_data(m_section_header.sh_offset); }
  115. ReadonlyBytes bytes() const { return { raw_data(), size() }; }
  116. Optional<RelocationSection> relocations() const;
  117. u32 flags() const { return m_section_header.sh_flags; }
  118. bool is_writable() const { return flags() & SHF_WRITE; }
  119. bool is_executable() const { return flags() & PF_X; }
  120. protected:
  121. friend class RelocationSection;
  122. const Image& m_image;
  123. const ElfW(Shdr) & m_section_header;
  124. unsigned m_section_index;
  125. };
  126. class RelocationSection : public Section {
  127. public:
  128. explicit RelocationSection(const Section& section)
  129. : Section(section.m_image, section.m_section_index)
  130. {
  131. }
  132. unsigned relocation_count() const { return entry_count(); }
  133. Relocation relocation(unsigned index) const;
  134. template<VoidFunction<Image::Relocation&> F>
  135. void for_each_relocation(F) const;
  136. };
  137. class Relocation {
  138. public:
  139. Relocation(const Image& image, const ElfW(Rel) & rel)
  140. : m_image(image)
  141. , m_rel(rel)
  142. {
  143. }
  144. ~Relocation() { }
  145. unsigned offset() const { return m_rel.r_offset; }
  146. #if ARCH(I386)
  147. unsigned type() const
  148. {
  149. return ELF32_R_TYPE(m_rel.r_info);
  150. }
  151. unsigned symbol_index() const { return ELF32_R_SYM(m_rel.r_info); }
  152. #else
  153. unsigned type() const
  154. {
  155. return ELF64_R_TYPE(m_rel.r_info);
  156. }
  157. unsigned symbol_index() const { return ELF64_R_SYM(m_rel.r_info); }
  158. #endif
  159. Symbol symbol() const
  160. {
  161. return m_image.symbol(symbol_index());
  162. }
  163. private:
  164. const Image& m_image;
  165. const ElfW(Rel) & m_rel;
  166. };
  167. unsigned symbol_count() const;
  168. unsigned section_count() const;
  169. unsigned program_header_count() const;
  170. Symbol symbol(unsigned) const;
  171. Section section(unsigned) const;
  172. ProgramHeader program_header(unsigned) const;
  173. FlatPtr program_header_table_offset() const;
  174. template<IteratorFunction<Image::Section> F>
  175. void for_each_section(F) const;
  176. template<VoidFunction<Section> F>
  177. void for_each_section(F) const;
  178. template<IteratorFunction<Section&> F>
  179. void for_each_section_of_type(unsigned, F) const;
  180. template<VoidFunction<Section&> F>
  181. void for_each_section_of_type(unsigned, F) const;
  182. template<IteratorFunction<Symbol> F>
  183. void for_each_symbol(F) const;
  184. template<VoidFunction<Symbol> F>
  185. void for_each_symbol(F) const;
  186. template<IteratorFunction<ProgramHeader> F>
  187. void for_each_program_header(F func) const;
  188. template<VoidFunction<ProgramHeader> F>
  189. void for_each_program_header(F) const;
  190. Optional<Section> lookup_section(StringView const& name) const;
  191. bool is_executable() const { return header().e_type == ET_EXEC; }
  192. bool is_relocatable() const { return header().e_type == ET_REL; }
  193. bool is_dynamic() const { return header().e_type == ET_DYN; }
  194. VirtualAddress entry() const { return VirtualAddress(header().e_entry); }
  195. FlatPtr base_address() const { return (FlatPtr)m_buffer; }
  196. size_t size() const { return m_size; }
  197. bool has_symbols() const { return symbol_count(); }
  198. #ifndef KERNEL
  199. Optional<Symbol> find_demangled_function(const StringView& name) const;
  200. String symbolicate(u32 address, u32* offset = nullptr) const;
  201. #endif
  202. Optional<Image::Symbol> find_symbol(u32 address, u32* offset = nullptr) const;
  203. private:
  204. const char* raw_data(unsigned offset) const;
  205. const ElfW(Ehdr) & header() const;
  206. const ElfW(Shdr) & section_header(unsigned) const;
  207. const ElfW(Phdr) & program_header_internal(unsigned) const;
  208. StringView table_string(unsigned offset) const;
  209. StringView section_header_table_string(unsigned offset) const;
  210. StringView section_index_to_string(unsigned index) const;
  211. StringView table_string(unsigned table_index, unsigned offset) const;
  212. const u8* m_buffer { nullptr };
  213. size_t m_size { 0 };
  214. bool m_verbose_logging { true };
  215. bool m_valid { false };
  216. unsigned m_symbol_table_section_index { 0 };
  217. unsigned m_string_table_section_index { 0 };
  218. struct SortedSymbol {
  219. u32 address;
  220. StringView name;
  221. String demangled_name;
  222. Optional<Image::Symbol> symbol;
  223. };
  224. void sort_symbols() const;
  225. SortedSymbol* find_sorted_symbol(FlatPtr) const;
  226. mutable Vector<SortedSymbol> m_sorted_symbols;
  227. };
  228. template<IteratorFunction<Image::Section> F>
  229. inline void Image::for_each_section(F func) const
  230. {
  231. auto section_count = this->section_count();
  232. for (unsigned i = 0; i < section_count; ++i) {
  233. if (func(section(i)) == IterationDecision::Break)
  234. break;
  235. }
  236. }
  237. template<VoidFunction<Image::Section> F>
  238. inline void Image::for_each_section(F func) const
  239. {
  240. for_each_section([&](auto section) {
  241. func(move(section));
  242. return IterationDecision::Continue;
  243. });
  244. }
  245. template<IteratorFunction<Image::Section&> F>
  246. inline void Image::for_each_section_of_type(unsigned type, F func) const
  247. {
  248. auto section_count = this->section_count();
  249. for (unsigned i = 0; i < section_count; ++i) {
  250. auto section = this->section(i);
  251. if (section.type() == type) {
  252. if (func(section) == IterationDecision::Break)
  253. break;
  254. }
  255. }
  256. }
  257. template<VoidFunction<Image::Section&> F>
  258. inline void Image::for_each_section_of_type(unsigned type, F func) const
  259. {
  260. for_each_section_of_type(type, [&](auto& section) {
  261. func(section);
  262. return IterationDecision::Continue;
  263. });
  264. }
  265. template<VoidFunction<Image::Relocation&> F>
  266. inline void Image::RelocationSection::for_each_relocation(F func) const
  267. {
  268. auto relocation_count = this->relocation_count();
  269. for (unsigned i = 0; i < relocation_count; ++i) {
  270. func(relocation(i));
  271. }
  272. }
  273. template<IteratorFunction<Image::Symbol> F>
  274. inline void Image::for_each_symbol(F func) const
  275. {
  276. auto symbol_count = this->symbol_count();
  277. for (unsigned i = 0; i < symbol_count; ++i) {
  278. if (func(symbol(i)) == IterationDecision::Break)
  279. break;
  280. }
  281. }
  282. template<VoidFunction<Image::Symbol> F>
  283. inline void Image::for_each_symbol(F func) const
  284. {
  285. for_each_symbol([&](auto symbol) {
  286. func(move(symbol));
  287. return IterationDecision::Continue;
  288. });
  289. }
  290. template<IteratorFunction<Image::ProgramHeader> F>
  291. inline void Image::for_each_program_header(F func) const
  292. {
  293. auto program_header_count = this->program_header_count();
  294. for (unsigned i = 0; i < program_header_count; ++i) {
  295. if (func(program_header(i)) == IterationDecision::Break)
  296. break;
  297. }
  298. }
  299. template<VoidFunction<Image::ProgramHeader> F>
  300. inline void Image::for_each_program_header(F func) const
  301. {
  302. for_each_program_header([&](auto header) {
  303. func(move(header));
  304. return IterationDecision::Continue;
  305. });
  306. }
  307. } // end namespace ELF