首页 > 开发 > 综合 > 正文

调试SQLSERVER (三)使用Windbg调试SQLSERVER的一些命令

2024-07-21 02:48:11
字体:
来源:转载
供稿:网友
调试SQLSERVER (三)使用Windbg调试SQLSERVER的一些命令调试SQLSERVER (三)使用Windbg调试SQLSERVER的一些命令

调试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 // 分离调试.restart // 重启并调试.kill // 强制结束当前调试q // 结束被调试进程,关闭命令行界面,返回到最初的工作空间

附加成功了,我们看到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命令,我们可以对这个线程设置上下文或查看

要设置上下文,可以使用命令~36s,s说明提取线程~36并设置我们的上下文(s)

当我们身处另外一个线程的上下文的时候,如果我们只是需要查看一下这个36线程的stack trace,我们可以使用命令:~36k

现在我们设置我们的上下文并获取我们的stack trace

使用命令:

~36s

然后输入命令 :k

注意:设置符号路径的时候,在符号文件夹下面一定要有sqlservr.pdb文件夹,否则当输入k命令的时候,会得不到函数名

下面是没有设置正确的符号路径和设置正确的符号路径的对比

设置正确,能看到实际的函数名

设置不正确,看不到实际的函数名

大家可以对比一下~36s命令和k 命令

先用~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号线程的栈情况

** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:/Windows/SYSTEM32/ntdll.dll - 0:010> ~10s*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:/Windows/system32/KERNELBASE.dll - ntdll!NtWaitForSingleObject+0xa:00000000`774412fa c3              ret0:010> kChild-SP          RetAddr           Call Site00000000`079deb98 000007fe`fd2110dc ntdll!NtWaitForSingleObject+0xa00000000`079deba0 00000000`00d83b55 KERNELBASE!WaitForSingleObjectEx+0x9c00000000`079dec40 00000000`00d834ca sqlservr!SOS_Scheduler::SwitchContext+0x26d00000000`079df0d0 00000000`00d82710 sqlservr!SOS_Scheduler::SuspendNonPreemptive+0xca00000000`079df110 00000000`00d829bc sqlservr!SOS_Scheduler::Suspend+0x2d00000000`079df140 00000000`00da2eab sqlservr!EventInternal<Spinlock<154,1,0> >::Wait+0x1a800000000`079df190 00000000`01949951 sqlservr!CTraceManagementTask::Invoke+0xbe00000000`079df1f0 00000000`00d8eb40 sqlservr!CTraceBatchTask::Task+0x1ad00000000`079df2d0 00000000`00d8f15a sqlservr!SOS_Task::Param::Execute+0x12a00000000`079df3e0 00000000`00d8ef9f sqlservr!SOS_Scheduler::RunTask+0x9600000000`079df440 00000000`0135e8ee sqlservr!SOS_Scheduler::ProcessTasks+0x12800000000`079df4b0 00000000`0135eb25 sqlservr!SchedulerManager::WorkerEntryPoint+0x2d200000000`079df590 00000000`00ea7631 sqlservr!SystemThread::RunWorker+0xcc00000000`079df5d0 00000000`0135f67a sqlservr!SystemThreadDispatcher::ProcessWorker+0x2db*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:/Windows/WinSxS/amd64_microsoft.vc80.crt_1fc8b3b9a1e18e3b_8.0.50727.4940_none_88df89932faf0bf6/MSVCR80.dll - 00000000`079df680 00000000`74c437d7 sqlservr!SchedulerManager::ThreadEntryPoint+0x17300000000`079df720 00000000`74c43894 MSVCR80!endthreadex+0x47*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:/Windows/system32/kernel32.dll - 00000000`079df750 00000000`771e59ed MSVCR80!endthreadex+0x10400000000`079df780 00000000`7741c541 kernel32!BaseThreadInitThunk+0xd00000000`079df7b0 00000000`00000000 ntdll!RtlUserThreadStart+0x21
0:010> dc 00000000`079df4b000000000`079df4b0  00000000 00000000 804aa1a0 00000000  ..........J.....00000000`079df4c0  fff914a8 000007ff 00000000 00000000  ................00000000`079df4d0  8fe8cfb8 00002dec 00000000 00000000  .....-..........00000000`079df4e0  032af070 00000000 00000000 00000000  p.*.............00000000`079df4f0  08d80080 00000000 00000000 00000000  ................00000000`079df500  00000001 00000000 fff914a8 000007ff  ................00000000`079df510  00000006 00000000 fffffffe ffffffff  ................00000000`079df520  fff914a8 000007ff fff9155c 000007ff  ......../.......0:010> dc00000000`079df530  804aa1a0 00000000 fff90000 000007ff  ..J.............00000000`079df540  271516fd 00000000 fffffffe ffffffff  ...'............00000000`079df550  00000003 00000000 fd210000 000007fe  ..........!.....00000000`079df560  8fe8ce78 00002dec 00000000 00000000  x....-
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表