Skip to content

Commit 26fa166

Browse files
Merge pull request #17 from Lordfirespeed/embedded_pdb
Embedded PDB support
2 parents 485da56 + 683ece8 commit 26fa166

11 files changed

+326
-191
lines changed

.editorconfig

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# EditorConfig is awesome: https://EditorConfig.org
2+
root = true
3+
4+
[*]
5+
charset = utf-8
6+
trim_trailing_whitespace = true
7+
end_of_line = lf
8+
insert_final_newline = true
9+
indent_style = space
10+
11+
[*.{csproj,props,targets}.user]
12+
indent_size = 4
13+
14+
[*.{csproj,props,targets}]
15+
indent_size = 4
16+
17+
[*.cs]
18+
indent_size = 4

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33

44
# Specific includes
55

6+
## Editorconfig
7+
!.editorconfig
8+
69
## Build System/Scripts
710
!/.config/
811
!NuGet.Config

NetcodePatcher/CodeGen/ApplyPatchedAttributeILPP.cs

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using Cecilifier.Runtime;
55
using Mono.Cecil;
66
using Mono.Cecil.Cil;
7-
using Mono.Cecil.Rocks;
87
using Unity.CompilationPipeline.Common.Diagnostics;
98
using Unity.CompilationPipeline.Common.ILPostProcessing;
109
using Unity.Netcode.Editor.CodeGen;
@@ -18,24 +17,30 @@ public class ApplyPatchedAttributeILPP : ILPostProcessor
1817
public static readonly string AttributeNamespaceSuffix = "NetcodePatcher";
1918

2019
public static readonly string AttributeName = "NetcodePatchedAssemblyAttribute";
21-
22-
public override ILPostProcessor GetInstance() => this;
23-
24-
public override bool WillProcess(ICompiledAssembly compiledAssembly) => true;
2520

