retdec
Public Types | Public Member Functions | Static Public Member Functions | Protected Member Functions | Protected Attributes | List of all members
retdec::bin2llvmir::IrModifier Class Reference

#include <ir_modifier.h>

Collaboration diagram for retdec::bin2llvmir::IrModifier:
Collaboration graph
[legend]

Public Types

using FunctionPair = std::pair< llvm::Function *, retdec::common::Function * >
 
using StackPair = std::pair< llvm::AllocaInst *, const retdec::common::Object * >
 

Public Member Functions

 IrModifier (llvm::Module *m, Config *c)
 
FunctionPair renameFunction (llvm::Function *fnc, const std::string &fncName)
 
StackPair getStackVariable (llvm::Function *fnc, int offset, llvm::Type *type, const std::string &name=std::string(), const std::string &realName=std::string(), bool fromDebug=false)
 
llvm::GlobalVariable * getGlobalVariable (FileImage *objf, DebugFormat *dbgf, retdec::common::Address addr, bool strict=false, const std::string &name=std::string())
 
llvm::Value * changeObjectType (FileImage *objf, llvm::Value *val, llvm::Type *toType, llvm::Constant *init=nullptr, std::unordered_set< llvm::Instruction * > *instToErase=nullptr, bool dbg=false, bool wideString=false)
 
FunctionPair modifyFunction (llvm::Function *fnc, llvm::Type *ret, std::vector< llvm::Type * > args, bool isVarArg=false, const std::map< llvm::ReturnInst *, llvm::Value * > &rets2vals=std::map< llvm::ReturnInst *, llvm::Value * >(), const std::map< llvm::CallInst *, std::vector< llvm::Value * >> &calls2vals=std::map< llvm::CallInst *, std::vector< llvm::Value * >>(), llvm::Value *retVal=nullptr, const std::vector< llvm::Value * > &argStores=std::vector< llvm::Value * >(), const std::vector< std::string > &argNames=std::vector< std::string >())
 
llvm::Argument * modifyFunctionArgumentType (llvm::Argument *arg, llvm::Type *type)
 

Static Public Member Functions

static llvm::AllocaInst * createAlloca (llvm::Function *fnc, llvm::Type *ty, const std::string &name=std::string())
 
static llvm::Value * convertValueToType (llvm::Value *val, llvm::Type *type, llvm::Instruction *before)
 
static llvm::Value * convertValueToTypeAfter (llvm::Value *val, llvm::Type *type, llvm::Instruction *after)
 
static llvm::Constant * convertConstantToType (llvm::Constant *val, llvm::Type *type)
 
static llvm::CallInst * modifyCallInst (llvm::CallInst *call, llvm::Type *ret, llvm::ArrayRef< llvm::Value * > args)
 
static void eraseUnusedInstructionRecursive (llvm::Value *insn)
 
static void eraseUnusedInstructionsRecursive (std::unordered_set< llvm::Value * > &insns)
 

Protected Member Functions

llvm::Value * changeObjectDeclarationType (FileImage *objf, llvm::Value *val, llvm::Type *toType, llvm::Constant *init=nullptr, bool wideString=false)
 

Protected Attributes

llvm::Module * _module = nullptr
 
Config_config = nullptr
 

Member Typedef Documentation

◆ FunctionPair

◆ StackPair

using retdec::bin2llvmir::IrModifier::StackPair = std::pair<llvm::AllocaInst*, const retdec::common::Object*>

Constructor & Destructor Documentation

◆ IrModifier()

retdec::bin2llvmir::IrModifier::IrModifier ( llvm::Module *  m,
Config c 
)

Member Function Documentation

◆ changeObjectDeclarationType()

llvm::Value * retdec::bin2llvmir::IrModifier::changeObjectDeclarationType ( FileImage objf,
llvm::Value *  val,
llvm::Type *  toType,
llvm::Constant *  init = nullptr,
bool  wideString = false 
)
protected

