Trying to make parser to correctly handle CS
This commit is contained in:
parent
0abbce6f4e
commit
7687c2b7d2
@ -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 */
|
||||||
|
|||||||
@ -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 */
|
||||||
|
|||||||
@ -228,8 +228,7 @@ struct ComLoader : public DosLoader {
|
|||||||
prog.initSP = 0xFFFE;
|
prog.initSP = 0xFFFE;
|
||||||
prog.cReloc = 0;
|
prog.cReloc = 0;
|
||||||
|
|
||||||
prepareImage(prog,cb,fp);
|
prepareImage(prog, cb, fp);
|
||||||
|
|
||||||
|
|
||||||
/* Set up memory map */
|
/* Set up memory map */
|
||||||
cb = (prog.cbImage + 3) / 4;
|
cb = (prog.cbImage + 3) / 4;
|
||||||
@ -238,6 +237,70 @@ struct ComLoader : public DosLoader {
|
|||||||
return true;
|
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;
|
||||||
|
prog.map = (uint8_t *)malloc(cb);
|
||||||
|
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 {
|
struct ExeLoader : public DosLoader {
|
||||||
bool canLoad(QFile &fp) {
|
bool canLoad(QFile &fp) {
|
||||||
if(fp.size()<sizeof(header))
|
if(fp.size()<sizeof(header))
|
||||||
@ -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);
|
||||||
|
|||||||
@ -135,7 +135,7 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
|
|||||||
}
|
}
|
||||||
if (option.VeryVerbose)
|
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 )
|
while (not done )
|
||||||
@ -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);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user