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

1741 lines
52 KiB
C

/*
*** Copyright (C) 1996-97 Intel Corporation. All rights reserved.
*** The information and source code contained herein is the exclusive
*** property of Intel Corporation and may not be disclosed, examined
*** or reproduced in whole or in part without explicit written authorization
*** from the company.
*/
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
ia64mach.c
Abstract:
This file contains the IA64 specific code for dealing with
the process of stepping a single instruction. This includes
determination of the next offset to be stopped at and if the
instruction is all call type instruction.
Author:
Ho Chen (hc)
Vadim Paretsky - major mods
Environment:
Win32 - User
Notes:
--*/
#include "precomp.h"
#pragma hdrstop
extern CRITICAL_SECTION csContinueQueue;
extern LPDM_MSG LpDmMsg;
/*
//setup a couple of macros
// The below macro is used to do subscripting operations
// len_item is the length of the embedded word that we are
// interested in subscripting
#define NTH_BIT(word,n,len_item) \
( ((word) >> ((len_item) - (n) - 1)) & 0x01)
*/
// Stuff for EM debug registers
#define RWE_WRITE (DWORDLONG)0x4000000000000000
#define RWE_READ (DWORDLONG)0x8000000000000000
#define RWE_EXEC (DWORDLONG)0x8000000000000000
#define RWE_MASK (DWORDLONG)0xf000000000000000
#define PLM_0 (DWORDLONG)0x0100000000000000
#define PLM_1 (DWORDLONG)0x0200000000000000
#define PLM_2 (DWORDLONG)0x0400000000000000
#define PLM_3 (DWORDLONG)0x0800000000000000
#define PLM_MASK (DWORDLONG)0x0f00000000000000
DWORDLONG LenMask[ MAX_DEBUG_REG_DATA_SIZE + 1 ] = DEBUG_REG_LENGTH_MASKS;
#define WIN_CDECL __cdecl
#define DECEM 1 /* GetNextOffset() based on Intel Falcon decoder DLL */
#include "EMTOOLS\decem.h"
BOOL RequestEMToDecode(HTHDX hthd, LPADDR lpAddr, EM_Decoder_Info* pInfo)
{
#if 0
IA64_INSTRUCTION disInstr;
ADDR BundleAddr = *lpAddr;
DWORD InstLen;
BYTE dwSlot = (BYTE)((GetAddrOff(*lpAddr) & 0xF) >> 2);
static EM_Decoder_Info Info[3];
static UOFFSET LastOffset = 0;
GetAddrOff(BundleAddr) &= ~0xF;
if (!AddrReadMemory( hthd->hprc, hthd, &BundleAddr, &disInstr, BUNDLE_SIZE, &InstLen)) {
DPRINT(0,("RequestEMToDecode: AddrReadMemory @ 0x%I64x failed\n",GetAddrOff(BundleAddr)));
return FALSE;
}
if (InstLen != BUNDLE_SIZE ) {
DPRINT(0,("RequestEMToDecode: ReadMemory @ 0x%I64x failed\n", GetAddrOff(BundleAddr)));
return FALSE;
}
// we check to see if the bundle out instruction belongs to has just been disaassembled by the EM
// (it disassembles by bundle, not by instruction; if so we just pick up the needed slot,if not
// we ask it to disassemble the bundle first
if (dwSlot == 0 && GetAddrOff(BundleAddr) != LastOffset) {
if (DMSendRequestReply (dbceDecode, hthd->hprc->hpid, hthd->htid, BUNDLE_SIZE, &disInstr, sizeof(Info), &Info) != xosdNone) {
DPRINT(0,("RequestEMToDecode: Decode @ 0x%I64x failed \n", GetAddrOff(BundleAddr)));
return FALSE;
}
LastOffset = GetAddrOff(BundleAddr);
}
*pInfo = Info[dwSlot];
return TRUE;
#else
ASSERT(!"EMDecode not supported");
return FALSE;
}
typedef struct
{
ULONGLONG Slot[3];
ULONGLONG Template;
} IA64_BUNDLE;
enum op_type { BAD_OP, I_OP, M_OP, F_OP, B_OP };
enum op_type OpType[64] = { M_OP, I_OP, I_OP, BAD_OP,
M_OP, I_OP, I_OP, BAD_OP,
M_OP, I_OP, BAD_OP, BAD_OP,
BAD_OP, BAD_OP, BAD_OP, BAD_OP,
M_OP, M_OP, I_OP, BAD_OP,
M_OP, M_OP, I_OP, BAD_OP,
M_OP, F_OP, I_OP, BAD_OP,
M_OP, M_OP, F_OP, BAD_OP,
M_OP, I_OP, B_OP, BAD_OP,
M_OP, B_OP, B_OP, BAD_OP,
BAD_OP, BAD_OP, BAD_OP, BAD_OP,
B_OP, B_OP, B_OP, BAD_OP,
M_OP, M_OP, B_OP, BAD_OP,
BAD_OP, BAD_OP, BAD_OP, BAD_OP,
M_OP, F_OP, B_OP, BAD_OP,
BAD_OP, BAD_OP, BAD_OP, BAD_OP};
#define OP_TYPE(Template,Slot) OpType[(Template << 2) | Slot]
#define BITS(BitField,iHigh,iLow) (ULONGLONG)(((ULONGLONG)BitField << (63 - iHigh)) >> (63-iHigh + iLow))
#define MAJOR_OPCODE(op) BITS(op,40,37)
BOOL GetInstAndTemplate(HTHDX hthd, LPADDR lpAddr, PULONGLONG pInst, PULONGLONG pTemplate)
{
ADDR addr = *lpAddr;
DWORD InstLen;
BOOL bSlot1;
if(!AddrReadMemory(hthd->hprc, hthd, &addr, pInst, sizeof(ULONGLONG), &InstLen)) {
return FALSE;
}
bSlot1 = FALSE;
switch(GetAddrOff(addr) & 0xF) {
case 0: *pInst = ((*pInst) & INST_SLOT0_MASK) >> 5;
break;
case 4: *pInst = ((*pInst) & INST_SLOT1_MASK) >> 14;
bSlot1 = TRUE;
break;
case 8: *pInst = ((*pInst) & INST_SLOT2_MASK) >> 23;
break;
default:
assert(!"Bad Slot");
}
GetAddrOff(addr) &= ~0xF;
if(!AddrReadMemory(hthd->hprc, hthd, &addr, pTemplate, sizeof(ULONGLONG), &InstLen)) {
return FALSE;
}
*pTemplate = ((*pTemplate) & INST_TEMPL_MASK) >> 1;
if(*pTemplate == 0x2 && bSlot1) { //check for the MLI template, for movl it we need to reread slot 2, since that's where all the interesting info about it (predicate, etc), really is
addr = *lpAddr;
GetAddrOff(addr) += 4;
if(!AddrReadMemory(hthd->hprc, hthd, &addr, pInst, sizeof(ULONGLONG), &InstLen)) {
return FALSE;
}
*pInst = ((*pInst) & INST_SLOT2_MASK) >> 23;
}
return TRUE;
}
BOOL IsInstBreak(ULONGLONG Inst, DWORD dwSlot, ULONGLONG Template)
{
if (MAJOR_OPCODE(Inst) != 0) { // the major opcode has to be 0
return FALSE;
}
if (BITS(Inst,32,27) != 0) { //6 bits 32:37 has to be 0
return FALSE;
}
if ((BITS(Inst,35,33) != 0) && (OP_TYPE(Template,dwSlot) != B_OP)) { //bits 35:33 has to be 0 everywhere but break.b
return FALSE;
}
return TRUE;
}
BOOL IsInstBranch(ULONGLONG Inst, DWORD dwSlot, ULONGLONG Template, DWORD dwMajorOpcode)
{
if (OP_TYPE(Template,dwSlot) != B_OP) { // not a B; period
DPRINT(1,("Inst: %I64x; Template:%I64x; Slot:%x - not a B\n",Inst,Template,dwSlot));
return FALSE;
}
if (MAJOR_OPCODE(Inst) == dwMajorOpcode) {
DPRINT(1,("Inst: %I64x; Template:%I64x; Slot:%x - a B with opcode %i\n",Inst,Template,dwSlot,dwMajorOpcode));
return TRUE;
} else {
DPRINT(1,("Inst: %I64x; Template:%I64x; Slot:%x - a B but not with opcode %i\n",Inst,Template,dwSlot,dwMajorOpcode));
return FALSE;
}
}
BOOL IsInstBranchReturn(ULONGLONG Inst, DWORD dwSlot, ULONGLONG Template)
{
if (OP_TYPE(Template,dwSlot) != B_OP) { // not a B; period
return FALSE;
}
if ((MAJOR_OPCODE(Inst) == 0) // major opcode 0
&& (BITS(Inst,32,27) == 21) // opcode extension 21
&& (BITS(Inst,8,6) == 4)) { // branch type opcode extension 4
return TRUE;
}
return FALSE;
}
void IsCall (HTHDX hthd, LPADDR lpaddr, LPINT lpf, BOOL fStepOver )
/*++
Routine Description:
IsCall
Arguments:
hthd - Supplies the handle to the thread
lpaddr - Supplies the address to be check for a call instruction
lpf - Returns class of instruction:
CALL
BREAKPOINT_INSTRUCTION
SOFTWARE_INTERRUPT
FALSE
fStepOver
Return Value:
None.
--*/
{
DWORD InstLen;
BYTE PredReg;
BYTE dwSlot = (BYTE)((GetAddrOff(*lpaddr) & 0xF) >> 2);
ULONGLONG Inst, Template;
DPRINT(0,("Entering the IsCall routine for %p\n", GetAddrOff(*lpaddr)));
if (hthd->fIsCallDone) {
*lpaddr = hthd->addrIsCall;
*lpf = hthd->iInstrIsCall;
DPRINT(0,("fIsCallDone was set, exiting\n"));
return;
}
/*
* Read in a bundle which contains the instruction under inspection to get the template
*/
if (!GetInstAndTemplate(hthd, lpaddr, &Inst, &Template)) {
DPRINT(0,("IsCall: Failed to get inst and template @ %p",GetAddrOff(*lpaddr)));
return;
}
PredReg = (BYTE)BITS(Inst,5,0);
if (((hthd->context.Preds >> PredReg) & 0x1) == 0) { //unset or bad predicate, we dont' care what the instruction really is
DPRINT(0,("IsCall: Predicate not set %I64x:%i:%I64i\n",
hthd->context.Preds,
(DWORD)PredReg,
hthd->context.Preds >> PredReg
));
} else if (IsInstBreak(Inst,dwSlot,Template)) {
DPRINT(0,("IsCall was a break, predicate set: Inst:%I64x Pred:%i\n",
Inst,
(DWORD)PredReg
));
switch (((BITS(Inst,36,36) << 21) | BITS(Inst,25,6)) & 0x1c0000) {
case BREAK_SYSCALL_BASE:
case BREAK_FASTSYS_BASE:
*lpf = INSTR_IS_CALL;
DPRINT(0,("IsCall opcode was a INSTR_IS_CALL\n"));
break;
case BREAK_DEBUG_BASE:
*lpf = INSTR_BREAKPOINT;
DPRINT(0,("IsCall opcode was an INSTR_BREAKPOINT\n"));
break;
default:
*lpf = INSTR_SOFT_INTERRUPT;
DPRINT(0,("IsCall opcode was a INSTR_SOFT_INTERRUPT\n"));
break;
}
} else if (IsInstBranch(Inst,dwSlot,Template,5)) {
DPRINT(0,("IsCall opcode == br.call b1=target25\n"));
*lpf = INSTR_IS_CALL;
} else if (IsInstBranch(Inst,dwSlot,Template,1)) {
DPRINT(0,("IsCall opcode == br.call b1=b2\n"));
*lpf = INSTR_IS_CALL;
} else {
DPRINT(0,("IsCall opcode == DEFAULT (not a call)\n"));
*lpf = FALSE;
}
// v-vadimp - shouldn't GetNextOffset do the following?
// advance current address for StepOver() breakpoint setting
if (*lpf==INSTR_IS_CALL || *lpf==INSTR_SOFT_INTERRUPT ) {
DPRINT(0,("Putting address in addrIsCall\n"));
lpaddr->addr.off += 0x10;
lpaddr->addr.off &= ~0xf;
if (*lpf==INSTR_IS_CALL) {
hthd->addrIsCall = *lpaddr;
}
}
hthd->iInstrIsCall = *lpf;
return;
} /* IsCall() */
BOOL IsRet(HTHDX hthd,LPADDR lpaddr)
{
DWORD InstLen;
BYTE PredReg;
BYTE dwSlot = (BYTE)((GetAddrOff(*lpaddr) & 0xF) >> 2);
ULONGLONG Inst, Template;
DPRINT(0,("Entering the IsRet routine for %p\n", GetAddrOff(*lpaddr)));
/*
* Read in a bundle which contains the instruction under inspection to get the template
*/
if (!GetInstAndTemplate(hthd, lpaddr, &Inst, &Template)) {
return FALSE;
}
PredReg = (BYTE)BITS(Inst,5,0);
if (((hthd->context.Preds >> PredReg) & 0x1) == 0) { //unset or bad predicate, we dont' care what the instruction really is
DPRINT(0,("IsRet: Predicate not set %I64x:%i:%I64i\n",
hthd->context.Preds,
(DWORD)PredReg,
hthd->context.Preds >> PredReg
));
return FALSE;
}
if (IsInstBranchReturn(Inst,dwSlot,Template)) {
DPRINT(0,("IsRet opcode == br.ret b2\n"));
return TRUE;
}
DPRINT(0,("IsRet opcode == DEFAULT (not a ret)\n"));
return FALSE;
} /* IsRet() */
UOFFSET IA64GetNextOffset (HTHDX hthd,BOOL fStep)
/*++
Routine Description:
From a limited disassembly of the instruction pointed
by the IAR register, compute the offset of the next
instruction for either a trace or step operation.
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
Return Value:
Offset to place breakpoint at for doing a STEP or TRACE
--*/
{
UOFFSET returnvalue;
ADDR firaddr;
DWORD InstLen;
BYTE dwSlot, PredReg;
ULONGLONG Inst, Template;
AddrFromHthdx(&firaddr, hthd);
DPRINT(0,("Entering the GetNextOffset routine for %p\n",GetAddrOff(firaddr)));
dwSlot = (BYTE)((GetAddrOff(firaddr) & 0xF) >> 2);
// increment current address as default return value
switch(dwSlot) {
case 0:
case 1:
returnvalue = GetAddrOff(firaddr) + 4;
break;
case 2:
returnvalue = GetAddrOff(firaddr) + 8;
break;
default:
DPRINT(0, ("(GetNextOffset?) illegal EM address FIR=%p", GetAddrOff(firaddr)));
}
if (!GetInstAndTemplate(hthd, &firaddr, &Inst, &Template))
{
DPRINT(0,("GetNextOffset: Failed to get inst and template @ %p",GetAddrOff(firaddr)));
return returnvalue;
}
PredReg = (BYTE)BITS(Inst,5,0);
if (IsInstBreak(Inst,dwSlot,Template)) {
DPRINT(0,("we have - break, \n"));
switch (((BITS(Inst,36,36) << 21) | BITS(Inst,25,6)) & 0x1c0000) {
case BREAK_SYSCALL_BASE: //stepping over a syscall inst sets a break on the callers return address
case BREAK_FASTSYS_BASE:
DPRINT(0,("Sys instruction - Setting next offset to %p\n",hthd->context.BrRp));
returnvalue = (UOFFSET)(hthd->context.BrRp);
break;
}
}
else if (IsInstBranch(Inst,dwSlot,Template,5)) { // IP relative call
DPRINT(0,("We have - br.call b1=target25\n"));
if (((hthd->context.Preds >> PredReg) & 0x1) && !fStep) { // predicate set and not StepOver
//LONG offset = (((INT)(BITS(Inst,36,36) << 21) | (LONG)(BITS(Inst,32,13) << 4)) << 11) >> 11;
//DPRINT(0,("target25 - offset:%li\n",offset));
returnvalue = (GetAddrOff(firaddr) & ~0xF) + ((((INT)(BITS(Inst,36,36) << 21) | (LONG)(BITS(Inst,32,13) << 4)) << 11) >> 11); //target25 == (sext(s<<20|imm21)) << 4;
}
}
else if (IsInstBranch(Inst,dwSlot,Template,1)) {// indirect call
DPRINT(0,("We have - br.call b1=b2\n"));
if (((hthd->context.Preds >> PredReg) & 0x1) && !fStep) { // predicate set and not StepOver
returnvalue = (UOFFSET)((ULONGLONG *)(&hthd->context.BrRp)[BITS(Inst,15,13)]);
}
} else if (IsInstBranch(Inst,dwSlot,Template,0)) { // indirect branch
DPRINT(0,("We have - br.<...> (minor opcode:%I64i) b1=b2\n",BITS(Inst,8,6)));
if ((hthd->context.Preds >> PredReg) & 0x1) // predicate set
returnvalue = (UOFFSET)((ULONGLONG *)(&hthd->context.BrRp)[BITS(Inst,15,13)]);
} else if (IsInstBranch(Inst,dwSlot,Template,4)) { // IP relative branch
UOFFSET NewReturnValue = (GetAddrOff(firaddr) & ~0xF) + ((((INT)(BITS(Inst,36,36) << 21) | (LONG)(BITS(Inst,32,13) << 4)) << 11) >> 11); //target25 == (sext(s<<20|imm21)) << 4;
switch (BITS(Inst,8,6)) {
case 0: // regular conditional branch
DPRINT(0,("We have - br.cond target25"));
if ((hthd->context.Preds >> PredReg) & 0x1) // taken if predicate set
returnvalue = NewReturnValue;
break;
case 2: // wexit
DPRINT(0,("We have - br.wexit b1=target25\n"));
if (!((hthd->context.Preds >> PredReg) & 0x1) && (hthd->context.ApEC <= 1)) // taken if predicate not set and EC <= 1
returnvalue = NewReturnValue;
break;
case 3: //wtop
DPRINT(0,("We have - br.wtop b1=target25\n"));
if (((hthd->context.Preds >> PredReg) & 0x1) || (hthd->context.ApEC > 1)) // taken if predicate set or EC > 1
returnvalue = NewReturnValue;
break;
case 5: // cloop
DPRINT(0,("We have - br.cloop target25"));
if (hthd->context.ApLC != 0) // taken if LC !=0
returnvalue = NewReturnValue;
break;
case 6: // cexit
DPRINT(0,("We have - br.cexit b1=target25\n"));
if ((hthd->context.ApLC ==0) && (hthd->context.ApEC <= 1)) // taken if LC==0 and EC <=1
returnvalue = NewReturnValue;
break;
case 7: // ctop
DPRINT(0,("We have - br.ctop b1=target25\n"));
if ((hthd->context.ApLC !=0) || (hthd->context.ApEC > 1)) // taken if LC!=0 or EC >1
returnvalue = NewReturnValue;
break;
default:
DPRINT(0,("We have - br.<unknown> b1=target25!!!\n"));
break;
}
} else if (Template == 0x2 && dwSlot == 1) {
// that should signify movl
// increment return offset since movl instruction takes two instruction slots
DPRINT(0,("We have - movl.r1 imm64; returnvalue:%p",returnvalue));
switch(returnvalue & 0xf) {
case 8:
returnvalue += returnvalue;
break;
default:
DPRINT(0, ("(GetNextOffset?) illegal MOVL address: %p", GetAddrOff(firaddr)));
break;
}
} else {
DPRINT(0,("GetNextOffset: We have an unhandled DEFAULT op\n"));
}
DPRINT(0,("GetNextOffset: next offset is %p\n",returnvalue));
return returnvalue;
} /* GetNextOffset() */
DWORD
BranchUnassemble(
HTHDX hthd,
void *Memory,
DWORD Size,
ADDR *Addr,
BOOL *IsBranch,
BOOL *TargetKnown,
BOOL *IsCall,
BOOL *IsTable,
ADDR *Target
)
{
UOFFSET TargetOffset;
ADDR firaddr = *Addr;
EM_Decoder_Info info;
DPRINT(0,("Entering the BranchUnassemble routine"));
assert( Memory );
assert( IsBranch );
assert( TargetKnown );
assert( IsCall );
assert( Target );
TargetOffset = 0;
*IsBranch = FALSE;
*IsTable = FALSE;
*TargetKnown = FALSE;
GetAddrOff(firaddr) &= ~0xF;
if (RequestEMToDecode(hthd, &firaddr, &info)) {
switch( info.inst ) {
// IP-Relative call B3 - br.call b1=target25
case EM_BR_CALL_SPNT_FEW_B1_TARGET25:
case EM_BR_CALL_SPNT_MANY_B1_TARGET25:
case EM_BR_CALL_SPTK_FEW_B1_TARGET25:
case EM_BR_CALL_SPTK_MANY_B1_TARGET25:
case EM_BR_CALL_DPNT_FEW_B1_TARGET25:
case EM_BR_CALL_DPNT_MANY_B1_TARGET25:
case EM_BR_CALL_DPTK_FEW_B1_TARGET25:
case EM_BR_CALL_DPTK_MANY_B1_TARGET25:
case EM_BR_CALL_SPNT_FEW_CLR_B1_TARGET25:
case EM_BR_CALL_SPNT_MANY_CLR_B1_TARGET25:
case EM_BR_CALL_SPTK_FEW_CLR_B1_TARGET25:
case EM_BR_CALL_SPTK_MANY_CLR_B1_TARGET25:
case EM_BR_CALL_DPNT_FEW_CLR_B1_TARGET25:
case EM_BR_CALL_DPNT_MANY_CLR_B1_TARGET25:
case EM_BR_CALL_DPTK_FEW_CLR_B1_TARGET25:
case EM_BR_CALL_DPTK_MANY_CLR_B1_TARGET25:
*IsCall = TRUE;
*IsBranch = TRUE;
if (info.src1.type == EM_DECODER_IMMEDIATE) {
if (info.src1.imm_info.imm_type == EM_DECODER_IMM_SIGNED) {
*TargetKnown = TRUE;
TargetOffset = (IEL_GETDW0(info.src1.imm_info.val64)) + firaddr.addr.off;
}
}
break;
// IP-Relative branch B1 - br.cond target25
case EM_BR_COND_SPNT_FEW_TARGET25:
case EM_BR_COND_SPNT_MANY_TARGET25:
case EM_BR_COND_SPTK_FEW_TARGET25:
case EM_BR_COND_SPTK_MANY_TARGET25:
case EM_BR_COND_DPNT_FEW_TARGET25:
case EM_BR_COND_DPNT_MANY_TARGET25:
case EM_BR_COND_DPTK_FEW_TARGET25:
case EM_BR_COND_DPTK_MANY_TARGET25:
case EM_BR_COND_SPNT_FEW_CLR_TARGET25:
case EM_BR_COND_SPNT_MANY_CLR_TARGET25:
case EM_BR_COND_SPTK_FEW_CLR_TARGET25:
case EM_BR_COND_SPTK_MANY_CLR_TARGET25:
case EM_BR_COND_DPNT_FEW_CLR_TARGET25:
case EM_BR_COND_DPNT_MANY_CLR_TARGET25:
case EM_BR_COND_DPTK_FEW_CLR_TARGET25:
case EM_BR_COND_DPTK_MANY_CLR_TARGET25:
*IsCall = FALSE;
*IsBranch = TRUE;
if (info.src1.type == EM_DECODER_IMMEDIATE) {
if (info.src1.imm_info.imm_type == EM_DECODER_IMM_SIGNED) {
*TargetKnown = TRUE;
TargetOffset = (IEL_GETDW0(info.src1.imm_info.val64)) + firaddr.addr.off;
}
}
break;
// - br.wexit target25
case EM_BR_WEXIT_SPNT_FEW_TARGET25:
case EM_BR_WEXIT_SPNT_MANY_TARGET25:
case EM_BR_WEXIT_SPTK_FEW_TARGET25:
case EM_BR_WEXIT_SPTK_MANY_TARGET25:
case EM_BR_WEXIT_DPNT_FEW_TARGET25:
case EM_BR_WEXIT_DPNT_MANY_TARGET25:
case EM_BR_WEXIT_DPTK_FEW_TARGET25:
case EM_BR_WEXIT_DPTK_MANY_TARGET25:
case EM_BR_WEXIT_SPNT_FEW_CLR_TARGET25:
case EM_BR_WEXIT_SPNT_MANY_CLR_TARGET25:
case EM_BR_WEXIT_SPTK_FEW_CLR_TARGET25:
case EM_BR_WEXIT_SPTK_MANY_CLR_TARGET25:
case EM_BR_WEXIT_DPNT_FEW_CLR_TARGET25:
case EM_BR_WEXIT_DPNT_MANY_CLR_TARGET25:
case EM_BR_WEXIT_DPTK_FEW_CLR_TARGET25:
case EM_BR_WEXIT_DPTK_MANY_CLR_TARGET25:
*IsCall = FALSE;
*IsBranch = TRUE;
if (info.src1.type == EM_DECODER_IMMEDIATE) {
if (info.src1.imm_info.imm_type == EM_DECODER_IMM_SIGNED) {
*TargetKnown = TRUE;
TargetOffset =(IEL_GETDW0(info.src1.imm_info.val64)) + firaddr.addr.off;
}
} // if PR[qp] = 0, kernel; fall-thru
break;
// - br.wtop target25
case EM_BR_WTOP_SPNT_FEW_TARGET25:
case EM_BR_WTOP_SPNT_MANY_TARGET25:
case EM_BR_WTOP_SPTK_FEW_TARGET25:
case EM_BR_WTOP_SPTK_MANY_TARGET25:
case EM_BR_WTOP_DPNT_FEW_TARGET25:
case EM_BR_WTOP_DPNT_MANY_TARGET25:
case EM_BR_WTOP_DPTK_FEW_TARGET25:
case EM_BR_WTOP_DPTK_MANY_TARGET25:
case EM_BR_WTOP_SPNT_FEW_CLR_TARGET25:
case EM_BR_WTOP_SPNT_MANY_CLR_TARGET25:
case EM_BR_WTOP_SPTK_FEW_CLR_TARGET25:
case EM_BR_WTOP_SPTK_MANY_CLR_TARGET25:
case EM_BR_WTOP_DPNT_FEW_CLR_TARGET25:
case EM_BR_WTOP_DPNT_MANY_CLR_TARGET25:
case EM_BR_WTOP_DPTK_FEW_CLR_TARGET25:
case EM_BR_WTOP_DPTK_MANY_CLR_TARGET25:
*IsCall = FALSE;
*IsBranch = TRUE;
if (info.src1.type == EM_DECODER_IMMEDIATE) {
if (info.src1.imm_info.imm_type == EM_DECODER_IMM_SIGNED) {
*TargetKnown = TRUE;
TargetOffset =(IEL_GETDW0(info.src1.imm_info.val64)) + firaddr.addr.off;
}
}
else { // if PR[qp] = 0, kernel; branch
if (info.src1.type == EM_DECODER_IMMEDIATE) {
if (info.src1.imm_info.imm_type == EM_DECODER_IMM_SIGNED) {
*TargetKnown = TRUE;
TargetOffset =(IEL_GETDW0(info.src1.imm_info.val64)) + firaddr.addr.off;
}
}
}
break;
// IP-Relative counted branch B2 - br.cloop target25
case EM_BR_CLOOP_SPNT_FEW_TARGET25:
case EM_BR_CLOOP_SPNT_MANY_TARGET25:
case EM_BR_CLOOP_SPTK_FEW_TARGET25:
case EM_BR_CLOOP_SPTK_MANY_TARGET25:
case EM_BR_CLOOP_DPNT_FEW_TARGET25:
case EM_BR_CLOOP_DPNT_MANY_TARGET25:
case EM_BR_CLOOP_DPTK_FEW_TARGET25:
case EM_BR_CLOOP_DPTK_MANY_TARGET25:
case EM_BR_CLOOP_SPNT_FEW_CLR_TARGET25:
case EM_BR_CLOOP_SPNT_MANY_CLR_TARGET25:
case EM_BR_CLOOP_SPTK_FEW_CLR_TARGET25:
case EM_BR_CLOOP_SPTK_MANY_CLR_TARGET25:
case EM_BR_CLOOP_DPNT_FEW_CLR_TARGET25:
case EM_BR_CLOOP_DPNT_MANY_CLR_TARGET25:
case EM_BR_CLOOP_DPTK_FEW_CLR_TARGET25:
case EM_BR_CLOOP_DPTK_MANY_CLR_TARGET25:
*IsCall = FALSE;
*IsBranch = TRUE;
if (info.src1.type == EM_DECODER_IMMEDIATE) {
if (info.src1.imm_info.imm_type == EM_DECODER_IMM_SIGNED) {
*TargetKnown = TRUE;
TargetOffset = (IEL_GETDW0(info.src1.imm_info.val64)) + firaddr.addr.off;
}
}
break;
// - br.cexit target25
case EM_BR_CEXIT_SPNT_FEW_TARGET25:
case EM_BR_CEXIT_SPNT_MANY_TARGET25:
case EM_BR_CEXIT_SPTK_FEW_TARGET25:
case EM_BR_CEXIT_SPTK_MANY_TARGET25:
case EM_BR_CEXIT_DPNT_FEW_TARGET25:
case EM_BR_CEXIT_DPNT_MANY_TARGET25:
case EM_BR_CEXIT_DPTK_FEW_TARGET25:
case EM_BR_CEXIT_DPTK_MANY_TARGET25:
case EM_BR_CEXIT_SPNT_FEW_CLR_TARGET25:
case EM_BR_CEXIT_SPNT_MANY_CLR_TARGET25:
case EM_BR_CEXIT_SPTK_FEW_CLR_TARGET25:
case EM_BR_CEXIT_SPTK_MANY_CLR_TARGET25:
case EM_BR_CEXIT_DPNT_FEW_CLR_TARGET25:
case EM_BR_CEXIT_DPNT_MANY_CLR_TARGET25:
case EM_BR_CEXIT_DPTK_FEW_CLR_TARGET25:
case EM_BR_CEXIT_DPTK_MANY_CLR_TARGET25:
*IsCall = FALSE;
*IsBranch = TRUE;
if (info.src1.type == EM_DECODER_IMMEDIATE) {
if (info.src1.imm_info.imm_type == EM_DECODER_IMM_SIGNED) {
*TargetKnown = TRUE;
TargetOffset = (IEL_GETDW0(info.src1.imm_info.val64)) + firaddr.addr.off;
}
} // if LC > 0, kernel; fall-thru
break;
// - br.ctop target25
case EM_BR_CTOP_SPNT_FEW_TARGET25:
case EM_BR_CTOP_SPNT_MANY_TARGET25:
case EM_BR_CTOP_SPTK_FEW_TARGET25:
case EM_BR_CTOP_SPTK_MANY_TARGET25:
case EM_BR_CTOP_DPNT_FEW_TARGET25:
case EM_BR_CTOP_DPNT_MANY_TARGET25:
case EM_BR_CTOP_DPTK_FEW_TARGET25:
case EM_BR_CTOP_DPTK_MANY_TARGET25:
case EM_BR_CTOP_SPNT_FEW_CLR_TARGET25:
case EM_BR_CTOP_SPNT_MANY_CLR_TARGET25:
case EM_BR_CTOP_SPTK_FEW_CLR_TARGET25:
case EM_BR_CTOP_SPTK_MANY_CLR_TARGET25:
case EM_BR_CTOP_DPNT_FEW_CLR_TARGET25:
case EM_BR_CTOP_DPNT_MANY_CLR_TARGET25:
case EM_BR_CTOP_DPTK_FEW_CLR_TARGET25:
case EM_BR_CTOP_DPTK_MANY_CLR_TARGET25:
*IsCall = FALSE;
*IsBranch = TRUE;
if (info.src1.type == EM_DECODER_IMMEDIATE) {
if (info.src1.imm_info.imm_type == EM_DECODER_IMM_SIGNED) {
*TargetKnown = TRUE;
TargetOffset = (IEL_GETDW0(info.src1.imm_info.val64)) + firaddr.addr.off;
}
}
else { // if LC > 0, kernel; branch
if (info.src1.type == EM_DECODER_IMMEDIATE)
if (info.src1.imm_info.imm_type == EM_DECODER_IMM_SIGNED) {
*TargetKnown = TRUE;
TargetOffset = (IEL_GETDW0(info.src1.imm_info.val64)) + firaddr.addr.off;
}
}
break;
// Indirect call B5 - br.call b1=b2
case EM_BR_CALL_SPNT_FEW_B1_B2:
case EM_BR_CALL_SPNT_MANY_B1_B2:
case EM_BR_CALL_SPTK_FEW_B1_B2:
case EM_BR_CALL_SPTK_MANY_B1_B2:
case EM_BR_CALL_DPNT_FEW_B1_B2:
case EM_BR_CALL_DPNT_MANY_B1_B2:
case EM_BR_CALL_DPTK_FEW_B1_B2:
case EM_BR_CALL_DPTK_MANY_B1_B2:
case EM_BR_CALL_SPNT_FEW_CLR_B1_B2:
case EM_BR_CALL_SPNT_MANY_CLR_B1_B2:
case EM_BR_CALL_SPTK_FEW_CLR_B1_B2:
case EM_BR_CALL_SPTK_MANY_CLR_B1_B2:
case EM_BR_CALL_DPNT_FEW_CLR_B1_B2:
case EM_BR_CALL_DPNT_MANY_CLR_B1_B2:
case EM_BR_CALL_DPTK_FEW_CLR_B1_B2:
case EM_BR_CALL_DPTK_MANY_CLR_B1_B2:
*IsCall = TRUE;
*IsBranch = TRUE;
*TargetKnown = FALSE;
break;
// Indirect branch B4 - br.ia b2
case EM_BR_IA_SPNT_FEW_B2:
case EM_BR_IA_SPNT_MANY_B2:
case EM_BR_IA_SPTK_FEW_B2:
case EM_BR_IA_SPTK_MANY_B2:
case EM_BR_IA_DPNT_FEW_B2:
case EM_BR_IA_DPNT_MANY_B2:
case EM_BR_IA_DPTK_FEW_B2:
case EM_BR_IA_DPTK_MANY_B2:
case EM_BR_IA_SPNT_FEW_CLR_B2:
case EM_BR_IA_SPNT_MANY_CLR_B2:
case EM_BR_IA_SPTK_FEW_CLR_B2:
case EM_BR_IA_SPTK_MANY_CLR_B2:
case EM_BR_IA_DPNT_FEW_CLR_B2:
case EM_BR_IA_DPNT_MANY_CLR_B2:
case EM_BR_IA_DPTK_FEW_CLR_B2:
case EM_BR_IA_DPTK_MANY_CLR_B2:
*IsCall = FALSE;
*IsBranch = TRUE;
*TargetKnown = FALSE;
break;
// - br.cond b2
case EM_BR_COND_SPNT_FEW_B2:
case EM_BR_COND_SPNT_MANY_B2:
case EM_BR_COND_SPTK_FEW_B2:
case EM_BR_COND_SPTK_MANY_B2:
case EM_BR_COND_DPNT_FEW_B2:
case EM_BR_COND_DPNT_MANY_B2:
case EM_BR_COND_DPTK_FEW_B2:
case EM_BR_COND_DPTK_MANY_B2:
case EM_BR_COND_SPNT_FEW_CLR_B2:
case EM_BR_COND_SPNT_MANY_CLR_B2:
case EM_BR_COND_SPTK_FEW_CLR_B2:
case EM_BR_COND_SPTK_MANY_CLR_B2:
case EM_BR_COND_DPNT_FEW_CLR_B2:
case EM_BR_COND_DPNT_MANY_CLR_B2:
case EM_BR_COND_DPTK_FEW_CLR_B2:
case EM_BR_COND_DPTK_MANY_CLR_B2:
*IsCall = FALSE;
*IsBranch = TRUE;
*TargetKnown = FALSE;
break;
// - br.ret b2
case EM_BR_RET_SPNT_FEW_B2:
case EM_BR_RET_SPNT_MANY_B2:
case EM_BR_RET_SPTK_FEW_B2:
case EM_BR_RET_SPTK_MANY_B2:
case EM_BR_RET_DPNT_FEW_B2:
case EM_BR_RET_DPNT_MANY_B2:
case EM_BR_RET_DPTK_FEW_B2:
case EM_BR_RET_DPTK_MANY_B2:
case EM_BR_RET_SPNT_FEW_CLR_B2:
case EM_BR_RET_SPNT_MANY_CLR_B2:
case EM_BR_RET_SPTK_FEW_CLR_B2:
case EM_BR_RET_SPTK_MANY_CLR_B2:
case EM_BR_RET_DPNT_FEW_CLR_B2:
case EM_BR_RET_DPNT_MANY_CLR_B2:
case EM_BR_RET_DPTK_FEW_CLR_B2:
case EM_BR_RET_DPTK_MANY_CLR_B2:
*IsCall = FALSE;
*IsBranch = TRUE;
*TargetKnown = FALSE;
break;
default:
*IsCall = FALSE;
*IsBranch = FALSE;
*TargetKnown = FALSE;
break;
}
} else {
DPRINT(0,("Error disassembling instruction @ %I64x",GetAddrOff(firaddr)));
return 0;
}
AddrInit( Target, 0, 0, TargetOffset, TRUE, TRUE, FALSE, FALSE );
return sizeof(IA64_INSTRUCTION);
} /* BranchUnassemble() */
#endif //"native code"
#ifndef KERNEL
void
ProcessGetDRegsCmd(
HPRCX hprc,
HTHDX hthd,
LPDBB lpdbb
)
{
PULONGLONG lpdw = (PULONGLONG)LpDmMsg->rgb;
CONTEXT cxt;
int rs = 0;
DEBUG_PRINT( "ProcessGetDRegsCmd :\n");
if (hthd == 0) {
rs = 0;
} else {
cxt.ContextFlags = CONTEXT_DEBUG;
if (!GetThreadContext(hthd->rwHand, &cxt)) {
LpDmMsg->xosdRet = xosdUnknown;
rs = 0;
} else {
lpdw[0] = hthd->context.DbI0;
lpdw[1] = hthd->context.DbI1;
lpdw[2] = hthd->context.DbI2;
lpdw[3] = hthd->context.DbI3;
lpdw[4] = hthd->context.DbI4;
lpdw[5] = hthd->context.DbI5;
lpdw[6] = hthd->context.DbI6;
lpdw[7] = hthd->context.DbI7;
lpdw[8] = hthd->context.DbD0;
lpdw[9] = hthd->context.DbD1;
lpdw[10] = hthd->context.DbD2;
lpdw[11] = hthd->context.DbD3;
lpdw[12] = hthd->context.DbD4;
lpdw[13] = hthd->context.DbD5;
lpdw[14] = hthd->context.DbD6;
lpdw[15] = hthd->context.DbD7;
LpDmMsg->xosdRet = xosdNone;
rs = sizeof(CONTEXT);
}
}
Reply( rs, LpDmMsg, lpdbb->hpid );
return;
} /* ProcessGetDRegsCmd() */
void
ProcessSetDRegsCmd(
HPRCX hprc,
HTHDX hthd,
LPDBB lpdbb
)
{
PULONGLONG lpdw = (PULONGLONG)(lpdbb->rgbVar);
XOSD xosd = xosdNone;
Unreferenced(hprc);
DPRINT(0, ("ProcessSetDRegsCmd : "));
hthd->context.ContextFlags = CONTEXT_DEBUG;
hthd->context.DbI0 = lpdw[0];
hthd->context.DbI1 = lpdw[1];
hthd->context.DbI2 = lpdw[2];
hthd->context.DbI3 = lpdw[3];
hthd->context.DbI4 = lpdw[4];
hthd->context.DbI5 = lpdw[5];
hthd->context.DbI6 = lpdw[6];
hthd->context.DbI7 = lpdw[7];
hthd->context.DbD0 = lpdw[8];
hthd->context.DbD1 = lpdw[9];
hthd->context.DbD2 = lpdw[10];
hthd->context.DbD3 = lpdw[11];
hthd->context.DbD4 = lpdw[12];
hthd->context.DbD5 = lpdw[13];
hthd->context.DbD6 = lpdw[14];
hthd->context.DbD7 = lpdw[15];
if (hthd->fWowEvent) {
WOWSetThreadContext(hthd, &hthd->context);
} else {
SetThreadContext(hthd->rwHand, &hthd->context);
}
Reply(0, &xosd, lpdbb->hpid);
return;
} /* ProcessSetDRegsCmd() */
/*VOID
MakeThreadSuspendItselfHelper(
HTHDX hthd,
FARPROC lpSuspendThread
)
{
ULONG NewBspStore;
ULONGLONG ArgumentsCopy[2];
ULONG Count = 0;
ULONG ShiftCount;
BOOLEAN RnatSaved = FALSE;
DWORD i, ra;
// set up the args to SuspendThread. IA64 software convention defines the
// parameter passing via backing store(r32-r39). Prepare argument copy
// with current thread handle and RNAT if its backing store address [10:3]
// are all 1.
NewBspStore = (ULONG)hthd->context.RsBSPSTORE;
if ((NewBspStore & 0x1F8) == 0x1F8) {
ArgumentsCopy[Count++] = hthd->context.RsRNAT;
NewBspStore += sizeof(ULONGLONG);
RnatSaved = TRUE;
}
ShiftCount = (NewBspStore & 0x1F8) >> 3;
hthd->context.RsRNAT &= ~(0x1 << ShiftCount);
ArgumentsCopy[Count++] = (ULONGLONG)GetCurrentThread();
NewBspStore += sizeof(ULONGLONG);
if ((RnatSaved == FALSE) && ((NewBspStore & 0x1F8) == 0x1F8)) {
ArgumentsCopy[Count++] = hthd->context.RsRNAT;
NewBspStore += sizeof(ULONGLONG);
}
// Copy the argument onto the backing store
AddrWriteMemory(hthd->hprc,
hthd,
(LPADDR)hthd->context.RsBSPSTORE,
ArgumentsCopy,
Count * sizeof(ULONGLONG),
&i);
// zero out loadrs, adjust RseStack
hthd->context.RsRSC = (RSC_MODE_LY<<RSC_MODE)
| (RSC_BE_LITTLE<<RSC_BE)
| (0x3<<RSC_PL);
// Setup argument numbers
hthd->context.StIFS = (ULONGLONG)Count; // # of arguments/size of frame(sof)
hthd->context.RsBSP = hthd->context.RsBSPSTORE = P32ToP64((LPVOID)NewBspStore);
// Set the address of the target code into IIP and IPSR.ri; save the current IIP in RP.
// No change to Sp and Ap.
ra = PC(hthd);
hthd->context.BrRp = P32ToP64((LPVOID)ra);
hthd->context.StIIP = P32ToP64(*lpSuspendThread);
hthd->context.StIPSR &= ~((ULONGLONG)0x3 << PSR_RI);
hthd->context.StIPSR |= ((hthd->context.StIIP & 0xf) >> 2) << PSR_RI;
hthd->context.StIIP &= 0xf;
hthd->fContextDirty = TRUE;
}
*/
#endif // !KERNEL
XOSD
SetupFunctionCall(
LPEXECUTE_OBJECT_DM lpeo,
LPEXECUTE_STRUCT lpes
)
{
/*
* Can only execute functions on the current stopped thread. Therefore
* assert that the current thread is stopped.
*/
assert(lpeo->hthd->tstate & ts_stopped);
if (!(lpeo->hthd->tstate & ts_stopped)) {
return xosdBadThread;
}
/*
* Now get the current stack offset.
*/
lpeo->addrStack.addr.off = (ULONG)lpeo->hthd->context.IntSp;
/*
* Now place the return address correctly
*/
// No need to update StIPSR.ri. return address is a bundle address.
lpeo->hthd->context.StIIP = lpeo->hthd->context.BrRp =
//P32ToP64((LPVOID)lpeo->addrStart.addr.off); v-vadimp???
/*
* Set the instruction pointer to the starting addresses
* and write the context back out
*/
lpeo->hthd->context.StIIP = GetAddrOff(lpeo->addrStart);
lpeo->hthd->fContextDirty = TRUE;
return xosdNone;
}
BOOL
CompareStacks(
LPEXECUTE_OBJECT_DM lpeo
)
/*++
Routine Description:
This routine is used to determine if the stack pointers are currect
for terminating function evaluation.
Arguments:
lpeo - Supplies the pointer to the DM Execute Object description
Return Value:
TRUE if the evaluation is to be terminated and FALSE otherwise
--*/
{
if (lpeo->addrStack.addr.off <= lpeo->hthd->context.IntSp) {
return TRUE;
}
return FALSE;
} /* CompareStacks() */
BOOL
ProcessFrameStackWalkNextCmd(
HPRCX hprc,
HTHDX hthd,
PCONTEXT context,
LPVOID pctxPtrs
)
{
return FALSE;
}
BOOL
SetupDebugRegister(
HTHDX hthd,
int Register,
int DataSize,
DWORDLONG DataAddr,
DWORD BpType
)
/*++
Routine Description:
This routine is used to initialize the selected debug register.
Arguments:
Register - Selected debug register # (0-3).
DataSize - Data size to be match in byte. Used by LenMask[] to select debug mask..
DataAddr - Breakpoint address
BpType - Breakpoint types. Defined in od.h
Return Value:
TRUE if successful and FALSE otherwise
--*/
{
DWORDLONG Len;
#ifdef KERNEL
KSPECIAL_REGISTERS ksr;
PULONGLONG DbI0 = &ksr.KernelDbI0;
PULONGLONG DbI1 = &ksr.KernelDbI1;
PULONGLONG DbI2 = &ksr.KernelDbI2;
PULONGLONG DbI3 = &ksr.KernelDbI3;
PULONGLONG DbI4 = &ksr.KernelDbI4;
PULONGLONG DbI5 = &ksr.KernelDbI5;
PULONGLONG DbI6 = &ksr.KernelDbI6;
PULONGLONG DbI7 = &ksr.KernelDbI7;
PULONGLONG DbD0 = &ksr.KernelDbD0;
PULONGLONG DbD1 = &ksr.KernelDbD1;
PULONGLONG DbD2 = &ksr.KernelDbD2;
PULONGLONG DbD3 = &ksr.KernelDbD3;
PULONGLONG DbD4 = &ksr.KernelDbD4;
PULONGLONG DbD5 = &ksr.KernelDbD5;
PULONGLONG DbD6 = &ksr.KernelDbD6;
PULONGLONG DbD7 = &ksr.KernelDbD7;
#else
BOOL bDbgRet;
CONTEXT Context;
PULONGLONG DbI0 = &Context.DbI0;
PULONGLONG DbI1 = &Context.DbI1;
PULONGLONG DbI2 = &Context.DbI2;
PULONGLONG DbI3 = &Context.DbI3;
PULONGLONG DbI4 = &Context.DbI4;
PULONGLONG DbI5 = &Context.DbI5;
PULONGLONG DbI6 = &Context.DbI6;
PULONGLONG DbI7 = &Context.DbI7;
PULONGLONG DbD0 = &Context.DbD0;
PULONGLONG DbD1 = &Context.DbD1;
PULONGLONG DbD2 = &Context.DbD2;
PULONGLONG DbD3 = &Context.DbD3;
PULONGLONG DbD4 = &Context.DbD4;
PULONGLONG DbD5 = &Context.DbD5;
PULONGLONG DbD6 = &Context.DbD6;
PULONGLONG DbD7 = &Context.DbD7;
#endif
// IA64 currently only supports 4 BR's
assert(Register >= 4);
#ifdef KERNEL
if (!GetExtendedContext(hthd, &ksr))
#else
Context.ContextFlags = CONTEXT_DEBUG;
if (!GetThreadContext(hthd->rwHand, &Context))
#endif
{
return FALSE;
}
assert(DataSize > 9);
Len = LenMask[ DataSize ];
// enable breakpoint at all privilege levels
switch( BpType ) {
case bptpDataR:
*(DbD0 + Register) = DataAddr;
*(DbD1 + Register) = RWE_READ | PLM_MASK | Len;
break;
case bptpDataW:
case bptpDataC:
*(DbD0 + Register) = DataAddr;
*(DbD1 + Register) = RWE_WRITE | PLM_MASK | Len;
break;
case bptpDataExec:
*(DbI0 + Register) = DataAddr;
*(DbI1 + Register) = RWE_EXEC | PLM_MASK | Len;
break;
default:
assert(!"Invalid BpType!!");
break;
}
#ifdef KERNEL
return SetExtendedContext(hthd, &ksr);
#else
bDbgRet = SetThreadContext(hthd->rwHand, &Context);
DPRINT(0, (_T("Setting Thread Context in debug register for thread %x:%i\n"),
hthd->tid,
bDbgRet
));
return bDbgRet;
#endif
}
VOID
ClearDebugRegister(
HTHDX hthd,
int Register
)
{
#ifdef KERNEL
KSPECIAL_REGISTERS ksr;
PULONGLONG DbI0 = &ksr.KernelDbI0;
PULONGLONG DbI1 = &ksr.KernelDbI1;
PULONGLONG DbI2 = &ksr.KernelDbI2;
PULONGLONG DbI3 = &ksr.KernelDbI3;
PULONGLONG DbI4 = &ksr.KernelDbI4;
PULONGLONG DbI5 = &ksr.KernelDbI5;
PULONGLONG DbI6 = &ksr.KernelDbI6;
PULONGLONG DbI7 = &ksr.KernelDbI7;
PULONGLONG DbD0 = &ksr.KernelDbD0;
PULONGLONG DbD1 = &ksr.KernelDbD1;
PULONGLONG DbD2 = &ksr.KernelDbD2;
PULONGLONG DbD3 = &ksr.KernelDbD3;
PULONGLONG DbD4 = &ksr.KernelDbD4;
PULONGLONG DbD5 = &ksr.KernelDbD5;
PULONGLONG DbD6 = &ksr.KernelDbD6;
PULONGLONG DbD7 = &ksr.KernelDbD7;
#else
CONTEXT Context;
PULONGLONG DbI0 = &Context.DbI0;
PULONGLONG DbI1 = &Context.DbI1;
PULONGLONG DbI2 = &Context.DbI2;
PULONGLONG DbI3 = &Context.DbI3;
PULONGLONG DbI4 = &Context.DbI4;
PULONGLONG DbI5 = &Context.DbI5;
PULONGLONG DbI6 = &Context.DbI6;
PULONGLONG DbI7 = &Context.DbI7;
PULONGLONG DbD0 = &Context.DbD0;
PULONGLONG DbD1 = &Context.DbD1;
PULONGLONG DbD2 = &Context.DbD2;
PULONGLONG DbD3 = &Context.DbD3;
PULONGLONG DbD4 = &Context.DbD4;
PULONGLONG DbD5 = &Context.DbD5;
PULONGLONG DbD6 = &Context.DbD6;
PULONGLONG DbD7 = &Context.DbD7;
#endif
// IA64 currently only supports 4
assert(Register == 4);
#ifdef KERNEL
if (GetExtendedContext(hthd, &ksr))
#else
Context.ContextFlags = CONTEXT_DEBUG;
if (GetThreadContext(hthd->rwHand, &Context))
#endif
{
switch( Register ) {
case 0:
*DbI0 = 0;
*DbI1 = 0;
*DbD0 = 0;
*DbD1 = 0;
break;
case 1:
*DbI2 = 0;
*DbI3 = 0;
*DbD2 = 0;
*DbD3 = 0;
break;
case 3:
*DbI4 = 0;
*DbI5 = 0;
*DbD4 = 0;
*DbD5 = 0;
break;
case 4:
*DbI6 = 0;
*DbI7 = 0;
*DbD6 = 0;
*DbD7 = 0;
break;
}
#ifdef KERNEL
SetExtendedContext(hthd, &ksr);
#else
DPRINT(0, (_T("Setting Thread Context in clear debug register for thread %x:%i\n"),
hthd->tid,
SetThreadContext(hthd->rwHand, &Context)
));
#endif
}
}
BOOL
DecodeSingleStepEvent(
HTHDX hthd,
DEBUG_EVENT64 *de,
PDWORD eventCode,
PDWORD_PTR subClass
)
/*++
Routine Description:
Arguments:
hthd - Supplies thread that has a single step exception pending
de - Supplies the DEBUG_EVENT structure for the exception
eventCode - Returns the remapped debug event id
subClass - Returns the remapped subClass id
Return Value:
TRUE if event was a real single step or was successfully mapped
to a breakpoint. FALSE if a register breakpoint occurred which was
not expected.
--*/
{
return TRUE;
// v-vadimp - below is the x86 code kept here for reference purpose, all it does is checking Dr6 to see if we had a single step exception,
// or a data BP has fired. I am not sure if this is still necessary for x86, and for Merced presumably EXCEPTION_SINGLE_STEP subclass
// uniquely identifies a sinlge step fault. We'll see
#if 0
// most register walk routines are implemented in non-portable x86 codes.
// i.e., heavy dependence on dr6. DO NOT TURN ON unless all references to
// dr6 are removed.
DWORD dr6;
PBREAKPOINT bp;
#ifdef KERNEL
KSPECIAL_REGISTERS ksr;
GetExtendedContext( hthd, &ksr);
dr6 = ksr.KernelDr6;
#else
CONTEXT Context;
Context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
DbgGetThreadContext( hthd, &Context);
dr6 = Context.Dr6;
#endif
// if it was a single step, look no further:
if ((dr6 & 0x4000) != 0) {
return TRUE;
}
// Search for a matching walk...
bp = GetWalkBPFromBits(hthd, (dr6 & 0xf));
if (bp) {
de->dwDebugEventCode = *eventCode = BREAKPOINT_DEBUG_EVENT;
de->u.Exception.ExceptionRecord.ExceptionCode = *subClass = (DWORD)bp;
return TRUE;
} else {
return FALSE;
}
return FALSE;
#endif
}
// v-vadimp for IA64
#ifndef KERNEL
UOFFSET
GetSPFromNLGDest(
HTHDX hthd,
LPNLG_DESTINATION pNlgDest
)
{
UOFFSET dwRet;
switch (pNlgDest->dwCode) {
case NLG_CATCH_ENTER: // Catch handler
case NLG_EXCEPT_ENTER: // Exception handler
case NLG_FILTER_ENTER: // Exception filter
case NLG_CATCH_LEAVE: // Return from Catch
case NLG_FINALLY_ENTER: // Termination handlers
case NLG_DESTRUCTOR_ENTER: // -GX handler
case NLG_LONGJMPEX: // Exception safe longjmp
dwRet = pNlgDest->uoffFramePointer;
break;
case NLG_LONGJMP:
dwRet = pNlgDest->uoffFramePointer+1;
break;
default:
dwRet = STACK_POINTER(hthd)+1; // emulate Virtual FP?
break;
}
return dwRet;
}
void* InfoExceptionDuringStep(
HTHDX hthd
)
{
Unreferenced(hthd);
// Information that needs to be propagated from the step location
// to the action handler when an exception occurs is passed in the
// void * returned by this function. In case of IA64 no information
// needs to be passed currently.
// v-vadimp: may need code here
return NULL;
}
BOOL
GetWndProcMessage(
HTHDX hthd,
UINT* pmsg
)
/*++
Routine Description:
This function is used to get the current Windows message (WM_CREATE, etc)
when execution has been stopped at a wndproc.
Return Value:
False on failure; True otherwise.
--*/
{
// v-vadimp - note: windbg uses a dufferent method of retrieveing a window message, so this is untested
ADDR addr;
ULONGLONG ulStackedRegs[2];
ULONG cb;
// read the back storage
AddrInit(&addr, 0, 0, hthd->context.RsBSP, hthd->fAddrIsFlat, hthd->fAddrOff32, 0, hthd->fAddrIsReal);
if (AddrReadMemory(hthd->hprc,hthd,&addr,(LPVOID)&ulStackedRegs,2,&cb) == xosdNone)
{
*pmsg = (UINT)ulStackedRegs[1]; // window messages come in R33 - second stacked register
return TRUE;
}
else
{
return FALSE;
}
}
DWORDLONG
GetFunctionResult(
PCALLSTRUCT pcs
)
{
return pcs->context.IntV0;
}
VOID
vCallFunctionHelper(
HTHDX hthd,
DWORDLONG lpFunction,
int cArgs,
va_list vargs
)
{
ULONG NewBspStore;
ULONGLONG ArgCopy[96];
ULONG ShiftCount;
BOOLEAN RnatSaved = FALSE;
DWORD ArgCount = 0;
int i;
assert(!"v-vadimp:vCallFunctionHelper not tested");
// set up the args to IA64 software convention defines the
// parameter passing via backing store(r32-r39). Prepare argument copy
// with current thread handle and RNAT if its backing store address [10:3]
// are all 1.
NewBspStore = (ULONG)hthd->context.RsBSPSTORE;
assert(cArgs < 96);
for (i = 0; i < min(cArgs,96); i++) { //v-vadimp - spill the arguments
ArgCopy[ArgCount++] = va_arg(vargs, DWORD); // dump the argument itself
NewBspStore += sizeof(ULONGLONG); // increment the backstore pointer
ShiftCount = (NewBspStore & 0x1F8) >> 3; // calculate the position for the argument's NAT bit in the RNAT (0x1f8 COMES FROM 63*8 - 63 arguments, then the RNAT)
hthd->context.RsRNAT &= ~(0x1 << ShiftCount); // put 1 there (we have no exception)
if ((NewBspStore & 0x1F8) == 0x1F8) // if it's time to spill the RNATm do it
{
ArgCopy[ArgCount++] = hthd->context.RsRNAT;
NewBspStore += sizeof(ULONGLONG);
}
}
// Copy the argument onto the backing store
AddrWriteMemory(hthd->hprc,
hthd,
(LPADDR)hthd->context.RsBSPSTORE,
ArgCopy,
ArgCount * sizeof(ULONGLONG),
&i);
// zero out loadrs, adjust RseStack
hthd->context.RsRSC = (RSC_MODE_LY<<RSC_MODE)
| (RSC_BE_LITTLE<<RSC_BE)
| (0x3<<RSC_PL);
// Setup argument numbers
hthd->context.StIFS = (ULONGLONG)ArgCount; // # of arguments/size of frame(sof)
hthd->context.RsBSP = hthd->context.RsBSPSTORE = NewBspStore;
// Set the address of the target code into IIP and IPSR.ri; save the current IIP in RP.
// No change to Sp and Ap.
hthd->context.BrRp = PC(hthd);
hthd->context.StIIP = lpFunction;
hthd->context.StIPSR &= ~((ULONGLONG)0x3 << PSR_RI);
hthd->context.StIPSR |= ((hthd->context.StIIP & 0xf) >> 2) << PSR_RI;
hthd->context.StIIP &= 0xf;
hthd->fContextDirty = TRUE;
}
#endif
ULONGLONG
GetRegValue(
PCONTEXT regs,
int cvindex
)
{
switch (cvindex)
{
case CV_IA64_IntT0:
return regs->IntT0;
break;
case CV_IA64_IntT1:
return regs->IntT1;
break;
case CV_IA64_IntS0:
return regs->IntS0;
break;
case CV_IA64_IntS1:
return regs->IntS1;
break;
case CV_IA64_IntS2:
return regs->IntS2;
break;
case CV_IA64_IntS3:
return regs->IntS3;
break;
case CV_IA64_IntV0:
return regs->IntV0;
break;
case CV_IA64_IntT2:
return regs->IntT2;
break;
case CV_IA64_IntT3:
return regs->IntT3;
break;
case CV_IA64_IntSp:
return regs->IntSp;
break;
case CV_IA64_IntTeb:
return regs->IntTeb;
break;
case CV_IA64_IntT5:
return regs->IntT5;
break;
case CV_IA64_IntT6:
return regs->IntT6;
break;
case CV_IA64_IntT7:
return regs->IntT7;
break;
case CV_IA64_IntT8:
return regs->IntT8;
break;
case CV_IA64_IntT9:
return regs->IntT9;
break;
case CV_IA64_IntT10:
return regs->IntT10;
break;
case CV_IA64_IntT11:
return regs->IntT11;
break;
case CV_IA64_IntT12:
return regs->IntT12;
break;
case CV_IA64_IntT13:
return regs->IntT13;
break;
case CV_IA64_IntT14:
return regs->IntT14;
break;
case CV_IA64_IntT15:
return regs->IntT15;
break;
case CV_IA64_IntT16:
return regs->IntT16;
break;
case CV_IA64_IntT17:
return regs->IntT17;
break;
case CV_IA64_IntT18:
return regs->IntT18;
break;
case CV_IA64_IntT19:
return regs->IntT19;
break;
case CV_IA64_IntT20:
return regs->IntT20;
break;
case CV_IA64_IntT21:
return regs->IntT21;
break;
case CV_IA64_IntT22:
return regs->IntT22;
break;
case CV_IA64_IntNats:
return regs->IntNats;
break;
case CV_IA64_Preds:
return regs->Preds;
break;
default:
assert(!"GetRegValue called with unrecognized index");
return (ULONGLONG)0 - 1;
}
}