zoukankan      html  css  js  c++  java
  • 蛙蛙推荐:windbg里查看DateTime值

    蛙蛙推荐:windbg里查看DateTime值
    我们都知道在windbg里可以用!do命令查看一个引用对象的详细信息,但像DateTime,Guid,IpAddress等并不能直接用windbg命令打印出来。
    我们一个一个说,先创建一个console程序叫DateTimeTest,在属性页里启用非托管代码调试,代码如下
    using System;
    namespace DateTimeTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                DateTime dt = DateTime.Now;
                Console.WriteLine(dt);
                Console.Read();
            }
        }
    }

    并在Console.Read();行上加入断点,F5启动调试程序,断点断住后,在即使窗口里输入如下命令
    .load sos
    已加载扩展 C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\sos.dll
    !Name2EE *!System.DateTime
    PDB symbol for mscorwks.dll not loaded
    Module: 790c2000 (mscorlib.dll)
    Token: 0x02000032
    MethodTable:
    79104b50
    EEClass: 79104aec
    Name: System.DateTime
    --------------------------------------
    Module: 00a9205c (sorttbls.nlp)
    --------------------------------------
    Module: 00a923cc (prcp.nlp)
    --------------------------------------
    Module: 00a927cc (mscorlib.resources.dll)
    --------------------------------------
    Module: 00a72c24 (DateTimeTest.exe)

    !clrstack -a
    OS Thread Id: 0xcd4 (3284)
    ESP       EIP    
    0012f434 011300d5 DateTimeTest.Program.Main(System.String[])
        PARAMETERS:
            args = 0x013e1b20
        LOCALS:
            0x0012f43c = 0x88f0476c

    0012f69c 79e7be1b [GCFrame: 0012f69c]

    !DumpVC  79104b50 0x0012f43c
    Name: System.DateTime
    MethodTable 79104b50
    EEClass: 79104aec
    Size: 16(0x10) bytes
     (C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
    Fields:
          MT    Field   Offset                 Type VT     Attr    Value Name
    791042d4  40000f4        0        System.UInt64  0 instance 9856781253186963308 dateData
    79122414  40000f0       30       System.Int32[]  0   shared   static DaysToMonth365
        >> Domain:Value  0014d3b0:013e1c78 <<
    79122414  40000f1       34       System.Int32[]  0   shared   static DaysToMonth366
        >> Domain:Value  0014d3b0:013e1cb8 <<
    79104b50  40000f2       28      System.DateTime  1   shared   static MinValue
        >> Domain:Value  0014d3b0:013e1c58 <<
    79104b50  40000f3       2c      System.DateTime  1   shared   static MaxValue
        >> Domain:Value  0014d3b0:013e1c68 <<

    9856781253186963308这个值是一个ULong类型的,DateTime的构造函数不支持这个类型的重载,Convert.ToDateTime对这个参数的重载版本也是始终返回异常,然后看MSDN里对DateTime的说明
    在 .NET Framework 2.0 版以前,DateTime 结构包含一个 64 位字段,该字段由一个未使用的 2 位字段和一个私有字段 Ticks 串联组成,Ticks 字段是一个 62 位无符号字段,其中包含表示日期和时间的刻度数。Ticks 字段的值可通过 Ticks 属性获取。

    从 .NET Framework 2.0 开始,DateTime 结构包含一个由私有字段 Kind 和 Ticks 字段串联组成的 64 位字段。Kind 字段是一个 2 位字段,它指示 DateTime 结构是表示本地时间、协调通用时间 (UTC) 还是 UTC 和本地时间都未指定。Kind 字段用于处理本地时间和 UTC 时间之间的转换,但不用于时间的比较或算术运算。Kind 字段的值可通过 Kind 属性获取。

    所以我们要把9856781253186963308这个值转换成2进制,然后把高位的2位换成零,然后在传入DateTime的构造函数里,具体代码如下
    using System;
    using System.IO;

    namespace DateTimeTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                MemoryStream ms = new MemoryStream();
                BinaryWriter bw = new BinaryWriter(ms);
                bw.Write(9856781253186963308UL);
                byte[] bs = ms.ToArray();
                bs[7] = (byte)(bs[7] & 63);
                ms = new MemoryStream(bs);
                BinaryReader br = new BinaryReader(ms);
                Int64 i = br.ReadInt64();
                Console.WriteLine(new DateTime(i));
                Console.Read();
            }
        }
    }
    其中把第8个字节按位于上63就是把高位2位置0,因为63的二进制是00111111。
    后来ReflectorDateTime的代码,发现.net里有一个类似的函数,只用以下代码就OK了
    Console.WriteLine(new DateTime((long)(9856781253186963308UL & 0x3fffffffffffffffL)));
    同理,IPAddress的代码如下
    IPAddress ip = IPAddress.Parse("192.168.1.1");
    windbg分析如下
    !clrstack -a
    OS Thread Id: 0x338 (824)
    ESP       EIP    
    0012f438 011300aa DateTimeTest.Program.Main(System.String[])
        PARAMETERS:
            args = 0x013e1b20
        LOCALS:
            0x0012f440 = 0x013e1d40

    0012f69c 79e7be1b [GCFrame: 0012f69c]


    !do 0x013e1d40
    Name: System.Net.IPAddress
    MethodTable: 7a77d078
    EEClass: 7a7dc4f8
    Size: 40(0x28) bytes
     (C:\WINDOWS\assembly\GAC_MSIL\System\2.0.0.0__b77a5c561934e089\System.dll)
    Fields:
          MT    Field   Offset                 Type VT     Attr    Value Name
    790fb9bc  400209c        4         System.Int64  0 instance 16885952 m_Address
    790f9244  400209d       14        System.String  0 instance 013fd0e4 m_ToString
    7a787ec0  40020a1       1c         System.Int32  0 instance        2 m_Family
    7912a84c  40020a2       18      System.UInt16[]  0 instance 013e1d68 m_Numbers
    790fb9bc  40020a3        c         System.Int64  0 instance 0 m_ScopeId
    790fdb60  40020a4       20         System.Int32  0 instance        0 m_HashCode
    7a77d078  4002098      7b4 System.Net.IPAddress  0   static 013fcef8 Any
    7a77d078  4002099      7b8 System.Net.IPAddress  0   static 013fcf3c Loopback
    7a77d078  400209a      7bc System.Net.IPAddress  0   static 013fcf80 Broadcast
    7a77d078  400209b      7c0 System.Net.IPAddress  0   static 013fcf80 None
    7a77d078  400209e      7c4 System.Net.IPAddress  0   static 013fcfe0 IPv6Any
    7a77d078  400209f      7c8 System.Net.IPAddress  0   static 013fd040 IPv6Loopback
    7a77d078  40020a0      7cc System.Net.IPAddress  0   static 013fd0a0 IPv6None


    最终可用如下函数得到IP
    private static string IntToIP(long ip_Int)
    {
        long num = ((ip_Int & 0xff000000L) >> 0x18);
        if (num < 0L)
        {
            num += 0x100L;
        }
        long num2 = (ip_Int & 0xff0000L) >> 0x10;
        if (num2 < 0L)
        {
            num2 += 0x100L;
        }
        long num3 = (ip_Int & 0xff00L) >> 8;
        if (num3 < 0L)
        {
            num3 += 0x100L;
        }
        long num4 = ip_Int & 0xffL;
        if (num4 < 0L)
        {
            num4 += 0x100L;
        }
        return (num4 + "." + num3 + "." + num2 + "." + num);
    }
    或者用以下语句(支持IPV6啥的)
    Console.WriteLine(new IPAddress(16885952));
    GUID类型dumpvc后是a到k的一串值,有int,short,byte的都有,你要一步一步的把值查出来,然后写一个程序传给System.Guid的构造函数,然后ToString()方法后才能看到,比较麻烦,如果能在windbg里动态执行某个对象的方法就好了,比如ToString()方法

  • 相关阅读:
    201671010113 201620172 《JAVA程序设计》第三周
    201671010113 201620172 《JAVA程序设计》浅入JAVA
    201671010113 201620172 《JAVA程序设计》第四周
    C++中的四种类型转换符
    《统计学习方法》 梯度下降的两种应用场景
    【转载】推荐系统算法总结
    剑指offer面试题1
    SQL清空数据技巧
    DataGridView绑定List时无法进行添加删除操作的解决方法
    MyEclipse新建web project和navicat110_mysql_en工具
  • 原文地址:https://www.cnblogs.com/onlytiancai/p/1102020.html
Copyright © 2011-2022 走看看