Skip to content
Open
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
71 changes: 71 additions & 0 deletions ILRepack/RepackImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ internal class RepackImporter : IRepackImporter, IRepackCopier
private readonly IRepackContext _repackContext;
private readonly RepackOptions _options;
private readonly Dictionary<AssemblyDefinition, int> _aspOffsets;
private readonly Dictionary<ImportDebugInformation, ImportDebugInformation> _importDebugInformations = new();
private readonly static Instruction _dummyInstruction = Instruction.Create(OpCodes.Nop);

public RepackImporter(
ILogger logger,
Expand Down Expand Up @@ -425,6 +427,9 @@ private void CloneTo(MethodDefinition meth, TypeDefinition type, bool typeJustCr

if (meth.HasBody)
CloneTo(meth.Body, nm);

nm.DebugInformation.Scope = CopyScope(meth.DebugInformation.Scope, nm, out _);

meth.Body = null; // frees memory

nm.IsAddOn = meth.IsAddOn;
Expand All @@ -434,6 +439,72 @@ private void CloneTo(MethodDefinition meth, TypeDefinition type, bool typeJustCr
nm.CallingConvention = meth.CallingConvention;
}

private ScopeDebugInformation CopyScope(ScopeDebugInformation scope, MethodDefinition nm, out bool copied)
{
copied = false;
if (scope is null || scope.Import is null && !scope.HasConstants && !scope.HasScopes)
return scope;

var ns = new ScopeDebugInformation(_dummyInstruction, null);
ns.Start = new InstructionOffset(scope.Start.Offset);
ns.End = scope.End.IsEndOfMethod ? default : new InstructionOffset(scope.End.Offset);
if (scope.HasCustomDebugInformations)
ns.CustomDebugInformations.AddRange(scope.CustomDebugInformations);
if (scope.HasVariables)
ns.Variables.AddRange(scope.Variables);
if (scope.HasScopes)
foreach (var ps in scope.Scopes)
{
ns.Scopes.Add(CopyScope(ps, nm, out var nc));
copied |= nc;
}
if (scope.HasConstants)
{
copied = true;
foreach (var pc in scope.Constants)
{
var nc = new ConstantDebugInformation(pc.Name, Import(pc.ConstantType, nm), pc.Value);
if (pc.HasCustomDebugInformations)
nc.CustomDebugInformations.AddRange(pc.CustomDebugInformations);
ns.Constants.Add(nc);
}
}
if (scope.Import is not null)
{
copied = true;
ns.Import = CopyImport(scope.Import, nm);
}

return copied ? ns : scope;
}

private ImportDebugInformation CopyImport(ImportDebugInformation import, MethodDefinition nm)
{
if (import is null)
return null;
if (_importDebugInformations.TryGetValue(import, out var ni))
return ni;

ni = new ImportDebugInformation();
ni.Parent = CopyImport(import.Parent, nm);
if (import.HasCustomDebugInformations)
ni.CustomDebugInformations.AddRange(import.CustomDebugInformations);
if (import.HasTargets)
foreach (var pt in import.Targets)
{
var nt = new ImportTarget(pt.Kind);
nt.Alias = pt.Alias;
nt.Namespace = pt.Namespace;
if (pt.Type is not null)
nt.Type = Import(pt.Type, nm);
if (pt.AssemblyReference is not null)
nt.AssemblyReference = _repackContext.PlatformFixer.FixPlatformVersion(pt.AssemblyReference) as AssemblyNameReference;
ni.Targets.Add(nt);
}
_importDebugInformations.Add(import, ni);
return ni;
}

private void CloneTo(MethodBody body, MethodDefinition parent)
{
MethodBody nb = new MethodBody(parent);
Expand Down