133 lines
3.8 KiB
C++
133 lines
3.8 KiB
C++
#include "recursiveanalysis.h"
|
|
#include <queue>
|
|
#include "console.h"
|
|
#include "filehelper.h"
|
|
#include "function.h"
|
|
#include "xrefs.h"
|
|
|
|
RecursiveAnalysis::RecursiveAnalysis(duint base, duint size, duint entryPoint, duint maxDepth, bool dump)
|
|
: Analysis(base, size),
|
|
mEntryPoint(entryPoint),
|
|
mMaxDepth(maxDepth),
|
|
mDump(dump)
|
|
{
|
|
}
|
|
|
|
void RecursiveAnalysis::Analyse()
|
|
{
|
|
//TODO: implement queue to analyze multiple functions
|
|
analyzeFunction(mEntryPoint);
|
|
}
|
|
|
|
void RecursiveAnalysis::SetMarkers()
|
|
{
|
|
if(mDump)
|
|
for(const auto & function : mFunctions)
|
|
FileHelper::WriteAllText(StringUtils::sprintf("cfgraph_" fhex ".dot", function.entryPoint), function.ToDot());
|
|
|
|
//set function ranges
|
|
for(const auto & function : mFunctions)
|
|
{
|
|
duint start = ~0;
|
|
duint end = 0;
|
|
duint icount = 0;
|
|
for(const auto & node : function.nodes)
|
|
{
|
|
icount += node.second.icount;
|
|
start = min(node.second.start, start);
|
|
end = max(node.second.end, end);
|
|
}
|
|
XrefDelRange(start, end);
|
|
if(!FunctionAdd(start, end, false, icount))
|
|
{
|
|
FunctionDelete(start);
|
|
FunctionDelete(end);
|
|
FunctionAdd(start, end, false, icount);
|
|
}
|
|
}
|
|
|
|
//set xrefs
|
|
for(const auto & xref : mXrefs)
|
|
XrefAdd(xref.addr, xref.from);
|
|
|
|
GuiUpdateAllViews();
|
|
}
|
|
|
|
void RecursiveAnalysis::analyzeFunction(duint entryPoint)
|
|
{
|
|
//BFS through the disassembly starting at entryPoint
|
|
CFGraph graph(entryPoint);
|
|
UintSet visited;
|
|
std::queue<duint> queue;
|
|
queue.push(graph.entryPoint);
|
|
while(!queue.empty())
|
|
{
|
|
auto start = queue.front();
|
|
queue.pop();
|
|
if(visited.count(start) || !inRange(start)) //already visited or out of range
|
|
continue;
|
|
visited.insert(start);
|
|
|
|
CFNode node(graph.entryPoint, start, start);
|
|
while(true)
|
|
{
|
|
node.icount++;
|
|
if(!mCp.Disassemble(node.end, translateAddr(node.end)))
|
|
{
|
|
node.end++;
|
|
continue;
|
|
}
|
|
|
|
//do xref analysis on the instruction
|
|
XREF xref;
|
|
xref.addr = 0;
|
|
xref.from = mCp.Address();
|
|
for(auto i = 0; i < mCp.OpCount(); i++)
|
|
{
|
|
duint dest = mCp.ResolveOpValue(i, [](x86_reg)->size_t
|
|
{
|
|
return 0;
|
|
});
|
|
if(inRange(dest))
|
|
{
|
|
xref.addr = dest;
|
|
break;
|
|
}
|
|
}
|
|
if(xref.addr)
|
|
mXrefs.push_back(xref);
|
|
|
|
if(mCp.InGroup(CS_GRP_JUMP) || mCp.IsLoop()) //jump
|
|
{
|
|
//set the branch destinations
|
|
node.brtrue = mCp.BranchDestination();
|
|
if(mCp.GetId() != X86_INS_JMP) //unconditional jumps dont have a brfalse
|
|
node.brfalse = node.end + mCp.Size();
|
|
|
|
//add node to the function graph
|
|
graph.AddNode(node);
|
|
|
|
//enqueue branch destinations
|
|
if(node.brtrue)
|
|
queue.push(node.brtrue);
|
|
if(node.brfalse)
|
|
queue.push(node.brfalse);
|
|
|
|
break;
|
|
}
|
|
if(mCp.InGroup(CS_GRP_CALL)) //call
|
|
{
|
|
//TODO: add this to a queue to be analyzed later
|
|
}
|
|
if(mCp.InGroup(CS_GRP_RET)) //return
|
|
{
|
|
node.terminal = true;
|
|
graph.AddNode(node);
|
|
break;
|
|
}
|
|
node.end += mCp.Size();
|
|
}
|
|
}
|
|
mFunctions.push_back(graph);
|
|
}
|