Windows2000/private/windbg64/debugger/dm/dmdisasm.c
2020-09-30 17:12:32 +02:00

320 lines
7.1 KiB
C

/**** DMDISASM.C - EM Lego disassembler interface *
* *
* *
* Copyright <C> 1995, Microsoft Corp *
* *
* Created: January 1, 1996 by Kent Forschmiedt
* *
* Revision History: *
* *
* *
* *
*/
#include "precomp.h"
#pragma hdrstop
#include <simpldis.h>
#define MAXL 20
#define CCHMAX 256
#if defined(TARGET_i386)
#define SIMPLE_ARCH_CURRENT Simple_Arch_X86
#elif defined(TARGET_ALPHA) || defined(TARGET_AXP64)
#define SIMPLE_ARCH_CURRENT Simple_Arch_AlphaAxp
#elif defined(TARGET_IA64)
#define SIMPLE_ARCH_CURRENT Simple_Arch_IA64
#else
#error "Undefined processor"
#endif
int
CvRegFromSimpleReg(
MPT mpt,
int regInstr
)
{
switch (mpt) {
case mptix86:
switch(regInstr) {
case SimpleRegEax: return CV_REG_EAX;
case SimpleRegEcx: return CV_REG_ECX;
case SimpleRegEdx: return CV_REG_EDX;
case SimpleRegEbx: return CV_REG_EBX;
case SimpleRegEsp: return CV_REG_ESP;
case SimpleRegEbp: return CV_REG_EBP;
case SimpleRegEsi: return CV_REG_ESI;
case SimpleRegEdi: return CV_REG_EDI;
}
break;
case mptdaxp:
return (regInstr + CV_ALPHA_IntV0);
case mptia64:
assert(!"Will need code for IA64"); //v-vadimp when msdis is ready
}
return (0);
}
#if !defined(TARGET_IA64) //v-vadimp we are so far using falcon
ULONGLONG
QwGetreg(
PVOID pv,
int regInstr
)
{
HTHDX hthdx = (HTHDX)pv;
XOSD xosd;
ULONGLONG retVal;
retVal = GetRegValue(&hthdx->context,
CvRegFromSimpleReg(MPT_CURRENT, regInstr)
);
return retVal;
}
XOSD
disasm (
HTHDX hthd,
LPSDI lpsdi,
PVOID Memory,
int Size
)
{
XOSD xosd = xosdNone;
int cbUsed;
int Bytes;
SIMPLEDIS Sdis;
Bytes = SimplyDisassemble(
Memory, // code ptr
Size, // bytes
//BUGBUG 64 bits
(ULONG)GetAddrOff(lpsdi->addr),
SIMPLE_ARCH_CURRENT,
&Sdis,
NULL,
NULL,
NULL,
QwGetreg,
(PVOID)hthd
);
if (Bytes < 0) {
cbUsed = -Bytes;
xosd = xosdGeneral;
} else {
cbUsed = Bytes;
}
return xosd;
}
DWORD
BranchUnassemble(
HTHDX hthd,
PVOID Memory,
DWORD Size,
LPADDR Addr,
BOOL *IsBranch,
BOOL *TargetKnown,
BOOL *IsCall,
BOOL *IsTable,
LPADDR Target
)
{
int cbUsed;
int Bytes;
SIMPLEDIS Sdis;
DWORD64 dwTarget = 0;
Bytes = SimplyDisassemble(
Memory, // code ptr
Size, // bytes
(ULONG)GetAddrOff(*Addr),
SIMPLE_ARCH_CURRENT,
&Sdis,
NULL,
NULL,
NULL,
QwGetreg,
(PVOID)hthd
);
if (Bytes < 0) {
*IsBranch = FALSE;
*IsTable = FALSE;
*IsCall = FALSE;
*TargetKnown = FALSE;
return 0;
}
*IsBranch = Sdis.IsBranch;
*IsCall = Sdis.IsCall;
*IsTable = FALSE;
if (*IsBranch) {
// when do we know the branch target, and when do we not?
if (Sdis.dwJumpTable && !Sdis.dwBranchTarget) {
*IsTable = TRUE;
dwTarget = SE32To64( Sdis.dwJumpTable );
} else {
*IsTable = FALSE;
dwTarget = SE32To64( Sdis.dwBranchTarget );
}
}
if (*IsCall) {
*IsCall = TRUE;
dwTarget = SE32To64( Sdis.dwBranchTarget );
}
*TargetKnown = !!dwTarget;
if (*TargetKnown) {
AddrInit( Target,
0,
0,
dwTarget,
TRUE,
TRUE,
FALSE,
FALSE
);
}
return Bytes;
}
#endif
ULONG64
GetNextOffset (
HTHDX hthd,
BOOL fStep
)
/*++
Routine Description:
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.
trace -> the next instruction to execute
step -> the instruction in the next memory location or the
next instruction executed due to a branch (step
over subroutine calls).
Arguments:
hthd - Supplies the handle to the thread to get the next offset for
fStep - Supplies TRUE for STEP offset and FALSE for trace offset
Returns:
step or trace offset if input is TRUE or FALSE, respectively
Version Information:
This copy of GetNextOffset is from ntsd\alpha\ntdis.c@v16 (11/14/92)
--*/
{
int Bytes;
PUCHAR Memory[MAX_INSTRUCTION_SIZE];
DWORD Size;
BOOL r;
ADDR TargetAddr;
ADDR IpAddr;
BOOL IsBranch;
BOOL TargetKnown;
BOOL IsCall;
BOOL IsTable;
DWORD64 NewOffset;
#if defined (TARGET_ALPHA) || defined (TARGET_AXP64)
ULONG64
AlpGetNextOffset (
HTHDX hthd,
BOOL fStep
);
DWORD64 AnswerX = AlpGetNextOffset(hthd, fStep);
return AnswerX;
#endif
#ifdef TARGET_IA64
ULONG64
IA64GetNextOffset (
HTHDX hthd,
BOOL fStep
);
DWORD64 AnswerX = IA64GetNextOffset(hthd, fStep);
return AnswerX;
#endif
AddrFromHthdx(&IpAddr, hthd);
// relative addressing updates PC first
// Assume next sequential instruction is next offset
r = AddrReadMemory(hthd->hprc,
hthd,
&IpAddr,
Memory,
MAX_INSTRUCTION_SIZE,
&Size );
if (!r) {
DPRINT(1, ("GetNextOffset: failed AddrReadMemory %I64x\n", GetAddrOff(IpAddr)));
assert(FALSE);
return 4;
}
Bytes = BranchUnassemble( hthd,
Memory,
Size,
&IpAddr,
&IsBranch,
&TargetKnown,
&IsCall,
&IsTable,
&TargetAddr
);
NewOffset = IpAddr.addr.off + Bytes;
// use the target address if it is a trace, or if it is a step and
// the instruction is not a call.
if (!fStep && IsCall && TargetKnown) {
NewOffset = GetAddrOff(TargetAddr);
}
if (IsBranch && TargetKnown) {
NewOffset = GetAddrOff(TargetAddr);
}
return NewOffset;
}