码迷,mamicode.com
首页 > 数据库 > 详细

Windbg如何设置应用程序的断点

时间:2020-07-07 17:28:56      阅读:69      评论:0      收藏:0      [点我收藏+]

标签:命令行   ring   lis   equal   pre   pmt   nal   for   token   

Windbg用户模式下,非托管代码,可以直接用bp命令设置断点。调试.Net 应用程序相对于非托管程序,要麻烦一些。因为.NET源码在编译的时候,首先是编译成IL文件,程序运行的时候,通过Load加载PE文件,然后JIT编译器负责将IL代码编译为汇编指令,然后执行。JIT编译器编译过后,就可以像非托管应用程序一样进行断点设置了。

断点设置步骤:

1、设置符号路径。

      我们可以在系统环境变量里,增加一个 _NT_SYMBOL_PATH  ,设置为   cache*d:\symbols;srv*http://msdl.microsoft.com/download/symbols  可以将路径更改为自己本地的缓存路径。如果有一把好梯子的话,设置为全局代理模式,在调试的时候,会将.NET的框架PDB文件下载到该缓存目录里,我们在调试的时候就能看到更详细的信息。

  当然,也可以通过命令行来主动获取微软官方调试符号。

      symchk /r C:\Windows\System32\*.dll /s SRV*D:\symbols\*http://msdl.microsoft.com/download/symbols
      symchk C:\WINDOWS\System32\KERNELBASE.dll /s SRV*D:\symbols\*http://msdl.microsoft.com/download/symbols

 

2、加载正确版本CLR以及SOS(Son of Strike)。

     Windbg用户模式下,调试.Net 应用程序,我们需要正确的加载CLR以及SOS(Son of Strike)。需要注意的是,加载的CLR以及SOS版本一定要正确。如果应用程序在X86平台下编译,则需要加载 C:\Windows\Microsoft.NET\Framework\v4.0.30319 目录下的SOS以及CLR,64位下编译的话,需要加载C:\Windows\Microsoft.NET\Framework64\v4.0.30319 目录下的SOS以及CLR。2.0的程序需要加载MSCORWKS。

3、例子

     以一个简单的Demo为例,来看一下如何在Windbg中设置断点。(在4.0FrameWork、X86平台下编译)。这个程序,根据体重身高来计算BMI指数,假定BMI指数为21的为最健康的,对给定的人员列表按照偏差大小的绝对值进行排序。让我们姑且认为偏差越小身体越健康吧。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 
 6 namespace WindbugDemo
 7 {
 8     public class Person
 9     {
10         //认为BMI和21偏差最小的为最健康的
11         private const double BmiHelthConst = 21f;
12 
13         public string Name { get; set; }
14         public int Age { get; set; }
15         public double Height { get; set; }
16         public double Weight { get; set; }
17         public double BmiVariance { get { return GetBmiVariance(); } }
18         //18岁至65岁可以Weight/(Height*Height)计算,否则抛出异常
19         public double GetBmiVariance()
20         {
21             if (Age > 65 || Age < 18)
22                 throw new Exception("18岁以下65岁以上人群不适用此计算方法");
23             double bmi = Math.Round(Weight / Math.Pow(Height, 2),2);
24             double variance = Math.Abs(bmi - BmiHelthConst);
25             return variance;
26         }
27     }
28 
29     public class HelthCompare : IComparer<Person>
30     {
31         public int Compare(Person x, Person y)
32         {
33 
34             double diffx = x.BmiVariance;
35             double diffy = y.BmiVariance;
36             if (diffx == diffy)
37                 return 0;
38             if (diffx > diffy)
39                 return 1;
40             return -1;
41         }
42     }
43 
44     class Health
45     {
46         [STAThread]
47         static void Main(string[] args)
48         {
49             Person person1 = new Person { Name = "James", Age = 35, Height = 1.70, Weight = 70 };
50             Person person2 = new Person { Name = "Tony", Age = 25, Height = 1.65, Weight = 60 };
51             Person person3 = new Person { Name = "John", Age = 30, Height = 1.75, Weight = 90 };
52             Person[] array = new Person[] { person1, person2, person3 };
53             List<Person> list = new List<Person>();
54             list.AddRange(array);
55             HelthCompare comparer = new HelthCompare();
56             list.Sort(comparer);
57             foreach(var item in list)
58             {
59                 string text = string.Format("Name:{0}  Age:{1}  Height:{2}  Weight:{3}  BMI Variance:{4}",
60                                     item.Name,item.Age, item.Height, item.Weight, item.BmiVariance);
61                 System.Console.WriteLine(text);
62             }
63             Console.ReadKey();
64             /*
65             Name:Tony  Age:25  Height:1.65  Weight:60  BMI Variance:1.04
66             Name:James  Age:35  Height:1.7  Weight:70  BMI Variance:3.22
67             Name:John  Age:30  Height:1.75  Weight:90  BMI Variance:8.39
68              */
69         }
70     }
71 
72 }

