Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[release/9.0-staging] [debugger] Support step into a tail call #110438

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 21 additions & 4 deletions src/coreclr/debug/ee/controller.cpp
Original file line number Diff line number Diff line change
@@ -25,6 +25,11 @@ const char *GetTType( TraceType tt);

#define IsSingleStep(exception) ((exception) == EXCEPTION_SINGLE_STEP)

typedef enum __TailCallFunctionType {
TailCallThatReturns = 1,
StoreTailCallArgs = 2
} TailCallFunctionType;

// -------------------------------------------------------------------------
// DebuggerController routines
// -------------------------------------------------------------------------
@@ -5631,10 +5636,10 @@ static bool IsTailCallJitHelper(const BYTE * ip)
// control flow will be a little peculiar in that the function will return
// immediately, so we need special handling in the debugger for it. This
// function detects that case to be used for those scenarios.
static bool IsTailCallThatReturns(const BYTE * ip, ControllerStackInfo* info)
static bool IsTailCall(const BYTE * ip, ControllerStackInfo* info, TailCallFunctionType type)
{
MethodDesc* pTailCallDispatcherMD = TailCallHelp::GetTailCallDispatcherMD();
if (pTailCallDispatcherMD == NULL)
if (pTailCallDispatcherMD == NULL && type == TailCallFunctionType::TailCallThatReturns)
{
return false;
}
@@ -5650,6 +5655,11 @@ static bool IsTailCallThatReturns(const BYTE * ip, ControllerStackInfo* info)
? trace.GetMethodDesc()
: g_pEEInterface->GetNativeCodeMethodDesc(trace.GetAddress());

if (type == TailCallFunctionType::StoreTailCallArgs)
{
return (pTargetMD->IsDynamicMethod() && pTargetMD->AsDynamicMethodDesc()->GetILStubType() == DynamicMethodDesc::StubTailCallStoreArgs);
}

if (pTargetMD != pTailCallDispatcherMD)
{
return false;
@@ -5881,6 +5891,13 @@ bool DebuggerStepper::TrapStep(ControllerStackInfo *info, bool in)
fCallingIntoFunclet = IsAddrWithinMethodIncludingFunclet(ji, info->m_activeFrame.md, walker.GetNextIP()) &&
((CORDB_ADDRESS)(SIZE_T)walker.GetNextIP() != ji->m_addrOfCode);
#endif
// If we are stepping into a tail call that uses the StoreTailCallArgs
// we need to enable the method enter, otherwise it will behave like a resume
if (in && IsTailCall(walker.GetNextIP(), info, TailCallFunctionType::StoreTailCallArgs))
{
EnableMethodEnter();
return true;
}
// At this point, we know that the call/branch target is not
// in the current method. The possible cases is that this is
// a jump or a tailcall-via-helper. There are two separate
@@ -5892,7 +5909,7 @@ bool DebuggerStepper::TrapStep(ControllerStackInfo *info, bool in)
// is done by stepping out to the previous user function
// (non IL stub).
if ((fIsJump && !fCallingIntoFunclet) || IsTailCallJitHelper(walker.GetNextIP()) ||
IsTailCallThatReturns(walker.GetNextIP(), info))
IsTailCall(walker.GetNextIP(), info, TailCallFunctionType::TailCallThatReturns))
{
// A step-over becomes a step-out for a tail call.
if (!in)
@@ -6038,7 +6055,7 @@ bool DebuggerStepper::TrapStep(ControllerStackInfo *info, bool in)
return true;
}

if (IsTailCallJitHelper(walker.GetNextIP()) || IsTailCallThatReturns(walker.GetNextIP(), info))
if (IsTailCallJitHelper(walker.GetNextIP()) || IsTailCall(walker.GetNextIP(), info, TailCallFunctionType::TailCallThatReturns))
{
if (!in)
{

Unchanged files with check annotations Beta

<!-- Use IgnoreStandardErrorWarningFormat because Arcade sets WarnAsError and there's an existing warning in the native build. -->
<Message Text="Executing &quot;$(MSBuildThisFileDirectory)$(_CoreClrBuildScript)&quot; @(_CoreClrBuildArg->'%(Identity)',' ')" Importance="High" />
<Exec Command="&quot;$(MSBuildThisFileDirectory)$(_CoreClrBuildScript)&quot; @(_CoreClrBuildArg->'%(Identity)',' ')"

Check failure on line 108 in src/coreclr/runtime.proj

Azure Pipelines / runtime (Build linux-armel checked CoreCLR_NonPortable)

src/coreclr/runtime.proj#L108

src/coreclr/runtime.proj(108,5): error MSB3073: (NETCORE_ENGINEERING_TELEMETRY=Build) The command ""/__w/1/s/src/coreclr/build-runtime.sh" -armel -checked -ci -cross -portablebuild=false -os linux -outputrid tizen.9.0.0-armel -cmakeargs "-DCLR_DOTNET_HOST_PATH=/__w/1/s/.dotnet/dotnet" -cmakeargs "-DCDAC_BUILD_TOOL_BINARY_PATH=/__w/1/s/artifacts/bin/coreclr/linux.armel.Checked/cdac-build-tool/cdac-build-tool.dll"" exited with code 1.

Check failure on line 108 in src/coreclr/runtime.proj

Azure Pipelines / runtime

src/coreclr/runtime.proj#L108

src/coreclr/runtime.proj(108,5): error MSB3073: (NETCORE_ENGINEERING_TELEMETRY=Build) The command ""/__w/1/s/src/coreclr/build-runtime.sh" -armel -checked -ci -cross -portablebuild=false -os linux -outputrid tizen.9.0.0-armel -cmakeargs "-DCLR_DOTNET_HOST_PATH=/__w/1/s/.dotnet/dotnet" -cmakeargs "-DCDAC_BUILD_TOOL_BINARY_PATH=/__w/1/s/artifacts/bin/coreclr/linux.armel.Checked/cdac-build-tool/cdac-build-tool.dll"" exited with code 1.
IgnoreStandardErrorWarningFormat="true" />
</Target>