Add APIs that allow specifying an insertion point (#642)

This commit is contained in:
Francesco Bertolaccini
2022-12-02 18:00:15 +01:00
committed by GitHub
parent a8ead7b584
commit ab03a02dbc
2 changed files with 75 additions and 31 deletions
+27 -6
View File
@@ -30,6 +30,8 @@
// clang-format on
#include <remill/BC/ABI.h>
#include <array>
#include <filesystem>
#include <functional>
@@ -39,8 +41,6 @@
#include <unordered_map>
#include <vector>
#include <remill/BC/ABI.h>
namespace llvm {
class Argument;
class BasicBlock;
@@ -68,6 +68,10 @@ class IntrinsicTable;
void InitFunctionAttributes(llvm::Function *F);
// Create a call from one lifted function to another.
llvm::CallInst *AddCall(llvm::IRBuilder<> &builder,
llvm::BasicBlock *source_block, llvm::Value *dest_func,
const IntrinsicTable &intrinsics);
llvm::CallInst *AddCall(llvm::BasicBlock *source_block, llvm::Value *dest_func,
const IntrinsicTable &intrinsics);
@@ -98,6 +102,9 @@ llvm::Value *LoadStatePointer(llvm::Function *function);
llvm::Value *LoadStatePointer(llvm::BasicBlock *block);
// Return the current program counter.
llvm::Value *LoadProgramCounter(llvm::IRBuilder<> &builder,
const IntrinsicTable &intrinsics);
llvm::Value *LoadProgramCounter(llvm::BasicBlock *block,
const IntrinsicTable &intrinsics);
@@ -131,6 +138,9 @@ llvm::Value *LoadMemoryPointerArg(llvm::Function *func);
llvm::Value *LoadProgramCounterArg(llvm::Function *function);
// Return the current memory pointer.
llvm::Value *LoadMemoryPointer(llvm::IRBuilder<> &builder,
const IntrinsicTable &intrinsics);
llvm::Value *LoadMemoryPointer(llvm::BasicBlock *block,
const IntrinsicTable &intrinsics);
@@ -139,6 +149,7 @@ llvm::Value *LoadMemoryPointerRef(llvm::BasicBlock *block);
// Return an `llvm::Value *` that is an `i1` (bool type) representing whether
// or not a conditional branch is taken.
llvm::Value *LoadBranchTaken(llvm::IRBuilder<> &builder);
llvm::Value *LoadBranchTaken(llvm::BasicBlock *block);
llvm::Value *LoadBranchTakenRef(llvm::BasicBlock *block);
@@ -155,8 +166,8 @@ bool VerifyModule(llvm::Module *module);
std::optional<std::string> VerifyModuleMsg(llvm::Module *module);
std::unique_ptr<llvm::Module> LoadModuleFromFile(llvm::LLVMContext *context,
std::filesystem::path file_name);
std::unique_ptr<llvm::Module>
LoadModuleFromFile(llvm::LLVMContext *context, std::filesystem::path file_name);
// Loads the semantics for the `arch`-specific machine, i.e. the machine of the
// code that we want to lift.
@@ -176,14 +187,15 @@ bool StoreModuleIRToFile(llvm::Module *module, std::string_view file_name,
// Find a semantics bitcode file for the architecture `arch`.
// Default compile-time created list of directories is searched.
std::optional<std::filesystem::path> FindSemanticsBitcodeFile(std::string_view arch);
std::optional<std::filesystem::path>
FindSemanticsBitcodeFile(std::string_view arch);
// List of directories to search is provided as second argument - default compile time
// created list is used as fallback only if `fallback_to_defaults` is set.
// A "shallow" search happens, searching for file `arch` + ".bc".
std::optional<std::filesystem::path>
FindSemanticsBitcodeFile(std::string_view arch,
const std::vector<std::filesystem::path> &dirs,
bool fallback_to_defaults=true);
bool fallback_to_defaults = true);
// Return a pointer to the Nth argument (N=0 is the first argument).
llvm::Argument *NthArgument(llvm::Function *func, size_t index);
@@ -247,6 +259,10 @@ llvm::Type *RecontextualizeType(llvm::Type *type, llvm::LLVMContext &context);
// recursively build up the right type.
//
// Returns the loaded value.
llvm::Value *LoadFromMemory(const IntrinsicTable &intrinsics,
llvm::IRBuilder<> &builder, llvm::Type *type,
llvm::Value *mem_ptr, llvm::Value *addr);
llvm::Value *LoadFromMemory(const IntrinsicTable &intrinsics,
llvm::BasicBlock *block, llvm::Type *type,
llvm::Value *mem_ptr, llvm::Value *addr);
@@ -257,6 +273,11 @@ llvm::Value *LoadFromMemory(const IntrinsicTable &intrinsics,
// the type into components which can be written to memory.
//
// Returns the new value of the memory pointer.
llvm::Value *StoreToMemory(const IntrinsicTable &intrinsics,
llvm::IRBuilder<> &builder,
llvm::Value *val_to_store, llvm::Value *mem_ptr,
llvm::Value *addr);
llvm::Value *StoreToMemory(const IntrinsicTable &intrinsics,
llvm::BasicBlock *block, llvm::Value *val_to_store,
llvm::Value *mem_ptr, llvm::Value *addr);
+48 -25
View File
@@ -146,6 +146,12 @@ void InitFunctionAttributes(llvm::Function *function) {
llvm::CallInst *AddCall(llvm::BasicBlock *source_block, llvm::Value *dest_func,
const IntrinsicTable &intrinsics) {
llvm::IRBuilder<> ir(source_block);
return AddCall(ir, source_block, dest_func, intrinsics);
}
llvm::CallInst *AddCall(llvm::IRBuilder<> &ir, llvm::BasicBlock *source_block,
llvm::Value *dest_func,
const IntrinsicTable &intrinsics) {
auto args = LiftedFunctionArgs(source_block, intrinsics);
if (auto func = llvm::dyn_cast<llvm::Function>(dest_func); func) {
return ir.CreateCall(func, args);
@@ -280,7 +286,13 @@ llvm::Value *LoadStatePointer(llvm::BasicBlock *block) {
llvm::Value *LoadProgramCounter(llvm::BasicBlock *block,
const IntrinsicTable &intrinsics) {
llvm::IRBuilder<> ir(block);
return ir.CreateLoad(intrinsics.pc_type, LoadProgramCounterRef(block));
return LoadProgramCounter(ir, intrinsics);
}
llvm::Value *LoadProgramCounter(llvm::IRBuilder<> &ir,
const IntrinsicTable &intrinsics) {
return ir.CreateLoad(intrinsics.pc_type,
LoadProgramCounterRef(ir.GetInsertBlock()));
}
// Return a reference to the current program counter.
@@ -327,13 +339,24 @@ void StoreProgramCounter(llvm::BasicBlock *block, uint64_t pc,
llvm::Value *LoadMemoryPointer(llvm::BasicBlock *block,
const IntrinsicTable &intrinsics) {
llvm::IRBuilder<> ir(block);
return ir.CreateLoad(intrinsics.mem_ptr_type, LoadMemoryPointerRef(block));
return LoadMemoryPointer(ir, intrinsics);
}
llvm::Value *LoadMemoryPointer(llvm::IRBuilder<> &ir,
const IntrinsicTable &intrinsics) {
return ir.CreateLoad(intrinsics.mem_ptr_type,
LoadMemoryPointerRef(ir.GetInsertBlock()));
}
// Return an `llvm::Value *` that is an `i1` (bool type) representing whether
// or not a conditional branch is taken.
llvm::Value *LoadBranchTaken(llvm::BasicBlock *block) {
llvm::IRBuilder<> ir(block);
return LoadBranchTaken(ir);
}
llvm::Value *LoadBranchTaken(llvm::IRBuilder<> &ir) {
auto block = ir.GetInsertBlock();
auto i8_type = llvm::Type::getInt8Ty(block->getContext());
auto cond = ir.CreateLoad(
i8_type,
@@ -1844,12 +1867,19 @@ llvm::Type *RecontextualizeType(llvm::Type *type, llvm::LLVMContext &context) {
return RecontextualizeType(type, context, cache);
}
llvm::Value *LoadFromMemory(const IntrinsicTable &intrinsics,
llvm::BasicBlock *block, llvm::Type *type,
llvm::Value *mem_ptr, llvm::Value *addr) {
llvm::IRBuilder<> ir(block);
return LoadFromMemory(intrinsics, ir, type, mem_ptr, addr);
}
// Produce a sequence of instructions that will load values from
// memory, building up the correct type. This will invoke the various
// memory read intrinsics in order to match the right type, or
// recursively build up the right type.
llvm::Value *LoadFromMemory(const IntrinsicTable &intrinsics,
llvm::BasicBlock *block, llvm::Type *type,
llvm::IRBuilder<> &ir, llvm::Type *type,
llvm::Value *mem_ptr, llvm::Value *addr) {
const auto initial_addr = addr;
@@ -1859,8 +1889,6 @@ llvm::Value *LoadFromMemory(const IntrinsicTable &intrinsics,
llvm::Value *args_2[2] = {mem_ptr, addr};
auto index_type = llvm::Type::getIntNTy(context, dl.getPointerSizeInBits(0));
llvm::IRBuilder<> ir(block);
switch (type->getTypeID()) {
case llvm::Type::HalfTyID: {
llvm::Type *types[] = {llvm::Type::getFloatTy(context)};
@@ -1940,8 +1968,7 @@ llvm::Value *LoadFromMemory(const IntrinsicTable &intrinsics,
addr = ir.CreateAdd(initial_addr, llvm::ConstantInt::get(
addr->getType(), offset, false));
auto elem_val =
LoadFromMemory(intrinsics, block, elem_type, mem_ptr, addr);
ir.SetInsertPoint(block);
LoadFromMemory(intrinsics, ir, elem_type, mem_ptr, addr);
unsigned indexes[] = {i};
val = ir.CreateInsertValue(val, elem_val, indexes);
}
@@ -1962,8 +1989,7 @@ llvm::Value *LoadFromMemory(const IntrinsicTable &intrinsics,
addr->getType(), offset, false));
unsigned indexes[] = {static_cast<unsigned>(index)};
auto elem_val =
LoadFromMemory(intrinsics, block, elem_type, mem_ptr, addr);
ir.SetInsertPoint(block);
LoadFromMemory(intrinsics, ir, elem_type, mem_ptr, addr);
val = ir.CreateInsertValue(val, elem_val, indexes);
}
return val;
@@ -1977,8 +2003,7 @@ llvm::Value *LoadFromMemory(const IntrinsicTable &intrinsics,
auto intptr_type =
llvm::IntegerType::get(context, static_cast<unsigned>(size_bits));
auto addr_val =
LoadFromMemory(intrinsics, block, intptr_type, mem_ptr, addr);
ir.SetInsertPoint(block);
LoadFromMemory(intrinsics, ir, intptr_type, mem_ptr, addr);
return ir.CreateIntToPtr(addr_val, ptr_type);
}
@@ -1995,8 +2020,7 @@ llvm::Value *LoadFromMemory(const IntrinsicTable &intrinsics,
addr = ir.CreateAdd(initial_addr, llvm::ConstantInt::get(
addr->getType(), offset, false));
auto elem_val =
LoadFromMemory(intrinsics, block, elem_type, mem_ptr, addr);
ir.SetInsertPoint(block);
LoadFromMemory(intrinsics, ir, elem_type, mem_ptr, addr);
val =
ir.CreateInsertElement(val, elem_val, static_cast<unsigned>(index));
}
@@ -2024,6 +2048,13 @@ llvm::Value *LoadFromMemory(const IntrinsicTable &intrinsics,
llvm::Value *StoreToMemory(const IntrinsicTable &intrinsics,
llvm::BasicBlock *block, llvm::Value *val_to_store,
llvm::Value *mem_ptr, llvm::Value *addr) {
llvm::IRBuilder<> ir(block);
return StoreToMemory(intrinsics, ir, val_to_store, mem_ptr, addr);
}
llvm::Value *StoreToMemory(const IntrinsicTable &intrinsics,
llvm::IRBuilder<> &ir, llvm::Value *val_to_store,
llvm::Value *mem_ptr, llvm::Value *addr) {
const auto initial_addr = addr;
auto module = intrinsics.error->getParent();
@@ -2032,8 +2063,6 @@ llvm::Value *StoreToMemory(const IntrinsicTable &intrinsics,
llvm::Value *args_3[3] = {mem_ptr, addr, val_to_store};
auto index_type = llvm::Type::getInt32Ty(context);
llvm::IRBuilder<> ir(block);
auto type = val_to_store->getType();
switch (type->getTypeID()) {
case llvm::Type::HalfTyID: {
@@ -2120,9 +2149,7 @@ llvm::Value *StoreToMemory(const IntrinsicTable &intrinsics,
llvm::ConstantInt::get(addr->getType(), offset, false));
unsigned indexes[] = {i};
const auto elem_val = ir.CreateExtractValue(val_to_store, indexes);
mem_ptr =
StoreToMemory(intrinsics, block, elem_val, mem_ptr, elem_addr);
ir.SetInsertPoint(block);
mem_ptr = StoreToMemory(intrinsics, ir, elem_val, mem_ptr, elem_addr);
}
return mem_ptr;
}
@@ -2142,9 +2169,7 @@ llvm::Value *StoreToMemory(const IntrinsicTable &intrinsics,
llvm::ConstantInt::get(addr->getType(), offset, false));
unsigned indexes[] = {static_cast<unsigned>(index)};
auto elem_val = ir.CreateExtractValue(val_to_store, indexes);
mem_ptr =
StoreToMemory(intrinsics, block, elem_val, mem_ptr, elem_addr);
ir.SetInsertPoint(block);
mem_ptr = StoreToMemory(intrinsics, ir, elem_val, mem_ptr, elem_addr);
offset += elem_size;
index += 1;
}
@@ -2158,7 +2183,7 @@ llvm::Value *StoreToMemory(const IntrinsicTable &intrinsics,
auto size_bits = dl.getTypeAllocSizeInBits(ptr_type);
auto intptr_type =
llvm::IntegerType::get(context, static_cast<unsigned>(size_bits));
return StoreToMemory(intrinsics, block,
return StoreToMemory(intrinsics, ir,
ir.CreatePtrToInt(val_to_store, intptr_type),
mem_ptr, addr);
}
@@ -2178,9 +2203,7 @@ llvm::Value *StoreToMemory(const IntrinsicTable &intrinsics,
llvm::ConstantInt::get(addr->getType(), offset, false));
auto elem_val =
ir.CreateExtractElement(val_to_store, static_cast<unsigned>(index));
mem_ptr =
StoreToMemory(intrinsics, block, elem_val, mem_ptr, elem_addr);
ir.SetInsertPoint(block);
mem_ptr = StoreToMemory(intrinsics, ir, elem_val, mem_ptr, elem_addr);
offset += elem_size;
index += 1;
}