Function's command queue implemented, flow control scanning starts to

work.
This commit is contained in:
nemerle 2016-05-05 14:28:25 +02:00
parent c8fd3a01df
commit 6ade935e37
15 changed files with 152 additions and 40 deletions

View File

@ -11,14 +11,12 @@ struct IDcc {
static IDcc *get(); static IDcc *get();
virtual void BaseInit()=0; virtual void BaseInit()=0;
virtual void Init(QObject *tgt)=0; virtual void Init(QObject *tgt)=0;
virtual PtrFunction GetCurFuncHandle()=0;
virtual void analysis_Once()=0; virtual void analysis_Once()=0;
virtual bool load(QString name)=0; // load and preprocess -> find entry point virtual bool load(QString name)=0; // load and preprocess -> find entry point
virtual void prtout_asm(IStructuredTextTarget *,int level=0)=0; virtual void prtout_asm(PtrFunction f,IStructuredTextTarget *,int level=0)=0;
virtual void prtout_cpp(IStructuredTextTarget *,int level=0)=0; virtual void prtout_cpp(PtrFunction f,IStructuredTextTarget *,int level=0)=0;
virtual size_t getFuncCount()=0; virtual size_t getFuncCount()=0;
virtual const lFunction &validFunctions() const =0; virtual const lFunction &validFunctions() const =0;
virtual void SetCurFunc_by_Name(QString )=0;
virtual QDir installDir()=0; virtual QDir installDir()=0;
virtual QDir dataDir(QString kind)=0; virtual QDir dataDir(QString kind)=0;
}; };

View File

@ -148,9 +148,12 @@ public:
bool addCommand(Command *cmd); bool addCommand(Command *cmd);
bool addCommand(PtrFunction f, Command *cmd); // Add function level command bool addCommand(PtrFunction f, Command *cmd); // Add function level command
bool hasCommands(const PtrFunction &f);
CommandStream *functionCommands(const PtrFunction &f);
void dumpAllErrors(); void dumpAllErrors();
void setLoader(DosLoader *ins); void setLoader(DosLoader *ins);
void processCommands(int count=1); void processCommands(int count=1);
void processFunctionCommands(const PtrFunction & func, int count);
public slots: public slots:
void onCommandStreamFinished(bool state); void onCommandStreamFinished(bool state);
signals: signals:

View File

@ -3,6 +3,7 @@
#include "project.h" #include "project.h"
#include "FollowControlFlow.h" #include "FollowControlFlow.h"
#include <QtCore/QDebug>
/** /**
* @class AutomatedPlanner * @class AutomatedPlanner
* @brief Class responsible for building command lists * @brief Class responsible for building command lists
@ -28,6 +29,11 @@ void AutomatedPlanner::planFor(Project &project) {
void AutomatedPlanner::planFor(Function & func) { void AutomatedPlanner::planFor(Function & func) {
if(func.doNotDecompile()) if(func.doNotDecompile())
return; // for functions marked as non-decompileable we don't add any commands return; // for functions marked as non-decompileable we don't add any commands
//TODO: Consider cases where commands are queued, but we can still plan some additional steps
bool function_has_commands = Project::get()->hasCommands(func.shared_from_this());
if(function_has_commands) {
qDebug() << "Function "<<func.name<<"still has some commands queued, planning skipped";
}
switch(func.nStep) { switch(func.nStep) {
case eNotDecoded: case eNotDecoded:
addAction(func,new FollowControlFlow(func.state)); addAction(func,new FollowControlFlow(func.state));

View File

@ -61,7 +61,7 @@ public:
class CommandStream : public QObject class CommandStream : public QObject
{ {
Q_OBJECT Q_OBJECT
int m_maximum_command_count; int m_maximum_command_count=5;
public: public:
QVector<Command *> m_recently_executed; QVector<Command *> m_recently_executed;
QVector<Command *> m_commands; QVector<Command *> m_commands;
@ -70,6 +70,7 @@ public:
bool processOne(CommandContext *ctx); bool processOne(CommandContext *ctx);
void processAll(CommandContext *ctx); void processAll(CommandContext *ctx);
void clear(); void clear();
bool isEmpty() const { return m_commands.isEmpty(); }
signals: signals:
void streamCompleted(bool success); void streamCompleted(bool success);
void streamChanged(); void streamChanged();

View File

@ -212,10 +212,12 @@ bool CreateFunction::execute(CommandContext *ctx) {
the same as the initial CS segment (of the startup code) */ the same as the initial CS segment (of the startup code) */
proj.m_entry_state.setState(rCS, prog.segMain); proj.m_entry_state.setState(rCS, prog.segMain);
proj.m_entry_state.IP = prog.offMain; proj.m_entry_state.IP = prog.offMain;
func->state = proj.m_entry_state;
} }
if(m_name=="start") { if(m_name=="start") {
proj.addCommand(new MachineStateInitialization); proj.addCommand(new MachineStateInitialization);
proj.addCommand(new FindMain); proj.addCommand(new FindMain);
func->state = proj.m_entry_state; // just in case we fail to find main, initialize 'state'
} }
// proj.addCommand(new ProcessFunction); // proj.addCommand(new ProcessFunction);