3.1 打开Windbg,在File==》Open Executable...打开编译后的程序。指定PDB路径以及源码路径。

0:000> .sympath+ d:\source
Symbol search path is: cache*d:\symbols;srv*http://msdl.microsoft.com/download/symbols;d:\source
Expanded Symbol search path is: cache*d:\symbols;srv*http://msdl.microsoft.com/download/symbols;d:\source
Source search path is: d:\source
0:000> .reload
Reloading current modules
.....

3.2 可以使用 sxe ld:clrjit 命令,这个命令发生在clrjit加载的时候,在进入Main方法之前,这对于我们设置自己程序的断点很方便。然后输入g命令,当加载clrjit的时候,就可以命中断点了。

0:000> sxe ld:clrjit
0:000> g
(cc8.cd0): Unknown exception - code 04242420 (first chance)
ModLoad: 6d110000 6d18d000   C:\Windows\Microsoft.NET\Framework\v4.0.30319\clrjit.dll
eax=00000000 ebx=00000000 ecx=001437a4 edx=00000001 esi=7ffdf000 edi=0027e340
eip=76df70b4 esp=0027e258 ebp=0027e2ac iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!KiFastSystemCallRet:
76df70b4 c3              ret
0:000> .load C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos.dll
0:000> .load C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
0:000> .loadby sos clr  (等同于上面两条命令)

3.3 加载完SOS后,就可以用扩展命令来设置断点了。

0:000> !name2ee Health!WindbugDemo.Health
Module:      00142edc
Assembly:    Health.exe
Token:       02000004
MethodTable: 001437b8
EEClass:     00141304
Name:        WindbugDemo.Health
0:000> !dumpmt -md 001437b8
EEClass:         00141304
Module:          00142edc
Name:            WindbugDemo.Health
mdToken:         02000004
File:            D:\bin\Health.exe
BaseSize:        0xc
ComponentSize:   0x0
Slots in VTable: 6
Number of IFaces in IFaceMap: 0
--------------------------------------
MethodDesc Table
   Entry MethodDe    JIT Name
6647952c 6619612c PreJIT System.Object.ToString()
6648ec30 66196134 PreJIT System.Object.Equals(System.Object)
6648e860 66196154 PreJIT System.Object.GetHashCode()
6648e2a0 66196168 PreJIT System.Object.Finalize()
0014c015 001437b0   NONE WindbugDemo.Health..ctor()
0014c011 001437a4   NONE WindbugDemo.Health.Main(System.String[])
0:000> !dumpmt -md 001437b8
EEClass:         00141304
Module:          00142edc
Name:            WindbugDemo.Health
mdToken:         02000004
File:            D:\bin\Health.exe
BaseSize:        0xc
ComponentSize:   0x0
Slots in VTable: 6
Number of IFaces in IFaceMap: 0
--------------------------------------
MethodDesc Table
   Entry MethodDe    JIT Name
6647952c 6619612c PreJIT System.Object.ToString()
6648ec30 66196134 PreJIT System.Object.Equals(System.Object)
6648e860 66196154 PreJIT System.Object.GetHashCode()
6648e2a0 66196168 PreJIT System.Object.Finalize()
0014c015 001437b0   NONE WindbugDemo.Health..ctor()
0014c011 001437a4   NONE WindbugDemo.Health.Main(System.String[])
0:000> !bpmd -md 001437a4   
MethodDesc = 001437a4
Adding pending breakpoints...

 在上面的Windbg调试窗口里,JIT为NONE的就表示还没有进行JIT编译。这种情况下,我们不能使用bp命令来设置断点的。我们可以使用bpmd命令加md参数来设置断点。输入g命令程序继续执行。

0:000> !u 001437a4    
Normal JIT generated code
WindbugDemo.Health.Main(System.String[])
Begin 011f0050, size 5cc

d:\source\02Health\Health.cs @ 48:
011f0050 55              push    ebp
011f0051 8bec            mov     ebp,esp

... ...

d:\source\02Health\Health.cs @ 56:
011f0377 8b8d68ffffff    mov     ecx,dword ptr [ebp-98h]
011f037d 8b9564ffffff    mov     edx,dword ptr [ebp-9Ch]
011f0383 3909            cmp     dword ptr [ecx],ecx
011f0385 e822022b65      call    mscorlib_ni+0x3105ac (664a05ac) (System.Collections.Generic.List`1[[System.__Canon, mscorlib]].Sort(System.Collections.Generic.IComparer`1<System.__Canon>), mdToken: 06002283)
011f038a 90              nop

... ...

0:000> bp 011f0377 

0:000> g

3.4 对于已经JIT编译的方法,我们可以采用u命令,查看反汇编,然后就可以在对应的行号用非托管应用程序的bp命令来设置断点了。

