蛙蛙推荐:windbg里查看DateTime值g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
我们都知道在windbg里可以用!do命令查看一个引用对象的详细信息,但像DateTime,Guid,IpAddress等并不能直接用windbg命令打印出来。g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
我们一个一个说,先创建一个console程序叫DateTimeTest,在属性页里启用非托管代码调试,代码如下g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
using System;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
namespace DateTimeTestg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    class Programg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    {g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        static void Main(string[] args)g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        {g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
            DateTime dt = DateTime.Now;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
            Console.WriteLine(dt);g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
            Console.Read();g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
}g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
并在Console.Read();行上加入断点,F5启动调试程序,断点断住后,在即使窗口里输入如下命令g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
.load sosg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
已加载扩展 C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\sos.dllg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
!Name2EE *!System.DateTimeg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
PDB symbol for mscorwks.dll not loadedg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
Module: 790c2000 (mscorlib.dll)g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
Token: 0x02000032g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
MethodTable: 79104b50g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
EEClass: 79104aecg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
Name: System.DateTimeg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
--------------------------------------g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
Module: 00a9205c (sorttbls.nlp)g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
--------------------------------------g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
Module: 00a923cc (prcp.nlp)g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
--------------------------------------g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
Module: 00a927cc (mscorlib.resources.dll)g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
--------------------------------------g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
Module: 00a72c24 (DateTimeTest.exe)g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
!clrstack -ag©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
OS Thread Id: 0xcd4 (3284)g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
ESP      EIP    g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
0012f434 011300d5 DateTimeTest.Program.Main(System.String[])g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    PARAMETERS:g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        args = 0x013e1b20g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    LOCALS:g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        0x0012f43c = 0x88f0476cg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
0012f69c 79e7be1b [GCFrame: 0012f69c] g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
!DumpVC  79104b50 0x0012f43cg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
Name: System.DateTimeg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
MethodTable 79104b50g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
EEClass: 79104aecg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
Size: 16(0x10) bytesg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
(C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
Fields:g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
      MT    Field  Offset                Type VT    Attr    Value Nameg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
791042d4  40000f4        0        System.UInt64  0 instance 9856781253186963308 dateDatag©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
79122414  40000f0      30      System.Int32[]  0  shared  static DaysToMonth365g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    >> Domain:Value  0014d3b0:013e1c78 <<g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
79122414  40000f1      34      System.Int32[]  0  shared  static DaysToMonth366g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    >> Domain:Value  0014d3b0:013e1cb8 <<g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
79104b50  40000f2      28      System.DateTime  1  shared  static MinValueg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    >> Domain:Value  0014d3b0:013e1c58 <<g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
79104b50  40000f3      2c      System.DateTime  1  shared  static MaxValueg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    >> Domain:Value  0014d3b0:013e1c68 <<g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
9856781253186963308这个值是一个ULong类型的,DateTime的构造函数不支持这个类型的重载,Convert.ToDateTime对这个参数的重载版本也是始终返回异常,然后看MSDN里对DateTime的说明g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
在 .NET Framework 2.0 版以前,DateTime 结构包含一个 64 位字段,该字段由一个未使用的 2 位字段和一个私有字段 Ticks 串联组成,Ticks 字段是一个 62 位无符号字段,其中包含表示日期和时间的刻度数。Ticks 字段的值可通过 Ticks 属性获取。g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
从 .NET Framework 2.0 开始,DateTime 结构包含一个由私有字段 Kind 和 Ticks 字段串联组成的 64 位字段。Kind 字段是一个 2 位字段,它指示 DateTime 结构是表示本地时间、协调通用时间 (UTC) 还是 UTC 和本地时间都未指定。Kind 字段用于处理本地时间和 UTC 时间之间的转换,但不用于时间的比较或算术运算。Kind 字段的值可通过 Kind 属性获取。g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
所以我们要把9856781253186963308这个值转换成2进制,然后把高位的2位换成零,然后在传入DateTime的构造函数里,具体代码如下g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
using System;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
using System.IO;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
namespace DateTimeTestg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    class Programg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    {g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        static void Main(string[] args)g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        {g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
            MemoryStream ms = new MemoryStream();g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
            BinaryWriter bw = new BinaryWriter(ms);g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
            bw.Write(9856781253186963308UL);g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
            byte[] bs = ms.ToArray();g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
            bs[7] = (byte)(bs[7] & 63);g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
            ms = new MemoryStream(bs);g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
            BinaryReader br = new BinaryReader(ms);g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
            Int64 i = br.ReadInt64();g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
            Console.WriteLine(new DateTime(i));g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
            Console.Read();g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
}g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
其中把第8个字节按位于上63就是把高位2位置0,因为63的二进制是00111111。g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
后来ReflectorDateTime的代码,发现.net里有一个类似的函数,只用以下代码就OK了g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
Console.WriteLine(new DateTime((long)(9856781253186963308UL & 0x3fffffffffffffffL)));g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
同理,IPAddress的代码如下g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
IPAddress ip = IPAddress.Parse("192.168.1.1");g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
windbg分析如下g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
!clrstack -ag©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
OS Thread Id: 0x338 (824)g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
ESP      EIP    g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
0012f438 011300aa DateTimeTest.Program.Main(System.String[])g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    PARAMETERS:g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        args = 0x013e1b20g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    LOCALS:g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        0x0012f440 = 0x013e1d40g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
0012f69c 79e7be1b [GCFrame: 0012f69c] g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
!do 0x013e1d40g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
Name: System.Net.IPAddressg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
MethodTable: 7a77d078g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
EEClass: 7a7dc4f8g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
Size: 40(0x28) bytesg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
(C:\WINDOWS\assembly\GAC_MSIL\System\2.0.0.0__b77a5c561934e089\System.dll)g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
Fields:g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
      MT    Field  Offset                Type VT    Attr    Value Nameg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
790fb9bc  400209c        4        System.Int64  0 instance 16885952 m_Addressg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
790f9244  400209d      14        System.String  0 instance 013fd0e4 m_ToStringg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
7a787ec0  40020a1      1c        System.Int32  0 instance        2 m_Familyg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
7912a84c  40020a2      18      System.UInt16[]  0 instance 013e1d68 m_Numbersg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
790fb9bc  40020a3        c        System.Int64  0 instance 0 m_ScopeIdg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
790fdb60  40020a4      20        System.Int32  0 instance        0 m_HashCodeg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
7a77d078  4002098      7b4 System.Net.IPAddress  0  static 013fcef8 Anyg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
7a77d078  4002099      7b8 System.Net.IPAddress  0  static 013fcf3c Loopbackg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
7a77d078  400209a      7bc System.Net.IPAddress  0  static 013fcf80 Broadcastg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
7a77d078  400209b      7c0 System.Net.IPAddress  0  static 013fcf80 Noneg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
7a77d078  400209e      7c4 System.Net.IPAddress  0  static 013fcfe0 IPv6Anyg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
7a77d078  400209f      7c8 System.Net.IPAddress  0  static 013fd040 IPv6Loopbackg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
7a77d078  40020a0      7cc System.Net.IPAddress  0  static 013fd0a0 IPv6Noneg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
最终可用如下函数得到IPg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
private static string IntToIP(long ip_Int)g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    long num = ((ip_Int & 0xff000000L) >> 0x18);g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    if (num < 0L)g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    {g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        num += 0x100L;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    long num2 = (ip_Int & 0xff0000L) >> 0x10;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    if (num2 < 0L)g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    {g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        num2 += 0x100L;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    long num3 = (ip_Int & 0xff00L) >> 8;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    if (num3 < 0L)g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    {g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        num3 += 0x100L;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    long num4 = ip_Int & 0xffL;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    if (num4 < 0L)g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    {g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        num4 += 0x100L;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    return (num4 + "." + num3 + "." + num2 + "." + num);g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
}g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
或者用以下语句(支持IPV6啥的)g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
Console.WriteLine(new IPAddress(16885952));g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
GUID类型dumpvc后是a到k的一串值,有int,short,byte的都有,你要一步一步的把值查出来,然后写一个程序传给System.Guid的构造函数,然后ToString()方法后才能看到,比较麻烦,如果能在windbg里动态执行某个对象的方法就好了,比如ToString()方法g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