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

强暴.Net程序集 之十一 (方法头的结构:窄头与宽头)

警告:本系列文章为本人原创,只作技术研究之用,您可以引用链接传播,禁止其它的转载方式,禁止用于商业或非法目的, 对于造成的一切后果本人概不负责

MethodDef的Rva定义了一个方法的位置, 每个方法体之前都有一个方法头
方法头分为tiny头 和 fat头两种格式, 方法的前两位定义是tiny还是fat头, Partition II Metadata文档描述如下:

25.4.1    Method header type values
The two least significant bits of the first byte of the method header indicate what type of header is present.  These 2 bits will be one and only one of the following:
Value                                     Value    Description
CorILMethod_TinyFormat    0x2    The method header is tiny (§25.4.2) .
CorILMethod_FatFormat    0x3    The method header is fat (§25.4.3).

tiny头的格式比较简单, 只有一个字节, 除了最低的0x2外, 其余6位保存IL代码的大小
如果一个方法没有局部变量, 异常处理, 方法小于64字节, 存储栈深度为8时, 那么就使用tiny头
Partition II Metadata文档描述如下:
Start Bit    Count of Bits    Description
0            2                Flags (CorILMethod_TinyFormat shall be set, see §25.4.4)
2            6                Size, in bytes, of the method body immediately following this header.

fat头的格式就比较复杂, 大小是12个字节, Partition II Metadata文档中描述如下:
Offset     Size         Field       Description
0          12 (bits)    Flags       Flags (CorILMethod_FatFormat shall be set in bits 0:1, see §25.4.4)
12 (bits)  4 (bits)     Size        Size of this header expressed as the count of 4-byte integers occupied (currently 3)
2          2            MaxStack    Maximum number of items on the operand stack
4          4            CodeSize    Size in bytes of the actual method body
8          4            LocalVarSigTok    Meta Data token for a signature describing the layout of the local variables for the method.  0 means there are no local variables present

最开始的2个字节中低两位是表示fat头的0x3, 接下来的10是标志(见Partition II Metadata 的 25.4.4 Flags for method headers), 最高4位一直为3
接下来的2个字节是MaxStack, 是存储栈最大深度
之后的4个字节是CodeSize, 是IL代码的大小
最后的4个字节是LocalVarSigTok,是局部变量的特征标识

程序如下:
    PBYTE instructions = (PBYTE)GetPtrFromRva(rva, m_pNTHeader, m_pImageBase);
    if((instructions[0] & 3) == 0x2)
    {

        WCHAR lBuffer[64];
        methodSize = instructions[0] >> 2;
        codeSize = methodSize;
        maxstack = 8;
        localVariables = 0;
        exceptionHandler = false;
        initLocals = false;           
    }
    else if((instructions[0] & 3) == 0x3)
    {

            USHORT flagsSize = *((USHORT*)&instructions[0]);
            methodSize = ((flagsSize >> 12) & 0xf) * 4;

            if((flagsSize & 0x8) != 0)
            {
                exceptionHandler = true;
            }
            else
            {
                exceptionHandler = false;
            }

            if((flagsSize & 0x10) != 0)
            {
                initLocals = true;
            }
            else
            {
                initLocals = false;           
            }


            maxstack = *((USHORT*)&instructions[2]);
            codeSize = *((DWORD*)&instructions[4]);

            localVariables = *((DWORD*)&instructions[8]);
    }

评论

请稍候...
很抱歉,您输入的评论太长。请缩短您的评论。
您没有输入任何内容,请重试。
很抱歉,我们当前无法添加您的评论。请稍后重试。
若要添加评论,需要您的家长授予您相应权限。请求权限
您的家长禁用了评论功能。
很抱歉,我们当前无法删除您的评论。请稍后重试。
您已超过了一天之内允许提供的评论数上限。请在 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!447.trak
引用此项的网络日志