In the last post we identified the next section as the
Metadata Table Header which has the following structure:
Size
|
Field
|
Description
|
4 bytes
|
Reserved
|
Reserved; set to 0.
|
1 byte
|
Major
|
Major
version of the table schema (1 for v1.0 and v1.1; 2 for v2.0 or later).
|
1 byte
|
Minor
|
Minor version of the table schema (0 for all versions).
|
1 byte
|
Heaps
|
Binary
flags indicate the offset sizes to be used within the heaps
.• 4-byte unsigned integer offset is indicated by 0x01 for a string heap, 0x02 for a GUID heap, and 0x04 for a blob heap .• If a flag is not set, the respective heap offset is a 2-byte unsigned integer .• A #- stream can also have special flags set: flag 0x20, indicating that the stream contains only changes made during an edit-and-continue session, and flag 0x80, indicating that the metadata might contain items marked as deleted. |
1 byte
|
Rid
|
Bit width of the maximal record index to all tables of the
metadata; calculated at run time (during the metadata stream initialization).
|
8 bytes
|
MaskValid
|
Bit
vector of present tables, each bit representing one table (1 if present).
|
8 bytes
|
Sorted
|
Bit vector of sorted tables, each bit representing a
respective table (1 if sorted).
|
Here is the data:
000002D0 50 00 00 00 23
42 6C 6F 62 00 00 00 00 00 00 00 P···#Blob·······
000002E0 02 00 00 01 47
15 00 00 09 00 00 00 00 FA 01 33 ····G········ú·3
000002F0 00 16 00 00 01
00 00 00 06 00 00 00 02 00 00 00 ················
00000300 02 00 00 00 01
00 00 00 06 00 00 00 02 00 00 00 ················
00000310 01 00 00 00 01
00 00 00 00 00 0A 00 01 00 00 00 ················
00000320 00 00 06 00 44
00 3D 00 06 00 76 00 56 00 06 00 ····D·=···v·V···
00000330 96 00 56 00 06
00 CC 00 3D 00 06 00 DE 00 3D 00 ?·V···I·=···_·=·
00000340 06 00 EA 00 3D
00 00 00 00 00 01 00 00 00 00 00 ··ê·=···········
00000350 01 00 01 00 00
00 10 00 21 00 29 00 05 00 01 00 ········!·)·····
00000360 01 00 50 20 00
00 00 00 91 00 4B 00 0A 00 01 00 ··P ····?·K·····
00000370 66 20 00 00 00
00 86 18 50 00 10 00 02 00 00 00 f ····?·P·······
00000380 01 00 C7 00 11
00 50 00 14 00 19 00 50 00 10 00 ··Ç···P·····P···
00000390 21 00 D4 00 19
00 29 00 F2 00 1E 00 21 00 D4 00 !·O···)·ò···!·O·
000003A0 23 00 09 00 50
00 10 00 2E 00 0B 00 28 00 2E 00 #···P···.···(·.·
000003B0 13 00 31 00 04
80 00 00 00 00 00 00 00 00 00 00 ··1··?··········
000003C0 00 00 00 00 00
00 B4 00 00 00 02 00 00 00 00 00 ······'·········
000003D0 00 00 00 00 00
00 01 00 34 00 00 00 00 00 00 00 ········4·······
We start with 4 reserved bytes, followed by the 1 byte Major
and 1 byte Minor version of the table Schema which are 0x02 and 0x00
respectively. That means that the data
in the stream is stored in the v2.0 schema.
Next is the Heaps which contains a flag field for the offset size stored
in the heap which contains 0x00 indicating that we are using a 2 byte unsigned
integer to store the heap offset. Here
is a table showing the options:
Binary
Flag Value
|
Meaning
|
0x00
|
2 byte offset values
|
0x01
|
4 byte offset values for a string heap
|
0x02
|
4 byte offset values for a GUID heap
|
0x04
|
4 byte offset values for a blob heap
|
0x20
|
The stream contains only changes from an edit and
continue session
|
0x80
|
The stream might contain data that is marked as deleted
|
The next value is the RID containing 0x01 which is the bit
width of the maximal record index in all of the tables. Next we have the MaskValid which is 8 bytes
containing the value 0x0000000900001547 which is a bit vector indicating which
tables are contained within the stream.
The Sorted bit vector is also 8
bytes and contains 0x000016003301FA00 and indicates if the table is sorted.
The MaskValid bit vector pattern is:
00000000 00000000 00000000 00001001 00000000 00000000 00010101 01000111
And the Sorted bit vector pattern is:
00000000 00000000 00010110 00000000 00110011 00000001 11111010 00000000
Which seems strange to me since it is telling me that there
are tables that are not there but are sorted.
Anyway, the list of table types is a bit long, so here is the MetadataTable Type List. What the MaskValid bit vector pattern tells us is that the tables stored are 0, 1, 2, 6, 8, 10, 12, 32, 35 or Module, TypeRef, TypeDef, Method, Param, MemberRef, CustomAttribute, Assembly, and AssemblyRef.
What the Sorted bit vector tells us that the sorted tables are 9, 11, 12, 13, 14, 15, 16, 24, 25, 28, 29, 41, 42, and 44 or InterfaceImpl, Constant, CustomAttribute, FieldMarshal, DeclSecurity, ClassLayout, FieldLayout, MethodSemantics, MethodImpl, ImplMap, FieldRVA, NestedClass, GenericParam, and GenericParamConstraint.
The next part is a series of 4 byte unsigned integers which
indicate the number of records in each of the tables indicated by the MaskValid
bit vector. There are 9 1s so there are 9 values:
0x0001, 0x0006, 0x0002, 0x0002, 0x0001, 0x0006, 0x0002, 0x0001, 0x0001
They tell us that the Module table has 1 entry, the TypeRef table has 6 entries, the TypeDef table has 2 entries, the Method table has 2 entries, the Param table has 1 entry, the MemberRef table has 6 entries, the CustomAttribute table has 2 entries, the Assembly table has 1 entry, and the AssemblyRef table has 1 entry.
That is it for tonight, we will pick back up and decode the tables tomorrow. Keep your code clean!