如何手工抓取windbg分析dump文件件及分析

百度技术 的BLOG
用户名:百度技术
文章数:403
评论数:153
访问量:1156464
注册日期:
阅读量:5863
阅读量:12276
阅读量:397323
阅读量:1087768
51CTO推荐博文
Core,又称之为Core Dump文件,是Unix/Linux操作系统的一种机制,对于线上服务而言,Core令人闻之色变,因为出Core的过程意味着服务暂时不能正常响应,需要恢复,并且随着吐Core进程的内存空间越大,此过程可能持续很长一段时间(例如当进程占用60G+以上内存时,完整Core文件需要15分钟才能完全写到磁盘上),这期间产生的流量损失,不可估量。
凡事皆有两面性,OS在出Core的同时,虽然会终止掉当前进程,但是也会保留下第一手的现场数据,OS仿佛是一架被按下快门的相机,而照片就是产出的Core文件。里面含有当进程被终止时内存、CPU寄存器等信息,可以供后续开发人员进行调试。
关于Core产生的原因很多,比如过去一些Unix的版本不支持现代Linux上这种GDB直接附着到进程上进行调试的机制,需要先向进程发送终止信号,然后用工具阅读core文件。在Linux上,我们就可以使用kill向一个指定的进程发送信号或者使用gcore命令来使其主动出Core并退出。如果从浅层次的原因上来讲,出Core意味着当前进程存在BUG,需要程序员修复。从深层次的原因上讲,是当前进程触犯了某些OS层级的保护机制,逼迫OS向当前进程发送诸如SIGSEGV(即signal 11)之类的信号, 例如访问空指针或数组越界出Core,实际上是触犯了OS的内存管理,访问了非当前进程的内存空间,OS需要通过出Core来进行警示,这就好像一个人身体内存在病毒,免疫系统就会通过发热来警示,并导致人体发烧是一个道理(有意思的是,并不是每次数组越界都会出Core,这和OS的内存管理中虚拟页面分配大小和边界有关,即使不出Core,也很有可能读到脏数据,引起后续程序行为紊乱,这是一种很难追查的BUG)。
说了这些,似乎感觉Core很强势,让人感觉缺乏控制力,其实不然。控制Core产生的行为和方式,有两个途径:
1.修改/proc/sys/kernel/core_pattern文件,此文件用于控制Core文件产生的文件名,默认情况下,此文件内容只有一行内容:&core&,此文件支持定制,一般使用%配合不同的字符,这里罗列几种:
%p& 出Core进程的PID
%u& 出Core进程的UID
%s& 造成Core的signal号
%t& 出Core的时间,从0:00:00开始的秒数
%e& 出Core进程对应的可执行文件名
2.Ulimit &C命令,此命令可以显示当前OS对于Core文件大小的限制,如果为0,则表示不允许产生Core文件。如果想进行修改,可以使用:
Ulimit &cn
其中n为数字,表示允许Core文件体积的最大值,单位为Kb,如果想设为无限大,可以执行:
Ulimit -cunlimited
产生了Core文件之后,就是如何查看Core文件,并确定问题所在,进行修复。为此,我们不妨先来看看Core文件的格式,多了解一些Core文件。
首先可以明确一点,Core文件的格式ELF格式,这一点可以通过使用readelf -h命令来证实,如下图:
从读出来的ELF头信息可以看到,此文件类型为Core文件,那么readelf是如何得知的呢?可以从下面的数据结构中窥得一二:
其中当值为4的时候,表示当前文件为Core文件。如此,整个过程就很清楚了。
了解了这些之后,我们来看看如何阅读Core文件,并从中追查BUG。在Linux下,一般读取Core的命令为:
gdb exec_file core_file
使用GDB,先从可执行文件中读取符号表信息,然后读取Core文件。如果不与可执行文件搅合在一起可以吗?答案是不行,因为Core文件中没有符号表信息,无法进行调试,可以使用如下命令来验证:
Objdump &x core_file | tail
我们看到如下两行信息:
SYMBOL TABLE:
no symbols
表明当前的ELF格式文件中没有符号表信息。
为了解释如何看Core中信息,我们来举一个简单的例子:
#include &stdio.h&
int main(){
int stack_of[];
这段程序使用gcc &g a.c &o a进行编译,运行后直接会Core掉,使用gdb a core_file查看栈信息,可见其Core在了这行代码:
int stack_of[];
原因很明显,直接在栈上申请如此大的数组,导致栈空间溢出,触犯了OS对于栈空间大小的限制,所以出Core(这里是否出Core还和OS对栈空间的大小配置有关,一般为8M)。但是这里要明确一点,真正出Core的代码不是分配栈空间的int stack_of[], 而是后面这句int b=1, 为何?出Core的一种原因是因为对内存的非法访问,在上面的代码中分配数组stack_of时并未访问它,但是在其后声明变量并赋值,就相当于进行了越界访问,继而出Core。为了解释得更详细些,让我们使用gdb来看一下出Core的地方,使用命令gdb a core_file可见:
可知程序出现了段错误&Segmentation fault&, 代码是int b=1这句。我们来查看一下当前的栈信息:
其中可见指令指针rip指向地址为0&400473, 我们来看下当前的指令是什么:
这条movl指令要把立即数1送到0xffffffffe8287bfc(%rbp)这个地址去,其中rbp存储的是帧指针,而0xffffffffe8287bfc很明显是一个负数,结果计算为-。这就可以解释了:其中我们申请的int stack_of[]占用字节,b是int类型,占用4个字节,且栈空间是由高地址向低地址延伸,那么b的栈地址就是0xffffffffe8287bfc(%rbp),也就是$rbp-。当我们尝试访问此地址时:
可以看到无法访问此内存地址,这是因为它已经超过了OS允许的范围。
下面我们把程序进行改进:
#include &stdio.h&
int main(){
int* stack_of = malloc(sizeof(int)*);
使用gcc &O3 &g a.c &o a进行编译,运行后会再次Core掉,使用gdb查看栈信息,请见下图:
可见BUG出在第7行,也就是*a=b这句,这时我们尝试打印b的值,却发现符号表中找不到b的信息。为何?原因在于gcc使用了-O3参数,此参数可以对程序进行优化,一个负面效应是优化过程中会舍弃部分局部变量,导致调试时出现困难。在我们的代码中,b声明时即赋值,随后用于为*a赋值。优化后,此变量不再需要,直接为*a赋值为1即可,如果汇编级代码上讲,此优化可以减少一条MOV语句,节省一个寄存器。
此时我们的调试信息已经出现了一些扭曲,为此我们重新编译源程序,去掉-O3参数(这就解释了为何一些大型软件都会有debug版本存在,因为debug是未经优化的版本,包含了完整的符号表信息,易于调试),并重新运行,得到新的core并查看,如下图:
这次就比较明显了,b中的值没有问题,有问题的是a,其指向的地址是非法区域,也就是a没有分配内存导致的Core。当然,本例中的问题其实非常明显,几乎一眼就能看出来,但不妨碍它成为一个例子,用来解释在看Core过程中,需要注意的一些问题。
【本文首发于:
【本文出自 “” 博客,谢绝转载!
了这篇文章
类别:┆阅读(0)┆评论(0)4133人阅读
声明:转载自
在生产环境下进行故障诊断时,为了不终止正在运行的服务或应用程序,有两种方式可以对正在运行的服务或应用程序的进程进行分析和调试。
首先一种比较直观简洁的方式就是用WinDbg等调试器直接attach到需要调试的进程,调试完毕之后再detach即可。但是这种方式有个缺点就是执
行debugger命令时必须先break这个进程,执行完debug命令之后又得赶紧F5让他继续运行,因为被你break住的时候意味着整个进程也已
经被你挂起。另外也经常会由于First Chance
Excetpion而自动break,你得时刻留意避免长时间break整个进程。所以这样的调试方式对时间是个很大的考验,往往没有充裕的时间来做仔细
另一种方式则是在出现问题的时候,比如CPU持续长时间100%,内存突然暴涨等非正常情况下,通过对服务进程snapshot抓取一个dump文件,完成dump之后先deatch,让进程继续运行。然后用windbg等工具来分析这个抓取到的dump文件。
那么如何在不终止进程的情况下抓取dump文件呢?Debugging Tools for Windows里提供了一个非常好的工具,adplus.vbs。从名字可以看出,实际上是一个vb脚本,只是对cdb调试器作的一个包装脚本。
其路径与Debugging Tools for Windows的安装路径相同,使用的方法也很简单,如下所示:
adplus.vbs -hang -p 1234 -o d:/dump
其中-hang指明使用hang模式,亦即在进程运行过程中附加上去snapshot抓取一个dump文件,完成之后detach。与之对应的是
-crash崩溃模式,用户先启动adplus,然后由它启动要监控的程序,在出现异常崩溃时自动生成dump文件,或者通过Ctrl-C人为发出抓取指
令。但是-crash模式在抓取完成之后,被监控的进程就必须终止。因此我们在这里只选用-hang模式。
-p是要调试的进程ID,比如ASP.NET应用线程池,在Win2003下就是w3wp.exe
-o 指定要output的dump文件路径。
另外,与adplus类似的,有个UserDump工具,但是抓取用户模式的进程,而adplus则是内核模式和用户模式两者皆可。
而总所周至的Dr. Waston,则会在进程崩溃之后的自动时候抓取dump文件,一样可以用于windbg等调试器来事后分析程序崩溃时的状态。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:15654次
排名:千里之外
转载:12篇
(1)(1)(1)(4)(6)下次自动登录
现在的位置:
& 综合 & 正文
使用Adplus抓取Dump小结
Adplus抓取Dump有三种方式:
一种是Hang模式
adplus -hang -pn Prs.exe -o c:/dump -quit /2/当进程进程运行时生成dump
二是Crash模式
adplus -crash -pn w3wp.exe -NoDumpOnFirst //同上,不对 first chance exceptions生成dump
三 使用配置文件
以给adplus指定配置文件,在某个特定的条件下生成dump file,并把dump file存在特定目录下
adplus -c myconfig.cfg -pn w3wp.exe
myconfig.cfg
&Settings&
&RunMode&crash&/RunMode&
&/Settings&
&PreCommands&
&Cmd& !load clr10/sos&/Cmd&
&/PreCommands&
&Exceptions&
&Option& NoDumpOnFirstChance &/Option&
&Option& NoDumpOnSecondChance &/Option&
&!-- This is for the CLR exception --&
&Code& clr &/Code&
&Actions1& Log &/Actions1&
&CustomActions1& !clr10/sos.cce System.Exception 1; j ($t1 = 1) '.dump /ma /u c:/dumps/exceptiondump.gn' ; 'gn' &/CustomActions1&
&ReturnAction1& GN &/ReturnAction1&
&Actions2& Void &/Actions2&
&ReturnAction2& GN &/ReturnAction2&
&/Exceptions&&/ADPlus&
参考文档:
Adplus参数设置
进程运行时,随时可以使用-hang参数得到一个Dump文件, 而不需要考虑线程是否真的处于死锁中,用于诊断高内存使用率, 高CPU使用率。
在hang模式下,dump file是以非侵入方式被抓取的, 并没有中断线程, 因此不需要跟启动进程有相同的身份,在客户端调试服务器时,hang模式抓取dump file很有用。
在进程异常终止时抓取dump file.
进程异常终止有3种情况:
1.unhandled的exception
2.asp.net进程由于iis reset或recycle而终止.
3.出现heap毁坏,栈溢出,内存不足等错误,进程必须退出
指定要分析的进程名。使用多个“-pn process name”开关来指定多个进程。
dump file的存储路径,缺省为adplus所在路径
-FullOnFirst
create full dumps on first chance exceptions
-MiniOnSecond
-NoDumpOnFirst
如果exception被try-catch block处理,使用这个参数就不会生成dump file
-NoDumpOnSecond
No dialog boxes will be displayed
其他方法:
服务启动自动附加调试的方法:
在注册表:HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows NT/CurrentVersion/Image File Execution Options
指向 新建 ,然后单击 键 。 在注册表编辑器在左窗格,会注意到 新项 # 1 (新的注册表子项的名称) 中选择进行编辑。
键入 ImageName 替换 新项 # 1 ,然后按 Enter 键。请注意 ImageName 是进程的承载您要调试的服务的映像名称占位符。 是例如如果您要调试由具有 MyService.exe 作为图像名称的进程承载的服务,键入 MyService.exe 。
用鼠标右键单击在步骤 e 中创建注册表子项。
指向 新建 ,然后单击 字符串值 。 在注册表编辑器在右窗格,会注意到 新值 # 1 ,一个新的注册表项的名称选择进行编辑。
使用 debugger,替换 新值 # 1 ,,然后按 ENTER 键。
右键单击您在步骤 h, 调试 注册表项,然后单击 修改 。 编辑字符串 对话框。
在该 数值数据 文字框键入 DebuggerPath,然后单击 确定 。请注意 DebuggerPath 是调试器的完整路径,您要使用的占位符。 是例如如果您要使用 WinDbg 调试器调试服务,您可以键入类似于以下的完整路径:
C:/Progra~1/Debugg~1/windbg.exe
二 在程序崩溃时候自动抓取Dump
在注册表位置
KEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows NT/CurrentVersion/AeDebug
将Auto设置为1 将Debugger设置为需要的Debugger值
下面是华生医生抓取dump设置
DRWTSN32 -p %ld -e %ld -g
下面是adplus抓取Dump设置:
"C:/Program Files/Debugging Tools for Windows (x86)/adlups.vbs" -pn notepad.exe -o -c d:/dump - quit -sc 1%
下面是用vistudio调试设置
KEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows NT/CurrentVersion/AeDebug
的Debugger设置为: "C:/Windows/system32/vsjitdebugger.exe" -p %ld -e %ld
当进程出现异常后自动抓取dump的方法:
C:/Program Files/Debugging Tools for Windows (x86)/windbg.exe -p %ld -e %ld -c ".dump /mfh d:/q"
&&&&推荐文章:
【上篇】【下篇】使用DEBUGDIAG手动抓取DUMP文件 - You are really something! - 51Testing软件测试网 51Testing软件测试网-中国软件测试人的精神家园
使用DEBUGDIAG手动抓取DUMP文件
& 14:35:09
/ 个人分类:
DebugDiagdumplIIS dumpldumpldumpldump手动抓取IIS dump文件DebugDiag 1.1 (x86)Processesw3wpCreate Full Userdumpdumpdump查看dump文件的默认存储位置DebugDiag 1.1 (x86)&&&&&&&&&&&&&&&&&&miscdump&&&&&&修改dump文件的存储位置DebugDiag 1.1 (x86)Tools-&Options and SettingsManual Userdump Save Folder&抓取dump文件的时机dumpIISPrvite#time in GCdumpgen2large object heapbytes in all heapsdumpdump

我要回帖

更多关于 java dump文件分析 的文章

 

随机推荐