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:
commit
a46ffb5e75
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue