집 >데이터 베이스 >MySQL 튜토리얼 >调试SQLSERVER (三)使用Windbg调试SQLSERVER的一些命令
调试SQLSERVER (三)使用Windbg调试SQLSERVER的一些命令 调试SQLSERVER (一)生成dump文件的方法 调试SQLSERVER (二)使用Windbg调试SQLSERVER的环境设置 windbg命令分为 标准命令、 元命令、 扩展命令 标准命令提供最基本的调试功能,不区分大小写。如:
调试SQLSERVER (一)生成dump文件的方法
调试SQLSERVER (二)使用Windbg调试SQLSERVER的环境设置
windbg命令分为标准命令、元命令、扩展命令
标准命令提供最基本的调试功能,不区分大小写。如:bp g dt dv k等
元命令提供标准命令没有提供的功能,也内建在调试引擎中,以.开头。如.sympath .reload等
扩展命令用于扩展某一方面的调试功能,实现在动态加载的扩展模块中,以!开头。如!analyze等
下面我们会直接将debugger 附加到sqlservr.exe 进程
在附加sqlservr之前,我们需要获得SQLSERVER的PID,在第一篇的时候我们就说过如何获取SQLSERVER的PID,我们这里就不再叙述了
GO OVER 回顾:调试SQLSERVER (一)生成dump文件的方法
注意:附加debugger 到sqlserver进程会停止SQLSERVER的运行,不要在生产环境上乱试!!
在调试的时候你可以在命令框里输入一些命令
首先,一个 stack trace很明显是对应一个线程的,SQLSERVER是一个多线程应用程序,要获得sqlserver的线程列表,使用命令:~
使用Windbg版本:6.12.0002.633 AMD64
SQL版本:SQL2008R2
操作系统:WIN2008R2
我们附加SQL进程
SQL进程ID是6192
如果要退出,记得输入q命令,而不要直接关闭窗口,要分离调试而不关闭命令行界面,输入.detach命令
.detach <span>//</span><span> 分离调试 .restart </span><span>//</span><span> 重启并调试 .</span><span>kill</span> <span>//</span><span> 强制结束当前调试 q </span><span>//</span> 结束被调试进程,关闭命令行界面,返回到最初的工作空间
附加成功了,我们看到Windbg会加载一些必要的模块
然后,我们输入 ~ 命令看一下当前SQL进程的线程列表
进程环境块(Process Enviroment Block)Peb
线程环境块(Thread Enviroment Block)Teb
Peb和Teb都是Windows的内核结构体,对于我们来说可以不用深入研究,毕竟我们不是专业的
当然有些可以查看Peb和Teb的命令在本文也不会进行介绍
在调试期间,是没有办法连接SQLSERVER的,连接的时候会报错
并且,如果你当前正在执行SQL语句,也会hang住
再说一次:附加debugger 到sqlserver进程会停止SQLSERVER的运行,不要在生产环境上乱试!!
从上图中可以看到我们有47个线程 ,线程从0开始计数。
在左边边缘的句点指明当前正在上下文中(in context)运行的线程,在提示框中(0:046>)也指明了当前上下文的线程的序数是46
第一列的数字只是给调试器使用的数字序数列
接下来那一列才是进程:线程列,调试器以hex的形式来显示(pid.tid),比如上面的46 Id: 1830.18a8 Suspend:1
1830的十进制是6192,18a8的十进制是6312
那么 Id: 1830.18a8就表示进程id是6192:线程id是6312
tid:thread id
我们假设有一个查询正在运行在线程36上面(9e4),我想看一下这个线程的stack trace。
我们可以发出相关命令来查看stack trace,命令是k,k命令可以附带有多个参数,
例如:
提供函数参数 输入 kv
提供frame 号码 输入 kn
提供内存使用 输入 kf
我们现在只关注k命令,我们可以对这个线程设置上下文或查看
要设置上下文,可以使用命令 <span>~</span>36s ,s说明提取线程~36并设置我们的上下文(s)
当我们身处另外一个线程的上下文的时候,如果我们只是需要查看一下这个36线程的 stack trace,我们可以使用命令: ~36k
现在我们设置我们的上下文并获取我们的stack trace
使用命令:
<span>~</span>36s
然后输入命令 : k
注意:设置符号路径的时候,在符号文件夹下面一定要有sqlservr.pdb文件夹,否则当输入k命令的时候,会得不到函数名
下面是没有设置正确的符号路径和设置正确的符号路径的对比
设置正确,能看到实际的函数名
设置不正确,看不到实际的函数名
大家可以对比一下 <span>~</span>36s 命令和 k 命令
先用 <span>~</span>36s 命令切换到36线程的上下文,并显示出当前36线程所执行的函数
然后用 k 命令进一步显示36线程的上下文内容,调用层次
比如我们输入 kf 查看一下各个函数的内存使用也是可以的,显示内存的单位是byte
输入 kn 加上frame号码
好了,回到刚才那里,我们现在在36线程的上下文里,最顶端的函数是“ntdll!NtSignalAndWaitForSingleObject” ,也是正在执行和最后执行的函数
这里其实是一个Windows API将我们的线程带入等待状态--等待线程需要的东西准备好的一个信号。
这里的Child-SP(Stack Pointer)和RetAddr(Return Address) ,他们是用于明确栈帧的构造和用于当前函数完成的时候返回执行结果
当我们需要知道当前sqlserver版本的时候,我们可以使用命令 lm
当然,这个命令也是有很多附带参数的,我们使用下面命令获得sqlservr模块的具体信息
lmvm sqlservr
有时候,lm命令对于微软的技术支持来说是很重要的,因为从这个命令的运行结果可以知道客户使用的操作系统版本,SQLSERVER版本
SQLSERVER是32位还是64位,是SQL2008还是SQL2008R2
如果输入 lm 命令, 就可以得到SQLSERVER地址空间里所加载的模块列表
deferred:表示延迟加载
如果要验证调试器所加载的目标,我们可以使用管道命令: |
内存命令
我们有时候可能还想把进程的内存内容dump出来,那么我们可以使用 d命令,d命令也一样有很多的附带参数,
例如
dc:把提供的地址处内存转换为ASCII字符数据
dd:只显示 4字节DWORD格式
内存命令一般用于分析堆空间的内存,或者栈内存里所传递的参数数据
我们看一下10号线程的栈情况
<span>**</span> ERROR: Symbol <span>file</span> could <span>not</span> be found. Defaulted <span>to</span> export symbols <span>for</span> C:\Windows\SYSTEM32\ntdll.dll <span>-</span> <span>0</span>:<span>010</span><span>></span> <span>~</span><span>10s </span><span>***</span> ERROR: Symbol <span>file</span> could <span>not</span> be found. Defaulted <span>to</span> export symbols <span>for</span> C:\Windows\system32\KERNELBASE.dll <span>-</span><span> ntdll!NtWaitForSingleObject</span><span>+</span><span>0xa</span><span>: </span><span>00000000</span><span>`774412fa c3 ret </span><span>0</span>:<span>010</span><span>></span><span> k Child</span><span>-</span><span>SP RetAddr Call Site </span><span>00000000</span>`079deb98 000007fe`fd2110dc ntdll!NtWaitForSingleObject<span>+</span><span>0xa</span> <span>00000000</span>`079deba0 <span>00000000</span>`00d83b55 KERNELBASE!WaitForSingleObjectEx<span>+</span><span>0x9c</span> <span>00000000</span>`079dec40 <span>00000000</span>`00d834ca sqlservr!SOS_Scheduler::SwitchContext<span>+</span><span>0x26d</span> <span>00000000</span>`079df0d0 <span>00000000</span>`00d82710 sqlservr!SOS_Scheduler::SuspendNonPreemptive<span>+</span><span>0xca</span> <span>00000000</span>`079df110 <span>00000000</span>`00d829bc sqlservr!SOS_Scheduler::Suspend<span>+</span><span>0x2d</span> <span>00000000</span>`079df140 <span>00000000</span>`00da2eab sqlservr!EventInternal<span>Spinlock<span><span>154</span>,<span>1</span>,<span>0</span><span>></span> <span>></span>::Wait<span>+</span><span>0x1a8</span> <span>00000000</span>`079df190 <span>00000000</span>`<span>01949951</span> sqlservr!CTraceManagementTask::Invoke<span>+</span><span>0xbe</span> <span>00000000</span>`079df1f0 <span>00000000</span>`00d8eb40 sqlservr!CTraceBatchTask::Task<span>+</span><span>0x1ad</span> <span>00000000</span>`079df2d0 <span>00000000</span>`00d8f15a sqlservr!SOS_Task::Param::<span>Execute</span><span>+</span><span>0x12a</span> <span>00000000</span>`079df3e0 <span>00000000</span>`00d8ef9f sqlservr!SOS_Scheduler::RunTask<span>+</span><span>0x96</span> <span>00000000</span>`079df440 <span>00000000</span>`0135e8ee sqlservr!SOS_Scheduler::ProcessTasks<span>+</span><span>0x128</span> <span>00000000</span>`079df4b0 <span>00000000</span>`0135eb25 sqlservr!SchedulerManager::WorkerEntryPoint<span>+</span><span>0x2d2</span> <span>00000000</span>`079df590 <span>00000000</span>`00ea7631 sqlservr!SystemThread::RunWorker<span>+</span><span>0xcc</span> <span>00000000</span>`079df5d0 <span>00000000</span>`0135f67a sqlservr!SystemThreadDispatcher::ProcessWorker<span>+</span><span>0x2db</span> <span>***</span> ERROR: Symbol <span>file</span> could <span>not</span> be found. Defaulted <span>to</span> export symbols <span>for</span> C:\Windows\WinSxS\amd64_microsoft.vc80.crt_1fc8b3b9a1e18e3b_8.<span>0.50727</span>.4940_none_88df89932faf0bf6\MSVCR80.dll <span>-</span> <span>00000000</span>`079df680 <span>00000000</span>`74c437d7 sqlservr!SchedulerManager::ThreadEntryPoint<span>+</span><span>0x173</span> <span>00000000</span>`079df720 <span>00000000</span>`74c43894 MSVCR80!endthreadex<span>+</span><span>0x47</span> <span>***</span> ERROR: Symbol <span>file</span> could <span>not</span> be found. Defaulted <span>to</span> export symbols <span>for</span> C:\Windows\system32\kernel32.dll <span>-</span> <span>00000000</span>`079df750 <span>00000000</span>`771e59ed MSVCR80!endthreadex<span>+</span><span>0x104</span> <span>00000000</span>`079df780 <span>00000000</span>`7741c541 kernel32!BaseThreadInitThunk<span>+</span><span>0xd</span> <span>00000000</span>`079df7b0 <span>00000000</span>`<span>00000000</span> ntdll!RtlUserThreadStart<span>+</span><span>0x21</span></span></span>
<span>0</span>:<span>010</span><span>></span> dc <span>00000000</span><span>`079df4b0 </span><span>00000000</span>`079df4b0 <span>00000000</span> <span>00000000</span> 804aa1a0 <span>00000000</span><span> ..........J..... </span><span>00000000</span>`079df4c0 fff914a8 000007ff <span>00000000</span> <span>00000000</span><span> ................ </span><span>00000000</span>`079df4d0 8fe8cfb8 00002<span>dec</span> <span>00000000</span> <span>00000000</span> .....<span>-</span><span>.......... </span><span>00000000</span>`079df4e0 032af070 <span>00000000</span> <span>00000000</span> <span>00000000</span> p.<span>*</span><span>............. </span><span>00000000</span>`079df4f0 08d80080 <span>00000000</span> <span>00000000</span> <span>00000000</span><span> ................ </span><span>00000000</span>`079df500 <span>00000001</span> <span>00000000</span><span> fff914a8 000007ff ................ </span><span>00000000</span>`079df510 <span>00000006</span> <span>00000000</span><span> fffffffe ffffffff ................ </span><span>00000000</span><span>`079df520 fff914a8 000007ff fff9155c 000007ff ........\....... </span><span>0</span>:<span>010</span><span>></span><span> dc </span><span>00000000</span>`079df530 804aa1a0 <span>00000000</span><span> fff90000 000007ff ..J............. </span><span>00000000</span>`079df540 271516fd <span>00000000</span> fffffffe ffffffff ...<span>'</span><span>............ 00000000`079df550 00000003 00000000 fd210000 000007fe ..........!..... 00000000`079df560 8fe8ce78 00002dec 00000000 00000000 x....-.......... 00000000`079df570 804aa1a0 00000000 fff914a8 000007ff ..J............. 00000000`079df580 00000000 00000000 0135eb25 00000000 ........%.5..... 00000000`079df590 804aa1a0 00000000 ab0c671e 00000d5f ..J......g.._... 00000000`079df5a0 ab0c6720 00000d5f ab0c6723 00000d5f g.._...#g.._...</span>
我们首先切到10号线程 (~10s),然后显示stack (k)。最后我们取出其中一个栈(在stack trace里面的一行),
然后利用Child-SP来dump 出来内存地址,Child-SP在stack-trace里面是一个栈帧的指针---指向栈帧在内存中的起始地址
目前我们只是介绍了在调试里面的一些普通的命令
我们会接着介绍下面命令
<span>vertarget .chain !analyze x r u bp, bl, bc</span>
vertarget命令
查看目标系统的版本信息,可使用下面的vertarget命令,vertarget命令给出在目标机器上的OS版本或者机器运行时间
<span>0</span>:<span>010</span><span>></span><span> vertarget Windows </span><span>7</span> Version <span>7601</span> (Service Pack <span>1</span>) MP (<span>2</span><span> procs) Free x64 Product: Server, suite: TerminalServer DataCenter SingleUserTS kernel32.dll version: </span><span>6.1</span>.<span>7601.18409</span> (win7sp1_gdr.<span>140303</span><span>-</span><span>2144</span><span>) Machine Name: Debug session time: Fri </span><span>Dec</span> <span>26</span> <span>12</span>:<span>04</span>:<span>42.159</span> <span>2014</span> (UTC <span>+</span> <span>8</span>:<span>00</span><span>) System Uptime: </span><span>17</span> days <span>2</span>:<span>05</span>:<span>00.191</span><span> Process Uptime: </span><span>0</span> days <span>1</span>:<span>37</span>:<span>28.844</span><span> Kernel time: </span><span>0</span> days <span>0</span>:<span>00</span>:<span>00.109</span> <span>User</span> time: <span>0</span> days <span>0</span>:<span>00</span>:<span>00.437</span>
.chain命令
能够给出一个扩展命令集的链表,大家看到.chain是有.开头,所以他是元命令
<span>0</span>:<span>010</span><span>></span><span> .chain Extension DLL search Path: C:\Program Files\Debugging Tools </span><span>for</span> Windows (x64)\WINXP;C:\Program Files\Debugging Tools <span>for</span> Windows (x64)\winext;C:\Program Files\Debugging Tools <span>for</span> Windows (x64)\winext\arcade;C:\Program Files\Debugging Tools <span>for</span> Windows (x64)\pri;C:\Program Files\Debugging Tools <span>for</span> Windows (x64);C:\Program Files\Debugging Tools <span>for</span> Windows (x64)\winext\arcade;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.<span>0</span>\;C:\Program Files (x86)\Microsoft SQL Server\<span>100</span>\Tools\Binn\;C:\Program Files\Microsoft SQL Server\<span>100</span>\Tools\Binn\;C:\Program Files\Microsoft SQL Server\<span>100</span>\DTS\Binn\;C:\Program Files (x86)\Microsoft SQL Server\<span>100</span>\Tools\Binn\VSShell\Common7\IDE\;C:\Program Files (x86)\Microsoft Visual Studio <span>9.0</span>\Common7\IDE\PrivateAssemblies\;C:\Program Files (x86)\Microsoft SQL Server\<span>100</span>\DTS\Binn\;C:\Program Files (x86)\Microsoft ASP.NET\ASP.NET Web Pages\v1.<span>0</span><span>\;C:\Program Files\Microsoft Windows Performance Toolkit\ Extension DLL chain: dbghelp: </span><span>image</span> <span>6.12</span>.<span>0002.633</span>, API <span>6.1</span>.<span>6</span>, built Tue Feb <span>02</span> <span>04</span>:<span>15</span>:<span>44</span> <span>2010</span> <span>[</span><span>path: C:\Program Files\Debugging Tools for Windows (x64)\dbghelp.dll</span><span>]</span><span> ext: </span><span>image</span> <span>6.12</span>.<span>0002.633</span>, API <span>1.0</span>.<span>0</span>, built Tue Feb <span>02</span> <span>04</span>:<span>15</span>:<span>46</span> <span>2010</span> <span>[</span><span>path: C:\Program Files\Debugging Tools for Windows (x64)\winext\ext.dll</span><span>]</span><span> exts: </span><span>image</span> <span>6.12</span>.<span>0002.633</span>, API <span>1.0</span>.<span>0</span>, built Tue Feb <span>02</span> <span>04</span>:<span>15</span>:<span>38</span> <span>2010</span> <span>[</span><span>path: C:\Program Files\Debugging Tools for Windows (x64)\WINXP\exts.dll</span><span>]</span><span> uext: </span><span>image</span> <span>6.12</span>.<span>0002.633</span>, API <span>1.0</span>.<span>0</span>, built Tue Feb <span>02</span> <span>04</span>:<span>15</span>:<span>36</span> <span>2010</span> <span>[</span><span>path: C:\Program Files\Debugging Tools for Windows (x64)\winext\uext.dll</span><span>]</span><span> ntsdexts: </span><span>image</span> <span>6.1</span>.<span>7650.0</span>, API <span>1.0</span>.<span>0</span>, built Tue Feb <span>02</span> <span>04</span>:<span>15</span>:<span>18</span> <span>2010</span> <span>[</span><span>path: C:\Program Files\Debugging Tools for Windows (x64)\WINXP\ntsdexts.dll</span><span>]</span>
最上面两行显示了扩展模块的搜索路径。
接下来共列出了5个Windbg自带的扩展模块:dbghellp、ext、exts、uext和ntsdexts。可以查看到这些扩展模块的版本信息、镜像文件路径。
!analyze -v
详细显示当前异常信息,!analyze是一个扩展命令,
此命令分析当前最近的异常事件(如果在进行dump分析,则是bug check),并显示分析结果
参数
-v:显示异常的详细信息,这个选项在调试错误的时候最有用。
-f:f是force的缩写。强制将任何事件都当作异常来分析,即使仅仅是普通的断点事件。将因此多输出一些内容。
-hang:在内核环境中,它分析内核锁和DPC栈;在用户环境中,它分析线程的调用栈,调试器只会对当前线程进行分析,所以一定要将线程环境切换到最可能引起问题的那个线程中去才有帮助。
<span>0</span>:<span>010</span><span>></span> !analyze <span>-</span><span>v </span><span>*******************************************************************************</span> <span>*</span> <span>*</span> <span>*</span> Exception Analysis <span>*</span> <span>*</span> <span>*</span> <span>*******************************************************************************</span> <span>*****</span> OS symbols are WRONG. Please fix symbols <span>to</span><span> do analysis. </span><span>*************************************************************************</span> <span>***</span> <span>***</span> <span>***</span> <span>***</span> <span>***</span> Your debugger <span>is</span> <span>not</span> using the correct symbols <span>***</span> <span>***</span> <span>***</span> <span>***</span> <span>In</span> <span>order</span> <span>for</span> this command <span>to</span> <span>work</span> properly, your symbol path <span>***</span> <span>***</span> must point <span>to</span> .pdb files that have <span>full</span> type information. <span>***</span> <span>***</span> <span>***</span> <span>***</span> Certain .pdb files (such <span>as</span> the <span>public</span> OS symbols) do <span>not</span> <span>***</span> <span>***</span> contain the required information. Contact the <span>group</span> that <span>***</span> <span>***</span> provided you <span>with</span> these symbols <span>if</span> you need this command <span>to</span> <span>***</span> <span>***</span> <span>work</span>. <span>***</span> <span>***</span> <span>***</span> <span>***</span> Type referenced: ntdll!_PEB <span>***</span> <span>***</span> <span>***</span> <span>*************************************************************************</span> <span>*************************************************************************</span> <span>***</span> <span>***</span> <span>***</span> <span>***</span> <span>***</span> Your debugger <span>is</span> <span>not</span> using the correct symbols <span>***</span> <span>***</span> <span>***</span> <span>***</span> <span>In</span> <span>order</span> <span>for</span> this command <span>to</span> <span>work</span> properly, your symbol path <span>***</span> <span>***</span> must point <span>to</span> .pdb files that have <span>full</span> type information. <span>***</span> <span>***</span> <span>***</span> <span>***</span> Certain .pdb files (such <span>as</span> the <span>public</span> OS symbols) do <span>not</span> <span>***</span> <span>***</span> contain the required information. Contact the <span>group</span> that <span>***</span> <span>***</span> provided you <span>with</span> these symbols <span>if</span> you need this command <span>to</span> <span>***</span> <span>***</span> <span>work</span>. <span>***</span> <span>***</span> <span>***</span> <span>***</span> Type referenced: nt!IMAGE_NT_HEADERS32 <span>***</span> <span>***</span> <span>***</span> <span>*************************************************************************</span> <span>***</span> ERROR: Symbol <span>file</span> could <span>not</span> be found. Defaulted <span>to</span> export symbols <span>for</span> C:\Windows\SYSTEM32\sechost.dll <span>-</span> <span>***</span> ERROR: Symbol <span>file</span> could <span>not</span> be found. Defaulted <span>to</span> export symbols <span>for</span> C:\Windows\system32\ole32.dll <span>-</span> <span>***</span> ERROR: Symbol <span>file</span> could <span>not</span> be found. Defaulted <span>to</span> export symbols <span>for</span> C:\Windows\system32\RPCRT4.dll <span>-</span> <span>***</span> ERROR: Module <span>load</span> completed but symbols could <span>not</span> be loaded <span>for</span> C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\Binn\Resources\<span>1033</span><span>\sqlevn70.rll </span><span>***</span> ERROR: Symbol <span>file</span> could <span>not</span> be found. Defaulted <span>to</span> export symbols <span>for</span> C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\Binn\xpstar.dll <span>-</span><span> GetPageUrlData failed, server returned HTTP status </span><span>404</span><span> URL requested: http:</span><span>//</span>watson.microsoft.com<span>/</span>StageOne<span>/</span>sqlservr_exe<span>/</span>2009_100_4319_<span>0</span><span>/</span>53a133d9<span>/</span>ntdll_dll<span>/</span>6_1_7601_<span>18247</span><span>/</span>521eaf24<span>/</span><span>80000003</span><span>/</span><span>00050590</span>.htm?Retriage<span>=</span><span>1</span><span> FAULTING_IP: ntdll!DbgBreakPoint</span><span>+</span><span>0</span> <span>00000000</span>`<span>77440590</span> cc <span>int</span> <span>3</span><span> EXCEPTION_RECORD: ffffffffffffffff </span><span>--</span><span> (.exr 0xffffffffffffffff)</span> ExceptionAddress: <span>0000000077440590</span><span> (ntdll!DbgBreakPoint) ExceptionCode: </span><span>80000003</span> (<span>Break</span><span> instruction exception) ExceptionFlags: </span><span>00000000</span><span> NumberParameters: </span><span>1</span><span> Parameter</span><span>[</span><span>0</span><span>]</span>: <span>0000000000000000</span><span> FAULTING_THREAD: </span><span>0000000000000444</span><span> DEFAULT_BUCKET_ID: WRONG_SYMBOLS PROCESS_NAME: sqlservr.exe ADDITIONAL_DEBUG_TEXT: </span><span>Use</span> <span>'</span><span>!findthebuild</span><span>'</span> command <span>to</span> search <span>for</span><span> the target build information. </span><span>If</span> the build information <span>is</span> available, run <span>'</span><span>!findthebuild -s ; .reload</span><span>'</span> <span>to</span> <span>set</span> symbol path <span>and</span> <span>load</span><span> symbols. MODULE_NAME: ntdll FAULTING_MODULE: 00000000773f0000 ntdll DEBUG_FLR_IMAGE_TIMESTAMP: 521eaf24 ERROR_CODE: (NTSTATUS) </span><span>0x80000003</span> <span>-</span><span> { EXCEPTION_CODE: (NTSTATUS) </span><span>0x80000003</span> (<span>2147483651</span>) <span>-</span><span> { EXCEPTION_PARAMETER1: </span><span>0000000000000000</span><span> MOD_LIST: </span><span>ANALYSIS<span>/></span><span> PRIMARY_PROBLEM_CLASS: WRONG_SYMBOLS BUGCHECK_STR: APPLICATION_FAULT_WRONG_SYMBOLS LAST_CONTROL_TRANSFER: </span><span>from</span> 00000000774e7f48 <span>to</span> <span>0000000077440590</span><span> STACK_TEXT: </span><span>00000000</span>`0e7ff838 <span>00000000</span>`774e7f48 : <span>00000000</span>`<span>00000000</span> <span>00000000</span>`<span>00000000</span> <span>00000000</span>`<span>00000000</span> <span>00000000</span>`<span>00000000</span><span> : ntdll!DbgBreakPoint </span><span>00000000</span>`0e7ff840 <span>00000000</span>`771e59ed : <span>00000000</span>`<span>00000000</span> <span>00000000</span>`<span>00000000</span> <span>00000000</span>`<span>00000000</span> <span>00000000</span>`<span>00000000</span> : ntdll!DbgUiRemoteBreakin<span>+</span><span>0x38</span> <span>00000000</span>`0e7ff870 <span>00000000</span>`7741c541 : <span>00000000</span>`<span>00000000</span> <span>00000000</span>`<span>00000000</span> <span>00000000</span>`<span>00000000</span> <span>00000000</span>`<span>00000000</span> : kernel32!BaseThreadInitThunk<span>+</span><span>0xd</span> <span>00000000</span>`0e7ff8a0 <span>00000000</span>`<span>00000000</span> : <span>00000000</span>`<span>00000000</span> <span>00000000</span>`<span>00000000</span> <span>00000000</span>`<span>00000000</span> <span>00000000</span>`<span>00000000</span> : ntdll!RtlUserThreadStart<span>+</span><span>0x21</span><span> FOLLOWUP_IP: ntdll!DbgBreakPoint</span><span>+</span><span>0</span> <span>00000000</span>`<span>77440590</span> cc <span>int</span> <span>3</span><span> SYMBOL_STACK_INDEX: </span><span>0</span><span> SYMBOL_NAME: ntdll!DbgBreakPoint</span><span>+</span><span>0</span><span> FOLLOWUP_NAME: MachineOwner IMAGE_NAME: ntdll.dll STACK_COMMAND: </span><span>~</span><span>41s ; kb BUCKET_ID: WRONG_SYMBOLS FAILURE_BUCKET_ID: WRONG_SYMBOLS_80000003_ntdll.dll!DbgBreakPoint WATSON_STAGEONE_URL: http:</span><span>//</span>watson.microsoft.com<span>/</span>StageOne<span>/</span>sqlservr_exe<span>/</span>2009_100_4319_<span>0</span><span>/</span>53a133d9<span>/</span>ntdll_dll<span>/</span>6_1_7601_<span>18247</span><span>/</span>521eaf24<span>/</span><span>80000003</span><span>/</span><span>00050590</span>.htm?Retriage<span>=</span><span>1</span><span> Followup: MachineOwner </span><span>--</span><span>-------</span></span>View Code
符号搜索
命令“x”被用来进行符号的全局搜索,你可以把它直接就理解为search
如果什么参数都没有的话,它将列出当前调试环境下的所有局部变量,前提是要在有局部变量存在的情况下
x <span>[</span><span>参数</span><span>]</span> <span>[</span><span>模块!符号</span><span>]</span>
<span>0</span>:<span>010</span><span>></span> x sqlservr!SOS_Scheduler::Run<span>*</span> <span>00000000</span>`00290f10 sqlservr!SOS_Scheduler::RunTask <span>=</span> <span>no type information<span>></span></span>
在SQL Server module (sqlservr)模块里面搜索所有符号里面包含SOS Scheduler (一个类)的符号
r命令
查看寄存器信息
r //当前线程寄存器信息
~* r // 所有线程寄存器信息
<span>0</span>:<span>010</span><span>></span><span> r rax</span><span>=</span>0000000002e520d8 rbx<span>=</span><span>0000000000000000</span> rcx<span>=</span><span>0000000003f0dac8 rdx</span><span>=</span>00000000000001e0 rsi<span>=</span>0000000000000fa0 rdi<span>=</span><span>000000000000041c rip</span><span>=</span>00000000774412fa rsp<span>=</span>00000000079deb98 rbp<span>=</span><span>00000000804aa1a0 r8</span><span>=</span>00000000000001e0 r9<span>=</span><span>0000000000000000</span> r10<span>=</span><span>0000000000000064</span><span> r11</span><span>=</span>00000000079df190 r12<span>=</span>00000000079debc8 r13<span>=</span><span>0000000000000000</span><span> r14</span><span>=</span><span>0000000000000000</span> r15<span>=</span><span>0000000008d808f8 iopl</span><span>=</span><span>0</span><span> nv up ei ng nz na po cy cs</span><span>=</span><span>0033</span> ss<span>=</span>002b ds<span>=</span>002b es<span>=</span>002b fs<span>=</span><span>0053</span> gs<span>=</span>002b efl<span>=</span><span>00000285</span><span> ntdll!NtWaitForSingleObject</span><span>+</span><span>0xa</span><span>: </span><span>00000000</span>`774412fa c3 ret
CPU上会有一些寄存器,它们是CPU内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和运算结果的
看一下上面的rax寄存器是一个多用途寄存器一般用来保存返回的值和操作的结果。
“rax”是64位寄存器,而对应32位平台,他的名字叫 “eax”。另外由于是64位CPU所以寄存器的大小也是64位
每一个数字代表4位或 半个字节,因此在寄存器里面存储的数值两个数字代表一个字节,下面rax寄存器里面存储的数就是代表一个64位数( 16 x 4 = 64 bits)
rax=0000000002e520d8
还有一些特别的寄存器,例如rip 和rsp 寄存器
rip寄存器保存了当前的指令指针,他指向下一个要执行的指令
rip寄存器包含一个指向当前栈位置的指针,我们可以使用中括号([])获取寄存器的实际地址并且里面用汇编代码显示出来
<span>0</span>:<span>010</span><span>></span> u <span>[</span><span>rip</span><span>]</span><span> ntdll!NtWaitForSingleObject</span><span>+</span><span>0xa</span><span>: </span><span>00000000</span><span>`774412fa c3 ret </span><span>00000000</span>`774412fb 0f1f440000 nop dword ptr <span>[</span><span>rax+rax</span><span>]</span><span> ntdll!NtCallbackReturn: </span><span>00000000</span>`<span>77441300</span><span> 4c8bd1 mov r10,rcx </span><span>00000000</span>`<span>77441303</span> b802000000 mov eax,<span>2</span> <span>00000000</span>`<span>77441308</span><span> 0f05 syscall </span><span>00000000</span><span>`7744130a c3 ret </span><span>00000000</span>`7744130b 0f1f440000 nop dword ptr <span>[</span><span>rax+rax</span><span>]</span><span> ntdll!NtReadFile: </span><span>00000000</span>`<span>77441310</span> 4c8bd1 mov r10,rcx
我们看到rip里面指向ntdll!NtWaitForSingleObject,这个函数位于在文章前面线程10的stack trace 的最顶层
u 命令
显示指定的内存中的程序代码的反汇编,如果要反汇编某一个地址,直接用u 命令加地址
如果存在符号文件,也可以这样直接加函数名:
u user32!SendMessagew
当你进行live debug的时候,你可能想在sqlserver运行的时候下断点,你可以使用符号名或函数起初地址初设置断点
然后你可以使用条件断点当某个条件成立的时候触发中断
例子
<span>0</span>:<span>010</span><span>></span> bp sqlservr<span>!<span>function</span> <span>or</span> method call<span>></span></span>
bp命令
<span>bp: 命令bp是BreakPoint的缩写。其指令格式如下: bp</span><span>[</span><span>ID</span><span>]</span> <span>[</span><span>Options</span><span>]</span> <span>[</span><span>Address [Passes</span><span>]</span>] <span>[</span><span>"CommandString"</span><span>]</span><span> 参数Address表示需设置断点的地址,缺省情况下使用当前指令指针(EIP)的地址。ID是断点号,一般不手动设置,由调试器内部编号。Passes是一个整数值,即第几次经过断点所在代码时,调试器才需要中断执行,默认为1,即每次都中断。CommandString用来设置一组命令,当断点发生的时候,就执行这一组命令,比如可以把它设置为“k”,这样断点处就会输出当前的调用栈。</span>
断点相关命令
<span>bl:列出所有断点 bd:禁止断点,d代表Disable。如bd </span><span>1</span><span>,禁止断点1。断点被禁止后将不起作用,但亦未删除。 be:恢复断点,e代表Enable。恢复被禁止的断点。如be 1恢复1号断点。 bc:清除断点,如:bc </span><span>1</span>,清除断点1;bc <span>*</span><span>,清除全部断点。 br:序号管理,r代表ReNumber,即重新排序。如:br </span><span>2</span> <span>0</span>,将2号断点重设为0号断点。
比如,我想在sqlservr!SOS_Scheduler::RunTask 这个符号上下断点
首先用x命令列出跟sqlservr!SOS_Scheduler::R*相关的符号名,以保证名字没有错误
<span>0</span>:<span>010</span><span>></span> x sqlservr!SOS_Scheduler::R<span>*</span> <span>00000000</span>`0179c6b0 sqlservr!SOS_Scheduler::RemoveFromCompletedTasks <span>=</span> <span>no type information<span>></span> <span>00000000</span>`0329e200 sqlservr!SOS_Scheduler::RemoveFromPendingQueue <span>=</span> <span>no type information<span>></span> <span>00000000</span>`013458c4 sqlservr!SOS_Scheduler::ResumeBulkInternal <span>=</span> <span>no type information<span>></span> <span>00000000</span>`00d8f0cc sqlservr!SOS_Scheduler::RunTask <span>=</span> <span>no type information<span>></span> <span>00000000</span>`032a4a68 sqlservr!SOS_Scheduler::RetrieveTask <span>=</span> <span>no type information<span>></span> <span>00000000</span>`00d85448 sqlservr!SOS_Scheduler::ResumeBulk <span>=</span> <span>no type information<span>></span> <span>00000000</span>`01345a90 sqlservr!SOS_Scheduler::RunnableQueueInsertBulk <span>=</span> <span>no type information<span>></span> <span>00000000</span>`01344c90 sqlservr!SOS_Scheduler::RemoveFromAbortedQueue <span>=</span> <span>no type information<span>></span> <span>00000000</span>`00d834f8 sqlservr!SOS_Scheduler::Resume <span>=</span> <span>no type information<span>></span> <span>00000000</span>`00d835c4 sqlservr!SOS_Scheduler::RunnableQueueInsert <span>=</span> <span>no type information<span>></span></span></span></span></span></span></span></span></span></span></span>
下断点
<span>0</span>:<span>010</span><span>></span> bp sqlservr!SOS_Scheduler::RunTask
列出所有断点
<span>0</span>:<span>010</span><span>></span><span> bl </span><span>0</span> e <span>00000000</span>`00d8f0cc <span>0001</span> (<span>0001</span>) <span>0</span>:<span>****</span> sqlservr!SOS_Scheduler::RunTask
清除第一个断点
<span>0</span>:<span>010</span><span>></span> bc <span>1</span>
检查断点是否清除了
<span>0</span>:<span>010</span><span>></span> bl
最后说一下获取帮助的命令
? // 打印出所有标准命令
<span>0</span>:<span>010</span><span>></span><span> ? </span><span>Open</span> debugger.chm <span>for</span><span> complete debugger documentation B</span><span>[</span><span>C|D|E</span><span>][</span><span><bps></bps></span><span>]</span> <span>-</span> clear<span>/</span>disable<span>/</span><span>enable breakpoint(s) BL </span><span>-</span><span> list breakpoints BA </span><span>access<span>></span> <span>size<span>></span> <span>addr<span>></span> <span>-</span> <span>set</span><span> processor breakpoint BP </span><span>address<span>></span> <span>-</span> <span>set</span><span> soft breakpoint D</span><span>[</span><span>type</span><span>][</span><span><range></range></span><span>]</span> <span>-</span> <span>dump</span><span> memory DT </span><span>[</span><span>-n|y</span><span>]</span> <span>[</span><span>[mod!</span><span>]</span>name] <span>[</span><span>[-n|y</span><span>]</span><span>fields] </span><span>[</span><span>address</span><span>]</span> <span>[</span><span>-l list</span><span>]</span> <span>[</span><span>-a[</span><span>]</span><span>|</span>c<span>|</span>i<span>|</span>o<span>|</span>r<span>[</span><span>#</span><span>]</span><span>|</span>v] <span>-</span> <span>dump</span><span> using type information DV </span><span>[</span><span><name></name></span><span>]</span> <span>-</span> <span>dump</span><span> local variables E</span><span>[</span><span>type</span><span>]</span> <span>address<span>></span> <span>[</span><span><values></values></span><span>]</span> <span>-</span> enter memory <span>values</span><span> G</span><span>[</span><span>H|N</span><span>]</span> <span>[</span><span>=<address> [<address>...</address> </address></span><span>]</span>] <span>-</span> <span>go</span><span> K </span><span><span>count</span><span>></span> <span>-</span><span> stacktrace KP </span><span><span>count</span><span>></span> <span>-</span> stacktrace <span>with</span><span> source arguments LM</span><span>[</span><span>k|l|u|v</span><span>]</span> <span>-</span><span> list modules LN </span><span>expr<span>></span> <span>-</span><span> list nearest symbols P </span><span>[</span><span>=<addr></addr></span><span>]</span> <span>[</span><span><value></value></span><span>]</span> <span>-</span> step <span>over</span><span> Q </span><span>-</span><span> quit R </span><span>[</span><span>[<reg> [= <expr></expr></reg></span><span>]</span>]] <span>-</span> <span>view</span> <span>or</span> <span>set</span><span> registers S</span><span>[</span><span><opts></opts></span><span>]</span> <span>range<span>></span> <span><span>values</span><span>></span> <span>-</span><span> search memory SX </span><span>[</span><span>{e|d|i|n} [-c "Cmd1"</span><span>]</span> <span>[</span><span>-c2 "Cmd2"</span><span>]</span> <span>[</span><span>-h</span><span>]</span> {Exception<span>|</span>Event<span>|*</span>}] <span>-</span><span> event filter T </span><span>[</span><span>=<address></address></span><span>]</span> <span>[</span><span><expr></expr></span><span>]</span> <span>-</span> trace <span>into</span><span> U </span><span>[</span><span><range></range></span><span>]</span> <span>-</span><span> unassemble version </span><span>-</span> show debuggee <span>and</span><span> debugger version X </span><span>[</span><span>!</span><span>]</span><span>symbol<span>></span> <span>-</span> <span>view</span><span> symbols ? </span><span>expr<span>></span> <span>-</span><span> display expression ?? </span><span>expr<span>></span> <span>-</span> display C<span>++</span><span> expression $</span><span> <span>filename<span>></span> <span>-</span> take input <span>from</span> a command <span>file</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>
.help // 打印出所有元命令
.hh // 打开windbg的chm帮助文件 弹出帮助文件
windbg<span>></span> .hh
command /? // 打印命令command具体参数用法
当然Windbg还有非常复杂的玩法,调试SQLSERVER也是很复杂,不是一般初学者可以驾驭
参考文章:
windbg调试命令
Windbg调试命令详解
windbg调试命令1(k、u、x)
如有不对的地方,欢迎大家拍砖o(∩_∩)o