警告:本系列文章为本人原创,只作技术研究之用,您可以引用链接传播,禁止其它的转载方式,禁止用于商业或非法目的, 对于造成的一切后果本人概不负责
FieldDef非常的简单, Partition II Metadata中描述为:
22.15 Field : 0x04
The Field table has the following columns:
• Flags (a 2-byte bitmask of type FieldAttributes, §23.1.5)
• Name (an index into the String heap)
• Signature (an index into the Blob heap)
其中Flags 字段是一个位掩码, 描述了字段的属性
corhdl.h中有它的定义
typedef enum CorFieldAttr
{
// member access mask - Use this mask to retrieve accessibility information.
fdFieldAccessMask = 0x0007,
fdPrivateScope = 0x0000, // Member not referenceable.
fdPrivate = 0x0001, // Accessible only by the parent type.
fdFamANDAssem = 0x0002, // Accessible by sub-types only in this Assembly.
fdAssembly = 0x0003, // Accessibly by anyone in the Assembly.
fdFamily = 0x0004, // Accessible only by type and sub-types.
fdFamORAssem = 0x0005, // Accessibly by sub-types anywhere, plus anyone in assembly.
fdPublic = 0x0006, // Accessibly by anyone who has visibility to this scope.
// end member access mask
// field contract attributes.
fdStatic = 0x0010, // Defined on type, else per instance.
fdInitOnly = 0x0020, // Field may only be initialized, not written to after init.
fdLiteral = 0x0040, // Value is compile time constant.
fdNotSerialized = 0x0080, // Field does not have to be serialized when type is remoted.
fdSpecialName = 0x0200, // field is special. Name describes how.
// interop attributes
fdPinvokeImpl = 0x2000, // Implementation is forwarded through pinvoke.
// Reserved flags for runtime use only.
fdReservedMask = 0x9500,
fdRTSpecialName = 0x0400, // Runtime(metadata internal APIs) should check name encoding.
fdHasFieldMarshal = 0x1000, // Field has marshalling information.
fdHasDefault = 0x8000, // Field has default.
fdHasFieldRVA = 0x0100, // Field has RVA.
} CorFieldAttr;
可以通过如下程序得到所有Field的属性, t为FieldDef表
for(DWORD i = 0; i < t.Rows; ++i)
{
row = t.Address + t.RowSize * index;
// Flags
flags = *((USHORT *)row);
row += 2;
// Name
if(t.HeapSizes & 0x01)
{
name = *((ULONG *)row);
row += 4;
}
else
{
name = *((USHORT *)row);
row += 2;
}
// Signature
if(t.HeapSizes & 0x04)
{
signature = *((ULONG *)row);
row += 4;
}
else
{
signature = *((USHORT *)row);
row += 2;
}
}
MethodDef 表在Partition II Metadata中描述为:
22.26 MethodDef : 0x06
The MethodDef table has the following columns:
• RVA (a 4-byte constant)
• ImplFlags (a 2-byte bitmask of type MethodImplAttributes, §23.1.10)
• Flags (a 2-byte bitmask of type MethodAttributes, §23.1.10)
• Name (an index into the String heap)
• Signature (an index into the Blob heap)
• ParamList (an index into the Param table). It marks the first of a contiguous run of Parameters owned by this method. The run continues to the smaller of:
o the last row of the Param table
o the next run of Parameters, found by inspecting the ParamList of the next row in the MethodDef table
对了, 别忘了Property(属性实际上就是get_和set_方法)
其中Flags标记保存Method的一些可访问性及其它属性
corhdr.h 中有它的定义
typedef enum CorMethodAttr
{
// member access mask - Use this mask to retrieve accessibility information.
mdMemberAccessMask = 0x0007,
mdPrivateScope = 0x0000, // Member not referenceable.
mdPrivate = 0x0001, // Accessible only by the parent type.
mdFamANDAssem = 0x0002, // Accessible by sub-types only in this Assembly.
mdAssem = 0x0003, // Accessibly by anyone in the Assembly.
mdFamily = 0x0004, // Accessible only by type and sub-types.
mdFamORAssem = 0x0005, // Accessibly by sub-types anywhere, plus anyone in assembly.
mdPublic = 0x0006, // Accessibly by anyone who has visibility to this scope.
// end member access mask
// method contract attributes.
mdStatic = 0x0010, // Defined on type, else per instance.
mdFinal = 0x0020, // Method may not be overridden.
mdVirtual = 0x0040, // Method virtual.
mdHideBySig = 0x0080, // Method hides by name+sig, else just by name.
// vtable layout mask - Use this mask to retrieve vtable attributes.
mdVtableLayoutMask = 0x0100,
mdReuseSlot = 0x0000, // The default.
mdNewSlot = 0x0100, // Method always gets a new slot in the vtable.
// end vtable layout mask
// method implementation attributes.
mdCheckAccessOnOverride = 0x0200, // Overridability is the same as the visibility.
mdAbstract = 0x0400, // Method does not provide an implementation.
mdSpecialName = 0x0800, // Method is special. Name describes how.
// interop attributes
mdPinvokeImpl = 0x2000, // Implementation is forwarded through pinvoke.
mdUnmanagedExport = 0x0008, // Managed method exported via thunk to unmanaged code.
// Reserved flags for runtime use only.
mdReservedMask = 0xd000,
mdRTSpecialName = 0x1000, // Runtime should check name encoding.
mdHasSecurity = 0x4000, // Method has security associate with it.
mdRequireSecObject = 0x8000, // Method calls another method containing security code.
} CorMethodAttr;
值得说明的是ParamList字段
它记录了Param表的记录索引, 指明所属方法的参数的开始位置, 结束于下一个方法参数的开始
程序如下, t为MethodDef表
for(DWORD i = 0; i < t.Rows; ++i)
{
row = t.Address + t.RowSize * index;
// RVA
rva = *((DWORD *)row);
row += 4;
// ImplFlags
implFlags = *((USHORT *)row);
row += 2;
// Flags
flags = *((USHORT *)row);
row += 2;
// Name
if(t.HeapSizes & 0x01)
{
nameIndex = *((ULONG *)row);
row += 4;
wcscpy(lBuffer, pView->StringTableEntry(nameIndex).c_str());
}
else
{
nameIndex = *((USHORT *)row);
row += 2;
wcscpy(lBuffer, pView->StringTableEntry(nameIndex).c_str());
}
// Signature
if(t.HeapSizes & 0x04)
{
signature = *((DWORD *)row);
row += 4;
}
else
{
signature = *((USHORT *)row);
row += 2;
}
// ParamList
if(t.IndexSizes & 0x10)
{
params = *((DWORD *)row);
if(index < t.Rows - 1)
endparams = *((DWORD *)(row + t.RowSize));
else
endparams = 0;
row += 4;
}
else
{
params = *((USHORT *)row);
if(index < t.Rows - 1)
endparams = *((USHORT *)(row + t.RowSize));
else
endparams = 0;
row += 2;
}
}