shuai 的个人资料娱乐精神照片日志 工具 帮助
2007/11/9

强暴.Net程序集 之九 (TypeDef表结构)


警告:本系列文章为本人原创,只作技术研究之用,您可以引用链接传播,禁止其它的转载方式,禁止用于商业或非法目的, 对于造成的一切后果本人概不负责
 
现在我们来看一个非常重要的元数据表TypeDef, 它定义了类型信息
在Partition II Metadata中描述了它的格式:
The TypeDef table has the following columns:
• Flags (a 4-byte bitmask of type TypeAttributes, §23.1.15)
• TypeName (an index into the String heap)
• TypeNamespace (an index into the String heap)
• Extends (an index into the TypeDef, TypeRef, or TypeSpec table; more precisely, a TypeDefOrRef  (§24.2.6) coded index)
• FieldList (an index into the Field table; it marks the first of a contiguous run of Fields owned by this Type).  The run continues to the smaller of:
o the last row of the Field table
o the next run of Fields, found by inspecting the FieldList of the next row in this TypeDef table
• MethodList (an index into the MethodDef table; it marks the first of a continguous run of Methods owned by this Type).  The run continues to the smaller of:
o the last row of the MethodDef table
o the next run of Methods, found by inspecting the MethodList of the next row in this TypeDef table
 
其中:

Flags 是一个位掩码, 描述了类型的一些属性信息, 文档中的23.1.15 Flags for types [TypeAttributes]一节中详情描述
在corhdr.h中也有一个定义, 下面是一个节选的列表:
typedef enum CorTypeAttr
{
    // Use this mask to retrieve the type visibility information.
    tdVisibilityMask        =   0x00000007,
    tdNotPublic             =   0x00000000,     // Class is not public scope.
    tdPublic                =   0x00000001,     // Class is public scope.
    // Use this mask to retrieve class semantics information.
    tdClassSemanticsMask    =   0x00000060,
    tdClass                 =   0x00000000,     // Type is a class.
    tdInterface             =   0x00000020,     // Type is an interface.
    // end semantics mask
    // Special semantics in addition to class semantics.
    tdAbstract              =   0x00000080,     // Class is abstract
    tdSealed                =   0x00000100,     // Class is concrete and may not be extended
    tdSpecialName           =   0x00000400,     // Class name is special.  Name describes how.
 //其它略
} CorTypeAttr;
 
并且corhdr.h还有一系列宏, 用于方便的查询类型的一些属性,比如
#define IsTdClass(x)                        (((x) & tdClassSemanticsMask) == tdClass)
 
TypeName和TypeNamespace 都是一个String 堆的索引值, 要注意它的长度随HeapSizes的大小而变
 
Extends 描述了类型的继承情况, 即指向基类的信息(接口为0), 但是这个值并不是一个元数据token, 而是一个对token进行压缩后的值, TypeDefOrRefEncoded一节中描述了这个值的算法
比如token为0x01000012,那么它的TypeDefOrRefEncoded 值为
 encoded = ( 0x000012 << 2 ) |  0x01  (0x01 指 TypeRef 在TypeDefOrRef中的编号)
            = 0x48 | 0x01
            = 0x49
其中TypeDefOrRef指将TypeDef, TypeRef, TypeSpec这一组号转为一个2位的编号:
TypeDefOrRef    Tag
TypeDef             0
TypeRef             1
TypeSpec           2
可以看出, 这个压缩后的值, 最后两位描述了基类所处于的元数据表在TypeDefOrRef中的编号, 编号之前的位是在该在表中的索引号
 
FieldList 和MethodList是一个指向Field和Method表中的起始索引的值, 从此开始遍历都是它的Field和Method, 结束于下一个类型的Field和Method表中的起始索引(相当不能超过RowSize), 在Partition II Metadata 的 Field 表一节中有详细的说明
比如FieldList值为0x01, 而下一个类型的FieldList为0x03, 那么0x01和0x02都是该类型的Field索引
 
 
下面我们通过代码看如何得到TypeDef 表中的这些值
 
        row = t.Address + t.RowSize * index; //每行的地址, index为类型在TypeDef中的索引

        // Flags
        flags = *((DWORD *)row);
        row += 4;

        // Name
        if(t.HeapSizes & 0x01)
        {
                nameIndex = *((ULONG *)row);
                row += 4;
                nameSpaceIndex = *((ULONG *)row);
                row += 4;
        }
        else
        {
                nameIndex = *((USHORT *)row);
                row += 2;
                nameSpaceIndex = *((USHORT *)row);
                row += 2;
        }
        //nameIndex 和nameSpaceIndex 为在String表中的索引

        // Extends
        if(t.IndexSizes & 0x08)
        {
                extends = *((DWORD *)row);
                row += 4;
        }
        else
        {
                extends = *((USHORT *)row);
                row += 2;
        }
        extendsTable = (BYTE)(extends & 0x3);
        extendsIndex = extends = extends >> 2;
        switch(extendsTable)
        {
        case 0:
                // TypeDef
                extends |= 0x02 << 24;
                break;
        case 1:
                // TypeRef
                extends |= 0x01 << 24;
                break;
        case 2:
                // TypeSpec
                extends |= 0x1b << 24;
                break;
        }
        // 现在extends 为Extends转成token的格式

        // FieldList
        if(t.IndexSizes & 0x08)
        {
                fields = *((DWORD *)row);
                if(index < t.Rows - 1)
                        endFields = *((DWORD *)(row + t.RowSize));
                else
                        endFields = 0;
                row += 4;
        }
        else
        {
                fields = *((USHORT *)row);
                if(index < t.Rows - 1)
                        endFields = *((USHORT *)(row + t.RowSize));
                else
                        endFields = 0;
                row += 2;
        }
        // fields 为该类型FieldList的起始索引, endFields 为结束索引

        // MethodList
        if(t.IndexSizes & 0x08)
        {
                methods = *((DWORD *)row);
                if(index < t.Rows - 1)
                        endMethods = *((DWORD *)(row + t.RowSize));
                else
                        endMethods = 0;
                row += 4;
        }
        else
        {
                methods = *((USHORT *)row);
                if(index < t.Rows - 1)
                        endMethods = *((USHORT *)(row + t.RowSize));
                else
                        endMethods = 0;
                row += 2;
        }
        // methods 为该类型MethodList的起始索引, endMethods 为结束索引


 

评论

请稍候...
很抱歉,您输入的评论太长。请缩短您的评论。
您没有输入任何内容,请重试。
很抱歉,我们当前无法添加您的评论。请稍后重试。
若要添加评论,需要您的家长授予您相应权限。请求权限
您的家长禁用了评论功能。
很抱歉,我们当前无法删除您的评论。请稍后重试。
您已超过了一天之内允许提供的评论数上限。请在 24 小时后重试。
因为我们的系统表明您可能在向其他用户提供垃圾评论,您的帐户已禁用了评论功能。如果您认为我们错误地禁用了您的帐户,请联系 Windows Live 支持部门
完成下面的安全检查,您提供评论的过程才能完成。
您在安全检查中键入的字符必须与图片或音频中的字符一致。

若要添加评论,请使用您的 Windows Live ID 登录(如果您使用过 Hotmail、Messenger 或 Xbox LIVE,您就拥有 Windows Live ID)。登录


还没有 Windows Live ID 吗?请注册

引用通告

此日志的引用通告 URL 是:
http://iauhsgnay.spaces.live.com/blog/cns!C7C5DB6D46321CDD!429.trak
引用此项的网络日志