Skip to content

Commit ba962fd

Browse files
Fix stepping issues with ReadyToRun and TieredCompilation (#66491)
* Fix stepping with ReadyToRun and TieredCompilation assemblies Get the correct PCODE version for ReadyToRun methods when the StubManager is computing the address to step to. * Update logging Update GetJitInfoWorker to respect code versioning
1 parent 3eea15a commit ba962fd

File tree

5 files changed

+89
-133
lines changed

5 files changed

+89
-133
lines changed

src/coreclr/debug/ee/controller.cpp

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,8 +1306,8 @@ bool DebuggerController::BindPatch(DebuggerControllerPatch *patch,
13061306
return false;
13071307
}
13081308

1309-
LOG((LF_CORDB,LL_INFO10000, "DC::BindPa: For startAddr 0x%x, got DJI "
1310-
"0x%x, from 0x%x size: 0x%x\n", startAddr, info, info->m_addrOfCode, info->m_sizeOfCode));
1309+
LOG((LF_CORDB,LL_INFO10000, "DC::BindPa: For startAddr 0x%p, got DJI "
1310+
"0x%p, from 0x%p size: 0x%x\n", startAddr, info, info->m_addrOfCode, info->m_sizeOfCode));
13111311
}
13121312

13131313
LOG((LF_CORDB, LL_INFO10000, "DC::BP:Trying to bind patch in %s::%s version %d\n",
@@ -1946,6 +1946,10 @@ BOOL DebuggerController::AddILPatch(AppDomain * pAppDomain, Module *module,
19461946
BOOL fOk = FALSE;
19471947

19481948
DebuggerMethodInfo *dmi = g_pDebugger->GetOrCreateMethodInfo(module, md); // throws
1949+
LOG((LF_CORDB,LL_INFO10000,"DC::AILP: dmi:0x%p, mdToken:0x%x, mdFilter:0x%p, "
1950+
"encVer:%zu, offset:0x%zx <- isIL:%d, Mod:0x%p\n",
1951+
dmi, md, pMethodDescFilter, encVersion, offset, offsetIsIL, module));
1952+
19491953
if (dmi == NULL)
19501954
{
19511955
return false;
@@ -7173,7 +7177,7 @@ TP_RESULT DebuggerStepper::TriggerPatch(DebuggerControllerPatch *patch,
71737177
else
71747178
{
71757179
LOG((LF_CORDB, LL_INFO10000,
7176-
"TSO for TRACE_MGR_PUSH case."));
7180+
"TSO for TRACE_MGR_PUSH case. RetAddr: 0x%p\n", traceManagerRetAddr));
71777181

71787182
// We'd better have a valid return address.
71797183
_ASSERTE(traceManagerRetAddr != NULL);
@@ -7184,28 +7188,39 @@ TP_RESULT DebuggerStepper::TriggerPatch(DebuggerControllerPatch *patch,
71847188
DebuggerJitInfo *dji;
71857189
dji = g_pDebugger->GetJitInfoFromAddr((TADDR) traceManagerRetAddr);
71867190

7187-
MethodDesc * mdNative = (dji == NULL) ?
7188-
g_pEEInterface->GetNativeCodeMethodDesc(dac_cast<PCODE>(traceManagerRetAddr)) : dji->m_nativeCodeVersion.GetMethodDesc();
7189-
_ASSERTE(mdNative != NULL);
7191+
MethodDesc* mdNative = NULL;
7192+
PCODE pcodeNative = NULL;
7193+
if (dji != NULL)
7194+
{
7195+
mdNative = dji->m_nativeCodeVersion.GetMethodDesc();
7196+
pcodeNative = dji->m_nativeCodeVersion.GetNativeCode();
7197+
}
7198+
else
7199+
{
7200+
// Find the method that the return is to.
7201+
mdNative = g_pEEInterface->GetNativeCodeMethodDesc(dac_cast<PCODE>(traceManagerRetAddr));
7202+
_ASSERTE(g_pEEInterface->GetFunctionAddress(mdNative) != NULL);
7203+
pcodeNative = g_pEEInterface->GetFunctionAddress(mdNative);
7204+
}
71907205

7191-
// Find the method that the return is to.
7192-
_ASSERTE(g_pEEInterface->GetFunctionAddress(mdNative) != NULL);
7193-
SIZE_T offsetRet = dac_cast<TADDR>(traceManagerRetAddr -
7194-
g_pEEInterface->GetFunctionAddress(mdNative));
7206+
_ASSERTE(mdNative != NULL && pcodeNative != NULL);
7207+
SIZE_T offsetRet = dac_cast<TADDR>(traceManagerRetAddr - pcodeNative);
7208+
LOG((LF_CORDB, LL_INFO10000,
7209+
"DS::TP: Before normally managed code AddPatch"
7210+
" in %s::%s \n\tmd=0x%p, offset 0x%x, pcode=0x%p, dji=0x%p\n",
7211+
mdNative->m_pszDebugClassName,
7212+
mdNative->m_pszDebugMethodName,
7213+
mdNative,
7214+
offsetRet,
7215+
pcodeNative,
7216+
dji));
71957217

71967218
// Place the patch.
71977219
AddBindAndActivateNativeManagedPatch(mdNative,
71987220
dji,
71997221
offsetRet,
72007222
LEAF_MOST_FRAME,
72017223
NULL);
7202-
7203-
LOG((LF_CORDB, LL_INFO10000,
7204-
"DS::TP: normally managed code AddPatch"
7205-
" in %s::%s, offset 0x%x\n",
7206-
mdNative->m_pszDebugClassName,
7207-
mdNative->m_pszDebugMethodName,
7208-
offsetRet));
72097224
}
72107225
else
72117226
{

src/coreclr/debug/ee/debugger.cpp

Lines changed: 45 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -2665,120 +2665,96 @@ DebuggerJitInfo *Debugger::GetJitInfo(MethodDesc *fd, const BYTE *pbAddr, Debugg
26652665
// Internal worker to GetJitInfo. Doesn't validate parameters.
26662666
DebuggerJitInfo *Debugger::GetJitInfoWorker(MethodDesc *fd, const BYTE *pbAddr, DebuggerMethodInfo **pMethInfo)
26672667
{
2668+
CONTRACTL
2669+
{
2670+
THROWS;
2671+
GC_NOTRIGGER;
2672+
PRECONDITION(!g_pDebugger->HasDebuggerDataLock());
2673+
}
2674+
CONTRACTL_END;
26682675

26692676
DebuggerMethodInfo *dmi = NULL;
26702677
DebuggerJitInfo *dji = NULL;
26712678

2679+
if (pMethInfo)
2680+
{
2681+
*pMethInfo = NULL;
2682+
}
2683+
26722684
// If we have a null MethodDesc - we're not going to get a jit-info. Do this check once at the top
26732685
// rather than littered throughout the rest of this function.
26742686
if (fd == NULL)
26752687
{
2676-
LOG((LF_CORDB, LL_EVERYTHING, "Debugger::GetJitInfo, addr=0x%p - null fd - returning null\n", pbAddr));
2688+
LOG((LF_CORDB, LL_EVERYTHING, "D::GJIW: addr=0x%p - null fd - returning null\n", pbAddr));
26772689
return NULL;
26782690
}
2679-
else
2680-
{
2681-
CONSISTENCY_CHECK_MSGF(!fd->IsWrapperStub(), ("Can't get Jit-info for wrapper MDesc,'%s'", fd->m_pszDebugMethodName));
2682-
}
26832691

2684-
// The debugger doesn't track Lightweight-codegen methods b/c they have no metadata.
2692+
CONSISTENCY_CHECK_MSGF(!fd->IsWrapperStub(), ("Can't get Jit-info for wrapper MDesc,'%s'", fd->m_pszDebugMethodName));
2693+
2694+
// The debugger doesn't track dynamic methods b/c they have no metadata.
26852695
if (fd->IsDynamicMethod())
26862696
{
26872697
return NULL;
26882698
}
26892699

2690-
2691-
// initialize our out param
2692-
if (pMethInfo)
2693-
{
2694-
*pMethInfo = NULL;
2695-
}
2696-
2697-
LOG((LF_CORDB, LL_EVERYTHING, "Debugger::GetJitInfo called\n"));
2698-
// CHECK_DJI_TABLE_DEBUGGER;
2699-
27002700
// Find the DJI via the DMI
27012701
//
27022702
// One way to improve the perf, both in terms of memory usage, number of allocations
27032703
// and lookup speeds would be to have the first JitInfo inline in the MethodInfo
27042704
// struct. After all, we never want to have a MethodInfo in the table without an
27052705
// associated JitInfo, and this should bring us back very close to the old situation
27062706
// in terms of perf. But correctness comes first, and perf later...
2707-
// CHECK_DMI_TABLE;
27082707
dmi = GetOrCreateMethodInfo(fd->GetModule(), fd->GetMemberDef());
2709-
27102708
if (dmi == NULL)
27112709
{
27122710
// If we can't create the DMI, we won't be able to create the DJI.
27132711
return NULL;
27142712
}
27152713

2716-
// TODO: Currently, this method does not handle code versioning properly (at least in some profiler scenarios), it may need
2717-
// to take pbAddr into account and lazily create a DJI for that particular version of the method.
2718-
2719-
// This may take the lock and lazily create an entry, so we do it up front.
2720-
dji = dmi->GetLatestJitInfo(fd);
2721-
2722-
2723-
DebuggerDataLockHolder debuggerDataLockHolder(this);
2724-
2725-
// Note the call to GetLatestJitInfo() will lazily create the first DJI if we don't already have one.
2726-
for (; dji != NULL; dji = dji->m_prevJitInfo)
2714+
if (pbAddr == NULL)
27272715
{
2728-
if (PTR_TO_TADDR(dji->m_nativeCodeVersion.GetMethodDesc()) == PTR_HOST_TO_TADDR(fd))
2729-
{
2730-
break;
2731-
}
2716+
dji = dmi->GetLatestJitInfo(fd);
27322717
}
2733-
2734-
LOG((LF_CORDB, LL_INFO1000, "D::GJI: for md:0x%p (%s::%s), got dmi:0x%p, dji:0x%p, latest dji:0x%p, latest fd:0x%p, prev dji:0x%p\n",
2735-
fd, fd->m_pszDebugClassName, fd->m_pszDebugMethodName,
2736-
dmi, dji, (dmi ? dmi->GetLatestJitInfo_NoCreate() : 0),
2737-
((dmi && dmi->GetLatestJitInfo_NoCreate()) ? dmi->GetLatestJitInfo_NoCreate()->m_nativeCodeVersion.GetMethodDesc():0),
2738-
(dji?dji->m_prevJitInfo:0)));
2739-
2740-
if ((dji != NULL) && (pbAddr != NULL))
2741-
{
2742-
dji = dji->GetJitInfoByAddress(pbAddr);
2743-
2744-
// XXX Microsoft - dac doesn't support stub tracing
2745-
// so this just results in not-impl exceptions.
27462718
#ifndef DACCESS_COMPILE
2747-
if (dji == NULL) //may have been given address of a thunk
2719+
else
2720+
{
2721+
PCODE startAddr = g_pEEInterface->GetNativeCodeStartAddress((PCODE)pbAddr);
2722+
if (startAddr == NULL)
27482723
{
2749-
LOG((LF_CORDB,LL_INFO1000,"Couldn't find a DJI by address 0x%p, "
2724+
LOG((LF_CORDB,LL_INFO1000,"D::GJIW: Couldn't find a DJI by address 0x%p, "
27502725
"so it might be a stub or thunk\n", pbAddr));
2751-
TraceDestination trace;
27522726

2753-
g_pEEInterface->TraceStub((const BYTE *)pbAddr, &trace);
2754-
2755-
if ((trace.GetTraceType() == TRACE_MANAGED) && (pbAddr != (const BYTE *)trace.GetAddress()))
2727+
// if the address wasn't in jitted code we'll also check to see if it is a stub that leads to jitted code
2728+
TraceDestination trace;
2729+
(void)g_pEEInterface->TraceStub(pbAddr, &trace);
2730+
if(trace.GetTraceType() == TRACE_MANAGED && (PCODE)pbAddr != trace.GetAddress())
27562731
{
2757-
LOG((LF_CORDB,LL_INFO1000,"Address thru thunk"
2758-
": 0x%p\n", trace.GetAddress()));
2759-
dji = GetJitInfo(fd, dac_cast<PTR_CBYTE>(trace.GetAddress()));
2732+
startAddr = trace.GetAddress();
2733+
LOG((LF_CORDB,LL_INFO1000,"D::GJIW: Address thru thunk: 0x%p\n", startAddr));
27602734
}
27612735
#ifdef LOGGING
27622736
else
27632737
{
2764-
_ASSERTE(trace.GetTraceType() != TRACE_UNJITTED_METHOD ||
2765-
(fd == trace.GetMethodDesc()));
2766-
LOG((LF_CORDB,LL_INFO1000,"Address not thunked - "
2738+
_ASSERTE(trace.GetTraceType() != TRACE_UNJITTED_METHOD || (fd == trace.GetMethodDesc()));
2739+
LOG((LF_CORDB,LL_INFO1000,"D::GJIW: Address not thunked - "
27672740
"must be to unJITted method, or normal managed "
27682741
"method lacking a DJI!\n"));
27692742
}
2770-
#endif //LOGGING
2743+
#endif // LOGGING
2744+
}
2745+
2746+
if (startAddr != NULL)
2747+
{
2748+
dji = dmi->FindOrCreateInitAndAddJitInfo(fd, startAddr);
27712749
}
2772-
#endif // #ifndef DACCESS_COMPILE
27732750
}
2751+
#endif // !DACCESS_COMPILE
27742752

27752753
if (pMethInfo)
27762754
{
27772755
*pMethInfo = dmi;
27782756
}
27792757

2780-
// DebuggerDataLockHolder out of scope - release implied
2781-
27822758
return dji;
27832759
}
27842760

@@ -2813,7 +2789,7 @@ DebuggerMethodInfo *Debugger::GetOrCreateMethodInfo(Module *pModule, mdMethodDef
28132789
{
28142790
info = CreateMethodInfo(pModule, token);
28152791

2816-
LOG((LF_CORDB, LL_INFO1000, "D::GOCMI: created DMI for mdToken:0x%x, dmi:0x%x\n",
2792+
LOG((LF_CORDB, LL_INFO1000, "D::GOCMI: created DMI for mdToken:0x%x, dmi:0x%p\n",
28172793
token, info));
28182794
}
28192795
#endif // #ifndef DACCESS_COMPILE
@@ -3093,12 +3069,12 @@ CodeRegionInfo CodeRegionInfo::GetCodeRegionInfo(DebuggerJitInfo *dji, MethodDes
30933069

30943070
if (dji && dji->m_addrOfCode)
30953071
{
3096-
LOG((LF_CORDB, LL_EVERYTHING, "CRI::GCRI: simple case\n"));
3072+
LOG((LF_CORDB, LL_INFO10000, "CRI::GCRI: simple case: CodeRegionInfo* 0x%p\n", &dji->m_codeRegionInfo));
30973073
return dji->m_codeRegionInfo;
30983074
}
30993075
else
31003076
{
3101-
LOG((LF_CORDB, LL_EVERYTHING, "CRI::GCRI: more complex case\n"));
3077+
LOG((LF_CORDB, LL_INFO10000, "CRI::GCRI: more complex case\n"));
31023078
CodeRegionInfo codeRegionInfo;
31033079

31043080
// Use method desc from dji if present
@@ -3119,6 +3095,7 @@ CodeRegionInfo CodeRegionInfo::GetCodeRegionInfo(DebuggerJitInfo *dji, MethodDes
31193095
(addr == dac_cast<PTR_CORDB_ADDRESS_TYPE>(g_pEEInterface->GetFunctionAddress(md))));
31203096
}
31213097

3098+
LOG((LF_CORDB, LL_INFO10000, "CRI::GCRI: Initializing CodeRegionInfo from 0x%p, md=0x%p\n", addr, md));
31223099
if (addr)
31233100
{
31243101
PCODE pCode = PINSTRToPCODE(dac_cast<TADDR>(addr));
@@ -13961,7 +13938,7 @@ Debugger::InsertToMethodInfoList( DebuggerMethodInfo *dmi )
1396113938
}
1396213939
CONTRACTL_END;
1396313940

13964-
LOG((LF_CORDB,LL_INFO10000,"D:IAHOL DMI: dmi:0x%08x\n", dmi));
13941+
LOG((LF_CORDB,LL_INFO10000,"D:IAHOL DMI: dmi:0x%p\n", dmi));
1396513942

1396613943
HRESULT hr = S_OK;
1396713944

@@ -13981,7 +13958,7 @@ Debugger::InsertToMethodInfoList( DebuggerMethodInfo *dmi )
1398113958

1398213959
_ASSERTE((dmiPrev == NULL) || ((dmi->m_token == dmiPrev->m_token) && (dmi->m_module == dmiPrev->m_module)));
1398313960

13984-
LOG((LF_CORDB,LL_INFO10000,"D:IAHOL: current head of dmi list:0x%08x\n",dmiPrev));
13961+
LOG((LF_CORDB,LL_INFO10000,"D:IAHOL: current head of dmi list:0x%p\n",dmiPrev));
1398513962

1398613963
if (dmiPrev != NULL)
1398713964
{
@@ -14006,7 +13983,7 @@ Debugger::InsertToMethodInfoList( DebuggerMethodInfo *dmi )
1400613983
}
1400713984
#ifdef _DEBUG
1400813985
dmiPrev = m_pMethodInfos->GetMethodInfo(dmi->m_module, dmi->m_token);
14009-
LOG((LF_CORDB,LL_INFO10000,"D:IAHOL: new head of dmi list:0x%08x\n",
13986+
LOG((LF_CORDB,LL_INFO10000,"D:IAHOL: new head of dmi list:0x%p\n",
1401013987
dmiPrev));
1401113988
#endif //_DEBUG
1401213989

src/coreclr/debug/ee/debugger.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1604,10 +1604,6 @@ class DebuggerJitInfo
16041604
DWORD *which,
16051605
BOOL skipPrologs=FALSE);
16061606

1607-
// If a method has multiple copies of code (because of EnC or code-pitching),
1608-
// this returns the DJI corresponding to 'pbAddr'
1609-
DebuggerJitInfo *GetJitInfoByAddress(const BYTE *pbAddr );
1610-
16111607
void Init(TADDR newAddress);
16121608

16131609
#if defined(FEATURE_EH_FUNCLETS)

src/coreclr/debug/ee/frameinfo.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -601,13 +601,11 @@ DebuggerJitInfo * FrameInfo::GetJitInfoFromFrame() const
601601

602602
DebuggerJitInfo *ji = NULL;
603603

604-
// @todo - we shouldn't need both a MD and an IP here.
605604
EX_TRY
606605
{
607606
_ASSERTE(this->md != NULL);
608607
ji = g_pDebugger->GetJitInfo(this->md, (const BYTE*)GetControlPC(&(this->registers)));
609-
_ASSERTE(ji != NULL);
610-
_ASSERTE(ji->m_nativeCodeVersion.GetMethodDesc() == this->md);
608+
_ASSERTE(ji == NULL || ji->m_nativeCodeVersion.GetMethodDesc() == this->md);
611609
}
612610
EX_CATCH
613611
{

0 commit comments

Comments
 (0)