DISASM.C
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:42k
源码类别:
Windows编程
开发平台:
Visual C++
- /*++
- Copyright (c) 1993-1997 Microsoft Corporation
- Module Name:
- disasm.c
- Abstract:
- This file provides support disassembly ( x86 ).
- Author:
- Gerd Immeyer 19-Oct-1989
- Wesley Witt (wesw) 1-May-1993 ( ported from ntsd to drwatson)
- Environment:
- User Mode
- --*/
- #include <windows.h>
- #include <stddef.h>
- #include <string.h>
- #include "regs.h"
- #include "disasm.h"
- #include "drwatson.h"
- #include "proto.h"
- /***** macros and defines *****/
- #define BIT20(b) (b & 0x07)
- #define BIT53(b) (b >> 3 & 0x07)
- #define BIT76(b) (b >> 6 & 0x03)
- #define MAXL 16
- #define MAXOPLEN 10
- #define OBOFFSET 26
- #define OBOPERAND 34
- #define OBLINEEND 77
- /***** static tables and variables *****/
- static char regtab[] = "alcldlblahchdhbhaxcxdxbxspbpsidi"; /* reg table */
- static char *mrmtb16[] = { "bx+si", /* modRM string table (16-bit) */
- "bx+di",
- "bp+si",
- "bp+di",
- "si",
- "di",
- "bp",
- "bx"
- };
- static char *mrmtb32[] = { "eax", /* modRM string table (32-bit) */
- "ecx",
- "edx",
- "ebx",
- "esp",
- "ebp",
- "esi",
- "edi"
- };
- static char seg16[8] = { REGDS, REGDS, REGSS, REGSS,
- REGDS, REGDS, REGSS, REGDS };
- static char reg16[8] = { REGEBX, REGEBX, REGEBP, REGEBP,
- REGESI, REGEDI, REGEBP, REGEBX };
- static char reg16_2[4] = { REGESI, REGEDI, REGESI, REGEDI };
- static char seg32[8] = { REGDS, REGDS, REGDS, REGDS,
- REGSS, REGSS, REGDS, REGDS };
- static char reg32[8] = { REGEAX, REGECX, REGEDX, REGEBX,
- REGESP, REGEBP, REGESI, REGEDI };
- static char sregtab[] = "ecsdfg"; // first letter of ES, CS, SS, DS, FS, GS
- char hexdigit[] = { '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
- static int mod; /* mod of mod/rm byte */
- static int rm; /* rm of mod/rm byte */
- static int ttt; /* return reg value (of mod/rm) */
- static unsigned char *pMem; /* current position in instruction */
- static int mode_32; /* local addressing mode indicator */
- static int opsize_32; /* operand size flag */
- ULONG EAaddr[2]; // offset of effective address
- static int EAsize[2]; // size of effective address item
- static char *pchEAseg[2]; // normal segment for operand
- int G_mode_32 = 1; /* global address mode indicator */
- static BOOLEAN fMovX; // indicates a MOVSX or MOVZX
- // internal function definitions
- BOOLEAN disasm(PDEBUGPACKET, PULONG, PUCHAR, BOOLEAN);
- void DIdoModrm(PDEBUGPACKET dp,char **, int, BOOLEAN);
- void OutputHexString(char **, char *, int);
- void OutputHexValue(char **, char *, int, int);
- void OutputHexCode(char **, char *, int);
- void OutputString(char **, char *);
- void OutputSymbol(PDEBUGPACKET, char **, char *, int, int);
- void GetNextOffset(PDEBUGPACKET, PULONG, BOOLEAN);
- void OutputHexAddr(PUCHAR *, ULONG);
- USHORT GetSegRegValue(PDEBUGPACKET,int);
- /**** disasm - disassemble an 80x86/80x87 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
- *
- ***************************************************************************/
- BOOLEAN
- disasm( PDEBUGPACKET dp, PULONG pOffset, PUCHAR pchDst, BOOLEAN fEAout )
- {
- int opcode; /* current opcode */
- int olen = 2; /* operand length */
- int alen = 2; /* address length */
- int end = FALSE; /* end of instruction flag */
- int mrm = FALSE; /* indicator that modrm is generated*/
- unsigned char *action; /* action for operand interpretation*/
- long tmp; /* temporary storage field */
- int indx; /* temporary index */
- int action2; /* secondary action */
- int instlen; /* instruction length */
- int cBytes; // bytes read into instr buffer
- int segOvr = 0; /* segment override opcode */
- char membuf[MAXL]; /* current instruction buffer */
- char *pEAlabel = ""; // optional label for operand
- char *pchResultBuf = pchDst; // working copy of pchDst pointer
- char RepPrefixBuffer[32]; // rep prefix buffer
- char *pchRepPrefixBuf = RepPrefixBuffer; // pointer to prefix buffer
- char OpcodeBuffer[8]; // opcode buffer
- char *pchOpcodeBuf = OpcodeBuffer; // pointer to opcode buffer
- char OperandBuffer[80]; // operand buffer
- char *pchOperandBuf = OperandBuffer; // pointer to operand buffer
- char ModrmBuffer[80]; // modRM buffer
- char *pchModrmBuf = ModrmBuffer; // pointer to modRM buffer
- char EABuffer[42]; // effective address buffer
- char *pchEABuf = EABuffer; // pointer to EA buffer
- int obOpcode = OBOFFSET;
- int obOpcodeMin;
- int obOpcodeMax;
- int obOperand = OBOPERAND;
- int obOperandMin;
- int obOperandMax;
- int cbOpcode;
- int cbOperand;
- int cbOffset;
- int cbEAddr;
- int fTwoLines = FALSE;
- fMovX = FALSE;
- EAsize[0] = EAsize[1] = 0; // no effective address
- pchEAseg[0] = dszDS_;
- pchEAseg[1] = dszES_;
- mode_32 = opsize_32 = (G_mode_32 == 1); /* local addressing mode */
- olen = alen = (1 + mode_32) << 1; // set operand/address lengths
- // 2 for 16-bit and 4 for 32-bit
- OutputHexAddr(&pchResultBuf, *pOffset);
- *pchResultBuf++ = ' ';
- DoMemoryRead( dp,
- (LPVOID)*pOffset,
- (LPVOID)membuf,
- MAXL,
- &cBytes
- );
- /* move full inst to local buffer */
- pMem = membuf; /* point to begin of instruction */
- opcode = *pMem++; /* get opcode */
- OutputString(&pchOpcodeBuf, distbl[opcode].instruct);
- action = actiontbl + distbl[opcode].opr; /* get operand action */
- /***** loop through all operand actions *****/
- do {
- action2 = (*action) & 0xc0;
- switch((*action++) & 0x3f) {
- case ALT: /* alter the opcode if 32-bit */
- if (opsize_32) {
- indx = *action++;
- pchOpcodeBuf = &OpcodeBuffer[indx];
- if (indx == 0)
- OutputString(&pchOpcodeBuf, dszCWDE);
- else {
- *pchOpcodeBuf++ = 'd';
- if (indx == 1)
- *pchOpcodeBuf++ = 'q';
- }
- }
- break;
- case STROP:
- // compute size of operands in indx
- // also if dword operands, change fifth
- // opcode letter from 'w' to 'd'.
- if (opcode & 1) {
- if (opsize_32) {
- indx = 4;
- OpcodeBuffer[4] = 'd';
- }
- else
- indx = 2;
- }
- else
- indx = 1;
- if (*action & 1) {
- if (fEAout) {
- EAaddr[0] = (DWORD)GetRegValue(dp, REGESI);
- EAsize[0] = indx;
- }
- }
- if (*action++ & 2) {
- if (fEAout) {
- EAaddr[1] = (DWORD)GetRegValue(dp, REGEDI);
- EAsize[1] = indx;
- }
- }
- break;
- case CHR: /* insert a character */
- *pchOperandBuf++ = *action++;
- break;
- case CREG: /* set debug, test or control reg */
- if ((opcode - 231) & 0x04) // remove bias from opcode
- *pchOperandBuf++ = 't';
- else if ((opcode - 231) & 0x01)
- *pchOperandBuf++ = 'd';
- else
- *pchOperandBuf++ = 'c';
- *pchOperandBuf++ = 'r';
- *pchOperandBuf++ = (char)('0' + ttt);
- break;
- case SREG2: /* segment register */
- ttt = BIT53(opcode); // set value to fall through
- case SREG3: /* segment register */
- *pchOperandBuf++ = sregtab[ttt]; // reg is part of modrm
- *pchOperandBuf++ = 's';
- break;
- case BRSTR: /* get index to register string */
- ttt = *action++; /* from action table */
- goto BREGlabel;
- case BOREG: /* byte register (in opcode) */
- ttt = BIT20(opcode); /* register is part of opcode */
- goto BREGlabel;
- case ALSTR:
- ttt = 0; /* point to AL register */
- BREGlabel:
- case BREG: /* general register */
- *pchOperandBuf++ = regtab[ttt * 2];
- *pchOperandBuf++ = regtab[ttt * 2 + 1];
- break;
- case WRSTR: /* get index to register string */
- ttt = *action++; /* from action table */
- goto WREGlabel;
- case VOREG: /* register is part of opcode */
- ttt = BIT20(opcode);
- goto VREGlabel;
- case AXSTR:
- ttt = 0; /* point to eAX register */
- VREGlabel:
- case VREG: /* general register */
- if (opsize_32) /* test for 32bit mode */
- *pchOperandBuf++ = 'e';
- WREGlabel:
- case WREG: /* register is word size */
- *pchOperandBuf++ = regtab[ttt * 2 + 16];
- *pchOperandBuf++ = regtab[ttt * 2 + 17];
- break;
- case IST_ST:
- OutputString(&pchOperandBuf, "st(0),st");
- *(pchOperandBuf - 5) += rm;
- break;
- case ST_IST:
- OutputString(&pchOperandBuf, "st,");
- case IST:
- OutputString(&pchOperandBuf, "st(0)");
- *(pchOperandBuf - 2) += rm;
- break;
- case xBYTE: /* set instruction to byte only */
- EAsize[0] = 1;
- pEAlabel = "byte ptr ";
- break;
- case VAR:
- if (opsize_32)
- goto DWORDlabel;
- case xWORD:
- EAsize[0] = 2;
- pEAlabel = "word ptr ";
- break;
- case EDWORD:
- opsize_32 = 1; // for control reg move, use eRegs
- case xDWORD:
- DWORDlabel:
- EAsize[0] = 4;
- pEAlabel = "dword ptr ";
- break;
- case QWORD:
- EAsize[0] = 8;
- pEAlabel = "qword ptr ";
- break;
- case TTBYTE:
- EAsize[0] = 10;
- pEAlabel = "tbyte ptr ";
- break;
- case FARPTR:
- if (opsize_32) {
- EAsize[0] = 6;
- pEAlabel = "fword ptr ";
- }
- else {
- EAsize[0] = 4;
- pEAlabel = "dword ptr ";
- }
- break;
- case LMODRM: // output modRM data type
- if (mod != 3)
- OutputString(&pchOperandBuf, pEAlabel);
- else
- EAsize[0] = 0;
- case MODRM: /* output modrm string */
- if (segOvr) /* in case of segment override */
- OutputString(&pchOperandBuf, distbl[segOvr].instruct);
- *pchModrmBuf = ' ';
- OutputString(&pchOperandBuf, ModrmBuffer);
- break;
- case ADDRP: /* address pointer */
- OutputHexString(&pchOperandBuf, pMem + olen, 2); // segment
- *pchOperandBuf++ = ':';
- OutputSymbol(dp, &pchOperandBuf, pMem, olen, segOvr);
- pMem += olen + 2;
- break;
- case REL8: /* relative address 8-bit */
- if (opcode == 0xe3 && mode_32) {
- pchOpcodeBuf = OpcodeBuffer;
- OutputString(&pchOpcodeBuf, dszJECXZ);
- }
- tmp = (long)*(char *)pMem++; /* get the 8-bit rel offset */
- goto DoRelDispl;
- case REL16: /* relative address 16-/32-bit */
- tmp = 0;
- memmove(&tmp,pMem,sizeof(long));
- pMem += alen; /* skip over offset */
- DoRelDispl:
- tmp += *pOffset + (pMem - membuf); /* calculate address */
- OutputSymbol(dp, &pchOperandBuf, (char *) &tmp, alen, segOvr);
- // address
- break;
- case UBYTE: // unsigned byte for int/in/out
- OutputHexString(&pchOperandBuf, pMem, 1); // ubyte
- pMem++;
- break;
- case IB: /* operand is immediate byte */
- if ((opcode & ~1) == 0xd4) { // postop for AAD/AAM is 0x0a
- if (*pMem++ != 0x0a) // test post-opcode byte
- OutputString(&pchOperandBuf, dszRESERVED);
- break;
- }
- olen = 1; /* set operand length */
- goto DoImmed;
- case IW: /* operand is immediate word */
- olen = 2; /* set operand length */
- case IV: /* operand is word or dword */
- DoImmed:
- OutputHexValue(&pchOperandBuf, pMem, olen, FALSE);
- pMem += olen;
- break;
- case OFFS: /* operand is offset */
- EAsize[0] = (opcode & 1) ? olen : 1;
- if (segOvr) /* in case of segment override */
- OutputString(&pchOperandBuf, distbl[segOvr].instruct);
- *pchOperandBuf++ = '[';
- OutputSymbol(dp,&pchOperandBuf, pMem, alen, segOvr); // offset
- pMem += alen;
- *pchOperandBuf++ = ']';
- break;
- case GROUPP: /* operand is of group 1,2,4,6 or 8 */
- /* output opcode symbol */
- OutputString(&pchOpcodeBuf, group[*action++][ttt]);
- break;
- case GROUPT: /* operand is of group 3,5 or 7 */
- indx = *action; /* get indx into group from action */
- goto doGroupT;
- case EGROUPT: /* x87 ESC (D8-DF) group index */
- indx = BIT20(opcode) * 2; /* get group index from opcode */
- if (mod == 3) { /* some operand variations exists */
- /* for x87 and mod == 3 */
- ++indx; /* take the next group table entry */
- if (indx == 3) { /* for x87 ESC==D9 and mod==3 */
- if (ttt > 3) { /* for those D9 instructions */
- indx = 12 + ttt; /* offset index to table by 12 */
- ttt = rm; /* set secondary index to rm */
- }
- }
- else if (indx == 7) { /* for x87 ESC==DB and mod==3 */
- if (ttt == 4) /* only valid if ttt==4 */
- ttt = rm; /* set secondary group table index */
- else
- ttt = 7; /* no an x87 instruction */
- }
- }
- doGroupT:
- /* handle group with different types of operands */
- OutputString(&pchOpcodeBuf, groupt[indx][ttt].instruct);
- action = actiontbl + groupt[indx][ttt].opr;
- /* get new action */
- break;
- case OPC0F: /* secondary opcode table (opcode 0F) */
- opcode = *pMem++; /* get real opcode */
- fMovX = (BOOLEAN)(opcode == 0xBF || opcode == 0xB7);
- if (opcode < 7) /* for the first 7 opcodes */
- opcode += 256; /* point begin of secondary opcode tab. */
- else if (opcode > 0x1f && opcode < 0x27)
- opcode += 231; /* adjust for non-existing opcodes */
- else if (opcode > 0x2f && opcode < 0x33)
- opcode += 222; /* adjust for non-existing opcodes */
- else if (opcode > 0x7e && opcode < 0xd0)
- opcode += 148; /* adjust for non-existing opcodes */
- else
- opcode = 260; /* all non-existing opcodes */
- goto getNxtByte1;
- case ADR_OVR: /* address override */
- mode_32 = !G_mode_32; /* override addressing mode */
- alen = (mode_32 + 1) << 1; /* toggle address length */
- goto getNxtByte;
- case OPR_OVR: /* operand size override */
- opsize_32 = !G_mode_32; /* override operand size */
- olen = (opsize_32 + 1) << 1; /* toggle operand length */
- goto getNxtByte;
- case SEG_OVR: /* handle segment override */
- segOvr = opcode; /* save segment override opcode */
- pchOpcodeBuf = OpcodeBuffer; // restart the opcode string
- goto getNxtByte;
- case REP: /* handle rep/lock prefixes */
- *pchOpcodeBuf = ' ';
- if (pchRepPrefixBuf != RepPrefixBuffer)
- *pchRepPrefixBuf++ = ' ';
- OutputString(&pchRepPrefixBuf, OpcodeBuffer);
- pchOpcodeBuf = OpcodeBuffer;
- getNxtByte:
- opcode = *pMem++; /* next byte is opcode */
- getNxtByte1:
- action = actiontbl + distbl[opcode].opr;
- OutputString(&pchOpcodeBuf, distbl[opcode].instruct);
- default: /* opcode has no operand */
- break;
- }
- switch (action2) { /* secondary action */
- case MRM: /* generate modrm for later use */
- if (!mrm) { /* ignore if it has been generated */
- DIdoModrm(dp, &pchModrmBuf, segOvr, fEAout);
- /* generate modrm */
- mrm = TRUE; /* remember its generation */
- }
- break;
- case COM: /* insert a comma after operand */
- *pchOperandBuf++ = ',';
- break;
- case END: /* end of instruction */
- end = TRUE;
- break;
- }
- } while (!end); /* loop til end of instruction */
- /***** prepare disassembled instruction for output *****/
- instlen = pMem - membuf;
- if (instlen < cBytes)
- cBytes = instlen;
- OutputHexCode(&pchResultBuf, membuf, cBytes);
- if (instlen > cBytes) {
- *pchResultBuf++ = '?';
- *pchResultBuf++ = '?';
- (*pOffset)++; // point past unread byte
- }
- *pOffset += instlen; /* set instruction length */
- if (instlen > cBytes) {
- do
- *pchResultBuf++ = ' ';
- while (pchResultBuf < pchDst + OBOFFSET);
- OutputString(&pchResultBuf, "???");
- *pchResultBuf++ = ' ';
- return FALSE;
- }
- // if fEAout is set, build each EA with trailing space in EABuf
- // point back over final trailing space if buffer nonnull
- if (fEAout) {
- for (indx = 0; indx < 2; indx++)
- if (EAsize[indx]) {
- OutputString(&pchEABuf, segOvr ? distbl[segOvr].instruct
- : pchEAseg[indx]);
- OutputHexAddr(&pchEABuf, EAaddr[indx]);
- *pchEABuf++ = '=';
- DoMemoryRead( dp,
- (LPVOID)EAaddr[indx],
- (LPVOID)membuf,
- EAsize[indx],
- &tmp
- );
- if (tmp == EAsize[indx])
- OutputHexString(&pchEABuf, (char *)membuf,
- EAsize[indx]);
- else
- while (EAsize[indx]--) {
- *pchEABuf++ = '?';
- *pchEABuf++ = '?';
- }
- *pchEABuf++ = ' ';
- }
- if (pchEABuf != EABuffer)
- pchEABuf--;
- }
- // compute lengths of component strings.
- // if the rep string is nonnull,
- // add the opcode string length to the operand
- // make the rep string the opcode string
- cbOffset = pchResultBuf - pchDst;
- cbOperand = pchOperandBuf - OperandBuffer;
- cbOpcode = pchOpcodeBuf - OpcodeBuffer;
- if (pchRepPrefixBuf != RepPrefixBuffer) {
- cbOperand += cbOpcode + (cbOperand != 0);
- cbOpcode = pchRepPrefixBuf - RepPrefixBuffer;
- }
- cbEAddr = pchEABuf - EABuffer;
- // for really long strings, where the opcode and operand
- // will not fit on a 77-character line, make two lines
- // with the opcode on offset 0 on the second line with
- // the operand following after one space
- if (cbOpcode + cbOperand > OBLINEEND - 1) {
- fTwoLines = TRUE;
- obOpcode = 0;
- obOperand = cbOpcode + 1;
- }
- else {
- // compute the minimum and maximum offset values for
- // opcode and operand strings.
- // if strings are nonnull, add extra for separating space
- obOpcodeMin = cbOffset + 1;
- obOperandMin = obOpcodeMin + cbOpcode + 1;
- obOperandMax = OBLINEEND - cbEAddr - (cbEAddr != 0) - cbOperand;
- obOpcodeMax = obOperandMax - (cbOperand != 0) - cbOpcode;
- // if minimum offset is more than the maximum, the strings
- // will not fit on one line. recompute the min/max
- // values with no offset and EA strings.
- if (obOpcodeMin > obOpcodeMax) {
- fTwoLines = TRUE;
- obOpcodeMin = 0;
- obOperandMin = cbOpcode + 1;
- obOperandMax = OBLINEEND - cbOperand;
- obOpcodeMax = obOperandMax - (cbOperand != 0) - cbOpcode;
- }
- // compute the opcode and operand offsets. set offset as
- // close to the default values as possible.
- if (obOpcodeMin > OBOFFSET)
- obOpcode = obOpcodeMin;
- else if (obOpcodeMax < OBOFFSET)
- obOpcode = obOpcodeMax;
- obOperandMin = obOpcode + cbOpcode + 1;
- if (obOperandMin > OBOPERAND)
- obOperand = obOperandMin;
- else if (obOperandMax < OBOPERAND)
- obOperand = obOperandMax;
- }
- // build the resultant string with the offsets computed
- // if two lines are to be output,
- // append the EAddr string
- // output a new line and reset the pointer
- if (fTwoLines) {
- if (pchEABuf != EABuffer) {
- do
- *pchResultBuf++ = ' ';
- while (pchResultBuf < pchDst + OBLINEEND - cbEAddr);
- *pchEABuf = ' ';
- OutputString(&pchResultBuf, EABuffer);
- OutputString(&pchResultBuf, "n ");
- }
- pchDst = pchResultBuf;
- }
- // output rep, opcode, and operand strings
- do
- *pchResultBuf++ = ' ';
- while (pchResultBuf < pchDst + obOpcode);
- if (pchRepPrefixBuf != RepPrefixBuffer) {
- *pchRepPrefixBuf = ' ';
- OutputString(&pchResultBuf, RepPrefixBuffer);
- do
- *pchResultBuf++ = ' ';
- while (pchResultBuf < pchDst + obOperand);
- }
- *pchOpcodeBuf = ' ';
- OutputString(&pchResultBuf, OpcodeBuffer);
- if (pchOperandBuf != OperandBuffer) {
- do
- *pchResultBuf++ = ' ';
- while (pchResultBuf < pchDst + obOperand);
- *pchOperandBuf = ' ';
- OutputString(&pchResultBuf, OperandBuffer);
- }
- // if one line is to be output, append the EAddr string
- if (!fTwoLines && pchEABuf != EABuffer) {
- *pchEABuf = ' ';
- do
- *pchResultBuf++ = ' ';
- while (pchResultBuf < pchDst + OBLINEEND - cbEAddr);
- OutputString(&pchResultBuf, EABuffer);
- }
- *pchResultBuf = ' ';
- return TRUE;
- }
- /*...........................internal function..............................*/
- /* */
- /* generate a mod/rm string */
- /* */
- void
- DIdoModrm (PDEBUGPACKET dp, char **ppchBuf, int segOvr, BOOLEAN fEAout)
- {
- int mrm; /* modrm byte */
- char *src; /* source string */
- int sib;
- int ss;
- int ind;
- int oldrm;
- mrm = *pMem++; /* get the mrm byte from instruction */
- mod = BIT76(mrm); /* get mod */
- ttt = BIT53(mrm); /* get reg - used outside routine */
- rm = BIT20(mrm); /* get rm */
- if (mod == 3) { /* register only mode */
- src = ®tab[rm * 2]; /* point to 16-bit register */
- if (EAsize[0] > 1) {
- src += 16; /* point to 16-bit register */
- if (opsize_32 && !fMovX)
- *(*ppchBuf)++ = 'e'; /* make it a 32-bit register */
- }
- *(*ppchBuf)++ = *src++; /* copy register name */
- *(*ppchBuf)++ = *src;
- EAsize[0] = 0; // no EA value to output
- return;
- }
- if (mode_32) { /* 32-bit addressing mode */
- oldrm = rm;
- if (rm == 4) { /* rm == 4 implies sib byte */
- sib = *pMem++; /* get s_i_b byte */
- rm = BIT20(sib); /* return base */
- }
- *(*ppchBuf)++ = '[';
- if (mod == 0 && rm == 5) {
- OutputSymbol(dp,ppchBuf, pMem, 4, segOvr); // offset
- pMem += 4;
- }
- else {
- if (fEAout) {
- if (segOvr) {
- EAaddr[0] = (DWORD)GetRegValue(dp, reg32[rm]);
- pchEAseg[0] = distbl[segOvr].instruct;
- }
- else if (reg32[rm] == REGEBP || reg32[rm] == REGESP) {
- EAaddr[0] = (DWORD)GetRegValue(dp, reg32[rm]);
- pchEAseg[0] = dszSS_;
- }
- else
- EAaddr[0] = (DWORD)GetRegValue(dp, reg32[rm]);
- }
- OutputString(ppchBuf, mrmtb32[rm]);
- }
- if (oldrm == 4) { // finish processing sib
- ind = BIT53(sib);
- if (ind != 4) {
- *(*ppchBuf)++ = '+';
- OutputString(ppchBuf, mrmtb32[ind]);
- ss = 1 << BIT76(sib);
- if (ss != 1) {
- *(*ppchBuf)++ = '*';
- *(*ppchBuf)++ = (char)(ss + '0');
- }
- if (fEAout)
- EAaddr[0] = (DWORD)GetRegValue(dp, reg32[ind]);
- }
- }
- }
- else { // 16-bit addressing mode
- *(*ppchBuf)++ = '[';
- if (mod == 0 && rm == 6) {
- OutputSymbol(dp,ppchBuf, pMem, 2, segOvr); // 16-bit offset
- pMem += 2;
- }
- else {
- if (fEAout) {
- if (segOvr) {
- EAaddr[0] = (DWORD)GetRegValue(dp, reg16[rm]);
- pchEAseg[0] = distbl[segOvr].instruct;
- }
- else if (reg16[rm] == REGEBP) {
- EAaddr[0] = (DWORD)GetRegValue(dp, reg16[rm]);
- pchEAseg[0] = dszSS_;
- }
- else
- EAaddr[0] = (DWORD)GetRegValue(dp, reg16[rm]);
- if (rm < 4)
- EAaddr[0] += (DWORD)GetRegValue(dp, reg16_2[rm]);
- }
- OutputString(ppchBuf, mrmtb16[rm]);
- }
- }
- // output any displacement
- if (mod == 1) {
- if (fEAout)
- EAaddr[0] += (ULONG)pMem;
- OutputHexValue(ppchBuf, pMem, 1, TRUE);
- pMem++;
- }
- else if (mod == 2) {
- long tmp = 0;
- if (mode_32) {
- memmove(&tmp,pMem,sizeof(long));
- if (fEAout)
- EAaddr[0] += (ULONG)tmp;
- OutputHexValue(ppchBuf, pMem, 4, TRUE);
- pMem += 4;
- }
- else {
- memmove(&tmp,pMem,sizeof(short));
- if (fEAout)
- EAaddr[0] += tmp;
- OutputHexValue(ppchBuf, pMem, 2, TRUE);
- pMem += 2;
- }
- }
- if (!mode_32 && fEAout) {
- EAaddr[0] &= 0xffff;
- EAaddr[1] &= 0xffff;
- }
- *(*ppchBuf)++ = ']';
- }
- /*** OutputHexValue - output hex value
- *
- * Purpose:
- * Output the value pointed by *ppchBuf of the specified
- * length. The value is treated as signed and leading
- * zeroes are not printed. The string is prefaced by a
- * '+' or '-' sign as appropriate.
- *
- * Input:
- * *ppchBuf - pointer to text buffer to fill
- * *pchMemBuf - pointer to memory buffer to extract value
- * length - length in bytes of value (1, 2, and 4 supported)
- * fDisp - set if displacement to output '+'
- *
- * Output:
- * *ppchBuf - pointer updated to next text character
- *
- *************************************************************************/
- void OutputHexValue (char **ppchBuf, char *pchMemBuf, int length, int fDisp)
- {
- long value;
- int index;
- char digit[8];
- value = 0;
- if (length == 1)
- value = (long)(*(char *)pchMemBuf);
- else if (length == 2)
- memmove(&value,pchMemBuf,2);
- else
- memmove(&value,pchMemBuf,sizeof(long));
- length <<= 1; // shift once to get hex length
- if (value != 0 || !fDisp) {
- if (fDisp)
- if (value < 0 && length == 2) { // use neg value for byte
- value = -value; // displacement
- *(*ppchBuf)++ = '-';
- }
- else
- *(*ppchBuf)++ = '+';
- *(*ppchBuf)++ = '0';
- *(*ppchBuf)++ = 'x';
- for (index = length - 1; index != -1; index--) {
- digit[index] = (char)(value & 0xf);
- value >>= 4;
- }
- index = 0;
- while (digit[index] == 0 && index < length - 1)
- index++;
- while (index < length)
- *(*ppchBuf)++ = hexdigit[digit[index++]];
- }
- }
- /*** OutputHexString - output hex string
- *
- * Purpose:
- * Output the value pointed by *ppchMemBuf of the specified
- * length. The value is treated as unsigned and leading
- * zeroes are printed.
- *
- * Input:
- * *ppchBuf - pointer to text buffer to fill
- * *pchValue - pointer to memory buffer to extract value
- * length - length in bytes of value
- *
- * Output:
- * *ppchBuf - pointer updated to next text character
- * *ppchMemBuf - pointer update to next memory byte
- *
- *************************************************************************/
- void
- OutputHexString (char **ppchBuf, char *pchValue, int length)
- {
- unsigned char chMem;
- pchValue += length;
- while (length--) {
- chMem = *--pchValue;
- *(*ppchBuf)++ = hexdigit[chMem >> 4];
- *(*ppchBuf)++ = hexdigit[chMem & 0x0f];
- }
- }
- /*** OutputHexCode - output hex code
- *
- * Purpose:
- * Output the code pointed by pchMemBuf 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:
- * *ppchBuf - pointer to text buffer to fill
- * pchMemBuf - pointer to memory buffer to extract value
- * length - length in bytes of value
- *
- * Output:
- * *ppchBuf - pointer updated to next text character
- *
- *************************************************************************/
- void
- OutputHexCode (char **ppchBuf, char *pchMemBuf, int length)
- {
- unsigned char chMem;
- while (length--) {
- chMem = *pchMemBuf++;
- *(*ppchBuf)++ = hexdigit[chMem >> 4];
- *(*ppchBuf)++ = hexdigit[chMem & 0x0f];
- }
- }
- /*** OutputString - output string
- *
- * Purpose:
- * Copy the string into the buffer pointed by *ppBuf.
- *
- * Input:
- * *pStr - pointer to string
- *
- * Output:
- * *ppBuf points to next character in buffer.
- *
- *************************************************************************/
- void
- OutputString (char **ppBuf, char *pStr)
- {
- while (*pStr)
- *(*ppBuf)++ = *pStr++;
- }
- /*** OutputSymbol - output symbolic value
- *
- * Purpose:
- * Output the value in outvalue into the buffer
- * pointed by *pBuf. Express the value as a
- * symbol plus displacment, if possible.
- *
- * Input:
- * *ppBuf - pointer to text buffer to fill
- * *pValue - pointer to memory buffer to extract value
- * length - length in bytes of value
- *
- * Output:
- * *ppBuf - pointer updated to next text character
- *
- *************************************************************************/
- void
- OutputSymbol (PDEBUGPACKET dp, char **ppBuf, char *pValue, int length, int segOvr)
- {
- ULONG displacement;
- ULONG value;
- char *szSymName;
- value = 0;
- if (length == 1)
- value = (long)(*(char *)pValue);
- else if (length == 2)
- memmove(&value,pValue,sizeof(short));
- else
- memmove(&value,pValue,sizeof(long));
- EAaddr[0] = value;
- if (SymGetSymFromAddr( dp->hProcess, value, &displacement, sym )) {
- szSymName = sym->Name;
- OutputString(ppBuf, szSymName);
- OutputHexValue(ppBuf, (char *)&displacement, length, TRUE);
- *(*ppBuf)++ = ' ';
- *(*ppBuf)++ = '(';
- OutputHexString(ppBuf, pValue, length);
- *(*ppBuf)++ = ')';
- }
- else
- OutputHexString(ppBuf, pValue, length);
- }
- /*** X86GetNextOffset - compute offset for trace or step
- *
- * Purpose:
- * From a limited disassembly of the instruction pointed
- * by the FIR register, compute the offset of the next
- * instruction for either a trace or step operation.
- *
- * Input:
- * fStep - TRUE if step offset returned - FALSE for trace offset
- *
- * Returns:
- * step or trace offset if input is TRUE or FALSE, respectively
- * -1 returned for trace flag to be used
- *
- *************************************************************************/
- void
- GetNextOffset (PDEBUGPACKET dp, PULONG pcaddr, BOOLEAN fStep)
- {
- int mode_32;
- int opsize_32;
- int cBytes;
- char membuf[MAXL]; // current instruction buffer
- ULONG addrReturn;
- USHORT retAddr[3]; // return address buffer
- char *pMem;
- UCHAR opcode;
- int fPrefix = TRUE;
- int fRepPrefix = FALSE;
- int ttt;
- int rm;
- ULONG instroffset;
- // read instruction stream bytes into membuf and set mode and
- // opcode size flags
- *pcaddr = (DWORD)GetRegValue(dp,REGEIP);
- instroffset = *pcaddr;
- G_mode_32 = TRUE;
- mode_32 = opsize_32 = (G_mode_32 == 1); /* local addressing mode */
- DoMemoryRead( dp,
- (LPVOID)*pcaddr,
- (LPVOID)membuf,
- MAXL,
- &cBytes
- );
- /* move full inst to local buffer */
- pMem = membuf; /* point to begin of instruction */
- // read and process any prefixes first
- do {
- opcode = (UCHAR)*pMem++; /* get opcode */
- if (opcode == 0x66)
- opsize_32 = !G_mode_32;
- else if (opcode == 0x67)
- mode_32 = !G_mode_32;
- else if ((opcode & ~1) == 0xf2)
- fRepPrefix = TRUE;
- else if (opcode != 0xf0 && (opcode & ~0x18) != 0x26
- && (opcode & ~1) != 0x64)
- fPrefix = FALSE;
- }
- while (fPrefix);
- // for instructions that alter the TF (trace flag), return the
- // offset of the next instruction despite the flag of fStep
- if (((opcode & ~0x3) == 0x9c))
- // 9c-9f, pushf, popf, sahf, lahf
- ;
- else if (opcode == 0xcf) { // cf - iret - get RA from stack
- addrReturn = (DWORD)GetRegValue(dp, REGESP);
- DoMemoryRead( dp,
- (LPVOID)addrReturn,
- (LPVOID)retAddr,
- sizeof(retAddr),
- NULL
- );
- *pcaddr = retAddr[2];
- return;
- }
- // repeated string/port instructions
- if (opcode == 0xe8) // near direct jump
- pMem += (1 + opsize_32) * 2;
- else if (opcode == 0x9a) // far direct jump
- pMem += (2 + opsize_32) * 2;
- else if (opcode == 0xcd ||
- (opcode >= 0xe0 && opcode <= 0xe2)) // loop / int nn instrs
- pMem++;
- else if (opcode == 0xff) { // indirect call - compute length
- opcode = *pMem++; // get modRM
- ttt = BIT53(opcode);
- if ((ttt & ~1) == 2) {
- mod = BIT76(opcode);
- if (mod != 3) { // nonregister operand
- rm = BIT20(opcode);
- if (mode_32) {
- if (rm == 4)
- rm = BIT20(*pMem++); // get base from SIB
- if (mod == 0) {
- if (rm == 5)
- pMem += 4; // long direct address
- } // else register
- else if (mod == 1)
- pMem++; // register with byte offset
- else
- pMem += 4; // register with long offset
- }
- else { // 16-bit mode
- if (mod == 0) {
- if (rm == 6)
- pMem += 2; // short direct address
- }
- else
- pMem += mod; // reg, byte, word offset
- }
- }
- }
- else
- instroffset = (ULONG)-1; // 0xff, but not call
- }
- else if (!((fRepPrefix && ((opcode & ~3) == 0x6c ||
- (opcode & ~3) == 0xa4 ||
- (opcode & ~1) == 0xaa ||
- (opcode & ~3) == 0xac)) ||
- opcode == 0xcc || opcode == 0xce))
- instroffset = (ULONG)-1; // not repeated string op
- // or int 3 / into
- // if not enough bytes were read for instruction parse,
- // just give up and trace the instruction
- if (cBytes < pMem - membuf)
- instroffset = (ULONG)-1;
- // if not tracing, compute the new instruction offset
- if (instroffset != (ULONG)-1)
- instroffset += pMem - membuf;
- *pcaddr = instroffset;
- }
- void
- OutputHexAddr (PUCHAR *ppBuffer, ULONG offset)
- {
- OutputHexString(ppBuffer, (char *)&offset, sizeof(ULONG));
- }
- USHORT
- GetSegRegValue (PDEBUGPACKET dp, int segOpcode)
- {
- ULONG regnum;
- switch (segOpcode) {
- case 0x26:
- regnum = REGES;
- break;
- case 0x2e:
- regnum = REGCS;
- break;
- case 0x36:
- regnum = REGSS;
- break;
- case 0x64:
- regnum = REGFS;
- break;
- case 0x65:
- regnum = REGGS;
- break;
- case 0x3e:
- default:
- regnum = REGDS;
- }
- return (USHORT)GetRegValue(dp,regnum);
- }