Add AutomatedPlanner skeleton class

This commit is contained in:
nemerle 2016-05-04 14:22:28 +02:00
parent 29353111ac
commit c8fd3a01df
12 changed files with 130 additions and 50 deletions

View File

@ -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

View File

@ -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
View 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
View 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

View File

@ -25,7 +25,7 @@ public:
}
Project *m_project;
PtrFunction *m_func;
PtrFunction m_func;
QVector<QPair<Command *,QString>> m_failures;
void reset();
};

View File

@ -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;
}

View File

@ -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:

View File

@ -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;

View File

@ -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);
}

View File

@ -24,6 +24,8 @@ protected:
private slots:
void on_btnStep_clicked();
void on_btnPlan_clicked();
private:
Ui::CommandQueueView *ui;
};

View File

@ -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>

View File

@ -11,12 +11,12 @@
</rect>
</property>
<property name="windowTitle">
<string>DockWidget</string>
<string>Doc&amp;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>