X64ImageInterpreter.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. #include "X64ImageInterpreter.hpp"
  2. namespace nkg {
  3. [[nodiscard]]
  4. X64ImageInterpreter X64ImageInterpreter::Parse(const void* lpImage, size_t cbImage) {
  5. X64ImageInterpreter Interpreter;
  6. Interpreter.m_MachOSize = cbImage;
  7. Interpreter.m_MachOHeader = reinterpret_cast<const mach_header_64*>(lpImage);
  8. if (Interpreter.m_MachOHeader->magic != MH_MAGIC_64) {
  9. throw ARL::AssertionError(__FILE__, __LINE__, "X64ImageInterpreter: bad MachO file: header magic check failure.");
  10. }
  11. auto cmd_p = ARL::AddressOffsetWithCast<const load_command*>(Interpreter.m_MachOHeader, sizeof(mach_header_64));
  12. for (decltype(mach_header_64::ncmds) i = 0; i < Interpreter.m_MachOHeader->ncmds; ++i) {
  13. switch (cmd_p->cmd) {
  14. case LC_SEGMENT_64: {
  15. auto segcmd_p = reinterpret_cast<const segment_command_64*>(cmd_p);
  16. auto section_p = ARL::AddressOffsetWithCast<const section_64*>(segcmd_p, sizeof(segment_command_64));
  17. Interpreter.m_Segments.emplace_back(segcmd_p);
  18. for (decltype(segment_command_64::nsects) j = 0; j < segcmd_p->nsects; ++j) {
  19. Interpreter.m_Sections.emplace_back(&section_p[j]);
  20. Interpreter.m_SectionsAddressMap[section_p[j].addr] = &section_p[j];
  21. Interpreter.m_SectionsOffsetMap[section_p[j].offset] = &section_p[j];
  22. }
  23. break;
  24. }
  25. case LC_DYSYMTAB: {
  26. Interpreter.m_SpecialLoadCommands.dysymtab = reinterpret_cast<const dysymtab_command*>(cmd_p);
  27. break;
  28. }
  29. case LC_SYMTAB: {
  30. Interpreter.m_SpecialLoadCommands.symtab = reinterpret_cast<const symtab_command*>(cmd_p);
  31. break;
  32. }
  33. case LC_DYLD_INFO_ONLY: {
  34. Interpreter.m_SpecialLoadCommands.dyld_info = reinterpret_cast<const dyld_info_command*>(cmd_p);
  35. break;
  36. }
  37. default:
  38. break;
  39. }
  40. cmd_p = ARL::AddressOffset(cmd_p, cmd_p->cmdsize);
  41. }
  42. return Interpreter;
  43. }
  44. [[nodiscard]]
  45. size_t X64ImageInterpreter::NumberOfSegments() const noexcept {
  46. return m_Segments.size();
  47. }
  48. [[nodiscard]]
  49. size_t X64ImageInterpreter::NumberOfSections() const noexcept {
  50. return m_Sections.size();
  51. }
  52. [[nodiscard]]
  53. const segment_command_64* X64ImageInterpreter::ImageSegment(size_t Index) const {
  54. if (Index < m_Segments.size()) {
  55. return m_Segments[Index];
  56. } else {
  57. throw ARL::IndexError(__FILE__, __LINE__, "X64ImageInterpreter: Index is out of range.");
  58. }
  59. }
  60. [[nodiscard]]
  61. const segment_command_64* X64ImageInterpreter::ImageSegment(const char* SegmentName) const {
  62. for (const auto& segment : m_Segments) {
  63. if (strncmp(SegmentName, segment->segname, sizeof(segment->segname)) == 0) {
  64. return segment;
  65. }
  66. }
  67. throw ARL::KeyError(__FILE__, __LINE__, "X64ImageInterpreter: segment is not found.");
  68. }
  69. [[nodiscard]]
  70. const section_64* X64ImageInterpreter::ImageSection(size_t Index) const {
  71. if (Index < m_Sections.size()) {
  72. return m_Sections[Index];
  73. } else {
  74. throw ARL::IndexError(__FILE__, __LINE__, "X64ImageInterpreter: Index is out of range.");
  75. }
  76. }
  77. [[nodiscard]]
  78. const section_64* X64ImageInterpreter::ImageSection(const char* SegmentName, const char* SectionName) const {
  79. for (const auto& segment : m_Segments) {
  80. if (strncmp(SegmentName, segment->segname, sizeof(segment->segname)) == 0) {
  81. auto section = reinterpret_cast<const section_64*>(segment + 1);
  82. for (uint32_t i = 0; i < segment->nsects; ++i) {
  83. if (strncmp(SectionName, section[i].sectname, sizeof(section[i].sectname)) == 0) {
  84. return &section[i];
  85. }
  86. }
  87. break;
  88. }
  89. }
  90. throw ARL::KeyError(__FILE__, __LINE__, "X64ImageInterpreter: section is not found.");
  91. }
  92. [[nodiscard]]
  93. const section_64* X64ImageInterpreter::ImageSectionFromOffset(X64ImageOffset Offset) const {
  94. auto it = m_SectionsOffsetMap.upper_bound(Offset);
  95. if (it != m_SectionsOffsetMap.begin() && (--it, it->first <= Offset && Offset < it->first + it->second->size)) {
  96. return it->second;
  97. } else {
  98. throw ARL::KeyError(__FILE__, __LINE__, "X64ImageInterpreter: section is not found.");
  99. }
  100. }
  101. [[nodiscard]]
  102. const section_64* X64ImageInterpreter::ImageSectionFromRva(X64ImageAddress Rva) const {
  103. auto it = m_SectionsAddressMap.upper_bound(Rva);
  104. if (it != m_SectionsAddressMap.begin() && (--it, it->first <= Rva && Rva < it->first + it->second->size)) {
  105. return it->second;
  106. } else {
  107. throw ARL::KeyError(__FILE__, __LINE__, "X64ImageInterpreter: section is not found.");
  108. }
  109. }
  110. [[nodiscard]]
  111. X64ImageAddress X64ImageInterpreter::ConvertOffsetToRva(X64ImageOffset Offset) const {
  112. auto section = ImageSectionFromOffset(Offset);
  113. return section->addr + static_cast<X64ImageAddress>(Offset - section->offset);
  114. }
  115. [[nodiscard]]
  116. X64ImageOffset X64ImageInterpreter::ConvertRvaToOffset(X64ImageAddress Rva) const {
  117. auto section = ImageSectionFromRva(Rva);
  118. return section->offset + static_cast<X64ImageOffset>(Rva - section->addr);
  119. }
  120. }