2621
private readonly List<DiagnosticMessage> m_Diagnostics = [];
2722
private PostProcessorAssemblyResolver m_AssemblyResolver;
28-
23+
24+
public override ILPostProcessor GetInstance()
25+
{
26+
return this;
27+
}
28+
29+
public override bool WillProcess(ICompiledAssembly compiledAssembly)
30+
{
31+
return true;
32+
}
33+
2934
// This function's implementation was written with the help of https://cecilifier.me/
3035
public override ILPostProcessResult? Process(ICompiledAssembly compiledAssembly)
3136
{
3237
if (!WillProcess(compiledAssembly)) return null;
33-
38+
3439
m_Diagnostics.Clear();
35-
36-
// read
40+
41+
// read
3742
var assemblyDefinition = CodeGenHelpers.AssemblyDefinitionFor(compiledAssembly, out m_AssemblyResolver);
38-
if (assemblyDefinition == null)
43+
if (assemblyDefinition is null)
3944
{
4045
m_Diagnostics.AddError($"Cannot read assembly definition: {compiledAssembly.Name}");
4146
return null;
@@ -49,25 +54,42 @@ public class ApplyPatchedAttributeILPP : ILPostProcessor
4954
assemblyDefinition.MainModule.ImportReference(typeof(Attribute))
5055
);
5156
assemblyDefinition.MainModule.Types.Add(cls_NetcodePatchedAttribute);
52-
57+
5358
// Add AttributeUsage(AttributeTargets.Assembly) to NetcodePatchedAttribute
54-
var attr_AttributeUsage = new CustomAttribute(assemblyDefinition.MainModule.ImportReference(typeof(AttributeUsageAttribute).GetConstructor([typeof(AttributeTargets)])));
55-
attr_AttributeUsage.ConstructorArguments.Add(new CustomAttributeArgument(assemblyDefinition.MainModule.ImportReference(typeof(AttributeTargets)), 4));
59+
var attr_AttributeUsage = new CustomAttribute(
60+
assemblyDefinition.MainModule.ImportReference(
61+
typeof(AttributeUsageAttribute).GetConstructor([typeof(AttributeTargets)])
62+
)
63+
);
64+
attr_AttributeUsage.ConstructorArguments.Add(
65+
new CustomAttributeArgument(assemblyDefinition.MainModule.ImportReference(typeof(AttributeTargets)), 4)
66+
);
5667
cls_NetcodePatchedAttribute.CustomAttributes.Add(attr_AttributeUsage);
57-
68+
5869
// Method : NetcodePatchedAttribute.ctor
59-
var ctor_NetcodePatchedAttribute = new MethodDefinition(".ctor", MethodAttributes.Assembly | MethodAttributes.RTSpecialName | MethodAttributes.SpecialName | MethodAttributes.HideBySig, assemblyDefinition.MainModule.TypeSystem.Void);
70+
var ctor_NetcodePatchedAttribute = new MethodDefinition(
71+
".ctor",
72+
MethodAttributes.Assembly | MethodAttributes.RTSpecialName | MethodAttributes.SpecialName |
73+
MethodAttributes.HideBySig, assemblyDefinition.MainModule.TypeSystem.Void
74+
);
6075
cls_NetcodePatchedAttribute.Methods.Add(ctor_NetcodePatchedAttribute);
6176
ctor_NetcodePatchedAttribute.Body.InitLocals = true;
6277
var il_ctor_NetcodePatchedAttribute = ctor_NetcodePatchedAttribute.Body.GetILProcessor();
6378
il_ctor_NetcodePatchedAttribute.Emit(OpCodes.Ldarg_0);
64-
il_ctor_NetcodePatchedAttribute.Emit(OpCodes.Call, assemblyDefinition.MainModule.ImportReference(TypeHelpers.DefaultCtorFor(cls_NetcodePatchedAttribute.BaseType)));
79+
il_ctor_NetcodePatchedAttribute.Emit(
80+
OpCodes.Call,
81+
assemblyDefinition.MainModule.ImportReference(
82+
TypeHelpers.DefaultCtorFor(cls_NetcodePatchedAttribute.BaseType)
83+
)
84+
);
6585
il_ctor_NetcodePatchedAttribute.Emit(OpCodes.Ret);
66-
86+
6787
// Add NetcodePatchedAttribute to assembly definition
68-
var attribute = new CustomAttribute(assemblyDefinition.MainModule.ImportReference(TypeHelpers.DefaultCtorFor(cls_NetcodePatchedAttribute)));
88+
var attribute = new CustomAttribute(
89+
assemblyDefinition.MainModule.ImportReference(TypeHelpers.DefaultCtorFor(cls_NetcodePatchedAttribute))
90+
);
6991
assemblyDefinition.CustomAttributes.Add(attribute);
70-
92+
7193
// write
7294
var pe = new MemoryStream();
7395
var pdb = new MemoryStream();
@@ -80,7 +102,7 @@ public class ApplyPatchedAttributeILPP : ILPostProcessor
80102
};
81103

82104
assemblyDefinition.Write(pe, writerParameters);
83-
105+
84106
return new ILPostProcessResult(new InMemoryAssembly(pe.ToArray(), pdb.ToArray()), m_Diagnostics);
85107
}
86-
}
108+
}
Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,63 @@
11
using System;
22
using System.IO;
3+
using System.Reflection.PortableExecutable;
4+
using Microsoft.DiaSymReader.Tools;
5+
using NetcodePatcher.Extensions;
6+
using Serilog;
37
using Unity.CompilationPipeline.Common.ILPostProcessing;
48

59
namespace NetcodePatcher.CodeGen;
610

