diff --git a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Debugger.cs b/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Debugger.cs index 576c1fe696be55..1c2dcd8dcb5407 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Debugger.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Debugger.cs @@ -58,13 +58,12 @@ static void NotifyOfCrossThreadDependencySlow() [return: MarshalAs(UnmanagedType.Bool)] private static partial bool LaunchInternal(); - // Returns whether or not a debugger is attached to the process. - // - public static extern bool IsAttached - { - [MethodImpl(MethodImplOptions.InternalCall)] - get; - } + // Returns whether or not a managed debugger is attached to the process. + public static bool IsAttached => IsManagedDebuggerAttached() != 0; + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "DebugDebugger_IsManagedDebuggerAttached")] + [SuppressGCTransition] + private static partial int IsManagedDebuggerAttached(); // Constants representing the importance level of messages to be logged. // @@ -85,9 +84,11 @@ public static extern bool IsAttached private static partial void LogInternal(int level, string? category, string? message); // Checks to see if an attached debugger has logging enabled - // - [MethodImpl(MethodImplOptions.InternalCall)] - public static extern bool IsLogging(); + public static bool IsLogging() => IsLoggingInternal() != 0; + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "DebugDebugger_IsLoggingHelper")] + [SuppressGCTransition] + private static partial int IsLoggingInternal(); // Posts a custom notification for the attached debugger. If there is no // debugger attached, has no effect. The debugger may or may not diff --git a/src/coreclr/debug/ee/debugger.cpp b/src/coreclr/debug/ee/debugger.cpp index 3c3883cb6590ab..7522ed6c6a11d9 100644 --- a/src/coreclr/debug/ee/debugger.cpp +++ b/src/coreclr/debug/ee/debugger.cpp @@ -1651,7 +1651,7 @@ void Debugger::SendRawEvent(const DebuggerIPCEvent * pManagedEvent) // If no debugger attached, then don't bother raising a 1st-chance exception because nobody will sniff it. // @dbgtodo iDNA: in iDNA case, the recorder may sniff it. - if (!IsDebuggerPresent()) + if (!minipal_is_native_debugger_present()) { return; } @@ -6469,7 +6469,7 @@ HRESULT Debugger::LaunchDebuggerForUser(Thread * pThread, EXCEPTION_POINTERS * p // SendUserBreakpointAndSynchronize(g_pEEInterface->GetThread()); } - else if (!CORDebuggerAttached() && IsDebuggerPresent()) + else if (!CORDebuggerAttached() && minipal_is_native_debugger_present()) { // // If the registered debugger is not a managed debugger, send a native breakpoint @@ -6485,7 +6485,7 @@ HRESULT Debugger::LaunchDebuggerForUser(Thread * pThread, EXCEPTION_POINTERS * p DebugBreak(); } - if (!IsDebuggerPresent()) + if (!minipal_is_native_debugger_present()) { LOG((LF_CORDB, LL_ERROR, "D::LDFU: Failed to launch the debugger.\n")); } @@ -7106,7 +7106,7 @@ void Debugger::JitAttach(Thread * pThread, EXCEPTION_POINTERS * pExceptionInfo, CONTRACTL_END; // Don't do anything if there is a native debugger already attached or the debugging support has been disabled. - if (IsDebuggerPresent() || m_pRCThread == NULL) + if (minipal_is_native_debugger_present() || m_pRCThread == NULL) return; GCX_PREEMP_EEINTERFACE_TOGGLE_IFTHREAD(); @@ -7181,7 +7181,7 @@ void Debugger::EnsureDebuggerAttached(Thread * pThread, EXCEPTION_POINTERS * pEx { // if the debugger is already attached then we can't launch one // and whatever attach state we are in is just what we get - if(IsDebuggerPresent()) + if(minipal_is_native_debugger_present()) { // unblock other threads waiting on our attach and clean up PostJitAttach(); @@ -8919,7 +8919,7 @@ void Debugger::SendUserBreakpoint(Thread * thread) // On jit-attach, we just send the UserBreak event. Don't do an extra step-out. SendUserBreakpointAndSynchronize(thread); } - else if (IsDebuggerPresent()) + else if (minipal_is_native_debugger_present()) { DebugBreak(); } @@ -16796,4 +16796,3 @@ void Debugger::MulticastTraceNextStep(DELEGATEREF pbDel, INT32 count) #endif //DACCESS_COMPILE #endif //DEBUGGING_SUPPORTED - diff --git a/src/coreclr/debug/ee/debuggermessagebox.cpp b/src/coreclr/debug/ee/debuggermessagebox.cpp index 39b746da216eef..f91c54e7cc74cb 100644 --- a/src/coreclr/debug/ee/debuggermessagebox.cpp +++ b/src/coreclr/debug/ee/debuggermessagebox.cpp @@ -23,7 +23,7 @@ static void DbgPrintf(const LPCSTR szFormat, ...) va_end(args); - if (IsDebuggerPresent()) + if (minipal_is_native_debugger_present()) { OutputDebugStringUtf8(szBuffer); } diff --git a/src/coreclr/dlls/mscordac/mscordac_unixexports.src b/src/coreclr/dlls/mscordac/mscordac_unixexports.src index 3257e6f37960aa..b7fe8d95f5b793 100644 --- a/src/coreclr/dlls/mscordac/mscordac_unixexports.src +++ b/src/coreclr/dlls/mscordac/mscordac_unixexports.src @@ -36,7 +36,6 @@ nativeStringResourceTable_mscorrc #PAL_GetTransportPipeName #PAL_InitializeDLL #PAL_TerminateEx -#PAL_IsDebuggerPresent #PAL_OpenProcessMemory #PAL_CloseProcessMemory #PAL_ReadProcessMemory diff --git a/src/coreclr/hosts/corerun/CMakeLists.txt b/src/coreclr/hosts/corerun/CMakeLists.txt index 249465e2a78070..c9e259d32165ed 100644 --- a/src/coreclr/hosts/corerun/CMakeLists.txt +++ b/src/coreclr/hosts/corerun/CMakeLists.txt @@ -14,6 +14,7 @@ set(CLR_CMAKE_KEEP_NATIVE_SYMBOLS TRUE) add_executable_clr(corerun corerun.cpp dotenv.cpp + ${CLR_SRC_NATIVE_DIR}/minipal/debugger.c native.rc ) diff --git a/src/coreclr/hosts/corerun/corerun.hpp b/src/coreclr/hosts/corerun/corerun.hpp index 0adcdce2348145..b312f24404f333 100644 --- a/src/coreclr/hosts/corerun/corerun.hpp +++ b/src/coreclr/hosts/corerun/corerun.hpp @@ -49,6 +49,7 @@ namespace pal #ifdef TARGET_WINDOWS #define CDECL __cdecl #include +#include #define DLL_EXPORT __declspec(dllexport) #define MAIN __cdecl wmain @@ -138,7 +139,7 @@ namespace pal inline debugger_state_t is_debugger_attached() { - return (::IsDebuggerPresent() == TRUE) ? debugger_state_t::attached : debugger_state_t::not_attached; + return (minipal_is_native_debugger_present() == TRUE) ? debugger_state_t::attached : debugger_state_t::not_attached; } inline bool does_file_exist(const string_t& file_path) diff --git a/src/coreclr/jit/error.h b/src/coreclr/jit/error.h index 9ef5bf8b9dcfa4..7eb8906f0ff7db 100644 --- a/src/coreclr/jit/error.h +++ b/src/coreclr/jit/error.h @@ -9,6 +9,8 @@ #include // for CORJIT_INTERNALERROR #include // For FitsIn, used by SafeCvt methods. +#include + #define FATAL_JIT_EXCEPTION 0x02345678 class Compiler; @@ -247,7 +249,7 @@ extern void notYetImplemented(const char* msg, const char* file, unsigned line); #define BreakIfDebuggerPresent() \ do \ { \ - if (IsDebuggerPresent()) \ + if (minipal_is_native_debugger_present()) \ DebugBreak(); \ } while (0) #endif diff --git a/src/coreclr/minipal/CMakeLists.txt b/src/coreclr/minipal/CMakeLists.txt index 78a1726af3e815..298e1d6fba3819 100644 --- a/src/coreclr/minipal/CMakeLists.txt +++ b/src/coreclr/minipal/CMakeLists.txt @@ -5,4 +5,3 @@ if (CLR_CMAKE_HOST_UNIX) else (CLR_CMAKE_HOST_UNIX) add_subdirectory(Windows) endif (CLR_CMAKE_HOST_UNIX) - diff --git a/src/coreclr/minipal/Unix/CMakeLists.txt b/src/coreclr/minipal/Unix/CMakeLists.txt index 6cb70d1e344697..e273b12091308b 100644 --- a/src/coreclr/minipal/Unix/CMakeLists.txt +++ b/src/coreclr/minipal/Unix/CMakeLists.txt @@ -1,6 +1,7 @@ set(SOURCES doublemapping.cpp dn-u16.cpp + ${CLR_SRC_NATIVE_DIR}/minipal/debugger.c ${CLR_SRC_NATIVE_DIR}/minipal/time.c ) diff --git a/src/coreclr/minipal/Windows/CMakeLists.txt b/src/coreclr/minipal/Windows/CMakeLists.txt index b1f1cb88a3e6ac..20805efe5d513b 100644 --- a/src/coreclr/minipal/Windows/CMakeLists.txt +++ b/src/coreclr/minipal/Windows/CMakeLists.txt @@ -1,6 +1,7 @@ set(SOURCES doublemapping.cpp dn-u16.cpp + ${CLR_SRC_NATIVE_DIR}/minipal/debugger.c ${CLR_SRC_NATIVE_DIR}/minipal/utf8.c ${CLR_SRC_NATIVE_DIR}/minipal/time.c ) diff --git a/src/coreclr/nativeaot/Runtime/CMakeLists.txt b/src/coreclr/nativeaot/Runtime/CMakeLists.txt index b763e76af80e96..57d0acd98300a4 100644 --- a/src/coreclr/nativeaot/Runtime/CMakeLists.txt +++ b/src/coreclr/nativeaot/Runtime/CMakeLists.txt @@ -51,6 +51,7 @@ set(COMMON_RUNTIME_SOURCES ${GC_DIR}/softwarewritewatch.cpp ${CLR_SRC_NATIVE_DIR}/minipal/cpufeatures.c + ${CLR_SRC_NATIVE_DIR}/minipal/debugger.c ${CLR_SRC_NATIVE_DIR}/minipal/time.c ) diff --git a/src/coreclr/nativeaot/Runtime/MiscHelpers.cpp b/src/coreclr/nativeaot/Runtime/MiscHelpers.cpp index 3351326ad3071e..7b5040284eab16 100644 --- a/src/coreclr/nativeaot/Runtime/MiscHelpers.cpp +++ b/src/coreclr/nativeaot/Runtime/MiscHelpers.cpp @@ -36,6 +36,7 @@ #include "yieldprocessornormalized.h" #include "RhConfig.h" #include +#include FCIMPL0(void, RhDebugBreak) { @@ -394,6 +395,11 @@ EXTERN_C int32_t QCALLTYPE RhpGetCurrentThreadStackTrace(void* pOutputBuffer, ui return RhpCalculateStackTraceWorker(pOutputBuffer, outputBufferLength, pAddressInCurrentFrame); } +EXTERN_C UInt32_BOOL QCALLTYPE DebugDebugger_IsNativeDebuggerAttached() +{ + return minipal_is_native_debugger_present(); +} + FCIMPL2(FC_BOOL_RET, RhCompareObjectContentsAndPadding, Object* pObj1, Object* pObj2) { ASSERT(pObj1->GetMethodTable() == pObj2->GetMethodTable()); diff --git a/src/coreclr/nativeaot/Runtime/PalRedhawkFunctions.h b/src/coreclr/nativeaot/Runtime/PalRedhawkFunctions.h index 9bb0a9da6b8f40..5ce370e963fbb5 100644 --- a/src/coreclr/nativeaot/Runtime/PalRedhawkFunctions.h +++ b/src/coreclr/nativeaot/Runtime/PalRedhawkFunctions.h @@ -77,12 +77,6 @@ inline UInt32_BOOL PalInitializeCriticalSectionEx(CRITICAL_SECTION * arg1, uint3 return InitializeCriticalSectionEx(arg1, arg2, arg3); } -extern "C" UInt32_BOOL __stdcall IsDebuggerPresent(); -inline UInt32_BOOL PalIsDebuggerPresent() -{ - return IsDebuggerPresent(); -} - extern "C" void __stdcall LeaveCriticalSection(CRITICAL_SECTION *); inline void PalLeaveCriticalSection(CRITICAL_SECTION * arg1) { diff --git a/src/coreclr/nativeaot/Runtime/rhassert.cpp b/src/coreclr/nativeaot/Runtime/rhassert.cpp index c80437d314125a..970a0b025700da 100644 --- a/src/coreclr/nativeaot/Runtime/rhassert.cpp +++ b/src/coreclr/nativeaot/Runtime/rhassert.cpp @@ -7,6 +7,8 @@ #include "PalRedhawk.h" #include "rhassert.h" +#include + #ifdef _DEBUG void Assert(const char * expr, const char * file, uint32_t line_num, const char * message) @@ -28,7 +30,7 @@ void Assert(const char * expr, const char * file, uint32_t line_num, const char fflush(stdout); // If there's no debugger attached, we just FailFast - if (!PalIsDebuggerPresent()) + if (!minipal_is_native_debugger_present()) PalRaiseFailFastException(NULL, NULL, FAIL_FAST_GENERATE_EXCEPTION_ADDRESS); // If there is a debugger attached, we break and then allow continuation. diff --git a/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp b/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp index 56b453adc6ba38..5cacb58e86970c 100644 --- a/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp @@ -964,17 +964,6 @@ extern "C" void LeaveCriticalSection(CRITICAL_SECTION * lpCriticalSection) pthread_mutex_unlock(&lpCriticalSection->mutex); } -extern "C" UInt32_BOOL IsDebuggerPresent() -{ -#ifdef HOST_WASM - // For now always true since the browser will handle it in case of WASM. - return UInt32_TRUE; -#else - // UNIXTODO: Implement this function - return UInt32_FALSE; -#endif -} - extern "C" UInt32_BOOL SetEvent(HANDLE event) { EventUnixHandle* unixHandle = (EventUnixHandle*)event; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj index a19a91f0797764..038291f667bb49 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj @@ -270,9 +270,6 @@ Common\Interop\Windows\Advapi32\Interop.ReportEvent_IntPtr.cs - - Interop\Windows\Kernel32\Interop.IsDebuggerPresent.cs - Interop\Windows\Kernel32\Interop.RaiseFailFastException.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Diagnostics/Debugger.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Diagnostics/Debugger.cs index a0106b1816ec5d..c59219c382e3e6 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Diagnostics/Debugger.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Diagnostics/Debugger.cs @@ -1,7 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace System.Diagnostics { @@ -13,7 +15,7 @@ public static void Break() { #if TARGET_WINDOWS // IsAttached is always true when IsDebuggerPresent is true, so no need to check for it - if (Interop.Kernel32.IsDebuggerPresent()) + if (Debugger.IsNativeDebuggerAttached()) Debug.DebugBreak(); #else // UNIXTODO: Implement Debugger.Break @@ -74,5 +76,10 @@ public static bool IsLogging() } return false; } + + internal static bool IsNativeDebuggerAttached() => IsNativeDebuggerAttachedInternal() != 0; + + [LibraryImport(RuntimeImports.RuntimeLibrary, EntryPoint = "DebugDebugger_IsNativeDebuggerAttached")] + private static partial int IsNativeDebuggerAttachedInternal(); } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/EventReporter.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/EventReporter.cs index efb46025dbf5b5..51c382f2caa073 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/EventReporter.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/EventReporter.cs @@ -177,7 +177,7 @@ public static bool ShouldLogInEventLog { get { - if (Interop.Kernel32.IsDebuggerPresent()) + if (Debugger.IsNativeDebuggerAttached()) return false; if (s_once == 1 || Interlocked.Exchange(ref s_once, 1) == 1) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs index 9f01baa32b7c0d..15587b47467210 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs @@ -24,7 +24,7 @@ namespace System.Runtime // optional library, those methods can be moved to a different file/namespace/dll internal static partial class RuntimeImports { - private const string RuntimeLibrary = "*"; + internal const string RuntimeLibrary = "*"; [MethodImplAttribute(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhGetCrashInfoBuffer")] @@ -425,7 +425,7 @@ internal static IntPtr RhHandleAllocDependent(object primary, object secondary) // Yield the cpu to another thread ready to process, if one is available. [LibraryImport(RuntimeLibrary, EntryPoint = "RhYield")] private static partial int _RhYield(); - internal static bool RhYield() { return (_RhYield() != 0); } + internal static bool RhYield() => _RhYield() != 0; [LibraryImport(RuntimeLibrary, EntryPoint = "RhFlushProcessWriteBuffers")] internal static partial void RhFlushProcessWriteBuffers(); diff --git a/src/coreclr/pal/inc/pal.h b/src/coreclr/pal/inc/pal.h index e4a520c1dcf5c9..8d768044f119a0 100644 --- a/src/coreclr/pal/inc/pal.h +++ b/src/coreclr/pal/inc/pal.h @@ -170,13 +170,6 @@ extern bool g_arm64_atomics_present; /******************* PAL-Specific Entrypoints *****************************/ -#define IsDebuggerPresent PAL_IsDebuggerPresent - -PALIMPORT -BOOL -PALAPI -PAL_IsDebuggerPresent(); - #define DLL_PROCESS_ATTACH 1 #define DLL_THREAD_ATTACH 2 #define DLL_THREAD_DETACH 3 diff --git a/src/coreclr/pal/src/CMakeLists.txt b/src/coreclr/pal/src/CMakeLists.txt index cc301eb2757318..40df255ce17501 100644 --- a/src/coreclr/pal/src/CMakeLists.txt +++ b/src/coreclr/pal/src/CMakeLists.txt @@ -252,6 +252,9 @@ if(CLR_CMAKE_TARGET_LINUX) add_library(tracepointprovider OBJECT misc/tracepointprovider.cpp) endif(CLR_CMAKE_TARGET_LINUX) +add_library(minipal_debugger STATIC ${CLR_SRC_NATIVE_DIR}/minipal/debugger.c) +target_link_libraries(coreclrpal PRIVATE minipal_debugger) + if(CLR_CMAKE_TARGET_OSX) find_library(COREFOUNDATION CoreFoundation) find_library(CORESERVICES CoreServices) diff --git a/src/coreclr/pal/src/exception/machexception.cpp b/src/coreclr/pal/src/exception/machexception.cpp index 5f1bf97605784b..ee7e8d37aed025 100644 --- a/src/coreclr/pal/src/exception/machexception.cpp +++ b/src/coreclr/pal/src/exception/machexception.cpp @@ -31,6 +31,8 @@ SET_DEFAULT_DEBUG_CHANNEL(EXCEPT); // some headers have code with asserts, so do #include "pal/virtual.h" #include "pal/map.hpp" #include "pal/environ.h" + +#include #include #include "machmessage.h" @@ -180,7 +182,7 @@ GetExceptionMask() } else { - if (PAL_IsDebuggerPresent()) + if (minipal_is_native_debugger_present()) { exMode = MachException_SuppressDebugging; } diff --git a/src/coreclr/pal/src/init/pal.cpp b/src/coreclr/pal/src/init/pal.cpp index 4eeaa93b1e1e65..14a869e13293d2 100644 --- a/src/coreclr/pal/src/init/pal.cpp +++ b/src/coreclr/pal/src/init/pal.cpp @@ -775,108 +775,6 @@ PAL_InitializeCoreCLR(const char *szExePath, BOOL runningInExe) return ERROR_SUCCESS; } -/*++ -Function: -PAL_IsDebuggerPresent - -Abstract: -This function should be used to determine if a debugger is attached to the process. ---*/ -PALIMPORT -BOOL -PALAPI -PAL_IsDebuggerPresent() -{ -#if defined(__linux__) - BOOL debugger_present = FALSE; - char buf[2048]; - - int status_fd = open("/proc/self/status", O_RDONLY); - if (status_fd == -1) - { - return FALSE; - } - ssize_t num_read = read(status_fd, buf, sizeof(buf) - 1); - - if (num_read > 0) - { - static const char TracerPid[] = "TracerPid:"; - char *tracer_pid; - - buf[num_read] = '\0'; - tracer_pid = strstr(buf, TracerPid); - if (tracer_pid) - { - debugger_present = !!atoi(tracer_pid + sizeof(TracerPid) - 1); - } - } - - close(status_fd); - - return debugger_present; -#elif defined(__APPLE__) || defined(__FreeBSD__) - struct kinfo_proc info = {}; - size_t size = sizeof(info); - int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid() }; - int ret = sysctl(mib, sizeof(mib)/sizeof(*mib), &info, &size, nullptr, 0); - - if (ret == 0) -#if defined(__APPLE__) - return ((info.kp_proc.p_flag & P_TRACED) != 0); -#else // __FreeBSD__ - return ((info.ki_flag & P_TRACED) != 0); -#endif - - return FALSE; -#elif defined(__NetBSD__) - int traced; - kvm_t *kd; - int cnt; - - struct kinfo_proc *info; - - kd = kvm_open(nullptr, nullptr, nullptr, KVM_NO_FILES, "kvm_open"); - if (kd == nullptr) - return FALSE; - - info = kvm_getprocs(kd, KERN_PROC_PID, getpid(), &cnt); - if (info == nullptr || cnt < 1) - { - kvm_close(kd); - return FALSE; - } - - traced = info->kp_proc.p_slflag & PSL_TRACED; - kvm_close(kd); - - if (traced != 0) - return TRUE; - else - return FALSE; -#elif defined(__sun) - int readResult; - char statusFilename[64]; - snprintf(statusFilename, sizeof(statusFilename), "/proc/%d/status", getpid()); - int fd = open(statusFilename, O_RDONLY); - if (fd == -1) - { - return FALSE; - } - - pstatus_t status; - do - { - readResult = read(fd, &status, sizeof(status)); - } - while ((readResult == -1) && (errno == EINTR)); - - close(fd); - return status.pr_flttrace.word[0] != 0; -#else - return FALSE; -#endif -} - /*++ Function: PAL_Shutdown diff --git a/src/coreclr/tools/superpmi/superpmi-shared/spmiutil.cpp b/src/coreclr/tools/superpmi/superpmi-shared/spmiutil.cpp index 2de18219184faf..fae4cea68159b6 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/spmiutil.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/spmiutil.cpp @@ -9,6 +9,8 @@ #include "logging.h" #include "spmiutil.h" +#include + static bool breakOnDebugBreakorAV = false; bool BreakOnDebugBreakorAV() @@ -35,7 +37,7 @@ void SetBreakOnException(bool value) void DebugBreakorAV(int val) { - if (IsDebuggerPresent()) + if (minipal_is_native_debugger_present()) { if (val == 0) DEBUG_BREAK; diff --git a/src/coreclr/tools/superpmi/superpmi/jitdebugger.cpp b/src/coreclr/tools/superpmi/superpmi/jitdebugger.cpp index 151cd95d88f980..e2878935ba45dd 100644 --- a/src/coreclr/tools/superpmi/superpmi/jitdebugger.cpp +++ b/src/coreclr/tools/superpmi/superpmi/jitdebugger.cpp @@ -419,7 +419,7 @@ int DbgBreakCheck(const char* szFile, int iLine, const char* szExpr) // Tell caller to break at the correct location. case IDRETRY: - if (IsDebuggerPresent()) + if (minipal_is_native_debugger_present()) { SetErrorMode(0); } diff --git a/src/coreclr/utilcode/check.cpp b/src/coreclr/utilcode/check.cpp index 6ca26099d40027..2d584d895d2378 100644 --- a/src/coreclr/utilcode/check.cpp +++ b/src/coreclr/utilcode/check.cpp @@ -11,6 +11,8 @@ #include #include +#include + #ifdef _DEBUG size_t CHECK::s_cLeakedBytes = 0; size_t CHECK::s_cNumFailures = 0; @@ -189,7 +191,7 @@ void CHECK::Setup(LPCSTR message, LPCSTR condition, LPCSTR file, INT line) #endif #if defined(_DEBUG_IMPL) - if (IsInAssert() && IsDebuggerPresent()) + if (IsInAssert() && minipal_is_native_debugger_present()) { DebugBreak(); } diff --git a/src/coreclr/utilcode/debug.cpp b/src/coreclr/utilcode/debug.cpp index 2d1354fd6f149e..9e56bebac348ba 100644 --- a/src/coreclr/utilcode/debug.cpp +++ b/src/coreclr/utilcode/debug.cpp @@ -1,23 +1,23 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. + //***************************************************************************** // Debug.cpp // // Helper code for debugging. //***************************************************************************** -// - #include "stdafx.h" #include "utilcode.h" #include "ex.h" #include "corexcep.h" +#include + #ifdef _DEBUG #define LOGGING #endif - #include "log.h" #ifdef HOST_WINDOWS @@ -283,7 +283,7 @@ bool _DbgBreakCheck( return false; // don't stop debugger. No gui. } - if (IsDebuggerPresent()) + if (minipal_is_native_debugger_present()) { return true; // like a retry } diff --git a/src/coreclr/vm/debugdebugger.cpp b/src/coreclr/vm/debugdebugger.cpp index abb873942abaa0..a77dd524d6eaf5 100644 --- a/src/coreclr/vm/debugdebugger.cpp +++ b/src/coreclr/vm/debugdebugger.cpp @@ -7,8 +7,6 @@ ** ** Purpose: Native methods on System.Debug.Debugger ** -** - ===========================================================*/ #include "common.h" @@ -68,7 +66,7 @@ extern "C" void QCALLTYPE DebugDebugger_Break() // A managed debugger is already attached -- let it handle the event. g_pDebugInterface->SendUserBreakpoint(GetThread()); } - else if (IsDebuggerPresent()) + else if (minipal_is_native_debugger_present()) { // No managed debugger, but a native debug is attached. Explicitly fire a native user breakpoint. // Don't rely on Watson support since that may have a different policy. @@ -105,43 +103,6 @@ extern "C" BOOL QCALLTYPE DebugDebugger_Launch() return FALSE; } -FCIMPL0(FC_BOOL_RET, DebugDebugger::IsDebuggerAttached) -{ - FCALL_CONTRACT; - - FC_GC_POLL_RET(); - -#ifdef DEBUGGING_SUPPORTED - FC_RETURN_BOOL(CORDebuggerAttached()); -#else // DEBUGGING_SUPPORTED - FC_RETURN_BOOL(FALSE); -#endif -} -FCIMPLEND - -namespace -{ - BOOL IsLoggingHelper() - { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - } - CONTRACTL_END; - - #ifdef DEBUGGING_SUPPORTED - if (CORDebuggerAttached()) - { - return (g_pDebugInterface->IsLoggingEnabled()); - } - #endif // DEBUGGING_SUPPORTED - return FALSE; - } -} - - // Log to managed debugger. // It will send a managed log event, which will faithfully send the two string parameters here without // appending a newline to anything. @@ -186,7 +147,7 @@ extern "C" void QCALLTYPE DebugDebugger_Log(INT32 Level, PCWSTR pwzModule, PCWST // for the given category if (CORDebuggerAttached()) { - if (IsLoggingHelper() ) + if (g_pDebugInterface->IsLoggingEnabled() ) { // Copy log message and category into our own SString to protect against GC // Strings may contain embedded nulls, but we need to handle null-terminated @@ -216,16 +177,6 @@ extern "C" void QCALLTYPE DebugDebugger_Log(INT32 Level, PCWSTR pwzModule, PCWST #endif // DEBUGGING_SUPPORTED } -FCIMPL0(FC_BOOL_RET, DebugDebugger::IsLogging) -{ - FCALL_CONTRACT; - - FC_GC_POLL_RET(); - - FC_RETURN_BOOL(IsLoggingHelper()); -} -FCIMPLEND - static StackWalkAction GetStackFramesCallback(CrawlFrame* pCf, VOID* data) { CONTRACTL @@ -901,6 +852,31 @@ extern "C" void QCALLTYPE DebugDebugger_CustomNotification(QCall::ObjectHandleOn END_QCALL; #endif // DEBUGGING_SUPPORTED } + +extern "C" BOOL QCALLTYPE DebugDebugger_IsLoggingHelper() +{ + QCALL_CONTRACT_NO_GC_TRANSITION; + +#ifdef DEBUGGING_SUPPORTED + if (CORDebuggerAttached()) + { + return g_pDebugInterface->IsLoggingEnabled(); + } +#endif // DEBUGGING_SUPPORTED + + return FALSE; +} + +extern "C" BOOL QCALLTYPE DebugDebugger_IsManagedDebuggerAttached() +{ + QCALL_CONTRACT_NO_GC_TRANSITION; + +#ifdef DEBUGGING_SUPPORTED + return CORDebuggerAttached(); +#else + return FALSE; +#endif +} #endif // !DACCESS_COMPILE void DebugStackTrace::GetStackFramesFromException(OBJECTREF * e, diff --git a/src/coreclr/vm/debugdebugger.h b/src/coreclr/vm/debugdebugger.h index bbf06268752c5c..f09fc5e00cdfe7 100644 --- a/src/coreclr/vm/debugdebugger.h +++ b/src/coreclr/vm/debugdebugger.h @@ -7,27 +7,18 @@ ** ** Purpose: Native methods on System.Debug.Debugger ** -** - ===========================================================*/ #ifndef __DEBUG_DEBUGGER_h__ #define __DEBUG_DEBUGGER_h__ #include - -class DebugDebugger -{ -public: - static FCDECL0(FC_BOOL_RET, IsDebuggerAttached); - - static FCDECL0(FC_BOOL_RET, IsLogging); -}; - extern "C" void QCALLTYPE DebugDebugger_Break(); extern "C" BOOL QCALLTYPE DebugDebugger_Launch(); extern "C" void QCALLTYPE DebugDebugger_Log(INT32 Level, PCWSTR pwzModule, PCWSTR pwzMessage); extern "C" void QCALLTYPE DebugDebugger_CustomNotification(QCall::ObjectHandleOnStack data); +extern "C" BOOL QCALLTYPE DebugDebugger_IsLoggingHelper(); +extern "C" BOOL QCALLTYPE DebugDebugger_IsManagedDebuggerAttached(); class StackFrameHelper : public Object { diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index 25ec7d044d5a3b..b9af3cff241faf 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -67,11 +67,6 @@ FCFuncStart(gStringFuncs) FCDynamicSig(COR_CTOR_METHOD_NAME, &gsig_IM_PtrSByt_Int_Int_Encoding_RetVoid, ECall::CtorSBytePtrStartLengthEncodingManaged) FCFuncEnd() -FCFuncStart(gDiagnosticsDebugger) - FCFuncElement("get_IsAttached", DebugDebugger::IsDebuggerAttached) - FCFuncElement("IsLogging", DebugDebugger::IsLogging) -FCFuncEnd() - FCFuncStart(gEnvironmentFuncs) FCFuncElement("get_CurrentManagedThreadId", JIT_GetCurrentManagedThreadId) FCFuncElement("get_TickCount", SystemNative::GetTickCount) @@ -415,7 +410,6 @@ FCClassElement("AssemblyLoadContext", "System.Runtime.Loader", gAssemblyLoadCont FCClassElement("Buffer", "System", gBufferFuncs) FCClassElement("CastHelpers", "System.Runtime.CompilerServices", gCastHelpers) FCClassElement("ComAwareWeakReference", "System", gComAwareWeakReferenceFuncs) -FCClassElement("Debugger", "System.Diagnostics", gDiagnosticsDebugger) FCClassElement("Delegate", "System", gDelegateFuncs) FCClassElement("DependentHandle", "System.Runtime", gDependentHandleFuncs) FCClassElement("Environment", "System", gEnvironmentFuncs) diff --git a/src/coreclr/vm/eeconfig.h b/src/coreclr/vm/eeconfig.h index 91d9930c62a327..1f66a86fec1269 100644 --- a/src/coreclr/vm/eeconfig.h +++ b/src/coreclr/vm/eeconfig.h @@ -1,14 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// EEConfig.H -// +// EEConfig.H // // Fetched configuration data from the registry (should we Jit, run GC checks ...) // -// - - #ifndef EECONFIG_H #define EECONFIG_H @@ -17,6 +13,7 @@ class MethodDesc; #include "shash.h" #include "corhost.h" +#include #ifdef _DEBUG class TypeNamesList @@ -716,7 +713,7 @@ class EEConfig _ASSERTE(str); \ } \ else if (!(str)) { \ - if (IsDebuggerPresent()) DebugBreak(); \ + if (minipal_is_native_debugger_present()) DebugBreak(); \ } \ } while(0) diff --git a/src/coreclr/vm/eepolicy.cpp b/src/coreclr/vm/eepolicy.cpp index 861fb5552d9bf8..14157b1f77e697 100644 --- a/src/coreclr/vm/eepolicy.cpp +++ b/src/coreclr/vm/eepolicy.cpp @@ -1,13 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// -// // --------------------------------------------------------------------------- // EEPolicy.cpp // --------------------------------------------------------------------------- - #include "common.h" #include "eepolicy.h" #include "corhost.h" @@ -519,7 +516,7 @@ void EEPolicy::LogFatalError(UINT exitCode, UINT_PTR address, LPCWSTR pszMessage // termination. // // This behavior can still be overridden if the right config value is set. - if (IsDebuggerPresent()) + if (minipal_is_native_debugger_present()) { bool fBreak = (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_DbgOOBinFEEE) != 0); diff --git a/src/coreclr/vm/eventreporter.cpp b/src/coreclr/vm/eventreporter.cpp index 8ffab60bbd94c1..a742fc5fce8b9e 100644 --- a/src/coreclr/vm/eventreporter.cpp +++ b/src/coreclr/vm/eventreporter.cpp @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// -// //***************************************************************************** // EventReporter.cpp // @@ -10,7 +8,6 @@ // //***************************************************************************** - #include "common.h" #include "utilcode.h" #include "eventreporter.h" @@ -466,7 +463,7 @@ BOOL ShouldLogInEventLog() CONTRACTL_END; // If the process is being debugged, don't log - if ((CORDebuggerAttached() || IsDebuggerPresent()) + if ((CORDebuggerAttached() || minipal_is_native_debugger_present()) #ifdef _DEBUG // Allow debug to be able to break in && diff --git a/src/coreclr/vm/excep.cpp b/src/coreclr/vm/excep.cpp index ece90cbda507b3..8deb717174265a 100644 --- a/src/coreclr/vm/excep.cpp +++ b/src/coreclr/vm/excep.cpp @@ -1,8 +1,5 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// - -// /* EXCEP.CPP: * @@ -3504,12 +3501,12 @@ LONG WatsonLastChance( // EXCEPTION_CONTINUE_SEARCH, _CONTINUE_ // VS debugger team requested the Whidbey experience, which is no Watson when the debugger thread detects // that the debugger process is abruptly terminated, and triggers a failfast error. In this particular - // scenario CORDebuggerAttached() will be TRUE, but IsDebuggerPresent() will be FALSE because from OS + // scenario CORDebuggerAttached() will be TRUE, but minipal_is_native_debugger_present() will be FALSE because from OS // perspective the native debugger has been detached from the debuggee, but CLR has not yet marked the // managed debugger as detached. Therefore, CORDebuggerAttached() is checked, so Watson will not pop up // when a debugger is abruptly terminated. It also prevents a debugger from being launched on a helper // thread. - BOOL alreadyDebugging = CORDebuggerAttached() || IsDebuggerPresent(); + BOOL alreadyDebugging = CORDebuggerAttached() || minipal_is_native_debugger_present(); BOOL jitAttachRequested = !alreadyDebugging; // Launch debugger if not already running. @@ -3600,7 +3597,7 @@ LONG WatsonLastChance( // EXCEPTION_CONTINUE_SEARCH, _CONTINUE_ } - if (IsDebuggerPresent()) + if (minipal_is_native_debugger_present()) { result = FaultReportResultDebug; jitAttachRequested = FALSE; @@ -3674,9 +3671,9 @@ LONG WatsonLastChance( // EXCEPTION_CONTINUE_SEARCH, _CONTINUE_ } } // When the debugger thread detects that the debugger process is abruptly terminated, and triggers - // a failfast error, CORDebuggerAttached() will be TRUE, but IsDebuggerPresent() will be FALSE. - // If IsDebuggerPresent() is FALSE, do not try to notify the deubgger. - else if (CORDebuggerAttached() && IsDebuggerPresent()) + // a failfast error, CORDebuggerAttached() will be TRUE, but minipal_is_native_debugger_present() will be FALSE. + // If minipal_is_native_debugger_present() is FALSE, do not try to notify the deubgger. + else if (CORDebuggerAttached() && minipal_is_native_debugger_present()) #else } else if (CORDebuggerAttached()) @@ -3721,7 +3718,7 @@ LONG WatsonLastChance( // EXCEPTION_CONTINUE_SEARCH, _CONTINUE_ NotifyDebuggerLastChance(pThread, pExceptionInfo, jitAttachRequested); // If the registed debugger is not a managed debugger, we need to stop the debugger here. - if (!CORDebuggerAttached() && IsDebuggerPresent()) + if (!CORDebuggerAttached() && minipal_is_native_debugger_present()) { DebugBreak(); } @@ -6874,7 +6871,7 @@ VEH_ACTION WINAPI CLRVectoredExceptionHandlerPhase3(PEXCEPTION_POINTERS pExcepti DWORD tid = GetCurrentThreadId(); - BOOL debuggerPresentBeforeAssert = IsDebuggerPresent(); + BOOL debuggerPresentBeforeAssert = minipal_is_native_debugger_present(); CONSISTENCY_CHECK_MSGF(false, ("AV in clr at this callstack:\n------\n%s\n-----\n.AV on tid=0x%x (%d), cxr=%p, exr=%p\n", @@ -6886,7 +6883,7 @@ VEH_ACTION WINAPI CLRVectoredExceptionHandlerPhase3(PEXCEPTION_POINTERS pExcepti // return EXCEPTION_CONTINUE_EXECUTION to re-execute the faulting instruction. This is // supposed to be a nice little feature for CLR devs who attach debuggers on the "Av in // mscorwks" assert above. Since this is only for that case, its only in debug builds. - if (!debuggerPresentBeforeAssert && IsDebuggerPresent()) + if (!debuggerPresentBeforeAssert && minipal_is_native_debugger_present()) { return VEH_CONTINUE_EXECUTION;; } diff --git a/src/coreclr/vm/exceptionhandling.cpp b/src/coreclr/vm/exceptionhandling.cpp index 311f2434e23429..62a536442f492e 100644 --- a/src/coreclr/vm/exceptionhandling.cpp +++ b/src/coreclr/vm/exceptionhandling.cpp @@ -5635,7 +5635,7 @@ BOOL HandleHardwareException(PAL_SEHException* ex) void FirstChanceExceptionNotification() { #ifndef TARGET_UNIX - if (IsDebuggerPresent()) + if (minipal_is_native_debugger_present()) { PAL_TRY(VOID *, unused, NULL) { diff --git a/src/coreclr/vm/i386/gmsx86.cpp b/src/coreclr/vm/i386/gmsx86.cpp index e329d7bf9750a9..f255a82f0fea94 100644 --- a/src/coreclr/vm/i386/gmsx86.cpp +++ b/src/coreclr/vm/i386/gmsx86.cpp @@ -1124,7 +1124,7 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState, #ifndef DACCESS_COMPILE case 0xCC: - if (IsDebuggerPresent()) + if (minipal_is_native_debugger_present()) { OutputDebugStringA("CLR: Invalid breakpoint in a helpermethod frame epilog\n"); DebugBreak(); diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index f13286a675ab78..d9b69373b225f8 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -1,9 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. + // =========================================================================== // File: JITinterface.CPP -// - // =========================================================================== #include "common.h" @@ -14061,7 +14060,7 @@ BOOL LoadDynamicInfoEntry(Module *currentModule, methodNameImplCompiler.GetUTF8()); _ASSERTE_MSG(false, fatalErrorString.GetUTF8()); - _ASSERTE(!IsDebuggerPresent() && "Stop on assert here instead of fatal error for ease of live debugging"); + _ASSERTE(!minipal_is_native_debugger_present() && "Stop on assert here instead of fatal error for ease of live debugging"); EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(-1, fatalErrorString.GetUnicode()); return FALSE; @@ -14208,7 +14207,7 @@ BOOL LoadDynamicInfoEntry(Module *currentModule, ); _ASSERTE_MSG(false, fatalErrorString.GetUTF8()); - _ASSERTE(!IsDebuggerPresent() && "Stop on assert here instead of fatal error for ease of live debugging"); + _ASSERTE(!minipal_is_native_debugger_present() && "Stop on assert here instead of fatal error for ease of live debugging"); EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(-1, fatalErrorString.GetUnicode()); return FALSE; diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp index 205060bff044ef..84dd8f77f1355a 100644 --- a/src/coreclr/vm/methodtablebuilder.cpp +++ b/src/coreclr/vm/methodtablebuilder.cpp @@ -1,14 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// -// File: METHODTABLEBUILDER.CPP -// - // - +// File: METHODTABLEBUILDER.CPP // -// ============================================================================ #include "common.h" @@ -2055,7 +2050,7 @@ MethodTableBuilder::BuildMethodTableThrowing( LOG((LF_ALWAYS, LL_ALWAYS, "Number of declared methods: %d\n", NumDeclaredMethods())); LOG((LF_ALWAYS, LL_ALWAYS, "Number of declared non-abstract methods: %d\n", bmtMethod->dwNumDeclaredNonAbstractMethods)); - BOOL debugging = IsDebuggerPresent(); + BOOL debugging = minipal_is_native_debugger_present(); pMT->Debug_DumpInterfaceMap("Approximate"); pMT->DebugDumpVtable(pszDebugName, debugging); pMT->DebugDumpFieldLayout(pszDebugName, debugging); diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index 5558e8efd91868..4bc6782bb75804 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -88,6 +88,8 @@ static const Entry s_QCall[] = DllImportEntry(DebugDebugger_Launch) DllImportEntry(DebugDebugger_Log) DllImportEntry(DebugDebugger_CustomNotification) + DllImportEntry(DebugDebugger_IsLoggingHelper) + DllImportEntry(DebugDebugger_IsManagedDebuggerAttached) DllImportEntry(Delegate_BindToMethodName) DllImportEntry(Delegate_BindToMethodInfo) DllImportEntry(Delegate_InitializeVirtualCallStub) diff --git a/src/coreclr/vm/stubmgr.cpp b/src/coreclr/vm/stubmgr.cpp index 225310c646cd15..c284fd48c9df96 100644 --- a/src/coreclr/vm/stubmgr.cpp +++ b/src/coreclr/vm/stubmgr.cpp @@ -734,7 +734,7 @@ bool StubManager::IsStubLoggingEnabled() // on the helper thread. (B/c it may deadlock. See SUPPRESS_ALLOCATION_ASSERTS_IN_THIS_SCOPE) // We avoid this by just not logging when native-debugging. - if (IsDebuggerPresent()) + if (minipal_is_native_debugger_present()) { return false; } @@ -2273,4 +2273,3 @@ void TailCallStubManager::DoEnumMemoryRegions(CLRDataEnumMemoryFlags flags) #endif #endif // #ifdef DACCESS_COMPILE - diff --git a/src/coreclr/vm/util.cpp b/src/coreclr/vm/util.cpp index 4531a8cd623349..c279c50bf2b981 100644 --- a/src/coreclr/vm/util.cpp +++ b/src/coreclr/vm/util.cpp @@ -1,12 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. + // =========================================================================== // File: UTIL.CPP -// - // =========================================================================== - #include "common.h" #include "excep.h" #include "corhost.h" @@ -1556,7 +1554,7 @@ void DACNotifyExceptionHelper(TADDR *args, UINT argCount) _ASSERTE(argCount <= MAX_CLR_NOTIFICATION_ARGS); - if (IsDebuggerPresent() && !CORDebuggerAttached()) + if (minipal_is_native_debugger_present() && !CORDebuggerAttached()) { CrstHolder lh(&g_clrNotificationCrst); diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.IsDebuggerPresent.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.IsDebuggerPresent.cs deleted file mode 100644 index 8dc6f52bef6415..00000000000000 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.IsDebuggerPresent.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Runtime.InteropServices; - -internal static partial class Interop -{ - internal static partial class Kernel32 - { - [LibraryImport(Libraries.Kernel32)] - [return: MarshalAs(UnmanagedType.Bool)] - internal static partial bool IsDebuggerPresent(); - } -} diff --git a/src/mono/mono/mini/calls.c b/src/mono/mono/mini/calls.c index 3898ccf8973a46..f150bc4d308174 100644 --- a/src/mono/mono/mini/calls.c +++ b/src/mono/mono/mini/calls.c @@ -4,6 +4,7 @@ #include #include +#include #ifndef DISABLE_JIT @@ -16,7 +17,6 @@ #include "aot-compiler.h" #include #include -#include #include "mono/metadata/icall-signatures.h" static const gboolean debug_tailcall_break_compile = FALSE; // break in method_to_ir @@ -165,7 +165,7 @@ mini_emit_call_args (MonoCompile *cfg, MonoMethodSignature *sig, } if (tailcall && (debug_tailcall_break_compile || debug_tailcall_break_run) - && mono_is_usermode_native_debugger_present ()) { + && minipal_is_native_debugger_present ()) { if (debug_tailcall_break_compile) G_BREAKPOINT (); diff --git a/src/mono/mono/mini/method-to-ir.c b/src/mono/mono/mini/method-to-ir.c index d9432fd5510de5..c04db640843c90 100644 --- a/src/mono/mono/mini/method-to-ir.c +++ b/src/mono/mono/mini/method-to-ir.c @@ -66,7 +66,6 @@ #include #include #include -#include #include #include #include @@ -5707,11 +5706,11 @@ is_addressable_valuetype_load (MonoCompile* cfg, guint8* ip, MonoType* ldtype) /* * check_get_virtual_method_assumptions: - * + * * This shadows mono_class_get_virtual_method, but instead of actually resolving * the virtual method, this only checks if mono_class_get_virtual_method would * succeed. This is in place because that function fails catastrophically in some - * cases, bringing down the entire runtime. Returns TRUE if the function is safe + * cases, bringing down the entire runtime. Returns TRUE if the function is safe * to call, FALSE otherwise. */ static gboolean @@ -5742,16 +5741,16 @@ check_get_virtual_method_assumptions (MonoClass* klass, MonoMethod* method) if (iface_offset <= 0) return FALSE; } - + if (method->is_inflated) return FALSE; - + return TRUE; } /* * try_prepare_objaddr_callvirt_optimization: - * + * * Determine in a load+callvirt optimization can be performed and if so, * resolve the callvirt target method, so that it can behave as call. * Returns null, if the optimization cannot be performed. @@ -5762,7 +5761,7 @@ try_prepare_objaddr_callvirt_optimization (MonoCompile *cfg, guchar *next_ip, gu // TODO: relax the _is_def requirement? if (cfg->compile_aot || cfg->compile_llvm || !klass || !mono_class_is_def (klass)) return NULL; - + guchar* callvirt_ip; guint32 callvirt_proc_token; if (!(callvirt_ip = il_read_callvirt (next_ip, end, &callvirt_proc_token)) || @@ -5779,8 +5778,8 @@ try_prepare_objaddr_callvirt_optimization (MonoCompile *cfg, guchar *next_ip, gu MonoMethodSignature* iface_method_sig; if (!((iface_method_sig = mono_method_signature_internal (iface_method)) && - iface_method_sig->hasthis && - iface_method_sig->param_count == 0 && + iface_method_sig->hasthis && + iface_method_sig->param_count == 0 && !iface_method_sig->has_type_parameters && iface_method_sig->generic_param_count == 0)) return NULL; @@ -6237,7 +6236,7 @@ method_make_alwaysthrow_typeloadfailure (MonoCompile* cfg, MonoClass* klass) mono_remove_bblock (cfg, cfg->bb_init->out_bb [i]); } } - + // Maintain linked list consistency. This BB should have been added as the last, // ignoring the ones that held actual method code. cfg->cbb = cfg->bb_init; @@ -7535,10 +7534,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b */ if (fsig->pinvoke && mono_method_signature_has_ext_callconv (fsig, MONO_EXT_CALLCONV_SWIFTCALL)) { g_assert (!fsig->hasthis); // Swift P/Invoke calls shouldn't contain 'this' - + n = fsig->param_count; sp -= n; - // Save the old arguments + // Save the old arguments MonoInst **old_params = (MonoInst**) mono_mempool_alloc (cfg->mempool, sizeof (MonoInst*) * n); for (int idx_param = 0; idx_param < n; ++idx_param) { old_params [idx_param] = sp [idx_param]; @@ -7551,7 +7550,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b MonoClass *swift_error = mono_class_try_get_swift_error_class (); MonoClass *swift_indirect_result = mono_class_try_get_swift_indirect_result_class (); /* - * Go through the lowered arguments, if the argument is a struct, + * Go through the lowered arguments, if the argument is a struct, * we need to replace it with a sequence of lowered arguments. * Also record the updated parameters for the new signature. */ @@ -7602,7 +7601,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b } } - // Create a new dummy signature with the lowered arguments + // Create a new dummy signature with the lowered arguments fsig = mono_metadata_signature_dup_new_params (cfg->mempool, NULL, fsig, new_param_count, (MonoType**)new_params->data); // Deallocate temp array @@ -9934,11 +9933,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b !mini_is_gsharedvt_klass (klass) && (iface_method = mini_get_method (cfg, method, callvirt_proc_token, NULL, generic_context)) && (iface_method_sig = mono_method_signature_internal (iface_method)) && // callee signture is healthy - iface_method_sig->hasthis && + iface_method_sig->hasthis && iface_method_sig->param_count == 0 && // the callee has no args (other than this) !iface_method_sig->has_type_parameters && iface_method_sig->generic_param_count == 0) { // and no type params, apparently virtual generic methods require special handling - + if (!m_class_is_inited (iface_method->klass)) { if (!mono_class_init_internal (iface_method->klass)) TYPE_LOAD_ERROR (iface_method->klass); @@ -9972,8 +9971,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b } else { mono_error_cleanup (struct_method_error); } - } - } + } + } gboolean is_true; @@ -10130,7 +10129,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b // and generate a runtime exception. if (cfg->error->error_code == MONO_ERROR_BAD_IMAGE) clear_cfg_error (cfg); - + // We need to push a dummy value onto the stack, respecting the intended type. if (il_op == MONO_CEE_LDFLDA || il_op == MONO_CEE_LDSFLDA) { // Address is expected, push a null pointer. @@ -10143,7 +10142,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b goto all_bbs_done; } - break; + break; } CHECK_CFG_ERROR; } @@ -12114,14 +12113,14 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b inline_costs += 10; break; // reached only in AOT } - + --sp; if (mini_class_is_reference (klass)) MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STORE_MEMBASE_IMM, sp [0]->dreg, 0, 0); else mini_emit_initobj (cfg, *sp, NULL, klass); - + inline_costs += 1; break; case MONO_CEE_CONSTRAINED_: diff --git a/src/mono/mono/utils/CMakeLists.txt b/src/mono/mono/utils/CMakeLists.txt index 8f5a70cfd3ff96..36277972ab9868 100644 --- a/src/mono/mono/utils/CMakeLists.txt +++ b/src/mono/mono/utils/CMakeLists.txt @@ -141,8 +141,6 @@ set(utils_common_sources mono-tls.h mono-tls-inline.h mono-tls.c - mono-utils-debug.c - mono-utils-debug.h mono-memory-model.h atomic.h atomic.c @@ -179,6 +177,7 @@ set(utils_common_sources wasm-module-reader.c mono-bitutils.h mono-bitutils.c + ${CLR_SRC_NATIVE_DIR}/minipal/debugger.c ) if(MONO_CROSS_COMPILE) diff --git a/src/mono/mono/utils/mono-utils-debug.c b/src/mono/mono/utils/mono-utils-debug.c deleted file mode 100644 index d5aae23f8ba714..00000000000000 --- a/src/mono/mono/utils/mono-utils-debug.c +++ /dev/null @@ -1,126 +0,0 @@ -/* mono-utils-debug.c - * - * Copyright 2018 Microsoft - * Licensed under the MIT license. See LICENSE file in the project root for full license information. -*/ - -#include -#include -#include "mono-utils-debug.h" - -#if defined (_WIN32) - -#include - -gboolean -mono_is_usermode_native_debugger_present (void) -{ - // This is just a few instructions and no syscall. It is very fast. - // Kernel debugger is detected otherwise and is also useful for usermode debugging. - // Mono managed debugger is detected otherwise. - return IsDebuggerPresent () ? TRUE : FALSE; -} - -#else - -#include -#include -#include -#include -#if defined (__APPLE__) -#include -#endif -#if defined (__NetBSD__) -#include -#endif -#if defined (_AIX) -#include -#endif - -static gboolean -mono_is_usermode_native_debugger_present_slow (void) -// PAL_IsDebuggerPresent -// based closely on with some local cleanup: -// https://github.com/dotnet/runtime/blob/main/src/coreclr/pal/src/init/pal.cpp -// https://raw.githubusercontent.com/dotnet/coreclr/f1c9dac3e2db2397e01cd2da3e8aaa4f81a80013/src/pal/src/init/pal.cpp -{ -#if defined (__APPLE__) - - struct kinfo_proc info; - size_t size = sizeof (info); - memset (&info, 0, size); - int mib [4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid () }; - return sysctl (mib, sizeof (mib) / sizeof (*mib), &info, &size, NULL, 0) == 0 - && (info.kp_proc.p_flag & P_TRACED) != 0; - -#elif defined (__linux__) - - int const status_fd = open ("/proc/self/status", O_RDONLY); - if (status_fd == -1) - return FALSE; - - char buf [4098]; - buf [0] = '\n'; // consider if the first line - buf [1] = 0; // clear out garbage - ssize_t const num_read = read (status_fd, &buf [1], sizeof(buf) - 2); - close (status_fd); - static const char TracerPid [ ] = "\nTracerPid:"; - if (num_read <= sizeof (TracerPid)) - return FALSE; - - buf [num_read + 1] = 0; - char const * const tracer_pid = strstr (buf, TracerPid); - return tracer_pid && atoi (tracer_pid + sizeof (TracerPid) - 1); - -#elif defined (__NetBSD__) - - kvm_t * const kd = kvm_open (NULL, NULL, NULL, KVM_NO_FILES, "kvm_open"); - if (!kd) - return FALSE; - int count = 0; - struct kinfo_proc const * const info = kvm_getprocs (kd, KERN_PROC_PID, getpid (), &count); - gboolean const traced = info && count > 0 && (info->kp_proc.p_slflag & PSL_TRACED); - kvm_close (kd); - return traced; - -#elif defined (_AIX) - - struct procentry64 proc; - pid_t pid; - pid = getpid (); - getprocs64 (&proc, sizeof (proc), NULL, 0, &pid, 1); - return (proc.pi_flags & STRC) != 0; // SMPTRACE or SWTED might work too - -#else - return FALSE; // FIXME Other operating systems. -#endif -} - -// Cache because it is slow. -static gchar mono_is_usermode_native_debugger_present_cache; // 0:uninitialized 1:true 2:false - -gboolean -mono_is_usermode_native_debugger_present (void) -{ - if (mono_is_usermode_native_debugger_present_cache == 0) { - int er = errno; - mono_is_usermode_native_debugger_present_cache = mono_is_usermode_native_debugger_present_slow () ? 1 : 2; - mono_set_errno (er); - } - return mono_is_usermode_native_debugger_present_cache == 1; -} - -#endif // fast uncached Window vs. slow cached the rest - -#if 0 // test - -int -#ifdef _MSC_VER -__cdecl -#endif -main () -{ - printf ("mono_usermode_native_debugger_present:%d\n", mono_is_usermode_native_debugger_present ()); -} - -#endif diff --git a/src/mono/mono/utils/mono-utils-debug.h b/src/mono/mono/utils/mono-utils-debug.h deleted file mode 100644 index 2962988c3f4bd2..00000000000000 --- a/src/mono/mono/utils/mono-utils-debug.h +++ /dev/null @@ -1,8 +0,0 @@ -/* mono-utils-debug.h - * - * Copyright 2018 Microsoft - * Licensed under the MIT license. See LICENSE file in the project root for full license information. -*/ - -gboolean -mono_is_usermode_native_debugger_present (void); diff --git a/src/native/minipal/debugger.c b/src/native/minipal/debugger.c new file mode 100644 index 00000000000000..dc417079bc352a --- /dev/null +++ b/src/native/minipal/debugger.c @@ -0,0 +1,135 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include + +#include +#include +#include +#include + +#ifndef _WIN32 +#include +#ifdef __FreeBSD__ +#include +#endif +#endif + +#if defined(_WIN32) +#include +#elif defined(__linux__) +#include +#elif defined(__APPLE__) || defined(__FreeBSD__) +#include +#include +#elif defined(__NetBSD__) +#include +#include +#include +#include +#elif defined(__sun) +#include +#include +#include +#elif defined(_AIX) +#include +#include +#include +#endif + +bool minipal_is_native_debugger_present(void) +{ +#if defined(_WIN32) + return IsDebuggerPresent(); + +#elif defined(__linux__) + bool debugger_present = false; + char buf[2048]; + + int status_fd = open("/proc/self/status", O_RDONLY); + if (status_fd == -1) + { + return false; + } + ssize_t num_read = read(status_fd, buf, sizeof(buf) - 1); + if (num_read > 0) + { + static const char TracerPid[] = "TracerPid:"; + char *tracer_pid; + + buf[num_read] = '\0'; + tracer_pid = strstr(buf, TracerPid); + if (tracer_pid) + { + debugger_present = !!atoi(tracer_pid + sizeof(TracerPid) - 1); + } + } + + close(status_fd); + return debugger_present; + +#elif defined(__APPLE__) || defined(__FreeBSD__) + struct kinfo_proc info; + size_t size = sizeof(info); + int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid() }; + if (sysctl(mib, sizeof(mib)/sizeof(*mib), &info, &size, NULL, 0) == 0) + { +#if defined(__APPLE__) + return ((info.kp_proc.p_flag & P_TRACED) != 0); +#else // FreeBSD + return ((info.ki_flag & P_TRACED) != 0); +#endif + } + return false; + +#elif defined(__NetBSD__) + int traced; + kvm_t *kd; + int cnt; + struct kinfo_proc *info; + + kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, "kvm_open"); + if (kd == NULL) + return false; + + info = kvm_getprocs(kd, KERN_PROC_PID, getpid(), &cnt); + if (info == NULL || cnt < 1) + { + kvm_close(kd); + return false; + } + + traced = info->kp_proc.p_slflag & PSL_TRACED; + kvm_close(kd); + return traced != 0; + +#elif defined(__sun) + int fd; + char statusFilename[64]; + snprintf(statusFilename, sizeof(statusFilename), "/proc/%d/status", getpid()); + fd = open(statusFilename, O_RDONLY); + if (fd == -1) + { + return false; + } + + pstatus_t status; + ssize_t readResult; + do + { + readResult = read(fd, &status, sizeof(status)); + } while (readResult == -1 && errno == EINTR); + + close(fd); + return status.pr_flttrace.word[0] != 0; + +#elif defined(_AIX) + struct procentry64 proc; + pid_t pid = getpid(); + getprocs64(&proc, sizeof(proc), NULL, 0, &pid, 1); + return (proc.pi_flags & STRC) != 0; // SMPTRACE or SWTED might work too + +#else + return false; +#endif +} diff --git a/src/native/minipal/debugger.h b/src/native/minipal/debugger.h new file mode 100644 index 00000000000000..ae9fd2279214fb --- /dev/null +++ b/src/native/minipal/debugger.h @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef HAVE_MINIPAL_IS_NATIVE_DEBUGGER_PRESENT_H +#define HAVE_MINIPAL_IS_NATIVE_DEBUGGER_PRESENT_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Check if a native debugger is attached to the current process. + * + * @return true if a debugger is attached, false otherwise. + */ +bool minipal_is_native_debugger_present(void); + +#ifdef __cplusplus +} +#endif + +#endif // HAVE_MINIPAL_IS_NATIVE_DEBUGGER_PRESENT_H