Change val declaration to toType. Only the object type is changed, not its usages. Because of this, it is not safe to use this function alone. This function is not public, i.e. accessible from other modules.

Parameters
objfObject file for this object – needed to initialize it values.
valValue which type to change.
toTypeType to change it to.
initInitializer constant.
wideStringIs type a wide string?
Returns
New value with a desired type. This may be the same as val if value's type can be mutated, or a new object if it cannot.

◆ changeObjectType()

llvm::Value * retdec::bin2llvmir::IrModifier::changeObjectType ( FileImage objf,
llvm::Value *  val,
llvm::Type *  toType,
llvm::Constant *  init = nullptr,
std::unordered_set< llvm::Instruction * > *  instToErase = nullptr,
bool  dbg = false,
bool  wideString = false 
)

Change val type to toType and fix all its uses.

Parameters
objfObject file for this object – needed to initialize it values.
valValue which type to change.
toTypeType to change it to.
initInitializer constant.
instToEraseSome instructions may become obsolete. If pointer to this container is provided, function adds such instructions to it and it is up to the caller to erase them. Otherwise, function erases such instructions from parent. If caller does not have instructions saved, it is save to erase them here – pass nullptr. If caller is performing some analysis where it has instructions stored in internal structures and it is possible that they will be used after they would have been erased, it should pass pointer to container here and erase instructions when it is finished.
dbgFlag to enable debug messages.
wideStringIs type a wide string?

◆ convertConstantToType()

Constant * retdec::bin2llvmir::IrModifier::convertConstantToType ( llvm::Constant *  val,
llvm::Type *  type 
)
static

This is the same as convertValueToType() but working with constants. It does not insert constant expressions (type casts) to any particular place in the IR. It just returns the created constant expressions.

Parameters
valConstant value to convert.
typeType to convert to.
Returns
Constant expression representing type conversion.

◆ convertValueToType()

Value * retdec::bin2llvmir::IrModifier::convertValueToType ( llvm::Value *  val,
llvm::Type *  type,
llvm::Instruction *  before 
)
static

Create type conversion from provided value to provided type. Created instructions are inserted before the specified instruction.

Parameters
valValue to convert.
typeType to convert to.
beforeInstruction before which created conversion instructions are inserted.
Returns
Final value of the specified type.

◆ convertValueToTypeAfter()

llvm::Value * retdec::bin2llvmir::IrModifier::convertValueToTypeAfter ( llvm::Value *  val,
llvm::Type *  type,
llvm::Instruction *  after 
)
static

Create type conversion from provided value to provided type. Created instructions are inserted after the specified instruction.

Parameters
valValue to convert.
typeType to convert to.
afterInstruction after which created conversion instructions are inserted.
Returns
Final value of the specified type.

◆ createAlloca()

llvm::AllocaInst * retdec::bin2llvmir::IrModifier::createAlloca ( llvm::Function *  fnc,
llvm::Type *  ty,
const std::string &  name = std::string() 
)
static

◆ eraseUnusedInstructionRecursive()

void retdec::bin2llvmir::IrModifier::eraseUnusedInstructionRecursive ( llvm::Value *  insn)
static

Erase insn if it is an unused instruction, and also all its operands that are also unused instructions.

◆ eraseUnusedInstructionsRecursive()

void retdec::bin2llvmir::IrModifier::eraseUnusedInstructionsRecursive ( std::unordered_set< llvm::Value * > &  insns)
static

◆ getGlobalVariable()

GlobalVariable * retdec::bin2llvmir::IrModifier::getGlobalVariable ( FileImage objf,
DebugFormat dbgf,
retdec::common::Address  addr,
bool  strict = false,
const std::string &  name = std::string() 
)

Get global variable from the given address addr in objf input file.

