|
11 | 11 |
|
12 | 12 | using Microsoft.Diagnostics.DataContractReader.Contracts;
|
13 | 13 | using Microsoft.Diagnostics.DataContractReader.Contracts.Extensions;
|
| 14 | +using Microsoft.Diagnostics.DataContractReader.Contracts.StackWalkHelpers; |
14 | 15 |
|
15 | 16 | namespace Microsoft.Diagnostics.DataContractReader.Legacy;
|
16 | 17 |
|
@@ -612,8 +613,80 @@ int ISOSDacInterface.GetJitHelperFunctionName(ClrDataAddress ip, uint count, byt
|
612 | 613 | => _legacyImpl is not null ? _legacyImpl.GetJitHelperFunctionName(ip, count, name, pNeeded) : HResults.E_NOTIMPL;
|
613 | 614 | int ISOSDacInterface.GetJitManagerList(uint count, void* managers, uint* pNeeded)
|
614 | 615 | => _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 | + } |
615 | 629 | 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 | + } |
617 | 690 | int ISOSDacInterface.GetMethodDescData(ClrDataAddress addr, ClrDataAddress ip, DacpMethodDescData* data, uint cRevertedRejitVersions, DacpReJitData* rgRevertedRejitData, uint* pcNeededRevertedRejitData)
|
618 | 691 | {
|
619 | 692 | if (addr == 0)
|
|
0 commit comments