public MetadataTable Load(TablesHeap h, MetadataReader rdr, uint[] lens, TableType type) { MetadataTable ret = new MetadataTable(h, type); Reader[] read = new Reader[ret.Columns.Length]; for (int i = 0; i < ret.Columns.Length; i++) { int k = i; var retColTypeObj = ret.Columns[i].Type; if (retColTypeObj is Type) { var retColType = retColTypeObj as Type; //if (retColType.IsSubclassOf(typeof(Enum))) if (retColType.IsEnum) { var underEnumType = Enum.GetUnderlyingType(retColType); //read[i] = DicEnumReader[underEnumType]; if (underEnumType == typeof(byte)) { read[i] = new Reader(ReadByteFlag); } else if (underEnumType == typeof(System.UInt16)) { read[i] = new Reader(ReadUInt16Flag); } else if (underEnumType == typeof(System.UInt32)) { read[i] = new Reader(ReadUInt32Flag); } //switch (Enum.GetUnderlyingType(retColType).FullName) //{ // case "System.Byte": // read[i] = new Reader(ReadByteFlag); // break; // case "System.UInt16": // read[i] = new Reader(ReadUInt16Flag); // break; // case "System.UInt32": // read[i] = new Reader(ReadUInt32Flag); // break; //} } else { //read[i] = DicReader[retColType]; if (retColType == typeof(byte)) { read[i] = new Reader(ReadByte); } else if (retColType == typeof(System.UInt16)) { read[i] = new Reader(ReadUInt16); } else if (retColType == typeof(System.UInt32)) { read[i] = new Reader(ReadUInt32); } else if (retColType == typeof(NetPE.Core.Rva)) { read[i] = new Reader(ReadRva); } else if (retColType == typeof(NetPE.Core.Metadata.BlobToken)) { read[i] = new Reader(ReadBlobToken); } else if (retColType == typeof(NetPE.Core.Metadata.GUIDToken)) { read[i] = new Reader(ReadGUIDToken); } else if (retColType == typeof(NetPE.Core.Metadata.StringToken)) { read[i] = new Reader(ReadStringToken); } //switch ((ret.Columns[i].Type as Type).FullName) //{ // case "System.Byte": // read[i] = new Reader(ReadByte); // break; // case "System.UInt16": // read[i] = new Reader(ReadUInt16); // break; // case "System.UInt32": // read[i] = new Reader(ReadUInt32); // break; // case "NetPE.Core.Rva": // read[i] = new Reader(ReadRva); // break; // case "NetPE.Core.Metadata.BlobToken": // read[i] = new Reader(ReadBlobToken); // break; // case "NetPE.Core.Metadata.GUIDToken": // read[i] = new Reader(ReadGUIDToken); // break; // case "NetPE.Core.Metadata.StringToken": // read[i] = new Reader(ReadStringToken); // break; //} } } else if (retColTypeObj is TableType) { read[i] = new Reader(ReadTableToken); } else if (retColTypeObj is CodedIndex) { read[i] = new Reader(ReadCodedToken); } } List <Rva> rvas = new List <Rva>(); for (int i = 1; i <= lens[(int)ret.Type]; i++) { MetadataRow r = new MetadataRow(ret, false); bool hasRva = ret.Type == TableType.MethodDef || ret.Type == TableType.FieldRVA; int rvaIdx = 0; Rva rva = 0; for (int ii = 0; ii < read.Length; ii++) { if (hasRva && (ret.Columns[ii].Type is Type) && ((ret.Columns[ii].Type as Type) == typeof(NetPE.Core.Rva))) { rvaIdx = ii; rva = (Rva)rdr.ReadUInt32(); } else { r[ii] = read[ii](ii, ret, rdr, lens); } } if (hasRva) { r[rvaIdx] = rva; rvas.Add(rva); } r.Token = new MetadataToken((MetadataTokenType)ret.Type, (uint)i); ret.Rows.Add(r); } ReadRvaData(ret, rdr, rvas, ret.Rows); return(ret); }
void ReadRvaData(MetadataTable tbl, MetadataReader mdRdr, List <Rva> rvas, MetadataRowCollection rows) { List <Rva> sorted = new List <Rva>(rvas); sorted.Sort(); for (int i = 0; i < rvas.Count; i++) { Rva rva = rvas[i]; MetadataRow r = rows[i + 1]; byte[] dat = null; VirtualReader rdr = new VirtualReader(mdRdr.BaseStream.File.SectionHeaders.GetVirtualStream()); if (tbl.Type == TableType.FieldRVA) { MetadataRoot root = tbl.Heap.Stream.Root; rdr.SetPosition(rva); MetadataRow fd = (r["Field"] as TableToken).ResolveRow(); FieldSig sig = new FieldSig(); SignatureReader sigRdr = new SignatureReader(new MetadataReader(root[MetadataStreamType.Blob])); sigRdr.BaseStream.Position = (fd["Signature"] as BlobToken).Token.Index; sig.Read(sigRdr); int c = 0; switch (sig.Type.Element) { case ElementType.Boolean: case ElementType.UInt8: case ElementType.Int8: c = 1; break; case ElementType.UInt16: case ElementType.Int16: case ElementType.Char: c = 2; break; case ElementType.UInt32: case ElementType.Int32: case ElementType.Single: c = 4; break; case ElementType.UInt64: case ElementType.Int64: case ElementType.Double: c = 8; break; case ElementType.ValueType: TableToken vt = (sig.Type as VALUETYPE).Type; foreach (MetadataRow cl in tbl.Heap[TableType.ClassLayout]) { if (cl["Parent"] == vt) { c = (int)cl["ClassSize"]; break; } } break; default: throw new InvalidOperationException("ReadRvaData"); } dat = rdr.ReadBytes(c); } else if (tbl.Type == TableType.MethodDef && rva != 0) { //MethodBody bdy; //if (((MethodImplAttributes)r["ImplFlags"] & MethodImplAttributes.Native) == MethodImplAttributes.Native) //{ // bdy = new NativeMethodBody(r); //} //else //{ // bdy = new ManagedMethodBody(r); //} //rdr.SetPosition(rva); //bdy.Load(rdr); //rdr.SetPosition(rva); //dat = rdr.ReadBytes((int)bdy.Size); int idx; Rva next; if ((idx = sorted.IndexOf(rva)) == sorted.Count - 1) { CLRDirectory root = tbl.Heap.Stream.Root.Directory; Rva now; next = uint.MaxValue; rdr.SetPosition(root.Location.Address); rdr.BaseStream.Seek(0x8, System.IO.SeekOrigin.Current); if ((now = rdr.ReadRva()) < next && now != 0 && now > rva) { next = now; } rdr.BaseStream.Seek(0xC, System.IO.SeekOrigin.Current); if ((now = rdr.ReadRva()) < next && now != 0 && now > rva) { next = now; } rdr.BaseStream.Seek(0x4, System.IO.SeekOrigin.Current); if ((now = rdr.ReadRva()) < next && now != 0 && now > rva) { next = now; } rdr.BaseStream.Seek(0x4, System.IO.SeekOrigin.Current); if ((now = rdr.ReadRva()) < next && now != 0 && now > rva) { next = now; } rdr.BaseStream.Seek(0x4, System.IO.SeekOrigin.Current); if ((now = rdr.ReadRva()) < next && now != 0 && now > rva) { next = now; } rdr.BaseStream.Seek(0x4, System.IO.SeekOrigin.Current); if ((now = rdr.ReadRva()) < next && now != 0 && now > rva) { next = now; } rdr.BaseStream.Seek(0x4, System.IO.SeekOrigin.Current); if ((now = rdr.ReadRva()) < next && now != 0 && now > rva) { next = now; } } else { next = sorted[idx + 1]; } rdr.SetPosition(rva); dat = rdr.ReadBytes((int)(next - rva)); } if (!tbl.Heap.Stream.Root.Directory.Datas.ContainsAddress(rva) && dat != null) { tbl.Heap.Stream.Root.Directory.Datas.Add(new CLRData() { Address = rva, Data = dat }); } } }