Skip to content

Commit ffe8967

Browse files
authored
[cDAC] Implement ISOSDacInterface::GetJumpThunkTarget (#117781)
* implement GetJumpThunkTarget
1 parent 028b30f commit ffe8967

File tree

2 files changed

+83
-1
lines changed

2 files changed

+83
-1
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
namespace Microsoft.Diagnostics.DataContractReader.Legacy;
5+
6+
internal static class CorDbgHResults
7+
{
8+
public const int CORDBG_E_READVIRTUAL_FAILURE = unchecked((int)0x80131c49);
9+
}

src/native/managed/cdac/mscordaccore_universal/Legacy/SOSDacImpl.cs

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
using Microsoft.Diagnostics.DataContractReader.Contracts;
1313
using Microsoft.Diagnostics.DataContractReader.Contracts.Extensions;
14+
using Microsoft.Diagnostics.DataContractReader.Contracts.StackWalkHelpers;
1415

1516
namespace Microsoft.Diagnostics.DataContractReader.Legacy;
1617

@@ -612,8 +613,80 @@ int ISOSDacInterface.GetJitHelperFunctionName(ClrDataAddress ip, uint count, byt
612613
=> _legacyImpl is not null ? _legacyImpl.GetJitHelperFunctionName(ip, count, name, pNeeded) : HResults.E_NOTIMPL;
613614
int ISOSDacInterface.GetJitManagerList(uint count, void* managers, uint* pNeeded)
614615
=> _legacyImpl is not null ? _legacyImpl.GetJitManagerList(count, managers, pNeeded) : HResults.E_NOTIMPL;
616+
617+
private bool IsJumpRel64(TargetPointer pThunk)
618+
=> 0x48 == _target.Read<byte>(pThunk) &&
619+
0xB8 == _target.Read<byte>(pThunk + 1) &&
620+
0xFF == _target.Read<byte>(pThunk + 10) &&
621+
0xE0 == _target.Read<byte>(pThunk + 11);
622+
623+
private TargetPointer DecodeJump64(TargetPointer pThunk)
624+
{
625+
Debug.Assert(IsJumpRel64(pThunk), "Expected a jump thunk");
626+
627+
return _target.ReadPointer(pThunk + 2);
628+
}
615629
int ISOSDacInterface.GetJumpThunkTarget(void* ctx, ClrDataAddress* targetIP, ClrDataAddress* targetMD)
616-
=> _legacyImpl is not null ? _legacyImpl.GetJumpThunkTarget(ctx, targetIP, targetMD) : HResults.E_NOTIMPL;
630+
{
631+
if (ctx == null || targetIP == null || targetMD == null)
632+
{
633+
return HResults.E_INVALIDARG;
634+
}
635+
636+
int hr = HResults.S_OK;
637+
try
638+
{
639+
// API is implemented for x64 only
640+
if (_target.Contracts.RuntimeInfo.GetTargetArchitecture() == RuntimeInfoArchitecture.X64)
641+
{
642+
IPlatformAgnosticContext context = IPlatformAgnosticContext.GetContextForPlatform(_target);
643+
644+
// Context is not stored in the target, but in our own process
645+
context.FillFromBuffer(new Span<byte>(ctx, (int)context.Size));
646+
TargetPointer pThunk = context.InstructionPointer;
647+
648+
if (IsJumpRel64(pThunk))
649+
{
650+
*targetMD = 0;
651+
*targetIP = DecodeJump64(pThunk).ToClrDataAddress(_target);
652+
}
653+
else
654+
{
655+
hr = HResults.E_FAIL;
656+
}
657+
}
658+
else
659+
{
660+
hr = HResults.E_FAIL;
661+
}
662+
}
663+
catch (InvalidOperationException)
664+
{
665+
// If the target read fails, expect HResult to be CORDBG_E_READVIRTUAL_FAILURE
666+
hr = CorDbgHResults.CORDBG_E_READVIRTUAL_FAILURE;
667+
}
668+
catch (System.Exception ex)
669+
{
670+
hr = ex.HResult;
671+
}
672+
673+
#if DEBUG
674+
if (_legacyImpl is not null)
675+
{
676+
ClrDataAddress targetIPLocal;
677+
ClrDataAddress targetMDLocal;
678+
int hrLocal = _legacyImpl.GetJumpThunkTarget(ctx, &targetIPLocal, &targetMDLocal);
679+
Debug.Assert(hrLocal == hr, $"cDAC: {hr:x}, DAC: {hrLocal:x}");
680+
if (hr == HResults.S_OK)
681+
{
682+
Debug.Assert(*targetIP == targetIPLocal, $"cDAC: {*targetIP:x}, DAC: {targetIPLocal:x}");
683+
Debug.Assert(*targetMD == targetMDLocal, $"cDAC: {*targetMD:x}, DAC: {targetMDLocal:x}");
684+
}
685+
}
686+
#endif
687+
688+
return hr;
689+
}
617690
int ISOSDacInterface.GetMethodDescData(ClrDataAddress addr, ClrDataAddress ip, DacpMethodDescData* data, uint cRevertedRejitVersions, DacpReJitData* rgRevertedRejitData, uint* pcNeededRevertedRejitData)
618691
{
619692
if (addr == 0)

0 commit comments

Comments
 (0)