View File

@ -92,7 +92,7 @@ void setupOptions(QCoreApplication &app) {
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
QCoreApplication::setApplicationName("dcc"); QCoreApplication::setApplicationName("dcc");
QCoreApplication::setApplicationVersion("0.1"); QCoreApplication::setApplicationVersion("0.2");
if(argc==1) { if(argc==1) {
QApplication app(argc,argv); QApplication app(argc,argv);
DccMainWindow win; DccMainWindow win;

View File

@ -28,7 +28,7 @@ public:
Project::get()->create(name); Project::get()->create(name);
return Project::get()->addLoadCommands(name); return Project::get()->addLoadCommands(name);
} }
void prtout_asm(IStructuredTextTarget *tgt, int level) void prtout_asm(PtrFunction f,IStructuredTextTarget *tgt, int level) override
{ {
// if (m_current_func->nStep == 0) // if (m_current_func->nStep == 0)
// return; // return;
@ -36,9 +36,9 @@ public:
// XmlOutPro out(iOut); // XmlOutPro out(iOut);
// FuncLL the(m_Cur_Func->ll.m_asmlist); // FuncLL the(m_Cur_Func->ll.m_asmlist);
// the.prtout_asm(m_Cur_Func, &m_Cur_Func->m_varll, &out); // the.prtout_asm(m_Cur_Func, &m_Cur_Func->m_varll, &out);
m_current_func->toStructuredText(tgt,level); f->toStructuredText(tgt,level);
} }
void prtout_cpp(IStructuredTextTarget *, int level) void prtout_cpp(PtrFunction f,IStructuredTextTarget *, int level) override
{ {
} }
bool isValidFuncHandle(ilFunction f) { bool isValidFuncHandle(ilFunction f) {

View File

@ -154,6 +154,26 @@ bool Project::addCommand(PtrFunction f, Command *cmd)
return res; return res;
} }
bool Project::hasCommands(const PtrFunction & f)
{
auto iter = m_function_streams.find(f);
if(iter!=m_function_streams.end()) {
return not iter->second.isEmpty();
}
return false;
}
CommandStream *Project::functionCommands(const PtrFunction & f)
{
if(f==nullptr)
return nullptr;
auto iter = m_function_streams.find(f);
if(iter!=m_function_streams.end()) {
return &iter->second;
}
return nullptr;
}
void Project::onCommandStreamFinished(bool state) void Project::onCommandStreamFinished(bool state)
{ {
if(false==state) { if(false==state) {
@ -196,6 +216,19 @@ void Project::processCommands(int count) {
} }
emit commandListChanged(); emit commandListChanged();
} }
void Project::processFunctionCommands(const PtrFunction &func,int count) {
m_command_ctx.m_project = this;
m_command_ctx.m_func = func;
CommandStream *cs = functionCommands(func);
if(nullptr==cs)
return;
while(count--) {
if(false==cs->processOne(&m_command_ctx)) {
break;
}
}
emit commandListChanged();
}
void Project::resetCommandsAndErrorState() void Project::resetCommandsAndErrorState()
{ {
m_error_state = false; m_error_state = false;

View File

@ -33,21 +33,39 @@ void CommandQueueView::changeEvent(QEvent *e)
void CommandQueueView::onCommandListChanged() { void CommandQueueView::onCommandListChanged() {
Project &project(*Project::get()); Project &project(*Project::get());
ui->lstQueuedCommands->clear(); ui->lstQueuedCommands->clear();
const CommandStream& cs(project.m_project_command_stream); CommandStream * func_stream = project.functionCommands(m_current_function);
for(const Command * cmd : cs.m_commands) { if(func_stream) {
for(const Command * cmd : func_stream->m_commands) {
ui->lstQueuedCommands->addItem(cmd->instanceDescription()); ui->lstQueuedCommands->addItem(cmd->instanceDescription());
} }
} }
const CommandStream& project_commands(project.m_project_command_stream);
for(const Command * cmd : project_commands.m_commands) {
ui->lstQueuedCommands->addItem(cmd->instanceDescription());
}
}
void CommandQueueView::onCurrentFunctionChanged(PtrFunction func)
{
m_current_function=func;
onCommandListChanged();
}
void CommandQueueView::on_btnStep_clicked() void CommandQueueView::on_btnStep_clicked()
{ {
Project &project(*Project::get()); Project &project(*Project::get());
if(nullptr!=m_current_function and project.hasCommands(m_current_function))
project.processFunctionCommands(m_current_function,1);
else
project.processCommands(1); project.processCommands(1);
} }
void CommandQueueView::on_btnPlan_clicked() void CommandQueueView::on_btnPlan_clicked()
{ {
AutomatedPlanner planner; AutomatedPlanner planner;
// TODO: Use some kind of UI context to retrieve currently selected function if(m_current_function!=nullptr) {
//planner.planFor(func); planner.planFor(*m_current_function);
}
else
planner.planFor(*Project::get());
} }

View File

@ -2,6 +2,8 @@
#define COMMANDQUEUEVIEW_H #define COMMANDQUEUEVIEW_H
#include <QtWidgets/QDockWidget> #include <QtWidgets/QDockWidget>
#include "Procedure.h"
namespace Ui { namespace Ui {
class CommandQueueView; class CommandQueueView;
@ -17,6 +19,7 @@ public:
public slots: public slots:
void onCommandListChanged(); void onCommandListChanged();
void onCurrentFunctionChanged(PtrFunction func);
protected: protected:
void changeEvent(QEvent *e); void changeEvent(QEvent *e);
@ -28,6 +31,7 @@ private slots:
private: private:
Ui::CommandQueueView *ui; Ui::CommandQueueView *ui;
PtrFunction m_current_function;
}; };
#endif // COMMANDQUEUEVIEW_H #endif // COMMANDQUEUEVIEW_H

View File

@ -30,13 +30,17 @@ DccMainWindow::DccMainWindow(QWidget *parent) :
m_command_queue = new CommandQueueView(this); m_command_queue = new CommandQueueView(this);
m_functionlist_widget = new FunctionListDockWidget(this); m_functionlist_widget = new FunctionListDockWidget(this);
m_functionlist_widget->setWindowTitle(QApplication::tr("Function list")); m_functionlist_widget->setWindowTitle(QApplication::tr("Function list"));
connect(m_functionlist_widget,SIGNAL(selectFunction(PtrFunction)),SLOT(onFunctionSelected(PtrFunction)));
connect(m_functionlist_widget,SIGNAL(displayRequested()), SLOT(displayCurrentFunction())); connect(m_functionlist_widget,SIGNAL(displayRequested()), SLOT(displayCurrentFunction()));
// we are beeing signalled when display is requested // we are beeing signalled when display is requested
connect(this,SIGNAL(functionListChanged()), m_functionlist_widget->model(),SLOT(updateFunctionList())); connect(this,SIGNAL(functionListChanged()), m_functionlist_widget->model(),SLOT(updateFunctionList()));
connect(Project::get(),SIGNAL(newFunctionCreated(PtrFunction)),SLOT(onNewFunction(PtrFunction))); connect(Project::get(),SIGNAL(newFunctionCreated(PtrFunction)),SLOT(onNewFunction(PtrFunction)));
this->addDockWidget(Qt::RightDockWidgetArea,m_functionlist_widget); this->addDockWidget(Qt::RightDockWidgetArea,m_functionlist_widget);
this->addDockWidget(Qt::LeftDockWidgetArea,m_command_queue); this->addDockWidget(Qt::LeftDockWidgetArea,m_command_queue);
connect(m_functionlist_widget,&FunctionListDockWidget::selectFunction,
m_command_queue, &CommandQueueView::onCurrentFunctionChanged);
m_asm_view = new FunctionViewWidget(this); m_asm_view = new FunctionViewWidget(this);
m_asm_view->setWindowTitle(tr("Assembly listing")); m_asm_view->setWindowTitle(tr("Assembly listing"));
ui->mdiArea->addSubWindow(m_asm_view); ui->mdiArea->addSubWindow(m_asm_view);
@ -64,6 +68,9 @@ void DccMainWindow::changeEvent(QEvent *e)
break; break;
} }
} }
void DccMainWindow::onFunctionSelected(PtrFunction func) {
m_selected_func = func;
}
void DccMainWindow::onNewFunction(PtrFunction f) { void DccMainWindow::onNewFunction(PtrFunction f) {
emit functionListChanged(); emit functionListChanged();
} }
@ -72,7 +79,7 @@ void DccMainWindow::onOptim()
Project::get()->processCommands(); Project::get()->processCommands();
g_EXE2C->analysis_Once(); g_EXE2C->analysis_Once();
emit functionListChanged(); emit functionListChanged();
if(m_last_display==g_EXE2C->GetCurFuncHandle()) if(m_last_display==m_selected_func)
{ {
displayCurrentFunction(); displayCurrentFunction();
} }
@ -82,7 +89,7 @@ void DccMainWindow::onOptim10()
for(int i=0; i<10; i++) for(int i=0; i<10; i++)
g_EXE2C->analysis_Once(); g_EXE2C->analysis_Once();
emit functionListChanged(); emit functionListChanged();
if(m_last_display==g_EXE2C->GetCurFuncHandle()) if(m_last_display==m_selected_func)
{ {
displayCurrentFunction(); displayCurrentFunction();
} }
@ -103,11 +110,11 @@ void DccMainWindow::onOpenFile_Action()
void DccMainWindow::displayCurrentFunction() void DccMainWindow::displayCurrentFunction()
{ {
if(m_last_display!=g_EXE2C->GetCurFuncHandle()) if(m_last_display!=m_selected_func)
m_last_display=g_EXE2C->GetCurFuncHandle(); m_last_display=m_selected_func;
g_EXE2C->prtout_asm(m_asm_view); g_EXE2C->prtout_asm(m_last_display, m_asm_view);
//g_EXE2C->prtout_itn(m_internal_view); //g_EXE2C->prtout_itn(m_internal_view);
g_EXE2C->prtout_cpp(m_c_view); g_EXE2C->prtout_cpp(m_last_display,m_c_view);
} }
void DccMainWindow::prt_log(const char *v) void DccMainWindow::prt_log(const char *v)
{ {

View File

@ -35,6 +35,7 @@ protected:
private slots: private slots:
void on_actionExit_triggered(); void on_actionExit_triggered();
void onNewFunction(PtrFunction f); void onNewFunction(PtrFunction f);
void onFunctionSelected(PtrFunction func);
private: private:
FunctionViewWidget *m_asm_view; FunctionViewWidget *m_asm_view;
@ -44,6 +45,7 @@ private:
FunctionListDockWidget *m_functionlist_widget; FunctionListDockWidget *m_functionlist_widget;
Ui::DccMainWindow *ui; Ui::DccMainWindow *ui;
PtrFunction m_last_display; PtrFunction m_last_display;
PtrFunction m_selected_func;
}; };
#endif // EXE2C_MAINWINDOW_H #endif // EXE2C_MAINWINDOW_H

