Browse Source

New feature: option to decompile only a specific function.

Similar to boomerang's -E option:

```
dcc -E 0x1222 ./TARGET.EXE
```

Will only decompile function at given address.
This might help in isolating dcc crashes.
nemerle 8 years ago
parent
commit
d1738ea630
3 changed files with 32 additions and 6 deletions
  1. 1 0
      include/dcc.h
  2. 7 3
      src/dcc.cpp
  3. 24 3
      src/udm.cpp

+ 1 - 0
include/dcc.h

@@ -39,6 +39,7 @@ typedef struct {            /* Command line option flags */
     unsigned Interact       : 1;    /* Interactive mode */
     unsigned Calls          : 1;    /* Follow register indirect calls */
     QString	filename;			/* The input filename */
+    uint32_t CustomEntryPoint;
 } OPTION;
 
 extern OPTION option;       /* Command line options             */

+ 7 - 3
src/dcc.cpp

@@ -137,14 +137,17 @@ void setupOptions(QCoreApplication &app) {
         parser.addOption(o);
     }
     QCommandLineOption assembly("a", QCoreApplication::translate("main", "Produce assembly"),"assembly_level");
-    // A boolean option with multiple names (-f, --force)
-    //QCommandLineOption forceOption(QStringList() << "f" << "force", "Overwrite existing files.");
-    // An option with a value
     QCommandLineOption targetFileOption(QStringList() << "o" << "output",
                                         QCoreApplication::translate("main", "Place output into <file>."),
                                         QCoreApplication::translate("main", "file"));
+    QCommandLineOption entryPointOption(QStringList() << "E",
+                                        QCoreApplication::translate("main", "Custom entry point as hex"),
+                                        QCoreApplication::translate("main", "offset"),
+                                        "0"
+                                        );
     parser.addOption(targetFileOption);
     parser.addOption(assembly);
+    parser.addOption(entryPointOption);
     //parser.addOption(forceOption);
     // Process the actual command line arguments given by the user
     parser.addPositionalArgument("source", QCoreApplication::translate("main", "Dos Executable file to decompile."));
@@ -166,6 +169,7 @@ void setupOptions(QCoreApplication &app) {
     option.Interact = false;
     option.Calls = parser.isSet(boolOpts[2]);
     option.filename = args.first();
+    option.CustomEntryPoint = parser.value(entryPointOption).toUInt(0,16);
     if(parser.isSet(targetFileOption))
         asm1_name = asm2_name = parser.value(targetFileOption);
     else if(option.asm1 or option.asm2) {

+ 24 - 3
src/udm.cpp

@@ -12,6 +12,7 @@
 #include <list>
 #include <cassert>
 #include <stdio.h>
+#include <CallGraph.h>
 extern Project g_proj;
 //static void displayCFG(Function * pProc);
 //static void displayDfs(BB * pBB);
@@ -75,9 +76,16 @@ void udm(void)
 
     /* Build the control flow graph, find idioms, and convert low-level
      * icodes to high-level ones */
+    Project *proj = Project::get();
     Disassembler ds(2);
-    for (auto iter = Project::get()->pProcList.rbegin(); iter!=Project::get()->pProcList.rend(); ++iter)
+    for (auto iter = proj->pProcList.rbegin(); iter!=proj->pProcList.rend(); ++iter)
     {
+        Function &f(*iter);
+        if(option.CustomEntryPoint) {
+            if(f.procEntry!=option.CustomEntryPoint) {
+                continue;
+            }
+        }
         iter->buildCFG(ds);
     }
     if (option.asm2)
@@ -88,10 +96,23 @@ void udm(void)
      * and intermediate instructions.  Find expressions by forward
      * substitution algorithm */
     LivenessSet live_regs;
-    Project::get()->pProcList.front().dataFlow (live_regs);
+    if(option.CustomEntryPoint) {
+        ilFunction iter = proj->findByEntry(option.CustomEntryPoint);
+        if(iter==proj->pProcList.end()) {
+            qCritical()<< "No function found at entry point" << QString::number(option.CustomEntryPoint,16);
+            return;
+        }
+        iter->dataFlow(live_regs);
+        iter->controlFlowAnalysis();
+        delete proj->callGraph;
+        proj->callGraph = new CALL_GRAPH;
+        proj->callGraph->proc = iter;
+        return;
+    }
+    proj->pProcList.front().dataFlow (live_regs);
 
     /* Control flow analysis - structuring algorithm */
-    for (auto iter = Project::get()->pProcList.rbegin(); iter!=Project::get()->pProcList.rend(); ++iter)
+    for (auto iter = proj->pProcList.rbegin(); iter!=proj->pProcList.rend(); ++iter)
     {
         iter->controlFlowAnalysis();
     }