From 082658b212c4cba98bd3137d8b356d4f2e2369ff Mon Sep 17 00:00:00 2001 From: jfrijters Date: Fri, 13 Jul 2012 09:12:28 +0000 Subject: [PATCH] Bug fix. Don't do the HasCustomAttribute and HasFieldMarshal in the tables, but only when writing the final data. Previously we weren't able to lookup anything in these tables after the module was saved. --- reflect/Metadata/Tables.cs | 303 +++++++++++++++++++------------ reflect/Writer/MetadataWriter.cs | 12 +- 2 files changed, 191 insertions(+), 124 deletions(-) diff --git a/reflect/Metadata/Tables.cs b/reflect/Metadata/Tables.cs index 107b5ce9..d78700f9 100644 --- a/reflect/Metadata/Tables.cs +++ b/reflect/Metadata/Tables.cs @@ -426,11 +426,12 @@ namespace IKVM.Reflection.Metadata } abstract class SortedTable : Table, IComparer - where T : SortedTable.ISortKey + where T : SortedTable.IRecord { - internal interface ISortKey + internal interface IRecord { - int Key { get; } + int SortKey { get; } + int FilterKey { get; } } internal struct Enumerable @@ -457,13 +458,13 @@ namespace IKVM.Reflection.Metadata return new Enumerator(null, 0, 1, -1); } int start = index; - while (start > 0 && (records[start - 1].Key & 0xFFFFFF) == (token & 0xFFFFFF)) + while (start > 0 && (records[start - 1].FilterKey & 0xFFFFFF) == (token & 0xFFFFFF)) { start--; } int end = index; int max = table.RowCount - 1; - while (end < max && (records[end + 1].Key & 0xFFFFFF) == (token & 0xFFFFFF)) + while (end < max && (records[end + 1].FilterKey & 0xFFFFFF) == (token & 0xFFFFFF)) { end++; } @@ -477,7 +478,7 @@ namespace IKVM.Reflection.Metadata while (min <= max) { int mid = min + ((max - min) / 2); - int maskedValue = records[mid].Key & 0xFFFFFF; + int maskedValue = records[mid].FilterKey & 0xFFFFFF; if (maskedToken == maskedValue) { return mid; @@ -520,7 +521,7 @@ namespace IKVM.Reflection.Metadata while (index < max) { index++; - if (records[index].Key == token) + if (records[index].FilterKey == token) { return true; } @@ -552,7 +553,7 @@ namespace IKVM.Reflection.Metadata int IComparer.Compare(int x, int y) { - int rc = records[x].Key.CompareTo(records[y].Key); + int rc = records[x].SortKey.CompareTo(records[y].SortKey); return rc == 0 ? x.CompareTo(y) : rc; } } @@ -879,12 +880,17 @@ namespace IKVM.Reflection.Metadata { internal const int Index = 0x09; - internal struct Record : ISortKey + internal struct Record : IRecord { internal int Class; internal int Interface; - int ISortKey.Key + int IRecord.SortKey + { + get { return Class; } + } + + int IRecord.FilterKey { get { return Class; } } @@ -1013,13 +1019,18 @@ namespace IKVM.Reflection.Metadata { internal const int Index = 0x0B; - internal struct Record : ISortKey + internal struct Record : IRecord { internal short Type; internal int Parent; internal int Value; - int ISortKey.Key + int IRecord.SortKey + { + get { return Parent; } + } + + int IRecord.FilterKey { get { return Parent; } } @@ -1138,13 +1149,18 @@ namespace IKVM.Reflection.Metadata { internal const int Index = 0x0C; - internal struct Record : ISortKey + internal struct Record : IRecord { internal int Parent; internal int Type; internal int Value; - int ISortKey.Key + int IRecord.SortKey + { + get { return EncodeHasCustomAttribute(Parent); } + } + + int IRecord.FilterKey { get { return Parent; } } @@ -1185,87 +1201,79 @@ namespace IKVM.Reflection.Metadata for (int i = 0; i < rowCount; i++) { moduleBuilder.FixupPseudoToken(ref records[i].Type); - int token = records[i].Parent; - moduleBuilder.FixupPseudoToken(ref token); - // do the HasCustomAttribute encoding, so that we can sort the table - switch (token >> 24) + moduleBuilder.FixupPseudoToken(ref records[i].Parent); + if (records[i].Parent >> 24 == GenericParamTable.Index) { - case MethodDefTable.Index: - records[i].Parent = (token & 0xFFFFFF) << 5 | 0; - break; - case FieldTable.Index: - records[i].Parent = (token & 0xFFFFFF) << 5 | 1; - break; - case TypeRefTable.Index: - records[i].Parent = (token & 0xFFFFFF) << 5 | 2; - break; - case TypeDefTable.Index: - records[i].Parent = (token & 0xFFFFFF) << 5 | 3; - break; - case ParamTable.Index: - records[i].Parent = (token & 0xFFFFFF) << 5 | 4; - break; - case InterfaceImplTable.Index: - records[i].Parent = (token & 0xFFFFFF) << 5 | 5; - break; - case MemberRefTable.Index: - records[i].Parent = (token & 0xFFFFFF) << 5 | 6; - break; - case ModuleTable.Index: - records[i].Parent = (token & 0xFFFFFF) << 5 | 7; - break; - // Permission (8) table doesn't exist in the spec - case PropertyTable.Index: - records[i].Parent = (token & 0xFFFFFF) << 5 | 9; - break; - case EventTable.Index: - records[i].Parent = (token & 0xFFFFFF) << 5 | 10; - break; - case StandAloneSigTable.Index: - records[i].Parent = (token & 0xFFFFFF) << 5 | 11; - break; - case ModuleRefTable.Index: - records[i].Parent = (token & 0xFFFFFF) << 5 | 12; - break; - case TypeSpecTable.Index: - records[i].Parent = (token & 0xFFFFFF) << 5 | 13; - break; - case AssemblyTable.Index: - records[i].Parent = (token & 0xFFFFFF) << 5 | 14; - break; - case AssemblyRefTable.Index: - records[i].Parent = (token & 0xFFFFFF) << 5 | 15; - break; - case FileTable.Index: - records[i].Parent = (token & 0xFFFFFF) << 5 | 16; - break; - case ExportedTypeTable.Index: - records[i].Parent = (token & 0xFFFFFF) << 5 | 17; - break; - case ManifestResourceTable.Index: - records[i].Parent = (token & 0xFFFFFF) << 5 | 18; - break; - case GenericParamTable.Index: - records[i].Parent = (genericParamFixup[(token & 0xFFFFFF) - 1] + 1) << 5 | 19; - break; - default: - throw new InvalidOperationException(); + records[i].Parent = (GenericParamTable.Index << 24) + genericParamFixup[(records[i].Parent & 0xFFFFFF) - 1] + 1; } } Sort(); } + + internal static int EncodeHasCustomAttribute(int token) + { + switch (token >> 24) + { + case MethodDefTable.Index: + return (token & 0xFFFFFF) << 5 | 0; + case FieldTable.Index: + return (token & 0xFFFFFF) << 5 | 1; + case TypeRefTable.Index: + return (token & 0xFFFFFF) << 5 | 2; + case TypeDefTable.Index: + return (token & 0xFFFFFF) << 5 | 3; + case ParamTable.Index: + return (token & 0xFFFFFF) << 5 | 4; + case InterfaceImplTable.Index: + return (token & 0xFFFFFF) << 5 | 5; + case MemberRefTable.Index: + return (token & 0xFFFFFF) << 5 | 6; + case ModuleTable.Index: + return (token & 0xFFFFFF) << 5 | 7; + // Permission (8) table doesn't exist in the spec + case PropertyTable.Index: + return (token & 0xFFFFFF) << 5 | 9; + case EventTable.Index: + return (token & 0xFFFFFF) << 5 | 10; + case StandAloneSigTable.Index: + return (token & 0xFFFFFF) << 5 | 11; + case ModuleRefTable.Index: + return (token & 0xFFFFFF) << 5 | 12; + case TypeSpecTable.Index: + return (token & 0xFFFFFF) << 5 | 13; + case AssemblyTable.Index: + return (token & 0xFFFFFF) << 5 | 14; + case AssemblyRefTable.Index: + return (token & 0xFFFFFF) << 5 | 15; + case FileTable.Index: + return (token & 0xFFFFFF) << 5 | 16; + case ExportedTypeTable.Index: + return (token & 0xFFFFFF) << 5 | 17; + case ManifestResourceTable.Index: + return (token & 0xFFFFFF) << 5 | 18; + case GenericParamTable.Index: + return (token & 0xFFFFFF) << 5 | 19; + default: + throw new InvalidOperationException(); + } + } } sealed class FieldMarshalTable : SortedTable { internal const int Index = 0x0D; - internal struct Record : ISortKey + internal struct Record : IRecord { internal int Parent; internal int NativeType; - int ISortKey.Key + int IRecord.SortKey + { + get { return EncodeHasFieldMarshal(Parent); } + } + + int IRecord.FilterKey { get { return Parent; } } @@ -1301,35 +1309,41 @@ namespace IKVM.Reflection.Metadata { for (int i = 0; i < rowCount; i++) { - int token = moduleBuilder.ResolvePseudoToken(records[i].Parent); - // do the HasFieldMarshal encoding, so that we can sort the table - switch (token >> 24) - { - case FieldTable.Index: - records[i].Parent = (token & 0xFFFFFF) << 1 | 0; - break; - case ParamTable.Index: - records[i].Parent = (token & 0xFFFFFF) << 1 | 1; - break; - default: - throw new InvalidOperationException(); - } + records[i].Parent = moduleBuilder.ResolvePseudoToken(records[i].Parent); } Sort(); } + + internal static int EncodeHasFieldMarshal(int token) + { + switch (token >> 24) + { + case FieldTable.Index: + return (token & 0xFFFFFF) << 1 | 0; + case ParamTable.Index: + return (token & 0xFFFFFF) << 1 | 1; + default: + throw new InvalidOperationException(); + } + } } sealed class DeclSecurityTable : SortedTable { internal const int Index = 0x0E; - internal struct Record : ISortKey + internal struct Record : IRecord { internal short Action; internal int Parent; internal int PermissionSet; - int ISortKey.Key + int IRecord.SortKey + { + get { return Parent; } + } + + int IRecord.FilterKey { get { return Parent; } } @@ -1395,13 +1409,18 @@ namespace IKVM.Reflection.Metadata { internal const int Index = 0x0f; - internal struct Record : ISortKey + internal struct Record : IRecord { internal short PackingSize; internal int ClassSize; internal int Parent; - int ISortKey.Key + int IRecord.SortKey + { + get { return Parent; } + } + + int IRecord.FilterKey { get { return Parent; } } @@ -1441,12 +1460,17 @@ namespace IKVM.Reflection.Metadata { internal const int Index = 0x10; - internal struct Record : ISortKey + internal struct Record : IRecord { internal int Offset; internal int Field; - int ISortKey.Key + int IRecord.SortKey + { + get { return Field; } + } + + int IRecord.FilterKey { get { return Field; } } @@ -1530,12 +1554,17 @@ namespace IKVM.Reflection.Metadata { internal const int Index = 0x12; - internal struct Record : ISortKey + internal struct Record : IRecord { internal int Parent; internal int EventList; - int ISortKey.Key + int IRecord.SortKey + { + get { return Parent; } + } + + int IRecord.FilterKey { get { return Parent; } } @@ -1626,12 +1655,17 @@ namespace IKVM.Reflection.Metadata { internal const int Index = 0x15; - internal struct Record : ISortKey + internal struct Record : IRecord { internal int Parent; internal int PropertyList; - int ISortKey.Key + int IRecord.SortKey + { + get { return Parent; } + } + + int IRecord.FilterKey { get { return Parent; } } @@ -1730,13 +1764,18 @@ namespace IKVM.Reflection.Metadata internal const short RemoveOn = 0x0010; internal const short Fire = 0x0020; - internal struct Record : ISortKey + internal struct Record : IRecord { internal short Semantics; internal int Method; internal int Association; - int ISortKey.Key + int IRecord.SortKey + { + get { return Association; } + } + + int IRecord.FilterKey { get { return Association; } } @@ -1846,13 +1885,18 @@ namespace IKVM.Reflection.Metadata { internal const int Index = 0x19; - internal struct Record : ISortKey + internal struct Record : IRecord { internal int Class; internal int MethodBody; internal int MethodDeclaration; - int ISortKey.Key + int IRecord.SortKey + { + get { return Class; } + } + + int IRecord.FilterKey { get { return Class; } } @@ -1968,14 +2012,19 @@ namespace IKVM.Reflection.Metadata { internal const int Index = 0x1C; - internal struct Record : ISortKey + internal struct Record : IRecord { internal short MappingFlags; internal int MemberForwarded; internal int ImportName; internal int ImportScope; - int ISortKey.Key + int IRecord.SortKey + { + get { return MemberForwarded; } + } + + int IRecord.FilterKey { get { return MemberForwarded; } } @@ -2027,12 +2076,17 @@ namespace IKVM.Reflection.Metadata { internal const int Index = 0x1D; - internal struct Record : ISortKey + internal struct Record : IRecord { internal int RVA; // we set the high bit to signify that the RVA is in the CIL stream (instead of .sdata) internal int Field; - int ISortKey.Key + int IRecord.SortKey + { + get { return Field; } + } + + int IRecord.FilterKey { get { return Field; } } @@ -2391,12 +2445,17 @@ namespace IKVM.Reflection.Metadata { internal const int Index = 0x29; - internal struct Record : ISortKey + internal struct Record : IRecord { internal int NestedClass; internal int EnclosingClass; - int ISortKey.Key + int IRecord.SortKey + { + get { return NestedClass; } + } + + int IRecord.FilterKey { get { return NestedClass; } } @@ -2446,7 +2505,7 @@ namespace IKVM.Reflection.Metadata { internal const int Index = 0x2A; - internal struct Record : ISortKey + internal struct Record : IRecord { internal short Number; internal short Flags; @@ -2455,7 +2514,12 @@ namespace IKVM.Reflection.Metadata // not part of the table, we use it to be able to fixup the GenericParamConstraint table internal int unsortedIndex; - int ISortKey.Key + int IRecord.SortKey + { + get { return Owner; } + } + + int IRecord.FilterKey { get { return Owner; } } @@ -2612,12 +2676,17 @@ namespace IKVM.Reflection.Metadata { internal const int Index = 0x2C; - internal struct Record : ISortKey + internal struct Record : IRecord { internal int Owner; internal int Constraint; - int ISortKey.Key + int IRecord.SortKey + { + get { return Owner; } + } + + int IRecord.FilterKey { get { return Owner; } } diff --git a/reflect/Writer/MetadataWriter.cs b/reflect/Writer/MetadataWriter.cs index edb0ddac..d7e36992 100644 --- a/reflect/Writer/MetadataWriter.cs +++ b/reflect/Writer/MetadataWriter.cs @@ -223,10 +223,9 @@ namespace IKVM.Reflection.Writer } } - internal void WriteHasCustomAttribute(int encodedToken) + internal void WriteHasCustomAttribute(int token) { - // NOTE because we've already had to do the encoding (to be able to sort the table) - // here we simple write the value + int encodedToken = CustomAttributeTable.EncodeHasCustomAttribute(token); if (bigHasCustomAttribute) { Write(encodedToken); @@ -547,13 +546,12 @@ namespace IKVM.Reflection.Writer } } - internal void WriteHasFieldMarshal(int encodedToken) + internal void WriteHasFieldMarshal(int token) { - // NOTE because we've already had to do the encoding (to be able to sort the table) - // here we simple write the value + int encodedToken = FieldMarshalTable.EncodeHasFieldMarshal(token); if (bigHasFieldMarshal) { - Write(encodedToken & 0xFFFFFF); + Write(encodedToken); } else {