mirror of
https://github.com/lifting-bits/remill
synced 2026-06-21 13:56:07 +00:00
Add APIs that allow specifying an insertion point (#642)
This commit is contained in:
committed by
GitHub
parent
a8ead7b584
commit
ab03a02dbc
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user