WIP to support opaque pointers

This commit is contained in:
Alex Cameron
2022-05-31 12:40:11 +10:00
parent 85d287c4f8
commit fd82a20a20
8 changed files with 36 additions and 53 deletions
+2 -3
View File
@@ -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(
+1 -1
View File
@@ -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 {
+3 -10
View File
@@ -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
View File
@@ -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));
+2 -2
View File
@@ -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");
+2 -2
View File
@@ -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");
+2 -1
View File
@@ -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
View File
@@ -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) {