symbolic_tree: fix WIP

This commit is contained in:
Peter Kubov 2019-09-22 02:19:39 +02:00
parent 33c02796fe
commit 2a374d918a
10 changed files with 990 additions and 260 deletions

View File

@ -10,6 +10,7 @@
#include <vector>
#include "retdec/bin2llvmir/providers/calling_convention/calling_convention.h"
#include "retdec/utils/value.h"
#include <llvm/IR/Function.h>
#include <llvm/IR/Instructions.h>
@ -17,6 +18,105 @@
namespace retdec {
namespace bin2llvmir {
class ArgumentEntry
{
public:
typedef std::shared_ptr<ArgumentEntry> Ptr;
protected:
ArgumentEntry();
ArgumentEntry(
llvm::Type* type = nullptr,
const std::string& name = "");
public:
void setType(llvm::Type* type);
void setName(const std::string& name);
std::pair<llvm::Value*, llvm::Type*> get(
llvm::Function* fnc,
const Abi& a) const;
std::pair<llvm::Value*, std::string> get(
llvm::Function* fnc,
const Abi& a,
const std::string& suffix,
const std::string& base = "") const;
llvm::Type* getType(llvm::Function* fnc, const Abi& a) const;
llvm::Value* getValue(llvm::Function* fnc, const Abi& a) const;
bool isDefined(llvm::Function* fnc, const Abi& a) const;
std::string getName(
llvm::Function* fnc,
const Abi& a,
const std::string& suffix = "",
const std::string& base = "") const;
protected:
virtual llvm::Value* fetchArgValue(
llvm::Function* fnc,
const Abi& a) const;
virtual std::string createName(
llvm::Function* fnc,
const Abi& a,
const std::string& suffix = "",
const std::string& base = "") const;
private:
llvm::Type* _type = nullptr;
std::string _name = "";
};
class DummyArgumentEntry: public ArgumentEntry {
public:
DummyArgumentEntry(
llvm::Type* type = nullptr,
const std::string& name = "");
~DummyArgumentEntry();
};
template<typename ArgID>
class ArgumentEntryImpl : public ArgumentEntry
{
public:
ArgumentEntryImpl(
ArgID argid,
llvm::Type* type = nullptr,
const std::string& name = "");
~ArgumentEntryImpl();
virtual llvm::Value* fetchArgValue(
llvm::Function* fnc,
const Abi& a) const override;
virtual std::string createName(
llvm::Function* fnc,
const Abi& a,
const std::string& suffix = "",
const std::string& base = "") const override;
private:
ArgID _argid;
};
template class ArgumentEntryImpl<int>;
typedef ArgumentEntryImpl<int> StackArgumentEntry;
template class ArgumentEntryImpl<std::size_t>;
typedef ArgumentEntryImpl<std::size_t> FunctionArgumentEntry;
template class ArgumentEntryImpl<unsigned int>;
typedef ArgumentEntryImpl<unsigned int> RegisterArgumentEntry;
template class ArgumentEntryImpl<llvm::Constant*>;
typedef ArgumentEntryImpl<llvm::Constant*> ConstantArgumentEntry;
class ReturnEntry
{
public:
@ -172,6 +272,10 @@ class DataFlowEntry : public FunctionEntry
const std::vector<CallEntry>& callEntries() const;
std::vector<CallEntry>& callEntries();
std::vector<ArgumentEntry::Ptr> tmpArgs;
std::map<llvm::ReturnInst*, llvm::Value*> rets2vals;
std::map<llvm::CallInst*, std::vector<ArgumentEntry::Ptr>> loadsOfCalls;
private:
llvm::Value* _calledValue = nullptr;

View File

@ -91,11 +91,15 @@ class ParamReturn : public llvm::ModulePass
private:
void applyToIr();
void applyToIr(DataFlowEntry& de);
void applyToIrRef(DataFlowEntry& de);
void connectWrappers(const DataFlowEntry& de);
std::map<llvm::CallInst*, std::vector<ArgumentEntry::Ptr>> fetchArgsOfCalls(
const std::vector<CallEntry>& calls) const;
std::map<llvm::CallInst*, std::vector<llvm::Value*>> fetchLoadsOfCalls(
const std::vector<CallEntry>& calls) const;
private:
llvm::Module* _module = nullptr;
Config* _config = nullptr;

View File

@ -10,6 +10,7 @@
#include <llvm/IR/Instructions.h>
#include <llvm/IR/Module.h>
#include "retdec/bin2llvmir/optimizations/param_return/data_entries.h" //TODO: This should be moved to .*/providers/
#include "retdec/bin2llvmir/providers/abi/abi.h"
#include "retdec/bin2llvmir/providers/config.h"
#include "retdec/bin2llvmir/providers/fileimage.h"
@ -90,6 +91,15 @@ class IrModifier
bool wideString = false);
FunctionPair modifyFunction(
llvm::Function* fnc,
llvm::Type* ret,
llvm::Value* retVal = nullptr,
const std::vector<ArgumentEntry::Ptr>& args = {},
const std::map<llvm::ReturnInst*, llvm::Value*>& rets2vals = {},
const std::map<llvm::CallInst*, std::vector<ArgumentEntry::Ptr>>& calls2args = {},
bool isVarArg = false);
FunctionPair modifyFunctionOld(
llvm::Function* fnc,
llvm::Type* ret,
std::vector<llvm::Type*> args,
@ -110,6 +120,25 @@ class IrModifier
llvm::Value* convertToStructure(
llvm::Value* gv,
llvm::StructType* strType);
llvm::Value* convertToPointer(
llvm::Value* gv,
std::size_t ptrDepth);
llvm::Value* createStructureFromStacks(
llvm::AllocaInst* startStack,
llvm::StructType* strType,
int offset,
llvm::Instruction* before,
llvm::InsertValueInst* newStructure = nullptr,
std::vector<unsigned int>idxs = {});
llvm::Value* extractStructureToStacks(
llvm::AllocaInst* startStack,
llvm::StructType* strType,
int offset,
llvm::Instruction* before,
llvm::InsertValueInst* newStructure = nullptr,
std::vector<unsigned int>idxs = {});
protected:
llvm::Value* changeObjectDeclarationType(
FileImage* objf,

View File

@ -128,7 +128,9 @@ BIN2LLVMIR_PARAMS = [
'-inst-opt',
'-cond-branch-opt',
'-syscalls',
'-dump-module',
'-stack',
'-dump-module',
'-constants',
'-dump-module',
'-param-return',

View File

@ -377,6 +377,7 @@ void SymbolicTree::_simplifyNode()
Value* val = nullptr;
LoadInst* load = nullptr;
GlobalVariable* global = nullptr;
AllocaInst* local = nullptr;
ConstantInt* c1 = nullptr;
ConstantInt* c2 = nullptr;
@ -418,6 +419,11 @@ void SymbolicTree::_simplifyNode()
{
*this = std::move(ops[0]);
}
else if (match(*this, m_Load(m_ConstantInt(c1), &load)))
{
std::cout << "You are genius!" << std::endl;
*this = std::move(ops[0]);
}
else if (match(*this, m_Add(m_ConstantInt(c1), m_ConstantInt(c2))))
{
value = ConstantInt::get(
@ -456,6 +462,15 @@ void SymbolicTree::_simplifyNode()
ops.clear();
}
}
else if (match(*this, m_Add(m_Value(val), m_ConstantInt(c1)))
&& _config->isStackVariable(val))
{
auto offset = _config->getStackVariableOffset(val);
value = ConstantInt::get(
c1->getType(),
c1->getSExtValue() + offset);
ops.clear();
}
else if (match(*this, m_Add(m_Value(), m_Zero()))
|| match(*this, m_Sub(m_Value(), m_Zero())))
{
@ -475,6 +490,15 @@ void SymbolicTree::_simplifyNode()
c1->getType(),
c1->getSExtValue() + c2->getSExtValue());
}
else if (match(*this, m_Add(m_Value(val), m_ConstantInt(c1)))
&& _config->isStackVariable(val))
{
auto offset = _config->getStackVariableOffset(val);
value = ConstantInt::get(
c1->getType(),
c1->getSExtValue() + offset);
ops.clear();
}
// Move Constants from ops[0] to ops[1].
//

View File

@ -5,14 +5,209 @@
*/
#include <set>
#include <tuple>
#include "retdec/bin2llvmir/optimizations/param_return/data_entries.h"
#include "retdec/bin2llvmir/providers/abi/abi.h"
using namespace llvm;
namespace retdec {
namespace bin2llvmir {
//
//=============================================================================
// ArgumentEntryImpl
//=============================================================================
//
ArgumentEntry::ArgumentEntry(llvm::Type* type, const std::string& name):
_type(type),
_name(name)
{
}
std::pair<Value*, Type*> ArgumentEntry::get(Function* fnc, const Abi& a) const
{
return {getValue(fnc, a), getType(fnc, a)};
}
std::pair<Value*, std::string> ArgumentEntry::get(
Function* fnc,
const Abi& a,
const std::string& suffix,
const std::string& base) const
{
return {getValue(fnc, a), getName(fnc, a, suffix, base)};
}
std::string ArgumentEntry::getName(
Function* fnc,
const Abi& a,
const std::string& suffix,
const std::string& base) const
{
if (!_name.empty())
{
return _name;
}
std::string newBase = base.empty() ? "arg":base;
return createName(fnc, a, suffix, newBase);
}
Value* ArgumentEntry::getValue(Function* fnc, const Abi& a) const
{
Value* val = fetchArgValue(fnc, a);
return val ? val : a.getConfig()->getGlobalDummy();
}
bool ArgumentEntry::isDefined(Function* fnc, const Abi& a) const
{
return fetchArgValue(fnc, a) != nullptr;
}
Type* ArgumentEntry::getType(Function* fnc, const Abi& a) const
{
if (_type)
{
return _type;
}
auto* val = getValue(fnc, a);
assert(val && val->getType()->isPointerTy());
return val->getType()->getPointerElementType();
}
llvm::Value* ArgumentEntry::fetchArgValue(llvm::Function* fnc, const Abi& a) const
{
return nullptr;
}
std::string ArgumentEntry::createName(
llvm::Function* fnc,
const Abi& a,
const std::string& suffix,
const std::string& base) const
{
return base+suffix;
}
void ArgumentEntry::setType(Type* type)
{
_type = FunctionType::isValidArgumentType(type) ?
type : nullptr;
}
DummyArgumentEntry::DummyArgumentEntry(
llvm::Type* type,
const std::string& name):
ArgumentEntry(type, name)
{
}
DummyArgumentEntry::~DummyArgumentEntry()
{
}
template<typename ArgID>
ArgumentEntryImpl<ArgID>::ArgumentEntryImpl(
ArgID argid,
llvm::Type* type,
const std::string& name):
ArgumentEntry(type, name)
{
_argid = argid;
}
template<typename ArgID>
ArgumentEntryImpl<ArgID>::~ArgumentEntryImpl()
{
}
template<>
Value* StackArgumentEntry::fetchArgValue(Function* fnc, const Abi& a) const
{
return a.getConfig()->getLlvmStackVariable(fnc, _argid);
}
template<>
Value* RegisterArgumentEntry::fetchArgValue(Function* fnc, const Abi& a) const
{
return a.getRegister(_argid);
}
template<>
Value* FunctionArgumentEntry::fetchArgValue(Function* fnc, const Abi& a) const
{
assert(fnc->arg_size() > _argid);
return (fnc->arg_begin() + _argid);
}
template<>
Value* ConstantArgumentEntry::fetchArgValue(Function* fnc, const Abi& a) const
{
return _argid;
}
template<>
std::string StackArgumentEntry::createName(
llvm::Function* fnc,
const Abi& a,
const std::string& suffix,
const std::string& base) const
{
if (suffix.empty())
{
return base+std::to_string(_argid);
}
return base+suffix;
}
template<>
std::string RegisterArgumentEntry::createName(
llvm::Function* fnc,
const Abi& a,
const std::string& suffix,
const std::string& base) const
{
if (suffix.empty())
{
Value* val = getValue(fnc, a);
return base+val->getName().str();
}
return base+suffix;
}
template<>
std::string FunctionArgumentEntry::createName(
llvm::Function* fnc,
const Abi& a,
const std::string& suffix,
const std::string& base) const
{
return getValue(fnc, a)->getName().str();
}
template<>
std::string ConstantArgumentEntry::createName(
llvm::Function* fnc,
const Abi& a,
const std::string& suffix,
const std::string& base) const
{
return getValue(fnc, a)->getName().str();
}
//
//=============================================================================
// ReturnEntry

View File

@ -19,7 +19,7 @@
#include "retdec/utils/string.h"
#include "retdec/bin2llvmir/optimizations/param_return/filter/filter.h"
#include "retdec/bin2llvmir/optimizations/param_return/param_return.h"
#define debug_enabled true
#define debug_enabled false
#include "retdec/bin2llvmir/utils/llvm.h"
#include "retdec/bin2llvmir/providers/asm_instruction.h"
#include "retdec/bin2llvmir/utils/ir_modifier.h"
@ -115,9 +115,9 @@ bool ParamReturn::run()
_RDA.runOnModule(*_module, _abi);
collectAllCalls();
dumpInfo();
//dumpInfo();
filterCalls();
dumpInfo();
//dumpInfo();
applyToIr();
_RDA.clear();
@ -891,8 +891,16 @@ void ParamReturn::applyToIr()
{
for (auto& p : _fnc2calls)
{
// dumpInfo(p.second);
//dumpInfo(p.second);
//std::cout << "Applying to ir" << std::endl;
applyToIr(p.second);
//std::cout << "Applied!" << std::endl;
}
//std::cout << "Appling to ir ref" << std::endl;
for (auto& p : _fnc2calls)
{
applyToIrRef(p.second);
}
for (auto& p : _fnc2calls)
@ -902,12 +910,13 @@ void ParamReturn::applyToIr()
}
}
void ParamReturn::applyToIr(DataFlowEntry& de)
void ParamReturn::applyToIrRef(DataFlowEntry& de)
{
Function* fnc = de.getFunction();
if (fnc == nullptr)
{
//std::cout << "fnc == nullptr" << std::endl;
auto loadsOfCalls = fetchLoadsOfCalls(de.callEntries());
for (auto l : loadsOfCalls)
@ -923,10 +932,10 @@ void ParamReturn::applyToIr(DataFlowEntry& de)
return;
}
auto loadsOfCalls = fetchLoadsOfCalls(de.callEntries());
std::map<ReturnInst*, Value*> rets2vals;
//std::cout << "Some analysis" << std::endl;
if (de.getRetValue())
{
if (de.getRetType() == nullptr)
@ -952,29 +961,106 @@ void ParamReturn::applyToIr(DataFlowEntry& de)
de.setRetType(Type::getVoidTy(_module->getContext()));
}
std::vector<llvm::Value*> definitionArgs;
for (auto& a : de.args())
{
if (a != nullptr)
{
definitionArgs.push_back(a);
}
}
//std::cout << "Well here" << std::endl;
//std::cout << de.tmpArgs.empty() << std::endl;
//std::cout << de.loadsOfCalls.empty() << std::endl;
//std::cout << de.rets2vals.empty() << std::endl;
IrModifier irm(_module, _config);
auto* newFnc = irm.modifyFunction(
fnc,
de.getRetType(),
de.argTypes(),
de.isVariadic(),
rets2vals,
loadsOfCalls,
de.getRetValue(),
definitionArgs,
de.argNames()).first;
de.tmpArgs,
rets2vals,
de.loadsOfCalls,
de.isVariadic()).first;
//std::cout << "Well fuck" << std::endl;
//std::cout << "setting called value" << std::endl;
de.setCalledValue(newFnc);
}
void ParamReturn::applyToIr(DataFlowEntry& de)
{
Function* fnc = de.getFunction();
if (fnc == nullptr)
{
return;
//std::cout << "fnc == nullptr" << std::endl;
auto loadsOfCalls = fetchLoadsOfCalls(de.callEntries());
for (auto l : loadsOfCalls)
{
IrModifier::modifyCallInst(l.first, de.getRetType(), l.second);
}
return;
}
if (fnc->arg_size() > 0)
{
return;
}
//std::cout << "fetching args of calls" << std::endl;
auto loadsOfCalls = fetchArgsOfCalls(de.callEntries());
//std::cout << "preparing args " << std::endl;
auto types = de.argTypes().begin();
auto names = de.argNames().begin();
auto args = de.args().begin();
std::vector<ArgumentEntry::Ptr> definitionArgs;
while (types != de.argTypes().end() || names != de.argNames().end() || args != de.args().end())
{
auto* t = types != de.argTypes().end() ?
*(types++) : nullptr;
auto name = names != de.argNames().end() ?
*(names++) : "";
auto a = args != de.args().end() ?
*(args++) : nullptr;
if (a == nullptr)
{
definitionArgs.push_back(
ArgumentEntry::Ptr(
new DummyArgumentEntry(t, name)));
}
if (_config->isStackVariable(a))
{
definitionArgs.push_back(
ArgumentEntry::Ptr(
new StackArgumentEntry(_config->getStackVariableOffset(a), t, name)));
}
else if (_abi->isRegister(a))
{
definitionArgs.push_back(
ArgumentEntry::Ptr(
new RegisterArgumentEntry(_abi->getRegisterId(a), t, name)));
}
}
de.tmpArgs = definitionArgs;
de.loadsOfCalls = loadsOfCalls;
//std::cout << "it modifier called" << std::endl;
// IrModifier irm(_module, _config);
// auto* newFnc = irm.modifyFunction(
// fnc,
// de.getRetType(),
// de.getRetValue(),
// definitionArgs,
// rets2vals,
// loadsOfCalls,
// de.isVariadic()).first;
//std::cout << "setting called value" << std::endl;
// de.setCalledValue(newFnc);
}
void ParamReturn::connectWrappers(const DataFlowEntry& de)
{
@ -1067,11 +1153,89 @@ void ParamReturn::connectWrappers(const DataFlowEntry& de)
}
}
std::map<CallInst*, std::vector<ArgumentEntry::Ptr>> ParamReturn::fetchArgsOfCalls(
const std::vector<CallEntry>& calls) const
{
std::map<CallInst*, std::vector<ArgumentEntry::Ptr>> loadsOfCalls;
IrModifier irm(_module, _config);
for (auto& e : calls)
{
std::vector<ArgumentEntry::Ptr> loads;
auto* call = e.getCallInstruction();
auto types = e.getBaseFunction()->argTypes();
types.insert(
types.end(),
e.argTypes().begin(),
e.argTypes().end());
auto tIt = types.begin();
auto aIt = e.args().begin();
retdec::utils::Maybe<int> nextPossibleOffset;
while (aIt != e.args().end() || tIt != types.end())
{
if (_abi->isRegister(*aIt))
{
loads.push_back(
ArgumentEntry::Ptr(
new RegisterArgumentEntry(_abi->getRegisterId(*aIt), *tIt)));
}
else if (_config->isStackVariable(*aIt))
{
int stackOffset = _config->getStackVariableOffset(*aIt);
//
// Sometimes we do not detect stack variables duting
// collection of values. In those cases we may
// guess next stack variable by applying same difference
// in stack offset as peviously found stack variable.
//
// Perpas better solution in those cases would be:
// offset = previous_off+(next_off - previous_off)/2;
//
// Where next_offset has to be found among values.
//
if (!nextPossibleOffset.isUndefined())
{
nextPossibleOffset = nextPossibleOffset+(stackOffset-nextPossibleOffset)*2;
}
else
{
nextPossibleOffset = stackOffset*2;
}
loads.push_back(ArgumentEntry::Ptr(
new StackArgumentEntry(stackOffset, *tIt)));
}
else if (*aIt == nullptr && nextPossibleOffset.isDefined())
{
loads.push_back(ArgumentEntry::Ptr(
new StackArgumentEntry(nextPossibleOffset, *tIt)));
}
else
{
loads.push_back(ArgumentEntry::Ptr(
new DummyArgumentEntry(*tIt)));
}
if (tIt != types.end())
tIt++;
if (aIt != e.args().end())
aIt++;
}
loadsOfCalls[call] = std::move(loads);
}
return loadsOfCalls;
}
std::map<CallInst*, std::vector<Value*>> ParamReturn::fetchLoadsOfCalls(
const std::vector<CallEntry>& calls) const
{
std::map<CallInst*, std::vector<Value*>> loadsOfCalls;
IrModifier irm(_module, _config);
for (auto& e : calls)
{
@ -1095,31 +1259,19 @@ std::map<CallInst*, std::vector<Value*>> ParamReturn::fetchLoadsOfCalls(
continue;
}
std::cout << llvmObjToString(*aIt) << std::endl;
Value* l = new LoadInst(*aIt, "", call);
auto *t = tIt != types.end() ? *tIt++ : _abi->getDefaultType();
Value* conv = *aIt;
if (auto* strType = dyn_cast<StructType>(t))
if (tIt != types.end())
{
conv = irm.convertToStructure(*aIt, strType);
}
if (!t->isPointerTy())
{
conv = IrModifier::convertValueToType(conv, PointerType::get(t, 0), call);
auto* l = new LoadInst(t, conv);
l->insertBefore(call);
loads.push_back(l);
l = IrModifier::convertValueToType(l, *tIt, call);
tIt++;
}
else
{
auto* l = new LoadInst(conv);
l->insertBefore(call);
conv = IrModifier::convertValueToType(conv, PointerType::get(t, 0), call);
loads.push_back(l);
l = IrModifier::convertValueToType(l, _abi->getDefaultType(), call);
}
loads.push_back(l);
aIt++;
}

View File

@ -17,7 +17,7 @@
#include "retdec/bin2llvmir/optimizations/stack/stack.h"
#include "retdec/bin2llvmir/providers/asm_instruction.h"
#include "retdec/bin2llvmir/utils/ir_modifier.h"
#define debug_enabled false
#define debug_enabled true
#include "retdec/bin2llvmir/utils/llvm.h"
using namespace llvm;
@ -76,6 +76,8 @@ bool StackAnalysis::run()
for (auto& f : *_module)
{
std::cout << "HANDLING: " << f.getName().str() << std::endl;
std::map<Value*, Value*> val2val;
for (inst_iterator I = inst_begin(f), E = inst_end(f); I != E;)
{
@ -96,9 +98,9 @@ bool StackAnalysis::run()
store->getValueOperand()->getType(),
val2val);
if (isa<GlobalVariable>(store->getPointerOperand()))
if (_abi->isStackPointerRegister(store->getPointerOperand()))
{
continue;
continue;
}
handleInstruction(
@ -110,9 +112,9 @@ bool StackAnalysis::run()
}
else if (LoadInst* load = dyn_cast<LoadInst>(&i))
{
if (isa<GlobalVariable>(load->getPointerOperand()))
if (_abi->isStackPointerRegister(load->getPointerOperand()))
{
continue;
continue;
}
handleInstruction(
@ -136,6 +138,7 @@ bool StackAnalysis::run()
return false;
}
void StackAnalysis::handleInstruction(
ReachingDefinitionsAnalysis& RDA,
llvm::Instruction* inst,
@ -143,17 +146,21 @@ void StackAnalysis::handleInstruction(
llvm::Type* type,
std::map<llvm::Value*, llvm::Value*>& val2val)
{
LOG << llvmObjToString(inst) << std::endl;
LOG << "Handling instruction: " << llvmObjToString(inst) << std::endl;
SymbolicTree root(RDA, val, &val2val);
LOG << root << std::endl;
//TODO: what about all globals?
SymbolicTree root = !_abi->isGeneralPurposeRegister(val) ?
SymbolicTree(RDA, val, &val2val) : SymbolicTree(RDA, inst);
LOG << "Root of instruction: " << std::endl << root << std::endl;
if (!root.isVal2ValMapUsed())
{
bool stackPtr = false;
for (SymbolicTree* n : root.getPostOrder())
{
if (_abi->isStackPointerRegister(n->value))
if (_abi->isStackPointerRegister(n->value)
|| _abi->isStackVariable(n->value))
{
stackPtr = true;
break;
@ -171,6 +178,7 @@ void StackAnalysis::handleInstruction(
auto* ci = dyn_cast_or_null<ConstantInt>(root.value);
root.simplifyNode();
LOG << "Simplified root of instruction: " << std::endl << root << std::endl;
if (auto* pdSv = getDebugStackVariable(inst->getFunction(), root))
{
@ -180,6 +188,7 @@ void StackAnalysis::handleInstruction(
{
configSv = pcSv;
}
LOG << "Root value: " << llvmObjToString(root.value) << std::endl;
ci = dyn_cast_or_null<ConstantInt>(root.value);
if (ci == nullptr)
@ -195,8 +204,8 @@ void StackAnalysis::handleInstruction(
}
}
LOG << "===> " << llvmObjToString(ci) << std::endl;
LOG << "===> " << ci->getSExtValue() << std::endl;
LOG << "\tConstant extracted: " << llvmObjToString(ci) << std::endl;
LOG << "\tInteger constant : " << ci->getSExtValue() << std::endl;
std::string name = "";
Type* t = type;
@ -228,8 +237,8 @@ void StackAnalysis::handleInstruction(
ca->setIsFromDebug(true);
}
LOG << "===> " << llvmObjToString(a) << std::endl;
LOG << "===> " << llvmObjToString(inst) << std::endl;
LOG << "\tHave stack variable: " << llvmObjToString(a) << std::endl;
LOG << "\tModifying instrucio: " << llvmObjToString(inst) << std::endl;
LOG << std::endl;
auto* s = dyn_cast<StoreInst>(inst);

View File

@ -6,6 +6,7 @@
#include <iostream>
#include <llvm/IR/Constants.h>
#include <llvm/IR/InstIterator.h>
#include <llvm/IR/InstrTypes.h>
@ -241,27 +242,21 @@ Value* convertToType(
else if (isa<LoadInst>(val) && type->isAggregateType())
{
conv = val;
std::cout << "val: " << llvmObjToString(val) << std::endl;
std::cout << "type: " << llvmObjToString(type) << std::endl;
std::cout << "EXITTING" << std::endl;
//std::cout << "type: " << llvmObjToString(type) << std::endl;
//std::cout << "EXITTING" << std::endl;
exit(1);
}
else if (val->getType()->isAggregateType())
{
std::cout << "Val: " << llvmObjToString(val) << std::endl;
std::cout << "Type: " << llvmObjToString(type) << std::endl;
auto* strType = dyn_cast<StructType>(val->getType());
Instruction* gep = GetElementPtrInst::CreateInBounds(strType, val, {0}, "", before);
gep = new LoadInst(gep);
gep->insertBefore(before);
conv = convertToType(gep, type, before, gep, constExpr);
conv = gep;
}
else if (CompositeType* cmp = dyn_cast<CompositeType>(type))
{
std::cout << "The val: " << llvmObjToString(val) << std::endl;
std::cout << "Type: " << llvmObjToString(type) << std::endl;
//std::cout << "The val: " << llvmObjToString(val) << std::endl;
//std::cout << "Type: " << llvmObjToString(type) << std::endl;
assert(!isa<Instruction>(val) && "This should not happen! Please rethink convertion.");
std::cout << "Should not happen" << std::endl;
exit(2);
conv = nullptr;
}
@ -292,8 +287,16 @@ llvm::CallInst* _modifyCallInst(
llvm::Value* calledVal,
llvm::ArrayRef<llvm::Value*> args)
{
//std::cout << "call: " << llvmObjToString(call) << std::endl;
//std::cout << "args: " << args.size() << std::endl;
for (auto a: args)
{
std::cout << "\tnarg: " << llvmObjToString(a) << std::endl;
}
std::set<Instruction*> toEraseCast;
auto* newCall = CallInst::Create(calledVal, args, "", call);
//std::cout << "newCall: " << llvmObjToString(newCall) << std::endl;
if (call->getNumUses())
{
if (!newCall->getType()->isVoidTy())
@ -734,9 +737,8 @@ Instruction* IrModifier::getElement(llvm::Value* v, const std::vector<Value*> &i
{
auto* var = dyn_cast<PointerType>(v->getType());
assert(var && "Expects variable.");
auto* strType = dyn_cast<StructType>(var->getElementType());
return GetElementPtrInst::CreateInBounds(strType, v, idxs);
return GetElementPtrInst::CreateInBounds(var->getPointerElementType(), v, idxs);
}
void IrModifier::replaceElementWithStrIdx(llvm::Value* element, llvm::Value* str, std::size_t idx)
@ -798,16 +800,9 @@ void IrModifier::replaceElementWithStrIdx(llvm::Value* element, llvm::Value* str
auto eIdx = ConstantInt::get(IntegerType::get(_module->getContext(), 32), idx);
auto elem = getElement(str, {zero, eIdx});
if (element->getType()->isArrayTy())
elem = getElement(str, {zero, eIdx, zero});
elem->insertBefore(i);
Value* val = new LoadInst(dyn_cast<PointerType>(elem->getType())->getElementType(), elem, "", i);
if (val->getType() != i->getType())
val = convertValueToType(val, i->getType(), i);
i->replaceAllUsesWith(val);
i->replaceAllUsesWith(convertValueToType(elem, i->getDestTy(), i));
i->eraseFromParent();
}
}
@ -1274,11 +1269,74 @@ void IrModifier::correctStackElementsInPadding(
*/
}
Value* IrModifier::convertToPointer(
Value* obj,
std::size_t ptrDepth)
{
//std::cout << "Converting to pointer: " << llvmObjToString(obj) << std::endl;
//std::cout << "Desired pointer length: " << ptrDepth << std::endl;
auto* ptrType = obj->getType();
for (std::size_t i = 0; i < ptrDepth; i++)
{
ptrType = PointerType::get(ptrType, 0);
}
std::list<User*> users;
// auto image = FileImageProvider::getFileImage(_module);
auto* nobj = obj;//changeObjectDeclarationType(image, obj, ptrType);
//std::cout << "New Object: " << llvmObjToString(nobj) << std::endl;
for (const auto& U : obj->users())
{
users.push_back(U);
}
for (auto* u: users)
{
//std::cout << "u: " << llvmObjToString(u) << std::endl;
auto first = ConstantInt::get(IntegerType::get(_module->getContext(), 32), ptrDepth);
std::vector<Value*> idxs(1, first);
if (auto* gep = dyn_cast<GetElementPtrInst>(u))
{
bool first = true;
for (auto& i : gep->indices())
{
if (!first)
idxs.push_back(i.get());
else
first = false;
}
}
//std::cout << "using" << std::endl;
for (auto i: idxs)
{
//std::cout << llvmObjToString(i) << std::endl;
}
if (auto* i = dyn_cast<Instruction>(u))
{
auto* ni = GetElementPtrInst::CreateInBounds(obj->getType()->getPointerElementType(), nobj, idxs);
//std::cout << "New get elem ptr: " << llvmObjToString(ni) << std::endl;
ni->insertBefore(i);
i->replaceAllUsesWith(ni);
i->eraseFromParent();
}
else
{
assert(false && "This should not happen!");
}
}
return nobj;
}
Value* IrModifier::convertToStructure(
Value* obj,
StructType* strType)
{
std::cout << "Correcing structure" << std::endl;
if (auto* gv = dyn_cast<GlobalVariable>(obj))
{
auto addr = _config->getGlobalAddress(gv);
@ -1287,7 +1345,6 @@ Value* IrModifier::convertToStructure(
else if (_config->isStackVariable(obj))
{
auto offset = _config->getStackVariableOffset(obj);
std::cout << "Modified opbject: " << llvmObjToString(obj) << std::endl;
return convertToStructure(dyn_cast<AllocaInst>(obj), strType, offset);
}
@ -1295,6 +1352,85 @@ Value* IrModifier::convertToStructure(
return obj;
}
Value* IrModifier::createStructureFromStacks(
AllocaInst* startStack,
StructType* strType,
int offset,
Instruction* before,
InsertValueInst* newStructure,
std::vector<unsigned int>idxs)
{
assert(_config->isStackVariable(startStack) && "Invalid usage of function!");
auto alignment = getAlignment(strType);
auto padding = alignment;
// Create copy of local variable.
auto* fnc = startStack->getFunction();
std::size_t idx = 0;
for (auto elem: strType->elements())
{
auto elemIdxs = idxs;
elemIdxs.push_back(idx++);
if (auto* eStrType = dyn_cast<StructType>(elem))
{
auto newAlignment = getAlignment(eStrType);
if (alignment > padding) {
int nOffset = offset+(padding)%newAlignment;
// TODO: find in padding
offset = nOffset;
}
padding = alignment;
AllocaInst* structElement = getStackVariable(fnc, offset, elem).first;
createStructureFromStacks(structElement, eStrType, offset, before, newStructure, elemIdxs);
continue;
}
auto a = AbiProvider::getAbi(_module);
auto elemSize = a->getTypeByteSize(elem);
if (padding < elemSize) {
//TODO: search padding
offset += padding;
padding = alignment;
}
AllocaInst* structElement = getStackVariable(fnc, offset, elem).first;
//TODO: is this way of load/convert correct? should investigate
Value* conv = convertValueToType(structElement, PointerType::get(elem, 0), before);
conv = new LoadInst(elem, conv, "", before);
//TODO: dummy if not found
newStructure = InsertValueInst::Create(
newStructure ?
static_cast<Value*>(newStructure)
: UndefValue::get(strType),
conv,
elemIdxs,
"",
before);
//TODO: serach type space of primitive
padding -= elemSize;
offset += elemSize;
}
// In case of recursive structures we must align
// space for correct address.
padding = padding%alignment;
if (padding)
{
//TODO: search padding
offset += padding; // (addr-oldAddr)%alignment
}
return newStructure;
}
llvm::GlobalVariable* IrModifier::convertToStructure(
GlobalVariable* gv,
StructType* strType,
@ -1470,8 +1606,6 @@ AllocaInst* IrModifier::convertToStructure(
// TODO:
// following 3 linses of code can go into replaceElementWithStrIdx.
auto* origType = structElement->getType()->getPointerElementType();
std::cout << "Original type : " << llvmObjToString(structElement) << std::endl;
std::cout << "Wanted type : " << llvmObjToString(elem) << std::endl;
if (origType != elem) {
auto* val = changeObjectDeclarationType(image, structElement, elem);
correctUsageOfModifiedObject(structElement, val, origType);
@ -1619,9 +1753,6 @@ void IrModifier::correctUsageOfModifiedObject(Value* val, Value* nval, Type* ori
}
PointerType* ptr = dyn_cast<PointerType>(dst->getType());
assert(ptr);
std::cout << "Before convert: " << std::endl;
std::cout << "src " << llvmObjToString(src) << std::endl;
std::cout << "dst " << llvmObjToString(dst) << std::endl;
src = IrModifier::convertValueToType(src, ptr->getElementType(), store);
store->setOperand(0, src);
store->setOperand(1, dst);
@ -1659,14 +1790,21 @@ void IrModifier::correctUsageOfModifiedObject(Value* val, Value* nval, Type* ori
}
else if (auto* gep = dyn_cast<GetElementPtrInst>(user))
{
//TODO: do this only if accssing first element.
//in other cases we are totally fucked up.
//But they will happen only if somene retarded
//will do retarded things.
//TODO: we should do this generally with pointers.
auto* conv = IrModifier::convertValueToType(nval, gep->getType(), gep);
gep->replaceAllUsesWith(conv);
gep->eraseFromParent();
if (nval->getType() == PointerType::get(gep->getPointerOperandType(), 0))
{
auto* newLoad = new LoadInst(nval);
newLoad->insertBefore(gep);
gep->setOperand(0, newLoad);
}
else
{
auto* conv = IrModifier::convertValueToType(nval, gep->getType(), gep);
gep->replaceAllUsesWith(conv);
gep->eraseFromParent();
}
}
else if (auto* cast = dyn_cast<CastInst>(user))
{
@ -1688,8 +1826,6 @@ void IrModifier::correctUsageOfModifiedObject(Value* val, Value* nval, Type* ori
else
{
auto* conv = IrModifier::convertValueToType(nval, cast->getType(), cast);
std::cout << "conv: " << llvmObjToString(conv) << std::endl;
std::cout << "cast: " << llvmObjToString(cast) << std::endl;
if (cast != conv)
{
cast->replaceAllUsesWith(conv);
@ -1710,15 +1846,11 @@ void IrModifier::correctUsageOfModifiedObject(Value* val, Value* nval, Type* ori
auto* conv = IrModifier::convertValueToType(nval, origType, instr);
if (val != conv)
{
std::cout << "val: " << llvmObjToString(val) << std::endl;
std::cout << "conv: " << llvmObjToString(conv) << std::endl;
instr->replaceUsesOfWith(val, conv);
}
}
else if (newConst && gvDeclr)
{
std::cout << "what" << std::endl;
auto* conv = IrModifier::convertConstantToType(
newConst,
gvDeclr->getType()->getPointerElementType());
@ -1731,7 +1863,6 @@ void IrModifier::correctUsageOfModifiedObject(Value* val, Value* nval, Type* ori
//
else if (newConst && c)
{
std::cout << "the funck" << std::endl;
auto* conv = IrModifier::convertConstantToType(newConst, c->getType());
if (c != conv)
{
@ -1783,7 +1914,7 @@ llvm::Value* IrModifier::changeObjectType(
return val;
}
if (val->getType() == toType)
if (val->getType()->getPointerElementType() == toType)
{
return val;
}
@ -1812,6 +1943,7 @@ llvm::Value* IrModifier::changeObjectType(
return nval;
}
/**
* Inspired by ArgPromotion::DoPromotion().
* Steps performed in ArgPromotion::DoPromotion() that are not done here:
@ -1825,26 +1957,42 @@ llvm::Value* IrModifier::changeObjectType(
IrModifier::FunctionPair IrModifier::modifyFunction(
llvm::Function* fnc,
llvm::Type* ret,
std::vector<llvm::Type*> args,
bool isVarArg,
const std::map<llvm::ReturnInst*, llvm::Value*>& rets2vals,
const std::map<llvm::CallInst*, std::vector<llvm::Value*>>& calls2vals,
llvm::Value* retVal,
const std::vector<llvm::Value*>& argStores,
const std::vector<std::string>& argNames)
const std::vector<ArgumentEntry::Ptr>& args,
const std::map<llvm::ReturnInst*, llvm::Value*>& rets2vals,
const std::map<llvm::CallInst*, std::vector<ArgumentEntry::Ptr>>& calls2args,
bool isVarArg)
{
//std::cout << "Modifying function " << std::endl;
//std::cout << fnc << std::endl;
auto _abi = AbiProvider::getAbi(_module);
//std::cout << "Her!" << std::endl;
auto* cf = _config->getConfigFunction(fnc);
//std::cout << "Her!" << std::endl;
//std::cout << ret << std::endl;
if (!FunctionType::isValidReturnType(ret))
{
{
//std::cout << "This is bad" << std::endl;
ret = Abi::getDefaultType(fnc->getParent());
}
for (Type*& t : args)
//std::cout << "what" << std::endl;
std::vector<ArgumentEntry::Ptr> templArgs = args;
//std::cout << "no copy!" << std::endl;
if (args.empty() && !isVarArg && !calls2args.empty())
{
if (!FunctionType::isValidArgumentType(t))
{
t = Abi::getDefaultType(fnc->getParent());
}
//std::cout << "Suicide!" << std::endl;
templArgs = calls2args.begin()->second;
}
//std::cout << "Types:" << std::endl;
std::vector<Type*> argTypes;
for (auto& arg: templArgs)
{
//std::cout << "at: " << llvmObjToString(arg->getType(fnc, *_abi)) << std::endl;
argTypes.push_back(arg->getType(fnc, *_abi));
}
// New function type.
@ -1852,9 +2000,11 @@ IrModifier::FunctionPair IrModifier::modifyFunction(
ret = ret ? ret : fnc->getReturnType();
llvm::FunctionType* newFncType = llvm::FunctionType::get(
ret,
args,
argTypes,
isVarArg);
//std::cout << "Created new function " << std::endl;
// New function.
//
Function *nf = nullptr;
@ -1877,49 +2027,34 @@ IrModifier::FunctionPair IrModifier::modifyFunction(
// Rename arguments.
//
auto nIt = argNames.begin();
auto oi = fnc->arg_begin();
auto oie = fnc->arg_end();
std::size_t idx = 1;
//std::cout << "Renaming args of new function " << std::endl;
std::size_t idx = 0;
std::vector<std::string> argnames;
for (auto i = nf->arg_begin(), e = nf->arg_end(); i != e; ++i, ++idx)
{
if (nIt != argNames.end() && !nIt->empty())
llvm::Value* argValue;
std::string argName;
std::tie(argValue, argName) = templArgs[idx]->get(nf, *_abi, std::to_string(idx));
//std::cout << "New arg: " << argName << std::endl;
if (_abi->isStackVariable(argValue) && argValue->getName() == argName)
{
if (auto* st = _config->getLlvmStackVariable(nf, *nIt))
{
i->takeName(st);
}
else
{
i->setName(*nIt);
}
i->takeName(argValue);
}
else
{
if (oi != oie && !oi->getName().empty())
{
if (nf != fnc)
{
i->setName(oi->getName());
}
}
else
{
std::string n = "arg" + std::to_string(idx);
i->setName(n);
}
i->setName(argName);
}
if (nIt != argNames.end())
{
++nIt;
}
if (oi != oie)
{
++oi;
}
argnames.push_back(argName);
}
//std::cout << "Setting args to config function " << std::endl;
// Set arguments to config function.
//
if (cf)
@ -1932,11 +2067,9 @@ IrModifier::FunctionPair IrModifier::modifyFunction(
assert(!n.empty());
auto s = retdec::config::Storage::undefined();
retdec::config::Object arg(n, s);
if (argNames.size() > idx)
{
arg.setRealName(argNames[idx]);
arg.setIsFromDebug(true);
}
arg.setRealName(argnames[idx]);
arg.setIsFromDebug(true);
arg.type.setLlvmIr(llvmObjToString(i->getType()));
// TODO: hack, we need to propagate type's wide string property.
@ -1952,11 +2085,14 @@ IrModifier::FunctionPair IrModifier::modifyFunction(
}
}
//std::cout << "Replacing uses of old args in func body." << std::endl;
// Replace uses of old arguments in function body for new arguments.
//
for (auto i = fnc->arg_begin(), e = fnc->arg_end(), i2 = nf->arg_begin();
i != e; ++i, ++i2)
{
//std::cout << "This happening?" << std::endl;
auto* a1 = &(*i);
auto* a2 = &(*i2);
if (a1->getType() == a2->getType())
@ -1974,7 +2110,6 @@ IrModifier::FunctionPair IrModifier::modifyFunction(
auto* inst = dyn_cast<Instruction>(u);
assert(inst && "we need an instruction here");
std::cout << "Is this the case?" << std::endl;
auto* conv = IrModifier::convertValueToType(a2, a1->getType(), inst);
inst->replaceUsesOfWith(a1, conv);
}
@ -1982,60 +2117,106 @@ IrModifier::FunctionPair IrModifier::modifyFunction(
a2->takeName(a1);
}
std::cout << "Investigating function: " << nf->getName().str() << std::endl;
//std::cout << "Finished" << std::endl;
// Store arguments into allocated objects (stacks, registers) at the
// beginning of function body.
//
auto asIt = argStores.begin();
auto asEndIt = argStores.end();
for (auto aIt = nf->arg_begin(), eIt = nf->arg_end();
aIt != eIt && asIt != asEndIt;
++aIt, ++asIt)
idx = 0;
bool hasDefinitionArgs = false;
for (auto& a: args)
{
auto* a = &(*aIt);
auto* v = *asIt;
//std::cout << "Perhaps this?" << std::endl;
if (a->isDefined(nf, *_abi))
{
hasDefinitionArgs = true;
}
//std::cout << "I knew it!" << std::endl;
}
//std::cout << "Found out that function definition is defined? " << hasDefinitionArgs << std::endl;
//TODO: check from llvm
for (auto i = nf->arg_begin(), e = nf->arg_end(); hasDefinitionArgs && i != e; ++i, ++idx)
{
auto* v = args[idx]->getValue(nf, *_abi);
auto* a = &(*i);
assert(v->getType()->isPointerTy());
std::cout << "Converting to structure: " << std::endl;
std::cout << "val: " << llvmObjToString(a) << std::endl;
std::cout << "at: " << llvmObjToString(a->getType()) << std::endl;
std::cout << "v : " << llvmObjToString(v) << std::endl;
std::cout << "type: " << llvmObjToString(v->getType()) << std::endl;
auto primitiveType = a->getType();
size_t pointerDepth = 0;
Value* conv = nullptr;
if (auto* strType = dyn_cast<StructType>(a->getType()))
while (primitiveType->isPointerTy())
{
v = convertToStructure(v, strType);
primitiveType = primitiveType->getPointerElementType();
pointerDepth++;
}
std::cout << "v : " << llvmObjToString(v) << std::endl;
conv = IrModifier::convertValueToType(
a,
v->getType()->getPointerElementType(),
&nf->front().front());
std::cout << "Converting to primitive" << std::endl;
auto* s = new StoreInst(conv, v);
//TODO: do not change dewclaration if -> declaration
Value* conv = v;
Value* aconv = a;
if (auto* alloca = dyn_cast<AllocaInst>(v))
if (_config->isStackVariable(conv))
{
if (auto* strType = dyn_cast<StructType>(primitiveType))
{
//std::cout << "Converting to structure" << std::endl;
conv = convertToStructure(v, strType);
}
else
{
conv = changeObjectType(
FileImageProvider::getFileImage(_module),
v,
primitiveType);
}
std::cout << "Convering to type" << std::endl;
//std::cout << "Vhangeing objet type: " << std::endl;
conv = changeObjectType(
FileImageProvider::getFileImage(_module),
conv,
a->getType());
std::cout << "Generatinbg store" << std::endl;
std::cout << "Well conv := " << llvmObjToString(conv) << std::endl;
std::cout << "Should be pointer of " << llvmObjToString(a) << std::endl;
}
else
{
aconv = convertValueToType(a, conv->getType()->getPointerElementType(), &nf->front().front());
}
auto* s = new StoreInst(aconv, conv);
std::cout << "generated" << std::endl;
if (auto* alloca = dyn_cast<AllocaInst>(conv))
{
s->insertAfter(alloca);
}
else
{
if (conv == a)
if (a == aconv)
{
s->insertBefore(&nf->front().front());
}
else
{
s->insertAfter(cast<Instruction>(conv));
s->insertAfter(cast<Instruction>(aconv));
}
}
std::cout << "Done1" << std::endl;
}
std::cout << "Updating returns" << std::endl;
// Update returns in function body.
//
// if (nf->getReturnType() != fnc->getReturnType())
@ -2091,7 +2272,51 @@ IrModifier::FunctionPair IrModifier::modifyFunction(
}
}
std::cout << "HERE" << std::endl;
std::cout << "Preparing calls" << nf->getName().str() << std::endl;
std::map<CallInst*, std::vector<Value*>> preparedCalls;
// Alter calls
for (auto ce: calls2args)
{
CallInst* call = ce.first;
std::vector<Value*> args;
for (auto& arg: ce.second)
{
Value* v; Type* t;
std::tie(v, t) = arg->get(call->getFunction(), *_abi);
Value* conv = v;
std::cout << "\tObject passed as arg: " << llvmObjToString(conv) << std::endl;
auto* strType = dyn_cast<StructType>(t);
if (strType && _config->isStackVariable(v))
{
conv = createStructureFromStacks(
dyn_cast<AllocaInst>(conv),
strType,
_config->getStackVariableOffset(conv),
call);
}
else if (!t->isPointerTy())
{
conv = IrModifier::convertValueToType(conv, PointerType::get(t, 0), call);
auto* l = new LoadInst(t, conv);
l->insertBefore(call);
conv = l;
}
else
{
auto* l = new LoadInst(conv);
l->insertBefore(call);
conv = IrModifier::convertValueToType(l, t, call);
}
std::cout << "\tObject passed as arg: " << llvmObjToString(conv) << std::endl;
args.push_back(conv);
}
preparedCalls[call] = args;
}
//std::cout << "Preparing other users" << std::endl;
// Update function users (calls, etc.).
//
auto uIt = fnc->user_begin();
@ -2102,55 +2327,9 @@ IrModifier::FunctionPair IrModifier::modifyFunction(
if (CallInst* call = dyn_cast<CallInst>(u))
{
std::vector<Value*> args;
auto fIt = calls2vals.find(call);
if (fIt != calls2vals.end())
if (!calls2args.count(call))
{
auto vIt = fIt->second.begin();
for (auto fa = nf->arg_begin(); fa != nf->arg_end(); ++fa)
{
std::cout << "fa: " << llvmObjToString(fa) << std::endl;
if (vIt != fIt->second.end())
{
Value* conv = nullptr;
if (auto* strType = dyn_cast<StructType>(fa->getType()))
{
std::cout << "vItStr: " << llvmObjToString(*vIt) << std::endl;
conv = convertToStructure(*vIt, strType);
std::cout << "vItStr: " << llvmObjToString(*vIt) << std::endl;
std::cout << "DONE" << std::endl;
}
else
{
std::cout << "vIt: " << llvmObjToString(*vIt) << std::endl;
conv = IrModifier::convertValueToType(
*vIt,
fa->getType(),
call);
}
args.push_back(conv);
++vIt;
}
else
{
auto* conv = IrModifier::convertValueToType(
_config->getGlobalDummy(),
fa->getType(),
call);
args.push_back(conv);
}
}
std::cout << "Ok?" << std::endl;
while (isVarArg && vIt != fIt->second.end())
{
args.push_back(*vIt);
++vIt;
}
}
else
{
std::cout << "PLS" << std::endl;
std::vector<Value*> args;
unsigned ai = 0;
unsigned ae = call->getNumArgOperands();
for (auto fa = nf->arg_begin(); fa != nf->arg_end(); ++fa)
@ -2173,23 +2352,7 @@ IrModifier::FunctionPair IrModifier::modifyFunction(
args.push_back(conv);
}
}
}
assert(isVarArg || args.size() == nf->arg_size());
auto* nc = _modifyCallInst(
call,
nf,
args);
if (!ret->isVoidTy() && retVal)
{
auto* n = nc->getNextNode();
assert(n);
auto* conv = IrModifier::convertValueToType(
nc,
retVal->getType()->getPointerElementType(),
n);
new StoreInst(conv, retVal, n);
preparedCalls[call] = args;
}
}
else if (StoreInst* s = dyn_cast<StoreInst>(u))
@ -2214,7 +2377,35 @@ IrModifier::FunctionPair IrModifier::modifyFunction(
assert(false && "unhandled use");
}
}
std::cout << "OLALAL" << std::endl;
//std::cout << "Modifing calls and other users" << std::endl;
for (auto cv: preparedCalls)
{
CallInst* call = cv.first;
//std::cout << "Modifying call" << std::endl;
auto* nc = _modifyCallInst(
call,
nf,
cv.second);
//std::cout << "Setting return" << std::endl;
if (!ret->isVoidTy() && retVal)
{
auto* n = nc->getNextNode();
assert(n);
auto* conv = IrModifier::convertValueToType(
nc,
retVal->getType()->getPointerElementType(),
n);
new StoreInst(conv, retVal, n);
}
}
//std::cout << "Changing ret type" << std::endl;
if (nf->getType() != fnc->getType())
{
@ -2226,6 +2417,7 @@ IrModifier::FunctionPair IrModifier::modifyFunction(
// No ide why.
// fnc->eraseFromParent();
//std::cout << "All ok!" << std::endl;
return {nf, cf};
}
@ -2238,12 +2430,15 @@ llvm::Argument* IrModifier::modifyFunctionArgumentType(
llvm::Type* type)
{
auto* f = arg->getParent();
std::vector<Type*> args;
std::vector<ArgumentEntry::Ptr> args;
std::size_t idx = 0;
for (auto& a : f->args())
{
args.push_back(&a == arg ? type : a.getType());
args.push_back(ArgumentEntry::Ptr(
new FunctionArgumentEntry(idx, &a == arg ? type : a.getType())));
idx++;
}
auto* nf = modifyFunction(f, f->getReturnType(), args).first;
auto* nf = modifyFunction(f, f->getReturnType(), nullptr, args).first;
std::size_t i = 0;
for (auto& a : nf->args())
{

View File

@ -79,8 +79,7 @@ TEST_F(IrModifierTests, convertValueToTypeFunctionToPointer)
parseInput(R"(
declare void @import()
define void @fnc() {
ret void
}
ret void1`` }
)");
auto* import = getValueByName("import");
auto* r = getNthInstruction<ReturnInst>();
@ -305,16 +304,20 @@ TEST_F(IrModifierTests, modifyFunctionVoid)
auto* call2 = getNthInstruction<CallInst>(1);
auto* i32 = Type::getInt32Ty(context);
auto* a1 = ConstantInt::get(i32, 123);
auto* a2 = ConstantInt::get(i32, 456);
auto a1 = ArgumentEntry::Ptr(new ConstantArgumentEntry(
dyn_cast<Constant>(ConstantInt::get(i32, 123)),
i32));
auto a2 = ArgumentEntry::Ptr(new ConstantArgumentEntry(
dyn_cast<Constant>(ConstantInt::get(i32, 456)),
i32));
auto c = Config::empty(module.get());
IrModifier irm(module.get(), &c);
irm.modifyFunction(
import,
i32,
{i32},
false,
nullptr,
{},
std::map<ReturnInst*, Value*>(),
{{call1, {a1}}, {call2, {a2}}});
@ -352,8 +355,12 @@ TEST_F(IrModifierTests, modifyFunctionWithZeroArguments)
auto* call2 = getNthInstruction<CallInst>(1);
auto* ret = getNthInstruction<ReturnInst>();
auto* i32 = Type::getInt32Ty(context);
auto* a1 = ConstantInt::get(i32, 123);
auto* a2 = ConstantInt::get(i32, 456);
auto a1 = ArgumentEntry::Ptr(new ConstantArgumentEntry(
dyn_cast<Constant>(ConstantInt::get(i32, 123)),
i32));
auto a2 = ArgumentEntry::Ptr(new ConstantArgumentEntry(
dyn_cast<Constant>(ConstantInt::get(i32, 456)),
i32));
auto* r = ConstantInt::get(i32, 789);
auto* userDef = cast<Function>(getValueByName("userDef"));
@ -362,8 +369,8 @@ TEST_F(IrModifierTests, modifyFunctionWithZeroArguments)
irm.modifyFunction(
userDef,
i32,
{i32},
false,
nullptr,
{},
{{ret, r}},
{{call1, {a1}}, {call2, {a2}}});
@ -407,7 +414,11 @@ TEST_F(IrModifierTests, modifyFunctionWithExistingArguments)
auto* d = Type::getDoubleTy(context);
auto c = Config::empty(module.get());
IrModifier irm(module.get(), &c);
irm.modifyFunction(fnc, f, {f, i32, d});
//TODO: provide separate function for this.
auto df = ArgumentEntry::Ptr(new DummyArgumentEntry(f));
auto dd = ArgumentEntry::Ptr(new DummyArgumentEntry(d));
auto di = ArgumentEntry::Ptr(new DummyArgumentEntry(i32));
irm.modifyFunction(fnc, f, nullptr, {df, di, dd});
std::string exp = R"(
define float @fnc(float %a1, i32 %a2, double %a3) {
@ -452,22 +463,27 @@ TEST_F(IrModifierTests, modifyFunctionVariadic)
ret i32 0
}
)");
auto* fnc = cast<Function>(getValueByName("fnc"));
auto* c1 = getNthInstruction<CallInst>();
auto* c2 = getNthInstruction<CallInst>(1);
auto* ret = getNthInstruction<ReturnInst>();
auto* i32 = Type::getInt32Ty(context);
auto* ci = ConstantInt::get(i32, 0);
auto ci = ArgumentEntry::Ptr(new ConstantArgumentEntry(
dyn_cast<Constant>(ConstantInt::get(i32, 0)),
i32));
auto ap = ArgumentEntry::Ptr(new DummyArgumentEntry(i32));
auto c = Config::empty(module.get());
IrModifier irm(module.get(), &c);
irm.modifyFunction(
fnc,
i32,
{i32},
true,
{{ret, ci}},
{{c1, {ci, ci}}, {c2, {ci, ci, ci, ci}}});
nullptr,
{ap},
{{ret, ConstantInt::get(i32, 0)}},
{{c1, {ci, ci}}, {c2, {ci, ci, ci, ci}}},
true);
std::string exp = R"(
target datalayout = "e-p:32:32:32-f80:32:32"