2
Copyright (C) 2009-2012 Jeroen Frijters
4
This software is provided 'as-is', without any express or implied
5
warranty. In no event will the authors be held liable for any damages
6
arising from the use of this software.
8
Permission is granted to anyone to use this software for any purpose,
9
including commercial applications, and to alter it and redistribute it
10
freely, subject to the following restrictions:
12
1. The origin of this software must not be misrepresented; you must not
13
claim that you wrote the original software. If you use this software
14
in a product, an acknowledgment in the product documentation would be
15
appreciated but is not required.
16
2. Altered source versions must be plainly marked as such, and must not be
17
misrepresented as being the original software.
18
3. This notice may not be removed or altered from any source distribution.
27
using System.Collections.Generic;
28
using IKVM.Reflection.Metadata;
30
namespace IKVM.Reflection.Reader
32
sealed class StreamHeader
38
internal void Read(BinaryReader br)
40
Offset = br.ReadUInt32();
41
Size = br.ReadUInt32();
42
byte[] buf = new byte[32];
45
while ((b = br.ReadByte()) != 0)
49
Name = Encoding.UTF8.GetString(buf, 0, len); ;
50
int padding = -1 + ((len + 4) & ~3) - len;
51
br.BaseStream.Seek(padding, SeekOrigin.Current);
55
sealed class ModuleReader : Module
57
internal readonly Stream stream;
58
private readonly string location;
59
private Assembly assembly;
60
private readonly PEReader peFile = new PEReader();
61
private readonly CliHeader cliHeader = new CliHeader();
62
private string imageRuntimeVersion;
63
private int metadataStreamVersion;
64
private byte[] stringHeap;
65
private byte[] blobHeap;
66
private byte[] userStringHeap;
67
private byte[] guidHeap;
68
private TypeDefImpl[] typeDefs;
69
private TypeDefImpl moduleType;
70
private Assembly[] assemblyRefs;
71
private Type[] typeRefs;
72
private Type[] typeSpecs;
73
private FieldInfo[] fields;
74
private MethodBase[] methods;
75
private MemberInfo[] memberRefs;
76
private Dictionary<int, string> strings = new Dictionary<int, string>();
77
private Dictionary<TypeName, Type> types = new Dictionary<TypeName, Type>();
78
private Dictionary<TypeName, LazyForwardedType> forwardedTypes = new Dictionary<TypeName, LazyForwardedType>();
80
private sealed class LazyForwardedType
82
private readonly int index;
85
internal LazyForwardedType(int index)
90
internal Type GetType(ModuleReader module)
92
return type ?? (type = module.ResolveExportedType(index));
96
internal ModuleReader(AssemblyReader assembly, Universe universe, Stream stream, string location)
100
this.location = location;
102
if (assembly == null && AssemblyTable.records.Length != 0)
104
assembly = new AssemblyReader(location, this);
106
this.assembly = assembly;
111
BinaryReader br = new BinaryReader(stream);
113
stream.Seek(peFile.RvaToFileOffset(peFile.GetComDescriptorVirtualAddress()), SeekOrigin.Begin);
115
stream.Seek(peFile.RvaToFileOffset(cliHeader.MetaData.VirtualAddress), SeekOrigin.Begin);
116
foreach (StreamHeader sh in ReadStreamHeaders(br, out imageRuntimeVersion))
121
stringHeap = ReadHeap(stream, sh);
124
blobHeap = ReadHeap(stream, sh);
127
userStringHeap = ReadHeap(stream, sh);
130
guidHeap = ReadHeap(stream, sh);
134
stream.Seek(peFile.RvaToFileOffset(cliHeader.MetaData.VirtualAddress + sh.Offset), SeekOrigin.Begin);
138
// we ignore unknown streams, because the CLR does so too
139
// (and some obfuscators add bogus streams)
145
internal void SetAssembly(Assembly assembly)
147
this.assembly = assembly;
150
private static StreamHeader[] ReadStreamHeaders(BinaryReader br, out string Version)
152
uint Signature = br.ReadUInt32();
153
if (Signature != 0x424A5342)
155
throw new BadImageFormatException("Invalid metadata signature");
157
/*ushort MajorVersion =*/ br.ReadUInt16();
158
/*ushort MinorVersion =*/ br.ReadUInt16();
159
/*uint Reserved =*/ br.ReadUInt32();
160
uint Length = br.ReadUInt32();
161
byte[] buf = br.ReadBytes((int)Length);
162
Version = Encoding.UTF8.GetString(buf).TrimEnd('\u0000');
163
/*ushort Flags =*/ br.ReadUInt16();
164
ushort Streams = br.ReadUInt16();
165
StreamHeader[] streamHeaders = new StreamHeader[Streams];
166
for (int i = 0; i < streamHeaders.Length; i++)
168
streamHeaders[i] = new StreamHeader();
169
streamHeaders[i].Read(br);
171
return streamHeaders;
174
private void ReadTables(BinaryReader br)
176
Table[] tables = GetTables();
177
/*uint Reserved0 =*/ br.ReadUInt32();
178
byte MajorVersion = br.ReadByte();
179
byte MinorVersion = br.ReadByte();
180
metadataStreamVersion = MajorVersion << 16 | MinorVersion;
181
byte HeapSizes = br.ReadByte();
182
/*byte Reserved7 =*/ br.ReadByte();
183
ulong Valid = br.ReadUInt64();
184
ulong Sorted = br.ReadUInt64();
185
for (int i = 0; i < 64; i++)
187
if ((Valid & (1UL << i)) != 0)
189
tables[i].Sorted = (Sorted & (1UL << i)) != 0;
190
tables[i].RowCount = br.ReadInt32();
193
MetadataReader mr = new MetadataReader(this, br.BaseStream, HeapSizes);
194
for (int i = 0; i < 64; i++)
196
if ((Valid & (1UL << i)) != 0)
201
if (ParamPtr.RowCount != 0)
203
throw new NotImplementedException("ParamPtr table support has not yet been implemented.");
207
private byte[] ReadHeap(Stream stream, StreamHeader sh)
209
byte[] buf = new byte[sh.Size];
210
stream.Seek(peFile.RvaToFileOffset(cliHeader.MetaData.VirtualAddress + sh.Offset), SeekOrigin.Begin);
211
for (int pos = 0; pos < buf.Length; )
213
int read = stream.Read(buf, pos, buf.Length - pos);
216
throw new BadImageFormatException();
223
internal void SeekRVA(int rva)
225
stream.Seek(peFile.RvaToFileOffset((uint)rva), SeekOrigin.Begin);
228
internal override void GetTypesImpl(List<Type> list)
231
foreach (TypeDefImpl type in typeDefs)
233
if (type != moduleType)
240
private void PopulateTypeDef()
242
if (typeDefs == null)
244
typeDefs = new TypeDefImpl[TypeDef.records.Length];
245
for (int i = 0; i < typeDefs.Length; i++)
247
TypeDefImpl type = new TypeDefImpl(this, i);
249
if (type.IsModulePseudoType)
253
else if (!type.IsNestedByFlags)
255
types.Add(new TypeName(type.__Namespace, type.__Name), type);
258
// add forwarded types to forwardedTypes dictionary (because Module.GetType(string) should return them)
259
for (int i = 0; i < ExportedType.records.Length; i++)
261
int implementation = ExportedType.records[i].Implementation;
262
if (implementation >> 24 == AssemblyRefTable.Index)
264
TypeName typeName = GetTypeName(ExportedType.records[i].TypeNamespace, ExportedType.records[i].TypeName);
265
forwardedTypes.Add(typeName, new LazyForwardedType(i));
271
internal override string GetString(int index)
278
if (!strings.TryGetValue(index, out str))
281
while (stringHeap[index + len] != 0)
285
str = Encoding.UTF8.GetString(stringHeap, index, len);
286
strings.Add(index, str);
291
private static int ReadCompressedUInt(byte[] buffer, ref int offset)
293
byte b1 = buffer[offset++];
298
else if ((b1 & 0xC0) == 0x80)
300
byte b2 = buffer[offset++];
301
return ((b1 & 0x3F) << 8) | b2;
305
byte b2 = buffer[offset++];
306
byte b3 = buffer[offset++];
307
byte b4 = buffer[offset++];
308
return ((b1 & 0x3F) << 24) + (b2 << 16) + (b3 << 8) + b4;
312
internal byte[] GetBlobCopy(int blobIndex)
314
int len = ReadCompressedUInt(blobHeap, ref blobIndex);
315
byte[] buf = new byte[len];
316
Buffer.BlockCopy(blobHeap, blobIndex, buf, 0, len);
320
internal override ByteReader GetBlob(int blobIndex)
322
return ByteReader.FromBlob(blobHeap, blobIndex);
325
public override string ResolveString(int metadataToken)
328
if (!strings.TryGetValue(metadataToken, out str))
330
if ((metadataToken >> 24) != 0x70)
332
throw TokenOutOfRangeException(metadataToken);
334
int index = metadataToken & 0xFFFFFF;
335
int len = ReadCompressedUInt(userStringHeap, ref index) & ~1;
336
StringBuilder sb = new StringBuilder(len / 2);
337
for (int i = 0; i < len; i += 2)
339
char ch = (char)(userStringHeap[index + i] | userStringHeap[index + i + 1] << 8);
343
strings.Add(metadataToken, str);
348
internal override Type ResolveType(int metadataToken, IGenericContext context)
350
int index = (metadataToken & 0xFFFFFF) - 1;
353
throw TokenOutOfRangeException(metadataToken);
355
else if ((metadataToken >> 24) == TypeDefTable.Index && index < TypeDef.RowCount)
358
return typeDefs[index];
360
else if ((metadataToken >> 24) == TypeRefTable.Index && index < TypeRef.RowCount)
362
if (typeRefs == null)
364
typeRefs = new Type[TypeRef.records.Length];
366
if (typeRefs[index] == null)
368
int scope = TypeRef.records[index].ResolutionScope;
371
case AssemblyRefTable.Index:
373
Assembly assembly = ResolveAssemblyRef((scope & 0xFFFFFF) - 1);
374
TypeName typeName = GetTypeName(TypeRef.records[index].TypeNameSpace, TypeRef.records[index].TypeName);
375
typeRefs[index] = assembly.ResolveType(typeName);
378
case TypeRefTable.Index:
380
Type outer = ResolveType(scope, null);
381
TypeName typeName = GetTypeName(TypeRef.records[index].TypeNameSpace, TypeRef.records[index].TypeName);
382
typeRefs[index] = outer.ResolveNestedType(typeName);
385
case ModuleTable.Index:
386
case ModuleRefTable.Index:
389
if (scope >> 24 == ModuleTable.Index)
391
if (scope == 0 || scope == 1)
397
throw new NotImplementedException("self reference scope?");
402
module = ResolveModuleRef(ModuleRef.records[(scope & 0xFFFFFF) - 1]);
404
TypeName typeName = GetTypeName(TypeRef.records[index].TypeNameSpace, TypeRef.records[index].TypeName);
405
typeRefs[index] = module.FindType(typeName) ?? module.universe.GetMissingTypeOrThrow(module, null, typeName);
409
throw new NotImplementedException("ResolutionScope = " + scope.ToString("X"));
412
return typeRefs[index];
414
else if ((metadataToken >> 24) == TypeSpecTable.Index && index < TypeSpec.RowCount)
416
if (typeSpecs == null)
418
typeSpecs = new Type[TypeSpec.records.Length];
420
Type type = typeSpecs[index];
423
TrackingGenericContext tc = context == null ? null : new TrackingGenericContext(context);
424
type = Signature.ReadTypeSpec(this, ByteReader.FromBlob(blobHeap, TypeSpec.records[index]), tc);
425
if (tc == null || !tc.IsUsed)
427
typeSpecs[index] = type;
434
throw TokenOutOfRangeException(metadataToken);
438
private Module ResolveModuleRef(int moduleNameIndex)
440
string moduleName = GetString(moduleNameIndex);
441
Module module = assembly.GetModule(moduleName);
444
throw new FileNotFoundException(moduleName);
449
private sealed class TrackingGenericContext : IGenericContext
451
private readonly IGenericContext context;
454
internal TrackingGenericContext(IGenericContext context)
456
this.context = context;
464
public Type GetGenericTypeArgument(int index)
467
return context.GetGenericTypeArgument(index);
470
public Type GetGenericMethodArgument(int index)
473
return context.GetGenericMethodArgument(index);
477
private TypeName GetTypeName(int typeNamespace, int typeName)
479
return new TypeName(GetString(typeNamespace), GetString(typeName));
482
internal Assembly ResolveAssemblyRef(int index)
484
if (assemblyRefs == null)
486
assemblyRefs = new Assembly[AssemblyRef.RowCount];
488
if (assemblyRefs[index] == null)
490
assemblyRefs[index] = ResolveAssemblyRefImpl(ref AssemblyRef.records[index]);
492
return assemblyRefs[index];
495
private Assembly ResolveAssemblyRefImpl(ref AssemblyRefTable.Record rec)
497
const int PublicKey = 0x0001;
498
string name = String.Format("{0}, Version={1}.{2}.{3}.{4}, Culture={5}, {6}={7}",
504
rec.Culture == 0 ? "neutral" : GetString(rec.Culture),
505
(rec.Flags & PublicKey) == 0 ? "PublicKeyToken" : "PublicKey",
506
PublicKeyOrTokenToString(rec.PublicKeyOrToken));
507
return universe.Load(name, this.Assembly, true);
510
private string PublicKeyOrTokenToString(int publicKeyOrToken)
512
if (publicKeyOrToken == 0)
516
ByteReader br = GetBlob(publicKeyOrToken);
521
StringBuilder sb = new StringBuilder(br.Length * 2);
522
while (br.Length > 0)
524
sb.AppendFormat("{0:x2}", br.ReadByte());
526
return sb.ToString();
529
public override Guid ModuleVersionId
533
byte[] buf = new byte[16];
534
Buffer.BlockCopy(guidHeap, 16 * (ModuleTable.records[0].Mvid - 1), buf, 0, 16);
535
return new Guid(buf);
539
public override string FullyQualifiedName
541
get { return location ?? "<Unknown>"; }
544
public override string Name
546
get { return location == null ? "<Unknown>" : System.IO.Path.GetFileName(location); }
549
public override Assembly Assembly
551
get { return assembly; }
554
internal override Type FindType(TypeName typeName)
558
if (!types.TryGetValue(typeName, out type))
560
LazyForwardedType fw;
561
if (forwardedTypes.TryGetValue(typeName, out fw))
563
return fw.GetType(this);
569
internal override Type FindTypeIgnoreCase(TypeName lowerCaseName)
572
foreach (Type type in types.Values)
574
if (new TypeName(type.__Namespace, type.__Name).ToLowerInvariant() == lowerCaseName)
579
foreach (TypeName name in forwardedTypes.Keys)
581
if (name.ToLowerInvariant() == lowerCaseName)
583
return forwardedTypes[name].GetType(this);
589
private Exception TokenOutOfRangeException(int metadataToken)
591
return new ArgumentOutOfRangeException("metadataToken", String.Format("Token 0x{0:x8} is not valid in the scope of module {1}.", metadataToken, this.Name));
594
public override MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
596
switch (metadataToken >> 24)
598
case FieldTable.Index:
599
return ResolveField(metadataToken, genericTypeArguments, genericMethodArguments);
600
case MemberRefTable.Index:
601
int index = (metadataToken & 0xFFFFFF) - 1;
602
if (index < 0 || index >= MemberRef.RowCount)
606
return GetMemberRef(index, genericTypeArguments, genericMethodArguments);
607
case MethodDefTable.Index:
608
case MethodSpecTable.Index:
609
return ResolveMethod(metadataToken, genericTypeArguments, genericMethodArguments);
610
case TypeRefTable.Index:
611
case TypeDefTable.Index:
612
case TypeSpecTable.Index:
613
return ResolveType(metadataToken, genericTypeArguments, genericMethodArguments);
615
throw TokenOutOfRangeException(metadataToken);
619
internal FieldInfo GetFieldAt(TypeDefImpl owner, int index)
623
fields = new FieldInfo[Field.records.Length];
625
if (fields[index] == null)
627
fields[index] = new FieldDefImpl(this, owner ?? FindFieldOwner(index), index);
629
return fields[index];
632
public override FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
634
int index = (metadataToken & 0xFFFFFF) - 1;
637
throw TokenOutOfRangeException(metadataToken);
639
else if ((metadataToken >> 24) == FieldTable.Index && index < Field.RowCount)
641
return GetFieldAt(null, index);
643
else if ((metadataToken >> 24) == MemberRefTable.Index && index < MemberRef.RowCount)
645
FieldInfo field = GetMemberRef(index, genericTypeArguments, genericMethodArguments) as FieldInfo;
650
throw new ArgumentException(String.Format("Token 0x{0:x8} is not a valid FieldInfo token in the scope of module {1}.", metadataToken, this.Name), "metadataToken");
654
throw TokenOutOfRangeException(metadataToken);
658
private TypeDefImpl FindFieldOwner(int fieldIndex)
660
// TODO use binary search?
661
for (int i = 0; i < TypeDef.records.Length; i++)
663
int field = TypeDef.records[i].FieldList - 1;
664
int end = TypeDef.records.Length > i + 1 ? TypeDef.records[i + 1].FieldList - 1 : Field.records.Length;
665
if (field <= fieldIndex && fieldIndex < end)
671
throw new InvalidOperationException();
674
internal MethodBase GetMethodAt(TypeDefImpl owner, int index)
678
methods = new MethodBase[MethodDef.records.Length];
680
if (methods[index] == null)
682
MethodDefImpl method = new MethodDefImpl(this, owner ?? FindMethodOwner(index), index);
683
methods[index] = method.IsConstructor ? new ConstructorInfoImpl(method) : (MethodBase)method;
685
return methods[index];
688
public override MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
690
int index = (metadataToken & 0xFFFFFF) - 1;
693
throw TokenOutOfRangeException(metadataToken);
695
else if ((metadataToken >> 24) == MethodDefTable.Index && index < MethodDef.RowCount)
697
return GetMethodAt(null, index);
699
else if ((metadataToken >> 24) == MemberRefTable.Index && index < MemberRef.RowCount)
701
MethodBase method = GetMemberRef(index, genericTypeArguments, genericMethodArguments) as MethodBase;
706
throw new ArgumentException(String.Format("Token 0x{0:x8} is not a valid MethodBase token in the scope of module {1}.", metadataToken, this.Name), "metadataToken");
708
else if ((metadataToken >> 24) == MethodSpecTable.Index && index < MethodSpec.RowCount)
710
MethodInfo method = (MethodInfo)ResolveMethod(MethodSpec.records[index].Method, genericTypeArguments, genericMethodArguments);
711
ByteReader instantiation = ByteReader.FromBlob(blobHeap, MethodSpec.records[index].Instantiation);
712
return method.MakeGenericMethod(Signature.ReadMethodSpec(this, instantiation, new GenericContext(genericTypeArguments, genericMethodArguments)));
716
throw TokenOutOfRangeException(metadataToken);
720
public override Type[] __ResolveOptionalParameterTypes(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments, out CustomModifiers[] customModifiers)
722
int index = (metadataToken & 0xFFFFFF) - 1;
725
throw TokenOutOfRangeException(metadataToken);
727
else if ((metadataToken >> 24) == MemberRefTable.Index && index < MemberRef.RowCount)
729
int sig = MemberRef.records[index].Signature;
730
return Signature.ReadOptionalParameterTypes(this, GetBlob(sig), new GenericContext(genericTypeArguments, genericMethodArguments), out customModifiers);
732
else if ((metadataToken >> 24) == MethodDefTable.Index && index < MethodDef.RowCount)
734
// for convenience, we support passing a MethodDef token as well, because in some places
735
// it makes sense to have a vararg method that is referred to by its methoddef (e.g. ldftn).
736
// Note that MethodSpec doesn't make sense, because generic methods cannot be vararg.
737
customModifiers = Empty<CustomModifiers>.Array;
738
return Type.EmptyTypes;
742
throw TokenOutOfRangeException(metadataToken);
746
public override string ScopeName
748
get { return GetString(ModuleTable.records[0].Name); }
751
private TypeDefImpl FindMethodOwner(int methodIndex)
753
// TODO use binary search?
754
for (int i = 0; i < TypeDef.records.Length; i++)
756
int method = TypeDef.records[i].MethodList - 1;
757
int end = TypeDef.records.Length > i + 1 ? TypeDef.records[i + 1].MethodList - 1 : MethodDef.records.Length;
758
if (method <= methodIndex && methodIndex < end)
764
throw new InvalidOperationException();
767
private MemberInfo GetMemberRef(int index, Type[] genericTypeArguments, Type[] genericMethodArguments)
769
if (memberRefs == null)
771
memberRefs = new MemberInfo[MemberRef.records.Length];
773
if (memberRefs[index] == null)
775
int owner = MemberRef.records[index].Class;
776
int sig = MemberRef.records[index].Signature;
777
string name = GetString(MemberRef.records[index].Name);
780
case MethodDefTable.Index:
781
return GetMethodAt(null, (owner & 0xFFFFFF) - 1);
782
case ModuleRefTable.Index:
783
memberRefs[index] = ResolveTypeMemberRef(ResolveModuleType(owner), name, ByteReader.FromBlob(blobHeap, sig));
785
case TypeDefTable.Index:
786
case TypeRefTable.Index:
787
memberRefs[index] = ResolveTypeMemberRef(ResolveType(owner), name, ByteReader.FromBlob(blobHeap, sig));
789
case TypeSpecTable.Index:
791
Type type = ResolveType(owner, genericTypeArguments, genericMethodArguments);
794
MethodSignature methodSig = MethodSignature.ReadSig(this, ByteReader.FromBlob(blobHeap, sig), new GenericContext(genericTypeArguments, genericMethodArguments));
795
return type.FindMethod(name, methodSig)
796
?? universe.GetMissingMethodOrThrow(type, name, methodSig);
798
else if (type.IsConstructedGenericType)
800
MemberInfo member = ResolveTypeMemberRef(type.GetGenericTypeDefinition(), name, ByteReader.FromBlob(blobHeap, sig));
801
MethodBase mb = member as MethodBase;
804
member = mb.BindTypeParameters(type);
806
FieldInfo fi = member as FieldInfo;
809
member = fi.BindTypeParameters(type);
815
return ResolveTypeMemberRef(type, name, ByteReader.FromBlob(blobHeap, sig));
819
throw new BadImageFormatException();
822
return memberRefs[index];
825
private Type ResolveModuleType(int token)
827
int index = (token & 0xFFFFFF) - 1;
828
string name = GetString(ModuleRef.records[index]);
829
Module module = assembly.GetModule(name);
830
if (module == null || module.IsResource())
832
throw new BadImageFormatException();
834
return module.GetModuleType();
837
private MemberInfo ResolveTypeMemberRef(Type type, string name, ByteReader sig)
839
if (sig.PeekByte() == Signature.FIELD)
842
FieldSignature fieldSig = FieldSignature.ReadSig(this, sig, type);
843
FieldInfo field = type.FindField(name, fieldSig);
844
if (field == null && universe.MissingMemberResolution)
846
return universe.GetMissingFieldOrThrow(type, name, fieldSig);
848
while (field == null && (type = type.BaseType) != null)
850
field = type.FindField(name, fieldSig);
856
throw new MissingFieldException(org.ToString(), name);
861
MethodSignature methodSig = MethodSignature.ReadSig(this, sig, type);
862
MethodBase method = type.FindMethod(name, methodSig);
863
if (method == null && universe.MissingMemberResolution)
865
return universe.GetMissingMethodOrThrow(type, name, methodSig);
867
while (method == null && (type = type.BaseType) != null)
869
method = type.FindMethod(name, methodSig);
875
throw new MissingMethodException(org.ToString(), name);
879
internal ByteReader GetStandAloneSig(int index)
881
return ByteReader.FromBlob(blobHeap, StandAloneSig.records[index]);
884
public override byte[] ResolveSignature(int metadataToken)
886
int index = (metadataToken & 0xFFFFFF) - 1;
887
if ((metadataToken >> 24) == StandAloneSigTable.Index && index >= 0 && index < StandAloneSig.RowCount)
889
ByteReader br = GetStandAloneSig(index);
890
return br.ReadBytes(br.Length);
894
throw TokenOutOfRangeException(metadataToken);
898
public override __StandAloneMethodSig __ResolveStandAloneMethodSig(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
900
int index = (metadataToken & 0xFFFFFF) - 1;
901
if ((metadataToken >> 24) == StandAloneSigTable.Index && index >= 0 && index < StandAloneSig.RowCount)
903
return MethodSignature.ReadStandAloneMethodSig(this, GetStandAloneSig(index), new GenericContext(genericTypeArguments, genericMethodArguments));
907
throw TokenOutOfRangeException(metadataToken);
911
internal MethodInfo GetEntryPoint()
913
if (cliHeader.EntryPointToken != 0 && (cliHeader.Flags & CliHeader.COMIMAGE_FLAGS_NATIVE_ENTRYPOINT) == 0)
915
return (MethodInfo)ResolveMethod((int)cliHeader.EntryPointToken);
920
internal string[] GetManifestResourceNames()
922
string[] names = new string[ManifestResource.records.Length];
923
for (int i = 0; i < ManifestResource.records.Length; i++)
925
names[i] = GetString(ManifestResource.records[i].Name);
930
internal ManifestResourceInfo GetManifestResourceInfo(string resourceName)
932
for (int i = 0; i < ManifestResource.records.Length; i++)
934
if (resourceName == GetString(ManifestResource.records[i].Name))
936
ManifestResourceInfo info = new ManifestResourceInfo(this, i);
937
Assembly asm = info.ReferencedAssembly;
938
if (asm != null && !asm.__IsMissing && asm.GetManifestResourceInfo(resourceName) == null)
948
internal Stream GetManifestResourceStream(string resourceName)
950
for (int i = 0; i < ManifestResource.records.Length; i++)
952
if (resourceName == GetString(ManifestResource.records[i].Name))
954
if (ManifestResource.records[i].Implementation != 0x26000000)
956
ManifestResourceInfo info = new ManifestResourceInfo(this, i);
957
switch (ManifestResource.records[i].Implementation >> 24)
959
case FileTable.Index:
960
string fileName = Path.Combine(Path.GetDirectoryName(location), info.FileName);
961
if (System.IO.File.Exists(fileName))
963
// note that, like System.Reflection, we return null for zero length files and
964
// ManifestResource.Offset is ignored
965
FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete);
974
case AssemblyRefTable.Index:
975
Assembly asm = info.ReferencedAssembly;
980
return asm.GetManifestResourceStream(resourceName);
982
throw new BadImageFormatException();
985
SeekRVA((int)cliHeader.Resources.VirtualAddress + ManifestResource.records[i].Offset);
986
BinaryReader br = new BinaryReader(stream);
987
int length = br.ReadInt32();
988
return new MemoryStream(br.ReadBytes(length));
994
public override AssemblyName[] __GetReferencedAssemblies()
996
List<AssemblyName> list = new List<AssemblyName>();
997
for (int i = 0; i < AssemblyRef.records.Length; i++)
999
AssemblyName name = new AssemblyName();
1000
name.Name = GetString(AssemblyRef.records[i].Name);
1001
name.Version = new Version(
1002
AssemblyRef.records[i].MajorVersion,
1003
AssemblyRef.records[i].MinorVersion,
1004
AssemblyRef.records[i].BuildNumber,
1005
AssemblyRef.records[i].RevisionNumber);
1006
if (AssemblyRef.records[i].PublicKeyOrToken != 0)
1008
byte[] keyOrToken = GetBlobCopy(AssemblyRef.records[i].PublicKeyOrToken);
1009
const int PublicKey = 0x0001;
1010
if ((AssemblyRef.records[i].Flags & PublicKey) != 0)
1012
name.SetPublicKey(keyOrToken);
1016
name.SetPublicKeyToken(keyOrToken);
1021
name.SetPublicKeyToken(Empty<byte>.Array);
1023
if (AssemblyRef.records[i].Culture != 0)
1025
name.Culture = GetString(AssemblyRef.records[i].Culture);
1031
if (AssemblyRef.records[i].HashValue != 0)
1033
name.hash = GetBlobCopy(AssemblyRef.records[i].HashValue);
1035
name.Flags = (AssemblyNameFlags)AssemblyRef.records[i].Flags;
1038
return list.ToArray();
1041
public override void __ResolveReferencedAssemblies(Assembly[] assemblies)
1043
if (assemblyRefs == null)
1045
assemblyRefs = new Assembly[AssemblyRef.RowCount];
1047
for (int i = 0; i < assemblies.Length; i++)
1049
if (assemblyRefs[i] == null)
1051
assemblyRefs[i] = assemblies[i];
1056
public override string[] __GetReferencedModules()
1058
string[] arr = new string[this.ModuleRef.RowCount];
1059
for (int i = 0; i < arr.Length; i++)
1061
arr[i] = GetString(this.ModuleRef.records[i]);
1066
public override Type[] __GetReferencedTypes()
1068
Type[] arr = new Type[this.TypeRef.RowCount];
1069
for (int i = 0; i < arr.Length; i++)
1071
arr[i] = ResolveType((TypeRefTable.Index << 24) + i + 1);
1076
public override Type[] __GetExportedTypes()
1078
Type[] arr = new Type[this.ExportedType.RowCount];
1079
for (int i = 0; i < arr.Length; i++)
1081
arr[i] = ResolveExportedType(i);
1086
private Type ResolveExportedType(int index)
1088
TypeName typeName = GetTypeName(ExportedType.records[index].TypeNamespace, ExportedType.records[index].TypeName);
1089
int implementation = ExportedType.records[index].Implementation;
1090
int token = ExportedType.records[index].TypeDefId;
1091
int flags = ExportedType.records[index].Flags;
1092
switch (implementation >> 24)
1094
case AssemblyRefTable.Index:
1095
return ResolveAssemblyRef((implementation & 0xFFFFFF) - 1).ResolveType(typeName).SetMetadataTokenForMissing(token, flags);
1096
case ExportedTypeTable.Index:
1097
return ResolveExportedType((implementation & 0xFFFFFF) - 1).ResolveNestedType(typeName).SetMetadataTokenForMissing(token, flags);
1098
case FileTable.Index:
1099
Module module = assembly.GetModule(GetString(File.records[(implementation & 0xFFFFFF) - 1].Name));
1100
return module.FindType(typeName) ?? module.universe.GetMissingTypeOrThrow(module, null, typeName).SetMetadataTokenForMissing(token, flags);
1102
throw new BadImageFormatException();
1106
internal override Type GetModuleType()
1112
public override string __ImageRuntimeVersion
1114
get { return imageRuntimeVersion; }
1117
public override int MDStreamVersion
1119
get { return metadataStreamVersion; }
1122
public override void __GetDataDirectoryEntry(int index, out int rva, out int length)
1124
peFile.GetDataDirectoryEntry(index, out rva, out length);
1127
public override long __RelativeVirtualAddressToFileOffset(int rva)
1129
return peFile.RvaToFileOffset((uint)rva);
1132
public override bool __GetSectionInfo(int rva, out string name, out int characteristics)
1134
return peFile.GetSectionInfo(rva, out name, out characteristics);
1137
public override int __ReadDataFromRVA(int rva, byte[] data, int offset, int length)
1140
int totalBytesRead = 0;
1143
int read = stream.Read(data, offset, length);
1146
// C++ assemblies can have fields that have an RVA that lies outside of the file
1151
totalBytesRead += read;
1153
return totalBytesRead;
1156
public override void GetPEKind(out PortableExecutableKinds peKind, out ImageFileMachine machine)
1159
if ((cliHeader.Flags & CliHeader.COMIMAGE_FLAGS_ILONLY) != 0)
1161
peKind |= PortableExecutableKinds.ILOnly;
1163
switch (cliHeader.Flags & (CliHeader.COMIMAGE_FLAGS_32BITREQUIRED | CliHeader.COMIMAGE_FLAGS_32BITPREFERRED))
1165
case CliHeader.COMIMAGE_FLAGS_32BITREQUIRED:
1166
peKind |= PortableExecutableKinds.Required32Bit;
1168
case CliHeader.COMIMAGE_FLAGS_32BITREQUIRED | CliHeader.COMIMAGE_FLAGS_32BITPREFERRED:
1169
peKind |= PortableExecutableKinds.Preferred32Bit;
1172
// COMIMAGE_FLAGS_32BITPREFERRED by itself is illegal, so we ignore it
1173
// (not setting any flag is ok)
1176
if (peFile.OptionalHeader.Magic == IMAGE_OPTIONAL_HEADER.IMAGE_NT_OPTIONAL_HDR64_MAGIC)
1178
peKind |= PortableExecutableKinds.PE32Plus;
1181
machine = (ImageFileMachine)peFile.FileHeader.Machine;
1184
public override int __Subsystem
1186
get { return peFile.OptionalHeader.Subsystem; }
1189
public override IList<CustomAttributeData> __GetPlaceholderAssemblyCustomAttributes(bool multiple, bool security)
1192
switch ((multiple ? 1 : 0) + (security ? 2 : 0))
1195
typeName = new TypeName("System.Runtime.CompilerServices", "AssemblyAttributesGoHere");
1198
typeName = new TypeName("System.Runtime.CompilerServices", "AssemblyAttributesGoHereM");
1201
typeName = new TypeName("System.Runtime.CompilerServices", "AssemblyAttributesGoHereS");
1205
typeName = new TypeName("System.Runtime.CompilerServices", "AssemblyAttributesGoHereSM");
1208
List<CustomAttributeData> list = new List<CustomAttributeData>();
1209
for (int i = 0; i < CustomAttribute.records.Length; i++)
1211
if ((CustomAttribute.records[i].Parent >> 24) == TypeRefTable.Index)
1213
int index = (CustomAttribute.records[i].Parent & 0xFFFFFF) - 1;
1214
if (typeName == GetTypeName(TypeRef.records[index].TypeNameSpace, TypeRef.records[index].TypeName))
1216
list.Add(new CustomAttributeData(this, i));
1223
internal override void Dispose()
1228
internal override void ExportTypes(int fileToken, IKVM.Reflection.Emit.ModuleBuilder manifestModule)
1231
manifestModule.ExportTypes(typeDefs, fileToken);
1234
protected override long GetImageBaseImpl()
1236
return (long)peFile.OptionalHeader.ImageBase;
1239
protected override long GetStackReserveImpl()
1241
return (long)peFile.OptionalHeader.SizeOfStackReserve;
1244
protected override int GetFileAlignmentImpl()
1246
return (int)peFile.OptionalHeader.FileAlignment;
1249
protected override DllCharacteristics GetDllCharacteristicsImpl()
1251
return (DllCharacteristics)peFile.OptionalHeader.DllCharacteristics;
1254
public override int __EntryPointRVA
1256
get { return (cliHeader.Flags & CliHeader.COMIMAGE_FLAGS_NATIVE_ENTRYPOINT) != 0 ? (int)cliHeader.EntryPointToken : 0; }
1259
public override int __EntryPointToken
1261
get { return (cliHeader.Flags & CliHeader.COMIMAGE_FLAGS_NATIVE_ENTRYPOINT) == 0 ? (int)cliHeader.EntryPointToken : 0; }
1264
#if !NO_AUTHENTICODE
1265
public override System.Security.Cryptography.X509Certificates.X509Certificate GetSignerCertificate()
1267
return Authenticode.GetSignerCertificate(stream);
1269
#endif // !NO_AUTHENTICODE