在软件开发过程中,测试和调试是保证软件质量的重要环节。本文将介绍在没有源代码的情况下,如何使用Windbg和SOS工具来获取函数的输入参数。
在开发过程中,经常会遇到各种问题。拥有源代码可以更容易地检测和修复这些问题,但在QA(质量保证)和生产环境中,情况并非总是如此。作为质量保证工程师,工作不仅仅是发现问题,更重要的是隔离问题,以便为开发人员提供尽可能多的信息。在QA中,需要一个与用户相似的环境,有时无法使用源代码进行问题隔离。
本文将展示一个简单的案例:“如何在运行时获取一个类中简单函数的输入参数”,而不需要源代码。将使用一个包含在可执行文件中的非常简单的函数。主要工具将是Windows调试工具和SOS用于.NET调试。假设没有从开发中获得良好的日志级别。
本文稍长,但同样适用于ASP.NET进程或Windows进程。如果需要帮助,请通过电子邮件联系,将乐意提供帮助。
首先,需要安装并下载Windows调试工具。请访问以下链接下载:
安装完成后,从以下路径复制.NET辅助调试文件:
%WINDIR%\Microsoft.NET\Framework\v2.X.XXXXX\SOS.dll
到:
%PROGRAMFILES%\Debugging Tools for Windows (x86)
使用Windbg启动进程(文件->打开可执行文件):
此时,可执行文件尚未启动,Windbg的命令提示符将打开。
加载库SOS.DLL以加载.NET调试助手:
.load sos
按F5运行可执行文件。
请注意,Sample.exe程序正在调试器下运行。
要冻结Sample.exe进程,只需点击调试器并按CTRL+BREAK。
要探索可执行文件的主线程和堆栈跟踪,将使用以下命令:
~*e !clrstack
正在显示所有线程及其堆栈(注意使用的是!clrstack,它包含在SOS.DLL文件中)。
现在想要获取封装类ConsoleApplication12.Program的方法。有很多方法可以做到这一点。让探索这个方法:
!ip2md
:IP指令指针转换为方法描述,给定一个IP(EIP)地址,希望将其转换为方法描述,这是CLR .NET的内部结构,可以给提供方法名称和IL代码:
!dumpmt命令允许获取方法表,而-MD参数给提供了方法表中每个方法的方法描述。
如果决定在这里设置一个断点?在Windbg(Windows调试器)中,可以使用bp(断点)命令,但可以观察到NumberOfWords方法尚未Jitted(该方法尚未运行,没有它们的确切入口点),但SOS允许使用方法描述设置断点:
!bpmd –md 0097c011
可以继续运行应用程序并使用这个(按F5):
在小程序中按ENTER。
请注意,如果按ENTER,程序会冻结。发生了什么?回到Windbg:
!clrstack
SOS助手有一个有趣的命令(!do DumpObject),让使用这个。给定一个对象地址的指针,它为打印对象:
!do
对打印字符串本身感兴趣:让探索这个对象的内存。
点击Windbg视图->内存/虚拟:写入014e9b90(包含对象的内存地址:
.printf "%mu", 0x014e9b90+c
字符串对象地址在每次执行进程时都可能改变,该怎么办?输入地址的对象地址存储在堆栈中,以及一些处理器寄存器中:
r
bp eip ".printf "\n%mu",ecx+c;gc"