diff --git a/Source/Implementation/Implementation.csproj b/Source/Implementation/Implementation.csproj
index cc172a9..5c62b62 100644
--- a/Source/Implementation/Implementation.csproj
+++ b/Source/Implementation/Implementation.csproj
@@ -10,11 +10,9 @@
false
Prepatcher
PrepatcherImpl
+ embedded
-
- none
-
diff --git a/Source/Implementation/Loader.cs b/Source/Implementation/Loader.cs
index adff048..39a289e 100644
--- a/Source/Implementation/Loader.cs
+++ b/Source/Implementation/Loader.cs
@@ -103,7 +103,16 @@ private static void LoadAssembly(ModifiableAssembly asm)
{
Lg.Verbose($"Loading assembly: {asm}");
- var loadedAssembly = Assembly.Load(asm.Bytes);
+ Assembly loadedAssembly;
+ if (asm.SymbolsLoaded)
+ {
+ Lg.Verbose($"Loading assembly with symbols: {asm}: ");
+ loadedAssembly = Assembly.Load(asm.Bytes, asm.SymbolBytes);
+ }
+ else
+ {
+ loadedAssembly = Assembly.Load(asm.Bytes);
+ }
if (loadedAssembly.GetName().Name == AssemblyCollector.AssemblyCSharp)
{
newAsm = loadedAssembly;
diff --git a/Source/Implementation/Patches/AssemblyLoadingFreePatch.cs b/Source/Implementation/Patches/AssemblyLoadingFreePatch.cs
index d0d9821..24b254f 100644
--- a/Source/Implementation/Patches/AssemblyLoadingFreePatch.cs
+++ b/Source/Implementation/Patches/AssemblyLoadingFreePatch.cs
@@ -30,16 +30,6 @@ public static Assembly LoadFrom(string filePath)
if (asmWithName != null)
return asmWithName;
- var rawAssembly = File.ReadAllBytes(filePath);
- var fileInfo = new FileInfo(Path.Combine(Path.GetDirectoryName(filePath)!, Path.GetFileNameWithoutExtension(filePath)) + ".pdb");
- if (fileInfo.Exists)
- {
- var rawSymbolStore = File.ReadAllBytes(fileInfo.FullName);
- return AppDomain.CurrentDomain.Load(rawAssembly, rawSymbolStore);
- }
- else
- {
- return AppDomain.CurrentDomain.Load(rawAssembly);
- }
+ return Assembly.LoadFrom(filePath);
}
}
diff --git a/Source/Implementation/Process/ModifiableAssembly.cs b/Source/Implementation/Process/ModifiableAssembly.cs
index abdc4b6..1bf628a 100644
--- a/Source/Implementation/Process/ModifiableAssembly.cs
+++ b/Source/Implementation/Process/ModifiableAssembly.cs
@@ -1,6 +1,9 @@
using System.IO;
using System.Reflection;
using Mono.Cecil;
+using Mono.Cecil.Cil;
+using Mono.Cecil.Pdb;
+using Verse;
namespace Prepatcher.Process;
@@ -21,6 +24,10 @@ public class ModifiableAssembly
public byte[]? Bytes { get; private set; }
private byte[]? RawBytes { get; }
+ public byte[]? SymbolBytes { get; private set; }
+
+ public bool SymbolsLoaded { get; private set; }
+
private bool needsReload;
public ModifiableAssembly(string ownerName, string friendlyName, Assembly sourceAssembly, IAssemblyResolver resolver)
@@ -28,24 +35,86 @@ public ModifiableAssembly(string ownerName, string friendlyName, Assembly source
OwnerName = ownerName;
FriendlyName = friendlyName;
SourceAssembly = sourceAssembly;
-
RawBytes = UnsafeAssembly.GetRawData(sourceAssembly);
- AsmDefinition = AssemblyDefinition.ReadAssembly(
- new MemoryStream(RawBytes),
- new ReaderParameters
+ if (sourceAssembly.Location != "")
+ {
+ try
{
- AssemblyResolver = resolver
- });
+ AsmDefinition = AssemblyDefinition.ReadAssembly(sourceAssembly.Location, new ReaderParameters
+ {
+ AssemblyResolver = resolver,
+ ReadSymbols = true,
+ InMemory = true
+ });
+ SymbolsLoaded = true;
+ CheckSymbols();
+
+
+ }
+ catch (Exception e)
+ {
+ AsmDefinition = AssemblyDefinition.ReadAssembly(sourceAssembly.Location, new ReaderParameters
+ {
+ AssemblyResolver = resolver,
+ ReadSymbols = false,
+ InMemory = true
+ });
+ SymbolsLoaded = false;
+ }
+ }
+ else
+ {
+ try
+ {
+ AsmDefinition = AssemblyDefinition.ReadAssembly(
+ new MemoryStream(RawBytes),
+ new ReaderParameters
+ {
+ AssemblyResolver = resolver,
+ ReadSymbols = true,
+ });
+ SymbolsLoaded = true;
+ CheckSymbols();
+ }
+ catch (Exception e)
+ {
+ AsmDefinition = AssemblyDefinition.ReadAssembly(
+ new MemoryStream(RawBytes),
+ new ReaderParameters
+ {
+ AssemblyResolver = resolver,
+ });
+ SymbolsLoaded = false;
+ }
+
+ }
}
public ModifiableAssembly(string ownerName, string friendlyName, string path, IAssemblyResolver resolver)
{
OwnerName = ownerName;
FriendlyName = friendlyName;
- AsmDefinition = AssemblyDefinition.ReadAssembly(
- path,
- new ReaderParameters { AssemblyResolver = resolver, InMemory = true }
- );
+ try
+ {
+ AsmDefinition = AssemblyDefinition.ReadAssembly(path, new ReaderParameters
+ {
+ AssemblyResolver = resolver,
+ ReadSymbols = true,
+ InMemory = true
+ });
+ SymbolsLoaded = true;
+ CheckSymbols();
+ }
+ catch (Exception e)
+ {
+ AsmDefinition = AssemblyDefinition.ReadAssembly(path, new ReaderParameters
+ {
+ AssemblyResolver = resolver,
+ ReadSymbols = false,
+ InMemory = true
+ });
+ SymbolsLoaded = false;
+ }
}
public void SerializeToByteArray()
@@ -59,7 +128,23 @@ public void SerializeToByteArray()
Lg.Verbose($"Serializing: {FriendlyName}");
var stream = new MemoryStream();
- AsmDefinition.Write(stream);
+ if (SymbolsLoaded)
+ {
+ Lg.Verbose($"Serializing assembly with symbols loaded: {FriendlyName} {AsmDefinition.MainModule} {AsmDefinition.MainModule.symbol_reader.GetType()}");
+ var symbolsStream = new MemoryStream();
+ AsmDefinition.Write(stream,
+ new WriterParameters
+ {
+ SymbolStream = symbolsStream,
+ SymbolWriterProvider = new PdbWriterProvider()
+ });
+ SymbolBytes = symbolsStream.ToArray();
+
+ }
+ else
+ {
+ AsmDefinition.Write(stream);
+ }
Bytes = stream.ToArray();
}
@@ -78,4 +163,32 @@ public override string ToString()
{
return FriendlyName;
}
+
+ private void CheckSymbols()
+ {
+ // embedded symbols are portable symbols compressed and inserted directly into assembly
+ // Mono.Cecil doesnt support writing embedded symbols into memory so we extract the portable provider from them
+ if (AsmDefinition.MainModule.symbol_reader is EmbeddedPortablePdbReader mainEmbedded)
+ {
+ AsmDefinition.MainModule.symbol_reader = mainEmbedded.reader;
+
+ }
+
+ if (!AsmDefinition.Modules.NullOrEmpty())
+ {
+ foreach (var module in AsmDefinition.Modules)
+ {
+ if (module.symbol_reader is EmbeddedPortablePdbReader embedded)
+ {
+ module.symbol_reader = embedded.reader;
+ }
+ }
+ }
+
+ // Mono has no support loading native pdb, we ignore them
+ if (AsmDefinition.MainModule.symbol_reader is NativePdbReader)
+ {
+ SymbolsLoaded = false;
+ }
+ }
}