elf64_interpreter.hpp 7.1 KB

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