2014-08-13 10:39:27 +01:00
|
|
|
/*
|
|
|
|
Copyright (C) 2009-2012 Jeroen Frijters
|
|
|
|
|
|
|
|
This software is provided 'as-is', without any express or implied
|
|
|
|
warranty. In no event will the authors be held liable for any damages
|
|
|
|
arising from the use of this software.
|
|
|
|
|
|
|
|
Permission is granted to anyone to use this software for any purpose,
|
|
|
|
including commercial applications, and to alter it and redistribute it
|
|
|
|
freely, subject to the following restrictions:
|
|
|
|
|
|
|
|
1. The origin of this software must not be misrepresented; you must not
|
|
|
|
claim that you wrote the original software. If you use this software
|
|
|
|
in a product, an acknowledgment in the product documentation would be
|
|
|
|
appreciated but is not required.
|
|
|
|
2. Altered source versions must be plainly marked as such, and must not be
|
|
|
|
misrepresented as being the original software.
|
|
|
|
3. This notice may not be removed or altered from any source distribution.
|
|
|
|
|
|
|
|
Jeroen Frijters
|
|
|
|
jeroen@frijters.net
|
|
|
|
|
|
|
|
*/
|
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Text;
|
|
|
|
using IKVM.Reflection.Emit;
|
|
|
|
using IKVM.Reflection.Writer;
|
|
|
|
using IKVM.Reflection.Reader;
|
|
|
|
|
|
|
|
namespace IKVM.Reflection.Metadata
|
|
|
|
{
|
|
|
|
internal abstract class Table
|
|
|
|
{
|
|
|
|
internal bool Sorted;
|
|
|
|
|
|
|
|
internal bool IsBig
|
|
|
|
{
|
|
|
|
get { return RowCount > 65535; }
|
|
|
|
}
|
|
|
|
|
|
|
|
internal abstract int RowCount { get; set; }
|
|
|
|
|
|
|
|
internal abstract void Write(MetadataWriter mw);
|
|
|
|
internal abstract void Read(MetadataReader mr);
|
|
|
|
|
|
|
|
internal int GetLength(MetadataWriter md)
|
|
|
|
{
|
|
|
|
return RowCount * GetRowSize(new RowSizeCalc(md));
|
|
|
|
}
|
|
|
|
|
|
|
|
protected abstract int GetRowSize(RowSizeCalc rsc);
|
|
|
|
|
|
|
|
protected sealed class RowSizeCalc
|
|
|
|
{
|
|
|
|
private readonly MetadataWriter mw;
|
|
|
|
private int size;
|
|
|
|
|
|
|
|
internal RowSizeCalc(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
this.mw = mw;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal RowSizeCalc AddFixed(int size)
|
|
|
|
{
|
|
|
|
this.size += size;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal RowSizeCalc WriteStringIndex()
|
|
|
|
{
|
|
|
|
if (mw.bigStrings)
|
|
|
|
{
|
|
|
|
this.size += 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.size += 2;
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal RowSizeCalc WriteGuidIndex()
|
|
|
|
{
|
|
|
|
if (mw.bigGuids)
|
|
|
|
{
|
|
|
|
this.size += 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.size += 2;
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal RowSizeCalc WriteBlobIndex()
|
|
|
|
{
|
|
|
|
if (mw.bigBlobs)
|
|
|
|
{
|
|
|
|
this.size += 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.size += 2;
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal RowSizeCalc WriteTypeDefOrRef()
|
|
|
|
{
|
|
|
|
if (mw.bigTypeDefOrRef)
|
|
|
|
{
|
|
|
|
this.size += 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.size += 2;
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal RowSizeCalc WriteField()
|
|
|
|
{
|
|
|
|
if (mw.bigField)
|
|
|
|
{
|
|
|
|
size += 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
size += 2;
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal RowSizeCalc WriteMethodDef()
|
|
|
|
{
|
|
|
|
if (mw.bigMethodDef)
|
|
|
|
{
|
|
|
|
this.size += 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.size += 2;
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal RowSizeCalc WriteParam()
|
|
|
|
{
|
|
|
|
if (mw.bigParam)
|
|
|
|
{
|
|
|
|
this.size += 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.size += 2;
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal RowSizeCalc WriteResolutionScope()
|
|
|
|
{
|
|
|
|
if (mw.bigResolutionScope)
|
|
|
|
{
|
|
|
|
this.size += 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.size += 2;
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal RowSizeCalc WriteMemberRefParent()
|
|
|
|
{
|
|
|
|
if (mw.bigMemberRefParent)
|
|
|
|
{
|
|
|
|
this.size += 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.size += 2;
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal RowSizeCalc WriteHasCustomAttribute()
|
|
|
|
{
|
|
|
|
if (mw.bigHasCustomAttribute)
|
|
|
|
{
|
|
|
|
size += 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
size += 2;
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal RowSizeCalc WriteCustomAttributeType()
|
|
|
|
{
|
|
|
|
if (mw.bigCustomAttributeType)
|
|
|
|
{
|
|
|
|
this.size += 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.size += 2;
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal RowSizeCalc WriteHasConstant()
|
|
|
|
{
|
|
|
|
if (mw.bigHasConstant)
|
|
|
|
{
|
|
|
|
size += 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
size += 2;
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal RowSizeCalc WriteTypeDef()
|
|
|
|
{
|
|
|
|
if (mw.bigTypeDef)
|
|
|
|
{
|
|
|
|
this.size += 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.size += 2;
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal RowSizeCalc WriteMethodDefOrRef()
|
|
|
|
{
|
|
|
|
if (mw.bigMethodDefOrRef)
|
|
|
|
{
|
|
|
|
this.size += 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.size += 2;
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal RowSizeCalc WriteEvent()
|
|
|
|
{
|
|
|
|
if (mw.bigEvent)
|
|
|
|
{
|
|
|
|
this.size += 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.size += 2;
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal RowSizeCalc WriteProperty()
|
|
|
|
{
|
|
|
|
if (mw.bigProperty)
|
|
|
|
{
|
|
|
|
this.size += 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.size += 2;
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal RowSizeCalc WriteHasSemantics()
|
|
|
|
{
|
|
|
|
if (mw.bigHasSemantics)
|
|
|
|
{
|
|
|
|
this.size += 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.size += 2;
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal RowSizeCalc WriteImplementation()
|
|
|
|
{
|
|
|
|
if (mw.bigImplementation)
|
|
|
|
{
|
|
|
|
this.size += 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.size += 2;
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal RowSizeCalc WriteTypeOrMethodDef()
|
|
|
|
{
|
|
|
|
if (mw.bigTypeOrMethodDef)
|
|
|
|
{
|
|
|
|
this.size += 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.size += 2;
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal RowSizeCalc WriteGenericParam()
|
|
|
|
{
|
|
|
|
if (mw.bigGenericParam)
|
|
|
|
{
|
|
|
|
this.size += 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.size += 2;
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal RowSizeCalc WriteHasDeclSecurity()
|
|
|
|
{
|
|
|
|
if (mw.bigHasDeclSecurity)
|
|
|
|
{
|
|
|
|
this.size += 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.size += 2;
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal RowSizeCalc WriteMemberForwarded()
|
|
|
|
{
|
|
|
|
if (mw.bigMemberForwarded)
|
|
|
|
{
|
|
|
|
this.size += 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.size += 2;
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal RowSizeCalc WriteModuleRef()
|
|
|
|
{
|
|
|
|
if (mw.bigModuleRef)
|
|
|
|
{
|
|
|
|
this.size += 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.size += 2;
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal RowSizeCalc WriteHasFieldMarshal()
|
|
|
|
{
|
|
|
|
if (mw.bigHasFieldMarshal)
|
|
|
|
{
|
|
|
|
this.size += 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.size += 2;
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal int Value
|
|
|
|
{
|
|
|
|
get { return size; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
abstract class Table<T> : Table
|
|
|
|
{
|
|
|
|
internal T[] records = Empty<T>.Array;
|
|
|
|
protected int rowCount;
|
|
|
|
|
|
|
|
internal sealed override int RowCount
|
|
|
|
{
|
|
|
|
get { return rowCount; }
|
|
|
|
set { rowCount = value; records = new T[value]; }
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
throw new InvalidOperationException();
|
|
|
|
}
|
|
|
|
|
|
|
|
internal int AddRecord(T newRecord)
|
|
|
|
{
|
|
|
|
if (rowCount == records.Length)
|
|
|
|
{
|
|
|
|
Array.Resize(ref records, Math.Max(16, records.Length * 2));
|
|
|
|
}
|
|
|
|
records[rowCount++] = newRecord;
|
|
|
|
return rowCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal int AddVirtualRecord()
|
|
|
|
{
|
|
|
|
return ++rowCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
throw new InvalidOperationException();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
abstract class SortedTable<T> : Table<T>
|
|
|
|
where T : SortedTable<T>.IRecord
|
|
|
|
{
|
|
|
|
internal interface IRecord
|
|
|
|
{
|
|
|
|
int SortKey { get; }
|
|
|
|
int FilterKey { get; }
|
|
|
|
}
|
|
|
|
|
|
|
|
internal struct Enumerable
|
|
|
|
{
|
|
|
|
private readonly SortedTable<T> table;
|
|
|
|
private readonly int token;
|
|
|
|
|
|
|
|
internal Enumerable(SortedTable<T> table, int token)
|
|
|
|
{
|
|
|
|
this.table = table;
|
|
|
|
this.token = token;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Enumerator GetEnumerator()
|
|
|
|
{
|
|
|
|
T[] records = table.records;
|
|
|
|
if (!table.Sorted)
|
|
|
|
{
|
|
|
|
return new Enumerator(records, table.RowCount - 1, -1, token);
|
|
|
|
}
|
|
|
|
int index = BinarySearch(records, table.RowCount, token & 0xFFFFFF);
|
|
|
|
if (index < 0)
|
|
|
|
{
|
|
|
|
return new Enumerator(null, 0, 1, -1);
|
|
|
|
}
|
|
|
|
int start = index;
|
|
|
|
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].FilterKey & 0xFFFFFF) == (token & 0xFFFFFF))
|
|
|
|
{
|
|
|
|
end++;
|
|
|
|
}
|
|
|
|
return new Enumerator(records, end, start - 1, token);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static int BinarySearch(T[] records, int length, int maskedToken)
|
|
|
|
{
|
|
|
|
int min = 0;
|
|
|
|
int max = length - 1;
|
|
|
|
while (min <= max)
|
|
|
|
{
|
|
|
|
int mid = min + ((max - min) / 2);
|
|
|
|
int maskedValue = records[mid].FilterKey & 0xFFFFFF;
|
|
|
|
if (maskedToken == maskedValue)
|
|
|
|
{
|
|
|
|
return mid;
|
|
|
|
}
|
|
|
|
else if (maskedToken < maskedValue)
|
|
|
|
{
|
|
|
|
max = mid - 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
min = mid + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal struct Enumerator
|
|
|
|
{
|
|
|
|
private readonly T[] records;
|
|
|
|
private readonly int token;
|
|
|
|
private readonly int max;
|
|
|
|
private int index;
|
|
|
|
|
|
|
|
internal Enumerator(T[] records, int max, int index, int token)
|
|
|
|
{
|
|
|
|
this.records = records;
|
|
|
|
this.token = token;
|
|
|
|
this.max = max;
|
|
|
|
this.index = index;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int Current
|
|
|
|
{
|
|
|
|
get { return index; }
|
|
|
|
}
|
|
|
|
|
|
|
|
public bool MoveNext()
|
|
|
|
{
|
|
|
|
while (index < max)
|
|
|
|
{
|
|
|
|
index++;
|
|
|
|
if (records[index].FilterKey == token)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal Enumerable Filter(int token)
|
|
|
|
{
|
|
|
|
return new Enumerable(this, token);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void Sort()
|
|
|
|
{
|
|
|
|
ulong[] map = new ulong[rowCount];
|
|
|
|
for (uint i = 0; i < map.Length; i++)
|
|
|
|
{
|
|
|
|
map[i] = ((ulong)records[i].SortKey << 32) | i;
|
|
|
|
}
|
|
|
|
Array.Sort(map);
|
|
|
|
T[] newRecords = new T[rowCount];
|
|
|
|
for (int i = 0; i < map.Length; i++)
|
|
|
|
{
|
|
|
|
newRecords[i] = records[(int)map[i]];
|
|
|
|
}
|
|
|
|
records = newRecords;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class ModuleTable : Table<ModuleTable.Record>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x00;
|
|
|
|
|
|
|
|
internal struct Record
|
|
|
|
{
|
|
|
|
internal short Generation;
|
|
|
|
internal int Name; // -> StringHeap
|
|
|
|
internal int Mvid; // -> GuidHeap
|
|
|
|
internal int EncId; // -> GuidHeap
|
|
|
|
internal int EncBaseId; // -> GuidHeap
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i].Generation = mr.ReadInt16();
|
|
|
|
records[i].Name = mr.ReadStringIndex();
|
|
|
|
records[i].Mvid = mr.ReadGuidIndex();
|
|
|
|
records[i].EncId = mr.ReadGuidIndex();
|
|
|
|
records[i].EncBaseId = mr.ReadGuidIndex();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
mw.Write(records[i].Generation);
|
|
|
|
mw.WriteStringIndex(records[i].Name);
|
|
|
|
mw.WriteGuidIndex(records[i].Mvid);
|
|
|
|
mw.WriteGuidIndex(records[i].EncId);
|
|
|
|
mw.WriteGuidIndex(records[i].EncBaseId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.AddFixed(2)
|
|
|
|
.WriteStringIndex()
|
|
|
|
.WriteGuidIndex()
|
|
|
|
.WriteGuidIndex()
|
|
|
|
.WriteGuidIndex()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void Add(short generation, int name, int mvid, int encid, int encbaseid)
|
|
|
|
{
|
|
|
|
Record record = new Record();
|
|
|
|
record.Generation = generation;
|
|
|
|
record.Name = name;
|
|
|
|
record.Mvid = mvid;
|
|
|
|
record.EncId = encid;
|
|
|
|
record.EncBaseId = encbaseid;
|
|
|
|
AddRecord(record);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class TypeRefTable : Table<TypeRefTable.Record>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x01;
|
|
|
|
|
|
|
|
internal struct Record
|
|
|
|
{
|
|
|
|
internal int ResolutionScope;
|
|
|
|
internal int TypeName;
|
2015-08-26 07:17:56 -04:00
|
|
|
internal int TypeNamespace;
|
2014-08-13 10:39:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i].ResolutionScope = mr.ReadResolutionScope();
|
|
|
|
records[i].TypeName = mr.ReadStringIndex();
|
2015-08-26 07:17:56 -04:00
|
|
|
records[i].TypeNamespace = mr.ReadStringIndex();
|
2014-08-13 10:39:27 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
mw.WriteResolutionScope(records[i].ResolutionScope);
|
|
|
|
mw.WriteStringIndex(records[i].TypeName);
|
2015-08-26 07:17:56 -04:00
|
|
|
mw.WriteStringIndex(records[i].TypeNamespace);
|
2014-08-13 10:39:27 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.WriteResolutionScope()
|
|
|
|
.WriteStringIndex()
|
|
|
|
.WriteStringIndex()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void Fixup(ModuleBuilder moduleBuilder)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
moduleBuilder.FixupPseudoToken(ref records[i].ResolutionScope);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class TypeDefTable : Table<TypeDefTable.Record>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x02;
|
|
|
|
|
|
|
|
internal struct Record
|
|
|
|
{
|
|
|
|
internal int Flags;
|
|
|
|
internal int TypeName;
|
|
|
|
internal int TypeNamespace;
|
|
|
|
internal int Extends;
|
|
|
|
internal int FieldList;
|
|
|
|
internal int MethodList;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i].Flags = mr.ReadInt32();
|
|
|
|
records[i].TypeName = mr.ReadStringIndex();
|
|
|
|
records[i].TypeNamespace = mr.ReadStringIndex();
|
|
|
|
records[i].Extends = mr.ReadTypeDefOrRef();
|
|
|
|
records[i].FieldList = mr.ReadField();
|
|
|
|
records[i].MethodList = mr.ReadMethodDef();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
mw.ModuleBuilder.WriteTypeDefTable(mw);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal int AllocToken()
|
|
|
|
{
|
|
|
|
return 0x02000000 + AddVirtualRecord();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.AddFixed(4)
|
|
|
|
.WriteStringIndex()
|
|
|
|
.WriteStringIndex()
|
|
|
|
.WriteTypeDefOrRef()
|
|
|
|
.WriteField()
|
|
|
|
.WriteMethodDef()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class FieldPtrTable : Table<int>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x03;
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i] = mr.ReadField();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class FieldTable : Table<FieldTable.Record>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x04;
|
|
|
|
|
|
|
|
internal struct Record
|
|
|
|
{
|
|
|
|
internal short Flags;
|
|
|
|
internal int Name;
|
|
|
|
internal int Signature;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i].Flags = mr.ReadInt16();
|
|
|
|
records[i].Name = mr.ReadStringIndex();
|
|
|
|
records[i].Signature = mr.ReadBlobIndex();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
mw.ModuleBuilder.WriteFieldTable(mw);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.AddFixed(2)
|
|
|
|
.WriteStringIndex()
|
|
|
|
.WriteBlobIndex()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class MethodPtrTable : Table<int>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x05;
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i] = mr.ReadMethodDef();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class MethodDefTable : Table<MethodDefTable.Record>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x06;
|
|
|
|
private int baseRVA;
|
|
|
|
|
|
|
|
internal struct Record
|
|
|
|
{
|
|
|
|
internal int RVA;
|
|
|
|
internal short ImplFlags;
|
|
|
|
internal short Flags;
|
|
|
|
internal int Name;
|
|
|
|
internal int Signature;
|
|
|
|
internal int ParamList;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i].RVA = mr.ReadInt32();
|
|
|
|
records[i].ImplFlags = mr.ReadInt16();
|
|
|
|
records[i].Flags = mr.ReadInt16();
|
|
|
|
records[i].Name = mr.ReadStringIndex();
|
|
|
|
records[i].Signature = mr.ReadBlobIndex();
|
|
|
|
records[i].ParamList = mr.ReadParam();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
mw.ModuleBuilder.WriteMethodDefTable(baseRVA, mw);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.AddFixed(8)
|
|
|
|
.WriteStringIndex()
|
|
|
|
.WriteBlobIndex()
|
|
|
|
.WriteParam()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void Fixup(TextSection code)
|
|
|
|
{
|
|
|
|
baseRVA = (int)code.MethodBodiesRVA;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class ParamPtrTable : Table<int>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x07;
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i] = mr.ReadParam();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class ParamTable : Table<ParamTable.Record>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x08;
|
|
|
|
|
|
|
|
internal struct Record
|
|
|
|
{
|
|
|
|
internal short Flags;
|
|
|
|
internal short Sequence;
|
|
|
|
internal int Name;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i].Flags = mr.ReadInt16();
|
|
|
|
records[i].Sequence = mr.ReadInt16();
|
|
|
|
records[i].Name = mr.ReadStringIndex();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
mw.ModuleBuilder.WriteParamTable(mw);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.AddFixed(4)
|
|
|
|
.WriteStringIndex()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class InterfaceImplTable : SortedTable<InterfaceImplTable.Record>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x09;
|
|
|
|
|
|
|
|
internal struct Record : IRecord
|
|
|
|
{
|
|
|
|
internal int Class;
|
|
|
|
internal int Interface;
|
|
|
|
|
|
|
|
int IRecord.SortKey
|
|
|
|
{
|
|
|
|
get { return Class; }
|
|
|
|
}
|
|
|
|
|
|
|
|
int IRecord.FilterKey
|
|
|
|
{
|
|
|
|
get { return Class; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i].Class = mr.ReadTypeDef();
|
|
|
|
records[i].Interface = mr.ReadTypeDefOrRef();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
mw.WriteTypeDef(records[i].Class);
|
|
|
|
mw.WriteEncodedTypeDefOrRef(records[i].Interface);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.WriteTypeDef()
|
|
|
|
.WriteTypeDefOrRef()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void Fixup()
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
int token = records[i].Interface;
|
|
|
|
switch (token >> 24)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
break;
|
|
|
|
case TypeDefTable.Index:
|
|
|
|
token = (token & 0xFFFFFF) << 2 | 0;
|
|
|
|
break;
|
|
|
|
case TypeRefTable.Index:
|
|
|
|
token = (token & 0xFFFFFF) << 2 | 1;
|
|
|
|
break;
|
|
|
|
case TypeSpecTable.Index:
|
|
|
|
token = (token & 0xFFFFFF) << 2 | 2;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
throw new InvalidOperationException();
|
|
|
|
}
|
|
|
|
records[i].Interface = token;
|
|
|
|
}
|
|
|
|
// LAMESPEC the CLI spec says that InterfaceImpl should be sorted by { Class, Interface },
|
|
|
|
// but it appears to only be necessary to sort by Class (and csc emits InterfaceImpl records in
|
|
|
|
// source file order, so to be able to support round tripping, we need to retain ordering as well).
|
|
|
|
Sort();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class MemberRefTable : Table<MemberRefTable.Record>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x0A;
|
|
|
|
|
|
|
|
internal struct Record
|
|
|
|
{
|
|
|
|
internal int Class;
|
|
|
|
internal int Name;
|
|
|
|
internal int Signature;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i].Class = mr.ReadMemberRefParent();
|
|
|
|
records[i].Name = mr.ReadStringIndex();
|
|
|
|
records[i].Signature = mr.ReadBlobIndex();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
mw.WriteMemberRefParent(records[i].Class);
|
|
|
|
mw.WriteStringIndex(records[i].Name);
|
|
|
|
mw.WriteBlobIndex(records[i].Signature);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.WriteMemberRefParent()
|
|
|
|
.WriteStringIndex()
|
|
|
|
.WriteBlobIndex()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal int FindOrAddRecord(Record record)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
if (records[i].Class == record.Class
|
|
|
|
&& records[i].Name == record.Name
|
|
|
|
&& records[i].Signature == record.Signature)
|
|
|
|
{
|
|
|
|
return i + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return AddRecord(record);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void Fixup(ModuleBuilder moduleBuilder)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
moduleBuilder.FixupPseudoToken(ref records[i].Class);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class ConstantTable : SortedTable<ConstantTable.Record>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x0B;
|
|
|
|
|
|
|
|
internal struct Record : IRecord
|
|
|
|
{
|
|
|
|
internal short Type;
|
|
|
|
internal int Parent;
|
|
|
|
internal int Value;
|
|
|
|
|
|
|
|
int IRecord.SortKey
|
|
|
|
{
|
|
|
|
get { return EncodeHasConstant(Parent); }
|
|
|
|
}
|
|
|
|
|
|
|
|
int IRecord.FilterKey
|
|
|
|
{
|
|
|
|
get { return Parent; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i].Type = mr.ReadInt16();
|
|
|
|
records[i].Parent = mr.ReadHasConstant();
|
|
|
|
records[i].Value = mr.ReadBlobIndex();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
mw.Write(records[i].Type);
|
|
|
|
mw.WriteHasConstant(records[i].Parent);
|
|
|
|
mw.WriteBlobIndex(records[i].Value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.AddFixed(2)
|
|
|
|
.WriteHasConstant()
|
|
|
|
.WriteBlobIndex()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void Fixup(ModuleBuilder moduleBuilder)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
moduleBuilder.FixupPseudoToken(ref records[i].Parent);
|
|
|
|
}
|
|
|
|
Sort();
|
|
|
|
}
|
|
|
|
|
|
|
|
internal static int EncodeHasConstant(int token)
|
|
|
|
{
|
|
|
|
switch (token >> 24)
|
|
|
|
{
|
|
|
|
case FieldTable.Index:
|
|
|
|
return (token & 0xFFFFFF) << 2 | 0;
|
|
|
|
case ParamTable.Index:
|
|
|
|
return (token & 0xFFFFFF) << 2 | 1;
|
|
|
|
case PropertyTable.Index:
|
|
|
|
return (token & 0xFFFFFF) << 2 | 2;
|
|
|
|
default:
|
|
|
|
throw new InvalidOperationException();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal object GetRawConstantValue(Module module, int parent)
|
|
|
|
{
|
|
|
|
foreach (int i in Filter(parent))
|
|
|
|
{
|
|
|
|
ByteReader br = module.GetBlob(module.Constant.records[i].Value);
|
|
|
|
switch (module.Constant.records[i].Type)
|
|
|
|
{
|
|
|
|
// see ModuleBuilder.AddConstant for the encodings
|
|
|
|
case Signature.ELEMENT_TYPE_BOOLEAN:
|
|
|
|
return br.ReadByte() != 0;
|
|
|
|
case Signature.ELEMENT_TYPE_I1:
|
|
|
|
return br.ReadSByte();
|
|
|
|
case Signature.ELEMENT_TYPE_I2:
|
|
|
|
return br.ReadInt16();
|
|
|
|
case Signature.ELEMENT_TYPE_I4:
|
|
|
|
return br.ReadInt32();
|
|
|
|
case Signature.ELEMENT_TYPE_I8:
|
|
|
|
return br.ReadInt64();
|
|
|
|
case Signature.ELEMENT_TYPE_U1:
|
|
|
|
return br.ReadByte();
|
|
|
|
case Signature.ELEMENT_TYPE_U2:
|
|
|
|
return br.ReadUInt16();
|
|
|
|
case Signature.ELEMENT_TYPE_U4:
|
|
|
|
return br.ReadUInt32();
|
|
|
|
case Signature.ELEMENT_TYPE_U8:
|
|
|
|
return br.ReadUInt64();
|
|
|
|
case Signature.ELEMENT_TYPE_R4:
|
|
|
|
return br.ReadSingle();
|
|
|
|
case Signature.ELEMENT_TYPE_R8:
|
|
|
|
return br.ReadDouble();
|
|
|
|
case Signature.ELEMENT_TYPE_CHAR:
|
|
|
|
return br.ReadChar();
|
|
|
|
case Signature.ELEMENT_TYPE_STRING:
|
|
|
|
{
|
|
|
|
char[] chars = new char[br.Length / 2];
|
|
|
|
for (int j = 0; j < chars.Length; j++)
|
|
|
|
{
|
|
|
|
chars[j] = br.ReadChar();
|
|
|
|
}
|
|
|
|
return new String(chars);
|
|
|
|
}
|
|
|
|
case Signature.ELEMENT_TYPE_CLASS:
|
|
|
|
if (br.ReadInt32() != 0)
|
|
|
|
{
|
|
|
|
throw new BadImageFormatException();
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
default:
|
|
|
|
throw new BadImageFormatException();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
throw new InvalidOperationException();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class CustomAttributeTable : SortedTable<CustomAttributeTable.Record>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x0C;
|
|
|
|
|
|
|
|
internal struct Record : IRecord
|
|
|
|
{
|
|
|
|
internal int Parent;
|
|
|
|
internal int Type;
|
|
|
|
internal int Value;
|
|
|
|
|
|
|
|
int IRecord.SortKey
|
|
|
|
{
|
|
|
|
get { return EncodeHasCustomAttribute(Parent); }
|
|
|
|
}
|
|
|
|
|
|
|
|
int IRecord.FilterKey
|
|
|
|
{
|
|
|
|
get { return Parent; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i].Parent = mr.ReadHasCustomAttribute();
|
|
|
|
records[i].Type = mr.ReadCustomAttributeType();
|
|
|
|
records[i].Value = mr.ReadBlobIndex();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
mw.WriteHasCustomAttribute(records[i].Parent);
|
|
|
|
mw.WriteCustomAttributeType(records[i].Type);
|
|
|
|
mw.WriteBlobIndex(records[i].Value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.WriteHasCustomAttribute()
|
|
|
|
.WriteCustomAttributeType()
|
|
|
|
.WriteBlobIndex()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void Fixup(ModuleBuilder moduleBuilder)
|
|
|
|
{
|
|
|
|
int[] genericParamFixup = moduleBuilder.GenericParam.GetIndexFixup();
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
moduleBuilder.FixupPseudoToken(ref records[i].Type);
|
|
|
|
moduleBuilder.FixupPseudoToken(ref records[i].Parent);
|
|
|
|
if (records[i].Parent >> 24 == GenericParamTable.Index)
|
|
|
|
{
|
|
|
|
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<FieldMarshalTable.Record>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x0D;
|
|
|
|
|
|
|
|
internal struct Record : IRecord
|
|
|
|
{
|
|
|
|
internal int Parent;
|
|
|
|
internal int NativeType;
|
|
|
|
|
|
|
|
int IRecord.SortKey
|
|
|
|
{
|
|
|
|
get { return EncodeHasFieldMarshal(Parent); }
|
|
|
|
}
|
|
|
|
|
|
|
|
int IRecord.FilterKey
|
|
|
|
{
|
|
|
|
get { return Parent; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i].Parent = mr.ReadHasFieldMarshal();
|
|
|
|
records[i].NativeType = mr.ReadBlobIndex();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
mw.WriteHasFieldMarshal(records[i].Parent);
|
|
|
|
mw.WriteBlobIndex(records[i].NativeType);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.WriteHasFieldMarshal()
|
|
|
|
.WriteBlobIndex()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void Fixup(ModuleBuilder moduleBuilder)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
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<DeclSecurityTable.Record>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x0E;
|
|
|
|
|
|
|
|
internal struct Record : IRecord
|
|
|
|
{
|
|
|
|
internal short Action;
|
|
|
|
internal int Parent;
|
|
|
|
internal int PermissionSet;
|
|
|
|
|
|
|
|
int IRecord.SortKey
|
|
|
|
{
|
|
|
|
get { return Parent; }
|
|
|
|
}
|
|
|
|
|
|
|
|
int IRecord.FilterKey
|
|
|
|
{
|
|
|
|
get { return Parent; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i].Action = mr.ReadInt16();
|
|
|
|
records[i].Parent = mr.ReadHasDeclSecurity();
|
|
|
|
records[i].PermissionSet = mr.ReadBlobIndex();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
mw.Write(records[i].Action);
|
|
|
|
mw.WriteHasDeclSecurity(records[i].Parent);
|
|
|
|
mw.WriteBlobIndex(records[i].PermissionSet);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.AddFixed(2)
|
|
|
|
.WriteHasDeclSecurity()
|
|
|
|
.WriteBlobIndex()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void Fixup(ModuleBuilder moduleBuilder)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
int token = records[i].Parent;
|
|
|
|
moduleBuilder.FixupPseudoToken(ref token);
|
|
|
|
// do the HasDeclSecurity encoding, so that we can sort the table
|
|
|
|
switch (token >> 24)
|
|
|
|
{
|
|
|
|
case TypeDefTable.Index:
|
|
|
|
token = (token & 0xFFFFFF) << 2 | 0;
|
|
|
|
break;
|
|
|
|
case MethodDefTable.Index:
|
|
|
|
token = (token & 0xFFFFFF) << 2 | 1;
|
|
|
|
break;
|
|
|
|
case AssemblyTable.Index:
|
|
|
|
token = (token & 0xFFFFFF) << 2 | 2;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
throw new InvalidOperationException();
|
|
|
|
}
|
|
|
|
records[i].Parent = token;
|
|
|
|
}
|
|
|
|
Sort();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class ClassLayoutTable : SortedTable<ClassLayoutTable.Record>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x0f;
|
|
|
|
|
|
|
|
internal struct Record : IRecord
|
|
|
|
{
|
|
|
|
internal short PackingSize;
|
|
|
|
internal int ClassSize;
|
|
|
|
internal int Parent;
|
|
|
|
|
|
|
|
int IRecord.SortKey
|
|
|
|
{
|
|
|
|
get { return Parent; }
|
|
|
|
}
|
|
|
|
|
|
|
|
int IRecord.FilterKey
|
|
|
|
{
|
|
|
|
get { return Parent; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i].PackingSize = mr.ReadInt16();
|
|
|
|
records[i].ClassSize = mr.ReadInt32();
|
|
|
|
records[i].Parent = mr.ReadTypeDef();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
Sort();
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
mw.Write(records[i].PackingSize);
|
|
|
|
mw.Write(records[i].ClassSize);
|
|
|
|
mw.WriteTypeDef(records[i].Parent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.AddFixed(6)
|
|
|
|
.WriteTypeDef()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class FieldLayoutTable : SortedTable<FieldLayoutTable.Record>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x10;
|
|
|
|
|
|
|
|
internal struct Record : IRecord
|
|
|
|
{
|
|
|
|
internal int Offset;
|
|
|
|
internal int Field;
|
|
|
|
|
|
|
|
int IRecord.SortKey
|
|
|
|
{
|
|
|
|
get { return Field; }
|
|
|
|
}
|
|
|
|
|
|
|
|
int IRecord.FilterKey
|
|
|
|
{
|
|
|
|
get { return Field; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i].Offset = mr.ReadInt32();
|
|
|
|
records[i].Field = mr.ReadField();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
mw.Write(records[i].Offset);
|
|
|
|
mw.WriteField(records[i].Field);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.AddFixed(4)
|
|
|
|
.WriteField()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void Fixup(ModuleBuilder moduleBuilder)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
records[i].Field = moduleBuilder.ResolvePseudoToken(records[i].Field) & 0xFFFFFF;
|
|
|
|
}
|
|
|
|
Sort();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class StandAloneSigTable : Table<int>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x11;
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i] = mr.ReadBlobIndex();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
mw.WriteBlobIndex(records[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(Table.RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc.WriteBlobIndex().Value;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal int FindOrAddRecord(int blob)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
if (records[i] == blob)
|
|
|
|
{
|
|
|
|
return i + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return AddRecord(blob);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class EventMapTable : SortedTable<EventMapTable.Record>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x12;
|
|
|
|
|
|
|
|
internal struct Record : IRecord
|
|
|
|
{
|
|
|
|
internal int Parent;
|
|
|
|
internal int EventList;
|
|
|
|
|
|
|
|
int IRecord.SortKey
|
|
|
|
{
|
|
|
|
get { return Parent; }
|
|
|
|
}
|
|
|
|
|
|
|
|
int IRecord.FilterKey
|
|
|
|
{
|
|
|
|
get { return Parent; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i].Parent = mr.ReadTypeDef();
|
|
|
|
records[i].EventList = mr.ReadEvent();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
mw.WriteTypeDef(records[i].Parent);
|
|
|
|
mw.WriteEvent(records[i].EventList);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.WriteTypeDef()
|
|
|
|
.WriteEvent()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class EventPtrTable : Table<int>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x13;
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i] = mr.ReadEvent();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class EventTable : Table<EventTable.Record>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x14;
|
|
|
|
|
|
|
|
internal struct Record
|
|
|
|
{
|
|
|
|
internal short EventFlags;
|
|
|
|
internal int Name;
|
|
|
|
internal int EventType;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i].EventFlags = mr.ReadInt16();
|
|
|
|
records[i].Name = mr.ReadStringIndex();
|
|
|
|
records[i].EventType = mr.ReadTypeDefOrRef();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
mw.Write(records[i].EventFlags);
|
|
|
|
mw.WriteStringIndex(records[i].Name);
|
|
|
|
mw.WriteTypeDefOrRef(records[i].EventType);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.AddFixed(2)
|
|
|
|
.WriteStringIndex()
|
|
|
|
.WriteTypeDefOrRef()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class PropertyMapTable : SortedTable<PropertyMapTable.Record>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x15;
|
|
|
|
|
|
|
|
internal struct Record : IRecord
|
|
|
|
{
|
|
|
|
internal int Parent;
|
|
|
|
internal int PropertyList;
|
|
|
|
|
|
|
|
int IRecord.SortKey
|
|
|
|
{
|
|
|
|
get { return Parent; }
|
|
|
|
}
|
|
|
|
|
|
|
|
int IRecord.FilterKey
|
|
|
|
{
|
|
|
|
get { return Parent; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i].Parent = mr.ReadTypeDef();
|
|
|
|
records[i].PropertyList = mr.ReadProperty();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
mw.WriteTypeDef(records[i].Parent);
|
|
|
|
mw.WriteProperty(records[i].PropertyList);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.WriteTypeDef()
|
|
|
|
.WriteProperty()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class PropertyPtrTable : Table<int>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x16;
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i] = mr.ReadProperty();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class PropertyTable : Table<PropertyTable.Record>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x17;
|
|
|
|
|
|
|
|
internal struct Record
|
|
|
|
{
|
|
|
|
internal short Flags;
|
|
|
|
internal int Name;
|
|
|
|
internal int Type;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i].Flags = mr.ReadInt16();
|
|
|
|
records[i].Name = mr.ReadStringIndex();
|
|
|
|
records[i].Type = mr.ReadBlobIndex();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
mw.Write(records[i].Flags);
|
|
|
|
mw.WriteStringIndex(records[i].Name);
|
|
|
|
mw.WriteBlobIndex(records[i].Type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.AddFixed(2)
|
|
|
|
.WriteStringIndex()
|
|
|
|
.WriteBlobIndex()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class MethodSemanticsTable : SortedTable<MethodSemanticsTable.Record>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x18;
|
|
|
|
|
|
|
|
// semantics
|
|
|
|
internal const short Setter = 0x0001;
|
|
|
|
internal const short Getter = 0x0002;
|
|
|
|
internal const short Other = 0x0004;
|
|
|
|
internal const short AddOn = 0x0008;
|
|
|
|
internal const short RemoveOn = 0x0010;
|
|
|
|
internal const short Fire = 0x0020;
|
|
|
|
|
|
|
|
internal struct Record : IRecord
|
|
|
|
{
|
|
|
|
internal short Semantics;
|
|
|
|
internal int Method;
|
|
|
|
internal int Association;
|
|
|
|
|
|
|
|
int IRecord.SortKey
|
|
|
|
{
|
|
|
|
get { return Association; }
|
|
|
|
}
|
|
|
|
|
|
|
|
int IRecord.FilterKey
|
|
|
|
{
|
|
|
|
get { return Association; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i].Semantics = mr.ReadInt16();
|
|
|
|
records[i].Method = mr.ReadMethodDef();
|
|
|
|
records[i].Association = mr.ReadHasSemantics();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
mw.Write(records[i].Semantics);
|
|
|
|
mw.WriteMethodDef(records[i].Method);
|
|
|
|
mw.WriteHasSemantics(records[i].Association);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.AddFixed(2)
|
|
|
|
.WriteMethodDef()
|
|
|
|
.WriteHasSemantics()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void Fixup(ModuleBuilder moduleBuilder)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
moduleBuilder.FixupPseudoToken(ref records[i].Method);
|
|
|
|
int token = records[i].Association;
|
|
|
|
// do the HasSemantics encoding, so that we can sort the table
|
|
|
|
switch (token >> 24)
|
|
|
|
{
|
|
|
|
case EventTable.Index:
|
|
|
|
token = (token & 0xFFFFFF) << 1 | 0;
|
|
|
|
break;
|
|
|
|
case PropertyTable.Index:
|
|
|
|
token = (token & 0xFFFFFF) << 1 | 1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
throw new InvalidOperationException();
|
|
|
|
}
|
|
|
|
records[i].Association = token;
|
|
|
|
}
|
|
|
|
Sort();
|
|
|
|
}
|
|
|
|
|
|
|
|
internal MethodInfo GetMethod(Module module, int token, bool nonPublic, short semantics)
|
|
|
|
{
|
|
|
|
foreach (int i in Filter(token))
|
|
|
|
{
|
|
|
|
if ((records[i].Semantics & semantics) != 0)
|
|
|
|
{
|
|
|
|
MethodBase method = module.ResolveMethod((MethodDefTable.Index << 24) + records[i].Method);
|
|
|
|
if (nonPublic || method.IsPublic)
|
|
|
|
{
|
|
|
|
return (MethodInfo)method;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal MethodInfo[] GetMethods(Module module, int token, bool nonPublic, short semantics)
|
|
|
|
{
|
|
|
|
List<MethodInfo> methods = new List<MethodInfo>();
|
|
|
|
foreach (int i in Filter(token))
|
|
|
|
{
|
|
|
|
if ((records[i].Semantics & semantics) != 0)
|
|
|
|
{
|
|
|
|
MethodInfo method = (MethodInfo)module.ResolveMethod((MethodDefTable.Index << 24) + records[i].Method);
|
|
|
|
if (nonPublic || method.IsPublic)
|
|
|
|
{
|
|
|
|
methods.Add(method);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return methods.ToArray();
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void ComputeFlags(Module module, int token, out bool isPublic, out bool isNonPrivate, out bool isStatic)
|
|
|
|
{
|
|
|
|
isPublic = false;
|
|
|
|
isNonPrivate = false;
|
|
|
|
isStatic = false;
|
|
|
|
foreach (int i in Filter(token))
|
|
|
|
{
|
|
|
|
MethodBase method = module.ResolveMethod((MethodDefTable.Index << 24) + records[i].Method);
|
|
|
|
isPublic |= method.IsPublic;
|
|
|
|
isNonPrivate |= (method.Attributes & MethodAttributes.MemberAccessMask) > MethodAttributes.Private;
|
|
|
|
isStatic |= method.IsStatic;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class MethodImplTable : SortedTable<MethodImplTable.Record>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x19;
|
|
|
|
|
|
|
|
internal struct Record : IRecord
|
|
|
|
{
|
|
|
|
internal int Class;
|
|
|
|
internal int MethodBody;
|
|
|
|
internal int MethodDeclaration;
|
|
|
|
|
|
|
|
int IRecord.SortKey
|
|
|
|
{
|
|
|
|
get { return Class; }
|
|
|
|
}
|
|
|
|
|
|
|
|
int IRecord.FilterKey
|
|
|
|
{
|
|
|
|
get { return Class; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i].Class = mr.ReadTypeDef();
|
|
|
|
records[i].MethodBody = mr.ReadMethodDefOrRef();
|
|
|
|
records[i].MethodDeclaration = mr.ReadMethodDefOrRef();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
mw.WriteTypeDef(records[i].Class);
|
|
|
|
mw.WriteMethodDefOrRef(records[i].MethodBody);
|
|
|
|
mw.WriteMethodDefOrRef(records[i].MethodDeclaration);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.WriteTypeDef()
|
|
|
|
.WriteMethodDefOrRef()
|
|
|
|
.WriteMethodDefOrRef()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void Fixup(ModuleBuilder moduleBuilder)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
moduleBuilder.FixupPseudoToken(ref records[i].MethodBody);
|
|
|
|
moduleBuilder.FixupPseudoToken(ref records[i].MethodDeclaration);
|
|
|
|
}
|
|
|
|
Sort();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class ModuleRefTable : Table<int>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x1A;
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i] = mr.ReadStringIndex();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
mw.WriteStringIndex(records[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.WriteStringIndex()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal int FindOrAddRecord(int str)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
if (records[i] == str)
|
|
|
|
{
|
|
|
|
return i + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return AddRecord(str);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class TypeSpecTable : Table<int>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x1B;
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i] = mr.ReadBlobIndex();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
mw.WriteBlobIndex(records[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(Table.RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc.WriteBlobIndex().Value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class ImplMapTable : SortedTable<ImplMapTable.Record>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x1C;
|
|
|
|
|
|
|
|
internal struct Record : IRecord
|
|
|
|
{
|
|
|
|
internal short MappingFlags;
|
|
|
|
internal int MemberForwarded;
|
|
|
|
internal int ImportName;
|
|
|
|
internal int ImportScope;
|
|
|
|
|
|
|
|
int IRecord.SortKey
|
|
|
|
{
|
|
|
|
get { return MemberForwarded; }
|
|
|
|
}
|
|
|
|
|
|
|
|
int IRecord.FilterKey
|
|
|
|
{
|
|
|
|
get { return MemberForwarded; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i].MappingFlags = mr.ReadInt16();
|
|
|
|
records[i].MemberForwarded = mr.ReadMemberForwarded();
|
|
|
|
records[i].ImportName = mr.ReadStringIndex();
|
|
|
|
records[i].ImportScope = mr.ReadModuleRef();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
mw.Write(records[i].MappingFlags);
|
|
|
|
mw.WriteMemberForwarded(records[i].MemberForwarded);
|
|
|
|
mw.WriteStringIndex(records[i].ImportName);
|
|
|
|
mw.WriteModuleRef(records[i].ImportScope);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.AddFixed(2)
|
|
|
|
.WriteMemberForwarded()
|
|
|
|
.WriteStringIndex()
|
|
|
|
.WriteModuleRef()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void Fixup(ModuleBuilder moduleBuilder)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
moduleBuilder.FixupPseudoToken(ref records[i].MemberForwarded);
|
|
|
|
}
|
|
|
|
Sort();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class FieldRVATable : SortedTable<FieldRVATable.Record>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x1D;
|
|
|
|
|
|
|
|
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 IRecord.SortKey
|
|
|
|
{
|
|
|
|
get { return Field; }
|
|
|
|
}
|
|
|
|
|
|
|
|
int IRecord.FilterKey
|
|
|
|
{
|
|
|
|
get { return Field; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i].RVA = mr.ReadInt32();
|
|
|
|
records[i].Field = mr.ReadField();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
mw.Write(records[i].RVA);
|
|
|
|
mw.WriteField(records[i].Field);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.AddFixed(4)
|
|
|
|
.WriteField()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void Fixup(ModuleBuilder moduleBuilder, int sdataRVA, int cilRVA)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
if (records[i].RVA < 0)
|
|
|
|
{
|
|
|
|
records[i].RVA = (records[i].RVA & 0x7fffffff) + cilRVA;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
records[i].RVA += sdataRVA;
|
|
|
|
}
|
|
|
|
moduleBuilder.FixupPseudoToken(ref records[i].Field);
|
|
|
|
}
|
|
|
|
Sort();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class AssemblyTable : Table<AssemblyTable.Record>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x20;
|
|
|
|
|
|
|
|
internal struct Record
|
|
|
|
{
|
|
|
|
internal int HashAlgId;
|
|
|
|
internal ushort MajorVersion;
|
|
|
|
internal ushort MinorVersion;
|
|
|
|
internal ushort BuildNumber;
|
|
|
|
internal ushort RevisionNumber;
|
|
|
|
internal int Flags;
|
|
|
|
internal int PublicKey;
|
|
|
|
internal int Name;
|
|
|
|
internal int Culture;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i].HashAlgId = mr.ReadInt32();
|
|
|
|
records[i].MajorVersion = mr.ReadUInt16();
|
|
|
|
records[i].MinorVersion = mr.ReadUInt16();
|
|
|
|
records[i].BuildNumber = mr.ReadUInt16();
|
|
|
|
records[i].RevisionNumber = mr.ReadUInt16();
|
|
|
|
records[i].Flags = mr.ReadInt32();
|
|
|
|
records[i].PublicKey = mr.ReadBlobIndex();
|
|
|
|
records[i].Name = mr.ReadStringIndex();
|
|
|
|
records[i].Culture = mr.ReadStringIndex();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
mw.Write(records[i].HashAlgId);
|
|
|
|
mw.Write(records[i].MajorVersion);
|
|
|
|
mw.Write(records[i].MinorVersion);
|
|
|
|
mw.Write(records[i].BuildNumber);
|
|
|
|
mw.Write(records[i].RevisionNumber);
|
|
|
|
mw.Write(records[i].Flags);
|
|
|
|
mw.WriteBlobIndex(records[i].PublicKey);
|
|
|
|
mw.WriteStringIndex(records[i].Name);
|
|
|
|
mw.WriteStringIndex(records[i].Culture);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.AddFixed(16)
|
|
|
|
.WriteBlobIndex()
|
|
|
|
.WriteStringIndex()
|
|
|
|
.WriteStringIndex()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class AssemblyRefTable : Table<AssemblyRefTable.Record>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x23;
|
|
|
|
|
|
|
|
internal struct Record
|
|
|
|
{
|
|
|
|
internal ushort MajorVersion;
|
|
|
|
internal ushort MinorVersion;
|
|
|
|
internal ushort BuildNumber;
|
|
|
|
internal ushort RevisionNumber;
|
|
|
|
internal int Flags;
|
|
|
|
internal int PublicKeyOrToken;
|
|
|
|
internal int Name;
|
|
|
|
internal int Culture;
|
|
|
|
internal int HashValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal int FindOrAddRecord(Record rec)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
// note that we ignore HashValue here!
|
|
|
|
if (records[i].Name == rec.Name
|
|
|
|
&& records[i].MajorVersion == rec.MajorVersion
|
|
|
|
&& records[i].MinorVersion == rec.MinorVersion
|
|
|
|
&& records[i].BuildNumber == rec.BuildNumber
|
|
|
|
&& records[i].RevisionNumber == rec.RevisionNumber
|
|
|
|
&& records[i].Flags == rec.Flags
|
|
|
|
&& records[i].PublicKeyOrToken == rec.PublicKeyOrToken
|
|
|
|
&& records[i].Culture == rec.Culture
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return i + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return AddRecord(rec);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i].MajorVersion = mr.ReadUInt16();
|
|
|
|
records[i].MinorVersion = mr.ReadUInt16();
|
|
|
|
records[i].BuildNumber = mr.ReadUInt16();
|
|
|
|
records[i].RevisionNumber = mr.ReadUInt16();
|
|
|
|
records[i].Flags = mr.ReadInt32();
|
|
|
|
records[i].PublicKeyOrToken = mr.ReadBlobIndex();
|
|
|
|
records[i].Name = mr.ReadStringIndex();
|
|
|
|
records[i].Culture = mr.ReadStringIndex();
|
|
|
|
records[i].HashValue = mr.ReadBlobIndex();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
mw.Write(records[i].MajorVersion);
|
|
|
|
mw.Write(records[i].MinorVersion);
|
|
|
|
mw.Write(records[i].BuildNumber);
|
|
|
|
mw.Write(records[i].RevisionNumber);
|
|
|
|
mw.Write(records[i].Flags);
|
|
|
|
mw.WriteBlobIndex(records[i].PublicKeyOrToken);
|
|
|
|
mw.WriteStringIndex(records[i].Name);
|
|
|
|
mw.WriteStringIndex(records[i].Culture);
|
|
|
|
mw.WriteBlobIndex(records[i].HashValue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.AddFixed(12)
|
|
|
|
.WriteBlobIndex()
|
|
|
|
.WriteStringIndex()
|
|
|
|
.WriteStringIndex()
|
|
|
|
.WriteBlobIndex()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class FileTable : Table<FileTable.Record>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x26;
|
|
|
|
|
|
|
|
internal struct Record
|
|
|
|
{
|
|
|
|
internal int Flags;
|
|
|
|
internal int Name;
|
|
|
|
internal int HashValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i].Flags = mr.ReadInt32();
|
|
|
|
records[i].Name = mr.ReadStringIndex();
|
|
|
|
records[i].HashValue = mr.ReadBlobIndex();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
mw.Write(records[i].Flags);
|
|
|
|
mw.WriteStringIndex(records[i].Name);
|
|
|
|
mw.WriteBlobIndex(records[i].HashValue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.AddFixed(4)
|
|
|
|
.WriteStringIndex()
|
|
|
|
.WriteBlobIndex()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class ExportedTypeTable : Table<ExportedTypeTable.Record>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x27;
|
|
|
|
|
|
|
|
internal struct Record
|
|
|
|
{
|
|
|
|
internal int Flags;
|
|
|
|
internal int TypeDefId;
|
|
|
|
internal int TypeName;
|
|
|
|
internal int TypeNamespace;
|
|
|
|
internal int Implementation;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i].Flags = mr.ReadInt32();
|
|
|
|
records[i].TypeDefId = mr.ReadInt32();
|
|
|
|
records[i].TypeName = mr.ReadStringIndex();
|
|
|
|
records[i].TypeNamespace = mr.ReadStringIndex();
|
|
|
|
records[i].Implementation = mr.ReadImplementation();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
mw.Write(records[i].Flags);
|
|
|
|
mw.Write(records[i].TypeDefId);
|
|
|
|
mw.WriteStringIndex(records[i].TypeName);
|
|
|
|
mw.WriteStringIndex(records[i].TypeNamespace);
|
|
|
|
mw.WriteImplementation(records[i].Implementation);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.AddFixed(8)
|
|
|
|
.WriteStringIndex()
|
|
|
|
.WriteStringIndex()
|
|
|
|
.WriteImplementation()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal int FindOrAddRecord(Record rec)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
if (records[i].Implementation == rec.Implementation
|
|
|
|
&& records[i].TypeName == rec.TypeName
|
|
|
|
&& records[i].TypeNamespace == rec.TypeNamespace)
|
|
|
|
{
|
|
|
|
return i + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return AddRecord(rec);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void Fixup(ModuleBuilder moduleBuilder)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
moduleBuilder.FixupPseudoToken(ref records[i].Implementation);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class ManifestResourceTable : Table<ManifestResourceTable.Record>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x28;
|
|
|
|
|
|
|
|
internal struct Record
|
|
|
|
{
|
|
|
|
internal int Offset;
|
|
|
|
internal int Flags;
|
|
|
|
internal int Name;
|
|
|
|
internal int Implementation;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i].Offset = mr.ReadInt32();
|
|
|
|
records[i].Flags = mr.ReadInt32();
|
|
|
|
records[i].Name = mr.ReadStringIndex();
|
|
|
|
records[i].Implementation = mr.ReadImplementation();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
mw.Write(records[i].Offset);
|
|
|
|
mw.Write(records[i].Flags);
|
|
|
|
mw.WriteStringIndex(records[i].Name);
|
|
|
|
mw.WriteImplementation(records[i].Implementation);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.AddFixed(8)
|
|
|
|
.WriteStringIndex()
|
|
|
|
.WriteImplementation()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void Fixup(ModuleBuilder moduleBuilder)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
moduleBuilder.FixupPseudoToken(ref records[i].Implementation);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class NestedClassTable : SortedTable<NestedClassTable.Record>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x29;
|
|
|
|
|
|
|
|
internal struct Record : IRecord
|
|
|
|
{
|
|
|
|
internal int NestedClass;
|
|
|
|
internal int EnclosingClass;
|
|
|
|
|
|
|
|
int IRecord.SortKey
|
|
|
|
{
|
|
|
|
get { return NestedClass; }
|
|
|
|
}
|
|
|
|
|
|
|
|
int IRecord.FilterKey
|
|
|
|
{
|
|
|
|
get { return NestedClass; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i].NestedClass = mr.ReadTypeDef();
|
|
|
|
records[i].EnclosingClass = mr.ReadTypeDef();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
mw.WriteTypeDef(records[i].NestedClass);
|
|
|
|
mw.WriteTypeDef(records[i].EnclosingClass);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.WriteTypeDef()
|
|
|
|
.WriteTypeDef()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal List<int> GetNestedClasses(int enclosingClass)
|
|
|
|
{
|
|
|
|
List<int> nestedClasses = new List<int>();
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
if (records[i].EnclosingClass == enclosingClass)
|
|
|
|
{
|
|
|
|
nestedClasses.Add(records[i].NestedClass);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nestedClasses;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class GenericParamTable : SortedTable<GenericParamTable.Record>, IComparer<GenericParamTable.Record>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x2A;
|
|
|
|
|
|
|
|
internal struct Record : IRecord
|
|
|
|
{
|
|
|
|
internal short Number;
|
|
|
|
internal short Flags;
|
|
|
|
internal int Owner;
|
|
|
|
internal int Name;
|
|
|
|
// not part of the table, we use it to be able to fixup the GenericParamConstraint table
|
|
|
|
internal int unsortedIndex;
|
|
|
|
|
|
|
|
int IRecord.SortKey
|
|
|
|
{
|
|
|
|
get { return Owner; }
|
|
|
|
}
|
|
|
|
|
|
|
|
int IRecord.FilterKey
|
|
|
|
{
|
|
|
|
get { return Owner; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i].Number = mr.ReadInt16();
|
|
|
|
records[i].Flags = mr.ReadInt16();
|
|
|
|
records[i].Owner = mr.ReadTypeOrMethodDef();
|
|
|
|
records[i].Name = mr.ReadStringIndex();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
mw.Write(records[i].Number);
|
|
|
|
mw.Write(records[i].Flags);
|
|
|
|
mw.WriteTypeOrMethodDef(records[i].Owner);
|
|
|
|
mw.WriteStringIndex(records[i].Name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.AddFixed(4)
|
|
|
|
.WriteTypeOrMethodDef()
|
|
|
|
.WriteStringIndex()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void Fixup(ModuleBuilder moduleBuilder)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
int token = records[i].Owner;
|
|
|
|
moduleBuilder.FixupPseudoToken(ref token);
|
|
|
|
// do the TypeOrMethodDef encoding, so that we can sort the table
|
|
|
|
switch (token >> 24)
|
|
|
|
{
|
|
|
|
case TypeDefTable.Index:
|
|
|
|
records[i].Owner = (token & 0xFFFFFF) << 1 | 0;
|
|
|
|
break;
|
|
|
|
case MethodDefTable.Index:
|
|
|
|
records[i].Owner = (token & 0xFFFFFF) << 1 | 1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
throw new InvalidOperationException();
|
|
|
|
}
|
|
|
|
records[i].unsortedIndex = i;
|
|
|
|
}
|
|
|
|
// FXBUG the unnecessary (IComparer<Record>) cast is a workaround for a .NET 2.0 C# compiler bug
|
|
|
|
Array.Sort(records, 0, rowCount, (IComparer<Record>)this);
|
|
|
|
}
|
|
|
|
|
|
|
|
int IComparer<Record>.Compare(Record x, Record y)
|
|
|
|
{
|
|
|
|
if (x.Owner == y.Owner)
|
|
|
|
{
|
|
|
|
return x.Number == y.Number ? 0 : (x.Number > y.Number ? 1 : -1);
|
|
|
|
}
|
|
|
|
return x.Owner > y.Owner ? 1 : -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void PatchAttribute(int token, GenericParameterAttributes genericParameterAttributes)
|
|
|
|
{
|
|
|
|
records[(token & 0xFFFFFF) - 1].Flags = (short)genericParameterAttributes;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal int[] GetIndexFixup()
|
|
|
|
{
|
|
|
|
int[] array = new int[rowCount];
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
array[records[i].unsortedIndex] = i;
|
|
|
|
}
|
|
|
|
return array;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal int FindFirstByOwner(int token)
|
|
|
|
{
|
|
|
|
foreach (int i in Filter(token))
|
|
|
|
{
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class MethodSpecTable : Table<MethodSpecTable.Record>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x2B;
|
|
|
|
|
|
|
|
internal struct Record
|
|
|
|
{
|
|
|
|
internal int Method;
|
|
|
|
internal int Instantiation;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i].Method = mr.ReadMethodDefOrRef();
|
|
|
|
records[i].Instantiation = mr.ReadBlobIndex();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
mw.WriteMethodDefOrRef(records[i].Method);
|
|
|
|
mw.WriteBlobIndex(records[i].Instantiation);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.WriteMethodDefOrRef()
|
|
|
|
.WriteBlobIndex()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal int FindOrAddRecord(Record record)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
if (records[i].Method == record.Method
|
|
|
|
&& records[i].Instantiation == record.Instantiation)
|
|
|
|
{
|
|
|
|
return i + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return AddRecord(record);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void Fixup(ModuleBuilder moduleBuilder)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
moduleBuilder.FixupPseudoToken(ref records[i].Method);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sealed class GenericParamConstraintTable : SortedTable<GenericParamConstraintTable.Record>
|
|
|
|
{
|
|
|
|
internal const int Index = 0x2C;
|
|
|
|
|
|
|
|
internal struct Record : IRecord
|
|
|
|
{
|
|
|
|
internal int Owner;
|
|
|
|
internal int Constraint;
|
|
|
|
|
|
|
|
int IRecord.SortKey
|
|
|
|
{
|
|
|
|
get { return Owner; }
|
|
|
|
}
|
|
|
|
|
|
|
|
int IRecord.FilterKey
|
|
|
|
{
|
|
|
|
get { return Owner; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Read(MetadataReader mr)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < records.Length; i++)
|
|
|
|
{
|
|
|
|
records[i].Owner = mr.ReadGenericParam();
|
|
|
|
records[i].Constraint = mr.ReadTypeDefOrRef();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override void Write(MetadataWriter mw)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
mw.WriteGenericParam(records[i].Owner);
|
|
|
|
mw.WriteTypeDefOrRef(records[i].Constraint);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override int GetRowSize(RowSizeCalc rsc)
|
|
|
|
{
|
|
|
|
return rsc
|
|
|
|
.WriteGenericParam()
|
|
|
|
.WriteTypeDefOrRef()
|
|
|
|
.Value;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void Fixup(ModuleBuilder moduleBuilder)
|
|
|
|
{
|
|
|
|
int[] fixups = moduleBuilder.GenericParam.GetIndexFixup();
|
|
|
|
for (int i = 0; i < rowCount; i++)
|
|
|
|
{
|
|
|
|
records[i].Owner = fixups[records[i].Owner - 1] + 1;
|
|
|
|
}
|
|
|
|
Sort();
|
|
|
|
}
|
|
|
|
}
|
2016-08-03 10:59:49 +00:00
|
|
|
|
|
|
|
// 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();
|
|
|
|
}
|
|
|
|
}
|
2014-08-13 10:39:27 +01:00
|
|
|
}
|