Elf64Interpreter.hpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. #pragma once
  2. #include <stddef.h>
  3. #include <stdint.h>
  4. #ifdef __APPLE__
  5. #include <libelf/libelf.h>
  6. #else
  7. #include <elf.h>
  8. #endif
  9. #include <string>
  10. #include <vector>
  11. #include <map>
  12. #include <type_traits>
  13. #include <utility>
  14. #include "MemoryAccess.hpp"
  15. namespace nkg {
  16. class Elf64Interpreter {
  17. private:
  18. size_t m_ElfSize;
  19. const Elf64_Ehdr* m_lpElfHdr;
  20. const Elf64_Phdr* m_lpElfProgramHdr;
  21. const Elf64_Shdr* m_lpElfSectionHdr;
  22. std::map<Elf64_Addr, const Elf64_Shdr*> m_SectionRvaMap;
  23. std::map<Elf64_Off, const Elf64_Shdr*> m_SectionOffsetMap;
  24. std::map<std::string, const Elf64_Shdr*> m_SectionNameMap;
  25. protected:
  26. Elf64Interpreter() :
  27. m_ElfSize(0),
  28. m_lpElfHdr(nullptr),
  29. m_lpElfProgramHdr(nullptr),
  30. m_lpElfSectionHdr(nullptr) {}
  31. public:
  32. [[nodiscard]]
  33. static Elf64Interpreter Parse(const void* lpImage, size_t cbImage);
  34. size_t ElfSize() const noexcept;
  35. template<typename __ReturnType = void*>
  36. [[nodiscard]]
  37. __ReturnType ElfBase() const noexcept {
  38. static_assert(std::is_pointer_v<__ReturnType>);
  39. return reinterpret_cast<__ReturnType>(const_cast<Elf64_Ehdr*>(m_lpElfHdr));
  40. }
  41. template<typename __ReturnType = void*>
  42. [[nodiscard]]
  43. __ReturnType ElfOffset(Elf64_Off Offset) const noexcept {
  44. static_assert(std::is_pointer_v<__ReturnType>);
  45. return ARL::AddressOffsetWithCast<__ReturnType>(m_lpElfHdr, Offset);
  46. }
  47. [[nodiscard]]
  48. const Elf64_Ehdr* ElfHeader() const noexcept {
  49. return m_lpElfHdr;
  50. }
  51. [[nodiscard]]
  52. size_t NumberOfElfProgramHeaders() const noexcept {
  53. return m_lpElfHdr->e_phnum;
  54. }
  55. [[nodiscard]]
  56. const Elf64_Phdr* ElfProgramHeader(size_t Idx) const;
  57. [[nodiscard]]
  58. size_t NumberOfElfSectionHeaders() const noexcept {
  59. return m_lpElfHdr->e_shnum;
  60. }
  61. [[nodiscard]]
  62. const Elf64_Shdr* ElfSectionHeader(size_t Idx) const;
  63. [[nodiscard]]
  64. const Elf64_Shdr* ElfSectionHeader(std::string_view SectionName) const;
  65. template<typename __ReturnType = void*>
  66. [[nodiscard]]
  67. __ReturnType ElfSectionView(const Elf64_Shdr* SectionHeader, Elf64_Off Offset = 0) const noexcept {
  68. return ElfOffset<__ReturnType>(SectionHeader->sh_offset + Offset);
  69. }
  70. template<typename __ReturnType = void*>
  71. [[nodiscard]]
  72. __ReturnType ElfSectionView(size_t Idx, Elf64_Off Offset = 0) const noexcept {
  73. return ElfOffset<__ReturnType>(ElfSectionHeader(Idx)->sh_offset + Offset);
  74. }
  75. template<typename __ReturnType = void*>
  76. [[nodiscard]]
  77. __ReturnType ElfSectionView(std::string_view SectionName, Elf64_Off Offset = 0) const noexcept {
  78. return ElfOffset<__ReturnType>(ElfSectionHeader(SectionName)->sh_offset + Offset);
  79. }
  80. //
  81. // Other
  82. //
  83. template<typename __ReturnType = void*, typename __HintType>
  84. __ReturnType SearchElfSectionView(const Elf64_Shdr* SectionHeader, __HintType&& Hint) const noexcept {
  85. auto secview = ElfSectionView<const uint8_t*>(SectionHeader);
  86. for (decltype(Elf64_Shdr::sh_size) i = 0; i < SectionHeader->sh_size; ++i) {
  87. if (Hint(secview, i, SectionHeader->sh_size)) {
  88. return reinterpret_cast<__ReturnType>(const_cast<uint8_t*>(secview + i));
  89. }
  90. }
  91. return nullptr;
  92. }
  93. template<typename __ReturnType = void*, typename __HintType>
  94. __ReturnType SearchElfSectionView(const Elf64_Shdr* SectionHeader, Elf64_Off Offset, __HintType&& Hint) const noexcept {
  95. auto secview = ElfSectionView<const uint8_t*>(SectionHeader);
  96. for (decltype(Elf64_Shdr::sh_size) i = Offset; i < SectionHeader->sh_size; ++i) {
  97. if (Hint(secview, i, SectionHeader->sh_size)) {
  98. return reinterpret_cast<__ReturnType>(const_cast<uint8_t*>(secview + i));
  99. }
  100. }
  101. return nullptr;
  102. }
  103. template<typename __ReturnType = void*, typename __HintType>
  104. __ReturnType SearchElfSectionView(size_t Idx, __HintType&& Hint) const noexcept {
  105. return SearchElfSectionView<__ReturnType>(ElfSectionHeader(Idx), std::forward<__HintType>(Hint));
  106. }
  107. template<typename __ReturnType = void*, typename __HintType>
  108. __ReturnType SearchElfSectionView(size_t Idx, Elf64_Off Offset, __HintType&& Hint) const noexcept {
  109. return SearchElfSectionView<__ReturnType>(ElfSectionHeader(Idx), Offset, std::forward<__HintType>(Hint));
  110. }
  111. template<typename __ReturnType = void*, typename __HintType>
  112. __ReturnType SearchElfSectionView(std::string_view SectionName, __HintType&& Hint) const noexcept {
  113. return SearchElfSectionView<__ReturnType>(ElfSectionHeader(SectionName), std::forward<__HintType>(Hint));
  114. }
  115. template<typename __ReturnType = void*, typename __HintType>
  116. __ReturnType SearchElfSectionView(std::string_view SectionName, Elf64_Off Offset, __HintType&& Hint) const noexcept {
  117. return SearchElfSectionView<__ReturnType>(ElfSectionHeader(SectionName), Offset, std::forward<__HintType>(Hint));
  118. }
  119. [[nodiscard]]
  120. const auto& ElfSectionRvaMap() const noexcept {
  121. return m_SectionRvaMap;
  122. }
  123. [[nodiscard]]
  124. const auto& ElfSectionOffsetMap() const noexcept {
  125. return m_SectionOffsetMap;
  126. }
  127. [[nodiscard]]
  128. const auto& ElfSectionNameMap() const noexcept {
  129. return m_SectionNameMap;
  130. }
  131. [[nodiscard]]
  132. Elf64_Off ConvertRvaToOffset(Elf64_Addr Rva) const;
  133. template<typename __PtrType>
  134. [[nodiscard]]
  135. Elf64_Off ConvertPtrToOffset(__PtrType Ptr) const {
  136. return ARL::AddressDelta(Ptr, m_lpElfHdr);
  137. }
  138. [[nodiscard]]
  139. Elf64_Addr ConvertOffsetToRva(Elf64_Off Offset) const;
  140. template<typename __PtrType>
  141. [[nodiscard]]
  142. Elf64_Addr ConvertPtrToRva(__PtrType Ptr) const {
  143. return ConvertOffsetToRva(ConvertPtrToOffset(Ptr));
  144. }
  145. template<typename __ReturnType = void*>
  146. [[nodiscard]]
  147. __ReturnType ConvertRvaToPtr(Elf64_Addr Rva) const {
  148. return ConvertOffsetToPtr<__ReturnType>(ConvertRvaToOffset(Rva));
  149. }
  150. template<typename __ReturnType = void*>
  151. [[nodiscard]]
  152. __ReturnType ConvertOffsetToPtr(Elf64_Off Offset) const {
  153. return ElfOffset<__ReturnType>(Offset);
  154. }
  155. };
  156. }