|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1993 Microsoft Corporation
4:
5: Module Name:
6:
7: regs.c
8:
9: Abstract:
10:
11: This file provides disassembly ( alpha )
12:
13: Author:
14:
15: Miche Baker-Harvey (v-michbh) 1-May-1993 (ported from ntsd)
16:
17: Environment:
18:
19: User Mode
20:
21: --*/
22:
23:
24: #include <windows.h>
25: #include <stddef.h>
26: #include <string.h>
27:
28: #include <alphaops.h>
29: #include "disasm.h"
30: #include "regs.h"
31: #include "optable.h"
32:
33: #include "drwatson.h"
34: #include "proto.h"
35:
36: void BlankFill(ULONG);
37: void OutputHex(ULONG, ULONG, BOOLEAN);
38:
39: void OutputEffectiveAddress(PDEBUGPACKET, ULONG);
40: void OutputString(char *);
41: void OutputReg(ULONG);
42: void OutputFReg(ULONG);
43: void GetNextOffset(PDEBUGPACKET, PULONG, BOOLEAN);
44:
45:
46: ALPHA_INSTRUCTION disinstr;
47:
48: extern PUCHAR pszReg[];
49:
50: BOOLEAN disasm(PDEBUGPACKET, PDWORD, char *, BOOLEAN);
51:
52:
53: static char *pBufStart;
54: static char *pBuf;
55:
56:
57: #define OPRNDCOL 27 // Column for first operand
58: #define EACOL 40 // column for effective address
59: #define FPTYPECOL 40 // .. for the type of FP instruction
60:
61:
62: BOOLEAN
63: disasm (PDEBUGPACKET dp, PDWORD poffset, char *bufptr, BOOLEAN fEAout)
64: {
65: static initialized = 0;
66: ULONG opcode;
67: ULONG Ea; // Effective Address
68: POPTBLENTRY pEntry;
69: LONG displacement;
70:
71: if (!initialized) {
72: opTableInit();
73: initialized = 1;
74: }
75: pBufStart = pBuf = bufptr; // Initialize pointers to buffer that
76: // will receive the disassembly text
77: OutputHex(*poffset, 8, FALSE);// Output Hex address of instruction
78: *pBuf++ = ':';
79: *pBuf++ = ' ';
80:
81: if (!ReadProcessMemory (dp->hProcess,
82: (LPVOID)*poffset,
83: (LPVOID)&disinstr.Long,
84: sizeof(DWORD),
85: NULL
86: )) {
87: OutputString("???????? ????");
88: *pBuf = '\0';
89: return(FALSE);
90: }
91:
92: OutputHex(disinstr.Long, 8, FALSE); // Output instruction in Hex
93: *pBuf++ = ' ';
94:
95: opcode = disinstr.Memory.Opcode; // Select disassembly procedure from
96:
97: pEntry = findOpCodeEntry(opcode); // Get non-func entry for this code
98: if (pEntry == (POPTBLENTRY)-1) {
99: OutputString("??????? ????");
100: *pBuf = '\0';
101: return (FALSE);
102: }
103:
104:
105: switch (pEntry->iType) {
106: case ALPHA_UNKNOWN:
107: OutputString(pEntry->pszAlphaName);
108: break;
109:
110: case ALPHA_MEMORY:
111: OutputString(pEntry->pszAlphaName);
112: BlankFill(OPRNDCOL);
113: OutputReg(disinstr.Memory.Ra);
114: *pBuf++ = ',';
115: OutputHex(disinstr.Memory.MemDisp, (WIDTH_MEM_DISP + 3)/4, TRUE );
116: *pBuf++ = '(';
117: OutputReg(disinstr.Memory.Rb);
118: *pBuf++ = ')';
119:
120: break;
121:
122: case ALPHA_FP_MEMORY:
123: OutputString(pEntry->pszAlphaName);
124: BlankFill(OPRNDCOL);
125: OutputFReg(disinstr.Memory.Ra);
126: *pBuf++ = ',';
127: OutputHex(disinstr.Memory.MemDisp, (WIDTH_MEM_DISP + 3)/4, TRUE );
128: *pBuf++ = '(';
129: OutputReg(disinstr.Memory.Rb);
130: *pBuf++ = ')';
131:
132: break;
133:
134: case ALPHA_MEMSPC:
135: OutputString(findFuncName(pEntry, disinstr.Memory.MemDisp & BITS_MEM_DISP));
136: //
137: // Some memory special instructions have an operand
138: //
139:
140: switch (disinstr.Memory.MemDisp & BITS_MEM_DISP) {
141: case FETCH_FUNC:
142: case FETCH_M_FUNC:
143: // one operand, in Rb
144: BlankFill(OPRNDCOL);
145: *pBuf++ = '0';
146: *pBuf++ = '(';
147: OutputReg(disinstr.Memory.Rb);
148: *pBuf++ = ')';
149: break;
150:
151: case RS_FUNC:
152: case RC_FUNC:
153: case RPCC_FUNC:
154: // one operand, in Ra
155: BlankFill(OPRNDCOL);
156: OutputReg(disinstr.Memory.Ra);
157: break;
158:
159: case MB_FUNC:
160: case WMB_FUNC:
161: case MB2_FUNC:
162: case MB3_FUNC:
163: case TRAPB_FUNC:
164: case EXCB_FUNC:
165: // no operands
166: break;
167:
168: default:
169: printf("we shouldn't get here \n");
170: break;
171: }
172:
173: break;
174:
175:
176: case ALPHA_JUMP:
177: OutputString(findFuncName(pEntry, disinstr.Jump.Function));
178: BlankFill(OPRNDCOL);
179: OutputReg(disinstr.Jump.Ra);
180: *pBuf++ = ',';
181: *pBuf++ = '(';
182: OutputReg(disinstr.Jump.Rb);
183: *pBuf++ = ')';
184: *pBuf++ = ',';
185: OutputHex(disinstr.Jump.Hint, (WIDTH_HINT + 3)/4, TRUE);
186:
187: Ea = GetRegValue(dp, GetIntRegNumber(disinstr.Jump.Rb)) & (~3);
188: OutputEffectiveAddress(dp, Ea);
189: break;
190:
191: case ALPHA_BRANCH:
192: OutputString(pEntry->pszAlphaName);
193: BlankFill(OPRNDCOL);
194: OutputReg(disinstr.Branch.Ra);
195: *pBuf++ = ',';
196:
197: //
198: // The next line might be a call to GetNextOffset, but
199: // GetNextOffset assumes that it should work from REGFIR.
200: //
201:
202: Ea = *poffset +
203: sizeof(DWORD) +
204: (disinstr.Branch.BranchDisp << 2);
205: OutputHex(Ea, 8, FALSE);
206: OutputEffectiveAddress(dp, Ea);
207:
208: break;
209:
210: case ALPHA_FP_BRANCH:
211: OutputString(pEntry->pszAlphaName);
212: BlankFill(OPRNDCOL);
213: OutputFReg(disinstr.Branch.Ra);
214: *pBuf++ = ',';
215:
216: //
217: // The next line might be a call to GetNextOffset, but
218: // GetNextOffset assumes that it should work from REGFIR.
219: //
220:
221: Ea = *poffset +
222: sizeof(DWORD) +
223: (disinstr.Branch.BranchDisp << 2);
224: OutputHex(Ea, 8, FALSE);
225: OutputEffectiveAddress(dp, Ea);
226:
227: break;
228:
229: case ALPHA_OPERATE:
230: OutputString(findFuncName(pEntry, disinstr.OpReg.Function));
231: BlankFill(OPRNDCOL);
232: OutputReg(disinstr.OpReg.Ra);
233: *pBuf++ = ',';
234: if (disinstr.OpReg.RbvType) {
235: *pBuf++ = '#';
236: OutputHex(disinstr.OpLit.Literal, (WIDTH_LIT + 3)/4, TRUE);
237: } else
238: OutputReg(disinstr.OpReg.Rb);
239: *pBuf++ = ',';
240: OutputReg(disinstr.OpReg.Rc);
241: break;
242:
243: case ALPHA_FP_OPERATE:
244:
245: {
246: ULONG Function;
247: ULONG Flags;
248:
249: Flags = disinstr.FpOp.Function & MSK_FP_FLAGS;
250: Function = disinstr.FpOp.Function & MSK_FP_OP;
251:
252: // if (fVerboseOutput) {
253: // dprintf("In FP_OPERATE: Flags %08x Function %08x\n",
254: // Flags, Function);
255: // dprintf("opcode %d \n", opcode);
256: // }
257:
258: //
259: // CVTST and CVTST/S are different: they look like
260: // CVTTS with some flags set
261: //
262: if (Function == CVTTS_FUNC) {
263: if (disinstr.FpOp.Function == CVTST_S_FUNC) {
264: Function = CVTST_S_FUNC;
265: Flags = NONE_FLAGS;
266: }
267: if (disinstr.FpOp.Function == CVTST_FUNC) {
268: Function = CVTST_FUNC;
269: Flags = NONE_FLAGS;
270: }
271: }
272:
273: OutputString(findFuncName(pEntry, Function));
274:
275: //
276: // Append the opcode qualifier, if any, to the opcode name.
277: //
278:
279: if ( (opcode == IEEEFP_OP) || (opcode == VAXFP_OP)
280: || (Function == CVTQL_FUNC) ) {
281: OutputString(findFlagName(Flags, Function));
282: }
283:
284: BlankFill(OPRNDCOL);
285: //
286: // If this is a convert instruction, only Rb and Rc are used
287: //
288: if (strncmp("cvt", findFuncName(pEntry, Function), 3) != 0) {
289: OutputFReg(disinstr.FpOp.Fa);
290: *pBuf++ = ',';
291: }
292: OutputFReg(disinstr.FpOp.Fb);
293: *pBuf++ = ',';
294: OutputFReg(disinstr.FpOp.Fc);
295:
296: break;
297: }
298:
299: case ALPHA_FP_CONVERT:
300: OutputString(pEntry->pszAlphaName);
301: BlankFill(OPRNDCOL);
302: OutputFReg(disinstr.FpOp.Fa);
303: *pBuf++ = ',';
304: OutputFReg(disinstr.FpOp.Fb);
305: break;
306:
307: case ALPHA_CALLPAL:
308: OutputString(findFuncName(pEntry, disinstr.Pal.Function));
309: break;
310:
311: case ALPHA_EV4_PR:
312: if ((disinstr.Long & MSK_EV4_PR) == 0)
313: OutputString("NOP");
314: else {
315: OutputString(pEntry->pszAlphaName);
316: BlankFill(OPRNDCOL);
317: OutputReg(disinstr.EV4_PR.Ra);
318: *pBuf++ = ',';
319: if(disinstr.EV4_PR.Ra != disinstr.EV4_PR.Rb) {
320: OutputReg(disinstr.EV4_PR.Rb);
321: *pBuf++ = ',';
322: };
323: OutputString(findFuncName(pEntry, (disinstr.Long & MSK_EV4_PR)));
324: };
325: break;
326: case ALPHA_EV4_MEM:
327: OutputString(pEntry->pszAlphaName);
328: BlankFill(OPRNDCOL);
329: OutputReg(disinstr.EV4_MEM.Ra);
330: *pBuf++ = ',';
331: OutputReg(disinstr.EV4_MEM.Rb);
332: break;
333: case ALPHA_EV4_REI:
334: OutputString(pEntry->pszAlphaName);
335: break;
336: default:
337: OutputString("Invalid type");
338: break;
339: };
340:
341:
342: *poffset += sizeof(ULONG);
343: *pBuf = '\0';
344: return(TRUE);
345: }
346:
347: /* BlankFill - blank-fill buffer
348: *
349: * Purpose:
350: * To fill the buffer at *pBuf with blanks until
351: * position count is reached.
352: *
353: * Input:
354: * None.
355: *
356: * Output:
357: * None.
358: *
359: ***********************************************************************/
360:
361: void BlankFill(ULONG count)
362: {
363: do
364: *pBuf++ = ' ';
365: while (pBuf < pBufStart + count);
366: }
367:
368: /* OutputHex - output hex value
369: *
370: * Purpose:
371: * Output the value in outvalue into the buffer
372: * pointed by *pBuf. The value may be signed
373: * or unsigned depending on the value fSigned.
374: *
375: * Input:
376: * outvalue - value to output
377: * length - length in digits
378: * fSigned - TRUE if signed else FALSE
379: *
380: * Output:
381: * None.
382: *
383: ***********************************************************************/
384:
385: UCHAR HexDigit[16] = {
386: '0', '1', '2', '3', '4', '5', '6', '7',
387: '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
388: };
389:
390: void OutputHex (ULONG outvalue, ULONG length, BOOLEAN fSigned)
391: {
392: UCHAR digit[8];
393: LONG index = 0;
394:
395: if (fSigned && (LONG)outvalue < 0) {
396: *pBuf++ = '-';
397: outvalue = - (LONG)outvalue;
398: }
399: do {
400: digit[index++] = HexDigit[outvalue & 0xf];
401: outvalue >>= 4;
402: }
403:
404: while ((fSigned && outvalue) || (!fSigned && index < (LONG)length))
405: ;
406: while (--index >= 0)
407: *pBuf++ = digit[index];
408: }
409:
410: /* OutputString - output string
411: *
412: * Purpose:
413: * Copy the string into the buffer pointed by pBuf.
414: *
415: * Input:
416: * *pStr - pointer to string
417: *
418: * Output:
419: * None.
420: *
421: ***********************************************************************/
422:
423: void OutputString (char *pStr)
424: {
425: while (*pStr)
426: *pBuf++ = *pStr++;
427: }
428:
429: void OutputReg (ULONG regnum)
430: {
431: OutputString(pszReg[GetIntRegNumber(regnum)]);
432: }
433:
434: void OutputFReg (ULONG regnum)
435: {
436: *pBuf++ = 'f';
437: if (regnum > 9)
438: *pBuf++ = (UCHAR)('0' + regnum / 10);
439: *pBuf++ = (UCHAR)('0' + regnum % 10);
440: }
441:
442:
443: /*** OutputEffectiveAddress - Print EA symbolically
444: *
445: * Purpose:
446: * Given the effective address (for a branch, jump or
447: * memory instruction, print it symbolically, if
448: * symbols are available.
449: *
450: * Input:
451: * offset - computed by the caller as
452: * for jumps, the value in Rb
453: * for branches, func(PC, displacement)
454: * for memory, func(PC, displacement)
455: *
456: * Returns:
457: * None
458: *
459: *************************************************************************/
460: void OutputEffectiveAddress(PDEBUGPACKET dp, ULONG offset)
461: {
462: ULONG displacement;
463: PUCHAR pszTemp;
464: UCHAR ch;
465:
466: PSYMBOL sym;
467:
468: BlankFill(EACOL);
469:
470: sym = GetSymFromAddrAllContexts( offset, &displacement, dp);
471:
472: if (sym) {
473: pszTemp = UnDName( &sym->szName[1] );
474: while (ch = *pszTemp++)
475: *pBuf++ = ch;
476: if (displacement) {
477: *pBuf++ = '+';
478: OutputHex(displacement, 8, TRUE);
479: }
480: }
481: else {
482: OutputHex(offset, 8, FALSE);
483: }
484: }
485:
486:
487: /*** GetNextOffset - compute offset for trace or step
488: *
489: * Purpose:
490: * From a limited disassembly of the instruction pointed
491: * by the FIR register, compute the offset of the next
492: * instruction for either a trace or step operation.
493: *
494: * trace -> the next instruction to execute
495: * step -> the instruction in the next memory location or the
496: * next instruction executed due to a branch (step over
497: * subroutine calls).
498: *
499: * Input:
500: * result - where to put the next offset
501: * fStep - TRUE for step offset; FALSE for trace offset
502: *
503: * Returns:
504: * step or trace offset if input is TRUE or FALSE, respectively
505: * in result
506: *
507: *************************************************************************/
508: /*
509: void
510: GetNextOffset (PDEBUGPACKET dp, PULONG result, BOOLEAN fStep)
511: {
512: ULONG rv;
513: ULONG opcode;
514: ULONG firaddr;
515: ULONG updatedpc;
516: ULONG branchTarget;
517: DWORD fir;
518:
519: // Canonical form to shorten tests; Abs is absolute value
520:
521: LONG Can, Abs;
522:
523: CONVERTED_DOUBLE Rav;
524: CONVERTED_DOUBLE Fav;
525: CONVERTED_DOUBLE Rbv;
526:
527: //
528: // Get current address
529: //
530:
531: firaddr = GetRegValue(dp, REGFIR);
532:
533: //
534: // relative addressing updates PC first
535: // Assume next sequential instruction is next offset
536: //
537:
538: updatedpc = firaddr + sizeof(ULONG);
539: rv = updatedpc;
540:
541: ReadProcessMemory (dp->hProcess,
542: (LPVOID)firaddr,
543: (LPVOID)&disinstr.Long,
544: sizeof(ULONG),
545: NULL
546: );
547:
548: opcode = disinstr.Memory.Opcode;
549:
550: switch(findOpCodeEntry(opcode)->iType) {
551:
552: case ALPHA_JUMP:
553:
554: switch(disinstr.Jump.Function) {
555:
556: case JSR_FUNC:
557: case JSR_CO_FUNC:
558:
559: if (fStep) {
560:
561: //
562: // Step over the subroutine call;
563: //
564:
565: break;
566: }
567:
568: //
569: // fall through
570: //
571:
572: case JMP_FUNC:
573: case RET_FUNC:
574:
575: GetQuadRegValue(dp, GetIntRegNumber(disinstr.Jump.Rb), &Rbv);
576: rv = (Rbv.li.LowPart & (~3));
577: break;
578:
579: }
580:
581: break;
582:
583: case ALPHA_BRANCH:
584:
585: branchTarget = (updatedpc + (disinstr.Branch.BranchDisp * 4));
586:
587: GetQuadRegValue(dp, GetIntRegNumber(disinstr.Branch.Ra), &Rav.li);
588:
589: //
590: // set up a canonical value for computing the branch test
591: // - works with ALPHA, MIPS and 386 hosts
592: //
593:
594: Can = Rav.li.LowPart & 1;
595:
596: if ((LONG)Rav.li.HighPart < 0) {
597: Can |= 0x80000000;
598: }
599:
600: if ((Rav.li.LowPart & 0xfffffffe) || (Rav.li.HighPart & 0x7fffffff)) {
601: Can |= 2;
602: }
603:
604: // if (fVerboseOutput) {
605: // dprintf("Rav High %08lx Low %08lx Canonical %08lx\n",
606: // Rav.li.HighPart, Rav.li.LowPart, Can);
607: // dprintf("returnvalue %08lx branchTarget %08lx\n",
608: // rv, branchTarget);
609: // }
610:
611: switch(opcode) {
612: case BR_OP: rv = branchTarget; break;
613: case BSR_OP: if (!fStep) rv = branchTarget; break;
614: case BEQ_OP: if (Can == 0) rv = branchTarget; break;
615: case BLT_OP: if (Can < 0) rv = branchTarget; break;
616: case BLE_OP: if (Can <= 0) rv = branchTarget; break;
617: case BNE_OP: if (Can != 0) rv = branchTarget; break;
618: case BGE_OP: if (Can >= 0) rv = branchTarget; break;
619: case BGT_OP: if (Can > 0) rv = branchTarget; break;
620: case BLBC_OP: if ((Can & 0x1) == 0) rv = branchTarget; break;
621: case BLBS_OP: if ((Can & 0x1) == 1) rv = branchTarget; break;
622: };
623:
624: break;
625:
626:
627: case ALPHA_FP_BRANCH:
628:
629: branchTarget = (updatedpc + (disinstr.Branch.BranchDisp * 4));
630:
631: GetFloatingPointRegValue(dp, disinstr.Branch.Ra, &Fav);
632:
633: //
634: // Set up a canonical value for computing the branch test
635: //
636:
637: Can = Fav.li.HighPart & 0x80000000;
638:
639: //
640: // The absolute value is needed -0 and non-zero computation
641: //
642:
643: Abs = Fav.li.LowPart || (Fav.li.HighPart & 0x7fffffff);
644:
645: if (Can && (Abs == 0x0)) {
646:
647: //
648: // negative 0 should be considered as zero
649: //
650:
651: Can = 0x0;
652:
653: } else {
654:
655: Can |= Abs;
656:
657: }
658:
659: // if (fVerboseOutput) {
660: // dprintf("Fav High %08lx Low %08lx Canonical %08lx Absolute %08lx\n",
661: // Fav.li.HighPart, Fav.li.LowPart, Can, Abs);
662: // dprintf("returnvalue %08lx branchTarget %08lx\n",
663: // rv, branchTarget);
664: // }
665:
666: switch(opcode) {
667: case FBEQ_OP: if (Can == 0) rv = branchTarget; break;
668: case FBLT_OP: if (Can < 0) rv = branchTarget; break;
669: case FBNE_OP: if (Can != 0) rv = branchTarget; break;
670: case FBLE_OP: if (Can <= 0) rv = branchTarget; break;
671: case FBGE_OP: if (Can >= 0) rv = branchTarget; break;
672: case FBGT_OP: if (Can > 0) rv = branchTarget; break;
673: };
674:
675: break;
676: };
677:
678: // if (fVerboseOutput) {
679: // dprintf("GetNextOffset returning %08lx\n", rv);
680: // }
681:
682: *result = rv;
683: }
684:
685:
686: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.