Skip to content

Commit

Permalink
Fix big endian type conversions for registers (lifting-bits#699)
Browse files Browse the repository at this point in the history
* add conversion checking

* Update lib/BC/SleighLifter.cpp

Co-authored-by: William Tan <[email protected]>

---------

Co-authored-by: William Tan <[email protected]>
  • Loading branch information
2over12 and Ninja3047 committed Feb 14, 2024
1 parent 3912619 commit 608acf8
Showing 1 changed file with 77 additions and 32 deletions.
109 changes: 77 additions & 32 deletions lib/BC/SleighLifter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Value.h>
#include <llvm/IR/Verifier.h>
#include <llvm/Support/Casting.h>
#include <remill/Arch/Context.h>
#include <remill/Arch/Name.h>
#include <remill/Arch/Runtime/HyperCall.h>
Expand Down Expand Up @@ -125,11 +126,40 @@ llvm::Value *CreatePcodeBitShift(llvm::Value *lhs, llvm::Value *rhs,
class SleighLifter::PcodeToLLVMEmitIntoBlock {
private:
class Parameter {
private:
llvm::Type *vnode_type;
bool allows_conversions;

public:
Parameter(llvm::Type *vnode_type, bool allows_conversions)
: vnode_type(vnode_type),
allows_conversions(allows_conversions) {}

virtual ~Parameter(void) = default;

virtual std::optional<llvm::Value *> LiftAsInParam(llvm::IRBuilder<> &bldr,
llvm::Type *ty) = 0;
llvm::Type *ty) {
auto mayberes = this->LiftAsInParamNoConvert(bldr, vnode_type);
if (!mayberes) {
return std::nullopt;
}

auto res = *mayberes;
if (res->getType() == ty) {
return res;
}

if (!allows_conversions ||
!llvm::isa<llvm::IntegerType>(res->getType()) ||
!llvm::isa<llvm::IntegerType>(ty)) {
return std::nullopt;
}

return bldr.CreateZExtOrTrunc(res, ty);
}

virtual std::optional<llvm::Value *>
LiftAsInParamNoConvert(llvm::IRBuilder<> &bldr, llvm::Type *ty) = 0;

virtual LiftStatus StoreIntoParam(llvm::IRBuilder<> &bldr,
llvm::Value *inner_lifted) = 0;
Expand Down Expand Up @@ -195,7 +225,9 @@ class SleighLifter::PcodeToLLVMEmitIntoBlock {
}


return RegisterValue::CreateRegister(maybe_reg->second);
return RegisterValue::CreateRegister(
maybe_reg->second,
llvm::IntegerType::get(this->context, target_vnode.size * 8));
}
};

Expand All @@ -206,8 +238,8 @@ class SleighLifter::PcodeToLLVMEmitIntoBlock {

public:
// TODO(Ian): allow this to be fallible and have better error handling
std::optional<llvm::Value *> LiftAsInParam(llvm::IRBuilder<> &bldr,
llvm::Type *ty) override {
std::optional<llvm::Value *>
LiftAsInParamNoConvert(llvm::IRBuilder<> &bldr, llvm::Type *ty) override {
return bldr.CreateLoad(ty, register_pointer);
}

Expand All @@ -218,11 +250,13 @@ class SleighLifter::PcodeToLLVMEmitIntoBlock {
}

public:
RegisterValue(llvm::Value *register_pointer)
: register_pointer(register_pointer) {}
RegisterValue(llvm::Value *register_pointer, llvm::Type *orig_type)
: Parameter(orig_type, true),
register_pointer(register_pointer) {}

static ParamPtr CreateRegister(llvm::Value *register_pointer) {
return std::make_shared<RegisterValue>(register_pointer);
static ParamPtr CreateRegister(llvm::Value *register_pointer,
llvm::Type *vnode_type) {
return std::make_shared<RegisterValue>(register_pointer, vnode_type);
}

virtual ~RegisterValue() {}
Expand All @@ -233,18 +267,20 @@ class SleighLifter::PcodeToLLVMEmitIntoBlock {
public:
virtual ~Memory() {}
Memory(llvm::Value *memory_ref_ptr, llvm::Value *index,
const IntrinsicTable *intrinsics, llvm::Type *memory_ptr_type)
: memory_ref_ptr(memory_ref_ptr),
const IntrinsicTable *intrinsics, llvm::Type *memory_ptr_type,
llvm::Type *vnode_type)
: Parameter(vnode_type, true),
memory_ref_ptr(memory_ref_ptr),
index(index),
intrinsics(intrinsics),
memory_ptr_type(memory_ptr_type) {}

static ParamPtr CreateMemory(llvm::Value *memory_ref_ptr,
llvm::Value *index,
const IntrinsicTable *intrinsics,
llvm::Type *memory_ptr_type) {
static ParamPtr
CreateMemory(llvm::Value *memory_ref_ptr, llvm::Value *index,
const IntrinsicTable *intrinsics, llvm::Type *memory_ptr_type,
llvm::Type *vnode_type) {
return std::make_shared<Memory>(memory_ref_ptr, index, intrinsics,
memory_ptr_type);
memory_ptr_type, vnode_type);
}

private:
Expand All @@ -253,8 +289,8 @@ class SleighLifter::PcodeToLLVMEmitIntoBlock {
const IntrinsicTable *intrinsics;
llvm::Type *memory_ptr_type;

std::optional<llvm::Value *> LiftAsInParam(llvm::IRBuilder<> &bldr,
llvm::Type *ty) override {
std::optional<llvm::Value *>
LiftAsInParamNoConvert(llvm::IRBuilder<> &bldr, llvm::Type *ty) override {
auto mem = bldr.CreateLoad(this->memory_ptr_type, this->memory_ref_ptr);
auto res = remill::LoadFromMemory(
*this->intrinsics, bldr.GetInsertBlock(), ty, mem, this->index);
Expand Down Expand Up @@ -285,8 +321,8 @@ class SleighLifter::PcodeToLLVMEmitIntoBlock {
llvm::Value *cst;

public:
std::optional<llvm::Value *> LiftAsInParam(llvm::IRBuilder<> &bldr,
llvm::Type *ty) override {
std::optional<llvm::Value *>
LiftAsInParamNoConvert(llvm::IRBuilder<> &bldr, llvm::Type *ty) override {
if (ty != cst->getType()) {
return std::nullopt;
}
Expand All @@ -298,7 +334,9 @@ class SleighLifter::PcodeToLLVMEmitIntoBlock {
return LiftStatus::kLiftedUnsupportedInstruction;
}

ConstantValue(llvm::Value *cst) : cst(cst) {}
ConstantValue(llvm::Value *cst)
: Parameter(cst->getType(), false),
cst(cst) {}

static ParamPtr CreatConstant(llvm::Value *cst) {
return std::make_shared<ConstantValue>(cst);
Expand Down Expand Up @@ -468,19 +506,21 @@ class SleighLifter::PcodeToLLVMEmitIntoBlock {
context_reg_lifter(std::move(context_reg_lifter)) {}


ParamPtr CreateMemoryAddress(llvm::Value *offset) {
ParamPtr CreateMemoryAddress(llvm::Value *offset, VarnodeData vnode) {
const auto mem_ptr_ref = this->insn_lifter_parent.LoadRegAddress(
this->target_block, this->state_pointer, kMemoryVariableName);
// compute pointer into memory at offset


return Memory::CreateMemory(mem_ptr_ref.first, offset,
this->insn_lifter_parent.GetIntrinsicTable(),
this->insn_lifter_parent.GetMemoryType());
return Memory::CreateMemory(
mem_ptr_ref.first, offset, this->insn_lifter_parent.GetIntrinsicTable(),
this->insn_lifter_parent.GetMemoryType(),
llvm::IntegerType::get(this->context, vnode.size * 8));
}

std::optional<ParamPtr> LiftNormalRegister(llvm::IRBuilder<> &bldr,
std::string reg_name) {
std::string reg_name,
VarnodeData target_vnode) {
for (auto &c : reg_name) {
c = toupper(c);
}
Expand All @@ -496,7 +536,9 @@ class SleighLifter::PcodeToLLVMEmitIntoBlock {
// TODO(Ian): will probably need to adjust the pointer here in certain circumstances
auto reg_ptr = this->insn_lifter_parent.LoadRegAddress(
bldr.GetInsertBlock(), this->state_pointer, reg_name);
return RegisterValue::CreateRegister(reg_ptr.first);
return RegisterValue::CreateRegister(
reg_ptr.first,
llvm::IntegerType::get(this->context, target_vnode.size * 8));
} else {
return std::nullopt;
}
Expand All @@ -505,7 +547,7 @@ class SleighLifter::PcodeToLLVMEmitIntoBlock {
ParamPtr LiftNormalRegisterOrCreateUnique(llvm::IRBuilder<> &bldr,
std::string reg_name,
VarnodeData target_vnode) {
if (auto res = this->LiftNormalRegister(bldr, reg_name)) {
if (auto res = this->LiftNormalRegister(bldr, reg_name, target_vnode)) {
return *res;
}

Expand All @@ -525,7 +567,8 @@ class SleighLifter::PcodeToLLVMEmitIntoBlock {
DLOG(ERROR) << "Creating unique for unknown register: " << ss.str() << " "
<< reg_ptr->getName().str();

return RegisterValue::CreateRegister(reg_ptr);
return RegisterValue::CreateRegister(
reg_ptr, llvm::IntegerType::get(this->context, 8 * target_vnode.size));
}

//TODO(Ian): Maybe this should be a failable function that returns an unsupported insn in certain failures
Expand All @@ -541,7 +584,7 @@ class SleighLifter::PcodeToLLVMEmitIntoBlock {
auto constant_offset = this->replacement_cont.LiftOffsetOrReplace(
bldr, vnode, this->insn_lifter_parent.GetWordType());

return this->CreateMemoryAddress(constant_offset);
return this->CreateMemoryAddress(constant_offset, vnode);
} else if (space_name == "register") {
auto reg_name = this->insn_lifter_parent.GetEngine().getRegisterName(
vnode.space, vnode.offset, vnode.size);
Expand All @@ -561,7 +604,8 @@ class SleighLifter::PcodeToLLVMEmitIntoBlock {

auto reg_ptr =
this->uniques.GetUniquePtr(vnode.offset, vnode.size, entry_bldr);
return RegisterValue::CreateRegister(reg_ptr);
return RegisterValue::CreateRegister(
reg_ptr, llvm::IntegerType::get(this->context, 8 * vnode.size));
} else {
LOG(FATAL) << "Unhandled memory space: " << space_name;
}
Expand Down Expand Up @@ -1154,7 +1198,7 @@ class SleighLifter::PcodeToLLVMEmitIntoBlock {
return LiftStatus::kLiftedUnsupportedInstruction;
}
auto out_type = llvm::IntegerType::get(this->context, out_op.size * 8);
auto lifted_addr = this->CreateMemoryAddress(*lifted_addr_offset);
auto lifted_addr = this->CreateMemoryAddress(*lifted_addr_offset, out_op);

auto loaded_value = lifted_addr->LiftAsInParam(bldr, out_type);

Expand Down Expand Up @@ -1243,7 +1287,8 @@ class SleighLifter::PcodeToLLVMEmitIntoBlock {
llvm::IntegerType::get(this->context, param2.size * 8));

if (store_param.has_value()) {
auto lifted_addr = this->CreateMemoryAddress(*lifted_addr_offset);
auto lifted_addr =
this->CreateMemoryAddress(*lifted_addr_offset, param2);
return lifted_addr->StoreIntoParam(bldr, *store_param);
}
}
Expand Down

0 comments on commit 608acf8

Please sign in to comment.