Parameters
objfObject file.
dbgfDebug file.
addrAddress of the global variable in the objf.
strictBe stricter when determining if variable can be created.
nameName to use. Global's address is always appended to this name.
Returns
Global variable on the given address, or nullptr.

TODO: there is many more things to do here:

  • create second similar method taking global variable type, or add default parameter to this method. if type specified, it is forced.
  • check that such global variable does not already exist, config is needed, if so, do not create new, use the old one
  • check debug info for variable on the specified address, if it exists, use name, type, ...
  • add/update info about this variable into config

◆ getStackVariable()

IrModifier::StackPair retdec::bin2llvmir::IrModifier::getStackVariable ( llvm::Function *  fnc,
int  offset,
llvm::Type *  type,
const std::string &  name = std::string(),
const std::string &  realName = std::string(),
bool  fromDebug = false 
)

Get or create&get stack variable.

Parameters
fncFunction owning the stack variable.
offsetStack varibale's offset.
typeStack varibale's type.
nameStack varibale's name in IR. If not set default name is used. Offset is always appended to this name. If you want to get this name to output C, set it as a real name to returned config stack variable entry.
realName
fromDebug
Returns
Pair of LLVM stack var (Alloca instruction) and associated config stack var.

◆ modifyCallInst()

llvm::CallInst * retdec::bin2llvmir::IrModifier::modifyCallInst ( llvm::CallInst *  call,
llvm::Type *  ret,
llvm::ArrayRef< llvm::Value * >  args 
)
static

Modify call instruction:

  • Old called value is casted to new function pointer type derived from return value and arguments. This is done even if called value is function. If you want to avoid casts, make sure called function's type is modified before this function is called and that arguments passed in args have same types as called function – they will not be casted, if they differ, function is casted to function pointer derived from them.
  • New function pointer type value is used to modify call instruction. Notes:
  • If ret is nullptr, call's return value is left unchanged. Pass void type in ret if you want the call to return no value.
  • If args is empty, call will have zero arguments.
    Returns
    New call instruction which replaced the old call. See _modifyCallInst() comment for details.

◆ modifyFunction()

IrModifier::FunctionPair retdec::bin2llvmir::IrModifier::modifyFunction ( llvm::Function *  fnc,
llvm::Type *  ret,
std::vector< llvm::Type * >  args,
bool  isVarArg = false,
const std::map< llvm::ReturnInst *, llvm::Value * > &  rets2vals = std::map<llvm::ReturnInst*, llvm::Value*>(),
const std::map< llvm::CallInst *, std::vector< llvm::Value * >> &  calls2vals = std::map<llvm::CallInst*, std::vector<llvm::Value*>>(),
llvm::Value *  retVal = nullptr,
const std::vector< llvm::Value * > &  argStores = std::vector<llvm::Value*>(),
const std::vector< std::string > &  argNames = std::vector<std::string>() 
)

Inspired by ArgPromotion::DoPromotion(). Steps performed in ArgPromotion::DoPromotion() that are not done here:

  • Patch the pointer to LLVM function in debug info descriptor.
  • Some attribute magic.
  • Update alias analysis.
  • Update call graph info.
    Returns
    New function that replaced the old one. Function type cannot be changed in situ -> we create an entirely new function with the desired type.

◆ modifyFunctionArgumentType()

llvm::Argument * retdec::bin2llvmir::IrModifier::modifyFunctionArgumentType ( llvm::Argument *  arg,
llvm::Type *  type 
)
Returns
New argument – function type cannot be changed in situ, we created an entirely new fuction with desired argument type.

◆ renameFunction()

IrModifier::FunctionPair retdec::bin2llvmir::IrModifier::renameFunction ( llvm::Function *  fnc,
const std::string &  fncName 
)

Member Data Documentation

◆ _config

Config* retdec::bin2llvmir::IrModifier::_config = nullptr
protected

◆ _module

llvm::Module* retdec::bin2llvmir::IrModifier::_module = nullptr
protected

The documentation for this class was generated from the following files: