123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- #pragma once
- #include <mach-o/loader.h>
- #include <mach-o/nlist.h>
- #include <string.h>
- #include <vector>
- #include <map>
- #include "Exception.hpp"
- #include "ExceptionGeneric.hpp"
- #include "MemoryAccess.hpp"
- namespace nkg {
- using X64ImageAddress = decltype(section_64::addr);
- using X64ImageOffset = decltype(section_64::offset);
- using X64ImageSize = decltype(section_64::size);
- class X64ImageInterpreter {
- private:
- size_t m_MachOSize;
- const mach_header_64* m_MachOHeader;
- std::vector<const segment_command_64*> m_Segments;
- std::vector<const section_64*> m_Sections;
- std::map<X64ImageAddress, const section_64*> m_SectionsAddressMap;
- std::map<X64ImageOffset, const section_64*> m_SectionsOffsetMap;
- struct {
- const dysymtab_command* dysymtab;
- const symtab_command* symtab;
- const dyld_info_command* dyld_info;
- } m_SpecialLoadCommands;
- X64ImageInterpreter() :
- m_MachOSize(0),
- m_MachOHeader(nullptr),
- m_SpecialLoadCommands{} {}
- public:
- [[nodiscard]]
- static X64ImageInterpreter Parse(const void* lpImage, size_t cbImage);
- template<typename __ReturnType = void*>
- [[nodiscard]]
- __ReturnType ImageBase() const noexcept {
- static_assert(std::is_pointer_v<__ReturnType>);
- return reinterpret_cast<__ReturnType>(
- const_cast<mach_header_64*>(m_MachOHeader)
- );
- }
- template<typename __ReturnType = void*>
- [[nodiscard]]
- __ReturnType ImageOffset(size_t Offset) const {
- if (Offset < m_MachOSize) {
- return ARL::AddressOffsetWithCast<__ReturnType>(m_MachOHeader, Offset);
- } else {
- throw ARL::OverflowError(__FILE__, __LINE__, "X64ImageInterpreter: out of range.");
- }
- }
- [[nodiscard]]
- size_t ImageSize() const noexcept {
- return m_MachOSize;
- }
- [[nodiscard]]
- size_t NumberOfSegments() const noexcept;
- [[nodiscard]]
- size_t NumberOfSections() const noexcept;
- [[nodiscard]]
- const segment_command_64* ImageSegment(size_t Index) const;
- [[nodiscard]]
- const segment_command_64* ImageSegment(const char* SegmentName) const;
- [[nodiscard]]
- const section_64* ImageSection(size_t Index) const;
- [[nodiscard]]
- const section_64* ImageSection(const char* SegmentName, const char* SectionName) const;
- [[nodiscard]]
- const section_64* ImageSectionFromOffset(X64ImageOffset Offset) const;
- [[nodiscard]]
- const section_64* ImageSectionFromRva(X64ImageAddress Rva) const;
- template<typename __ReturnType = void*>
- [[nodiscard]]
- __ReturnType ImageSectionView(const section_64* Section) const noexcept {
- return ImageOffset<__ReturnType>(Section->offset);
- }
- template<typename __ReturnType = void*>
- [[nodiscard]]
- __ReturnType ImageSectionView(size_t Index) const {
- return ImageSectionView<__ReturnType>(ImageSection(Index));
- }
- template<typename __ReturnType = void*>
- [[nodiscard]]
- __ReturnType ImageSectionView(const char* SegmentName, const char* SectionName) const {
- return ImageSectionView<__ReturnType>(ImageSection(SegmentName, SectionName));
- }
- template<unsigned __CommandMacro>
- [[nodiscard]]
- auto SpecialLoadCommand() const noexcept {
- if constexpr (__CommandMacro == LC_DYSYMTAB) {
- return m_SpecialLoadCommands.dysymtab;
- } else if constexpr (__CommandMacro == LC_SYMTAB) {
- return m_SpecialLoadCommands.symtab;
- } else if constexpr (__CommandMacro == LC_DYLD_INFO_ONLY) {
- return m_SpecialLoadCommands.dyld_info;
- } else {
- #pragma clang diagnostic push
- #pragma GCC diagnostic ignored "-Wtautological-compare"
- constexpr bool always_false = __CommandMacro != __CommandMacro;
- #pragma clang diagnostic pop
- static_assert(always_false);
- }
- }
- template<typename __ReturnType = void*, typename __HintType>
- [[nodiscard]]
- __ReturnType SearchSection(const section_64* Section, __HintType&& Hint) const {
- static_assert(std::is_pointer_v<__ReturnType>);
- auto base = ImageSectionView<const uint8_t*>(Section);
- for (decltype(section_64::size) i = 0; i < Section->size; ++i) {
- if (Hint(base, i, Section->size) == true) {
- return ARL::AddressOffsetWithCast<__ReturnType>(base, i);
- }
- }
- return nullptr;
- }
- template<typename __ReturnType = void*, typename __HintType>
- [[nodiscard]]
- __ReturnType SearchSection(const section_64* Section, size_t Offset, __HintType&& Hint) const {
- static_assert(std::is_pointer_v<__ReturnType>);
- auto base = ImageSectionView<const uint8_t*>(Section);
- for (decltype(section_64::size) i = Offset; i < Section->size; ++i) {
- if (Hint(base, i, Section->size) == true) {
- return ARL::AddressOffsetWithCast<__ReturnType>(base, i);
- }
- }
- return nullptr;
- }
- template<typename __ReturnType = void*, typename __HintType>
- [[nodiscard]]
- __ReturnType SearchSection(size_t Index, __HintType&& Hint) const {
- return SearchSection<__ReturnType>(ImageSection(Index), std::forward<__HintType>(Hint));
- }
- template<typename __ReturnType = void*, typename __HintType>
- [[nodiscard]]
- __ReturnType SearchSection(size_t Index, size_t Offset, __HintType&& Hint) const {
- return SearchSection<__ReturnType>(ImageSection(Index), Offset, std::forward<__HintType>(Hint));
- }
- template<typename __ReturnType = void*, typename __HintType>
- [[nodiscard]]
- __ReturnType SearchSection(const char* SegmentName, const char* SectionName, __HintType&& Hint) const {
- return SearchSection<__ReturnType>(ImageSection(SegmentName, SectionName), std::forward<__HintType>(Hint));
- }
- template<typename __ReturnType = void*, typename __HintType>
- [[nodiscard]]
- __ReturnType SearchSection(const char* SegmentName, const char* SectionName, size_t Offset, __HintType&& Hint) const {
- return SearchSection<__ReturnType>(ImageSection(SegmentName, SectionName), Offset, std::forward<__HintType>(Hint));
- }
- [[nodiscard]]
- X64ImageAddress ConvertOffsetToRva(X64ImageOffset Offset) const;
- template<typename __ReturnType = void*>
- [[nodiscard]]
- __ReturnType ConvertOffsetToPtr(X64ImageOffset Offset) const {
- return ImageOffset<__ReturnType>(Offset);
- }
- [[nodiscard]]
- X64ImageOffset ConvertRvaToOffset(X64ImageAddress Address) const;
- template<typename __ReturnType = void*>
- [[nodiscard]]
- __ReturnType ConvertRvaToPtr(X64ImageAddress Rva) const {
- return ConvertOffsetToPtr<__ReturnType>(ConvertRvaToOffset(Rva));
- }
- template<typename __PtrType>
- [[nodiscard]]
- X64ImageAddress ConvertPtrToRva(__PtrType Ptr) const {
- auto offset = ARL::AddressDelta(Ptr, m_MachOHeader);
- if (offset < m_MachOSize) {
- return ConvertOffsetToRva(offset);
- } else {
- throw ARL::OverflowError(__FILE__, __LINE__, "X64ImageInterpreter: out of range.");
- }
- }
- template<typename __PtrType>
- [[nodiscard]]
- X64ImageAddress ConvertPtrToOffset(__PtrType Ptr) const {
- auto offset = ARL::AddressDelta(Ptr, m_MachOHeader);
- if (offset < m_MachOSize) {
- return offset;
- } else {
- throw ARL::OverflowError(__FILE__, __LINE__, "X64ImageInterpreter: out of range.");
- }
- }
- };
- }
|