From: Mike McLaughlin Date: Tue, 8 Sep 2015 23:26:28 +0000 (-0700) Subject: Fix managed breakpoints on OSx. X-Git-Tag: submit/tizen/20210909.063632~11030^2~12164^2~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c6f7e539be90ffc94a9ff30e2ac2f3064c4d9a79;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Fix managed breakpoints on OSx. Changed the OSx exception initialization to enable breakpoints/stepping. Fix problem with faults and breakpoints in coreclr code not being forwarded to native debugger (if being debugged). Fix debugger shutdown where we release the transport too many times and assert in debug. When building the register context for an exception don't save/restore the debug registers because they cause an priviledged instruction fault. Fixed the PAL's TRACE formatting by merging the printfcpp.cpp formatting into silent_printf.cpp. "%p" wasn't being formatted correctly in a PAL TRACE statement. The executable heap zone wasn't being set because the process heap is used instead of creating a new heap. Commit migrated from https://github.com/dotnet/coreclr/commit/08f67f0acdb3935acc30b0a0f0ebee21513f2668 --- diff --git a/src/coreclr/src/debug/di/shimremotedatatarget.cpp b/src/coreclr/src/debug/di/shimremotedatatarget.cpp index 4983d74..fd34d33 100644 --- a/src/coreclr/src/debug/di/shimremotedatatarget.cpp +++ b/src/coreclr/src/debug/di/shimremotedatatarget.cpp @@ -130,6 +130,7 @@ void ShimRemoteDataTarget::Dispose() m_pProxy->ReleaseTransport(m_pTransport); } + m_pTransport = NULL; m_hr = CORDBG_E_OBJECT_NEUTERED; } diff --git a/src/coreclr/src/debug/ee/debugger.cpp b/src/coreclr/src/debug/ee/debugger.cpp index 270615b..eb649a5 100644 --- a/src/coreclr/src/debug/ee/debugger.cpp +++ b/src/coreclr/src/debug/ee/debugger.cpp @@ -2054,6 +2054,9 @@ HRESULT Debugger::Startup(void) } #endif +#ifdef FEATURE_PAL + PAL_InitializeDebug(); +#endif // FEATURE_PAL // Lazily initialize the interop-safe heap diff --git a/src/coreclr/src/pal/src/cruntime/silent_printf.cpp b/src/coreclr/src/pal/src/cruntime/silent_printf.cpp index 09de2a6..d01070c 100644 --- a/src/coreclr/src/pal/src/cruntime/silent_printf.cpp +++ b/src/coreclr/src/pal/src/cruntime/silent_printf.cpp @@ -80,6 +80,16 @@ INT Silent_PAL_vsnprintf(LPSTR Buffer, INT Count, LPCSTR Format, va_list aparg) { if (Prefix == PFF_PREFIX_LONG && Type == PFF_TYPE_STRING) { + if (WIDTH_STAR == Width) + { + Width = va_arg(ap, INT); + } + else if (WIDTH_INVALID == Width) + { + /* both a '*' and a number, ignore, but remove arg */ + TempInt = va_arg(ap, INT); /* value not used */ + } + if (PRECISION_STAR == Precision) { Precision = va_arg(ap, INT); @@ -89,6 +99,7 @@ INT Silent_PAL_vsnprintf(LPSTR Buffer, INT Count, LPCSTR Format, va_list aparg) /* both a '*' and a number, ignore, but remove arg */ TempInt = va_arg(ap, INT); /* value not used */ } + TempWStr = va_arg(ap, LPWSTR); Length = Silent_WideCharToMultiByte(TempWStr, -1, 0, 0); if (!Length) @@ -98,7 +109,7 @@ INT Silent_PAL_vsnprintf(LPSTR Buffer, INT Count, LPCSTR Format, va_list aparg) } /* clip string output to MAX_STR_LEN characters */ - if(-1 == Precision) + if (PRECISION_DOT == Precision) { Precision = MAX_STR_LEN; } @@ -145,6 +156,13 @@ INT Silent_PAL_vsnprintf(LPSTR Buffer, INT Count, LPCSTR Format, va_list aparg) else if (Prefix == PFF_PREFIX_LONG && Type == PFF_TYPE_CHAR) { CHAR TempBuffer[4]; + + if (WIDTH_STAR == Width || + WIDTH_INVALID == Width) + { + /* ignore (because it's a char), and remove arg */ + TempInt = va_arg(ap, INT); /* value not used */ + } if (PRECISION_STAR == Precision || PRECISION_INVALID == Precision) { @@ -173,6 +191,10 @@ INT Silent_PAL_vsnprintf(LPSTR Buffer, INT Count, LPCSTR Format, va_list aparg) next arg */ else if (Type == PFF_TYPE_N) { + if (WIDTH_STAR == Width) + { + Width = va_arg(ap, INT); + } if (PRECISION_STAR == Precision) { Precision = va_arg(ap, INT); @@ -186,6 +208,35 @@ INT Silent_PAL_vsnprintf(LPSTR Buffer, INT Count, LPCSTR Format, va_list aparg) *(va_arg(ap, LPLONG)) = BufferPtr - Buffer; } } + else if (Type == PFF_TYPE_CHAR && (Flags & PFF_ZERO) != 0) + { + // Some versions of sprintf don't support 0-padded chars, + // so we handle them here. + char ch[2]; + + ch[0] = (char) va_arg(ap, int); + ch[1] = '\0'; + Length = 1; + BufferRanOut = !Internal_AddPaddingA(&BufferPtr, + Count - (BufferPtr - Buffer), + ch, + Width - Length, + Flags); + } + else if (Type == PFF_TYPE_STRING && (Flags & PFF_ZERO) != 0) + { + // Some versions of sprintf don't support 0-padded strings, + // so we handle them here. + char *tempStr; + + tempStr = va_arg(ap, char *); + Length = strlen(tempStr); + BufferRanOut = !Internal_AddPaddingA(&BufferPtr, + Count - (BufferPtr - Buffer), + tempStr, + Width - Length, + Flags); + } /* types that sprintf can handle */ else { @@ -205,10 +256,22 @@ INT Silent_PAL_vsnprintf(LPSTR Buffer, INT Count, LPCSTR Format, va_list aparg) TempInt = snprintf(BufferPtr, TempCount, TempBuff, trunc2); } + else if (Type == PFF_TYPE_INT && Prefix == PFF_PREFIX_SHORT) + { + // Convert explicitly from int to short to get + // correct sign extension for shorts on all systems. + int n; + short s; + + n = va_arg(ap, int); + s = (short) n; + + TempInt = snprintf(BufferPtr, TempCount, TempBuff, s); + } else { /* limit string output (%s) to 300 characters */ - if(TempBuff[0]=='%' && TempBuff[1]=='s') + if(TempBuff[0] == '%' && TempBuff[1] == 's') { if (strcpy_s(TempBuff, sizeof(TempBuff), "%.300s") != SAFECRT_SUCCESS) { @@ -253,7 +316,6 @@ INT Silent_PAL_vsnprintf(LPSTR Buffer, INT Count, LPCSTR Format, va_list aparg) } else { - return BufferPtr - Buffer; } } @@ -293,6 +355,16 @@ int Silent_PAL_vfprintf(PAL_FILE *stream, const char *format, va_list aparg) { if (Prefix == PFF_PREFIX_LONG && Type == PFF_TYPE_STRING) { + if (WIDTH_STAR == Width) + { + Width = va_arg(ap, INT); + } + else if (WIDTH_INVALID == Width) + { + /* both a '*' and a number, ignore, but remove arg */ + TempInt = va_arg(ap, INT); /* value not used */ + } + if (PRECISION_STAR == Precision) { Precision = va_arg(ap, INT); @@ -302,6 +374,7 @@ int Silent_PAL_vfprintf(PAL_FILE *stream, const char *format, va_list aparg) /* both a '*' and a number, ignore, but remove arg */ TempInt = va_arg(ap, INT); /* value not used */ } + TempWStr = va_arg(ap, LPWSTR); Length = Silent_WideCharToMultiByte(TempWStr, -1, 0, 0); if (!Length) @@ -364,6 +437,12 @@ int Silent_PAL_vfprintf(PAL_FILE *stream, const char *format, va_list aparg) else if (Prefix == PFF_PREFIX_LONG && Type == PFF_TYPE_CHAR) { CHAR TempBuffer[4]; + if (WIDTH_STAR == Width || + WIDTH_INVALID == Width) + { + /* ignore (because it's a char), and remove arg */ + TempInt = va_arg(ap, INT); /* value not used */ + } if (PRECISION_STAR == Precision || PRECISION_INVALID == Precision) { @@ -396,10 +475,15 @@ int Silent_PAL_vfprintf(PAL_FILE *stream, const char *format, va_list aparg) next arg */ else if (Type == PFF_TYPE_N) { + if (WIDTH_STAR == Width) + { + Width = va_arg(ap, INT); + } if (PRECISION_STAR == Precision) { Precision = va_arg(ap, INT); } + if (Prefix == PFF_PREFIX_SHORT) { *(va_arg(ap, short *)) = written; @@ -427,6 +511,18 @@ int Silent_PAL_vfprintf(PAL_FILE *stream, const char *format, va_list aparg) TempInt = fprintf((FILE*)stream, TempBuff, trunc2); } + else if (Type == PFF_TYPE_INT && Prefix == PFF_PREFIX_SHORT) + { + // Convert explicitly from int to short to get + // correct sign extension for shorts on all systems. + int n; + short s; + + n = va_arg(ap, int); + s = (short)n; + + TempInt = fprintf((FILE*)stream, TempBuff, s); + } else { va_list apcopy; @@ -521,19 +617,17 @@ Function: see Internal_ExtractFormatA function in printf.c *******************************************************************************/ -BOOL Silent_ExtractFormatA(LPCSTR *Fmt, LPSTR Out, LPINT Flags, - LPINT Width, LPINT Precision, - LPINT Prefix, LPINT Type) +BOOL Silent_ExtractFormatA(LPCSTR *Fmt, LPSTR Out, LPINT Flags, LPINT Width, LPINT Precision, LPINT Prefix, LPINT Type) { BOOL Result = FALSE; LPSTR TempStr; LPSTR TempStrPtr; - *Width = -1; - *Precision = -1; - *Flags = 0; - *Prefix = -1; - *Type = -1; + *Width = WIDTH_DEFAULT; + *Precision = PRECISION_DEFAULT; + *Flags = PFF_NONE; + *Prefix = PFF_PREFIX_DEFAULT; + *Type = PFF_TYPE_DEFAULT; if (*Fmt && **Fmt == '%') { @@ -593,6 +687,22 @@ BOOL Silent_ExtractFormatA(LPCSTR *Fmt, LPSTR Out, LPINT Flags, return Result; } } + else if (**Fmt == '*') + { + *Width = WIDTH_STAR; + *Out++ = *(*Fmt)++; + if (isdigit((unsigned char) **Fmt)) + { + /* this is an invalid width because we have a * then a number */ + /* printf handles this by just printing the whole string */ + *Width = WIDTH_INVALID; + while (isdigit((unsigned char) **Fmt)) + { + *Out++ = *(*Fmt)++; + } + } + } + /* grab precision specifier */ if (**Fmt == '.') @@ -629,10 +739,6 @@ BOOL Silent_ExtractFormatA(LPCSTR *Fmt, LPSTR Out, LPINT Flags, *Out++ = *(*Fmt)++; } } - else - { - *Precision = PRECISION_STAR; - } } else { @@ -640,6 +746,12 @@ BOOL Silent_ExtractFormatA(LPCSTR *Fmt, LPSTR Out, LPINT Flags, } } +#ifdef BIT64 + if (**Fmt == 'p') + { + *Prefix = PFF_PREFIX_LONGLONG; + } +#endif /* grab prefix of 'I64' for __int64 */ if ((*Fmt)[0] == 'I' && (*Fmt)[1] == '6' && (*Fmt)[2] == '4') { @@ -656,8 +768,14 @@ BOOL Silent_ExtractFormatA(LPCSTR *Fmt, LPSTR Out, LPINT Flags, /* grab prefix of 'l' or the undocumented 'w' (at least in MSDN) */ else if (**Fmt == 'l' || **Fmt == 'w') { - *Prefix = PFF_PREFIX_LONG; ++(*Fmt); +#ifdef BIT64 + // Only want to change the prefix on 64 bit when printing characters. + if (**Fmt == 'c' || **Fmt == 's') +#endif + { + *Prefix = PFF_PREFIX_LONG; + } } else if (**Fmt == 'L') { @@ -739,25 +857,22 @@ BOOL Silent_ExtractFormatA(LPCSTR *Fmt, LPSTR Out, LPINT Flags, else if (**Fmt == 'p') { *Type = PFF_TYPE_P; - if (*Prefix == PFF_PREFIX_SHORT) - { - *Out++ = 'h'; - } - else if (*Prefix == PFF_PREFIX_LONG) + *Out++ = *(*Fmt)++; + + if (*Prefix == PFF_PREFIX_LONGLONG) { - *Out++ = 'l'; + if (*Precision == PRECISION_DEFAULT) + { + *Precision = 16; + } } - else if (*Prefix == PFF_PREFIX_LONGLONG) + else { - /* native *printf does not support %I64p - (actually %llp), so we need to cheat a little bit */ - *Out++ = 'l'; - *Out++ = 'l'; + if (*Precision == PRECISION_DEFAULT) + { + *Precision = 8; + } } - (*Fmt)++; - *Out++ = '.'; - *Out++ = '8'; - *Out++ = 'X'; Result = TRUE; } diff --git a/src/coreclr/src/pal/src/exception/machexception.cpp b/src/coreclr/src/pal/src/exception/machexception.cpp index 201aa80..d51c692 100644 --- a/src/coreclr/src/pal/src/exception/machexception.cpp +++ b/src/coreclr/src/pal/src/exception/machexception.cpp @@ -93,6 +93,7 @@ struct ForwardedNotification #endif // !DISABLE_EXCEPTIONS static const char * PAL_MACH_EXCEPTION_MODE = "PAL_MachExceptionMode"; + enum MachExceptionMode { // special value to indicate we've not initialized yet @@ -123,7 +124,7 @@ enum MachExceptionMode MachException_SuppressManaged = 4, // Default value to use if environment variable not set. - MachException_Default = 2, + MachException_Default = 0, }; static exception_mask_t GetExceptionMask() @@ -536,6 +537,7 @@ void PAL_DispatchException(DWORD64 dwRDI, DWORD64 dwRSI, DWORD64 dwRDX, DWORD64 pointers.ExceptionRecord = pExRecord; pointers.ContextRecord = pContext; + NONPAL_TRACE("PAL_DispatchException(EC %08x EA %p)\n", pExRecord->ExceptionCode, pExRecord->ExceptionAddress); SEHProcessException(&pointers); } @@ -717,7 +719,13 @@ catch_exception_raise( #endif // _AMD64_ ); - ThreadContext.ContextFlags = CONTEXT_ALL; + // Don't save/restore the debug registers because loading them on OSx causes a + // priviledged instruction fault. The "DE" in CR4 is set. +#ifdef _X86_ + ThreadContext.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS +#else + ThreadContext.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT; +#endif MachRet = CONTEXT_GetThreadContextFromPort(thread, &ThreadContext); CHECK_MACH("CONTEXT_GetThreadContextFromPort", MachRet); @@ -1178,12 +1186,11 @@ bool IsHandledException(MachMessage *pNotification) if (IsWithinCoreCLR(ip)) { NONPAL_TRACE(" IP (%p) is in CoreCLR.\n", ip); - return true; + return CatchHardwareExceptionHolder::IsEnabled(); } // Check inside our executable heap. - bool fExecutableHeap = s_pExecutableHeap != NULL && - malloc_zone_owns_addr(s_pExecutableHeap, ip); + bool fExecutableHeap = s_pExecutableHeap != NULL && malloc_zone_owns_addr(s_pExecutableHeap, ip); if (fExecutableHeap) { NONPAL_TRACE(" IP (%p) is in the executable heap (%p).\n", ip, s_pExecutableHeap); @@ -1219,7 +1226,7 @@ bool IsHandledException(MachMessage *pNotification) void *pCallerIP = (void *)*((PULONG64)(rbpFaultingFunc+1)); if (IsWithinCoreCLR(pCallerIP)) { - NONPAL_TRACE(" CallerIP (%p) is in CoreCLR.\n", pCallerIP); + NONPAL_TRACE(" CallerIP (%p) is in CoreCLR (IP %p).\n", pCallerIP, ip); return true; } #endif // defined(_AMD64_) diff --git a/src/coreclr/src/pal/src/exception/seh.cpp b/src/coreclr/src/pal/src/exception/seh.cpp index 3080814..846da29 100644 --- a/src/coreclr/src/pal/src/exception/seh.cpp +++ b/src/coreclr/src/pal/src/exception/seh.cpp @@ -164,6 +164,7 @@ PAL_SetHardwareExceptionHandler( IN PHARDWARE_EXCEPTION_HANDLER exceptionHandler) { + //TRACE("Hardware exception installed: %p\n", exceptionHandler); g_hardwareExceptionHandler = exceptionHandler; } @@ -194,7 +195,8 @@ SEHProcessException(PEXCEPTION_POINTERS pointers) throw exception; } - TRACE("Unhandled hardware exception %08x\n", pointers->ExceptionRecord->ExceptionCode); + TRACE("Unhandled hardware exception %08x at %p\n", + pointers->ExceptionRecord->ExceptionCode, pointers->ExceptionRecord->ExceptionAddress); } /*++ diff --git a/src/coreclr/src/pal/src/memory/heap.cpp b/src/coreclr/src/pal/src/memory/heap.cpp index 5cc59d0..c2f316d 100644 --- a/src/coreclr/src/pal/src/memory/heap.cpp +++ b/src/coreclr/src/pal/src/memory/heap.cpp @@ -137,13 +137,7 @@ HeapCreate( } else { - malloc_zone_t *pZone = malloc_create_zone(dwInitialSize, 0 /* flags */); - ret = (HANDLE)pZone; -#ifdef CACHE_HEAP_ZONE - _ASSERT_MSG(s_pExecutableHeap == NULL, "PAL currently only handles the creation of one executable heap."); - s_pExecutableHeap = pZone; - TRACE("s_pExecutableHeap is %p.\n", s_pExecutableHeap); -#endif // CACHE_HEAP_ZONE + ret = (HANDLE)malloc_create_zone(dwInitialSize, 0 /* flags */); } #else // __APPLE__ @@ -176,7 +170,15 @@ GetProcessHeap( #if HEAP_HANDLES_ARE_REAL_HANDLES #error #else - ret = (HANDLE) malloc_default_zone(); + malloc_zone_t *pZone = malloc_default_zone(); + ret = (HANDLE)pZone; +#ifdef CACHE_HEAP_ZONE + if (s_pExecutableHeap == NULL) + { + s_pExecutableHeap = pZone; + TRACE("s_pExecutableHeap is %p (process heap).\n", s_pExecutableHeap); + } +#endif // CACHE_HEAP_ZONE #endif // HEAP_HANDLES_ARE_REAL_HANDLES #else ret = (HANDLE) DUMMY_HEAP; diff --git a/src/coreclr/src/pal/src/thread/context.cpp b/src/coreclr/src/pal/src/thread/context.cpp index 6006aad..fdeeda3 100644 --- a/src/coreclr/src/pal/src/thread/context.cpp +++ b/src/coreclr/src/pal/src/thread/context.cpp @@ -894,12 +894,14 @@ CONTEXT_GetThreadContextFromPort( lpContext->R13 = State.__r13; lpContext->R14 = State.__r14; lpContext->R15 = State.__r15; -// lpContext->SegSs = State.ss; // no such state? lpContext->EFlags = State.__rflags; lpContext->Rip = State.__rip; lpContext->SegCs = State.__cs; -// lpContext->SegDs_PAL_Undefined = State.ds; // no such state? -// lpContext->SegEs_PAL_Undefined = State.es; // no such state? + // RtlRestoreContext uses the actual ss instead of this one + // to build the iret frame so just set it zero. + lpContext->SegSs = 0; + lpContext->SegDs = 0; + lpContext->SegEs = 0; lpContext->SegFs = State.__fs; lpContext->SegGs = State.__gs; #else