From 1818fc8e50cc96b72c2c97b1925562f401bb8e4a Mon Sep 17 00:00:00 2001 From: Alex Cameron Date: Fri, 17 Feb 2023 10:34:21 +1300 Subject: [PATCH] Support PowerPC syscall (#653) * Support PowerPC syscall * Enable PowerPC syscall unit test * Create stub sync hyper call * Cleanup * Fix `ConstantInt` call * Use `LoadMemoryPointerRef` util --- include/remill/Arch/Runtime/HyperCall.h | 1 + include/remill/Arch/Runtime/Intrinsics.h | 2 ++ include/remill/BC/IntrinsicTable.h | 1 + lib/Arch/Runtime/HyperCall.cpp | 4 ++++ lib/BC/IntrinsicTable.cpp | 1 + lib/BC/SleighLifter.cpp | 23 +++++++++++++++++++++++ test_runner_lib/TestRunner.cpp | 10 ++++++++++ tests/PPC/TestLifting.cpp | 3 +-- 8 files changed, 43 insertions(+), 2 deletions(-) diff --git a/include/remill/Arch/Runtime/HyperCall.h b/include/remill/Arch/Runtime/HyperCall.h index 4c529c5b..1a32eeaf 100644 --- a/include/remill/Arch/Runtime/HyperCall.h +++ b/include/remill/Arch/Runtime/HyperCall.h @@ -95,6 +95,7 @@ class SyncHyperCall { kSPARCTrapCondVS, kPPCEmulateInstruction, + kPPCSysCall, }; } __attribute__((packed)); diff --git a/include/remill/Arch/Runtime/Intrinsics.h b/include/remill/Arch/Runtime/Intrinsics.h index 1cc244d7..c0634314 100644 --- a/include/remill/Arch/Runtime/Intrinsics.h +++ b/include/remill/Arch/Runtime/Intrinsics.h @@ -423,4 +423,6 @@ __remill_sparc64_emulate_instruction(Memory *); [[gnu::used, gnu::const]] extern Memory * __remill_ppc_emulate_instruction(Memory *); +[[gnu::used, gnu::const]] extern Memory *__remill_ppc_syscall(Memory *); + } // extern C diff --git a/include/remill/BC/IntrinsicTable.h b/include/remill/BC/IntrinsicTable.h index d31fd777..227b60f6 100644 --- a/include/remill/BC/IntrinsicTable.h +++ b/include/remill/BC/IntrinsicTable.h @@ -42,6 +42,7 @@ class IntrinsicTable { llvm::Function *const missing_block; // OS interaction. + llvm::Function *const sync_hyper_call; llvm::Function *const async_hyper_call; // Memory read intrinsics. diff --git a/lib/Arch/Runtime/HyperCall.cpp b/lib/Arch/Runtime/HyperCall.cpp index 51f54eca..4633d858 100644 --- a/lib/Arch/Runtime/HyperCall.cpp +++ b/lib/Arch/Runtime/HyperCall.cpp @@ -386,6 +386,10 @@ Memory *__remill_sync_hyper_call(State &state, Memory *mem, mem = __remill_ppc_emulate_instruction(mem); break; + case SyncHyperCall::kPPCSysCall: + mem = __remill_ppc_syscall(mem); + break; + #endif default: __builtin_unreachable(); break; diff --git a/lib/BC/IntrinsicTable.cpp b/lib/BC/IntrinsicTable.cpp index d1203a5c..735a8d1e 100644 --- a/lib/BC/IntrinsicTable.cpp +++ b/lib/BC/IntrinsicTable.cpp @@ -79,6 +79,7 @@ IntrinsicTable::IntrinsicTable(llvm::Module *module) missing_block(FindIntrinsic(module, "__remill_missing_block")), // OS interaction. + sync_hyper_call(FindIntrinsic(module, "__remill_sync_hyper_call")), async_hyper_call(FindIntrinsic(module, "__remill_async_hyper_call")), // Memory access. diff --git a/lib/BC/SleighLifter.cpp b/lib/BC/SleighLifter.cpp index 294a53bd..1d167fd5 100644 --- a/lib/BC/SleighLifter.cpp +++ b/lib/BC/SleighLifter.cpp @@ -22,12 +22,15 @@ #include #include #include +#include +#include #include #include #include #include #include +#include #include #include #include @@ -74,6 +77,7 @@ static size_t kNextPcArgNum = 3; static const std::string kEqualityClaimName = "claim_eq"; +static const std::string kSysCallName = "syscall"; static bool isVarnodeInConstantSpace(VarnodeData vnode) { auto spc = vnode.getAddr().getSpace(); @@ -1263,6 +1267,25 @@ class SleighLifter::PcodeToLLVMEmitIntoBlock { vars[2]); return kLiftedInstruction; } + if (other_func_name == kSysCallName && + insn.arch_name == ArchName::kArchPPC) { + DLOG(INFO) << "Invoking syscall"; + + const auto mem_ptr_ref = LoadMemoryPointerRef(bldr.GetInsertBlock()); + + // Get a LLVM value for the sync hyper call enumeration. + auto hyper_call_int = + static_cast(SyncHyperCall::Name::kPPCSysCall); + auto hyper_call = llvm::ConstantInt::get( + llvm::IntegerType::get(this->context, 32), hyper_call_int); + std::array args = {state_pointer, mem_ptr_ref, + hyper_call}; + + bldr.CreateCall(insn_lifter_parent.GetIntrinsicTable()->sync_hyper_call, + args); + + return kLiftedInstruction; + } DLOG(ERROR) << "Unsupported pcode intrinsic: " << *other_func_name; } return kLiftedUnsupportedInstruction; diff --git a/test_runner_lib/TestRunner.cpp b/test_runner_lib/TestRunner.cpp index d060ccb0..4a0aa8b9 100644 --- a/test_runner_lib/TestRunner.cpp +++ b/test_runner_lib/TestRunner.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -185,6 +186,15 @@ MemoryHandler *__remill_write_memory_64(MemoryHandler *memory, uint64_t addr, memory->WriteMemory(addr, value); return memory; } + +struct State; + +// PowerPC syscalls leave a `__remill_sync_hyper_call` invocation. +// Create an empty stub implementation so we can still execute our LLVM code. +MemoryHandler *__remill_sync_hyper_call(State &state, MemoryHandler *mem, + SyncHyperCall::Name call) { + return mem; +} } diff --git a/tests/PPC/TestLifting.cpp b/tests/PPC/TestLifting.cpp index 93e99502..bdb5dc9e 100644 --- a/tests/PPC/TestLifting.cpp +++ b/tests/PPC/TestLifting.cpp @@ -760,8 +760,7 @@ TEST(PPCVLELifts, PPCVLEConvertFloatToSignedInteger) { } // Test syscall -// TODO(wtan): Disabled, callother not supported -TEST(PPCVLELifts, DISABLED_PPCVLESyscall) { +TEST(PPCVLELifts, PPCVLESyscall) { llvm::LLVMContext curr_context; // e_sc std::string insn_data("\x7c\x00\x00\x48", 4);