mirror of
https://github.com/lifting-bits/remill
synced 2026-06-21 13:56:07 +00:00
WIP to support opaque pointers
This commit is contained in:
+2
-3
@@ -259,7 +259,6 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
std::unique_ptr<llvm::Module> module(remill::LoadArchSemantics(arch.get()));
|
||||
|
||||
const auto state_ptr_type = arch->StatePointerType();
|
||||
const auto mem_ptr_type = arch->MemoryPointerType();
|
||||
|
||||
Memory memory = UnhexlifyInputBytes(addr_mask);
|
||||
@@ -343,10 +342,10 @@ int main(int argc, char *argv[]) {
|
||||
<< "Invalid register name '" << reg_name.str()
|
||||
<< "' used in output slice list '" << FLAGS_slice_outputs << "'";
|
||||
|
||||
arg_types.push_back(llvm::PointerType::get(reg->type, 0));
|
||||
arg_types.push_back(llvm::PointerType::get(context, 0));
|
||||
}
|
||||
|
||||
const auto state_type = state_ptr_type->getPointerElementType();
|
||||
const auto state_type = llvm::PointerType::get(context, 0);
|
||||
const auto func_type =
|
||||
llvm::FunctionType::get(mem_ptr_type, arg_types, false);
|
||||
const auto func = llvm::Function::Create(
|
||||
|
||||
@@ -125,7 +125,7 @@ struct Register {
|
||||
// The directly enclosed registers.
|
||||
std::vector<const Register *> children;
|
||||
|
||||
void CompteGEPAccessors(const llvm::DataLayout &dl, llvm::Type *state_type);
|
||||
void ComputeGEPAccessors(const llvm::DataLayout &dl, llvm::Type *state_type);
|
||||
};
|
||||
|
||||
class Arch {
|
||||
|
||||
@@ -19,17 +19,10 @@
|
||||
|
||||
namespace remill {
|
||||
|
||||
// TODO(alex): Just remove this function entirely
|
||||
inline static llvm::Type *PointerElementType(llvm::PointerType *type) {
|
||||
#if LLVM_VERSION_NUMBER > LLVM_VERSION(13, 0)
|
||||
if (type->isOpaque())
|
||||
return nullptr;
|
||||
#endif
|
||||
|
||||
#if LLVM_VERSION_NUMBER < LLVM_VERSION(14, 0)
|
||||
return type->getElementType();
|
||||
#else
|
||||
return type->getPointerElementType();
|
||||
#endif
|
||||
assert(type->isOpaque());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace remill
|
||||
|
||||
+20
-26
@@ -237,7 +237,7 @@ llvm::StructType *Arch::StateStructType(void) const {
|
||||
llvm::PointerType *Arch::StatePointerType(void) const {
|
||||
CHECK(impl)
|
||||
<< "Have you not run `PrepareModule` on a loaded semantics module?";
|
||||
return llvm::PointerType::get(impl->state_type, 0);
|
||||
return llvm::PointerType::get(*context, 0);
|
||||
}
|
||||
|
||||
// Return the type of an address, i.e. `addr_t` in the semantics.
|
||||
@@ -444,10 +444,9 @@ namespace {
|
||||
|
||||
// Compute the total offset of a GEP chain.
|
||||
static uint64_t TotalOffset(const llvm::DataLayout &dl, llvm::Value *base,
|
||||
llvm::Type *state_ptr_type) {
|
||||
llvm::Type *state_type) {
|
||||
uint64_t total_offset = 0;
|
||||
const auto state_size =
|
||||
dl.getTypeAllocSize(state_ptr_type->getPointerElementType());
|
||||
const auto state_size = dl.getTypeAllocSize(state_type);
|
||||
while (base) {
|
||||
if (auto gep = llvm::dyn_cast<llvm::GEPOperator>(base); gep) {
|
||||
llvm::APInt accumulated_offset(dl.getPointerSizeInBits(0), 0, false);
|
||||
@@ -468,7 +467,7 @@ static uint64_t TotalOffset(const llvm::DataLayout &dl, llvm::Value *base,
|
||||
} else if (auto pti = llvm::dyn_cast<llvm::PtrToIntOperator>(base); pti) {
|
||||
base = pti->getOperand(0);
|
||||
|
||||
} else if (base->getType() == state_ptr_type) {
|
||||
} else if (base->getType()->isPointerTy()) {
|
||||
break;
|
||||
|
||||
} else {
|
||||
@@ -482,23 +481,22 @@ static uint64_t TotalOffset(const llvm::DataLayout &dl, llvm::Value *base,
|
||||
|
||||
static llvm::Value *
|
||||
FinishAddressOf(llvm::IRBuilder<> &ir, const llvm::DataLayout &dl,
|
||||
llvm::Type *state_ptr_type, size_t state_size,
|
||||
llvm::Type *state_type, size_t state_size,
|
||||
const Register *reg, unsigned addr_space,
|
||||
llvm::Value *gep) {
|
||||
|
||||
|
||||
auto gep_offset = TotalOffset(dl, gep, state_ptr_type);
|
||||
auto gep_type_at_offset = gep->getType()->getPointerElementType();
|
||||
auto gep_offset = TotalOffset(dl, gep, state_type);
|
||||
|
||||
CHECK_LT(gep_offset, state_size);
|
||||
|
||||
const auto index_type = reg->gep_index_list[0]->getType();
|
||||
const auto goal_ptr_type = llvm::PointerType::get(reg->type, addr_space);
|
||||
const auto goal_ptr_type = llvm::PointerType::get(ir.getContext(), addr_space);
|
||||
|
||||
// Best case: we've found a value field in the structure that
|
||||
// is located at the correct byte offset.
|
||||
if (gep_offset == reg->offset) {
|
||||
if (gep_type_at_offset == reg->type) {
|
||||
if (gep->getType()->isPointerTy()) {
|
||||
return gep;
|
||||
|
||||
} else if (auto const_gep = llvm::dyn_cast<llvm::Constant>(gep);
|
||||
@@ -539,13 +537,13 @@ FinishAddressOf(llvm::IRBuilder<> &ir, const llvm::DataLayout &dl,
|
||||
|
||||
if (auto const_gep = llvm::dyn_cast<llvm::Constant>(gep); const_gep) {
|
||||
const_gep = llvm::ConstantExpr::getBitCast(
|
||||
const_gep, llvm::PointerType::get(byte_type, addr_space));
|
||||
const_gep, llvm::PointerType::get(ir.getContext(), addr_space));
|
||||
const_gep = llvm::ConstantExpr::getGetElementPtr(byte_type, const_gep,
|
||||
elem_indexes);
|
||||
return llvm::ConstantExpr::getBitCast(const_gep, goal_ptr_type);
|
||||
|
||||
} else {
|
||||
gep = ir.CreateBitCast(gep, llvm::PointerType::get(byte_type, addr_space));
|
||||
gep = ir.CreateBitCast(gep, llvm::PointerType::get(ir.getContext(), addr_space));
|
||||
gep = ir.CreateGEP(byte_type, gep, elem_indexes);
|
||||
return ir.CreateBitCast(gep, goal_ptr_type);
|
||||
}
|
||||
@@ -553,8 +551,8 @@ FinishAddressOf(llvm::IRBuilder<> &ir, const llvm::DataLayout &dl,
|
||||
|
||||
} // namespace
|
||||
|
||||
void Register::CompteGEPAccessors(const llvm::DataLayout &dl,
|
||||
llvm::Type *state_type) {
|
||||
void Register::ComputeGEPAccessors(const llvm::DataLayout &dl,
|
||||
llvm::Type *state_type) {
|
||||
if (gep_type_at_offset || !state_type) {
|
||||
return;
|
||||
}
|
||||
@@ -576,7 +574,8 @@ llvm::Value *Register::AddressOf(llvm::Value *state_ptr,
|
||||
return AddressOf(state_ptr, ir);
|
||||
}
|
||||
|
||||
llvm::Value *Register::AddressOf(llvm::Value *state_ptr,
|
||||
llvm::Value *
|
||||
Register::AddressOf(llvm::Value *state_ptr,
|
||||
llvm::IRBuilder<> &ir) const {
|
||||
auto &context = type->getContext();
|
||||
CHECK_EQ(&context, &(state_ptr->getContext()));
|
||||
@@ -585,15 +584,13 @@ llvm::Value *Register::AddressOf(llvm::Value *state_ptr,
|
||||
CHECK_NOTNULL(state_ptr_type);
|
||||
const auto addr_space = state_ptr_type->getAddressSpace();
|
||||
|
||||
const auto state_type =
|
||||
llvm::dyn_cast<llvm::StructType>(state_ptr_type->getPointerElementType());
|
||||
CHECK_NOTNULL(state_type);
|
||||
const auto state_type = arch->state_type;
|
||||
|
||||
const auto module = ir.GetInsertBlock()->getParent()->getParent();
|
||||
const auto &dl = module->getDataLayout();
|
||||
|
||||
if (!gep_type_at_offset) {
|
||||
const_cast<Register *>(this)->CompteGEPAccessors(dl, state_type);
|
||||
const_cast<Register *>(this)->ComputeGEPAccessors(dl, state_type);
|
||||
}
|
||||
|
||||
llvm::Value *gep = nullptr;
|
||||
@@ -607,7 +604,7 @@ llvm::Value *Register::AddressOf(llvm::Value *state_ptr,
|
||||
|
||||
auto state_size = dl.getTypeAllocSize(state_type);
|
||||
auto ret = FinishAddressOf(
|
||||
ir, dl, state_ptr_type, state_size, this, addr_space, gep);
|
||||
ir, dl, state_type, state_size, this, addr_space, gep);
|
||||
|
||||
// Add the metadata to `inst`.
|
||||
if (auto inst = llvm::dyn_cast<llvm::Instruction>(ret); inst) {
|
||||
@@ -722,7 +719,7 @@ void Arch::InitializeEmptyLiftedFunction(llvm::Function *func) const {
|
||||
// `FinishLiftedFunctionInitialization`.
|
||||
|
||||
ir.CreateStore(state,
|
||||
ir.CreateAlloca(llvm::PointerType::get(impl->state_type, 0),
|
||||
ir.CreateAlloca(llvm::PointerType::get(context, 0),
|
||||
nullptr, "STATE"));
|
||||
ir.CreateStore(memory,
|
||||
ir.CreateAlloca(impl->memory_type, nullptr, "MEMORY"));
|
||||
@@ -757,7 +754,7 @@ const Register *Arch::AddRegister(const char *reg_name_, llvm::Type *val_type,
|
||||
auto reg_impl = new Register(reg_name, offset, dl.getTypeAllocSize(val_type),
|
||||
val_type, parent_reg, impl.get());
|
||||
|
||||
reg_impl->CompteGEPAccessors(dl, impl->state_type);
|
||||
reg_impl->ComputeGEPAccessors(dl, impl->state_type);
|
||||
|
||||
reg = reg_impl;
|
||||
impl->registers.emplace_back(reg_impl);
|
||||
@@ -803,10 +800,7 @@ void Arch::InitFromSemanticsModule(llvm::Module *module) const {
|
||||
const auto &dl = module->getDataLayout();
|
||||
const auto basic_block = module->getFunction("__remill_jump");
|
||||
CHECK_NOTNULL(basic_block);
|
||||
const auto state_ptr_type =
|
||||
NthArgument(basic_block, kStatePointerArgNum)->getType();
|
||||
const auto state_type =
|
||||
llvm::dyn_cast<llvm::StructType>(state_ptr_type->getPointerElementType());
|
||||
const auto state_type = llvm::StructType::getTypeByName(module->getContext(), "struct.State");
|
||||
|
||||
impl->state_type = state_type;
|
||||
impl->reg_by_offset.resize(dl.getTypeAllocSize(state_type));
|
||||
|
||||
@@ -222,7 +222,7 @@ void SPARC32Arch::PopulateRegisterTable(void) const {
|
||||
|
||||
std::vector<llvm::Type *> window_types(33, u64);
|
||||
auto window_type = llvm::StructType::create(*context, "RegisterWindow");
|
||||
auto window_ptr_type = llvm::PointerType::get(window_type, 0);
|
||||
auto window_ptr_type = llvm::PointerType::get(*context, 0);
|
||||
window_types.push_back(window_ptr_type);
|
||||
window_type->setBody(window_types, false);
|
||||
|
||||
@@ -404,7 +404,7 @@ void SPARC32Arch::FinishLiftedFunctionInitialization(
|
||||
// a structure type, so we can check that.
|
||||
const auto prev_window_link = RegisterByName("PREV_WINDOW_LINK");
|
||||
CHECK(prev_window_link->type->isPointerTy());
|
||||
const auto window_type = prev_window_link->type->getPointerElementType();
|
||||
const auto window_type = llvm::StructType::getTypeByName(context, "RegisterWindow");
|
||||
CHECK(window_type->isStructTy());
|
||||
|
||||
auto window = ir.CreateAlloca(window_type, nullptr, "WINDOW");
|
||||
|
||||
@@ -129,7 +129,7 @@ void SPARC64Arch::PopulateRegisterTable(void) const {
|
||||
|
||||
std::vector<llvm::Type *> window_types(33, u64);
|
||||
auto window_type = llvm::StructType::create(*context, "RegisterWindow");
|
||||
auto window_ptr_type = llvm::PointerType::get(window_type, 0);
|
||||
auto window_ptr_type = llvm::PointerType::get(*context, 0);
|
||||
window_types.push_back(window_ptr_type);
|
||||
window_type->setBody(window_types, false);
|
||||
|
||||
@@ -376,7 +376,7 @@ void SPARC64Arch::FinishLiftedFunctionInitialization(
|
||||
// a structure type, so we can check that.
|
||||
const auto prev_window_link = this->RegisterByName("PREV_WINDOW_LINK");
|
||||
CHECK(prev_window_link->type->isPointerTy());
|
||||
const auto window_type = prev_window_link->type->getPointerElementType();
|
||||
const auto window_type = llvm::StructType::getTypeByName(context, "RegisterWindow");
|
||||
CHECK(window_type->isStructTy());
|
||||
|
||||
auto window = ir.CreateAlloca(window_type, nullptr, "WINDOW");
|
||||
|
||||
@@ -328,7 +328,8 @@ llvm::Value *InstructionLifter::LoadRegValue(llvm::BasicBlock *block,
|
||||
std::string_view reg_name) const {
|
||||
auto ptr = LoadRegAddress(block, state_ptr, reg_name);
|
||||
CHECK_NOTNULL(ptr);
|
||||
auto ptr_ty = ptr->getType()->getPointerElementType();
|
||||
// NOTE(alex): This isn't right. Not sure how to solve this right now.
|
||||
auto ptr_ty = impl->word_type;
|
||||
return new llvm::LoadInst(ptr_ty, ptr, llvm::Twine::createNull(), block);
|
||||
}
|
||||
|
||||
|
||||
+4
-8
@@ -935,9 +935,8 @@ RecontextualizeType(llvm::Type *type, llvm::LLVMContext &context,
|
||||
|
||||
case llvm::Type::PointerTyID: {
|
||||
auto ptr_type = llvm::dyn_cast<llvm::PointerType>(type);
|
||||
auto elem_type = PointerElementType(ptr_type);
|
||||
cached =
|
||||
llvm::PointerType::get(RecontextualizeType(elem_type, context, cache),
|
||||
llvm::PointerType::get(context,
|
||||
ptr_type->getAddressSpace());
|
||||
break;
|
||||
}
|
||||
@@ -1588,8 +1587,6 @@ static void MoveInstructionIntoModule(llvm::Instruction *inst,
|
||||
auto dest_func_type = llvm::dyn_cast<llvm::FunctionType>(
|
||||
RecontextualizeType(
|
||||
call->getFunctionType(), dest_module->getContext(), type_map));
|
||||
CHECK_EQ(new_callee_val->getType()->getPointerElementType(),
|
||||
dest_func_type);
|
||||
llvm::FunctionCallee callee(dest_func_type, new_callee_val);
|
||||
call->setCalledFunction(callee);
|
||||
}
|
||||
@@ -2009,7 +2006,7 @@ llvm::Value *LoadFromMemory(const IntrinsicTable &intrinsics,
|
||||
auto i8_array =
|
||||
llvm::ArrayType::get(llvm::Type::getInt8Ty(context), size);
|
||||
auto byte_array =
|
||||
ir.CreateBitCast(res, llvm::PointerType::get(i8_array, 0));
|
||||
ir.CreateBitCast(res, llvm::PointerType::get(context, 0));
|
||||
|
||||
auto gep_zero = llvm::ConstantInt::get(index_type, 0, false);
|
||||
// Load one byte at a time from memory, and store it into
|
||||
@@ -2192,7 +2189,7 @@ llvm::Value *StoreToMemory(const IntrinsicTable &intrinsics,
|
||||
auto i8 = llvm::Type::getInt8Ty(context);
|
||||
auto i8_array = llvm::ArrayType::get(i8, size);
|
||||
auto byte_array =
|
||||
ir.CreateBitCast(res, llvm::PointerType::get(i8_array, 0));
|
||||
ir.CreateBitCast(res, llvm::PointerType::get(context, 0));
|
||||
llvm::Value *gep_indices[2] = {
|
||||
llvm::ConstantInt::get(index_type, 0, false), nullptr};
|
||||
|
||||
@@ -2424,8 +2421,7 @@ llvm::Value *BuildPointerToOffset(llvm::IRBuilder<> &ir, llvm::Value *ptr,
|
||||
|
||||
// Change address spaces if necessary before indexing.
|
||||
if (dest_ptr_addr_space != ptr_addr_space) {
|
||||
ptr_type = llvm::PointerType::get(ptr_type->getPointerElementType(),
|
||||
dest_ptr_addr_space);
|
||||
ptr_type = llvm::PointerType::get(context, dest_ptr_addr_space);
|
||||
ptr_addr_space = dest_ptr_addr_space;
|
||||
|
||||
if (constant_ptr) {
|
||||
|
||||
Reference in New Issue
Block a user