diff options
author | Marek Safar <marek.safar@gmail.com> | 2021-06-30 19:13:42 +0300 |
---|---|---|
committer | Marek Safar <marek.safar@gmail.com> | 2021-06-30 19:13:42 +0300 |
commit | cfb80b23787949a6fa5e3e3d6af35d86287517e9 (patch) | |
tree | f0da81c6aa2dd83a5309775aa9da05bd1f459b27 | |
parent | e069cd8d25d5b61b0e28fe65e75959c20af7aa80 (diff) | |
parent | 96c159d4687ea7493893011f3bd4a6e098dab163 (diff) |
Merge remote-tracking branch 'upstream/master'
20 files changed, 275 insertions, 118 deletions
diff --git a/Mono.Cecil.Cil/CodeWriter.cs b/Mono.Cecil.Cil/CodeWriter.cs index 88942e1..501710e 100644 --- a/Mono.Cecil.Cil/CodeWriter.cs +++ b/Mono.Cecil.Cil/CodeWriter.cs @@ -424,7 +424,6 @@ namespace Mono.Cecil.Cil { { switch (instruction.opcode.FlowControl) { case FlowControl.Branch: - case FlowControl.Break: case FlowControl.Throw: case FlowControl.Return: stack_size = 0; diff --git a/Mono.Cecil.Cil/PortablePdb.cs b/Mono.Cecil.Cil/PortablePdb.cs index b5515ba..aff6b29 100644 --- a/Mono.Cecil.Cil/PortablePdb.cs +++ b/Mono.Cecil.Cil/PortablePdb.cs @@ -70,8 +70,20 @@ namespace Mono.Cecil.Cil { if (image == module.Image) return true; - var entry = header.GetCodeViewEntry (); - if (entry == null) + foreach (var entry in header.Entries) { + if (!IsMatchingEntry (image.PdbHeap, entry)) + continue; + + ReadModule (); + return true; + } + + return false; + } + + static bool IsMatchingEntry (PdbHeap heap, ImageDebugHeaderEntry entry) + { + if (entry.Directory.Type != ImageDebugType.CodeView) return false; var data = entry.Data; @@ -88,15 +100,11 @@ namespace Mono.Cecil.Cil { var module_guid = new Guid (buffer); - Buffer.BlockCopy (image.PdbHeap.Id, 0, buffer, 0, 16); + Buffer.BlockCopy (heap.Id, 0, buffer, 0, 16); var pdb_guid = new Guid (buffer); - if (module_guid != pdb_guid) - return false; - - ReadModule (); - return true; + return module_guid == pdb_guid; } static int ReadInt32 (byte [] bytes, int start) @@ -301,7 +309,11 @@ namespace Mono.Cecil.Cil { // PDB Age buffer.WriteUInt32 (1); // PDB Path - buffer.WriteBytes (System.Text.Encoding.UTF8.GetBytes (writer.BaseStream.GetFileName ())); + var fileName = writer.BaseStream.GetFileName (); + if (string.IsNullOrEmpty (fileName)) { + fileName = module.Assembly.Name.Name + ".pdb"; + } + buffer.WriteBytes (System.Text.Encoding.UTF8.GetBytes (fileName)); buffer.WriteByte (0); var data = new byte [buffer.length]; diff --git a/Mono.Cecil.Cil/Symbols.cs b/Mono.Cecil.Cil/Symbols.cs index 4cf435d..5e92b67 100644 --- a/Mono.Cecil.Cil/Symbols.cs +++ b/Mono.Cecil.Cil/Symbols.cs @@ -619,17 +619,36 @@ namespace Mono.Cecil.Cil { public sealed class EmbeddedSourceDebugInformation : CustomDebugInformation { + internal uint index; + internal MetadataReader debug_reader; + internal bool resolved; internal byte [] content; internal bool compress; public byte [] Content { - get { return content; } - set { content = value; } + get { + if (!resolved) + Resolve (); + + return content; + } + set { + content = value; + resolved = true; + } } public bool Compress { - get { return compress; } - set { compress = value; } + get { + if (!resolved) + Resolve (); + + return compress; + } + set { + compress = value; + resolved = true; + } } public override CustomDebugInformationKind Kind { @@ -638,12 +657,42 @@ namespace Mono.Cecil.Cil { public static Guid KindIdentifier = new Guid ("{0E8A571B-6926-466E-B4AD-8AB04611F5FE}"); + internal EmbeddedSourceDebugInformation (uint index, MetadataReader debug_reader) + : base (KindIdentifier) + { + this.index = index; + this.debug_reader = debug_reader; + } + public EmbeddedSourceDebugInformation (byte [] content, bool compress) : base (KindIdentifier) { + this.resolved = true; this.content = content; this.compress = compress; } + + internal byte [] ReadRawEmbeddedSourceDebugInformation () + { + if (debug_reader == null) + throw new InvalidOperationException (); + + return debug_reader.ReadRawEmbeddedSourceDebugInformation (index); + } + + void Resolve () + { + if (resolved) + return; + + if (debug_reader == null) + throw new InvalidOperationException (); + + var row = debug_reader.ReadEmbeddedSourceDebugInformation (index); + content = row.Col1; + compress = row.Col2; + resolved = true; + } } public sealed class SourceLinkDebugInformation : CustomDebugInformation { diff --git a/Mono.Cecil.PE/ImageWriter.cs b/Mono.Cecil.PE/ImageWriter.cs index b33efe3..7e5e923 100644 --- a/Mono.Cecil.PE/ImageWriter.cs +++ b/Mono.Cecil.PE/ImageWriter.cs @@ -784,7 +784,7 @@ namespace Mono.Cecil.PE { int GetStrongNameLength () { - if (module.Assembly == null) + if (module.kind == ModuleKind.NetModule || module.Assembly == null) return 0; var public_key = module.Assembly.Name.PublicKey; diff --git a/Mono.Cecil/AssemblyReader.cs b/Mono.Cecil/AssemblyReader.cs index 2a59358..9fdcf68 100644 --- a/Mono.Cecil/AssemblyReader.cs +++ b/Mono.Cecil/AssemblyReader.cs @@ -182,7 +182,7 @@ namespace Mono.Cecil { ReadCustomAttributes (module); var assembly = module.Assembly; - if (assembly == null) + if (module.kind == ModuleKind.NetModule || assembly == null) return; ReadCustomAttributes (assembly); @@ -667,8 +667,10 @@ namespace Mono.Cecil { AssemblyResolver = module.AssemblyResolver }; - modules.Add (ModuleDefinition.ReadModule ( - GetModuleFileName (name), parameters)); + var netmodule = ModuleDefinition.ReadModule (GetModuleFileName (name), parameters); + netmodule.assembly = this.module.assembly; + + modules.Add (netmodule); } return modules; @@ -3221,28 +3223,7 @@ namespace Mono.Cecil { infos.Add (async_body); } else if (rows [i].Col1 == EmbeddedSourceDebugInformation.KindIdentifier) { - var signature = ReadSignature (rows [i].Col2); - var format = signature.ReadInt32 (); - var length = signature.sig_length - 4; - - var info = null as CustomDebugInformation; - - if (format == 0) { - info = new EmbeddedSourceDebugInformation (signature.ReadBytes ((int) length), compress: false); - } else if (format > 0) { - var compressed_stream = new MemoryStream (signature.ReadBytes ((int) length)); - var decompressed_document = new byte [format]; // if positive, format is the decompressed length of the document - var decompressed_stream = new MemoryStream (decompressed_document); - - using (var deflate_stream = new DeflateStream (compressed_stream, CompressionMode.Decompress, leaveOpen: true)) - deflate_stream.CopyTo (decompressed_stream); - - info = new EmbeddedSourceDebugInformation (decompressed_document, compress: true); - } else if (format < 0) { - info = new BinaryCustomDebugInformation (rows [i].Col1, ReadBlob (rows [i].Col2)); - } - - infos.Add (info); + infos.Add (new EmbeddedSourceDebugInformation (rows [i].Col2, this)); } else if (rows [i].Col1 == SourceLinkDebugInformation.KindIdentifier) { infos.Add (new SourceLinkDebugInformation (Encoding.UTF8.GetString (ReadBlob (rows [i].Col2)))); } else { @@ -3254,6 +3235,33 @@ namespace Mono.Cecil { return infos; } + + public byte [] ReadRawEmbeddedSourceDebugInformation (uint index) + { + var signature = ReadSignature (index); + return signature.ReadBytes ((int) signature.sig_length); + } + + public Row<byte [], bool> ReadEmbeddedSourceDebugInformation (uint index) + { + var signature = ReadSignature (index); + var format = signature.ReadInt32 (); + var length = signature.sig_length - 4; + + if (format == 0) { + return new Row<byte [], bool> (signature.ReadBytes ((int) length), false); + } else if (format > 0) { + var compressed_stream = new MemoryStream (signature.ReadBytes ((int) length)); + var decompressed_document = new byte [format]; // if positive, format is the decompressed length of the document + var decompressed_stream = new MemoryStream (decompressed_document); + + using (var deflate_stream = new DeflateStream (compressed_stream, CompressionMode.Decompress, leaveOpen: true)) + deflate_stream.CopyTo (decompressed_stream); + + return new Row<byte [], bool> (decompressed_document, true); + } else + throw new NotSupportedException (); + } } sealed class SignatureReader : ByteBuffer { diff --git a/Mono.Cecil/AssemblyWriter.cs b/Mono.Cecil/AssemblyWriter.cs index f14ce1b..c83f997 100644 --- a/Mono.Cecil/AssemblyWriter.cs +++ b/Mono.Cecil/AssemblyWriter.cs @@ -94,7 +94,7 @@ namespace Mono.Cecil { if (module.symbol_reader != null) module.symbol_reader.Dispose (); - var name = module.assembly != null ? module.assembly.Name : null; + var name = module.assembly != null && module.kind != ModuleKind.NetModule ? module.assembly.Name : null; var fq_name = stream.value.GetFileName (); var timestamp = parameters.Timestamp ?? module.timestamp; var symbol_writer_provider = parameters.SymbolWriterProvider; @@ -1018,7 +1018,7 @@ namespace Mono.Cecil { var assembly = module.Assembly; - if (assembly != null) + if (module.kind != ModuleKind.NetModule && assembly != null) BuildAssembly (); if (module.HasAssemblyReferences) @@ -1035,7 +1035,7 @@ namespace Mono.Cecil { BuildTypes (); - if (assembly != null) { + if (module.kind != ModuleKind.NetModule && assembly != null) { if (assembly.HasCustomAttributes) AddCustomAttributes (assembly); @@ -2428,6 +2428,13 @@ namespace Mono.Cecil { void AddEmbeddedSourceDebugInformation (ICustomDebugInformationProvider provider, EmbeddedSourceDebugInformation embedded_source) { var signature = CreateSignatureWriter (); + + if (!embedded_source.resolved) { + signature.WriteBytes (embedded_source.ReadRawEmbeddedSourceDebugInformation ()); + AddCustomDebugInformation (provider, embedded_source, signature); + return; + } + var content = embedded_source.content ?? Empty<byte>.Array; if (embedded_source.compress) { signature.WriteInt32 (content.Length); diff --git a/Mono.Cecil/FieldDefinition.cs b/Mono.Cecil/FieldDefinition.cs index 15b7720..7ce8d27 100644 --- a/Mono.Cecil/FieldDefinition.cs +++ b/Mono.Cecil/FieldDefinition.cs @@ -113,6 +113,7 @@ namespace Mono.Cecil { } set { initial_value = value; + HasFieldRVA = !initial_value.IsNullOrEmpty (); rva = 0; } } @@ -245,6 +246,11 @@ namespace Mono.Cecil { set { attributes = attributes.SetAttributes ((ushort) FieldAttributes.HasDefault, value); } } + public bool HasFieldRVA { + get { return attributes.GetAttributes ((ushort) FieldAttributes.HasFieldRVA); } + set { attributes = attributes.SetAttributes ((ushort) FieldAttributes.HasFieldRVA, value); } + } + #endregion public override bool IsDefinition { diff --git a/Mono.Cecil/MetadataResolver.cs b/Mono.Cecil/MetadataResolver.cs index 630ec8a..6511b41 100644 --- a/Mono.Cecil/MetadataResolver.cs +++ b/Mono.Cecil/MetadataResolver.cs @@ -115,6 +115,9 @@ namespace Mono.Cecil { case MetadataScopeType.ModuleDefinition: return GetType ((ModuleDefinition) scope, type); case MetadataScopeType.ModuleReference: + if (type.Module.Assembly == null) + return null; + var modules = type.Module.Assembly.Modules; var module_ref = (ModuleReference) scope; for (int i = 0; i < modules.Count; i++) { diff --git a/Test/Mono.Cecil.Tests/FieldTests.cs b/Test/Mono.Cecil.Tests/FieldTests.cs index 05165d6..4f575de 100644 --- a/Test/Mono.Cecil.Tests/FieldTests.cs +++ b/Test/Mono.Cecil.Tests/FieldTests.cs @@ -122,6 +122,14 @@ namespace Mono.Cecil.Tests { Assert.AreEqual (2, buffer.ReadUInt32 ()); Assert.AreEqual (3, buffer.ReadUInt32 ()); Assert.AreEqual (4, buffer.ReadUInt32 ()); + + var intialValue = field.InitialValue; + field.InitialValue = null; + Assert.False (field.Attributes.HasFlag (FieldAttributes.HasFieldRVA)); + + field.InitialValue = intialValue; + + Assert.True (field.Attributes.HasFlag (FieldAttributes.HasFieldRVA)); }); } diff --git a/Test/Mono.Cecil.Tests/PortablePdbTests.cs b/Test/Mono.Cecil.Tests/PortablePdbTests.cs index b0c1f32..43b8cfe 100644 --- a/Test/Mono.Cecil.Tests/PortablePdbTests.cs +++ b/Test/Mono.Cecil.Tests/PortablePdbTests.cs @@ -491,9 +491,12 @@ namespace Mono.Cecil.Tests { public void EmbeddedSource () { TestModule ("embedcs.exe", module => { + }, symbolReaderProvider: typeof (PortablePdbReaderProvider), symbolWriterProvider: typeof (PortablePdbWriterProvider)); + + TestModule ("embedcs.exe", module => { var program = GetDocument (module.GetType ("Program")); var program_src = GetSourceDebugInfo (program); - Assert.IsTrue (program_src.compress); + Assert.IsTrue (program_src.Compress); var program_src_content = Encoding.UTF8.GetString (program_src.Content); Assert.AreEqual (Normalize (@"using System; @@ -533,7 +536,7 @@ class Program var a = GetDocument (module.GetType ("A")); var a_src = GetSourceDebugInfo (a); - Assert.IsFalse (a_src.compress); + Assert.IsFalse (a_src.Compress); var a_src_content = Encoding.UTF8.GetString (a_src.Content); Assert.AreEqual (Normalize (@"class A { diff --git a/Test/Mono.Cecil.Tests/ResolveTests.cs b/Test/Mono.Cecil.Tests/ResolveTests.cs index bb57570..bce0003 100644 --- a/Test/Mono.Cecil.Tests/ResolveTests.cs +++ b/Test/Mono.Cecil.Tests/ResolveTests.cs @@ -247,6 +247,41 @@ namespace Mono.Cecil.Tests { } } + [Test] + public void ResolveModuleReferenceFromMemberReferenceTest () + { + using (var mma = AssemblyDefinition.ReadAssembly (GetAssemblyResourcePath ("mma.exe"))) { + var modB = mma.Modules [2]; + var bazType = modB.GetType ("Module.B.Baz"); + var gazonkMethod = bazType.Methods.First (m => m.Name.Equals ("Gazonk")); + var callInstr = gazonkMethod.Body.Instructions [1]; + + var methodRef = callInstr.Operand as MethodReference; + var methodTypeRef = methodRef.DeclaringType; + + Assert.AreEqual (mma, methodTypeRef.Module.Assembly); + + var def = methodTypeRef.Resolve (); + Assert.IsNotNull (def); + Assert.AreEqual ("Module.A.Foo", def.FullName); + } + } + + [Test] + public void ResolveModuleReferenceFromMemberReferenceOfSingleNetModuleTest () + { + using (var modb = ModuleDefinition.ReadModule (GetAssemblyResourcePath ("modb.netmodule"))) { + var bazType = modb.GetType ("Module.B.Baz"); + var gazonkMethod = bazType.Methods.First (m => m.Name.Equals ("Gazonk")); + var callInstr = gazonkMethod.Body.Instructions [1]; + + var methodRef = callInstr.Operand as MethodReference; + var methodTypeRef = methodRef.DeclaringType; + + Assert.IsNull (methodTypeRef.Module.Assembly); + Assert.IsNull (methodTypeRef.Resolve ()); + } + } TRet GetReference<TDel, TRet> (TDel code) { var @delegate = code as Delegate; diff --git a/Test/Mono.Cecil.Tests/SymbolTests.cs b/Test/Mono.Cecil.Tests/SymbolTests.cs index 941f4a1..691581e 100644 --- a/Test/Mono.Cecil.Tests/SymbolTests.cs +++ b/Test/Mono.Cecil.Tests/SymbolTests.cs @@ -128,5 +128,14 @@ namespace Mono.Cecil.Tests { } } } + + [Test] + public void MultipleCodeViewEntries () + { + using (var module = GetResourceModule ("System.Private.Xml.dll", new ReaderParameters { ReadSymbols = true })) { + Assert.IsTrue (module.HasSymbols); + Assert.IsNotNull (module.SymbolReader); + } + } } } diff --git a/Test/Resources/assemblies/System.Private.Xml.dll b/Test/Resources/assemblies/System.Private.Xml.dll Binary files differnew file mode 100644 index 0000000..82bc088 --- /dev/null +++ b/Test/Resources/assemblies/System.Private.Xml.dll diff --git a/Test/Resources/assemblies/System.Private.Xml.pdb b/Test/Resources/assemblies/System.Private.Xml.pdb Binary files differnew file mode 100644 index 0000000..9790d8d --- /dev/null +++ b/Test/Resources/assemblies/System.Private.Xml.pdb diff --git a/symbols/pdb/Mono.Cecil.Pdb.csproj b/symbols/pdb/Mono.Cecil.Pdb.csproj index 265159d..8e7d08c 100644 --- a/symbols/pdb/Mono.Cecil.Pdb.csproj +++ b/symbols/pdb/Mono.Cecil.Pdb.csproj @@ -2,6 +2,7 @@ <PropertyGroup> <TargetFrameworks>netstandard2.0;net40</TargetFrameworks> <NoWarn>0649</NoWarn> + <AllowUnsafeBlocks>True</AllowUnsafeBlocks> </PropertyGroup> <ItemGroup> <ProjectReference Include="..\..\Mono.Cecil.csproj"> diff --git a/symbols/pdb/Mono.Cecil.Pdb/ModuleMetadata.cs b/symbols/pdb/Mono.Cecil.Pdb/ModuleMetadata.cs index 297df0c..0bc32dc 100644 --- a/symbols/pdb/Mono.Cecil.Pdb/ModuleMetadata.cs +++ b/symbols/pdb/Mono.Cecil.Pdb/ModuleMetadata.cs @@ -5,8 +5,10 @@ using System.Text; namespace Mono.Cecil.Pdb { + // WARNING: most methods should be reworked into PreserveSig methods + [ComImport, InterfaceType (ComInterfaceType.InterfaceIsIUnknown), Guid ("BA3FEE4C-ECB9-4e41-83B7-183FA41CD859")] - interface IMetaDataEmit { + unsafe interface IMetaDataEmit { void SetModuleProps (string szName); void Save (string szFile, uint dwSaveFlags); void SaveToStream (IntPtr pIStream, uint dwSaveFlags); @@ -63,7 +65,7 @@ namespace Mono.Cecil.Pdb { } [ComImport, InterfaceType (ComInterfaceType.InterfaceIsIUnknown), Guid ("7DAC8207-D3AE-4c75-9B67-92801A497D44")] - interface IMetaDataImport { + unsafe interface IMetaDataImport { [PreserveSig] void CloseEnum (uint hEnum); uint CountEnum (uint hEnum); @@ -74,7 +76,9 @@ namespace Mono.Cecil.Pdb { uint FindTypeDefByName (string szTypeDef, uint tkEnclosingClass); Guid GetScopeProps (StringBuilder szName, uint cchName, out uint pchName); uint GetModuleFromScope (); - uint GetTypeDefProps (uint td, IntPtr szTypeDef, uint cchTypeDef, out uint pchTypeDef, IntPtr pdwTypeDefFlags); + + [PreserveSig] + uint GetTypeDefProps (uint td, char* szTypeDef, uint cchTypeDef, uint* pchTypeDef, uint* pdwTypeDefFlags, uint* ptkExtends); uint GetInterfaceImplProps (uint iiImpl, out uint pClass); uint GetTypeRefProps (uint tr, out uint ptkResolutionScope, StringBuilder szName, uint cchName); uint ResolveTypeRef (uint tr, [In] ref Guid riid, [MarshalAs (UnmanagedType.Interface)] out object ppIScope); @@ -94,7 +98,9 @@ namespace Mono.Cecil.Pdb { uint FindMethod (uint td, string szName, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 3)] byte [] pvSigBlob, uint cbSigBlob); uint FindField (uint td, string szName, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 3)] byte [] pvSigBlob, uint cbSigBlob); uint FindMemberRef (uint td, string szName, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 3)] byte [] pvSigBlob, uint cbSigBlob); - uint GetMethodProps (uint mb, out uint pClass, IntPtr szMethod, uint cchMethod, out uint pchMethod, IntPtr pdwAttr, IntPtr ppvSigBlob, IntPtr pcbSigBlob, IntPtr pulCodeRVA); + + [PreserveSig] + uint GetMethodProps (uint mb, uint* pClass, char* szMethod, uint cchMethod, uint* pchMethod, uint* pdwAttr, IntPtr ppvSigBlob, IntPtr pcbSigBlob, uint* pulCodeRVA, uint* pdwImplFlags); uint GetMemberRefProps (uint mr, ref uint ptk, StringBuilder szMember, uint cchMember, out uint pchMember, out IntPtr /* byte* */ ppvSigBlob); uint EnumProperties (ref uint phEnum, uint td, IntPtr /* uint* */ rProperties, uint cMax); uint EnumEvents (ref uint phEnum, uint td, IntPtr /* uint* */ rEvents, uint cMax); @@ -136,18 +142,22 @@ namespace Mono.Cecil.Pdb { [PreserveSig] [return: MarshalAs (UnmanagedType.Bool)] bool IsValidToken (uint tk); - uint GetNestedClassProps (uint tdNestedClass); + [PreserveSig] + uint GetNestedClassProps (uint tdNestedClass, uint* ptdEnclosingClass); uint GetNativeCallConvFromSig (IntPtr /* void* */ pvSig, uint cbSig); int IsGlobal (uint pd); } - class ModuleMetadata : IMetaDataEmit, IMetaDataImport { + unsafe class ModuleMetadata : IMetaDataEmit, IMetaDataImport { readonly ModuleDefinition module; Dictionary<uint, TypeDefinition> types; Dictionary<uint, MethodDefinition> methods; + const uint S_OK = 0x00000000; + const uint E_FAIL = 0x80004005; + public ModuleMetadata (ModuleDefinition module) { this.module = module; @@ -476,40 +486,22 @@ namespace Mono.Cecil.Pdb { throw new NotImplementedException (); } - public uint GetTypeDefProps (uint td, IntPtr szTypeDef, uint cchTypeDef, out uint pchTypeDef, IntPtr pdwTypeDefFlags) + public uint GetTypeDefProps (uint td, char* szTypeDef, uint cchTypeDef, uint* pchTypeDef, uint* pdwTypeDefFlags, uint* ptkExtends) { TypeDefinition type; - if (!TryGetType (td, out type)) { - Marshal.WriteInt16 (szTypeDef, 0); - pchTypeDef = 1; - return 0; - } - - WriteString (type.IsNested ? type.Name : type.FullName, szTypeDef, cchTypeDef, out pchTypeDef); - WriteIntPtr (pdwTypeDefFlags, (uint) type.Attributes); - return type.BaseType != null ? type.BaseType.MetadataToken.ToUInt32 () : 0; - } - - static void WriteIntPtr (IntPtr ptr, uint value) - { - if (ptr == IntPtr.Zero) - return; + if (!TryGetType (td, out type)) + return E_FAIL; - Marshal.WriteInt32 (ptr, (int) value); - } + var name = type.IsNested ? type.Name : type.FullName; - static void WriteString (string str, IntPtr buffer, uint bufferSize, out uint chars) - { - var length = str.Length + 1 >= bufferSize ? bufferSize - 1 : (uint) str.Length; - chars = length + 1; - var offset = 0; + WriteNameBuffer (name, szTypeDef, cchTypeDef, pchTypeDef); - for (int i = 0; i < length; i++) { - Marshal.WriteInt16 (buffer, offset, str [i]); - offset += 2; - } + if (pdwTypeDefFlags != null) + *pdwTypeDefFlags = (uint) type.Attributes; + if (ptkExtends != null) + *ptkExtends = type.BaseType != null ? type.BaseType.MetadataToken.ToUInt32 () : 0; - Marshal.WriteInt16 (buffer, offset, 0); + return S_OK; } public uint GetInterfaceImplProps (uint iiImpl, out uint pClass) @@ -597,22 +589,38 @@ namespace Mono.Cecil.Pdb { throw new NotImplementedException (); } - public uint GetMethodProps (uint mb, out uint pClass, IntPtr szMethod, uint cchMethod, out uint pchMethod, IntPtr pdwAttr, IntPtr ppvSigBlob, IntPtr pcbSigBlob, IntPtr pulCodeRVA) + public uint GetMethodProps (uint mb, uint* pClass, char* szMethod, uint cchMethod, uint* pchMethod, uint* pdwAttr, IntPtr ppvSigBlob, IntPtr pcbSigBlob, uint* pulCodeRVA, uint* pdwImplFlags) { MethodDefinition method; - if (!TryGetMethod (mb, out method)) { - Marshal.WriteInt16 (szMethod, 0); - pchMethod = 1; - pClass = 0; - return 0; - } + if (!TryGetMethod (mb, out method)) + return E_FAIL; + + if (pClass != null) + *pClass = method.DeclaringType.MetadataToken.ToUInt32 (); + + WriteNameBuffer (method.Name, szMethod, cchMethod, pchMethod); - pClass = method.DeclaringType.MetadataToken.ToUInt32 (); - WriteString (method.Name, szMethod, cchMethod, out pchMethod); - WriteIntPtr (pdwAttr, (uint) method.Attributes); - WriteIntPtr (pulCodeRVA, (uint) method.RVA); + if (pdwAttr != null) + *pdwAttr = (uint) method.Attributes; + if (pulCodeRVA != null) + *pulCodeRVA = (uint) method.RVA; + if (pdwImplFlags != null) + *pdwImplFlags = (uint) method.ImplAttributes; - return (uint) method.ImplAttributes; + return S_OK; + } + + static void WriteNameBuffer(string name, char* buffer, uint bufferLength, uint* actualLength) + { + var length = Math.Min (name.Length, bufferLength - 1); + if (actualLength != null) + *actualLength = (uint) length; + + if (buffer != null && bufferLength > 0) { + for (int i = 0; i < length; i++) + buffer [i] = name [i]; + buffer [length + 1] = '\0'; + } } public uint GetMemberRefProps (uint mr, ref uint ptk, StringBuilder szMember, uint cchMember, out uint pchMember, out IntPtr ppvSigBlob) @@ -770,13 +778,16 @@ namespace Mono.Cecil.Pdb { throw new NotImplementedException (); } - public uint GetNestedClassProps (uint tdNestedClass) + public uint GetNestedClassProps (uint tdNestedClass, uint* ptdEnclosingClass) { TypeDefinition type; if (!TryGetType (tdNestedClass, out type)) - return 0; + return E_FAIL; + + if (ptdEnclosingClass != null) + *ptdEnclosingClass = type.IsNested ? type.DeclaringType.MetadataToken.ToUInt32 () : 0; - return type.IsNested ? type.DeclaringType.MetadataToken.ToUInt32 () : 0; + return S_OK; } public uint GetNativeCallConvFromSig (IntPtr pvSig, uint cbSig) diff --git a/symbols/pdb/Mono.Cecil.Pdb/NativePdbReader.cs b/symbols/pdb/Mono.Cecil.Pdb/NativePdbReader.cs index 2d6b1ba..91f1f3e 100644 --- a/symbols/pdb/Mono.Cecil.Pdb/NativePdbReader.cs +++ b/symbols/pdb/Mono.Cecil.Pdb/NativePdbReader.cs @@ -22,7 +22,6 @@ namespace Mono.Cecil.Pdb { public class NativePdbReader : ISymbolReader { - int age; Guid guid; readonly Disposable<Stream> pdb_file; @@ -52,13 +51,26 @@ namespace Mono.Cecil.Pdb { if (!header.HasEntries) return false; - var entry = header.GetCodeViewEntry (); - if (entry == null) - return false; + using (pdb_file) { + var info = PdbFile.LoadFunctions (pdb_file.value); + + foreach (var entry in header.Entries) { + if (!IsMatchingEntry (info, entry)) + continue; + + foreach (var function in info.Functions) + functions.Add (function.token, function); - var directory = entry.Directory; + return true; + } + } + + return false; + } - if (directory.Type != ImageDebugType.CodeView) + static bool IsMatchingEntry (PdbInfo info, ImageDebugHeaderEntry entry) + { + if (entry.Directory.Type != ImageDebugType.CodeView) return false; var data = entry.Data; @@ -73,10 +85,7 @@ namespace Mono.Cecil.Pdb { var guid_bytes = new byte [16]; Buffer.BlockCopy (data, 4, guid_bytes, 0, 16); - this.guid = new Guid (guid_bytes); - this.age = ReadInt32 (data, 20); - - return PopulateFunctions (); + return info.Guid == new Guid (guid_bytes); } static int ReadInt32 (byte [] bytes, int start) @@ -87,20 +96,6 @@ namespace Mono.Cecil.Pdb { | (bytes [start + 3] << 24)); } - bool PopulateFunctions () - { - using (pdb_file) { - var info = PdbFile.LoadFunctions (pdb_file.value); - - if (this.guid != info.Guid) - return false; - - foreach (PdbFunction function in info.Functions) - functions.Add (function.token, function); - } - - return true; - } public MethodDebugInformation Read (MethodDefinition method) { diff --git a/symbols/pdb/Test/Mono.Cecil.Tests/PdbTests.cs b/symbols/pdb/Test/Mono.Cecil.Tests/PdbTests.cs index 797f680..6f2d2fa 100644 --- a/symbols/pdb/Test/Mono.Cecil.Tests/PdbTests.cs +++ b/symbols/pdb/Test/Mono.Cecil.Tests/PdbTests.cs @@ -465,5 +465,16 @@ namespace Mono.Cecil.Tests { Assert.AreEqual ("temp", method.DebugInformation.Scope.Variables [0].Name); } + + [Test] + public void TypeNameExceedingMaxPdbPath () + { + if (!Platform.HasNativePdbSupport) + Assert.Ignore (); + + TestModule ("longtypename.dll", module => { + Assert.IsTrue (module.HasSymbols); + }, symbolReaderProvider: typeof (NativePdbReaderProvider), symbolWriterProvider: typeof (NativePdbWriterProvider)); + } } } diff --git a/symbols/pdb/Test/Resources/assemblies/longtypename.dll b/symbols/pdb/Test/Resources/assemblies/longtypename.dll Binary files differnew file mode 100644 index 0000000..803757f --- /dev/null +++ b/symbols/pdb/Test/Resources/assemblies/longtypename.dll diff --git a/symbols/pdb/Test/Resources/assemblies/longtypename.pdb b/symbols/pdb/Test/Resources/assemblies/longtypename.pdb Binary files differnew file mode 100644 index 0000000..0c5ca89 --- /dev/null +++ b/symbols/pdb/Test/Resources/assemblies/longtypename.pdb |