711
public class CompiledAssemblyFromFile : ICompiledAssembly
812
{
9-
readonly string _assemblyPath;
13+
private readonly string _assemblyPath;
14+
15+
public CompiledAssemblyFromFile(string assemblyPath)
16+
{
17+
_assemblyPath = assemblyPath;
18+
using var peSrcStream = new FileStream(assemblyPath, FileMode.Open, FileAccess.Read);
19+
20+
var pdbData = ReadPdb(peSrcStream);
21+
22+
peSrcStream.Seek(0, SeekOrigin.Begin);
23+
using var peStream = new MemoryStream();
24+
peSrcStream.CopyTo(peStream);
25+
var peData = peStream.ToArray();
26+
27+
InMemoryAssembly = new InMemoryAssembly(peData, pdbData);
28+
}
29+
30+
public bool DebugSymbolsAreEmbedded { get; private set; }
31+
public string? PortableDebugSymbolsFilePath { get; private set; }
1032

1133
public string Name => Path.GetFileNameWithoutExtension(_assemblyPath);
1234
public string[] References { get; set; } = Array.Empty<string>();
1335
public string[] Defines { get; set; } = Array.Empty<string>();
1436
public InMemoryAssembly InMemoryAssembly { get; }
1537

16-
public CompiledAssemblyFromFile(string assemblyPath)
38+
public byte[] ReadPdb(FileStream peStream)
1739
{
18-
_assemblyPath = assemblyPath;
19-
byte[] peData = File.ReadAllBytes(assemblyPath);
20-
string pdbFileName = Path.GetFileNameWithoutExtension(assemblyPath) + ".pdb";
40+
using var peReader = new PEReader(peStream, PEStreamOptions.LeaveOpen);
41+
var assemblyName = Path.GetFileNameWithoutExtension(_assemblyPath);
2142

22-
// if pdb is not found, try reading embedded pdb (?)
43+
if (!peReader.TryOpenAssociatedPortablePdb(_assemblyPath, File.OpenRead, out var pdbReaderProvider, out var pdbPath))
44+
throw new InvalidDataException(
45+
$"Failed to discover portable debug information for {Path.GetFileName(_assemblyPath)}"
46+
);
2347

24-
byte[] pdbData = File.ReadAllBytes(Path.Combine(Path.GetDirectoryName(assemblyPath)!, pdbFileName));
25-
InMemoryAssembly = new InMemoryAssembly(peData, pdbData);
48+
var pdbReader = pdbReaderProvider!.GetMetadataReader();
49+
50+
if (pdbPath is null)
51+
{
52+
Log.Information("Found embedded debug info : ({AssemblyName})", assemblyName);
53+
DebugSymbolsAreEmbedded = true;
54+
}
55+
else
56+
{
57+
Log.Information("Found debug info : ({PdbFileName})", Path.GetFileName(pdbPath));
58+
PortableDebugSymbolsFilePath = pdbPath;
59+
}
60+
61+
return pdbReader.ReadAllBytes();
2662
}
27-
}
63+
}
Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,19 @@
11
using System;
22
using Unity.CompilationPipeline.Common.ILPostProcessing;
33

4-
namespace NetcodePatcher.CodeGen
4+
namespace NetcodePatcher.CodeGen;
5+
6+
public class CompiledAssemblyFromInMemoryAssembly : ICompiledAssembly
57
{
6-
public class CompiledAssemblyFromInMemoryAssembly : ICompiledAssembly
8+
public CompiledAssemblyFromInMemoryAssembly(InMemoryAssembly inMemoryAssembly, string name = "")
79
{
8-
readonly string _assemblyName;
9-
public string Name => _assemblyName;
10-
public string[] References { get; set; } = Array.Empty<string>();
11-
public string[] Defines { get; set; } = Array.Empty<string>();
12-
public InMemoryAssembly InMemoryAssembly { get; }
10+
InMemoryAssembly = inMemoryAssembly;
11+
Name = name;
12+
}
1313

14-
public CompiledAssemblyFromInMemoryAssembly(InMemoryAssembly inMemoryAssembly, string name = "")
15-
{
16-
InMemoryAssembly = inMemoryAssembly;
17-
_assemblyName = name;
18-
}
14+
public string Name { get; }
1915

20-
}
16+
public string[] References { get; set; } = Array.Empty<string>();
17+
public string[] Defines { get; set; } = Array.Empty<string>();
18+
public InMemoryAssembly InMemoryAssembly { get; }
2119
}

NetcodePatcher/CodeGen/ILPostProcessorFromFile.cs

Lines changed: 0 additions & 138 deletions
This file was deleted.

0 commit comments

Comments
 (0)