以上两种方法可以在Windbg下设置断点。查找方法表还可以根据domain信息查找Module信息

0:000> !dumpdomain
--------------------------------------
System Domain:      67840f60
LowFrequencyHeap:   67841284
HighFrequencyHeap:  678412cc
StubHeap:           67841314
Stage:              OPEN
Name:               None
--------------------------------------
Shared Domain:      67840c08
LowFrequencyHeap:   67841284
HighFrequencyHeap:  678412cc
StubHeap:           67841314
Stage:              OPEN
Name:               None
Assembly:           003b24f0 [C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll]
ClassLoader:        003b25b8
  Module Name
66191000    C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll

--------------------------------------
Domain 1:           00364d50
LowFrequencyHeap:   003651a4
HighFrequencyHeap:  003651ec
StubHeap:           00365234
Stage:              OPEN
SecurityDescriptor: 00366920
Name:               Health.exe
Assembly:           003b24f0 [C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll]
ClassLoader:        003b25b8
SecurityDescriptor: 003af690
  Module Name
66191000    C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll

Assembly:           003bfbd8 [D:\bin\Health.exe]
ClassLoader:        003bfca0
SecurityDescriptor: 003bf880
  Module Name
00142edc    D:\bin\Health.exe

0:000> !dumpmodule -mt 00142edc    
Name:       D:\bin\Health.exe
Attributes: PEFile 
Assembly:   003bfbd8
LoaderHeap:              00000000
TypeDefToMethodTableMap: 00140038
TypeRefToMethodTableMap: 0014004c
MethodDefToDescMap:      0014009c
FieldDefToDescMap:       001400dc
MemberRefToDescMap:      00000000
FileReferencesMap:       001400f8
AssemblyReferencesMap:   001400fc
MetaData start address:  0123237c (2360 bytes)

Types defined in this module

      MT  TypeDef Name
------------------------------------------------------------------------------
001437b8 0x02000004 WindbugDemo.Health

Types referenced in this module

      MT    TypeRef Name
------------------------------------------------------------------------------
665941b8 0x02000001 System.Object
0:000> !dumpmt -md 001437b8
EEClass:         00141304
Module:          00142edc
Name:            WindbugDemo.Health
mdToken:         02000004
File:            D:\bin\Health.exe
BaseSize:        0xc
ComponentSize:   0x0
Slots in VTable: 6
Number of IFaces in IFaceMap: 0
--------------------------------------
MethodDesc Table
   Entry MethodDe    JIT Name
6647952c 6619612c PreJIT System.Object.ToString()
6648ec30 66196134 PreJIT System.Object.Equals(System.Object)
6648e860 66196154 PreJIT System.Object.GetHashCode()
6648e2a0 66196168 PreJIT System.Object.Finalize()
0014c015 001437b0   NONE WindbugDemo.Health..ctor()
0014c011 001437a4   NONE WindbugDemo.Health.Main(System.String[])

3.5 也可以通过JIT编译的代码地址来设置断点。

0:000> !name2ee  Health!WindbugDemo.HelthCompare
Module:      00142edc
Assembly:    Health.exe
Token:       02000003
MethodTable: 00143d6c
EEClass:     0014144c
Name:        WindbugDemo.HelthCompare
0:000> !dumpmt -md 00143d6c
EEClass:         0014144c
Module:          00142edc
Name:            WindbugDemo.HelthCompare
mdToken:         02000003
File:            D:\bin\Health.exe
BaseSize:        0xc
ComponentSize:   0x0
Slots in VTable: 6
Number of IFaces in IFaceMap: 1
--------------------------------------
MethodDesc Table
   Entry MethodDe    JIT Name
6647952c 6619612c PreJIT System.Object.ToString()
6648ec30 66196134 PreJIT System.Object.Equals(System.Object)
6648e860 66196154 PreJIT System.Object.GetHashCode()
6648e2a0 66196168 PreJIT System.Object.Finalize()
011f07b8 00143d5c    JIT WindbugDemo.HelthCompare.Compare(WindbugDemo.Person, WindbugDemo.Person)
011f0780 00143d64    JIT WindbugDemo.HelthCompare..ctor()
0:000> !dumpmd 00143d5c    
Method Name:  WindbugDemo.HelthCompare.Compare(WindbugDemo.Person, WindbugDemo.Person)
Class:        0014144c
MethodTable:  00143d6c
mdToken:      0600000c
Module:       00142edc
IsJitted:     yes
CodeAddr:     011f07b8
Transparency: Safe critical
0:000> bp 011f07b8

 

Windbg如何设置应用程序的断点

标签:命令行   ring   lis   equal   pre   pmt   nal   for   token   

原文地址:https://www.cnblogs.com/hzwanglw/p/13261171.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!