elf64_interpreter.hpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. #pragma once
  2. #include <stddef.h>
  3. #include <stdint.h>
  4. #include <elf.h>
  5. #include <map>
  6. #include <string>
  7. #include <optional>
  8. #include "exception.hpp"
  9. #include "memory_utility.hpp"
  10. namespace nkg {
  11. class elf64_interpreter {
  12. public:
  13. using fo_t = uintptr_t;
  14. using rva_t = uintptr_t;
  15. using va_t = uintptr_t;
  16. class parse_error : public ::nkg::exception {
  17. public:
  18. parse_error(std::string_view file, int line, std::string_view message) noexcept :
  19. ::nkg::exception(file, line, message) {}
  20. };
  21. class bad_fo_exception : public ::nkg::exception {
  22. public:
  23. bad_fo_exception(std::string_view file, int line, std::string_view message) noexcept :
  24. ::nkg::exception(file, line, message) {}
  25. };
  26. class bad_va_exception : public ::nkg::exception {
  27. public:
  28. bad_va_exception(std::string_view file, int line, std::string_view message) noexcept :
  29. ::nkg::exception(file, line, message) {}
  30. };
  31. private:
  32. size_t m_elf_size;
  33. Elf64_Ehdr* m_elf_header;
  34. Elf64_Phdr* m_elf_program_headers;
  35. Elf64_Shdr* m_elf_section_headers;
  36. std::map<Elf64_Addr, Elf64_Phdr*> m_segment_va_lookup_table;
  37. std::map<Elf64_Off, Elf64_Phdr*> m_segment_fo_lookup_table;
  38. std::map<Elf64_Addr, Elf64_Shdr*> m_section_va_lookup_table;
  39. std::map<Elf64_Off, Elf64_Shdr*> m_section_fo_lookup_table;
  40. std::map<std::string_view, Elf64_Shdr*> m_section_name_lookup_table;
  41. Elf64_Dyn* m_dynamic_rela;
  42. Elf64_Dyn* m_dynamic_relasz;
  43. Elf64_Dyn* m_dynamic_rel;
  44. Elf64_Dyn* m_dynamic_relsz;
  45. Elf64_Dyn* m_dynamic_pltgot;
  46. Elf64_Dyn* m_dynamic_jmprel;
  47. Elf64_Dyn* m_dynamic_pltrel;
  48. Elf64_Dyn* m_dynamic_pltrelsz;
  49. Elf64_Dyn* m_dynamic_symtab;
  50. Elf64_Dyn* m_dynamic_strtab;
  51. std::map<va_t, size_t> m_relocation_distribute;
  52. elf64_interpreter();
  53. public:
  54. [[nodiscard]]
  55. static elf64_interpreter parse(void* image_ptr, size_t image_size);
  56. [[nodiscard]]
  57. size_t elf_size() const noexcept;
  58. template<typename return_t = void*>
  59. [[nodiscard]]
  60. return_t elf_base() const noexcept {
  61. static_assert(std::is_pointer_v<return_t>);
  62. return reinterpret_cast<return_t>(m_elf_header);
  63. }
  64. template<typename return_t = void*>
  65. [[nodiscard]]
  66. return_t elf_offset(fo_t offset) const noexcept {
  67. static_assert(std::is_pointer_v<return_t>);
  68. return address_offset_cast<return_t>(m_elf_header, offset);
  69. }
  70. [[nodiscard]]
  71. Elf64_Ehdr* elf_header() const noexcept;
  72. [[nodiscard]]
  73. Elf64_Phdr* elf_program_header(size_t n) const;
  74. [[nodiscard]]
  75. Elf64_Phdr* elf_program_header_from_fo(fo_t file_offset) const;
  76. [[nodiscard]]
  77. Elf64_Phdr* elf_program_header_from_rva(rva_t rva) const;
  78. [[nodiscard]]
  79. Elf64_Phdr* elf_program_header_from_va(va_t va) const;
  80. [[nodiscard]]
  81. size_t elf_program_headers_num() const noexcept;
  82. [[nodiscard]]
  83. Elf64_Shdr* elf_section_header(size_t n) const;
  84. [[nodiscard]]
  85. Elf64_Shdr* elf_section_header(std::string_view section_name) const;
  86. [[nodiscard]]
  87. size_t elf_section_headers_num() const noexcept;
  88. template<typename return_t = void*>
  89. [[nodiscard]]
  90. return_t elf_section_view(size_t n, fo_t offset = 0) const {
  91. return elf_offset<return_t>(elf_section_header(n)->sh_offset + offset);
  92. }
  93. template<typename return_t = void*>
  94. [[nodiscard]]
  95. return_t elf_section_view(std::string_view section_name, fo_t offset = 0) const {
  96. return elf_offset<return_t>(elf_section_header(section_name)->sh_offset + offset);
  97. }
  98. template<typename ptr_t>
  99. [[nodiscard]]
  100. fo_t convert_ptr_to_fo(ptr_t ptr) const {
  101. return address_delta(ptr, m_elf_header);
  102. }
  103. [[nodiscard]]
  104. fo_t convert_rva_to_fo(rva_t rva) const;
  105. [[nodiscard]]
  106. fo_t convert_va_to_fo(va_t va) const;
  107. [[nodiscard]]
  108. rva_t convert_fo_to_rva(fo_t file_offset) const;
  109. template<typename ptr_t>
  110. [[nodiscard]]
  111. rva_t convert_ptr_to_rva(ptr_t ptr) const {
  112. return convert_fo_to_rva(convert_ptr_to_fo(ptr));
  113. }
  114. rva_t convert_va_to_rva(va_t va) const;
  115. [[nodiscard]]
  116. va_t convert_fo_to_va(fo_t file_offset) const;
  117. [[nodiscard]]
  118. va_t convert_rva_to_va(rva_t rva) const;
  119. template<typename ptr_t>
  120. va_t convert_ptr_to_va(ptr_t ptr) const {
  121. return convert_fo_to_va(convert_ptr_to_fo(ptr));
  122. }
  123. template<typename ptr_t = void*>
  124. [[nodiscard]]
  125. ptr_t convert_fo_to_ptr(fo_t offset) const {
  126. return elf_offset<ptr_t>(offset);
  127. }
  128. template<typename ptr_t = void*>
  129. [[nodiscard]]
  130. ptr_t convert_rva_to_ptr(rva_t rva) const {
  131. return convert_fo_to_ptr<ptr_t>(convert_rva_to_fo(rva));
  132. }
  133. template<typename ptr_t = void*>
  134. [[nodiscard]]
  135. ptr_t convert_va_to_ptr(va_t va) const {
  136. return convert_fo_to_ptr<ptr_t>(convert_va_to_fo(va));
  137. }
  138. template<typename return_t = void*, typename callable_t>
  139. [[nodiscard]]
  140. return_t search_section(size_t n, callable_t&& pred_func) const noexcept {
  141. auto sect_hdr = elf_section_header(n);
  142. auto sect_view = elf_offset<uint8_t*>(sect_hdr->sh_offset);
  143. for (size_t i = 0; i < sect_hdr->sh_size; ++i) {
  144. if (pred_func(sect_view, i, sect_hdr->sh_size)) {
  145. return reinterpret_cast<return_t>(sect_view + i);
  146. }
  147. }
  148. return nullptr;
  149. }
  150. template<typename return_t = void*, typename callable_t>
  151. [[nodiscard]]
  152. return_t search_section(std::string_view section_name, callable_t&& pred_func) const noexcept {
  153. auto sect_hdr = elf_section_header(section_name);
  154. auto sect_view = elf_offset<uint8_t*>(sect_hdr->sh_offset);
  155. for (size_t i = 0; i < sect_hdr->sh_size; ++i) {
  156. if (pred_func(sect_view, i, sect_hdr->sh_size)) {
  157. return reinterpret_cast<return_t>(sect_view + i);
  158. }
  159. }
  160. return nullptr;
  161. }
  162. [[nodiscard]]
  163. std::optional<va_t> elf_dynamic_rela() const;
  164. [[nodiscard]]
  165. std::optional<size_t> elf_dynamic_relasz() const;
  166. [[nodiscard]]
  167. std::optional<va_t> elf_dynamic_rel() const;
  168. [[nodiscard]]
  169. std::optional<size_t> elf_dynamic_relsz() const;
  170. [[nodiscard]]
  171. std::optional<va_t> elf_dynamic_pltgot() const;
  172. [[nodiscard]]
  173. std::optional<va_t> elf_dynamic_jmprel() const;
  174. [[nodiscard]]
  175. std::optional<int> elf_dynamic_pltrel() const;
  176. [[nodiscard]]
  177. std::optional<size_t> elf_dynamic_pltrelsz() const;
  178. [[nodiscard]]
  179. std::optional<va_t> elf_dynamic_symtab() const;
  180. [[nodiscard]]
  181. std::optional<va_t> elf_dynamic_strtab() const;
  182. [[nodiscard]]
  183. const std::map<va_t, size_t>& relocation_distribute() const;
  184. };
  185. }