/*++ */ #define _tsizeof(str) (sizeof(str)/sizeof(TCHAR)) #define DONT_NOTIFY ((METHOD*)0) #define NO_ACTION ((ACVECTOR)0) #define INVALID (-1L) #define NO_SUBCLASS ((DWORD_PTR)(-1L)) // This should really be defined by shapi or osdebug or something #define CMODULEDEMARCATOR _T('|') // WaitForDebugEvent() timeout, milliseconds #define WAITFORDEBUG_MS (50L) // Wait for loader breakpoint timeout sec * ticks/sec #define LDRBP_MAXTICKS (60L * 1000L/WAITFORDEBUG_MS) #define SetFile() extern DBF *lpdbf; #ifndef KERNEL #include extern BOOL CrashDump; #endif // Definitions for backward compatibility handling #if defined(TARGET_i386) #define CONTEXT_SIZE_PRE_NT5 FIELD_OFFSET(CONTEXT, ExtendedRegisters) #define CONTEXT_SIZE_NT5_VERSION 1732 #endif // Macros for common registers #if defined(TARGET_i386) #define IP_TYPE ULONG #define PC(x) SE32To64( ((x)->context.Eip) ) #define cPC(x) SE32To64( ((x)->Eip) ) #define STACK_POINTER(x) SE32To64( ((x)->context.Esp) ) #define FRAME_POINTER(x) SE32To64( ((x)->context.Ebp) ) #define Set_PC(x, y) (((x)->context.Eip) = (IP_TYPE) (y)) #define Set_cPC(x, y) (((x)->Eip) = (IP_TYPE) (y)) #define Set_STACK_POINTER(x, y) (((x)->context.Esp) = (IP_TYPE) (y)) #define Set_FRAME_POINTER(x, y) (((x)->context.Ebp) = (IP_TYPE) (y)) #define PcSegOfHthdx(x) ((SEGMENT) (x->context.SegCs)) #define SsSegOfHthdx(x) ((SEGMENT) (x->context.SegSs)) #define MPT_CURRENT mptix86 #elif defined (TARGET_ALPHA) || defined (TARGET_AXP64) #include "alphaops.h" #include "ctxptrs.h" #define IP_TYPE ULONGLONG #define PC(x) ((x)->context.Fir) #define cPC(x) ((x)->Fir) #define STACK_POINTER(x) ((x)->context.IntSp) #define FRAME_POINTER(x) ((x)->context.IntSp) #define Set_PC(x, y) (PC(x) = (IP_TYPE) (y)) #define Set_cPC(x, y) (cPC(x) = (IP_TYPE) (y)) #define Set_STACK_POINTER(x, y) (STACK_POINTER(x) = (IP_TYPE) (y)) #define Set_FRAME_POINTER(x, y) (FRAME_POINTER(x) = (IP_TYPE) (y)) #define PcSegOfHthdx(x) (0) #define SsSegOfHthdx(x) (0) #define MPT_CURRENT mptdaxp #elif defined (TARGET_IA64) #define IP_TYPE ULONGLONG #define PC(x) ((x)->context.StIIP | ((((x)->context.StIPSR >> PSR_RI) & 0x3) << 2)) #define cPC(x) ((x)->StIIP | ((((x)->StIPSR >> PSR_RI) & 0x3) << 2)) #define STACK_POINTER(x) ((x)->context.IntSp) #define FRAME_POINTER(x) ((x)->context.IntSp) #define Set_PC(x, y) (PC(x) = (IP_TYPE) (y)) #define Set_cPC(x, y) (cPC(x) = (IP_TYPE) (y)) #define Set_STACK_POINTER(x, y) (STACK_POINTER(x) = (IP_TYPE) (y)) #define Set_FRAME_POINTER(x, y) (FRAME_POINTER(x) = (IP_TYPE) (y)) #define PcSegOfHthdx(x) (0) #define SsSegOfHthdx(x) (0) #define TF_BIT_MASK ((ULONGLONG)0x1 << PSR_SS) #include #define MPT_CURRENT mptia64 #else #error "Undefined processor" #endif // Breakpoint stuff #if defined(TARGET_i386) typedef BYTE BP_UNIT; #define BP_OPCODE 0xCC #define DELAYED_BRANCH_SLOT_SIZE 0 #define MAX_INSTRUCTION_SIZE 20 #define HAS_DEBUG_REGS // #undef NO_TRACE_FLAG #define NUMBER_OF_DEBUG_REGISTERS 4 #define DEBUG_REG_DATA_SIZES { 1, 2, 4 } #define MAX_DEBUG_REG_DATA_SIZE 4 #define DEBUG_REG_LENGTH_MASKS { \ 0xffffffff, \ 0, \ 1, \ 0Xffffffff, \ 3 \ } #define TF_BIT_MASK 0x00000100 /* This is the right bit map for */ /* the 286, make sure its correct */ /* for the 386. */ #elif defined (TARGET_ALPHA) || defined (TARGET_AXP64) typedef DWORD BP_UNIT; #define BP_OPCODE 0x80L #define DELAYED_BRANCH_SLOT_SIZE 0 #define MAX_INSTRUCTION_SIZE 4 // #undef HAS_DEBUG_REGS #define NO_TRACE_FLAG #elif defined(TARGET_IA64) typedef ULONGLONG BP_UNIT; #define KDP_BREAKPOINT_ALIGN 0x3 #define BP_OPCODE (BREAK_INSTR | (ULONGLONG)(DEBUG_STOP_BREAKPOINT << 6)) #define KERNEL_BREAKIN_OPCODE (BREAK_INSTR | (ULONGLONG)(BREAKIN_BREAKPOINT << 6)) #define DELAYED_BRANCH_SLOT_SIZE 0 #define MAX_INSTRUCTION_SIZE 4 //v-vadimp ? // HAS_DEBUG_REGS must be defined to enable ExtendedContext support #define HAS_DEBUG_REGS //#define NO_TRACE_FLAG //v-vadimp - there's some code for setting the SS flag (PSR.ss), rem'-ing this out should enable it // IA64 has 8 DBR's and 8 IBR's that can emulate up to 4 full feature BR's #define NUMBER_OF_DEBUG_REGISTERS 4 #define DEBUG_REG_DATA_SIZES { 1, 2, 4, 8 } #define MAX_DEBUG_REG_DATA_SIZE 8 #define DEBUG_REG_LENGTH_MASKS { \ (DWORDLONG)0, \ (DWORDLONG)0xff, \ (DWORDLONG)0xffff, \ (DWORDLONG)0, \ (DWORDLONG)0xffffffff, \ (DWORDLONG)0, \ (DWORDLONG)0, \ (DWORDLONG)0, \ (DWORDLONG)0xffffffffffffff, \ } #else #error "Unknown target CPU" #endif // constant from windbgkd.h: #define MAX_KD_BPS BREAKPOINT_TABLE_SIZE // machine-dependent BP instruction size #define BP_SIZE sizeof(BP_UNIT) #ifdef HAS_DEBUG_REGS typedef struct DEBUGREG { DWORDLONG DataAddr; // Data Address DWORD DataSize; // Data Size BPTP BpType; // read, write, execute, etc BOOL InUse; // In use DWORD ReferenceCount; } DEBUGREG; typedef DEBUGREG *PDEBUGREG; extern DWORD DebugRegDataSizes[]; #endif #define EXADDR(pde) ((pde)->u.Exception.ExceptionRecord.ExceptionAddress) #define AddrFromHthdx(paddr, hthd) \ AddrInit(paddr, \ 0, \ PcSegOfHthdx(hthd), \ PC(hthd), \ (BOOL)hthd->fAddrIsFlat, \ (BOOL)hthd->fAddrOff32, \ FALSE, \ (BOOL)hthd->fAddrIsReal) typedef struct _CALLSTRUCT *PCALLSTRUCT; /* * These are "debug events" which are generated internally by the DM. * They are either remappings of certain exceptions or events which * do not correspond directly to a system-generated event or exception. */ enum { BREAKPOINT_DEBUG_EVENT=(RIP_EVENT+1), CHECK_BREAKPOINT_DEBUG_EVENT, SEGMENT_LOAD_DEBUG_EVENT, DESTROY_PROCESS_DEBUG_EVENT, DESTROY_THREAD_DEBUG_EVENT, ATTACH_DEADLOCK_DEBUG_EVENT, ATTACH_EXITED_DEBUG_EVENT, ENTRYPOINT_DEBUG_EVENT, LOAD_COMPLETE_DEBUG_EVENT, INPUT_DEBUG_STRING_EVENT, MESSAGE_DEBUG_EVENT, MESSAGE_SEND_DEBUG_EVENT, FUNC_EXIT_EVENT, OLE_DEBUG_EVENT, FIBER_DEBUG_EVENT, GENERIC_DEBUG_EVENT, BOGUS_WIN95_SINGLESTEP_EVENT, MAX_EVENT_CODE }; /* * This is the set of legal return values from IsCall. The function of * that routine is to analyze the instruction and determine if the * debugger can simply step over it. */ typedef enum { INSTR_TRACE_BIT, /* Use the trace bit stepping or emulation thereof */ INSTR_BREAKPOINT, /* This is a breakpoint instruction */ INSTR_CANNOT_TRACE, /* Can not trace this instruction */ INSTR_SOFT_INTERRUPT, /* This is an interrupt opcode */ INSTR_IS_CALL, /* This is a call instruction */ INSTR_CANNOT_STEP, /* In Win95 system code */ } INSTR_TYPES; typedef enum { THUNK_NONE = 0, THUNK_USER, THUNK_SYSTEM, } DM32ThunkTypes; typedef enum { RETURN_NONE = 0, RETURN_USER, RETURN_SYSTEM, } DM32ReturnTypes; typedef enum { ps_root = 0x0001, /* This is the root process, do not send a */ /* dbcDeleteProc when this is continued */ /* after a dbcProcTerm. */ ps_preStart = 0x0002, /* Process is expecting loader BP */ ps_preEntry = 0x0004, /* Process is expecting Entry BP */ ps_dead = 0x0010, /* This process is dead. */ ps_deadThread = 0x0020, /* This process owns dead threads */ ps_exited = 0x0040, /* We have notified the debugger that this */ /* process has exited. */ ps_destroyed = 0x0080, /* This process has been destroyed (deleted) */ ps_killed = 0x0100, /* This process is being killed */ ps_connect = 0x0200 } DMPSTATE; typedef void (*VECTOR)(); typedef struct _EXCEPTION_LIST { struct _EXCEPTION_LIST *next; EXCEPTION_DESCRIPTION excp; } EXCEPTION_LIST, *LPEXCEPTION_LIST; typedef struct _DLLLOAD_ITEM { BOOL fValidDll; // is this entry filled? DWORDLONG offBaseOfImage; // offset for base of Image DWORD cbImage; // size of image in bytes LPTSTR szDllName; // dll name PIMAGE_SECTION_HEADER Sections; // pointer to section headers DWORD NumberOfSections; // number of section headers #ifndef KERNEL BOOL fReal; BOOL fWow; OFFSET offTlsIndex; // The offset of the TLS index for the DLL // kentf The following comment is what I found in the sources which I // hacked the OLE stuff from. // ptr (in debuggee's memory space) to this // DLL's 1-byte boolean flag indicating whether // OLE RPC debugging is enabled. If this DLL // does not support OLE RPC, then this field // will be zero. // However, the code in dmole.c uses this as a pointer to a function which // takes two args, the first of which is the above described flag, and the // second of which is zero. LPVOID lpvOleRpc; BOOL fContainsOle; // does this DLL contain any OLE RPC segments? #else DWORD TimeStamp; // DWORD CheckSum; // WORD SegCs; // WORD SegDs; // PIMAGE_SECTION_HEADER sec; // #endif } DLLLOAD_ITEM, * PDLLLOAD_ITEM; #if defined(INTERNAL) typedef struct _DLL_DEFER_LIST { struct _DLL_DEFER_LIST * next; LOAD_DLL_DEBUG_INFO LoadDll; } DLL_DEFER_LIST, *PDLL_DEFER_LIST; #endif /* * CWPI is the number of Wndproc-invoking functions that exist: * SendMessage * SendMessageTimeout * SendMessageCallback * SendNotifyMessage * SendDlgItemMessage * DispatchMessage * CallWindowProc * times two (A version and W version) */ #define CWPI 14 // Misc forward declarations for OLE types typedef struct _OLERG *POLERG; typedef enum _ORPCKEYSTATE ORPCKEYSTATE; typedef struct _OLERET *POLERET; // When the user requests that we begin orpc debugging, we set the // OrpcDebugging variable in the process structure to be // ORPC_START_DEBUGGING. The next appropiate time -- during a step, for // example -- we check the value of the OrpcDebgging and if it's // ORPC_START_DEBUGGING, we call the trojan and set OrpcDebugging to to // ORPC_DEBUGGING. When we are ORPC_DEBUGGING and the user requests to // stop orpc debugging we set the OrpcDebugging value to ORPC_STOP_DEBUGGING // and at the next appropiate time, call the trojan to stop debugging. // We cannot call the trojan immediately because this fails on W95. typedef enum _ORPC_DEBUGGING_STATE { ORPC_NOT_DEBUGGING = 0, ORPC_START_DEBUGGING, ORPC_DEBUGGING, ORPC_STOP_DEBUGGING } ORPC_DEBUGGING_STATE; typedef struct _HFBRX { // linked list struct _HFBRX *next; LPVOID fbrstrt; LPVOID fbrcntx; } HFBRXSTRUCT,*HFBRX; typedef struct _HPRCX { // linked lists struct _HPRCX *next; struct _HTHDX *hthdChild; struct _HFBRX *FbrLst; PID pid; // OS provided process ID HANDLE rwHand; // OS provided Process handle BOOL CloseProcessHandle; // If we have a private // handle to this process, close it. // Otherwise, it belongs to smss. DWORD dwExitCode; // Process exit status HPID hpid; // binding to EM object DMPSTATE pstate; // DM state model BOOL f16bit; // CreateProcess EXE was 16 bit EXCEPTION_LIST *exceptionList; // list of exceptions to silently // continue unhandled int cLdrBPWait; // timeout counter while waiting for ldr BP HANDLE hExitEvent; // synchronization object for // process termination PDLLLOAD_ITEM rgDllList; // module list int cDllList; // item count for module list HANDLE hEventCreateThread; // Sync object for thread creation #ifndef KERNEL BOOL fUseFbrs; // Use fiber context or thread context PVOID pFbrCntx; // Pointer to a fiber context to display // NULL = use thread context DWORD_PTR dwKernel32Base; // lpBaseOfDll for kernel32. DWORD colerg; // number of OLE ranges in *rgolerg POLERG rgolerg; // array of OLERGs: sorted list of all // addresses in this process (including // its DLLs) which are special OLE // segments. May be // NULL if colerg is zero. ORPC_DEBUGGING_STATE OrpcDebugging; // orpc debugging state (see above) ORPCKEYSTATE orpcKeyState; DWORD_PTR rgwpoff[CWPI]; // addrs of Wndproc-invoking functions HLLI llnlg; // non-local goto UOFFSET PebAddress; // NT Process Environment Block #else BOOL fRomImage; // rom image BOOL fRelocatable; // relocatable code #endif #if defined(TARGET_i386) SEGMENT segCode; #endif #if defined(INTERNAL) // during process startup, dll name resolution may be // deferred until the loader BP. Once the process is // fully initialized, this deferral is no longer allowed. BOOL fNameRequired; PDLL_DEFER_LIST pDllDeferList; #endif } HPRCXSTRUCT, *HPRCX; #define hprcxNull ((HPRCX) 0) typedef enum { //ts_preStart =0x1000, /* Before the starting point of the thread */ /* from this state a registers and trace */ /* are dealt with specially */ ts_running = 1, /* Execution is proceeding on the thead */ ts_stopped = 2, /* An event has stopped execution */ ts_frozen = 0x010, /* Debugger froze thread. */ ts_dead = 0x020, /* Thread is dead. */ ts_destroyed =0x040, /* Thread is destroyed (deleted) */ ts_first = 0x100, /* Thread is at first chance exception */ ts_second = 0x200, /* Thread is at second chance exception */ ts_rip = 0x400, /* Thread is in RIP state */ ts_stepping = 0x800, /* */ ts_funceval = 0x40000000 /* Thread is being used for function call */ } TSTATEX; typedef struct _WTNODE { struct _WTNODE *caller; // caller's wtnode struct _WTNODE *callee; // current function called by this function DWORDLONG offset; // address of this function DWORDLONG sp; // SP for this frame int icnt; // number of instructions executed int scnt; // subordinate count int lex; // lexical level of this function LPSTR fname; // function name } WTNODE, *LPWTNODE; typedef struct _HTHDX { // list of all threads struct _HTHDX *nextGlobalThreadThisProbablyIsntTheOneYouWantedToUse; // list of threads in one process struct _HTHDX *nextSibling; HPRCX hprc; // OSDebug handle for process HTID htid; // OSDebug handle for thread TID tid; // OS thread ID HANDLE rwHand; // OS handle to thread ULONG64 lpStartAddress;// Thread start address CONTEXT context; // Thread context LPVOID atBP; TSTATEX tstate; BOOL fExceptionHandled; DWORDLONG stackRA; DWORDLONG stackBase; int cFuncEval; DWORD dwExitCode; DWORDLONG offTeb; BOOL fContextDirty;// has the context changed? BOOL fContextStale;// does the context need to be refreshed? BOOL fAddrIsFlat; // Is this address segmented? BOOL fAddrIsReal; // Is this address in real mode? BOOL fAddrOff32; // Is the offset of this addres 32 bits? BOOL fDontStepOff; // BOOL fWowEvent; // Was the last event WOW? ADDR addrIsCall; int iInstrIsCall; EXCEPTION_RECORD64 ExceptionRecord; BOOL fIsCallDone; BOOL fDisplayReturnValues; BOOL fStopOnNLG; BOOL fReturning; ADDR addrFrom; ADDR addrStack; WTNODE wthead; // root of the call tree for a wt command LPWTNODE wtcurr; // current wtnode DWORD wtmode; // wt command executing? LIST_ENTRY WalkList; // Walks associated with thread #ifdef HAS_DEBUG_REGS DEBUGREG DebugRegs[NUMBER_OF_DEBUG_REGISTERS]; #endif #ifndef KERNEL CRASH_THREAD CrashThread; // State info from crashdump PCALLSTRUCT pcs; // used for DM initiated function calling POLERET poleret; #endif // !KERNEL } HTHDXSTRUCT, *HTHDX; #define PassingExceptionForThisThread(h) \ (((h)->tstate & (ts_first | ts_second)) && !(h)->fExceptionHandled) typedef void (*ACVECTOR)(DEBUG_EVENT64*, HTHDX, DWORDLONG, DWORDLONG); typedef void (*DDVECTOR)(DEBUG_EVENT64*, HTHDX); #define hthdxNull ((HTHDX) NULL) #if defined(TARGET_IA64) // these are used in the flags field of a BREAKPOINT (IA64-specific) typedef enum { BREAKPOINT_IA64_MASK = 0x000f0000, BREAKPOINT_IA64_MODE = 0x00010000, // IA64 EM mode BREAKPOINT_IA64_MOVL = 0x00020000, // displaced instruction is MOVL } BPFLG; #endif typedef struct _BREAKPOINT { struct _BREAKPOINT *next; HPRCX hprc; // The process the BP belongs to HTHDX hthd; // The thread the BP belongs to BPTP bpType; // OSDebug BP type BPNS bpNotify; // OSDebug notify type ADDR addr; // The address of the Breakpoint BP_UNIT instr1; // The displaced instruction HANDLE hWalk; // walk list handle if it is a watchpoint BYTE instances; // The # of instances that exist HPID id; // Id supplied by the EM BOOL isStep; // Single step flag DWORD hBreakPoint; // kernel debugger breakpoint handle #if defined(TARGET_IA64) BPFLG flags; // IA64 mode mask #endif } BREAKPOINT; typedef BREAKPOINT *PBREAKPOINT; // these are magic values used in the hthd->atBP field. #define EMBEDDED_BP ((PBREAKPOINT)(-1)) // These are used in the id field of a BREAKPOINT. #define ENTRY_BP ((ULONG) -2) #define ASYNC_STOP_BP ((ULONG) -3) extern BREAKPOINT masterBP , *bpList; typedef struct _METHOD { ACVECTOR notifyFunction; /* The notification function to call */ DWORDLONG lparam; /* The parameter to pass to it */ void *lparam2; /* Extra pointer in case the method */ /* needs to be freed afterwards */ } METHOD; typedef METHOD *PMETHOD; typedef struct _EXPECTED_EVENT { struct _EXPECTED_EVENT *next; HPRCX hprc; HTHDX hthd; DWORD eventCode; DWORD_PTR subClass; METHOD* notifier; ACVECTOR action; BOOL fPersistent; DWORDLONG lparam; } EXPECTED_EVENT; typedef EXPECTED_EVENT *PEXPECTED_EVENT; typedef VOID (*STEPPER)(HTHDX,METHOD*,BOOL, BOOL); typedef DWORD (*CDVECTOR)(HPRCX,HTHDX,LPDBB); typedef struct { DMF dmf; CDVECTOR function; WORD type; } CMD_DESC; enum { BLOCKING, NON_BLOCKING, REPLY }; /* * Setup for a CreateProcess to occur */ typedef struct _SPAWN_STRUCT { BOOL fSpawn; HANDLE hEventApiDone; BOOL fReturn; // return from API DWORD dwError; char * szAppName; // args to API etc char * szArgs; char * pszCurrentDirectory; // directory to spawn process. DWORD fdwCreate; BOOL fInheritHandles; STARTUPINFO si; } SPAWN_STRUCT, *PSPAWN_STRUCT; /* * Setup for a DebugActiveProcess to occur */ typedef struct _DEBUG_ACTIVE_STRUCT { volatile BOOL fAttach; // tell DmPoll to act HANDLE hEventApiDone; // signal shell that API finished HANDLE hEventReady; // clear until finished loading BOOL fReturn; // API return value DWORD dwError; // GetLastError() value DWORD dwProcessId; // pid to debug HANDLE hEventGo; // signal after hitting ldr BP HANDLE hProcess; // handle for waiting on } DEBUG_ACTIVE_STRUCT, *PDEBUG_ACTIVE_STRUCT; // packet for starting WT (Watch Trace) typedef struct _WT_STRUCT { BOOL fWt; DWORD dwType; HTHDX hthd; } WT_STRUCT, *LPWT_STRUCT; // Packet for killing a process typedef struct _KILLSTRUCT { struct _KILLSTRUCT * next; HPRCX hprc; } KILLSTRUCT, *PKILLSTRUCT; // usermode reload notification packet typedef struct _RELOAD_STRUCT { BOOL Flag; HTHDX Hthd; PTCHAR String; } RELOAD_STRUCT, *PRELOAD_STRUCT; extern BOOL StartDmPollThread(void); extern BOOL StartCrashPollThread(void); extern BOOL SearchPathSet; extern char SearchPathString[]; // Single stepping stuff typedef struct _BRANCH_NODE { BOOL TargetKnown; // Know target address BOOL IsCall; // Is a call instruction ADDR Addr; // Branch instruction address ADDR Target; // Target address } BRANCH_NODE; #pragma warning( disable: 4200) typedef struct _BRANCH_LIST { ADDR AddrStart; // Start of range ADDR AddrEnd; // End of range DWORD Count; // Count of branch nodes BRANCH_NODE BranchNode[0]; // List of branch nodes } BRANCH_LIST; #pragma warning( default: 4200 ) DWORD BranchUnassemble( HTHDX hthd, void *Memory, DWORD Size, ADDR *Addr, BOOL *IsBranch, BOOL *TargetKnown, BOOL *IsCall, BOOL *IsTable, ADDR *Target ); // Structure for doing range stepping typedef struct _RANGESTRUCT { HTHDX hthd; // thread BOOL fStepOver; // Step over flag BOOL fStopOnBP; // Stop on BP flag METHOD *Method; // Method DWORD BpCount; // Count of temporary breakpoints ADDR *BpAddrs; // List of breakpoint addresses BREAKPOINT **BpList; // List of breakpoints BRANCH_LIST *BranchList; // branch list ADDR PrevAddr; // For single stepping BOOL fSingleStep; // For single stepping ADDR TmpAddr; // For single stepping BOOL fInCall; // For single stepping BREAKPOINT *TmpBp; // For single stepping } RANGESTRUCT; BOOL SmartRangeStep( HTHDX hthd, DWORDLONG offStart, DWORDLONG offEnd, BOOL fStopOnBP, BOOL fStepOver ); VOID MethodSmartRangeStep( DEBUG_EVENT64* pde, HTHDX hthd, DWORDLONG unused, DWORDLONG lparam ); typedef struct _RANGESTEP { HTHDX hthd; // The thread's structure SEGMENT segCur; // Segment to do range stepping in DWORDLONG addrStart; // starting address of range step DWORDLONG addrEnd; // ending address of range step SEGMENT SavedSeg; // Save locations for thunk stepping DWORDLONG SavedAddrStart; // " " DWORDLONG SavedAddrEnd; // " " STEPPER stepFunction; // The step function to call METHOD *method; // The method to handle this event BREAKPOINT *safetyBP; // Safety BP FUNCTION_INFORMATION CallSiteInfo; BOOL fIsCall; // just traced a call instruction? BOOL fIsRet; // just traced a ret? BOOL fInThunk; // stepping in a thunk? BOOL fSkipProlog; // step past prolog on function entry BOOL fGetReturnValue;// Getting a return value. } RANGESTEP; typedef RANGESTEP * PRANGESTEP; extern DEBUG_EVENT64 FuncExitEvent; extern HINSTANCE hInstance; // The DM DLLs hInstance VOID RangeStep( HTHDX hthd, DWORDLONG offStart, DWORDLONG offEnd, BOOL fStopOnBP, BOOL fstepOver ); VOID MethodRangeStep( DEBUG_EVENT64* pde, HTHDX hthd, DWORDLONG unused, DWORDLONG lparam ); VOID IsCall( HTHDX hthd, LPADDR lpAddr, LPINT lpFlag, BOOL fStepOver ); VOID DecrementIP( HTHDX hthd ); VOID IncrementIP( HTHDX hthd ); BOOL IsRet( HTHDX hthd, LPADDR addr ); VOID ContinueFromBP( HTHDX hthd, PBREAKPOINT pbp ); #if defined(TARGET_IA64) #define CB_THUNK_MAX 64 //4 bundles #else #define CB_THUNK_MAX 32 #endif BOOL IsThunk ( HTHDX hthd, DWORDLONG uoffset, LPINT lpfThunkType, DWORDLONG * lpuoffThunkDest, LPDWORD lpdwThunkSize ); BOOL FIsDirectJump( BYTE * rgbBuffer, DWORD cbBuff, HTHDX hthd, DWORDLONG uoffset, DWORDLONG * lpuoffThunkDest, LPDWORD lpdwThunkSize ); BOOL FIsIndirectJump( BYTE * rgbBuffer, DWORD cbBuff, HTHDX hthd, DWORDLONG uoffset, DWORDLONG * lpuoffThunkDest, LPDWORD lpdwThunkSize ); BOOL FIsVCallThunk( BYTE * rgbBuffer, DWORD cbBuff, HTHDX hthd, DWORDLONG uoffset, DWORDLONG * lpuoffThunkDest, LPDWORD lpdwThunkSize ); BOOL FIsVTDispAdjustorThunk( BYTE * rgbBuffer, DWORD cbBuff, HTHDX hthd, DWORDLONG uoffset, DWORDLONG * lpuoffThunkDest, LPDWORD lpdwThunkSize ); BOOL FIsAdjustorThunk( BYTE * rgbBuffer, DWORD cbBuff, HTHDX hthd, DWORDLONG uoffset, DWORDLONG * lpuoffThunkDest, LPDWORD lpdwThunkSize ); BOOL GetPMFDest( HTHDX hthd, DWORDLONG uThis, DWORDLONG uPMF, DWORDLONG *lpuOffDest ); BOOL SetupSingleStep( HTHDX hthd, BOOL DoContinue ); BOOL SetupReturnStep( HTHDX hthd, BOOL DoContinue, LPADDR lpaddr, LPADDR addrStack ); DWORD GetCanStep ( HPID hpid, HTID htid, LPADDR lpaddr, LPCANSTEP lpCanStep ); DWORDLONG GetEndOfRange ( HPRCX hprc, HTHDX hthd, DWORDLONG Addr ); VOID SingleStep( HTHDX hthd, METHOD* notify, BOOL stopOnBP, BOOL fInFuncEval ); VOID SingleStepEx( HTHDX hthd, METHOD* notify, BOOL stopOnBP, BOOL fInFuncEval, BOOL fDoContinue ); VOID ReturnStep( HTHDX hthd, METHOD* notify, BOOL stopOnBP, BOOL fInFuncEval, LPADDR addrRA, LPADDR addrStack ); VOID ReturnStepEx( HTHDX hthd, METHOD* notify, BOOL stopOnBP, BOOL fInFuncEval, LPADDR addrRA, LPADDR addrStack, BOOL fDoContinue ); VOID StepOver( HTHDX hthd, METHOD* notify, BOOL stopOnBP, BOOL fInFuncEval ); VOID MoveIPToException( HTHDX hthd, LPDEBUG_EVENT64 pde ); void MethodContinueSS( DEBUG_EVENT64 *pde, HTHDX hthd, DWORDLONG unused, DWORDLONG lparam ); BOOL DecodeSingleStepEvent( HTHDX hthd, DEBUG_EVENT64 *de, PDWORD eventCode, PDWORD_PTR subClass ); VOID WtRangeStep( HTHDX hthd ); VOID WtMethodRangeStep( DEBUG_EVENT64* pde, HTHDX hthd, DWORDLONG unused, DWORDLONG lparam ); BOOL GetWndProcMessage( HTHDX hthd, UINT* message ); // Function calling, for internal use typedef struct _CALLSTRUCT { PBREAKPOINT pbp; LPVOID atBP; CONTEXT context; ACVECTOR Action; LPARAM lparam; BOOL HasReturnValue; } CALLSTRUCT, *PCALLSTRUCT; BOOL WINAPIV CallFunction( HTHDX hthd, ACVECTOR Action, LPARAM lparam, BOOL HasReturnValue, DWORDLONG Function, int cArgs, ... ); // This function is machine-specific VOID vCallFunctionHelper( HTHDX hthd, DWORDLONG lpFunction, int cArgs, va_list vargs ); // This function is machine-specific DWORDLONG GetFunctionResult( PCALLSTRUCT pcs ); // Win95 support BOOL IsInSystemDll ( DWORDLONG uoffDest ); void SendDBCErrorStep(HPRCX hprc); /* */ #ifdef KERNEL extern void ProcessDebugEvent( DEBUG_EVENT64 *de, DBGKD_WAIT_STATE_CHANGE64 *sc ); extern VOID ProcessHandleExceptionCmd(HPRCX,HTHDX,LPDBB); extern VOID ProcessIgnoreExceptionCmd(HPRCX,HTHDX,LPDBB); extern BOOL ProcessFrameStackWalkNextCmd( HPRCX, HTHDX, PCONTEXT, LPVOID ); extern VOID ProcessGetExtendedContextCmd(HPRCX hprc,HTHDX hthd,LPDBB lpdbb); extern VOID ProcessSetExtendedContextCmd(HPRCX hprc,HTHDX hthd,LPDBB lpdbb); extern void DeleteAllBps( VOID ); extern VOID DmPollTerminate( VOID ); #else extern VOID ProcessBPAcceptedCmd( HPRCX hprcx, HTHDX hthdx, LPDBB lpdbb ); extern VOID ProcessGetDRegsCmd(HPRCX hprc, HTHDX hthd, LPDBB lpdbb); extern VOID ProcessSetDRegsCmd(HPRCX hprc, HTHDX hthd, LPDBB lpdbb); #endif extern void ProcessExceptionEvent(DEBUG_EVENT64*, HTHDX); extern void ProcessCreateThreadEvent(DEBUG_EVENT64*, HTHDX); extern void ProcessCreateProcessEvent(DEBUG_EVENT64*, HTHDX); extern void ProcessExitThreadEvent(DEBUG_EVENT64*, HTHDX); extern void ProcessExitProcessEvent(DEBUG_EVENT64*, HTHDX); extern void ProcessLoadDLLEvent(DEBUG_EVENT64*, HTHDX); extern void ProcessUnloadDLLEvent(DEBUG_EVENT64*, HTHDX); extern void ProcessOutputDebugStringEvent(DEBUG_EVENT64*, HTHDX); extern void ProcessBreakpointEvent(DEBUG_EVENT64*, HTHDX); extern void ProcessRipEvent(DEBUG_EVENT64*, HTHDX); extern void ProcessBogusSSEvent(DEBUG_EVENT64*, HTHDX); extern void ProcessSegmentLoadEvent(DEBUG_EVENT64 *, HTHDX); extern void ProcessEntryPointEvent(DEBUG_EVENT64 *pde, HTHDX hthdx); extern void NotifyEM(DEBUG_EVENT64*, HTHDX, DWORDLONG, DWORDLONG); extern void ConsumeThreadEventsAndNotifyEM(DEBUG_EVENT64*, HTHDX, DWORDLONG, DWORDLONG); extern void FreeHthdx(HTHDX hthd); extern XOSD FreeProcess( HPRCX hprc, BOOL fKillRoot); extern VOID ProcessCreateProcessCmd(HPRCX,HTHDX,LPDBB); extern DWORD ProcessProcStatCmd(HPRCX,HTHDX,LPDBB); extern DWORD ProcessThreadStatCmd(HPRCX,HTHDX,LPDBB); extern void ProcessSpawnOrphanCmd(HPRCX,HTHDX,LPDBB); extern void ProcessProgLoadCmd(HPRCX,HTHDX,LPDBB); extern DWORD ProcessUnloadCmd(HPRCX,HTHDX,LPDBB); extern VOID ProcessReadMemoryCmd(HPRCX,HTHDX,LPDBB); extern VOID ProcessWriteMemoryCmd(HPRCX,HTHDX,LPDBB); extern VOID ProcessGetContextCmd(HPRCX,HTHDX,LPDBB); extern VOID ProcessGetSectionsCmd(HPRCX,HTHDX,LPDBB); extern VOID ProcessSetContextCmd(HPRCX,HTHDX,LPDBB); extern VOID ProcessSingleStepCmd(HPRCX,HTHDX,LPDBB); extern VOID ProcessRangeStepCmd(HPRCX,HTHDX,LPDBB); extern VOID ProcessReturnStepCmd(HPRCX,HTHDX,LPDBB); extern DWORD ProcessExecuteCmd(HPRCX,HTHDX,LPDBB); extern VOID ProcessContinueCmd(HPRCX,HTHDX,LPDBB); extern DWORD ProcessFreezeThreadCmd(HPRCX,HTHDX,LPDBB); extern DWORD ProcessTerminateThreadCmd(HPRCX,HTHDX,LPDBB); extern DWORD ProcessTerminateProcessCmd(HPRCX,HTHDX,LPDBB); extern DWORD ProcessAsyncGoCmd(HPRCX,HTHDX,LPDBB); extern VOID ProcessGetFP(HPRCX,HTHDX,LPDBB); extern VOID ProcessIoctlCmd( HPRCX, HTHDX, LPDBB ); extern VOID ProcessSSVCCustomCmd( HPRCX, HTHDX, LPDBB ); extern VOID ProcessSelLimCmd( HPRCX, HTHDX, LPDBB ); extern VOID ClearContextPointers(PKNONVOLATILE_CONTEXT_POINTERS); extern VOID ProcessDebugActiveCmd(HPRCX, HTHDX, LPDBB); extern VOID ProcessAsyncStopCmd(HPRCX, HTHDX, LPDBB ); extern VOID ProcessAllProgFreeCmd( HPRCX hprcXX, HTHDX hthd, LPDBB lpdbb ); extern VOID ProcessSetPathCmd( HPRCX hprcXX, HTHDX hthd, LPDBB lpdbb ); extern VOID ProcessQueryTlsBaseCmd( HPRCX hprcx, HTHDX hthdx, LPDBB lpdbb ); extern VOID ProcessQuerySelectorCmd(HPRCX, HTHDX, LPDBB); extern VOID ProcessReloadModulesCmd(HPRCX hprcx, HTHDX hthdx, LPDBB lpdbb ); extern VOID ProcessVirtualQueryCmd(HPRCX hprcx, LPDBB lpdbb); extern VOID ProcessGetDmInfoCmd(HPRCX hprc, LPDBB lpdbb, DWORD cb); extern VOID ProcessRemoteQuit(VOID); extern ULONG ProcessGetTimeStamp (HPRCX, HTHDX, LPDBB); VOID ProcessGetFrameContextCmd( HPRCX hprc, HTHDX hthd, LPDBB lpdbb ); VOID ProcessGetExceptionState( HPRCX hprc, HTHDX hthd, LPDBB lpdbb ); VOID ProcessSetExceptionState( HPRCX hprc, HTHDX hthd, LPDBB lpdbb ); EXCEPTION_FILTER_DEFAULT ExceptionAction( HPRCX hprc, DWORD dwExceptionCode ); VOID RemoveExceptionList( HPRCX hprc ); EXCEPTION_LIST * InsertException( EXCEPTION_LIST ** ppeList, LPEXCEPTION_DESCRIPTION lpexc ); VOID ProcessBreakpointCmd( HPRCX hprcx, HTHDX hthdx, LPDBB lpdbb ); VOID ProcessSystemServiceCmd( HPRCX hprc, HTHDX hthd, LPDBB lpdbb ); VOID InitExceptionList( HPRCX hprc ); VOID CompleteTerminateProcessCmd( VOID ); // Public functions from walk.c VOID ExprBPCreateThread( HPRCX hprc, HTHDX hthd ); VOID ExprBPExitThread( HPRCX hprc, HTHDX hthd ); VOID ExprBPContinue( HPRCX hprc, HTHDX hthd ); VOID ExprBPRestoreDebugRegs( HTHDX hthd ); VOID ExprBPClearBPForStep( HTHDX hthd ); VOID ExprBPResetBP( HTHDX hthd, PBREAKPOINT bp ); VOID ExprBPInitialize( VOID ); PBREAKPOINT GetWalkBPFromBits( HTHDX hthd, DWORD bits ); BOOL IsWalkInGroup( HANDLE hWalk, PVOID pWalk ); HANDLE SetWalk( HPRCX hprc, HTHDX hthd, DWORDLONG Addr, DWORD Size, DWORD BpType ); BOOL RemoveWalk( HANDLE hWalk, BOOL Global ); BOOL CheckDataBP( HTHDX hthd, PBREAKPOINT Bp ); #ifdef HAS_DEBUG_REGS BOOL SetupDebugRegister( // implemented in mach.c HTHDX hthd, int Register, int DataSize, DWORDLONG DataAddr, DWORD BpType ); VOID ClearDebugRegister( HTHDX hthd, int Register ); VOID ClearAllDebugRegisters( HPRCX hprc ); #endif extern void SSActionReplaceByte( DEBUG_EVENT64 *de, HTHDX hthdx, DWORDLONG unused, DWORDLONG lparam ); extern void SSActionRemoveBP( DEBUG_EVENT64 *de, HTHDX hthd, DWORDLONG unused, DWORDLONG lparam ); extern void ActionDefineProcess( DEBUG_EVENT64 *de, HTHDX hthd, DWORDLONG unused, DWORDLONG lparam ); extern void ActionAllDllsLoaded( DEBUG_EVENT64 *de, HTHDX hthd, DWORDLONG unused, DWORDLONG lparam ); extern void ActionDebugActiveReady( DEBUG_EVENT64 *pde, HTHDX hthd, DWORDLONG unused, DWORDLONG lparam ); extern void ActionDebugNewReady( DEBUG_EVENT64 *pde, HTHDX hthd, DWORDLONG unused, DWORDLONG lparam ); extern void ActionExceptionDuringStep( DEBUG_EVENT64* de, HTHDX hthd, DWORDLONG unused, DWORDLONG lparam ); extern void * InfoExceptionDuringStep( HTHDX hthd ); BOOL CDECL DMPrintShellMsg( PCHAR szFormat, ... ); // event.c PEXPECTED_EVENT RegisterExpectedEvent( HPRCX hprc, HTHDX hthd, DWORD eventcode, DWORD_PTR subclass, METHOD* method, ACVECTOR action, BOOL persistent, DWORDLONG lparam ); PEXPECTED_EVENT PeeIsEventExpected( HTHDX hthd, DWORD eventcode, DWORD_PTR subclass, BOOL bRemove ); VOID ConsumeAllThreadEvents( HTHDX hthd, BOOL ConsumePersistent ); VOID ConsumeAllProcessEvents( HPRCX hprc, BOOL ConsumePersistent ); VOID ConsumeSpecifiedEvent( PEXPECTED_EVENT ee ); XOSD Load( HPRCX hprc, LPCTSTR szAppName, LPCTSTR szArg, LPVOID pattrib, LPVOID tattrib, DWORD creationFlags, BOOL inheritHandles, CONST LPCTSTR* environment, LPCTSTR currentDirectory, STARTUPINFO FAR * pstartupInfo, LPPROCESS_INFORMATION lppi ); HPRCX InitProcess( HPID hpid ); #if defined (TARGET_ALPHA) || defined (TARGET_AXP64) || defined(TARGET_IA64) VOID RemoveFuncList( HPRCX hprc ); #endif VOID WINAPI DMFunc( DWORD cb, LPDBB lpdbb ); VOID ReConnectDebugger( DEBUG_EVENT64 *de, BOOL fNoDllLoad ); DWORDLONG GetNextOffset ( HTHDX, BOOL ); extern void SetupEntryBP(HTHDX hthd); void DestroyDllLoadItem(PDLLLOAD_ITEM pDll); VOID Reply( UINT length, void * lpbBuffer, HPID hpid ); // Use this specifically to send errors about process startup. VOID SendNTError( HPRCX hprc, DWORD dwErr, LPTSTR lszString ); // Used for other dbcError's. VOID SendDBCError( HPRCX hprc, DWORD dwErr, LPTSTR lszString ); /* */ // Why a negative number, becuase someone set a whole dunch of DPRINTS to 0. // So now we just continue the tradition. #define MIN_VERBOSITY_LEVEL (-3) #if DBG #define assert(exp) if (!(exp)) {lpdbf->lpfnLBAssert(#exp,__FILE__,__LINE__);} extern int nVerbose; extern BOOL FUseOutputDebugString; extern char rgchDebug[]; extern void DebugPrint(char *, ...); #define DPRINT(level, args) \ if (nVerbose >= level) { \ extern HPID hpidRoot; \ ( (FUseOutputDebugString || (HPID)INVALID == hpidRoot) ? (DebugPrint) : (DMPrintShellMsg)) args; \ } #define DEBUG_PRINT(str) DPRINT(5, (str)) #define DEBUG_PRINT_1(str, a1) DPRINT(5, (str, a1)) #define DEBUG_PRINT_2(str, a1, a2) DPRINT(5, (str, a1, a2)) #define DEBUG_PRINT_3(str, a1, a2, a3) DPRINT(5, (str, a1, a2, a3)) #define DEBUG_PRINT_4(str, a1, a2, a3, a4) DPRINT(5, (str, a1, a2, a3, a4)) #define DEBUG_PRINT_5(str, a1, a2, a3, a4, a5) DPRINT(5, (str, a1, a2, a3, a4, a5)) #define DEBUG_LEVEL_PRINT(level, str) DPRINT(level, (str)) #else #define assert(exp) #define DPRINT(level, args) #define DEBUG_PRINT(str) #define DEBUG_PRINT_1(str, a1) #define DEBUG_PRINT_2(str, a1, a2) #define DEBUG_PRINT_3(str, a1, a2, a3) #define DEBUG_PRINT_4(str, a1, a2, a3, a4) #define DEBUG_PRINT_5(str, a1, a2, a3, a4, a5) #define DEBUG_LEVEL_PRINT(level, str) #endif #define VERIFY(X) if (!(X)) assert(FALSE) extern DMTLFUNCTYPE DmTlFunc; /* ** Win95/Chicago related functions */ BOOL IsChicago(VOID); /* ** WOW functions */ BOOL TranslateAddress(HPRCX, HTHDX, LPADDR, BOOL); BOOL IsWOWPresent(VOID); /* ** Prototypes from util.c */ ULONG SetReadPointer( ULONG cbOffset, int iFrom ); VOID SetPointerToFile( HANDLE hFile ); VOID SetPointerToMemory( HPRCX hprcx, DWORDLONG qw ); BOOL DoRead( LPVOID lpv, DWORD cb ); BOOL AreAddrsEqual( HPRCX hprc, HTHDX hthd, LPADDR paddr1, LPADDR paddr2 ); HTHDX HTHDXFromPIDTID(PID, TID); HTHDX HTHDXFromHPIDHTID(HPID, HTID); HPRCX HPRCFromPID(PID); HPRCX HPRCFromHPID(HPID); HPRCX HPRCFromHPRC(HANDLE); BOOL WOWGetThreadContext(HTHDX hthdx, LPCONTEXT lpcxt); BOOL WOWSetThreadContext(HTHDX hthdx, LPCONTEXT lpcxt); BOOL CheckBpt( HTHDX hthd, PBREAKPOINT pbp ); LPTSTR MHStrdup( LPCTSTR s ); XOSD DMSendRequestReply ( DBC dbc, HPID hpid, HTID htid, DWORD cbInput, LPVOID lpInput, DWORD cbOutput, LPVOID lpOutput ); PVOID DMCopyLargeReply( DWORD size ); XOSD DMSendDebugPacket( DBC dbc, HPID hpid, HTID htid, DWORD cbInput, LPVOID lpInput ); UOFFSET FileOffFromVA( PDLLLOAD_ITEM pdi, HFILE hfile, UOFFSET uoffBasePE, const IMAGE_NT_HEADERS *pnthdr, UOFFSET va ); DWORD CbReadDllHdr( HFILE hfile, UOFFSET uoff, LPVOID lpvBuf, DWORD cb ); ULONGLONG GetRegValue( PCONTEXT regs, int cvindex ); VOID DmSetFocus ( HPRCX phprc ); BOOL FGetExport( PDLLLOAD_ITEM pdi, HFILE hfile, LPCTSTR szExport, LPVOID* plpvValue ); VOID GetTaskList( PTASK_LIST pTask, DWORD dwNumTasks, LPDWORD lpdwNumReturned ); BOOL AddrReadMemory( HPRCX hprc, HTHDX hthd, LPADDR paddr, LPVOID lpb, DWORD cb, LPDWORD pcbRead ); BOOL AddrWriteMemory( HPRCX hprc, HTHDX hthd, LPADDR paddr, LPVOID lpv, DWORD cb, LPDWORD pcbWritten ); int NumberOfThreadsInProcess( HPRCX hprc ); void SetHandledStateInStoppedThreads( HPRCX hprc, BOOL ContinueHandled ); HTHDX FindStoppedThread( HPRCX hprc ); // userapi.c / kdapi.c BOOL DbgReadMemory( HPRCX hprc, DWORDLONG lpOffset, LPVOID lpv, DWORD cb, LPDWORD pcbRead ); BOOL DbgWriteMemory( HPRCX hprc, DWORDLONG lpOffset, LPVOID lpb, DWORD cb, LPDWORD pcbWritten ); BOOL DbgGetThreadContext( HTHDX hthd, LPCONTEXT lpContext ); BOOL DbgSetThreadContext( IN HTHDX hthd, IN LPCONTEXT lpContext ); EXHDLR * GetExceptionCatchLocations( IN HTHDX, IN LPVOID ); VOID GetMachineType( LPPROCESSOR p ); BOOL DequeueAllEvents( BOOL fForce, BOOL fConsume ); VOID InitEventQueue( VOID ); void ContinueProcess( HPRCX hprc ); void ContinueThread( HTHDX hthd ); void ContinueThreadEx( HTHDX hthd, DWORD ContinueStatus, DWORD EventType, TSTATEX NewState ); BOOL LoadDll( DEBUG_EVENT64 * de, HTHDX hthd, LPWORD lpcbPacket, LPBYTE * lplpbPacket, BOOL fThreadIsStopped ); #ifndef KERNEL VOID UnloadAllModules( HPRCX hprc, HTHDX hthd, BOOL AlwaysNotify, BOOL ReallyDestroy ); VOID ReloadUsermodeModules( HTHDX hthd, PTCHAR String ); BOOL DMWaitForDebugEvent( LPDEBUG_EVENT64 de64, DWORD timeout ); BOOL MakeThreadSuspendItself( HTHDX hthd ); void ClearPendingDebugEvents( PID pid, TID tid ); #endif // KERNEL VOID AddQueue( DWORD dwType, DWORD dwProcessId, DWORD dwThreadId, DWORD64 dwData, DWORD dwLen ); #define QT_CONTINUE_DEBUG_EVENT 1 #define QT_RELOAD_MODULES 2 #define QT_TRACE_DEBUG_EVENT 3 #define QT_REBOOT 4 #define QT_RESYNC 5 #define QT_DEBUGSTRING 6 #define QT_CRASH 7 // any ssvc not recognized by ProcessSystemServiceCmd is // punted to this, which is provided separately by the user // and kernel versions. VOID LocalProcessSystemServiceCmd( HPRCX hprc, HTHDX hthd, LPDBB lpdbb ); // Non Local Goto support typedef HDEP HNLG; // Handle to NLG typedef struct _NLG_DESTINATION { UOFFSET uoffDestination; UOFFSET uoffFramePointer; DWORD dwSig; DWORD dwCode; } NLG_DESTINATION; typedef NLG_DESTINATION FAR * LPNLG_DESTINATION; #define NLG_LONGJMP 0x00000000 #define NLG_EXCEPT_ENTER 0x00000001 #define NLG_CATCH_LEAVE 0x00000002 #define NLG_LONGJMPEX 0x00000003 #define NLG_CATCH_ENTER 0x00000100 #define NLG_FINALLY_ENTER 0x00000101 #define NLG_FILTER_ENTER 0x00000102 #define NLG_DESTRUCTOR_ENTER 0x00000103 // Post V4 #define NLG_GLOBAL_CONSTRUCTOR_ENTER 0x104 #define NLG_GLOBAL_DESTRUCTOR_ENTER 0x105 #define NLG_DLL_ENTRY 0x106 #define NLG_DLL_EXIT 0x107 // Mac has no 2nd chance notification #define NLG_EXCEPT_LAST_CHANCE 0x108 #define NLG_SIG 0x19930520 typedef enum _NLG_LOCATION { NLG_DISPATCH, NLG_RETURN } NLG_LOCATION, FAR * LPNLG_LOCATION; #define hnlgNull ((HNLG)NULL) INT FAR PASCAL NLGComp ( LPNLG, LPVOID, LONG ); VOID ActionNLGDispatch( DEBUG_EVENT64* de, HTHDX hthd, DWORDLONG unused, DWORDLONG lparam ); VOID ActionNLGDestination ( DEBUG_EVENT64* de, HTHDX hthd, DWORDLONG unused, DWORDLONG lparam ); HNLG CheckNLG ( HPRCX, HTHDX, NLG_LOCATION, LPADDR ); BOOL SetupNLG ( HTHDX, LPADDR ); UOFFSET GetSPFromNLGDest(HTHDX, LPNLG_DESTINATION); void ProcessNonLocalGoto( HPRCX, HTHDX, LPDBB ); typedef enum _NFI { nfiHEMI, } NFI; // NonLocalGoto Find Information typedef NFI FAR * LPNFI; #ifndef KERNEL // OLE debugging support typedef enum _OLESEG OLESEG; typedef enum _ORPC ORPC; typedef VOID (*COMPLETION_FUNCTION) (HTHDX, LPVOID); OLESEG GetOleSegType(LPVOID); OLESEG OleSegFromAddr(HPRCX, UOFFSET); VOID EnsureOleRpcStatus(HTHDX, COMPLETION_FUNCTION, LPVOID Argument); BOOL FClientNotifyStep(HTHDX, DEBUG_EVENT64*); BOOL FServerNotifyStop(HTHDX, DEBUG_EVENT64*); ORPC OrpcFromPthd(HTHDX, DEBUG_EVENT64*); VOID PushOleRetAddr(HTHDX, UOFFSET, UOFFSET); VOID PopOleRetAddr(HTHDX); UOFFSET UoffOleRet(HTHDX); UOFFSET EspOleRet(HTHDX); VOID ProcessOleEvent(DEBUG_EVENT64*, HTHDX); BOOL CheckAndSetupForOrpcSection( HTHDX hthd ); UOFFSET GetReturnDestination( HTHDX hthd ); VOID ActionOrpcClientGetBufferSize ( DEBUG_EVENT64 * pde, HTHDX hthd, DWORDLONG unused, DWORDLONG lparam ); VOID ActionOrpcClientFillBuffer ( DEBUG_EVENT64 * pde, HTHDX hthd, DWORDLONG unused, DWORDLONG lparam ); VOID ActionOrpcClientNotify ( LPDEBUG_EVENT64 pde, HTHDX hthd, DWORDLONG unused, DWORDLONG lparam ); VOID ActionOrpcServerNotify( LPDEBUG_EVENT64 pde, HTHDX hthd, DWORDLONG unused, DWORDLONG lparam ); VOID ActionOrpcServerGetBufferSize( LPDEBUG_EVENT64 pde, HTHDX hthd, DWORDLONG unused, DWORDLONG lparam ); void ActionOrpcSkipToSource( LPDEBUG_EVENT64 pde, HTHDX hthd, DWORDLONG unused, DWORDLONG lparam ); // Fiber Support VOID ProcessFiberEvent(DEBUG_EVENT64*,HTHDX); VOID RemoveFiberList(HPRCX); typedef struct _DETOSAVE { LIST_ENTRY List; DEBUG_EVENT64 de; } DETOSAVE, * PDETOSAVE; PDETOSAVE GetMostRecentDebugEvent( PID pid, TID tid ); #endif // !KERNEL #ifdef KERNEL /* ** Kernel Debugger Specific Functions */ extern BOOL DmKdPtr64; extern BOOL DmKdApi64; BOOL DmKdConnectAndInitialize( LPSTR lpProgName ); BOOL WriteBreakPointEx( IN HTHDX hthd, IN ULONG BreakPointCount, IN OUT PDBGKD_WRITE_BREAKPOINT64 BreakPoints, IN ULONG ContinueStatus ); BOOL RestoreBreakPointEx( IN ULONG BreakPointCount, IN PDBGKD_RESTORE_BREAKPOINT BreakPointHandles ); VOID ContinueTargetSystem( DWORD ContinueStatus, PDBGKD_CONTROL_SET ControlSet ); VOID RestoreKernelBreakpoints( HTHDX hthd, DWORDLONG Offset ); BOOL ReadControlSpace( USHORT Processor, DWORDLONG TargetBaseAddress, PVOID UserInterfaceBuffer, ULONG TransferCount, PULONG ActualBytesRead ); NTSTATUS DmKdReadDebuggerDataBlock( ULONG64 Address, OUT PDBGKD_DEBUG_DATA_HEADER64 DataBlock, ULONG SizeToRead ); NTSTATUS DmKdReadDebuggerDataHeader( ULONG64 Address, OUT PDBGKD_DEBUG_DATA_HEADER64 DataHeader ); NTSTATUS DmKdReadListEntry( ULONG64 Address, PLIST_ENTRY64 List64 ); NTSTATUS DmKdReadPointer( ULONG64 Address, PULONG64 Pointer64 ); NTSTATUS DmKdReadLoaderEntry( ULONG64 Address, PLDR_DATA_TABLE_ENTRY64 b64 ); #if defined(HAS_DEBUG_REGS) BOOL GetExtendedContext(HTHDX hthd, PKSPECIAL_REGISTERS pksr); BOOL SetExtendedContext(HTHDX hthd, PKSPECIAL_REGISTERS pksr); #endif #define KERNEL_MODULE_NAME "nt" #define KERNEL_IMAGE_NAME "ntoskrnl.exe" #define KERNEL_IMAGE_NAME_MP "ntkrnlmp.exe" #define OSLOADER_IMAGE_NAME "osloader.exe" #define HAL_IMAGE_NAME "hal.dll" #define HAL_MODULE_NAME "HAL" extern CRITICAL_SECTION csApiInterlock; extern CRITICAL_SECTION csSynchronizeTargetInterlock; #ifdef DBG #define DEBUG_API_INTERLOCK 1 #endif #ifndef DEBUG_API_INTERLOCK #define TakeApiLock() EnterCriticalSection(&csApiInterlock) #define ReleaseApiLock() LeaveCriticalSection(&csApiInterlock) #define TryApiLock() TryEnterCriticalSection(&csApiInterlock) #else VOID TakeApiLockFunc( PCSTR pszFile, int nLine ); BOOL TryApiLockFunc( PCSTR pszFile, int nLine ); VOID ReleaseApiLockFunc( PCSTR pszFile, int nLine ); #define TakeApiLock() TakeApiLockFunc(__FILE__, __LINE__) #define TryApiLock() TryApiLockFunc(__FILE__, __LINE__) #define ReleaseApiLock() ReleaseApiLockFunc(__FILE__, __LINE__) #endif typedef struct MODULEALIAS { CHAR ModuleName[16]; CHAR Alias[16]; BOOL Special; } MODULEALIAS, *LPMODULEALIAS; #define MAX_MODULEALIAS 100 LPMODULEALIAS FindAliasByImageName( LPSTR lpImageName ); LPMODULEALIAS FindAddAliasByModule( LPSTR lpImageName, LPSTR lpModuleName ); typedef struct IMAGEINFO { DWORD CheckSum; DWORD TimeStamp; DWORD SizeOfImage; DWORDLONG BaseOfImage; DWORD NumberOfSections; PIMAGE_SECTION_HEADER Sections; } IMAGEINFO, *LPIMAGEINFO; void ParseDmParams( LPSTR p ); BOOL ReadImageInfo( LPSTR lpImageName, LPSTR lpFoundName, LPSTR lpPath, LPIMAGEINFO ii ); #endif // KERNEL