Support PowerPC syscall (#653)

* Support PowerPC syscall

* Enable PowerPC syscall unit test

* Create stub sync hyper call

* Cleanup

* Fix `ConstantInt` call

* Use `LoadMemoryPointerRef` util
This commit is contained in:
Alex Cameron
2023-02-17 10:34:21 +13:00
committed by GitHub
parent 6cc821bc7e
commit 1818fc8e50
8 changed files with 43 additions and 2 deletions
+1
View File
@@ -95,6 +95,7 @@ class SyncHyperCall {
kSPARCTrapCondVS,
kPPCEmulateInstruction,
kPPCSysCall,
};
} __attribute__((packed));
+2
View File
@@ -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
+1
View File
@@ -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.
+4
View File
@@ -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;
+1
View File
@@ -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.
+23
View File
@@ -22,12 +22,15 @@
#include <llvm/IR/DerivedTypes.h>
#include <llvm/IR/Value.h>
#include <llvm/IR/Verifier.h>
#include <remill/Arch/Name.h>
#include <remill/Arch/Runtime/HyperCall.h>
#include <remill/BC/ABI.h>
#include <remill/BC/IntrinsicTable.h>
#include <remill/BC/PCodeCFG.h>
#include <remill/BC/SleighLifter.h>
#include <remill/BC/Util.h>
#include <array>
#include <cassert>
#include <optional>
#include <sleigh/pcoderaw.hh>
@@ -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<uint32_t>(SyncHyperCall::Name::kPPCSysCall);
auto hyper_call = llvm::ConstantInt::get(
llvm::IntegerType::get(this->context, 32), hyper_call_int);
std::array<llvm::Value *, 3> 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;
+10
View File
@@ -30,6 +30,7 @@
#include <llvm/Support/TargetSelect.h>
#include <llvm/Transforms/Utils/Cloning.h>
#include <remill/Arch/Arch.h>
#include <remill/Arch/Runtime/HyperCall.h>
#include <remill/BC/InstructionLifter.h>
#include <remill/BC/IntrinsicTable.h>
#include <remill/BC/Lifter.h>
@@ -185,6 +186,15 @@ MemoryHandler *__remill_write_memory_64(MemoryHandler *memory, uint64_t addr,
memory->WriteMemory<uint64_t>(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;
}
}
+1 -2
View File
@@ -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);