Skip to content

Commit

Permalink
Apple silicon debugger (#47834)
Browse files Browse the repository at this point in the history
* Use PAL_JITWriteEnable in debug/ee/controller.cpp

* Fix breakpoint exception handling on macos

* Fix Arm64SingleStepper for osx W^X

* Fix DebuggerHeapExecutableMemoryPage for W^X

* Fix DebuggerEval::DebuggerEval() during W^X
  • Loading branch information
sdmaclea authored Feb 4, 2021
1 parent 6c56444 commit f818e29
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 2 deletions.
12 changes: 12 additions & 0 deletions src/coreclr/debug/ee/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1364,6 +1364,9 @@ bool DebuggerController::ApplyPatch(DebuggerControllerPatch *patch)

LPVOID baseAddress = (LPVOID)(patch->address);

#if defined(HOST_OSX) && defined(HOST_ARM64)
auto jitWriteEnableHolder = PAL_JITWriteEnable(true);
#else // defined(HOST_OSX) && defined(HOST_ARM64)
DWORD oldProt;

if (!VirtualProtect(baseAddress,
Expand All @@ -1373,19 +1376,22 @@ bool DebuggerController::ApplyPatch(DebuggerControllerPatch *patch)
_ASSERTE(!"VirtualProtect of code page failed");
return false;
}
#endif // defined(HOST_OSX) && defined(HOST_ARM64)

patch->opcode = CORDbgGetInstruction(patch->address);

CORDbgInsertBreakpoint((CORDB_ADDRESS_TYPE *)patch->address);
LOG((LF_CORDB, LL_EVERYTHING, "Breakpoint was inserted at %p for opcode %x\n", patch->address, patch->opcode));

#if !defined(HOST_OSX) || !defined(HOST_ARM64)
if (!VirtualProtect(baseAddress,
CORDbg_BREAK_INSTRUCTION_SIZE,
oldProt, &oldProt))
{
_ASSERTE(!"VirtualProtect of code page failed");
return false;
}
#endif // !defined(HOST_OSX) || !defined(HOST_ARM64)
}
// TODO: : determine if this is needed for AMD64
#if defined(TARGET_X86) //REVISIT_TODO what is this?!
Expand Down Expand Up @@ -1454,6 +1460,9 @@ bool DebuggerController::UnapplyPatch(DebuggerControllerPatch *patch)

LPVOID baseAddress = (LPVOID)(patch->address);

#if defined(HOST_OSX) && defined(HOST_ARM64)
auto jitWriteEnableHolder = PAL_JITWriteEnable(true);
#else // defined(HOST_OSX) && defined(HOST_ARM64)
DWORD oldProt;

if (!VirtualProtect(baseAddress,
Expand All @@ -1468,6 +1477,7 @@ bool DebuggerController::UnapplyPatch(DebuggerControllerPatch *patch)
InitializePRD(&(patch->opcode));
return false;
}
#endif // defined(HOST_OSX) && defined(HOST_ARM64)

CORDbgSetInstruction((CORDB_ADDRESS_TYPE *)patch->address, patch->opcode);

Expand All @@ -1476,13 +1486,15 @@ bool DebuggerController::UnapplyPatch(DebuggerControllerPatch *patch)
//header file comment)
InitializePRD(&(patch->opcode));

#if !defined(HOST_OSX) || !defined(HOST_ARM64)
if (!VirtualProtect(baseAddress,
CORDbg_BREAK_INSTRUCTION_SIZE,
oldProt, &oldProt))
{
_ASSERTE(!"VirtualProtect of code page failed");
return false;
}
#endif // !defined(HOST_OSX) || !defined(HOST_ARM64)
}
else
{
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/debug/ee/debugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1381,6 +1381,10 @@ DebuggerEval::DebuggerEval(CONTEXT * pContext, DebuggerIPCE_FuncEvalInfo * pEval
{
WRAPPER_NO_CONTRACT;

#if defined(HOST_OSX) && defined(HOST_ARM64)
auto jitWriteEnableHolder = PAL_JITWriteEnable(true);
#endif // defined(HOST_OSX) && defined(HOST_ARM64)

// Allocate the breakpoint instruction info in executable memory.
m_bpInfoSegment = new (interopsafeEXEC, nothrow) DebuggerEvalBreakpointInfoSegment(this);

Expand Down
12 changes: 12 additions & 0 deletions src/coreclr/debug/ee/debugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -1114,6 +1114,10 @@ struct DECLSPEC_ALIGN(4096) DebuggerHeapExecutableMemoryPage

inline void SetNextPage(DebuggerHeapExecutableMemoryPage* nextPage)
{
#if defined(HOST_OSX) && defined(HOST_ARM64)
auto jitWriteEnableHolder = PAL_JITWriteEnable(true);
#endif // defined(HOST_OSX) && defined(HOST_ARM64)

chunks[0].bookkeeping.nextPage = nextPage;
}

Expand All @@ -1124,6 +1128,10 @@ struct DECLSPEC_ALIGN(4096) DebuggerHeapExecutableMemoryPage

inline void SetPageOccupancy(uint64_t newOccupancy)
{
#if defined(HOST_OSX) && defined(HOST_ARM64)
auto jitWriteEnableHolder = PAL_JITWriteEnable(true);
#endif // defined(HOST_OSX) && defined(HOST_ARM64)

// Can't unset first bit of occupancy!
ASSERT((newOccupancy & 0x8000000000000000) != 0);

Expand All @@ -1137,6 +1145,10 @@ struct DECLSPEC_ALIGN(4096) DebuggerHeapExecutableMemoryPage

DebuggerHeapExecutableMemoryPage()
{
#if defined(HOST_OSX) && defined(HOST_ARM64)
auto jitWriteEnableHolder = PAL_JITWriteEnable(true);
#endif // defined(HOST_OSX) && defined(HOST_ARM64)

SetPageOccupancy(0x8000000000000000); // only the first bit is set.
for (uint8_t i = 1; i < sizeof(chunks)/sizeof(chunks[0]); i++)
{
Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/vm/arm64/arm64singlestepper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,9 @@ void Arm64SingleStepper::Apply(T_CONTEXT *pCtx)
// control in the breakpoint fixup logic we can then reset the PC to its proper location.

unsigned int idxNextInstruction = 0;
#if defined(HOST_OSX) && defined(HOST_ARM64)
auto jitWriteEnableHolder = PAL_JITWriteEnable(true);
#endif // defined(HOST_OSX) && defined(HOST_ARM64)

if (TryEmulate(pCtx, opcode, false))
{
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/vm/exceptionhandling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5191,11 +5191,11 @@ BOOL HandleHardwareException(PAL_SEHException* ex)
Thread *pThread = GetThread();
if (pThread != NULL && g_pDebugInterface != NULL)
{
// On ARM and ARM64 Linux exception point to the break instruction.
#if (defined(TARGET_ARM) || defined(TARGET_ARM64))
// On ARM and ARM64 exception point to the break instruction.
// See https://static.docs.arm.com/ddi0487/db/DDI0487D_b_armv8_arm.pdf#page=6916&zoom=100,0,152
// at aarch64/exceptions/debug/AArch64.SoftwareBreakpoint
// However, the rest of the code expects that it points to an instruction after the break.
#if defined(__linux__) && (defined(TARGET_ARM) || defined(TARGET_ARM64))
if (ex->GetExceptionRecord()->ExceptionCode == STATUS_BREAKPOINT)
{
SetIP(ex->GetContextRecord(), GetIP(ex->GetContextRecord()) + CORDbg_BREAK_INSTRUCTION_SIZE);
Expand Down

0 comments on commit f818e29

Please sign in to comment.