#include #include #include #include #include namespace Codegen { namespace { class Amd64OnlyConverter : public IAmd64OnlyConverter { public: [[nodiscard]] ConvertResult Convert( std::vector fileBytes, const std::vector& codeSegments ) const override; private: X64InstructionRewriter _rewriter; std::unique_ptr _matcher = MakeAmd64OnlyInstructionMatcher(); std::unique_ptr _scanner = MakeInstructionScanner(); std::size_t _convertSegment( std::vector& fileBytes, const Domain::ProgramHeader& ph ) const; }; std::size_t Amd64OnlyConverter::_convertSegment( std::vector& fileBytes, const Domain::ProgramHeader& ph ) const { const auto segOffset = static_cast(ph.Offset); const auto segSize = static_cast(ph.FileSize); std::vector seg( fileBytes.begin() + segOffset, fileBytes.begin() + segOffset + segSize ); const auto matches = _scanner->ScanCodeSection(seg, 0, seg.size()); std::int64_t shift = 0; std::size_t count = 0; for (const auto& match : matches) { const auto shiftedOffset = static_cast(match.Offset) + shift; const auto offset = static_cast(shiftedOffset); const auto result = _matcher->Match(seg.data() + offset, match.Length); if (!result.has_value()) { continue; } const RewriteRequest request{ static_cast(offset), result->ReplacementBytes }; auto rewriteResult = _rewriter.Rewrite(seg, request); shift += static_cast(result->ReplacementBytes.size()) - static_cast(match.Length); seg = std::move(rewriteResult.Bytes); ++count; } const auto copySize = std::min(seg.size(), segSize); std::copy(seg.begin(), seg.begin() + copySize, fileBytes.begin() + segOffset); return count; } ConvertResult Amd64OnlyConverter::Convert( std::vector fileBytes, const std::vector& codeSegments ) const { std::size_t total = 0; for (const auto& ph : codeSegments) { total += _convertSegment(fileBytes, ph); } return {std::move(fileBytes), total}; } } std::unique_ptr MakeAmd64OnlyConverter() { return std::make_unique(); } }