Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/ikvm-fork.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZoltan Varga <vargaz@gmail.com>2016-04-06 00:34:28 +0300
committerZoltan Varga <vargaz@gmail.com>2016-04-06 00:34:28 +0300
commit1f93971046fb8d0739c04cc502ec7cd226b6308e (patch)
tree285c7becd5d27f8a82b8639932bea2401d200360
parent00252c18fc0a4a206e45461736a890acb785a9d8 (diff)
Add preliminary support for reading portable pdb files.
-rw-r--r--reflect/Emit/ModuleBuilder.cs5
-rw-r--r--reflect/Metadata/Tables.cs283
-rw-r--r--reflect/Module.cs28
-rw-r--r--reflect/Reader/ModuleReader.cs78
4 files changed, 388 insertions, 6 deletions
diff --git a/reflect/Emit/ModuleBuilder.cs b/reflect/Emit/ModuleBuilder.cs
index 571f8e24..b3940bc1 100644
--- a/reflect/Emit/ModuleBuilder.cs
+++ b/reflect/Emit/ModuleBuilder.cs
@@ -1532,6 +1532,11 @@ namespace IKVM.Reflection.Emit
return Blobs.GetBlob(blobIndex);
}
+ internal sealed override Guid GetGuid(int guidIndex)
+ {
+ throw new NotImplementedException();
+ }
+
internal int GetSignatureBlobIndex(Signature sig)
{
ByteBuffer bb = new ByteBuffer(16);
diff --git a/reflect/Metadata/Tables.cs b/reflect/Metadata/Tables.cs
index b8734c2e..75ceef7c 100644
--- a/reflect/Metadata/Tables.cs
+++ b/reflect/Metadata/Tables.cs
@@ -2719,4 +2719,287 @@ namespace IKVM.Reflection.Metadata
Sort();
}
}
+
+ // Portable PDB
+ sealed class DocumentTable : Table<DocumentTable.Record>
+ {
+ internal const int Index = 0x30;
+
+ internal static Guid SHA1Guid = new Guid("ff1816ec-aa5e-4d10-87f7-6f4963833460");
+ internal static Guid CSharpGuid = new Guid("3f5162f8-07c6-11d3-9053-00c04fa302a1");
+
+ internal struct Record
+ {
+ internal int Name; // -> StringHeap
+ internal int HashAlgorithm; // -> GuidHeap
+ internal int Hash; // -> BlobHeap
+ internal int Language; // -> GuidHeap
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].Name = mr.ReadBlobIndex();
+ records[i].HashAlgorithm = mr.ReadGuidIndex();
+ records[i].Hash = mr.ReadBlobIndex();
+ records[i].Language = mr.ReadGuidIndex();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ throw new NotImplementedException ();
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .WriteStringIndex()
+ .WriteGuidIndex()
+ .WriteBlobIndex()
+ .WriteGuidIndex()
+ .Value;
+ }
+ }
+
+ // Portable PDB
+ sealed class MethodDebugInformationTable : Table<MethodDebugInformationTable.Record>
+ {
+ internal const int Index = 0x31;
+
+ internal struct Record
+ {
+ internal int Document; // -> Document table
+ internal int SequencePoints; // -> BlobHeap
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ // FIXME: Token size
+ records[i].Document = mr.ReadInt16 ();
+ records[i].SequencePoints = mr.ReadBlobIndex();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ throw new NotImplementedException ();
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .WriteBlobIndex()
+ .Value;
+ }
+ }
+
+ // Portable PDB
+ // FIXME: Sorted
+ sealed class LocalScopeTable : Table<LocalScopeTable.Record>
+ {
+ internal const int Index = 0x32;
+
+ internal struct Record
+ {
+ internal int Method;
+ internal int ImportScope;
+ internal int VariableList;
+ internal int ConstantList;
+ internal uint StartOffset;
+ internal uint Length;
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ // FIXME: Token sizes ?
+ records[i].Method = mr.ReadInt16();
+ records[i].ImportScope = mr.ReadInt16();
+ records[i].VariableList = mr.ReadInt16();
+ records[i].ConstantList = mr.ReadInt16();
+ records[i].StartOffset = (uint)mr.ReadInt32();
+ records[i].Length = (uint)mr.ReadInt32();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ throw new NotImplementedException ();
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ // Portable PDB
+ sealed class LocalVariableTable : Table<LocalVariableTable.Record>
+ {
+ internal const int Index = 0x33;
+
+ internal enum LocalVariableAttributes {
+ DebuggerHidden = 0x1
+ }
+
+ internal struct Record
+ {
+ internal int Attributes;
+ internal int Index;
+ internal int Name; // -> StringHeap
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].Attributes = mr.ReadInt16();
+ records[i].Index = mr.ReadInt16();
+ records[i].Name = mr.ReadStringIndex();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ throw new NotImplementedException ();
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ // Portable PDB
+ sealed class LocalConstantTable : Table<LocalConstantTable.Record>
+ {
+ internal const int Index = 0x34;
+
+ internal struct Record
+ {
+ internal int Name; // -> StringHeap
+ internal int Signature; // -> BlobHeap
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].Name = mr.ReadStringIndex();
+ records[i].Signature = mr.ReadBlobIndex();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ throw new NotImplementedException ();
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ // Portable PDB
+ sealed class ImportScopeTable : Table<ImportScopeTable.Record>
+ {
+ internal const int Index = 0x35;
+
+ internal struct Record
+ {
+ internal int Parent;
+ internal int Imports; // -> BlobHeap
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ // FIXME: Token size
+ records[i].Parent = mr.ReadUInt16();
+ records[i].Imports = mr.ReadBlobIndex();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ throw new NotImplementedException ();
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ // Portable PDB
+ sealed class StateMachineTable : Table<StateMachineTable.Record>
+ {
+ internal const int Index = 0x36;
+
+ internal struct Record
+ {
+ internal int MoveNextMethod;
+ internal int KickoffMethod;
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].MoveNextMethod = mr.ReadUInt16();
+ records[i].KickoffMethod = mr.ReadUInt16();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ throw new NotImplementedException ();
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ // Portable PDB
+ sealed class CustomDebugInformationTable : Table<CustomDebugInformationTable.Record>
+ {
+ internal const int Index = 0x37;
+
+ internal struct Record
+ {
+ internal int Parent;
+ internal int Kind; // -> GuidHeap
+ internal int Value; // -> BlobHeap
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ // FIXME: Token size
+ records[i].Parent = mr.ReadUInt16();
+ records[i].Kind = mr.ReadBlobIndex();
+ records[i].Value = mr.ReadBlobIndex();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ throw new NotImplementedException ();
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ throw new NotImplementedException();
+ }
+ }
}
diff --git a/reflect/Module.cs b/reflect/Module.cs
index d93dba5f..23c14057 100644
--- a/reflect/Module.cs
+++ b/reflect/Module.cs
@@ -156,6 +156,14 @@ namespace IKVM.Reflection
internal readonly GenericParamTable GenericParam = new GenericParamTable();
internal readonly MethodSpecTable MethodSpec = new MethodSpecTable();
internal readonly GenericParamConstraintTable GenericParamConstraint = new GenericParamConstraintTable();
+ internal readonly DocumentTable Document = new DocumentTable();
+ internal readonly MethodDebugInformationTable MethodDebugInformation = new MethodDebugInformationTable();
+ internal readonly LocalScopeTable LocalScope = new LocalScopeTable();
+ internal readonly LocalVariableTable LocalVariable = new LocalVariableTable();
+ internal readonly LocalConstantTable LocalConstant = new LocalConstantTable();
+ internal readonly ImportScopeTable ImportScope = new ImportScopeTable();
+ internal readonly StateMachineTable StateMachine = new StateMachineTable();
+ internal readonly CustomDebugInformationTable CustomDebugInformation = new CustomDebugInformationTable();
protected Module(Universe universe)
{
@@ -204,6 +212,14 @@ namespace IKVM.Reflection
tables[GenericParamTable.Index] = GenericParam;
tables[MethodSpecTable.Index] = MethodSpec;
tables[GenericParamConstraintTable.Index] = GenericParamConstraint;
+ tables[DocumentTable.Index] = Document;
+ tables[MethodDebugInformationTable.Index] = MethodDebugInformation;
+ tables[LocalScopeTable.Index] = LocalScope;
+ tables[LocalVariableTable.Index] = LocalVariable;
+ tables[LocalConstantTable.Index] = LocalConstant;
+ tables[ImportScopeTable.Index] = ImportScope;
+ tables[StateMachineTable.Index] = StateMachine;
+ tables[CustomDebugInformationTable.Index] = CustomDebugInformation;
return tables;
}
@@ -552,6 +568,11 @@ namespace IKVM.Reflection
get { throw new NotSupportedException(); }
}
+ public virtual bool __IsMetadataOnly
+ {
+ get { throw new NotSupportedException(); }
+ }
+
public IEnumerable<CustomAttributeData> __EnumerateCustomAttributeTable()
{
List<CustomAttributeData> list = new List<CustomAttributeData>(CustomAttribute.RowCount);
@@ -594,6 +615,8 @@ namespace IKVM.Reflection
internal abstract ByteReader GetBlob(int blobIndex);
+ internal abstract Guid GetGuid(int guidIndex);
+
internal IList<CustomAttributeData> GetDeclarativeSecurity(int metadataToken)
{
List<CustomAttributeData> list = new List<CustomAttributeData>();
@@ -650,6 +673,11 @@ namespace IKVM.Reflection
throw InvalidOperationException();
}
+ internal sealed override Guid GetGuid(int guidIndex)
+ {
+ throw InvalidOperationException();
+ }
+
public sealed override AssemblyName[] __GetReferencedAssemblies()
{
throw NotSupportedException();
diff --git a/reflect/Reader/ModuleReader.cs b/reflect/Reader/ModuleReader.cs
index 4daa5355..75e703a8 100644
--- a/reflect/Reader/ModuleReader.cs
+++ b/reflect/Reader/ModuleReader.cs
@@ -52,6 +52,13 @@ namespace IKVM.Reflection.Reader
}
}
+ // FIXME: Put this somewhere else
+ class PdbStream {
+ public int EntryPoint { get; set; }
+ public ulong ReferencedTables { get; set; }
+ public int[] TableSizes { get; set; }
+ }
+
sealed class ModuleReader : Module
{
private readonly Stream stream;
@@ -78,6 +85,8 @@ namespace IKVM.Reflection.Reader
private Dictionary<int, string> strings = new Dictionary<int, string>();
private Dictionary<TypeName, Type> types = new Dictionary<TypeName, Type>();
private Dictionary<TypeName, LazyForwardedType> forwardedTypes = new Dictionary<TypeName, LazyForwardedType>();
+ private PdbStream pdbStream;
+ private bool isMetadataOnly;
private sealed class LazyForwardedType
{
@@ -126,10 +135,23 @@ namespace IKVM.Reflection.Reader
private void Read(Stream stream, bool mapped)
{
BinaryReader br = new BinaryReader(stream);
- peFile.Read(br, mapped);
- stream.Seek(peFile.RvaToFileOffset(peFile.GetComDescriptorVirtualAddress()), SeekOrigin.Begin);
- cliHeader.Read(br);
- stream.Seek(peFile.RvaToFileOffset(cliHeader.MetaData.VirtualAddress), SeekOrigin.Begin);
+
+ long pos = stream.Position;
+ uint header = br.ReadUInt32();
+ stream.Seek(pos, SeekOrigin.Begin);
+
+ if (header == 0x424a5342)
+ {
+ // Naked metadata file (enc/portable pdb)
+ this.isMetadataOnly = true;
+ }
+ else
+ {
+ peFile.Read(br, mapped);
+ stream.Seek(peFile.RvaToFileOffset(peFile.GetComDescriptorVirtualAddress()), SeekOrigin.Begin);
+ cliHeader.Read(br);
+ stream.Seek(peFile.RvaToFileOffset(cliHeader.MetaData.VirtualAddress), SeekOrigin.Begin);
+ }
foreach (StreamHeader sh in ReadStreamHeaders(br, out imageRuntimeVersion))
{
switch (sh.Name)
@@ -149,9 +171,26 @@ namespace IKVM.Reflection.Reader
break;
case "#~":
case "#-":
- stream.Seek(peFile.RvaToFileOffset(cliHeader.MetaData.VirtualAddress + sh.Offset), SeekOrigin.Begin);
+ if (isMetadataOnly)
+ {
+ stream.Seek(sh.Offset, SeekOrigin.Begin);
+ }
+ else
+ {
+ stream.Seek(peFile.RvaToFileOffset(cliHeader.MetaData.VirtualAddress + sh.Offset), SeekOrigin.Begin);
+ }
ReadTables(br);
break;
+ case "#Pdb":
+ var entryPoint = br.ReadInt32 ();
+ var referencedTables = br.ReadUInt64 ();
+ var tableSizes = new int [64];
+ for (int i = 0; i < 64; ++i) {
+ if ((referencedTables & ((ulong)1 << i)) != 0)
+ tableSizes [i] = (int)br.ReadUInt32 ();
+ }
+ pdbStream = new PdbStream () { EntryPoint = entryPoint, ReferencedTables = referencedTables, TableSizes = tableSizes };
+ break;
default:
// we ignore unknown streams, because the CLR does so too
// (and some obfuscators add bogus streams)
@@ -204,6 +243,10 @@ namespace IKVM.Reflection.Reader
{
if ((Valid & (1UL << i)) != 0)
{
+ if (tables[i] == null)
+ {
+ throw new NotImplementedException ("Unknown table " + i);
+ }
tables[i].Sorted = (Sorted & (1UL << i)) != 0;
tables[i].RowCount = br.ReadInt32();
}
@@ -225,7 +268,14 @@ namespace IKVM.Reflection.Reader
private byte[] ReadHeap(Stream stream, uint offset, uint size)
{
byte[] buf = new byte[size];
- stream.Seek(peFile.RvaToFileOffset(cliHeader.MetaData.VirtualAddress + offset), SeekOrigin.Begin);
+ if (isMetadataOnly)
+ {
+ stream.Seek(offset, SeekOrigin.Begin);
+ }
+ else
+ {
+ stream.Seek(peFile.RvaToFileOffset(cliHeader.MetaData.VirtualAddress + offset), SeekOrigin.Begin);
+ }
for (int pos = 0; pos < buf.Length; )
{
int read = stream.Read(buf, pos, buf.Length - pos);
@@ -349,6 +399,13 @@ namespace IKVM.Reflection.Reader
return ByteReader.FromBlob(blobHeap, blobIndex);
}
+ internal override Guid GetGuid(int guidIndex)
+ {
+ byte[] buf = new byte[16];
+ Buffer.BlockCopy(guidHeap, 16 * (guidIndex - 1), buf, 0, 16);
+ return new Guid(buf);
+ }
+
public override string ResolveString(int metadataToken)
{
string str;
@@ -1149,8 +1206,17 @@ namespace IKVM.Reflection.Reader
get { return metadataStreamVersion; }
}
+ public override bool __IsMetadataOnly
+ {
+ get { return isMetadataOnly; }
+ }
+
public override void __GetDataDirectoryEntry(int index, out int rva, out int length)
{
+ if (isMetadataOnly)
+ {
+ throw new NotSupportedException();
+ }
peFile.GetDataDirectoryEntry(index, out rva, out length);
}