Trying to make parser to correctly handle CS

This commit is contained in:
Godzil 2018-09-18 18:50:13 +01:00
parent 0abbce6f4e
commit 7687c2b7d2
4 changed files with 128 additions and 9 deletions

View File

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

View File

@ -11,7 +11,7 @@
struct STATE struct STATE
{ {
uint32_t IP; /* Offset into Image */ 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 */ bool f[INDEX_BX_SI]; /* True if r[.] has a value */
struct struct
{ /* For case stmt indexed reg */ { /* For case stmt indexed reg */

View File

@ -230,6 +230,53 @@ struct ComLoader : public DosLoader {
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 */ /* Set up memory map */
cb = (prog.cbImage + 3) / 4; cb = (prog.cbImage + 3) / 4;
@ -237,6 +284,22 @@ struct ComLoader : public DosLoader {
memset(prog.map, BM_UNKNOWN, (size_t)cb); memset(prog.map, BM_UNKNOWN, (size_t)cb);
return true; 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 { struct ExeLoader : public DosLoader {
bool canLoad(QFile &fp) { bool canLoad(QFile &fp) {
@ -340,8 +403,16 @@ bool Project::load()
{ {
fatalError(CANNOT_READ, fname); fatalError(CANNOT_READ, fname);
} }
RomLoader rom_loader;
ComLoader com_loader; ComLoader com_loader;
ExeLoader exe_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)) { if(exe_loader.canLoad(finfo)) {
prog.fCOM = false; prog.fCOM = false;
return exe_loader.load(prog,finfo); return exe_loader.load(prog,finfo);

View File

@ -145,6 +145,7 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
break; break;
LLInst *ll = _Icode.ll(); LLInst *ll = _Icode.ll();
pstate->IP += (uint32_t)ll->numBytes; pstate->IP += (uint32_t)ll->numBytes;
setBits(BM_CODE, ll->label, (uint32_t)ll->numBytes); setBits(BM_CODE, ll->label, (uint32_t)ll->numBytes);
process_operands(_Icode,pstate); process_operands(_Icode,pstate);
@ -180,6 +181,7 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
case iJCXZ: case iJCXZ:
{ {
STATE StCopy; STATE StCopy;
uint32_t lastIp = pstate->IP - 2;
int ip = Icode.size()-1; /* Index of this jump */ int ip = Icode.size()-1; /* Index of this jump */
ICODE &prev(*(++Icode.rbegin())); /* Previous icode */ ICODE &prev(*(++Icode.rbegin())); /* Previous icode */
bool fBranch = false; bool fBranch = false;
@ -200,6 +202,13 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
} }
StCopy = *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 */ /* Straight line code */
this->FollowCtrl (pcallGraph, &StCopy); // recurrent ? 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); PROG &prog(Project::get()->prog);
static uint8_t i2r[4] = {rSI, rDI, rBP, rBX}; static uint8_t i2r[4] = {rSI, rDI, rBP, rBX};
ICODE _Icode; ICODE _Icode;
uint32_t lastIp = pstate->IP - 1;
uint32_t cs, offTable, endTable; uint32_t cs, offTable, endTable;
uint32_t i, k, seg, target; 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) if (pIcode.ll()->getOpcode() == iJMPF)
pstate->setState( rCS, LH(prog.image() + pIcode.ll()->label + 3)); 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(); int64_t i = pIcode.ll()->src().getImm2();
if (i < 0) if (i < 0)
{ {
@ -677,6 +713,7 @@ bool Function::process_CALL(ICODE & pIcode, CALL_GRAPH * pcallGraph, STATE *psta
PROG &prog(Project::get()->prog); PROG &prog(Project::get()->prog);
ICODE &last_insn(Icode.back()); ICODE &last_insn(Icode.back());
STATE localState; /* Local copy of the machine state */ STATE localState; /* Local copy of the machine state */
uint32_t lastIp = pstate->IP - 2;
uint32_t off; uint32_t off;
/* For Indirect Calls, find the function address */ /* For Indirect Calls, find the function address */
bool indirect = false; bool indirect = false;
@ -770,10 +807,21 @@ bool Function::process_CALL(ICODE & pIcode, CALL_GRAPH * pcallGraph, STATE *psta
pstate->IP = pIcode.ll()->src().getImm2(); pstate->IP = pIcode.ll()->src().getImm2();
if (pIcode.ll()->getOpcode() == iCALLF) if (pIcode.ll()->getOpcode() == iCALLF)
pstate->setState( rCS, LH(prog.image() + pIcode.ll()->label + 3)); pstate->setState( rCS, LH(prog.image() + pIcode.ll()->label + 3));
/* Need to use CS! */
pstate->IP += pstate->r[rCS] << 4;
x.state = *pstate; x.state = *pstate;
/* Insert new procedure in call graph */ /* 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 */ /* Process new procedure */
x.FollowCtrl (pcallGraph, pstate); x.FollowCtrl (pcallGraph, pstate);