Skip to content

Commit

Permalink
Update Cecil submodule to latest
Browse files Browse the repository at this point in the history
Read embedded pdbs

Copy debug information for scopes and imports
Taken from Alexx999#3

Make the output assembly MVID deterministic

Fix test locking dlls
Add .ToArray() to flush the Linq expression so that it is not evaluated more than once.

Better error if the pdb doesn't exist

Use cecil from https://github.com/KirillOsenkov/cecil/tree/ilrepack
  • Loading branch information
KirillOsenkov committed Dec 29, 2023
1 parent 96a60b6 commit 8ebc6f9
Show file tree
Hide file tree
Showing 14 changed files with 205 additions and 49 deletions.
3 changes: 2 additions & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
[submodule "cecil"]
path = cecil
url = https://github.com/gluck/cecil.git
url = https://github.com/KirillOsenkov/cecil
branch = ilrepack
4 changes: 4 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
<Project>

<PropertyGroup>
<LangVersion>latest</LangVersion>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" />
</ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion ILRepack.IntegrationTests/NuGet/RepackNuGetTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ public void VerifiesMergedPdbUnchangedSourceIndexationForTfsIndexation()
{
// This test requires Mono.Cecil.Pdb.dll. Indicate a dependency such that
// the reference is not accidentally removed.
_ = typeof(Mono.Cecil.Pdb.PdbReader);
_ = typeof(Mono.Cecil.Pdb.PdbReaderProvider);

var platform = Platform.From(
Package.From("TfsIndexer", "1.2.4"),
Expand Down
12 changes: 10 additions & 2 deletions ILRepack.IntegrationTests/NuGet/TestHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,20 @@ public static void DoRepackForCmd(IEnumerable<string> args)

private static void ReloadAndCheckReferences(RepackOptions repackOptions)
{
var outputFile = AssemblyDefinition.ReadAssembly(repackOptions.OutputFile, new ReaderParameters(ReadingMode.Immediate));
var mergedFiles = repackOptions.ResolveFiles().Select(f => AssemblyDefinition.ReadAssembly(f, new ReaderParameters(ReadingMode.Deferred)));
using var ar = new DefaultAssemblyResolver();
using var outputFile = AssemblyDefinition.ReadAssembly(repackOptions.OutputFile, new ReaderParameters(ReadingMode.Immediate));
var mergedFiles = repackOptions
.ResolveFiles()
.Select(f => AssemblyDefinition.ReadAssembly(f, new ReaderParameters(ReadingMode.Deferred)))
.ToArray();
foreach (var a in outputFile.MainModule.AssemblyReferences.Where(x => mergedFiles.Any(y => repackOptions.KeepOtherVersionReferences ? x.FullName == y.FullName : x.Name == y.Name.Name)))
{
Assert.Fail($"Merged assembly retains a reference to one (or more) of the merged files: {a.FullName}");
}
foreach (var a in mergedFiles)
{
a.Dispose();
}
}

public static void SaveAs(Stream input, string directory, string fileName)
Expand Down
32 changes: 14 additions & 18 deletions ILRepack/IKVMLineIndexer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ internal class IKVMLineIndexer
{
private readonly IRepackContext repack;
private bool enabled;
private LineNumberWriter lineNumberWriter;
private string fileName;
private TypeReference sourceFileAttributeTypeReference;
private TypeReference lineNumberTableAttributeTypeReference;
Expand All @@ -41,29 +40,29 @@ public IKVMLineIndexer(IRepackContext ilRepack, bool doLineIndexing)

public void Reset()
{
lineNumberWriter = null;
fileName = null;
}

public void PreMethodBodyRepack(MethodBody body, MethodDefinition parent)
{
if (!enabled)
if (!enabled || !parent.DebugInformation.HasSequencePoints)
return;

Reset();
if (!parent.CustomAttributes.Any(x => x.Constructor.DeclaringType.Name == "LineNumberTableAttribute"))
{
lineNumberWriter = new LineNumberWriter(body.Instructions.Count / 4);
var lineNumberWriter = new LineNumberWriter(body.Instructions.Count / 4);
foreach (var sp in parent.DebugInformation.SequencePoints)
{
AddSeqPoint(sp, lineNumberWriter);
}
PostMethodBodyRepack(parent, lineNumberWriter);
}
}

public void ProcessMethodBodyInstruction(Instruction instr)
private void AddSeqPoint(SequencePoint currentSeqPoint, LineNumberWriter lineNumberWriter)
{
if (!enabled)
return;

var currentSeqPoint = instr.SequencePoint;
if (lineNumberWriter != null && currentSeqPoint != null)
if (currentSeqPoint != null)
{
if (fileName == null && currentSeqPoint.Document != null)
{
Expand All @@ -84,25 +83,22 @@ public void ProcessMethodBodyInstruction(Instruction instr)
{
if (lineNumberWriter.LineNo > 0)
{
lineNumberWriter.AddMapping(instr.Offset, -1);
lineNumberWriter.AddMapping(currentSeqPoint.Offset, -1);
}
}
else
{
if (lineNumberWriter.LineNo != currentSeqPoint.StartLine)
{
lineNumberWriter.AddMapping(instr.Offset, currentSeqPoint.StartLine);
lineNumberWriter.AddMapping(currentSeqPoint.Offset, currentSeqPoint.StartLine);
}
}
}
}

public void PostMethodBodyRepack(MethodDefinition parent)
private void PostMethodBodyRepack(MethodDefinition parent, LineNumberWriter lineNumberWriter)
{
if (!enabled)
return;

if (lineNumberWriter != null && lineNumberWriter.Count > 0)
if (lineNumberWriter.Count > 0)
{
CustomAttribute ca;
if (lineNumberWriter.Count == 1)
Expand Down Expand Up @@ -155,7 +151,7 @@ public void PostRepackReferences()
IMetadataScope ikvmRuntimeReference = repack.TargetAssemblyMainModule.AssemblyReferences.FirstOrDefault(r => r.Name == "IKVM.Runtime");
if (ikvmRuntimeReference == null)
{
ikvmRuntimeReference = repack.MergeScope(repack.GlobalAssemblyResolver.Resolve("IKVM.Runtime").Name);
ikvmRuntimeReference = repack.MergeScope(repack.GlobalAssemblyResolver.Resolve(new AssemblyNameReference("IKVM.Runtime", null)).Name);
}
if (ikvmRuntimeReference == null)
{
Expand Down
38 changes: 29 additions & 9 deletions ILRepack/ILRepack.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
using System.Text.RegularExpressions;
using ILRepacking.Steps;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Cecil.PE;
using Mono.Unix.Native;
using ILRepacking.Mixins;
Expand Down Expand Up @@ -112,9 +113,10 @@ private AssemblyDefinitionContainer ReadInputAssembly(string assembly, bool isPr
{
ReaderParameters rp = new ReaderParameters(ReadingMode.Immediate) { AssemblyResolver = GlobalAssemblyResolver };
// read PDB/MDB?
if (Options.DebugInfo && (File.Exists(Path.ChangeExtension(assembly, "pdb")) || File.Exists(assembly + ".mdb")))
if (Options.DebugInfo)
{
rp.ReadSymbols = true;
rp.SymbolReaderProvider = new DefaultSymbolReaderProvider(throwIfNoSymbol: false);
}
AssemblyDefinition mergeAsm;
try
Expand Down Expand Up @@ -144,6 +146,7 @@ private AssemblyDefinitionContainer ReadInputAssembly(string assembly, bool isPr

if (!Options.AllowZeroPeKind && (mergeAsm.MainModule.Attributes & ModuleAttributes.ILOnly) == 0)
throw new ArgumentException("Failed to load assembly with Zero PeKind: " + assembly);
GlobalAssemblyResolver.RegisterAssembly(mergeAsm);

return new AssemblyDefinitionContainer
{
Expand Down Expand Up @@ -264,7 +267,6 @@ public void Repack()

// Read input assemblies only after all properties are set.
ReadInputAssemblies();
GlobalAssemblyResolver.RegisterAssemblies(MergedAssemblies);

_platformFixer = new PlatformFixer(this, PrimaryAssemblyMainModule.Runtime);
_mappingHandler = new MappingHandler();
Expand Down Expand Up @@ -309,7 +311,7 @@ public void Repack()
}
// set the main module attributes
TargetAssemblyMainModule.Attributes = PrimaryAssemblyMainModule.Attributes;
TargetAssemblyMainModule.Win32ResourceDirectory = MergeWin32Resources(PrimaryAssemblyMainModule.Win32ResourceDirectory);
TargetAssemblyMainModule.Win32ResourceDirectory = MergeWin32Resources();

if (Options.Version != null)
TargetAssemblyDefinition.Name.Version = Options.Version;
Expand Down Expand Up @@ -337,10 +339,16 @@ public void Repack()
step.Perform();
}

var anySymbolReader = MergedAssemblies
.Select(m => m.MainModule.SymbolReader)
.Where(r => r != null)
.FirstOrDefault();
var parameters = new WriterParameters
{
StrongNameKeyPair = signingStep.KeyPair,
WriteSymbols = Options.DebugInfo
WriteSymbols = Options.DebugInfo,
SymbolWriterProvider = anySymbolReader?.GetWriterProvider(),
DeterministicMvid = true
};
// create output directory if it does not exist
var outputDir = Path.GetDirectoryName(Options.OutputFile);
Expand All @@ -350,11 +358,19 @@ public void Repack()
Directory.CreateDirectory(outputDir);
}

Logger.Info("Writing output assembly to disk");
TargetAssemblyDefinition.Write(Options.OutputFile, parameters);

sourceServerDataStep.Write();

Logger.Info("Writing output assembly to disk");
foreach (var assembly in MergedAssemblies)
{
assembly.Dispose();
}

TargetAssemblyDefinition.Dispose();
GlobalAssemblyResolver.Dispose();

// If this is an executable and we are on linux/osx we should copy file permissions from
// the primary assembly
if (isUnixEnvironment && (kind == ModuleKind.Console || kind == ModuleKind.Windows))
Expand Down Expand Up @@ -405,13 +421,17 @@ private void ResolveSearchDirectories()
}
}

private ResourceDirectory MergeWin32Resources(ResourceDirectory primary)
private ResourceDirectory MergeWin32Resources()
{
if (primary == null)
return null;
var primary = PrimaryAssemblyMainModule.ReadWin32ResourceDirectory() ?? new ResourceDirectory();

foreach (var ass in OtherAssemblies)
{
MergeDirectory(new List<ResourceEntry>(), primary, ass, ass.MainModule.Win32ResourceDirectory);
var directory = ass.MainModule.ReadWin32ResourceDirectory();
if (directory != null)
{
MergeDirectory(new List<ResourceEntry>(), primary, ass, directory);
}
}
return primary;
}
Expand Down
16 changes: 16 additions & 0 deletions ILRepack/Mixins/Mixins.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Collections.Generic;
using Mono.Collections.Generic;

namespace ILRepacking.Mixins
{
static class CollectionMixins
{
public static void AddRange<T>(this Collection<T> destination, IEnumerable<T> source)
{
foreach (var item in source)
{
destination.Add(item);
}
}
}
}
7 changes: 6 additions & 1 deletion ILRepack/PlatformFixer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ private void FixPlatformVersion(ParameterDefinition pd)
private void FixPlatformVersion(GenericParameter gp)
{
if (gp.HasConstraints)
foreach (TypeReference tr in gp.Constraints)
foreach (var tr in gp.Constraints)
FixPlatformVersion(tr);
if (gp.HasCustomAttributes)
foreach (CustomAttribute ca in gp.CustomAttributes)
Expand All @@ -202,6 +202,11 @@ private void FixPlatformVersion(GenericParameter gp)
FixPlatformVersion(gp1);
}

private void FixPlatformVersion(GenericParameterConstraint gp)
{
FixPlatformVersion(gp.ConstraintType);
}

private void FixPlatformVersion(CustomAttribute ca)
{
FixPlatformVersion(ca.Constructor);
Expand Down
17 changes: 15 additions & 2 deletions ILRepack/ReferenceFixator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,14 +111,27 @@ internal void FixMethodVisibility(TypeDefinition type)
FixOverridenMethodDef(meth);
}

private void FixReferences(Collection<GenericParameterConstraint> constraints)
{
foreach (var constraint in constraints)
{
constraint.ConstraintType = Fix(constraint.ConstraintType);
FixReferences(constraint.CustomAttributes);
}
}

internal void FixReferences(TypeDefinition type)
{
FixReferences(type.GenericParameters);

type.BaseType = Fix(type.BaseType);

// interfaces before methods, because methods will have to go through them
FixReferences(type.Interfaces);
foreach (InterfaceImplementation nested in type.Interfaces)
{
nested.InterfaceType = Fix(nested.InterfaceType);
FixReferences(nested.CustomAttributes);
}

// nested types first
foreach (TypeDefinition nested in type.NestedTypes)
Expand Down Expand Up @@ -332,7 +345,7 @@ private bool IsAnnotation(TypeDefinition typeAttribute)
{
if (typeAttribute == null)
return false;
if (typeAttribute.Interfaces.Any(@interface => @interface.FullName == "java.lang.annotation.Annotation"))
if (typeAttribute.Interfaces.Any(@interface => @interface.InterfaceType.FullName == "java.lang.annotation.Annotation"))
return true;
return typeAttribute.BaseType != null && IsAnnotation(typeAttribute.BaseType.Resolve());
}
Expand Down
8 changes: 2 additions & 6 deletions ILRepack/RepackAssemblyResolver.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
using Mono.Cecil;
using System.Collections.Generic;

namespace ILRepacking
{
public class RepackAssemblyResolver : DefaultAssemblyResolver
{
public void RegisterAssemblies(IList<AssemblyDefinition> mergedAssemblies)
public new void RegisterAssembly(AssemblyDefinition assembly)
{
foreach (var assemblyDefinition in mergedAssemblies)
{
RegisterAssembly(assemblyDefinition);
}
base.RegisterAssembly(assembly);
}
}
}
Loading

0 comments on commit 8ebc6f9

Please sign in to comment.