Add AutomatedPlanner skeleton class
This commit is contained in:
parent
29353111ac
commit
c8fd3a01df
@ -97,6 +97,8 @@ set(dcc_LIB_SOURCES
|
||||
src/Loaders.h
|
||||
src/FollowControlFlow.cpp
|
||||
src/FollowControlFlow.h
|
||||
|
||||
src/AutomatedPlanner
|
||||
)
|
||||
set(dcc_UI_SOURCES
|
||||
src/ui/DccMainWindow.ui
|
||||
|
||||
@ -151,7 +151,7 @@ enum DecompilationStep : uint32_t {
|
||||
//eStackTracing, // tracing stack depth across function calls
|
||||
|
||||
};
|
||||
struct Function : public std::enable_shared_from_this<Function>
|
||||
class Function : public std::enable_shared_from_this<Function>
|
||||
{
|
||||
typedef llvm::iplist<BB> BasicBlockListType;
|
||||
// BasicBlock iterators...
|
||||
@ -216,6 +216,7 @@ public:
|
||||
// bool anyFlagsSet(uint32_t t) { return (flg&t)!=0;}
|
||||
bool hasRegArgs() const { return (flg & REG_ARGS)!=0;}
|
||||
void markDoNotDecompile() { flg |= PROC_ISLIB; }
|
||||
bool doNotDecompile() const { return isLibrary(); }
|
||||
bool isLibrary() const { return (flg & PROC_ISLIB)!=0;}
|
||||
void compoundCond();
|
||||
void writeProcComments();
|
||||
|
||||
45
src/AutomatedPlanner.cpp
Normal file
45
src/AutomatedPlanner.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
#include "AutomatedPlanner.h"
|
||||
|
||||
#include "project.h"
|
||||
#include "FollowControlFlow.h"
|
||||
|
||||
/**
|
||||
* @class AutomatedPlanner
|
||||
* @brief Class responsible for building command lists
|
||||
*
|
||||
* The goal for top level [Project] plan is to build a fully decompiled representation of source binaries
|
||||
*/
|
||||
|
||||
AutomatedPlanner::AutomatedPlanner()
|
||||
{
|
||||
|
||||
}
|
||||
/**
|
||||
* @brief Given a state of a project, add actions that will advance the decompilation
|
||||
* @param project
|
||||
*/
|
||||
void AutomatedPlanner::planFor(Project &project) {
|
||||
// TODO: For now this logic is sprinkled all over the place, should move it here
|
||||
// IF NO BINARY IMAGE LOADED - > add SelectImage/SelectProject command
|
||||
// IF NO LOADER SELECTED -> add SelectLoader command
|
||||
// ...
|
||||
}
|
||||
|
||||
void AutomatedPlanner::planFor(Function & func) {
|
||||
if(func.doNotDecompile())
|
||||
return; // for functions marked as non-decompileable we don't add any commands
|
||||
switch(func.nStep) {
|
||||
case eNotDecoded:
|
||||
addAction(func,new FollowControlFlow(func.state));
|
||||
}
|
||||
}
|
||||
|
||||
void AutomatedPlanner::addAction(Function & func, Command * cmd)
|
||||
{
|
||||
Project::get()->addCommand(func.shared_from_this(),cmd);
|
||||
}
|
||||
|
||||
void AutomatedPlanner::addAction(Project & func, Command * cmd)
|
||||
{
|
||||
func.addCommand(cmd);
|
||||
}
|
||||
20
src/AutomatedPlanner.h
Normal file
20
src/AutomatedPlanner.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef AUTOMATEDPLANNER_H
|
||||
#define AUTOMATEDPLANNER_H
|
||||
|
||||
class Project;
|
||||
class Function;
|
||||
class Command;
|
||||
|
||||
class AutomatedPlanner
|
||||
{
|
||||
public:
|
||||
AutomatedPlanner();
|
||||
|
||||
void planFor(Project & project);
|
||||
void planFor(Function & func);
|
||||
protected:
|
||||
void addAction(Function &func,Command *cmd);
|
||||
void addAction(Project &func,Command *cmd);
|
||||
};
|
||||
|
||||
#endif // AUTOMATEDPLANNER_H
|
||||
@ -25,7 +25,7 @@ public:
|
||||
}
|
||||
|
||||
Project *m_project;
|
||||
PtrFunction *m_func;
|
||||
PtrFunction m_func;
|
||||
QVector<QPair<Command *,QString>> m_failures;
|
||||
void reset();
|
||||
};
|
||||
|
||||
@ -1,11 +1,16 @@
|
||||
#include "FollowControlFlow.h"
|
||||
|
||||
#include "project.h"
|
||||
|
||||
QString FollowControlFlow::instanceDescription() const
|
||||
{
|
||||
return name() + " @ 0x"+QString::number(m_address,16);
|
||||
return name() + " @ 0x"+QString::number(m_start_state.IP,16);
|
||||
}
|
||||
|
||||
bool FollowControlFlow::execute(CommandContext *ctx)
|
||||
{
|
||||
Project &proj(*ctx->m_project);
|
||||
PtrFunction scanned_func(ctx->m_func);
|
||||
scanned_func->FollowCtrl(proj.callGraph, &m_start_state);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3,11 +3,13 @@
|
||||
|
||||
#include "Command.h"
|
||||
|
||||
#include "state.h"
|
||||
|
||||
class FollowControlFlow : public Command
|
||||
{
|
||||
uint32_t m_address;
|
||||
STATE m_start_state;
|
||||
public:
|
||||
FollowControlFlow(uint32_t addr) : Command("Follow control flow",eFunction),m_address(addr) {}
|
||||
FollowControlFlow(STATE addr) : Command("Follow control flow",eFunction),m_start_state(addr) {}
|
||||
|
||||
// Command interface
|
||||
public:
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#include "CallGraph.h"
|
||||
#include "msvc_fixes.h"
|
||||
#include "chklib.h"
|
||||
#include "FollowControlFlow.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
@ -116,6 +117,7 @@ ICODE *Function::translate_XCHG(LLInst *ll,ICODE &_Icode)
|
||||
* using a depth first search. */
|
||||
void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
|
||||
{
|
||||
Project *project(Project::get());
|
||||
PROG &prog(Project::get()->prog);
|
||||
ICODE _Icode, *pIcode; /* This gets copied to pProc->Icode[] later */
|
||||
SYM * psym;
|
||||
@ -201,7 +203,7 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
|
||||
StCopy = *pstate;
|
||||
|
||||
/* Straight line code */
|
||||
this->FollowCtrl (pcallGraph, &StCopy); // recurrent ?
|
||||
project->addCommand(shared_from_this(),new FollowControlFlow(StCopy)); // recurrent ?
|
||||
|
||||
if (fBranch) /* Do branching code */
|
||||
{
|
||||
@ -359,7 +361,7 @@ bool Function::followAllTableEntries(JumpTable &table, uint32_t cs, ICODE& pIcod
|
||||
StCopy.IP = cs + LH(&prog.image()[i]);
|
||||
iICODE last_current_insn = (++Icode.rbegin()).base();
|
||||
|
||||
FollowCtrl (pcallGraph, &StCopy);
|
||||
Project::get()->addCommand(shared_from_this(),new FollowControlFlow(StCopy));
|
||||
|
||||
++last_current_insn; // incremented here because FollowCtrl might have adde more instructions after the Jmp
|
||||
last_current_insn->ll()->caseEntry = k++;
|
||||
@ -446,7 +448,7 @@ bool Function::decodeIndirectJMP(ICODE & pIcode, STATE *pstate, CALL_GRAPH * pca
|
||||
uint32_t jump_target_location = table_addr + num_cases*2 + i*2;
|
||||
StCopy.IP = cs + *(uint16_t *)(prog.image()+jump_target_location);
|
||||
iICODE last_current_insn = (++Icode.rbegin()).base();
|
||||
FollowCtrl (pcallGraph, &StCopy);
|
||||
Project::get()->addCommand(shared_from_this(),new FollowControlFlow(StCopy));
|
||||
++last_current_insn;
|
||||
last_current_insn->ll()->caseEntry = i;
|
||||
last_current_insn->ll()->setFlags(CASE);
|
||||
@ -532,7 +534,7 @@ bool Function::decodeIndirectJMP2(ICODE & pIcode, STATE *pstate, CALL_GRAPH * pc
|
||||
uint32_t jump_target_location = table_addr + num_cases*4 + i*2;
|
||||
StCopy.IP = cs + *(uint16_t *)(prog.image()+jump_target_location);
|
||||
iICODE last_current_insn = (++Icode.rbegin()).base();
|
||||
FollowCtrl (pcallGraph, &StCopy);
|
||||
Project::get()->addCommand(shared_from_this(),new FollowControlFlow(StCopy));
|
||||
++last_current_insn;
|
||||
last_current_insn->ll()->caseEntry = i;
|
||||
last_current_insn->ll()->setFlags(CASE);
|
||||
@ -637,7 +639,8 @@ bool Function::process_JMP (ICODE & pIcode, STATE *pstate, CALL_GRAPH * pcallGra
|
||||
iICODE last_current_insn = (++Icode.rbegin()).base();
|
||||
//ip = Icode.size();
|
||||
|
||||
FollowCtrl (pcallGraph, &StCopy);
|
||||
Project::get()->addCommand(shared_from_this(),new FollowControlFlow(StCopy));
|
||||
|
||||
++last_current_insn;
|
||||
last_current_insn->ll()->caseEntry = k++;
|
||||
last_current_insn->ll()->setFlags(CASE);
|
||||
@ -658,6 +661,7 @@ bool Function::process_JMP (ICODE & pIcode, STATE *pstate, CALL_GRAPH * pcallGra
|
||||
|
||||
flg |= PROC_IJMP;
|
||||
flg &= ~TERMINATES;
|
||||
// TODO: consider adding a new user-interactive command ResolveControlFlowFailure ?
|
||||
interactDis(shared_from_this(), Icode.size()-1);
|
||||
return true;
|
||||
}
|
||||
@ -777,7 +781,7 @@ bool Function::process_CALL(ICODE & pIcode, CALL_GRAPH * pcallGraph, STATE *psta
|
||||
pcallGraph->insertCallGraph (this->shared_from_this(), iter);
|
||||
|
||||
/* Process new procedure */
|
||||
x.FollowCtrl (pcallGraph, pstate);
|
||||
Project::get()->addCommand(iter,new FollowControlFlow(*pstate));
|
||||
|
||||
/* Restore segment registers & IP from localState */
|
||||
pstate->IP = localState.IP;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#include "CommandQueueView.h"
|
||||
|
||||
#include "project.h"
|
||||
#include "../AutomatedPlanner.h"
|
||||
|
||||
#include "ui_CommandQueueView.h"
|
||||
|
||||
@ -43,3 +44,10 @@ void CommandQueueView::on_btnStep_clicked()
|
||||
Project &project(*Project::get());
|
||||
project.processCommands(1);
|
||||
}
|
||||
|
||||
void CommandQueueView::on_btnPlan_clicked()
|
||||
{
|
||||
AutomatedPlanner planner;
|
||||
// TODO: Use some kind of UI context to retrieve currently selected function
|
||||
//planner.planFor(func);
|
||||
}
|
||||
|
||||
@ -24,6 +24,8 @@ protected:
|
||||
private slots:
|
||||
void on_btnStep_clicked();
|
||||
|
||||
void on_btnPlan_clicked();
|
||||
|
||||
private:
|
||||
Ui::CommandQueueView *ui;
|
||||
};
|
||||
|
||||
@ -15,16 +15,40 @@
|
||||
</property>
|
||||
<widget class="QWidget" name="dockWidgetContents">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Planned actions:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListWidget" name="lstQueuedCommands"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnPlan">
|
||||
<property name="text">
|
||||
<string>Plan</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnStep">
|
||||
<property name="text">
|
||||
<string>Step</string>
|
||||
<string>Execute</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Completed actions:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListWidget" name="lstCompletedCommands"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
|
||||
@ -11,12 +11,12 @@
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>DockWidget</string>
|
||||
<string>Doc&kWidget</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="dockWidgetContents">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTableView" name="m_func_list_view">
|
||||
<widget class="QTreeView" name="m_func_list_view">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
@ -32,40 +32,7 @@
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>m_func_list_view</sender>
|
||||
<signal>activated(QModelIndex)</signal>
|
||||
<receiver>FunctionListDockWidget</receiver>
|
||||
<slot>displayRequest(QModelIndex)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>199</x>
|
||||
<y>161</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>199</x>
|
||||
<y>149</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>m_func_list_view</sender>
|
||||
<signal>clicked(QModelIndex)</signal>
|
||||
<receiver>FunctionListDockWidget</receiver>
|
||||
<slot>functionSelected(QModelIndex)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>199</x>
|
||||
<y>161</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>199</x>
|
||||
<y>149</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<connections/>
|
||||
<slots>
|
||||
<signal>displayRequested()</signal>
|
||||
<slot>displayRequest(QModelIndex)</slot>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user