View File

@ -21,15 +21,16 @@ FunctionListDockWidget::~FunctionListDockWidget()
{ {
delete ui; delete ui;
} }
void FunctionListDockWidget::functionSelected(const QModelIndex &idx) void FunctionListDockWidget::onFunctionSelected(const QModelIndex &idx)
{ {
QVariant v=m_list_model.data(m_list_model.index(idx.row(),0),Qt::DisplayRole); QVariant v=m_list_model.data(m_list_model.index(idx.row(),0),Qt::DisplayRole);
qDebug()<<"changed function to "<<v; qDebug()<<"changed function to "<<v;
g_EXE2C->SetCurFunc_by_Name(v.toString()); PtrFunction p(Project::get()->findByName(v.toString()));
emit selectFunction(p);
} }
// signalled by m_func_list_view accepted signal // signalled by m_func_list_view accepted signal
void FunctionListDockWidget::displayRequest(const QModelIndex &) void FunctionListDockWidget::onDisplayRequested(const QModelIndex &)
{ {
// argument ignored since functionSelected must've been called before us // argument ignored since functionSelected must've been called before us
emit displayRequested(); emit displayRequested();
@ -38,6 +39,17 @@ void FunctionListModel::updateFunctionList()
{ {
rebuildFunctionList(); rebuildFunctionList();
} }
void FunctionListModel::add_function(const QString & name, DecompilationStep step, int start_off, int end_off, int stack_purge)
{
function_info info;
info.m_name=name;
info.m_decoding_step=step;
info.m_start_off=start_off;
info.m_end_off=end_off;
info.m_stack_purge=stack_purge;
m_list.push_back(info);
}
void FunctionListModel::rebuildFunctionList() void FunctionListModel::rebuildFunctionList()
{ {
Project &project(*Project::get()); Project &project(*Project::get());

View File

@ -3,7 +3,9 @@
#include <QAbstractTableModel> #include <QAbstractTableModel>
#include <QDockWidget> #include <QDockWidget>
//#include "exe2c.h"
#include "Procedure.h"
enum DecompilationStep : uint32_t; enum DecompilationStep : uint32_t;
class FunctionListModel : public QAbstractTableModel class FunctionListModel : public QAbstractTableModel
{ {
@ -31,17 +33,7 @@ public slots:
void updateFunctionList(); void updateFunctionList();
protected: protected:
void add_function(const QString &name,DecompilationStep step,int start_off,int end_off,int stack_purge) void add_function(const QString &name,DecompilationStep step,int start_off,int end_off,int stack_purge);
{
function_info info;
info.m_name=name;
info.m_decoding_step=step;
info.m_start_off=start_off;
info.m_end_off=end_off;
info.m_stack_purge=stack_purge;
m_list.push_back(info);
}
void rebuildFunctionList(); void rebuildFunctionList();
}; };
@ -59,11 +51,12 @@ public:
~FunctionListDockWidget(); ~FunctionListDockWidget();
FunctionListModel *model() {return &m_list_model;} FunctionListModel *model() {return &m_list_model;}
public slots: public slots:
void displayRequest(const QModelIndex &idx); void onDisplayRequested(const QModelIndex &idx);
void functionSelected(const QModelIndex &idx); void onFunctionSelected(const QModelIndex &idx);
signals: signals:
void displayRequested(); void displayRequested();
void selectFunction(PtrFunction p);
private: private:
Ui::FunctionListDockWidget *ui; Ui::FunctionListDockWidget *ui;
FunctionListModel m_list_model; FunctionListModel m_list_model;

View File

@ -32,10 +32,43 @@
</widget> </widget>
</widget> </widget>
<resources/> <resources/>
<connections/> <connections>
<connection>
<sender>m_func_list_view</sender>
<signal>activated(QModelIndex)</signal>
<receiver>FunctionListDockWidget</receiver>
<slot>onDisplayRequested(QModelIndex)</slot>
<hints>
<hint type="sourcelabel">
<x>267</x>
<y>97</y>
</hint>
<hint type="destinationlabel">
<x>573</x>
<y>154</y>
</hint>
</hints>
</connection>
<connection>
<sender>m_func_list_view</sender>
<signal>clicked(QModelIndex)</signal>
<receiver>FunctionListDockWidget</receiver>
<slot>onFunctionSelected(QModelIndex)</slot>
<hints>
<hint type="sourcelabel">
<x>283</x>
<y>211</y>
</hint>
<hint type="destinationlabel">
<x>508</x>
<y>253</y>
</hint>
</hints>
</connection>
</connections>
<slots> <slots>
<signal>displayRequested()</signal> <signal>displayRequested()</signal>
<slot>displayRequest(QModelIndex)</slot> <slot>onDisplayRequested(QModelIndex)</slot>
<slot>functionSelected(QModelIndex)</slot> <slot>onFunctionSelected(QModelIndex)</slot>
</slots> </slots>
</ui> </ui>