Track debug info for DynamicMethods for Profiler API (#24139)
authorMukul Sabharwal <mjsabby@gmail.com>
Wed, 22 May 2019 08:52:38 +0000 (01:52 -0700)
committerDavid Mason <davmason@microsoft.com>
Wed, 22 May 2019 08:52:37 +0000 (01:52 -0700)
src/debug/ee/debugger.cpp
src/inc/clrconfigvalues.h
src/vm/eeconfig.cpp
src/vm/eeconfig.h
src/vm/jitinterface.cpp

index c6ce925..7a54b46 100644 (file)
@@ -2957,6 +2957,13 @@ DebuggerMethodInfo *Debugger::GetOrCreateMethodInfo(Module *pModule, mdMethodDef
 
 #ifndef DACCESS_COMPILE
 
+// Helper to use w/ the debug stores.
+BYTE* InteropSafeNoThrowNew(void*, size_t cBytes)
+{
+    BYTE* p = new (interopsafe, nothrow) BYTE[cBytes];
+    return p;
+}
+
 /******************************************************************************
  * GetILToNativeMapping returns a map from IL offsets to native
  * offsets for this code. An array of COR_PROF_IL_TO_NATIVE_MAP
@@ -2992,11 +2999,54 @@ HRESULT Debugger::GetILToNativeMapping(PCODE pNativeCodeStartAddress, ULONG32 cM
 #endif // PROFILING_SUPPORTED
 
     MethodDesc *fd = g_pEEInterface->GetNativeCodeMethodDesc(pNativeCodeStartAddress);
-    if (fd == NULL || fd->IsWrapperStub() || fd->IsDynamicMethod())
+    if (fd == NULL || fd->IsWrapperStub())
     {
         return E_FAIL;
     }
 
+    if (fd->IsDynamicMethod())
+    {
+        if (g_pConfig->GetTrackDynamicMethodDebugInfo())
+        {
+            DebugInfoRequest diq;
+            diq.InitFromStartingAddr(fd, pNativeCodeStartAddress);
+
+            if (cMap == 0)
+            {
+                if (DebugInfoManager::GetBoundariesAndVars(diq, nullptr, nullptr, pcMap, nullptr, nullptr, nullptr))
+                {
+                    return S_OK;
+                }
+
+                return E_FAIL;
+            }
+
+            ICorDebugInfo::OffsetMapping* pMap = nullptr;
+            if (DebugInfoManager::GetBoundariesAndVars(diq, InteropSafeNoThrowNew, nullptr, pcMap, &pMap, nullptr, nullptr))
+            {
+                for (ULONG32 i = 0; i < cMap; ++i)
+                {
+                    map[i].ilOffset = pMap[i].ilOffset;
+                    map[i].nativeStartOffset = pMap[i].nativeOffset;
+                    if (i > 0)
+                    {
+                        map[i - 1].nativeEndOffset = map[i].nativeStartOffset;
+                    }
+                }
+
+                DeleteInteropSafe(pMap);
+
+                return S_OK;
+            }
+
+            return E_FAIL;
+        }
+        else
+        {
+            return E_FAIL;
+        }
+    }
+
     DebuggerMethodInfo *pDMI = GetOrCreateMethodInfo(fd->GetModule(), fd->GetMemberDef());
     if (pDMI == NULL)
     {
index 4967278..b55c79a 100644 (file)
@@ -403,6 +403,7 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitVNMapSelBudget, W("JitVNMapSelBudget"), 100
 RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_FeatureSIMD, W("FeatureSIMD"), EXTERNAL_FeatureSIMD_Default, "Enable SIMD intrinsics recognition in System.Numerics.dll and/or System.Numerics.Vectors.dll", CLRConfig::REGUTIL_default)
 RETAIL_CONFIG_DWORD_INFO(INTERNAL_SIMD16ByteOnly, W("SIMD16ByteOnly"), 0, "Limit maximum SIMD vector length to 16 bytes (used by x64_arm64_altjit)")
 RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_EnableAVX, W("EnableAVX"), EXTERNAL_JitEnableAVX_Default, "Enable AVX instruction set for wide operations as default", CLRConfig::REGUTIL_default)
+RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_TrackDynamicMethodDebugInfo, W("TrackDynamicMethodDebugInfo"), 0, "Specifies whether debug info should be generated and tracked for dynamic methods", CLRConfig::REGUTIL_default)
 
 #ifdef FEATURE_MULTICOREJIT
 
index 87e7467..83c1f1e 100644 (file)
@@ -704,6 +704,8 @@ HRESULT EEConfig::sync()
     // Note the global variable is not updated directly by the GetRegKey function
     // so we only update it once (to avoid reentrancy windows)
 
+fTrackDynamicMethodDebugInfo = CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_TrackDynamicMethodDebugInfo);
+
 #ifdef _DEBUG
     iFastGCStress       = GetConfigDWORD_DontUse_(CLRConfig::INTERNAL_FastGCStress, iFastGCStress);
 
index f96a5a2..c952265 100644 (file)
@@ -273,13 +273,13 @@ public:
 
     // Jit-config
 
-    DWORD         JitHostMaxSlabCache(void)         const {LIMITED_METHOD_CONTRACT;  return dwJitHostMaxSlabCache; }
-    
-    unsigned int  GenOptimizeType(void)             const {LIMITED_METHOD_CONTRACT;  return iJitOptimizeType; }
-    bool          JitFramed(void)                   const {LIMITED_METHOD_CONTRACT;  return fJitFramed; }
-    bool          JitAlignLoops(void)               const {LIMITED_METHOD_CONTRACT;  return fJitAlignLoops; }
-    bool          AddRejitNops(void)                const {LIMITED_METHOD_DAC_CONTRACT;  return fAddRejitNops; }
-    bool          JitMinOpts(void)                  const {LIMITED_METHOD_CONTRACT;  return fJitMinOpts; }
+    DWORD         JitHostMaxSlabCache(void)                 const {LIMITED_METHOD_CONTRACT;  return dwJitHostMaxSlabCache; }
+    bool          GetTrackDynamicMethodDebugInfo(void)      const {LIMITED_METHOD_CONTRACT;  return fTrackDynamicMethodDebugInfo; }    
+    unsigned int  GenOptimizeType(void)                     const {LIMITED_METHOD_CONTRACT;  return iJitOptimizeType; }
+    bool          JitFramed(void)                           const {LIMITED_METHOD_CONTRACT;  return fJitFramed; }
+    bool          JitAlignLoops(void)                       const {LIMITED_METHOD_CONTRACT;  return fJitAlignLoops; }
+    bool          AddRejitNops(void)                        const {LIMITED_METHOD_DAC_CONTRACT;  return fAddRejitNops; }
+    bool          JitMinOpts(void)                          const {LIMITED_METHOD_CONTRACT;  return fJitMinOpts; }
     
     // Tiered Compilation config
 #if defined(FEATURE_TIERED_COMPILATION)
@@ -784,12 +784,12 @@ private: //----------------------------------------------------------------
 
     // Jit-config
 
-    DWORD dwJitHostMaxSlabCache; // max size for jit host slab cache
-
-    bool fJitFramed;           // Enable/Disable EBP based frames
-    bool fJitAlignLoops;       // Enable/Disable loop alignment
-    bool fAddRejitNops;        // Enable/Disable nop padding for rejit.          default is true
-    bool fJitMinOpts;          // Enable MinOpts for all jitted methods
+    DWORD dwJitHostMaxSlabCache;       // max size for jit host slab cache
+    bool fTrackDynamicMethodDebugInfo; //  Enable/Disable tracking dynamic method debug info
+    bool fJitFramed;                   // Enable/Disable EBP based frames
+    bool fJitAlignLoops;               // Enable/Disable loop alignment
+    bool fAddRejitNops;                // Enable/Disable nop padding for rejit.          default is true
+    bool fJitMinOpts;                  // Enable MinOpts for all jitted methods
 
     unsigned iJitOptimizeType; // 0=Blended,1=SmallCode,2=FastCode,              default is 0=Blended
     
index ef3b9d0..cf177a3 100644 (file)
@@ -11179,7 +11179,7 @@ void CEEJitInfo::CompressDebugInfo()
     } CONTRACTL_END;
 
     // Don't track JIT info for DynamicMethods.
-    if (m_pMethodBeingCompiled->IsDynamicMethod())
+    if (m_pMethodBeingCompiled->IsDynamicMethod() && !g_pConfig->GetTrackDynamicMethodDebugInfo())
         return;
 
     if (m_iOffsetMapping == 0 && m_iNativeVarInfo == 0)
@@ -12713,7 +12713,7 @@ CORJIT_FLAGS GetCompileFlags(MethodDesc * ftn, CORJIT_FLAGS flags, CORINFO_METHO
 
     flags.Set(CORJIT_FLAGS::CORJIT_FLAG_SKIP_VERIFICATION);
 
-    if (ftn->IsILStub())
+    if (ftn->IsILStub() && !g_pConfig->GetTrackDynamicMethodDebugInfo())
     {
         // no debug info available for IL stubs
         flags.Clear(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO);