From ab03a02dbc838224dfd7e02756270177c9dff9e4 Mon Sep 17 00:00:00 2001 From: Francesco Bertolaccini Date: Fri, 2 Dec 2022 18:00:15 +0100 Subject: [PATCH] Add APIs that allow specifying an insertion point (#642) --- include/remill/BC/Util.h | 33 ++++++++++++++---- lib/BC/Util.cpp | 73 ++++++++++++++++++++++++++-------------- 2 files changed, 75 insertions(+), 31 deletions(-) diff --git a/include/remill/BC/Util.h b/include/remill/BC/Util.h index f9ae2f4d..8f36bbff 100644 --- a/include/remill/BC/Util.h +++ b/include/remill/BC/Util.h @@ -30,6 +30,8 @@ // clang-format on +#include + #include #include #include @@ -39,8 +41,6 @@ #include #include -#include - 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 VerifyModuleMsg(llvm::Module *module); -std::unique_ptr LoadModuleFromFile(llvm::LLVMContext *context, - std::filesystem::path file_name); +std::unique_ptr +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 FindSemanticsBitcodeFile(std::string_view arch); +std::optional +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 FindSemanticsBitcodeFile(std::string_view arch, const std::vector &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); diff --git a/lib/BC/Util.cpp b/lib/BC/Util.cpp index e43c2a20..cf21555d 100644 --- a/lib/BC/Util.cpp +++ b/lib/BC/Util.cpp @@ -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(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(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(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(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(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(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(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; }