Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

890 lines
22 KiB

/*++
Copyright (c) 1992,3 Digital Equipment Corporation
Module Name:
d3.c
Abstract:
Author:
Miche Baker-Harvey (mbh) Nov 1992
Environment:
Win32 -- User
Notes:
Largely taken from NTSD code.
--*/
#include "precomp.h"
#pragma hdrstop
#include "alphaops.h"
#include "optable.h"
#include "ntdis.h"
#include "ntasm.h"
typedef LPCH FAR *LPLPCH;
#define MAXL 20
char lhexdigit[] = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
char uhexdigit[] = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
char *hexdigit = &uhexdigit[0];
static int fUpper = TRUE;
static int EAsize [2] = {0}; // size of effective address item
static long EAaddr [2] = {0}; // offset of effective address
int DumpAddress ( LPADDR, LPCH, int );
int DumpGeneric ( LSZ, LPCH, int );
int DumpComment ( LSZ, LPCH, int );
int DumpEA ( HPID, HTID, LPADDR, LPCH, int );
void OutputEffectiveAddress(ULONG);
void OutputAddr(LPLPCH , LPADDR, int );
void OutputHexString(LPLPCH , LPCH, int);
void OutputHexCode(LPLPCH , LPCH, int);
ULONG GetIntRegNumber (ULONG);
extern BOOLEAN GetMemDword(PULONG, PULONG);
static char *PBuf;
static int CchBuf;
extern RD Rgrd[];
ALPHA_INSTRUCTION disinstr;
#define OPRNDCOL 27 // Column for first operand
#define EACOL 40 // column for effective address
#define FPTYPECOL 40 // .. for the type of FP instruction
/////////////// from ntdis.c above
void CalcMain (HPID, HTID, DOP, LPADDR, LPB, int, int*, LPCH, int, LPCH, int,
LPCH, int, LPCH, int);
/****disasm - disassemble an ALPHA instruction
*
* Input:
* pOffset = pointer to offset to start disassembly
* fEAout = if set, include EA (effective address)
*
* Output:
* pOffset = pointer to offset of next instruction
* pchDst = pointer to result string
*
***************************************************************************/
#define CCHMAX 256
static char rgchDisasm [ CCHMAX ];
//
// MBH - this code is the same for MIPS and i386 and doesn't
// seem to have any (but one) machine dependencies in it.
//
XOSD
disasm ( HPID hpid, HTID htid, LPSDI lpsdi )
{
XOSD xosd = xosdNone;
int cchMax = CCHMAX;
DOP dop = lpsdi->dop;
LPCH lpchOut = rgchDisasm;
int ichCur = 0;
ADDR addrStart = lpsdi->addr;
int cch = 0;
int cb;
int cbUsed=0;
BYTE rgb [ MAXL ];
char rgchRaw [ MAXL * 2 + 1 ];
char rgchOpcode [ 80 ];
char rgchOperands [ 80 ];
char rgchEA [ 44 ];
char rgchComment [ 80 ];
_fmemset ( rgchRaw, 0, sizeof ( rgchRaw ) );
_fmemset ( rgchOpcode, 0, sizeof ( rgchOpcode ) );
_fmemset ( rgchOperands, 0, sizeof ( rgchOperands ) );
_fmemset ( rgchEA, 0, sizeof ( rgchEA ) );
_fmemset ( rgchComment, 0, sizeof ( rgchComment ) );
lpsdi->ichAddr = -1;
lpsdi->ichBytes = -1;
lpsdi->ichOpcode = -1;
lpsdi->ichOperands = -1;
lpsdi->ichComment = -1;
lpsdi->ichEA0 = -1;
lpsdi->ichEA1 = -1;
lpsdi->ichEA2 = -1;
lpsdi->cbEA0 = 0;
lpsdi->cbEA1 = 0;
lpsdi->cbEA2 = 0;
lpsdi->fAssocNext = 0;
lpsdi->lpch = rgchDisasm;
// Set up for upper or lower case
fUpper = ( dop & dopUpper ) == dopUpper;
if ( fUpper ) {
hexdigit = uhexdigit;
}
else {
hexdigit = lhexdigit;
}
SETADDRMODE ( addrStart );
// Output the address if it is requested
if ( ( dop & dopAddr ) == dopAddr ) {
cch = DumpAddress ( &addrStart, lpchOut, cchMax );
lpsdi->ichAddr = 0;
cchMax -= cch;
lpchOut += cch;
ichCur += cch;
}
EMFunc ( emfSetAddr, hpid, htid, adrCurrent, (LONG) &addrStart );
cb = EMFunc ( emfReadBuf, hpid, htid, MAXL, (LONG) (LPV) rgb );
if ( cb <= 0 ) {
_fmemcpy ( rgchRaw, " ??", 4 );
_fmemcpy ( rgchOpcode, "???", 4 );
offAddr ( lpsdi->addr )++;
}
else {
CalcMain (
hpid,
htid,
lpsdi->dop,
&lpsdi->addr,
rgb,
cb,
&cbUsed,
rgchOpcode, sizeof(rgchOpcode),
rgchOperands, sizeof(rgchOperands),
rgchComment, sizeof(rgchComment),
rgchEA, sizeof(rgchEA)
);
// MBH - for debugging
// DbgPrint("CalcMain returns: Opcode %s Operands %s\n",
// rgchOpcode, rgchOperands);
// DbgPrint(" Comment %s EA %s\n",
// rgchComment, rgchEA);
// NOTENOTE jimsch - cbUsed must be 4
cbUsed = 4;
if ( offAddr(lpsdi->addr) > 0xFFFFFFFF - cbUsed ) {
return xosdBadAddress;
}
if ( dop & dopRaw ) {
LPCH lpchT = rgchRaw;
OutputHexCode ( &lpchT, rgb, cbUsed );
*lpchT = '\0';
}
}
if ( ( dop & dopRaw ) && ( cchMax > 0 ) ) {
cch = DumpGeneric ( rgchRaw, lpchOut, cchMax );
lpsdi->ichBytes = ichCur;
cchMax -= cch;
lpchOut += cch;
ichCur += cch;
}
if ( ( dop & dopOpcode ) && ( cchMax > 0 ) ) {
cch = DumpGeneric ( rgchOpcode, lpchOut, cchMax );
lpsdi->ichOpcode = ichCur;
cchMax -= cch;
lpchOut += cch;
ichCur += cch;
}
if ( ( dop & dopOperands ) && ( cchMax > 0 ) && ( rgchOperands [ 0 ] != '\0' ) ) {
cch = DumpGeneric ( rgchOperands, lpchOut, cchMax );
lpsdi->ichOperands = ichCur;
cchMax -= cch;
lpchOut += cch;
ichCur += cch;
}
if ( ( dop & dopOperands ) && ( cchMax > 0 ) && ( rgchComment [ 0 ] != '\0' ) ) {
cch = DumpComment ( rgchComment, lpchOut, cchMax );
lpsdi->ichComment = ichCur;
cchMax -= cch;
lpchOut += cch;
ichCur += cch;
}
if ( (dop & dopEA) && (cchMax > 0) ) {
cch = DumpGeneric ( rgchEA, lpchOut, cchMax );
//
/// cch = DumpEA ( hpid, htid, &lpsdi->addrEA0, lpchOut, cchMax );
//
if ( cch > 0 ) {
lpsdi->ichEA0 = ichCur;
cchMax -= cch;
lpchOut += cch;
ichCur += cch;
}
}
offAddr ( lpsdi->addr ) += cbUsed;
return xosd;
}
void OutputString (PUCHAR pStr)
{
int cb;
cb = strlen(pStr);
if (CchBuf < cb) {
cb = CchBuf - 1;
}
strncpy(PBuf, pStr, cb);
PBuf[cb] = 0;
if (fUpper) {
_strupr(PBuf);
} else {
_strlwr(PBuf);
}
PBuf += cb;
CchBuf -= cb;
return;
}
void OutputReg (ULONG regnum)
{
assert(regnum < 32);
OutputString(Rgrd[regnum].lpsz);
}
void OutputFReg (ULONG regnum)
{
assert(regnum < 32);
OutputString(Rgrd[regnum+36].lpsz);
}
void OutputHex (ULONG outvalue, ULONG length, BOOLEAN fSigned)
{
UCHAR digit[8];
LONG index = 0;
if (fSigned && (long)outvalue < 0) {
if (CchBuf > 1) {
*PBuf++ = '-';
CchBuf -= 1;
}
outvalue = (ULONG) (- (LONG) outvalue);
}
if (CchBuf > 2) {
*PBuf++ = '0';
*PBuf++ = (fUpper) ? 'X' : 'x';
CchBuf -= 2;
}
do {
digit[index++] = hexdigit[outvalue & 0xf];
outvalue >>= 4;
}
while (outvalue || (!fSigned && index < (LONG)length));
if (CchBuf > index) {
CchBuf -= index;
while (--index >= 0) {
*PBuf++ = digit[index];
}
}
return;
}
//
// This is stolen and modified from ntsd\alpha\ntdis.c (disasm())
// version ntsd.c@v16 (11-14-92)
//
void
CalcMain (
HPID hpid,
HTID htid,
DOP dop,
LPADDR lpaddr,
LPB rgb,
int cbMax,
int FAR *lpcbUsed,
LPCH rgchOpcode,
int cchOpcode,
LPCH rgchOperands,
int cchOperands,
LPCH rgchComment,
int cchComment,
LPCH rgchEA,
int cchEA
)
/*++
Routine Description:
description-of-function.
Arguments:
hpid - Supplies the process handle
hthd - Supplies a thread handle
dop - Supplies the set of disassembly options
lpaddr - Supplies the address to be disassembled
rgb - Supplies the buffer to dissassemble into
cbMax - Supplies the size of rgb
lpcbUsed - Returns the acutal size used
rgchOpcode - Supplies location to place opcode
rgchOperands - Supplies location to place operands
rgchComment - Supplies location to place comment
rgchEA - Supplies location to place effective address
Return Value:
None.
--*/
{
ULONG opcode;
POPTBLENTRY pEntry;
PULONG poffset = &lpaddr->addr.off;
*rgchComment = *rgchOperands = 0;
//
// Never use second EAsize value, nor does MIPS
//
EAsize[0] = EAsize[1] = 0;
PBuf = rgchOpcode; // Initialize pointers to buffer that
// will receive the disassembly text
CchBuf = cchOpcode;
disinstr = *((PALPHA_INSTRUCTION)rgb);
opcode = disinstr.Memory.Opcode; // Select disassembly procedure from
pEntry = findOpCodeEntry(opcode); // Get non-func entry for this code
switch (pEntry->iType) {
case ALPHA_UNKNOWN:
OutputString(pEntry->pszAlphaName);
break;
case ALPHA_MEMORY:
OutputString(pEntry->pszAlphaName);
PBuf = rgchOperands;
CchBuf = cchOperands;
OutputReg(disinstr.Memory.Ra);
*PBuf++ = ',';
CchBuf -= 1;
OutputHex(disinstr.Memory.MemDisp, (WIDTH_MEM_DISP + 3)/4, TRUE );
*PBuf++ = '(';
CchBuf -= 1;
OutputReg(disinstr.Memory.Rb);
*PBuf++ = ')';
CchBuf -= 1;
break;
case ALPHA_FP_MEMORY:
OutputString(pEntry->pszAlphaName);
PBuf = rgchOperands;
CchBuf = cchOperands;
OutputFReg(disinstr.Memory.Ra);
*PBuf++ = ',';
CchBuf -= 1;
OutputHex(disinstr.Memory.MemDisp, (WIDTH_MEM_DISP + 3)/4, TRUE );
*PBuf++ = '(';
CchBuf -= 1;
OutputReg(disinstr.Memory.Rb);
*PBuf++ = ')';
CchBuf -= 1;
break;
case ALPHA_MEMSPC:
OutputString(findFuncName(pEntry,
disinstr.Memory.MemDisp & BITS_MEM_DISP));
PBuf = rgchOperands;
CchBuf = cchOperands;
switch (pEntry->funcCode)
{
default:
break;
case (MB_FUNC): // MB
case (WMB_FUNC): // ???
case (MB2_FUNC): // ???
case (MB3_FUNC): // ???
case (TRAPB_FUNC): // TRAPB
case (EXCB_FUNC): // EXCB
break;
case (FETCH_FUNC): // FETCH 0(Rb)
case (FETCH_M_FUNC): // FETCH_M 0(Rb)
OutputHex(0, 1, FALSE);
*PBuf++ = '(';
CchBuf -= 1;
OutputReg(disinstr.Memory.Rb);
*PBuf++ = ')';
CchBuf -= 1;
break;
case (RC_FUNC): // RS Ra
case (RS_FUNC): // RC Ra
case (RPCC_FUNC): // RPCC Ra
OutputReg(disinstr.Memory.Ra);
break;
}
break;
case ALPHA_JUMP:
OutputString(findFuncName(pEntry, disinstr.Jump.Function));
PBuf = rgchOperands;
CchBuf -= 1;
OutputReg(disinstr.Jump.Ra);
*PBuf++ = ',';
*PBuf++ = '(';
CchBuf -= 2;
OutputReg(disinstr.Jump.Rb);
*PBuf++ = ')';
*PBuf++ = ',';
CchBuf -= 2;
OutputHex(disinstr.Jump.Hint, (WIDTH_HINT + 3)/4, TRUE);
EMFunc (
emfGetReg, hpid, htid,
disinstr.Jump.Rb + 32,
(LONG)(LPV)&EAaddr[0]
);
EAaddr[0] = EAaddr[0] & (~3);
EAsize[0] = 4;
PBuf = rgchEA;
CchBuf = cchEA;
OutputEffectiveAddress(EAaddr[0]);
break;
case ALPHA_BRANCH:
OutputString(pEntry->pszAlphaName);
PBuf = rgchOperands;
CchBuf = cchOperands;
OutputReg(disinstr.Branch.Ra);
*PBuf++ = ',';
CchBuf -= 1;
EAaddr[0] = (*poffset + 4) + (disinstr.Branch.BranchDisp * 4);
OutputEffectiveAddress(EAaddr[0]);
PBuf = rgchComment;
CchBuf = cchComment;
OutputHex(EAaddr[0], 8, FALSE);
break;
case ALPHA_FP_BRANCH:
OutputString(pEntry->pszAlphaName);
PBuf = rgchOperands;
CchBuf = cchOperands;
OutputFReg(disinstr.Branch.Ra);
*PBuf++ = ',';
CchBuf -= 1;
EAaddr[0] = (*poffset + 4) + (disinstr.Branch.BranchDisp * 4);
OutputEffectiveAddress(EAaddr[0]);
PBuf = rgchComment;
CchBuf = cchComment;
OutputHex(EAaddr[0], 8, FALSE);
break;
case ALPHA_OPERATE:
OutputString(findFuncName(pEntry, disinstr.OpReg.Function));
PBuf = rgchOperands;
CchBuf = cchOperands;
OutputReg(disinstr.OpReg.Ra);
*PBuf++ = ',';
CchBuf -= 1;
if (disinstr.OpReg.RbvType) {
*PBuf++ = '#';
CchBuf -= 1;
OutputHex(disinstr.OpLit.Literal, (WIDTH_LIT + 3)/4, TRUE);
} else
OutputReg(disinstr.OpReg.Rb);
*PBuf++ = ',';
CchBuf -= 1;
OutputReg(disinstr.OpReg.Rc);
break;
case ALPHA_FP_OPERATE:
{
ULONG Function;
ULONG Flags;
Flags = disinstr.FpOp.Function & MSK_FP_FLAGS;
Function = disinstr.FpOp.Function & MSK_FP_OP;
OutputString(findFuncName(pEntry, Function));
if ( (opcode == IEEEFP_OP) || (opcode == VAXFP_OP) ) {
OutputString(findFlagName(Flags, Function));
}
PBuf = rgchOperands;
CchBuf = cchOperands;
OutputFReg(disinstr.FpOp.Fa);
*PBuf++ = ',';
CchBuf -= 1;
OutputFReg(disinstr.FpOp.Fb);
*PBuf++ = ',';
CchBuf -= 1;
OutputFReg(disinstr.FpOp.Fc);
break;
}
case ALPHA_FP_CONVERT:
//
// This is a clone of the ALPHA_FP_OPERATE branch, except that
// we don't display Ra (which is always F31 and is implicit).
{
ULONG Function;
ULONG Flags;
Flags = disinstr.FpOp.Function & MSK_FP_FLAGS;
Function = disinstr.FpOp.Function & MSK_FP_OP;
OutputString(findFuncName(pEntry, Function));
if ( (opcode == IEEEFP_OP) || (opcode == VAXFP_OP) )
{
OutputString(findFlagName(Flags, Function));
}
PBuf = rgchOperands;
CchBuf = cchOperands;
OutputFReg(disinstr.FpOp.Fb);
*PBuf++ = ',';
CchBuf -= 1;
OutputFReg(disinstr.FpOp.Fc);
break;
}
case ALPHA_CALLPAL:
{
char* callPalCode = findFuncName(pEntry, disinstr.Pal.Function);
if (!strcmp (callPalCode, "???"))
{
OutputHex ((ULONG)disinstr.Pal.Function, 8, FALSE);
}
else
{
OutputString (callPalCode);
}
}
break;
case ALPHA_EV4_PR:
if ((disinstr.Long & MSK_EV4_PR) == 0)
OutputString("NOP");
else {
OutputString(pEntry->pszAlphaName);
PBuf = rgchOperands;
CchBuf = cchOperands;
OutputReg(disinstr.EV4_PR.Ra);
*PBuf++ = ',';
CchBuf -= 1;
if(disinstr.EV4_PR.Ra != disinstr.EV4_PR.Rb) {
OutputReg(disinstr.EV4_PR.Rb);
*PBuf++ = ',';
CchBuf -= 1;
};
OutputString(findFuncName(pEntry, (disinstr.Long & MSK_EV4_PR)));
};
break;
case ALPHA_EV4_MEM:
OutputString(pEntry->pszAlphaName);
PBuf = rgchOperands;
CchBuf = cchOperands;
OutputReg(disinstr.EV4_MEM.Ra);
*PBuf++ = ',';
CchBuf -= 1;
OutputReg(disinstr.EV4_MEM.Rb);
break;
case ALPHA_EV4_REI:
OutputString(pEntry->pszAlphaName);
break;
default:
OutputString("Invalid type");
break;
};
return;
}
/*** OutputEffectiveAddress - Print EA symbolically
*
* Purpose:
* Given the effective address (for a branch, jump or
* memory instruction, print it symbolically, if
* symbols are available.
*
* Input:
* offset - computed by the caller as
* for jumps, the value in Rb
* for branches, func(PC, displacement)
* for memory, func(PC, displacement)
*
* Returns:
* None
*
*************************************************************************/
void OutputEffectiveAddress(ULONG offset)
{
UCHAR chAddrBuffer[60];
LPCH lpchSymbol;
ADDR addrT={0}, addr={0};
int cb;
ODR odr;
odr.lszName = chAddrBuffer;
addr.addr.off = addrT.addr.off = offset;
MODE_IS_FLAT(addr.mode) = TRUE;
MODE_IS_FLAT(addrT.mode) = TRUE;
lpchSymbol = SHGetSymbol (&addrT, &addr, sopNone, &odr);
if (chAddrBuffer[0]) {
cb = strlen(chAddrBuffer);
if (cb > CchBuf) {
cb = CchBuf - 1;
}
strncpy(PBuf, chAddrBuffer, cb);
PBuf += cb;
if (odr.dwDeltaOff) {
if (CchBuf > 1) {
*PBuf++ = '+';
CchBuf -= 1;
}
OutputHex(odr.dwDeltaOff, 8, TRUE);
}
} else {
OutputHex(offset, 8, FALSE);
}
}
int DumpAddress ( LPADDR lpaddr, LPCH lpch, int cchMax ) {
LPCH lpchT = lpch;
Unreferenced(cchMax);
OutputAddr ( &lpch, lpaddr, (ADDR_IS_FLAT(*lpaddr) + 1) * 2 );
*lpch = '\0';
return lpch - lpchT + 1;
}
int DumpGeneric ( LSZ lsz, LPCH lpch, int cchMax )
{
int cb;
cb = strlen(lsz);
if (cb > cchMax-1) {
cb = cchMax -1;
}
strncpy(lpch, lsz, cb);
lpch[cb] = 0;
return cb + 1;
}
int DumpComment ( LSZ lsz, LPCH lpch, int cchMax ) {
*(lpch) = ';';
return DumpGeneric ( lsz, lpch + 1, cchMax - 1 ) + 1;
}
/*
** MBH bugbug - should we eliminate this routine?
** or do we want to print out something like this?
** We don't use this routine.
** Being used in MIPS to print *EA, where EA value is set up in CalcMain.
** We call OutputEffectiveAddress, instead, which prints out the symbol
** associated with an effective address
*/
int DumpEA ( HPID hpid, HTID htid, LPADDR lpaddr, LPCH lpch, int cchMax ) {
LPCH lpchT = lpch;
BYTE rgb [ MAXL ];
int indx;
int cb;
Unreferenced(cchMax);
for ( indx = 0; indx < 2; indx++ ) {
if ( EAsize [ indx ] ) {
ADDR addr = {0};
OutputHexString ( &lpchT, (LPB) &EAaddr [ indx ], 4 );
*lpchT++ = '=';
offAddr ( addr ) = (UOFFSET) EAaddr [ indx ];
segAddr ( addr ) = (SEGMENT) 0;
*lpaddr = addr;
EMFunc (
emfSetAddr,
hpid,
htid,
adrCurrent,
(LONG) (LPADDR) &addr
);
cb = EMFunc (
emfReadBuf,
hpid,
htid,
EAsize [ indx ],
(LONG) (LPV) rgb
);
if ( cb == EAsize [ indx ] ) {
OutputHexString ( &lpchT, rgb, EAsize [ indx ] );
}
else {
while ( EAsize [ indx ]-- ) {
*lpchT++ = '?';
*lpchT++ = '?';
}
}
*lpchT++ = '\0';
}
}
return lpchT - lpch;
}
/*** OutputHexString - output hex string
*
* Purpose:
* Output the value pointed by *lplpchMemBuf of the specified
* length. The value is treated as unsigned and leading
* zeroes are printed.
*
* Input:
* *lplpchBuf - pointer to text buffer to fill
* *pchValue - pointer to memory buffer to extract value
* length - length in bytes of value
*
* Output:
* *lplpchBuf - pointer updated to next text character
* *lplpchMemBuf - pointer update to next memory byte
*
*************************************************************************/
void OutputHexString (LPLPCH lplpchBuf, PCH pchValue, int length)
{
unsigned char chMem;
pchValue += length;
while ( length-- ) {
chMem = *--pchValue;
*(*lplpchBuf)++ = hexdigit[chMem >> 4];
*(*lplpchBuf)++ = hexdigit[chMem & 0x0f];
}
}
/*** OutputAddr - output address package
*
* Purpose:
* Output the address pointed to by lpaddr.
*
* Input:
* *lplpchBuf - pointer to text buffer to fill
* lpaddr - Standard address package.
*
* Output:
* *lplpchBuf - pointer updated to next text character
*
*************************************************************************/
void OutputAddr ( LPLPCH lplpchBuf, LPADDR lpaddr, int alen )
{
ADDR addr = *lpaddr;
*(*lplpchBuf)++ = '0';
*(*lplpchBuf)++ = (fUpper) ? 'X' : 'x';
OutputHexString ( lplpchBuf, (LPCH) &offAddr ( addr ), alen );
}
/*** OutputHexCode - output hex code
*
* Purpose:
* Output the code pointed by lpchMemBuf of the specified
* length. The value is treated as unsigned and leading
* zeroes are printed. This differs from OutputHexString
* in that bytes are printed from low to high addresses.
*
* Input:
* *lplpchBuf - pointer to text buffer to fill
* lpchMemBuf - - pointer to memory buffer to extract value
* length - length in bytes of value
*
* Output:
* *lplpchBuf - pointer updated to next text character
*
*************************************************************************/
void OutputHexCode (LPLPCH lplpchBuf, LPCH lpchMemBuf, int length)
{
unsigned char chMem;
while (length--) {
chMem = lpchMemBuf[length];
*(*lplpchBuf)++ = hexdigit[chMem >> 4];
*(*lplpchBuf)++ = hexdigit[chMem & 0x0f];
}
}