Exemple #1
0
 public MetadataTable(TablesHeap h, TableType t)
 {
     this.h = h;
     def    = TableDefs.MdTableDefs[t];
     rs     = new MetadataRowCollection(this);
     cols   = new MetadataColumn[def.Columns.Length];
     for (int i = 0; i < def.Columns.Length; i++)
     {
         cols[i] = new MetadataColumn(i, def.Columns[i].Key, def.Columns[i].Value);
     }
 }
        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
                    });
                }
            }
        }