diff --git a/Directory.Build.props b/Directory.Build.props
index 5b9f0da9d..a37508076 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -9,6 +9,7 @@
$(MSBuildThisFileDirectory)\cecil.snk
$(DefineConstants);NET_CORE
+ latest
true
diff --git a/Mono.Cecil.Cil/PortablePdb.cs b/Mono.Cecil.Cil/PortablePdb.cs
index 6664bee32..4f58ebf52 100644
--- a/Mono.Cecil.Cil/PortablePdb.cs
+++ b/Mono.Cecil.Cil/PortablePdb.cs
@@ -13,6 +13,7 @@
using System.IO;
using System.IO.Compression;
using System.Security.Cryptography;
+using Mono.Collections.Generic;
using Mono.Cecil.Metadata;
using Mono.Cecil.PE;
@@ -145,6 +146,11 @@ void ReadStateMachineKickOffMethod (MethodDebugInformation method_info)
method_info.kickoff_method = debug_reader.ReadStateMachineKickoffMethod (method_info.method);
}
+ public Collection Read (ICustomDebugInformationProvider provider)
+ {
+ return debug_reader.GetCustomDebugInformation (provider);
+ }
+
void ReadCustomDebugInformations (MethodDebugInformation info)
{
info.method.custom_infos = debug_reader.GetCustomDebugInformation (info.method);
@@ -221,6 +227,11 @@ public MethodDebugInformation Read (MethodDefinition method)
return reader.Read (method);
}
+ public Collection Read (ICustomDebugInformationProvider provider)
+ {
+ return reader.Read (provider);
+ }
+
public void Dispose ()
{
reader.Dispose ();
@@ -319,6 +330,11 @@ public void Write ()
}
}
+ public void Write (ICustomDebugInformationProvider provider)
+ {
+ pdb_metadata.AddCustomDebugInformations (provider);
+ }
+
public ImageDebugHeader GetDebugHeader ()
{
if (IsEmbedded)
@@ -519,6 +535,11 @@ public void Write (MethodDebugInformation info)
writer.Write (info);
}
+ public void Write (ICustomDebugInformationProvider provider)
+ {
+ writer.Write (provider);
+ }
+
public ImageDebugHeader GetDebugHeader ()
{
ImageDebugHeader pdbDebugHeader = writer.GetDebugHeader ();
diff --git a/Mono.Cecil.Cil/Symbols.cs b/Mono.Cecil.Cil/Symbols.cs
index 744e7a82b..294eb16db 100644
--- a/Mono.Cecil.Cil/Symbols.cs
+++ b/Mono.Cecil.Cil/Symbols.cs
@@ -854,6 +854,7 @@ public interface ISymbolReader : IDisposable {
ISymbolWriterProvider GetWriterProvider ();
bool ProcessDebugHeader (ImageDebugHeader header);
MethodDebugInformation Read (MethodDefinition method);
+ Collection Read (ICustomDebugInformationProvider provider);
}
public interface ISymbolReaderProvider {
@@ -1116,6 +1117,7 @@ public interface ISymbolWriter : IDisposable {
ImageDebugHeader GetDebugHeader ();
void Write (MethodDebugInformation info);
void Write ();
+ void Write (ICustomDebugInformationProvider provider);
}
public interface ISymbolWriterProvider {
@@ -1224,5 +1226,40 @@ public static bool IsPortablePdb (Stream stream)
stream.Position = position;
}
}
+
+ public static bool GetHasCustomDebugInformations (
+ this ICustomDebugInformationProvider self,
+ ref Collection collection,
+ ModuleDefinition module)
+ {
+ if (module.HasImage ()) {
+ module.Read (ref collection, self, static (provider, reader) => {
+ var symbol_reader = reader.module.symbol_reader;
+ if (symbol_reader != null)
+ return symbol_reader.Read (provider);
+ return null;
+ });
+ }
+
+ return !collection.IsNullOrEmpty ();
+ }
+
+ public static Collection GetCustomDebugInformations (
+ this ICustomDebugInformationProvider self,
+ ref Collection collection,
+ ModuleDefinition module)
+ {
+ if (module.HasImage ()) {
+ module.Read (ref collection, self, static (provider, reader) => {
+ var symbol_reader = reader.module.symbol_reader;
+ if (symbol_reader != null)
+ return symbol_reader.Read (provider);
+ return null;
+ });
+ }
+
+ Interlocked.CompareExchange (ref collection, new Collection (), null);
+ return collection;
+ }
}
}
diff --git a/Mono.Cecil/AssemblyReader.cs b/Mono.Cecil/AssemblyReader.cs
index 4564071e8..a21d0a966 100644
--- a/Mono.Cecil/AssemblyReader.cs
+++ b/Mono.Cecil/AssemblyReader.cs
@@ -404,6 +404,7 @@ void ReadTypesSymbols (Collection types, ISymbolReader symbol_re
{
for (int i = 0; i < types.Count; i++) {
var type = types [i];
+ type.custom_infos = symbol_reader.Read (type);
if (type.HasNestedTypes)
ReadTypesSymbols (type.NestedTypes, symbol_reader);
@@ -3160,6 +3161,17 @@ void InitializeCustomDebugInformations ()
}
}
+ public bool HasCustomDebugInformation (ICustomDebugInformationProvider provider)
+ {
+ InitializeCustomDebugInformations ();
+
+ Row [] rows;
+ if (!metadata.CustomDebugInformations.TryGetValue (provider.MetadataToken, out rows))
+ return false;
+
+ return rows.Length > 0;
+ }
+
public Collection GetCustomDebugInformation (ICustomDebugInformationProvider provider)
{
InitializeCustomDebugInformations ();
diff --git a/Mono.Cecil/AssemblyWriter.cs b/Mono.Cecil/AssemblyWriter.cs
index 836aa2172..ee234c81f 100644
--- a/Mono.Cecil/AssemblyWriter.cs
+++ b/Mono.Cecil/AssemblyWriter.cs
@@ -1487,6 +1487,9 @@ void AddType (TypeDefinition type)
if (type.HasNestedTypes)
AddNestedTypes (type);
+ if (symbol_writer != null && type.HasCustomDebugInformations)
+ symbol_writer.Write (type);
+
WindowsRuntimeProjections.ApplyProjection (type, treatment);
}
diff --git a/Mono.Cecil/TypeDefinition.cs b/Mono.Cecil/TypeDefinition.cs
index 872e4c253..92d6ab299 100644
--- a/Mono.Cecil/TypeDefinition.cs
+++ b/Mono.Cecil/TypeDefinition.cs
@@ -10,12 +10,13 @@
using System;
using System.Threading;
+using Mono.Cecil.Cil;
using Mono.Cecil.Metadata;
using Mono.Collections.Generic;
namespace Mono.Cecil {
- public sealed class TypeDefinition : TypeReference, IMemberDefinition, ISecurityDeclarationProvider {
+ public sealed class TypeDefinition : TypeReference, IMemberDefinition, ISecurityDeclarationProvider, ICustomDebugInformationProvider {
uint attributes;
TypeReference base_type;
@@ -34,6 +35,8 @@ public sealed class TypeDefinition : TypeReference, IMemberDefinition, ISecurity
Collection custom_attributes;
Collection security_declarations;
+ internal Collection custom_infos;
+
public TypeAttributes Attributes {
get { return (TypeAttributes) attributes; }
set {
@@ -284,6 +287,19 @@ public override Collection GenericParameters {
get { return generic_parameters ?? (this.GetGenericParameters (ref generic_parameters, Module)); }
}
+ public bool HasCustomDebugInformations {
+ get {
+ if (custom_infos != null)
+ return custom_infos.Count > 0;
+
+ return this.GetHasCustomDebugInformations (ref custom_infos, Module);
+ }
+ }
+
+ public Collection CustomDebugInformations {
+ get { return custom_infos ?? (this.GetCustomDebugInformations (ref custom_infos, module)); }
+ }
+
#region TypeAttributes
public bool IsNotPublic {
diff --git a/Test/Mono.Cecil.Tests/BaseTestFixture.cs b/Test/Mono.Cecil.Tests/BaseTestFixture.cs
index 046791bfa..12de4227a 100644
--- a/Test/Mono.Cecil.Tests/BaseTestFixture.cs
+++ b/Test/Mono.Cecil.Tests/BaseTestFixture.cs
@@ -2,6 +2,7 @@
using System.IO;
using System.Runtime.CompilerServices;
using Mono.Cecil.Cil;
+using Mono.Cecil.Pdb;
using NUnit.Framework;
using Mono.Cecil.PE;
@@ -154,6 +155,54 @@ static void Run (TestCase testCase)
using (var runner = new TestRunner (testCase, TestCaseType.WriteFromImmediate))
runner.RunTest ();
}
+
+ public enum RoundtripType {
+ None,
+ Pdb,
+ PortablePdb
+ }
+
+ protected static ModuleDefinition RoundtripModule(ModuleDefinition module, RoundtripType roundtripType)
+ {
+ if (roundtripType == RoundtripType.None)
+ return module;
+
+ var file = Path.Combine (Path.GetTempPath (), "RoundtripModule.dll");
+ if (File.Exists (file))
+ File.Delete (file);
+
+ ISymbolWriterProvider symbolWriterProvider;
+ switch (roundtripType) {
+ case RoundtripType.Pdb when Platform.HasNativePdbSupport:
+ symbolWriterProvider = new PdbWriterProvider ();
+ break;
+ case RoundtripType.PortablePdb:
+ default:
+ symbolWriterProvider = new PortablePdbWriterProvider ();
+ break;
+ }
+
+ module.Write (file, new WriterParameters {
+ SymbolWriterProvider = symbolWriterProvider,
+ });
+ module.Dispose ();
+
+ ISymbolReaderProvider symbolReaderProvider;
+ switch (roundtripType) {
+ case RoundtripType.Pdb when Platform.HasNativePdbSupport:
+ symbolReaderProvider = new PdbReaderProvider ();
+ break;
+ case RoundtripType.PortablePdb:
+ default:
+ symbolReaderProvider = new PortablePdbReaderProvider ();
+ break;
+ }
+
+ return ModuleDefinition.ReadModule (file, new ReaderParameters {
+ SymbolReaderProvider = symbolReaderProvider,
+ InMemory = true
+ });
+ }
}
abstract class TestCase {
diff --git a/Test/Mono.Cecil.Tests/ILProcessorTests.cs b/Test/Mono.Cecil.Tests/ILProcessorTests.cs
index fd462c365..93ca078c8 100644
--- a/Test/Mono.Cecil.Tests/ILProcessorTests.cs
+++ b/Test/Mono.Cecil.Tests/ILProcessorTests.cs
@@ -3,10 +3,8 @@
using System.IO;
using System.Linq;
-using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Cecil.Mdb;
-using Mono.Cecil.Pdb;
using NUnit.Framework;
namespace Mono.Cecil.Tests {
@@ -499,12 +497,6 @@ static MethodBody CreateTestMethodWithLocalScopes (RoundtripType roundtripType,
return methodBody;
}
- public enum RoundtripType {
- None,
- Pdb,
- PortablePdb
- }
-
static MethodBody RoundtripMethodBody(MethodBody methodBody, RoundtripType roundtripType, bool forceUnresolvedScopes = false, bool reverseScopeOrder = false)
{
var newModule = RoundtripModule (methodBody.Method.Module, roundtripType);
@@ -540,47 +532,5 @@ static void ReverseScopeOrder(ScopeDebugInformation scope)
foreach (var subScope in scope.Scopes)
ReverseScopeOrder (subScope);
}
-
- static ModuleDefinition RoundtripModule(ModuleDefinition module, RoundtripType roundtripType)
- {
- if (roundtripType == RoundtripType.None)
- return module;
-
- var file = Path.Combine (Path.GetTempPath (), "TestILProcessor.dll");
- if (File.Exists (file))
- File.Delete (file);
-
- ISymbolWriterProvider symbolWriterProvider;
- switch (roundtripType) {
- case RoundtripType.Pdb when Platform.HasNativePdbSupport:
- symbolWriterProvider = new PdbWriterProvider ();
- break;
- case RoundtripType.PortablePdb:
- default:
- symbolWriterProvider = new PortablePdbWriterProvider ();
- break;
- }
-
- module.Write (file, new WriterParameters {
- SymbolWriterProvider = symbolWriterProvider,
- });
- module.Dispose ();
-
- ISymbolReaderProvider symbolReaderProvider;
- switch (roundtripType) {
- case RoundtripType.Pdb when Platform.HasNativePdbSupport:
- symbolReaderProvider = new PdbReaderProvider ();
- break;
- case RoundtripType.PortablePdb:
- default:
- symbolReaderProvider = new PortablePdbReaderProvider ();
- break;
- }
-
- return ModuleDefinition.ReadModule (file, new ReaderParameters {
- SymbolReaderProvider = symbolReaderProvider,
- InMemory = true
- });
- }
}
}
diff --git a/Test/Mono.Cecil.Tests/PortablePdbTests.cs b/Test/Mono.Cecil.Tests/PortablePdbTests.cs
index a89f79d83..c2b04524b 100644
--- a/Test/Mono.Cecil.Tests/PortablePdbTests.cs
+++ b/Test/Mono.Cecil.Tests/PortablePdbTests.cs
@@ -646,6 +646,43 @@ public void PortablePdbLineInfo()
}, symbolReaderProvider: typeof (PortablePdbReaderProvider), symbolWriterProvider: typeof (PortablePdbWriterProvider));
}
+ [Test]
+ public void TypeDefinitionDebugInformation ()
+ {
+ TestModule ("TypeDefinitionDebugInformation.dll", module => {
+ var enum_type = module.GetType ("TypeDefinitionDebugInformation.Enum");
+ Assert.IsTrue (enum_type.HasCustomDebugInformations);
+ var binary_custom_debug_info = enum_type.CustomDebugInformations.OfType ().FirstOrDefault ();
+ Assert.IsNotNull (binary_custom_debug_info);
+ Assert.AreEqual (new Guid ("932E74BC-DBA9-4478-8D46-0F32A7BAB3D3"), binary_custom_debug_info.Identifier);
+ Assert.AreEqual (new byte [] { 0x1 }, binary_custom_debug_info.Data);
+
+ var interface_type = module.GetType ("TypeDefinitionDebugInformation.Interface");
+ Assert.IsTrue (interface_type.HasCustomDebugInformations);
+ binary_custom_debug_info = interface_type.CustomDebugInformations.OfType ().FirstOrDefault ();
+ Assert.IsNotNull (binary_custom_debug_info);
+ Assert.AreEqual (new Guid ("932E74BC-DBA9-4478-8D46-0F32A7BAB3D3"), binary_custom_debug_info.Identifier);
+ Assert.AreEqual (new byte [] { 0x1 }, binary_custom_debug_info.Data);
+ }, symbolReaderProvider: typeof (PortablePdbReaderProvider), symbolWriterProvider: typeof (PortablePdbWriterProvider));
+ }
+
+ [Test]
+ public void ModifyTypeDefinitionDebugInformation ()
+ {
+ using (var module = GetResourceModule ("TypeDefinitionDebugInformation.dll", new ReaderParameters { SymbolReaderProvider = new PortablePdbReaderProvider () })) {
+ var enum_type = module.GetType ("TypeDefinitionDebugInformation.Enum");
+ var binary_custom_debug_info = enum_type.CustomDebugInformations.OfType ().FirstOrDefault ();
+ Assert.AreEqual (new byte [] { 0x1 }, binary_custom_debug_info.Data);
+ binary_custom_debug_info.Data = new byte [] { 0x2 };
+
+ var outputModule = RoundtripModule (module, RoundtripType.None);
+ enum_type = outputModule.GetType ("TypeDefinitionDebugInformation.Enum");
+ binary_custom_debug_info = enum_type.CustomDebugInformations.OfType ().FirstOrDefault ();
+ Assert.IsNotNull (binary_custom_debug_info);
+ Assert.AreEqual (new byte [] { 0x2 }, binary_custom_debug_info.Data);
+ }
+ }
+
public sealed class SymbolWriterProvider : ISymbolWriterProvider {
readonly DefaultSymbolWriterProvider writer_provider = new DefaultSymbolWriterProvider ();
@@ -730,6 +767,11 @@ public void Write ()
symbol_writer.Write ();
}
+ public void Write (ICustomDebugInformationProvider provider)
+ {
+ symbol_writer.Write (provider);
+ }
+
public void Dispose ()
{
symbol_writer.Dispose ();
diff --git a/Test/Resources/assemblies/TypeDefinitionDebugInformation.dll b/Test/Resources/assemblies/TypeDefinitionDebugInformation.dll
new file mode 100644
index 000000000..6b41377d0
Binary files /dev/null and b/Test/Resources/assemblies/TypeDefinitionDebugInformation.dll differ
diff --git a/Test/Resources/assemblies/TypeDefinitionDebugInformation.pdb b/Test/Resources/assemblies/TypeDefinitionDebugInformation.pdb
new file mode 100644
index 000000000..954231334
Binary files /dev/null and b/Test/Resources/assemblies/TypeDefinitionDebugInformation.pdb differ
diff --git a/symbols/mdb/Mono.Cecil.Mdb/MdbReader.cs b/symbols/mdb/Mono.Cecil.Mdb/MdbReader.cs
index 3e2dd18e4..f19212f60 100644
--- a/symbols/mdb/Mono.Cecil.Mdb/MdbReader.cs
+++ b/symbols/mdb/Mono.Cecil.Mdb/MdbReader.cs
@@ -186,6 +186,11 @@ SequencePoint LineToSequencePoint (LineNumberEntry line)
};
}
+ public Collection Read (ICustomDebugInformationProvider provider)
+ {
+ return new Collection ();
+ }
+
public void Dispose ()
{
symbol_file.Dispose ();
diff --git a/symbols/mdb/Mono.Cecil.Mdb/MdbWriter.cs b/symbols/mdb/Mono.Cecil.Mdb/MdbWriter.cs
index 4d4ce933b..81a0d539d 100644
--- a/symbols/mdb/Mono.Cecil.Mdb/MdbWriter.cs
+++ b/symbols/mdb/Mono.Cecil.Mdb/MdbWriter.cs
@@ -173,6 +173,10 @@ public void Write ()
// after the entire image of the assembly is written (since it's computed from the hash of that)
}
+ public void Write (ICustomDebugInformationProvider provider)
+ {
+ }
+
public void Dispose ()
{
writer.WriteSymbolFile (module.Mvid);
diff --git a/symbols/pdb/Mono.Cecil.Pdb/NativePdbReader.cs b/symbols/pdb/Mono.Cecil.Pdb/NativePdbReader.cs
index 484704447..400fb0b48 100644
--- a/symbols/pdb/Mono.Cecil.Pdb/NativePdbReader.cs
+++ b/symbols/pdb/Mono.Cecil.Pdb/NativePdbReader.cs
@@ -355,6 +355,11 @@ Document GetDocument (PdbSource source)
return document;
}
+ public Collection Read (ICustomDebugInformationProvider provider)
+ {
+ return new Collection ();
+ }
+
public void Dispose ()
{
pdb_file.Dispose ();
diff --git a/symbols/pdb/Mono.Cecil.Pdb/NativePdbWriter.cs b/symbols/pdb/Mono.Cecil.Pdb/NativePdbWriter.cs
index 9597d7fa4..55515d5e5 100644
--- a/symbols/pdb/Mono.Cecil.Pdb/NativePdbWriter.cs
+++ b/symbols/pdb/Mono.Cecil.Pdb/NativePdbWriter.cs
@@ -265,6 +265,10 @@ public void Write ()
writer.Close ();
}
+ public void Write (ICustomDebugInformationProvider provider)
+ {
+ }
+
public void Dispose ()
{
writer.Close ();