fuzz_with_unicorn: Avoid self-modifying code
* Don't immediately terminate when unicorn raises an interrupt * Detect self-modifying code
This commit is contained in:
parent
9f8c6f60f5
commit
9c4f234417
3 changed files with 22 additions and 4 deletions
|
@ -119,7 +119,7 @@ static u32 GenFloatInst(u64 pc, bool is_last_inst) {
|
|||
// Approximation. Produces incorrect results.
|
||||
"FMADD_float", "FMSUB_float", "FNMADD_float", "FNMSUB_float",
|
||||
// Requires investigation (temporarily disabled).
|
||||
"FDIV_2",
|
||||
"FDIV_1", "FDIV_2",
|
||||
};
|
||||
|
||||
std::vector<InstructionGenerator> result;
|
||||
|
@ -150,8 +150,8 @@ static u32 GenFloatInst(u64 pc, bool is_last_inst) {
|
|||
|
||||
static void RunTestInstance(const Unicorn::RegisterArray& regs, const Unicorn::VectorArray& vecs, const size_t instructions_offset,
|
||||
const std::vector<u32>& instructions, const u32 pstate, const u32 fpcr) {
|
||||
static TestEnv jit_env;
|
||||
static TestEnv uni_env;
|
||||
static TestEnv jit_env{};
|
||||
static TestEnv uni_env{};
|
||||
|
||||
std::copy(instructions.begin(), instructions.end(), jit_env.code_mem.begin() + instructions_offset);
|
||||
std::copy(instructions.begin(), instructions.end(), uni_env.code_mem.begin() + instructions_offset);
|
||||
|
@ -159,6 +159,8 @@ static void RunTestInstance(const Unicorn::RegisterArray& regs, const Unicorn::V
|
|||
uni_env.code_mem[instructions.size() + instructions_offset] = 0x14000000; // B .
|
||||
jit_env.modified_memory.clear();
|
||||
uni_env.modified_memory.clear();
|
||||
jit_env.interrupts.clear();
|
||||
uni_env.interrupts.clear();
|
||||
|
||||
Dynarmic::A64::UserConfig jit_user_config{&jit_env};
|
||||
// The below corresponds to the settings for qemu's aarch64_max_initfn
|
||||
|
@ -238,14 +240,25 @@ static void RunTestInstance(const Unicorn::RegisterArray& regs, const Unicorn::V
|
|||
|
||||
fmt::print("x86_64:\n");
|
||||
fmt::print("{}\n", jit.Disassemble());
|
||||
|
||||
fmt::print("Interrupts:\n");
|
||||
for (auto& i : uni_env.interrupts) {
|
||||
puts(i.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
REQUIRE(uni_env.code_mem_modified_by_guest == jit_env.code_mem_modified_by_guest);
|
||||
if (uni_env.code_mem_modified_by_guest) {
|
||||
return;
|
||||
}
|
||||
|
||||
REQUIRE(uni.GetPC() == jit.GetPC());
|
||||
REQUIRE(uni.GetRegisters() == jit.GetRegisters());
|
||||
REQUIRE(uni.GetVectors() == jit.GetVectors());
|
||||
REQUIRE(uni.GetSP() == jit.GetSP());
|
||||
REQUIRE((uni.GetPstate() & 0xF0000000) == (jit.GetPstate() & 0xF0000000));
|
||||
REQUIRE(uni_env.modified_memory == jit_env.modified_memory);
|
||||
REQUIRE(uni_env.interrupts.empty());
|
||||
}
|
||||
|
||||
TEST_CASE("A64: Single random instruction", "[a64]") {
|
||||
|
|
|
@ -22,6 +22,7 @@ public:
|
|||
bool code_mem_modified_by_guest = false;
|
||||
std::array<u32, 1024> code_mem{};
|
||||
std::map<u64, u8> modified_memory;
|
||||
std::vector<std::string> interrupts;
|
||||
|
||||
std::uint32_t MemoryReadCode(u64 vaddr) override {
|
||||
if (vaddr < code_mem.size() * sizeof(u32)) {
|
||||
|
|
|
@ -38,6 +38,9 @@ void Unicorn::Run() {
|
|||
while (testenv.ticks_left > 0) {
|
||||
CHECKED(uc_emu_start(uc, GetPC(), END_ADDRESS, 0, 1));
|
||||
testenv.ticks_left--;
|
||||
if (!testenv.interrupts.empty() || testenv.code_mem_modified_by_guest) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,7 +171,8 @@ void Unicorn::InterruptHook(uc_engine* uc, u32 int_number, void* user_data) {
|
|||
this_->testenv.CallSVC(iss);
|
||||
break;
|
||||
default:
|
||||
ASSERT_MSG(false, "Unhandled interrupt: int_number: {:#x}, esr: {:#x} (ec: {:#x}, iss: {:#x})", int_number, esr, ec, iss);
|
||||
this_->testenv.interrupts.emplace_back(fmt::format("Unhandled interrupt: int_number: {:#x}, esr: {:#x} (ec: {:#x}, iss: {:#x})", int_number, esr, ec, iss));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue