Skip to content

Commit aa6cca9

Browse files
authored
[cDAC] X86 support HijackFrame (#116829)
* x86 hijackframe support
1 parent 430ff53 commit aa6cca9

File tree

5 files changed

+47
-4
lines changed

5 files changed

+47
-4
lines changed

docs/design/datacontracts/StackWalk.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ This contract depends on the following descriptors:
5656
| `HijackFrame` | `HijackArgsPtr` | Pointer to the Frame's stored HijackArgs |
5757
| `HijackArgs` (amd64) | `CalleeSavedRegisters` | CalleeSavedRegisters data structure |
5858
| `HijackArgs` (amd64 Windows) | `Rsp` | Saved stack pointer |
59-
| `HijackArgs` (arm64) | For each register `r` saved in HijackArgs, `r` | Register names associated with stored register values |
59+
| `HijackArgs` (arm64/x86) | For each register `r` saved in HijackArgs, `r` | Register names associated with stored register values |
6060
| `CalleeSavedRegisters` | For each callee saved register `r`, `r` | Register names associated with stored register values |
6161
| `TailCallFrame` (x86 Windows) | `CalleeSavedRegisters` | CalleeSavedRegisters data structure |
6262
| `TailCallFrame` (x86 Windows) | `ReturnAddress` | Frame's stored instruction pointer |

src/coreclr/debug/runtimeinfo/datadescriptor.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,17 @@ CDAC_TYPE_FIELD(HijackArgs, /*pointer*/, X28, offsetof(HijackArgs, X28))
777777
CDAC_TYPE_FIELD(HijackArgs, /*pointer*/, Fp, offsetof(HijackArgs, X29))
778778
CDAC_TYPE_FIELD(HijackArgs, /*pointer*/, Lr, offsetof(HijackArgs, Lr))
779779

780+
#elif defined(TARGET_X86)
781+
782+
CDAC_TYPE_FIELD(HijackArgs, /*pointer*/, Edi, offsetof(HijackArgs, Edi))
783+
CDAC_TYPE_FIELD(HijackArgs, /*pointer*/, Esi, offsetof(HijackArgs, Esi))
784+
CDAC_TYPE_FIELD(HijackArgs, /*pointer*/, Ebx, offsetof(HijackArgs, Ebx))
785+
CDAC_TYPE_FIELD(HijackArgs, /*pointer*/, Edx, offsetof(HijackArgs, Edx))
786+
CDAC_TYPE_FIELD(HijackArgs, /*pointer*/, Ecx, offsetof(HijackArgs, Ecx))
787+
CDAC_TYPE_FIELD(HijackArgs, /*pointer*/, Eax, offsetof(HijackArgs, Eax))
788+
CDAC_TYPE_FIELD(HijackArgs, /*pointer*/, Ebp, offsetof(HijackArgs, Ebp))
789+
CDAC_TYPE_FIELD(HijackArgs, /*pointer*/, Eip, offsetof(HijackArgs, Eip))
790+
780791
#endif // Platform switch
781792
CDAC_TYPE_END(HijackArgs)
782793
#endif // FEATURE_HIJACK

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/ARM64FrameHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ void IPlatformFrameHandler.HandleHijackFrame(HijackFrame frame)
2828

2929
_holder.InstructionPointer = frame.ReturnAddress;
3030

31-
// The stack pointer is the address immediately following HijacksArgs
31+
// The stack pointer is the address immediately following HijackArgs
3232
uint hijackArgsSize = _target.GetTypeInfo(DataType.HijackArgs).Size ?? throw new InvalidOperationException("HijackArgs size is not set");
3333
Debug.Assert(hijackArgsSize % 8 == 0, "HijackArgs contains register values and should be a multiple of 8");
3434
// The stack must be multiple of 16. So if hijackArgsSize is not multiple of 16 then there must be padding of 8 bytes

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/X86FrameHandler.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,13 @@ public void HandleFaultingExceptionFrame(FaultingExceptionFrame frame)
2323

2424
public void HandleHijackFrame(HijackFrame frame)
2525
{
26-
// TODO(cdacX86): Implement handling for HijackFrame
27-
throw new NotImplementedException();
26+
HijackArgsX86 args = _target.ProcessedData.GetOrAdd<HijackArgsX86>(frame.HijackArgsPtr);
27+
28+
// The stack pointer is the address immediately following HijackArgs
29+
uint hijackArgsSize = _target.GetTypeInfo(DataType.HijackArgs).Size ?? throw new InvalidOperationException("HijackArgs size is not set");
30+
_context.Context.Esp = (uint)frame.HijackArgsPtr + hijackArgsSize;
31+
32+
UpdateFromRegisterDict(args.Registers);
2833
}
2934

3035
public override void HandleTailCallFrame(TailCallFrame frame)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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+
using System.Collections.Generic;
5+
6+
namespace Microsoft.Diagnostics.DataContractReader.Data;
7+
8+
internal class HijackArgsX86 : IData<HijackArgsX86>
9+
{
10+
static HijackArgsX86 IData<HijackArgsX86>.Create(Target target, TargetPointer address)
11+
=> new HijackArgsX86(target, address);
12+
13+
public HijackArgsX86(Target target, TargetPointer address)
14+
{
15+
Target.TypeInfo type = target.GetTypeInfo(DataType.HijackArgs);
16+
17+
Dictionary<string, TargetNUInt> registers = new Dictionary<string, TargetNUInt>(type.Fields.Count);
18+
foreach ((string name, Target.FieldInfo field) in type.Fields)
19+
{
20+
TargetNUInt value = target.ReadNUInt(address + (ulong)field.Offset);
21+
registers.Add(name, value);
22+
}
23+
Registers = registers;
24+
}
25+
26+
public IReadOnlyDictionary<string, TargetNUInt> Registers { get; }
27+
}

0 commit comments

Comments
 (0)