summaryrefslogtreecommitdiff
path: root/src/debug/inc/i386/primitives.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/debug/inc/i386/primitives.h')
-rw-r--r--src/debug/inc/i386/primitives.h223
1 files changed, 223 insertions, 0 deletions
diff --git a/src/debug/inc/i386/primitives.h b/src/debug/inc/i386/primitives.h
new file mode 100644
index 0000000000..abad642bbd
--- /dev/null
+++ b/src/debug/inc/i386/primitives.h
@@ -0,0 +1,223 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//*****************************************************************************
+// File: primitives.h
+//
+
+//
+// Platform-specific debugger primitives
+//
+//*****************************************************************************
+
+#ifndef PRIMITIVES_H_
+#define PRIMITIVES_H_
+
+
+typedef const BYTE CORDB_ADDRESS_TYPE;
+typedef DPTR(CORDB_ADDRESS_TYPE) PTR_CORDB_ADDRESS_TYPE;
+
+//This is an abstraction to keep x86/ia64 patch data separate
+#define PRD_TYPE DWORD_PTR
+
+#define MAX_INSTRUCTION_LENGTH 16
+
+// Given a return address retrieved during stackwalk,
+// this is the offset by which it should be decremented to lend somewhere in a call instruction.
+#define STACKWALK_CONTROLPC_ADJUST_OFFSET 1
+
+#define CORDbg_BREAK_INSTRUCTION_SIZE 1
+#define CORDbg_BREAK_INSTRUCTION (BYTE)0xCC
+
+inline CORDB_ADDRESS GetPatchEndAddr(CORDB_ADDRESS patchAddr)
+{
+ LIMITED_METHOD_DAC_CONTRACT;
+ return patchAddr + CORDbg_BREAK_INSTRUCTION_SIZE;
+}
+
+
+#define InitializePRDToBreakInst(_pPRD) *(_pPRD) = CORDbg_BREAK_INSTRUCTION
+#define PRDIsBreakInst(_pPRD) (*(_pPRD) == CORDbg_BREAK_INSTRUCTION)
+
+#define CORDbgGetInstructionEx(_buffer, _requestedAddr, _patchAddr, _dummy1, _dummy2) \
+ CORDbgGetInstruction((CORDB_ADDRESS_TYPE *)((_buffer) + ((_patchAddr) - (_requestedAddr))));
+
+#define CORDbgSetInstructionEx(_buffer, _requestedAddr, _patchAddr, _opcode, _dummy2) \
+ CORDbgSetInstruction((CORDB_ADDRESS_TYPE *)((_buffer) + ((_patchAddr) - (_requestedAddr))), (_opcode));
+
+#define CORDbgInsertBreakpointEx(_buffer, _requestedAddr, _patchAddr, _dummy1, _dummy2) \
+ CORDbgInsertBreakpoint((CORDB_ADDRESS_TYPE *)((_buffer) + ((_patchAddr) - (_requestedAddr))));
+
+
+SELECTANY const CorDebugRegister g_JITToCorDbgReg[] =
+{
+ REGISTER_X86_EAX,
+ REGISTER_X86_ECX,
+ REGISTER_X86_EDX,
+ REGISTER_X86_EBX,
+ REGISTER_X86_ESP,
+ REGISTER_X86_EBP,
+ REGISTER_X86_ESI,
+ REGISTER_X86_EDI
+};
+
+//
+// Mapping from ICorDebugInfo register numbers to CorDebugRegister
+// numbers. Note: this must match the order in corinfo.h.
+//
+inline CorDebugRegister ConvertRegNumToCorDebugRegister(ICorDebugInfo::RegNum reg)
+{
+ return g_JITToCorDbgReg[reg];
+}
+
+
+//
+// inline function to access/modify the CONTEXT
+//
+inline LPVOID CORDbgGetIP(DT_CONTEXT *context) {
+ LIMITED_METHOD_CONTRACT;
+
+ return (LPVOID)(size_t)(context->Eip);
+}
+
+inline void CORDbgSetIP(DT_CONTEXT *context, LPVOID eip) {
+ LIMITED_METHOD_CONTRACT;
+
+ context->Eip = (UINT32)(size_t)eip;
+}
+
+inline LPVOID CORDbgGetSP(const DT_CONTEXT * context) {
+ LIMITED_METHOD_CONTRACT;
+
+ return (LPVOID)(size_t)(context->Esp);
+}
+
+inline void CORDbgSetSP(DT_CONTEXT *context, LPVOID esp) {
+ LIMITED_METHOD_CONTRACT;
+
+ context->Esp = (UINT32)(size_t)esp;
+}
+
+inline void CORDbgSetFP(DT_CONTEXT *context, LPVOID ebp) {
+ LIMITED_METHOD_CONTRACT;
+
+ context->Ebp = (UINT32)(size_t)ebp;
+}
+inline LPVOID CORDbgGetFP(DT_CONTEXT* context)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ return (LPVOID)(UINT_PTR)context->Ebp;
+}
+
+// compare the EIP, ESP, and EBP
+inline BOOL CompareControlRegisters(const DT_CONTEXT * pCtx1, const DT_CONTEXT * pCtx2)
+{
+ LIMITED_METHOD_DAC_CONTRACT;
+
+ if ((pCtx1->Eip == pCtx2->Eip) &&
+ (pCtx1->Esp == pCtx2->Esp) &&
+ (pCtx1->Ebp == pCtx2->Ebp))
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/* ========================================================================= */
+//
+// Routines used by debugger support functions such as codepatch.cpp or
+// exception handling code.
+//
+// GetInstruction, InsertBreakpoint, and SetInstruction all operate on
+// a _single_ byte of memory. This is really important. If you only
+// save one byte from the instruction stream before placing a breakpoint,
+// you need to make sure to only replace one byte later on.
+//
+
+
+inline PRD_TYPE CORDbgGetInstruction(UNALIGNED CORDB_ADDRESS_TYPE* address)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ return *address; // retrieving only one byte is important
+
+}
+
+inline void CORDbgInsertBreakpoint(UNALIGNED CORDB_ADDRESS_TYPE *address)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ *((unsigned char*)address) = 0xCC; // int 3 (single byte patch)
+ FlushInstructionCache(GetCurrentProcess(), address, 1);
+}
+
+inline void CORDbgSetInstruction(CORDB_ADDRESS_TYPE* address,
+ DWORD instruction)
+{
+ // In a DAC build, this function assumes the input is an host address.
+ LIMITED_METHOD_DAC_CONTRACT;
+
+ *((unsigned char*)address)
+ = (unsigned char) instruction; // setting one byte is important
+ FlushInstructionCache(GetCurrentProcess(), address, 1);
+}
+
+// After a breakpoint exception, the CPU points to _after_ the break instruction.
+// Adjust the IP so that it points at the break instruction. This lets us patch that
+// opcode and re-excute what was underneath the bp.
+inline void CORDbgAdjustPCForBreakInstruction(DT_CONTEXT* pContext)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ pContext->Eip -= 1;
+}
+
+inline bool AddressIsBreakpoint(CORDB_ADDRESS_TYPE* address)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ return *address == CORDbg_BREAK_INSTRUCTION;
+}
+
+// Set the hardware trace flag.
+inline void SetSSFlag(DT_CONTEXT *context)
+{
+ _ASSERTE(context != NULL);
+ context->EFlags |= 0x100;
+}
+
+// Unset the hardware trace flag.
+inline void UnsetSSFlag(DT_CONTEXT *context)
+{
+ SUPPORTS_DAC;
+ _ASSERTE(context != NULL);
+ context->EFlags &= ~0x100;
+}
+
+// return true if the hardware trace flag applied.
+inline bool IsSSFlagEnabled(DT_CONTEXT * context)
+{
+ _ASSERTE(context != NULL);
+ return (context->EFlags & 0x100) != 0;
+}
+
+
+
+inline bool PRDIsEqual(PRD_TYPE p1, PRD_TYPE p2){
+ return p1 == p2;
+}
+
+// On x86 opcode 0 is an 8-bit version of ADD. Do we really want to use 0 to mean empty? (see issue 366221).
+inline void InitializePRD(PRD_TYPE *p1) {
+ *p1 = 0;
+}
+inline bool PRDIsEmpty(PRD_TYPE p1) {
+ LIMITED_METHOD_CONTRACT;
+
+ return p1 == 0;
+}
+
+
+#endif // PRIMITIVES_H_