Merge pull request #4066 from hawwwwwk/pr/relinker-ff-callsite-current

fix(relinker): filter non-reference RIP-relative FF operations
This commit is contained in:
Dean 2026-10-13 01:25:57 +13:00 committed by GitHub
commit a46ffb5e75
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 55 additions and 1 deletions

View File

@ -325,6 +325,18 @@ if(BUILD_TESTING)
${CMAKE_CURRENT_SOURCE_DIR}/io/include
)
add_test(NAME amd64_only_converter COMMAND amd64_only_converter_tests)
add_test_executable(call_site_resolver_tests
${CMAKE_CURRENT_SOURCE_DIR}/relinker/tests/CallSiteResolverTests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/relinker/src/analysis/CallSiteResolver.cpp
${CMAKE_CURRENT_SOURCE_DIR}/codegen/src/InstructionScanner.cpp
${CMAKE_CURRENT_SOURCE_DIR}/codegen/src/x86/X64InstructionDecoder.cpp
)
target_include_directories(call_site_resolver_tests PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/domain/include
${CMAKE_CURRENT_SOURCE_DIR}/relinker/include
${CMAKE_CURRENT_SOURCE_DIR}/codegen/include
)
add_test(NAME call_site_resolver COMMAND call_site_resolver_tests)
add_test_executable(decoder_length_tests
${CMAKE_CURRENT_SOURCE_DIR}/codegen/tests/DecoderLengthTests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/codegen/src/x86/X64InstructionDecoder.cpp

View File

@ -28,7 +28,8 @@ bool isRipRelativeFF(const std::vector<std::uint8_t>& text, const Codegen::Instr
std::uint8_t modrm = text[cur + 1];
std::uint8_t mod = (modrm >> ModRmModShift) & ModRmModMask;
std::uint8_t rm = modrm & ModRmRmMask;
return mod == ModRmModIndirect && rm == ModRmRmRipRelative;
const auto operation = (modrm >> ModRmRegShift) & ModRmRegMask;
return mod == ModRmModIndirect && rm == ModRmRmRipRelative && (operation >= 2 && operation <= 6);
}
break;
}

View File

@ -0,0 +1,41 @@
#include <relinker/analysis/CallSiteResolver.hpp>
#include <cstdint>
#include <initializer_list>
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>
namespace {
void require(bool condition, const std::string& name) {
if (!condition) throw std::runtime_error(name);
}
void check(const std::string& name, std::initializer_list<std::uint8_t> instruction, bool expected) {
auto resolver = Relinker::MakeCallSiteResolver();
const std::vector<std::uint8_t> text(instruction);
const auto sites = resolver->ResolveCallSites(text, 0x1000, 0x1100, 8);
require(sites == (expected ? std::vector<Relinker::FileByteOffset>{0x1000} : std::vector<Relinker::FileByteOffset>{}), name);
require(resolver->ResolveCallSites(text, 0x1000, 0x1200, 8).empty(), name + " unexpected address");
}
}
int main() {
try {
check("indirect call", {0xff, 0x15, 0xfa, 0, 0, 0}, true);
check("indirect tail jump", {0xff, 0x25, 0xfa, 0, 0, 0}, true);
check("far indirect call", {0xff, 0x1d, 0xfa, 0, 0, 0}, true);
check("far indirect jump", {0xff, 0x2d, 0xfa, 0, 0, 0}, true);
check("RIP-relative function pointer load", {0x48, 0x8b, 0x05, 0xf9, 0, 0, 0}, true);
check("increment memory", {0xff, 0x05, 0xfa, 0, 0, 0}, false);
check("decrement memory", {0xff, 0x0d, 0xfa, 0, 0, 0}, false);
check("push memory", {0xff, 0x35, 0xfa, 0, 0, 0}, true);
std::cout << "Call-site resolver tests passed\n";
return 0;
} catch (const std::exception& error) {
std::cerr << "call_site_resolver_tests: " << error.what() << '\n';
return 1;
}
}