📄 disasm.cpp
字号:
struct dialogboxheader
{ unsigned long style,extendedstyle;
unsigned short numberofitems;
unsigned short x,y;
unsigned short cx,cy;
};*/
if(exd)
{ addcomment(loc,"Signature+Version");
disdatadword(loc);
addcomment(loc+4,"HelpID");
disdatadword(loc+4);
loc=loc+8;
}
if(exd)
addcomment(loc,"Extended Style");
else
addcomment(loc,"Style");
disdatadword(loc);
if(exd)
addcomment(loc+4,"Style");
else
addcomment(loc+4,"Extended Style");
disdatadword(loc+4);
addcomment(loc+8,"Number of Items");
disdataword(loc+8);
addcomment(loc+10,"x");
disdataword(loc+10);
addcomment(loc+12,"y");
disdataword(loc+12);
addcomment(loc+14,"cx");
disdataword(loc+14);
addcomment(loc+16,"cy");
disdataword(loc+16);
cloc=loc+18;
addcomment(cloc,"Menu name/ordinal");
ilen=disname_or_ordinal(cloc,false);
cloc+=ilen;
addcomment(cloc,"Class name/ordinal");
ilen=disname_or_ordinal(cloc,false);
cloc+=ilen;
addcomment(cloc,"Caption");
disdataucstring(cloc);
cloc+=getlength(cloc);
findit=dsmfindaddrtype(loc+4*(exd?1:0),dsmcode);
hdrstyle=0;
if(findit!=NULL)
{ if((findit->addr==loc+4*(exd?1:0))&&(findit->type==dsmcode))
hdrstyle=((dword *)findit->data)[0];
}
// i noticed a reference to DS_SHELLFONT on msdn, but what is that ????????
if (hdrstyle&DS_SETFONT) // if ds_setfont then 2 more items...in theory
{ addcomment(cloc,"font pointsize");
disdataword(cloc);
cloc+=2;
if(exd) // more options with exd
{ addcomment(cloc,"weight");
disdataword(cloc);
cloc+=2;
addcomment(cloc,"italic");
//disdatabyte(cloc);
cloc+=1;
addcomment(cloc,"charset");
//disdatabyte(cloc);
cloc+=1;
}
addcomment(cloc,"font");
disdataucstring(cloc);
cloc+=getlength(cloc);
}
// now do controls
findit=dsmfindaddrtype(loc+8,dsmcode);
numctrls=0;
if(findit!=NULL)
{ if((findit->addr==loc+8)&&(findit->type==dsmcode))
numctrls=((word *)findit->data)[0];
}
/*struct ctrlheader
{ unsigned long style,extendedstyle;
unsigned short x,y;
unsigned short cx,cy;
unsigned short wid;
};*/
while(numctrls)
{ if(cloc.offs&0x03)
cloc.offs=(cloc.offs|0x03)+1;
if(exd)
{ addcomment(cloc,"HelpID");
disdatadword(cloc);
cloc+=4;
}
if(exd)
addcomment(cloc,"Extended Style");
else
addcomment(cloc,"Style");
disdatadword(cloc);
if(exd)
addcomment(cloc+4,"Style");
else
addcomment(cloc+4,"Extended Style");
disdatadword(cloc+4);
addcomment(cloc+8,"x");
disdataword(cloc+8);
addcomment(cloc+10,"y");
disdataword(cloc+10);
addcomment(cloc+12,"cx");
disdataword(cloc+12);
addcomment(cloc+14,"cy");
disdataword(cloc+14);
addcomment(cloc+16,"wid");
disdataword(cloc+16);
cloc+=18;
if(exd)
if(cloc.offs&0x03)
cloc.offs=(cloc.offs|0x03)+1;
addcomment(cloc,"Class id");
ilen=disname_or_ordinal(cloc,true);
cloc+=ilen;
addcomment(cloc,"Text");
ilen=disname_or_ordinal(cloc,false);
cloc+=ilen;
addcomment(cloc,"Extra Stuff");
disdataword(cloc);
findit=dsmfindaddrtype(cloc,dsmcode);
if(findit!=NULL)
{ if((findit->addr==cloc)&&(findit->type==dsmcode))
cloc+=((word *)findit->data)[0];
}
cloc+=2;
numctrls--;
}
}
#ifdef __BORLANDC__
#pragma warn +par
#endif
/************************************************************************
* disstringtable *
* - disassembles a string table, by which I mean that the strings are *
* disassembled into strings and the locations are named according to *
* the strings id numbers (I chose this in preference to naming by *
* string because they are a resource, and so the locations will not *
* be referenced, but if the program wants to use them then it will *
* use the id numbers, and make an API call to get hold of them). *
************************************************************************/
void disasm::disstringtable(lptr loc,char *basename)
{ int i;
lptr cloc;
char callit[40];
dword idnum;
int ipt;
dsmitem *lastdsm;
ipt=0;
idnum=0;
if(basename!=NULL)
{ while((basename[ipt])&&(basename[ipt]!=':'))
ipt++;
if(basename[ipt]==':')
{ ipt++;
while(basename[ipt])
{ if(basename[ipt]>='a')
idnum=idnum*16+basename[ipt]-'a'+10;
else
idnum=idnum*16+basename[ipt]-'0';
ipt++;
if(basename[ipt]=='h')
break;
}
}
}
cloc=loc;
for(i=0;i<16;i++) // 16 strings in a stringtable, of type unicode_pascal.
{ disdataupstring(cloc);
if(idnum)
{ wsprintf(callit,"String_ID_%lx",(idnum-1)*16+i);
name.addname(cloc,callit);
}
lastdsm=dsmfindaddrtype(cloc,dsmcode);
if(lastdsm==NULL)
break;
if((lastdsm->type!=dsmcode)||(lastdsm->addr!=cloc))
break;
cloc+=lastdsm->length;
}
}
/************************************************************************
* codeseek *
* - this is the aggressive code search if it is chosen as an option. It *
* has a low priority, and so appears near the end of the queue. It *
* hunts for possible code to disassemble in the code segments (added *
* as a task during file load for each code segment). When it finds an *
* undisassembled byte it tries to disassemble from that point, and *
* drops into the background again until disassembly has been done *
* - note that if it doesnt find anything in a short time it exits and *
* puts a continuation request in to the scheduler, this ensures that *
* userrequests are answered quickly *
************************************************************************/
void disasm::codeseek(lptr loc)
{ bool doneblock;
dsegitem *dblock;
dsmitem *tblock;
int dcount,ilength;
// check if already done.
dblock=dta.findseg(loc); // find segment item.
dcount=0;
if(dblock==NULL)
return;
do{
doneblock=false;
ilength=1;
dsmfindaddrtype(loc,dsmnull);
tblock=nextiterator();
tblock=nextiter_code(tblock);
if(tblock!=NULL)
{ if((tblock->addr.segm==loc.segm)&&(dsmitem_contains_loc(tblock,loc)))
doneblock=true;
while(tblock->addr==loc)
{ if(tblock->length)
ilength=tblock->length;
if(tblock->type!=dsmcomment)
{ doneblock=true;
break;
}
tblock=nextiterator();
if(tblock==NULL)
break;
}
}
if(doneblock)
{ loc+=ilength;
dcount++;
if(loc>=(dblock->addr+dblock->size))
return;
if(dcount>1000)
{ // dont forget the main thread!
scheduler.addtask(seek_code,priority_continuation,loc,NULL);
return;
}
}
} while (doneblock);
// decode it.
scheduler.addtask(seek_code,priority_aggressivesearch,loc+1,NULL);
scheduler.addtask(dis_code,priority_possiblecode,loc,NULL);
}
/************************************************************************
* disexportblock *
* - this disassembles a block of code, from an export address, but only *
* if the export address is in a code segment *
************************************************************************/
void disasm::disexportblock(lptr loc)
{ dsegitem *dblock;
dblock=dta.findseg(loc);
if(dblock==NULL)
return;
if(dblock->typ==code32)
disblock(loc);
}
/************************************************************************
* disblock *
* - disassembles a block from the starting point loc, calling *
* decodeinst for each instruction. *
* - we dont just keep going in here, but only disassemble a few *
* instructions then ask for a continuation and quit back to the *
* scheduler for userrequests to be processed. If Borg seems to slow *
* on your machine when you scroll around and it is still analysing *
* then try dropping the number of instructions to disassemble and *
* window updates should occur more often. *
* - If Borg cannot disassemble for whatever reason, or if a ret or jmp *
* type instruction is reached then we finish. *
************************************************************************/
void disasm::disblock(lptr loc)
{ byte ibuff[20]; // ibuff is the disassembly buffer - m/c is moved here
// for disassembly - no checking of eof is then needed
// until after the code is identified.
dsegitem *dblock;
int i,disasmcount;
bool doneblock;
dsmitem *tblock;
dword aaddr;
byte *mcode;
asminstdata *codefound;
dblock=dta.findseg(loc); // find segment item.
disasmcount=0;
if(dblock==NULL)
return;
if(dblock->typ==uninitdata)
return;
if(loc>=dblock->addr+dblock->size)
return;
doneblock=false;
while(!doneblock)
{ // don't spend too long in here
disasmcount++;
if(disasmcount>50)
{ scheduler.addtask(dis_code,priority_continuation,loc,NULL);
return;
}
memset(ibuff,0,20);
// check if already done.
dsmfindaddrtype(loc,dsmnull);
tblock=nextiterator();
tblock=nextiter_code(tblock);
if(tblock!=NULL)
{ if((tblock->addr.segm==loc.segm)&&(dsmitem_contains_loc(tblock,loc)))
doneblock=true;
while(tblock->addr==loc)
{ if(tblock->type!=dsmcomment)
{ doneblock=true;
break;
}
tblock=nextiterator();
if(tblock==NULL)
break;
}
}
// decode it.
if(doneblock)
break;
aaddr=loc-dblock->addr;
mcode=dblock->data+aaddr;
i=0;
while((i<15)&&(aaddr<dblock->size))
{ ibuff[i]=mcode[i];
i++;
aaddr++;
}
tblock=decodeinst(ibuff,mcode,loc,TABLE_MAIN,options.mode32,0);
if(tblock!=NULL)
{ if(!checkvalid(tblock))
{ delete tblock;
tblock=NULL;
}
}
if(tblock!=NULL)
{ addto(tblock);
//check if need to update window.
dio.updatewindowifinrange(loc);
loc.offs+=tblock->length;
if((loc-dblock->addr)>dblock->size)
{ doneblock=true;
delfrom(tblock);
}
}
else
doneblock=true;
if(doneblock)
break;
// check if end (jmp,ret,etc)
codefound=(asminstdata *)tblock->tptr;
if((codefound->flags&FLAGS_JMP)||(codefound->flags&FLAGS_RET))
doneblock=true;
}
}
/************************************************************************
* decodeinst *
* - disassembles one instruction *
* - in some ways this is the single most important function in Borg. It *
* disassembles an instruction adding a disassembled item to the *
* database. It uses the options we have set, and the processor tables *
* identified. *
* - If some kind of call or conditional jump is reached then Borg *
* just adds another disassembly task to the scheduler to look at *
* later, and then carries on. *
* - Note that this function is recursive, for handling some complex *
* x86 overrides, note that the recursion depth is limited but Borg *
* should handle complex prefix byte sequences and 'double sequences' *
* - The majority of the code here is some of the oldest code in Borg, *
* and probably some of the most complex. *
* - xreffing and windowupdates are performed from here *
************************************************************************/
dsmitem *disasm::decodeinst(byte *ibuff,byte *mcode,lptr loc,byte tabtype,bool omode32,int depth)
{ int tablenum=0; // asmtable table number
int instnum; // instruction num in table
asminstdata *insttab;
dsmitem *newdsm;
dword flgs; // inst flags
argtype a1,a2,a3; // inst args
lptr j; // jump/call target
byte *dta;
byte length;
gnameitem *imp;
char impname[GNAME_MAXLEN+1];
bool righttable;
byte cbyte,mbyte;
bool fupbyte;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -