Skip to content

Commit b311bae

Browse files
author
Popax21
committed
Implement deep CustomDebugInformations copy
Previously, `AsyncMethodBodyDebugInformation` and `StateMachineScopeDebugInformation` instances of cloned method bodys would still refer to the old method bodies, which could cause the PDB instruction offsets to desync. This change fixes this by explicitly cloning them along with the method body.
1 parent b1806f5 commit b311bae

File tree

1 file changed

+26
-2
lines changed

1 file changed

+26
-2
lines changed

Utils/Extensions.Relinker.cs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,33 @@ public static MethodBody Clone(this MethodBody bo, MethodDefinition m) {
120120
}));
121121

122122
#if !CECIL0_9
123-
m.CustomDebugInformations.AddRange(bo.Method.CustomDebugInformations); // Abstract. TODO: Implement deep CustomDebugInformations copy.
123+
Instruction ResolveInstrOff(int off) {
124+
// Can't check cloned instruction offsets directly, as those can change for some reason
125+
for (int i = 0; i < bo.Instructions.Count; i++)
126+
if (bo.Instructions[i].Offset == off)
127+
return bc.Instructions[i];
128+
throw new ArgumentException($"Invalid instruction offset {off}");
129+
}
130+
131+
m.CustomDebugInformations.AddRange(bo.Method.CustomDebugInformations.Select(o => {
132+
if (o is AsyncMethodBodyDebugInformation ao) {
133+
AsyncMethodBodyDebugInformation c = new AsyncMethodBodyDebugInformation();
134+
if (ao.CatchHandler.Offset >= 0)
135+
c.CatchHandler = ao.CatchHandler.IsEndOfMethod ? new InstructionOffset() : new InstructionOffset(ResolveInstrOff(ao.CatchHandler.Offset));
136+
c.Yields.AddRange(ao.Yields.Select(off => off.IsEndOfMethod ? new InstructionOffset() : new InstructionOffset(ResolveInstrOff(off.Offset))));
137+
c.Resumes.AddRange(ao.Resumes.Select(off => off.IsEndOfMethod ? new InstructionOffset() : new InstructionOffset(ResolveInstrOff(off.Offset))));
138+
c.ResumeMethods.AddRange(ao.ResumeMethods);
139+
return c;
140+
} else if (o is StateMachineScopeDebugInformation so) {
141+
StateMachineScopeDebugInformation c = new StateMachineScopeDebugInformation();
142+
c.Scopes.AddRange(so.Scopes.Select(s => new StateMachineScope(ResolveInstrOff(s.Start.Offset), s.End.IsEndOfMethod ? null : ResolveInstrOff(s.End.Offset))));
143+
return c;
144+
} else
145+
return o;
146+
}));
147+
124148
m.DebugInformation.SequencePoints.AddRange(bo.Method.DebugInformation.SequencePoints.Select(o => {
125-
SequencePoint c = new SequencePoint(bc.Instructions.FirstOrDefault(i => i.Offset == o.Offset), o.Document);
149+
SequencePoint c = new SequencePoint(ResolveInstrOff(o.Offset), o.Document);
126150
c.StartLine = o.StartLine;
127151
c.StartColumn = o.StartColumn;
128152
c.EndLine = o.EndLine;

0 commit comments

Comments
 (0)