阅读文章

蛙蛙推荐:windbg里查看DateTime值

[日期:2008-03-13] 来源:  作者: [字体: ]

     我们都知道在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()方法
  
    


阅读:
录入:blue1000

评论 】 【 推荐 】 【 打印
上一篇:C#异步编程
下一篇:Asp.net Mvc Framework 七 (Filter及其执行顺序) 应用于Acti
相关文章      
本文评论
发表评论


点评: 字数
姓名:

  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款