Browse Source

Trying to make parser to correctly handle CS

Godzil 5 years ago
parent
commit
7687c2b7d2
4 changed files with 127 additions and 8 deletions
  1. 3 3
      include/BinaryImage.h
  2. 1 1
      include/state.h
  3. 72 1
      src/DccFrontend.cpp
  4. 51 3
      src/parser.cpp

+ 3 - 3
include/BinaryImage.h

@@ -3,9 +3,9 @@
 #include <vector>
 struct PROG /* Loaded program image parameters  */
 {
-    int16_t     initCS=0;
-    int16_t     initIP=0;     /* These are initial load values    */
-    int16_t     initSS=0;     /* Probably not of great interest   */
+    uint16_t    initCS=0;
+    uint16_t    initIP=0;     /* These are initial load values    */
+    uint16_t    initSS=0;     /* Probably not of great interest   */
     uint16_t    initSP=0;
     bool        fCOM=false;       /* Flag set if COM program (else EXE)*/
     int         cReloc=0;     /* No. of relocation table entries  */

+ 1 - 1
include/state.h

@@ -11,7 +11,7 @@
 struct STATE
 {
     uint32_t      IP;             /* Offset into Image                    */
-    int16_t       r[INDEX_BX_SI];   /* Value of segs and AX                 */
+    uint16_t      r[INDEX_BX_SI];   /* Value of segs and AX                 */
     bool          f[INDEX_BX_SI];   /* True if r[.] has a value             */
     struct
     {                           /* For case stmt indexed reg            */

+ 72 - 1
src/DccFrontend.cpp

@@ -228,8 +228,55 @@ struct ComLoader : public DosLoader {
         prog.initSP = 0xFFFE;
         prog.cReloc = 0;
 
-        prepareImage(prog,cb,fp);
+        prepareImage(prog, cb, fp);
 
+        /* Set up memory map */
+        cb = (prog.cbImage + 3) / 4;
+        prog.map = (uint8_t *)malloc(cb);
+        memset(prog.map, BM_UNKNOWN, (size_t)cb);
+        return true;
+    }
+};
+struct RomLoader {
+    bool canLoad(QFile &fp) {
+        fp.seek(0xFFF0);
+        uint8_t sig[1];
+        if(fp.read((char *)sig,1) == 1)
+        {
+            return (sig[0] == 0xEA);
+        }
+        return false;
+    }
+    bool load(PROG &prog,QFile &fp) {
+        printf("Loading ROM...\n");
+        fp.seek(0);
+        /* ROM file
+         * In this case the load module size is just the file length
+         */
+        auto cb = fp.size();
+
+        fp.seek(cb - 0x10);
+        uint8_t buf[5];
+        printf("Going to get CS/IP...\n");
+        if(fp.read((char *)buf, 5) != 5)
+        {
+            return false;
+        }
+
+        fp.seek(0);
+
+        /* ROM File, Hard to say where it is suppose to start, so try to trust the
+         */
+        prog.initIP = (buf[2] << 8) | buf[1];
+        //prog.initCS = 0;
+        prog.initCS = (buf[4] << 8) | buf[3];
+
+        prog.initSS = 0;
+        prog.initSP = 0xFFFE;
+
+        prog.cReloc = 0;
+
+        prepareImage(prog, cb, fp);
 
         /* Set up memory map */
         cb = (prog.cbImage + 3) / 4;
@@ -237,6 +284,22 @@ struct ComLoader : public DosLoader {
         memset(prog.map, BM_UNKNOWN, (size_t)cb);
         return true;
     }
+
+protected:
+    void prepareImage(PROG &prog, size_t sz, QFile &fp)
+    {
+        int32_t start = 0x100000 - sz;
+        /* Allocate a block of memory for the program. */
+        prog.cbImage  = 1 * 1024 * 1024; /* Allocate the whole 1MB memory */
+        //prog.cbImage  = 64 * 1024; /* Allocate the whole 1MB memory */
+        prog.Imagez    = new uint8_t [prog.cbImage];
+
+        if (fp.read((char *)prog.Imagez + start, sz) != sz)
+        //if (fp.read((char *)prog.Imagez, sz) != sz)
+        {
+            fatalError(CANNOT_READ, fp.fileName().toLocal8Bit().data());
+        }
+    }
 };
 struct ExeLoader : public DosLoader {
     bool canLoad(QFile &fp) {
@@ -340,8 +403,16 @@ bool Project::load()
     {
         fatalError(CANNOT_READ, fname);
     }
+    RomLoader rom_loader;
     ComLoader com_loader;
     ExeLoader exe_loader;
+    if(rom_loader.canLoad(finfo)) {
+        /* We have no relacation and code should be on 64K only,
+         * So let's consider it as a COM file
+         */
+        prog.fCOM = true;
+        return rom_loader.load(prog,finfo);
+    }
     if(exe_loader.canLoad(finfo)) {
         prog.fCOM = false;
         return exe_loader.load(prog,finfo);

+ 51 - 3
src/parser.cpp

@@ -135,7 +135,7 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
     }
     if (option.VeryVerbose)
     {
-        qDebug() << "Parsing proc" << name << "at"<< QString::number(pstate->IP,16).toUpper();
+        qDebug() << "Parsing proc" << name << "at" << QString::number(pstate->IP,16).toUpper();
     }
 
     while (not done )
@@ -145,6 +145,7 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
             break;
         LLInst *ll = _Icode.ll();
         pstate->IP += (uint32_t)ll->numBytes;
+
         setBits(BM_CODE, ll->label, (uint32_t)ll->numBytes);
 
         process_operands(_Icode,pstate);
@@ -180,6 +181,7 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
             case iJCXZ:
             {
                 STATE   StCopy;
+                uint32_t  lastIp = pstate->IP - 2;
                 int     ip      = Icode.size()-1;	/* Index of this jump */
                 ICODE  &prev(*(++Icode.rbegin())); /* Previous icode */
                 bool   fBranch = false;
@@ -200,6 +202,13 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
                 }
                 StCopy = *pstate;
 
+                if (pstate->IP > 0x100000)
+                {
+                    printf("Something wrong with IP...\n");
+                }
+
+                printf("From %X condJump to %X\n", lastIp, pstate->IP);
+
                 /* Straight line code */
                 this->FollowCtrl (pcallGraph, &StCopy); // recurrent ?
 
@@ -546,6 +555,7 @@ bool Function::process_JMP (ICODE & pIcode, STATE *pstate, CALL_GRAPH * pcallGra
     PROG &prog(Project::get()->prog);
     static uint8_t i2r[4] = {rSI, rDI, rBP, rBX};
     ICODE       _Icode;
+    uint32_t     lastIp = pstate->IP - 1;
     uint32_t       cs, offTable, endTable;
     uint32_t       i, k, seg, target;
 
@@ -553,7 +563,33 @@ bool Function::process_JMP (ICODE & pIcode, STATE *pstate, CALL_GRAPH * pcallGra
     {
         if (pIcode.ll()->getOpcode() == iJMPF)
             pstate->setState( rCS, LH(prog.image() + pIcode.ll()->label + 3));
-        pstate->IP = pIcode.ll()->src().getImm2();
+
+        pstate->IP =  pIcode.ll()->src().getImm2();
+
+        if (pstate->IP == 0)
+        {
+            printf("debug...\n");
+        }
+
+        /* Need to use CS! */
+        if ((pIcode.ll()->getOpcode() != iJMPF) && (pIcode.ll()->getOpcode() != iJMP))
+        {
+            printf("debug\n");
+        }
+        if (pstate->IP > 0x10000)
+        {
+            printf("debug\n");
+        }
+
+        pstate->IP += pstate->r[rCS] << 4;
+
+        if (pstate->IP > 0x100000)
+        {
+            printf("Something wrong with IP (was %x)...\n", lastIp);
+        }
+
+        printf("From %X JMP(F) to %X\n", lastIp, pstate->IP);
+
         int64_t i = pIcode.ll()->src().getImm2();
         if (i < 0)
         {
@@ -677,6 +713,7 @@ bool Function::process_CALL(ICODE & pIcode, CALL_GRAPH * pcallGraph, STATE *psta
     PROG &prog(Project::get()->prog);
     ICODE &last_insn(Icode.back());
     STATE localState;     /* Local copy of the machine state */
+    uint32_t     lastIp = pstate->IP - 2;
     uint32_t off;
     /* For Indirect Calls, find the function address */
     bool indirect = false;
@@ -770,10 +807,21 @@ bool Function::process_CALL(ICODE & pIcode, CALL_GRAPH * pcallGraph, STATE *psta
             pstate->IP = pIcode.ll()->src().getImm2();
             if (pIcode.ll()->getOpcode() == iCALLF)
                 pstate->setState( rCS, LH(prog.image() + pIcode.ll()->label + 3));
+
+            /* Need to use CS! */
+            pstate->IP += pstate->r[rCS] << 4;
+
             x.state = *pstate;
 
             /* Insert new procedure in call graph */
-            pcallGraph->insertCallGraph (this, iter);
+-            pcallGraph->insertCallGraph (this, iter);
+
+            if (pstate->IP > 0x100000)
+            {
+                printf("Something wrong with IP (was %x)...\n", lastIp);
+            }
+
+            printf("From %X CALL to %X\n", lastIp, pstate->IP);
 
             /* Process new procedure */
             x.FollowCtrl (pcallGraph, pstate);