Linux Debugging(五): coredump 分析入门

时间:2022-09-24 22:47:11

作为工作几年的老程序猿,肯定会遇到coredump,log severity设置的比较高,导致可用的log无法分析问题所在。 更悲剧的是,这个问题不好复现!所以现在你手头唯一的线索就是这个程序的尸体:coredump。你不得不通过它,来寻找问题根源。

通过上几篇文章,我们知道了函数参数是如何传递的,和函数调用时栈是如何变化的;当然了还有AT&T的汇编基础,这些,已经可以使我们具备了一定的调试基础。其实,很多调试还是需要经验+感觉的。当然说这句话可能会被打。但是你不得不承认,随着调试的增多,你的很多推断在解决问题时显得很重要,因此,我们需要不断积累经验,来面对各种case。

导致coredump的原因很多,比如死锁,这些还不要操作系统相关的知识,这些问题的分析不在本文的讨论范围之内。大家敬请期待接下来的文章吧!本文从一个非常典型的coredump入手。

请下载本文用到的coredump: Linux Debugging: coredump 分析入门的材料

首先使用gdb a.out core.25992打开这个core

看一下backtrace是什么:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400703 in __do_global_dtors_aux ()
(gdb) bt
Cannot access memory at address 0x303938373635343b

出错的地方很奇怪,而且整个callstack都被破坏了,因此首先看一下寄存器和bp是否正常:

(gdb) i r
rax 0x7fffffffe040 140737488347200
rbx 0x400820 4196384
rcx 0x3332312c21646c72 3689065110378409074
rdx 0x0 0
rsi 0x40091d 4196637
rdi 0x7fffffffe059 140737488347225
rbp 0x3039383736353433 0x3039383736353433
rsp 0x7fffffffe060 0x7fffffffe060
r8 0x30393837363534 13573712489362740
r9 0x7ffff7dc3680 140737351792256
r10 0xffffffffffffffff -1
r11 0x7ffff7389ae0 140737341070048
r12 0x400660 4195936
r13 0x7fffffffe180 140737488347520
r14 0x0 0
r15 0x0 0
rip 0x400703 0x400703 <__do_global_dtors_aux+83>
eflags 0x10202 [ IF RF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
fctrl 0x37f 895
fstat 0x0 0
ftag 0xffff 65535
fiseg 0x0 0
fioff 0x0 0
foseg 0x0 0
fooff 0x0 0
fop 0x0 0
mxcsr 0x1f80 [ IM DM ZM OM UM PM ]
(gdb) x/i $rip
0x400703 <__do_global_dtors_aux+83>: fidivl -0x1e(%rdx)
(gdb) x/20i $rip-10
0x4006f9 <__do_global_dtors_aux+73>: add %cl,-0x75(%rax)
0x4006fc <__do_global_dtors_aux+76>: adc $0x200947,%eax
0x400701 <__do_global_dtors_aux+81>: cmp %rbx,%rdx
0x400704 <__do_global_dtors_aux+84>: jb 0x4006e8 <__do_global_dtors_aux+56>
0x400706 <__do_global_dtors_aux+86>: movb $0x1,0x200933(%rip) # 0x601040 <completed.6159>
0x40070d <__do_global_dtors_aux+93>: add $0x8,%rsp
0x400711 <__do_global_dtors_aux+97>: pop %rbx
0x400712 <__do_global_dtors_aux+98>: leaveq
0x400713 <__do_global_dtors_aux+99>: retq
0x400714 <__do_global_dtors_aux+100>: nopw %cs:0x0(%rax,%rax,1)
0x400720 <frame_dummy>: push %rbp
0x400721 <frame_dummy+1>: cmpq $0x0,0x2006df(%rip) # 0x600e08 <__JCR_LIST__>
0x400729 <frame_dummy+9>: mov %rsp,%rbp
0x40072c <frame_dummy+12>: je 0x400748 <frame_dummy+40>
0x40072e <frame_dummy+14>: mov $0x0,%eax
0x400733 <frame_dummy+19>: test %rax,%rax
0x400736 <frame_dummy+22>: je 0x400748 <frame_dummy+40>
0x400738 <frame_dummy+24>: mov $0x600e08,%edi
0x40073d <frame_dummy+29>: mov %rax,%r11
0x400740 <frame_dummy+32>: leaveq

rbp的值很奇怪,基本确定栈被破坏了(bt不正常,也应该看一下栈是否出问题了)。打印一下栈的内容,看是否栈被写坏了:

(gdb) x/30c $rsp-20
0x7fffffffe04c: 33 '!' 44 ',' 49 '1' 50 '2' 51 '3' 52 '4' 53 '5' 54 '6'
0x7fffffffe054: 55 '7' 56 '8' 57 '9' 48 '0' 0 '\000' 7 '\a' 64 '@' 0 '\000'
0x7fffffffe05c: 0 '\000' 0 '\000' 0 '\000' 0 '\000' 0 '\000' 0 '\000' 0 '\000' 0 '\000'
0x7fffffffe064: 0 '\000' 0 '\000' 0 '\000' 0 '\000' -21 '\353' 5 '\005'

我们看到了特殊的字符!,1234567890。当然实际的生产环境可能不会这么简单,比如笔者曾经遇到过这个字符串是/local/share/tracker_...这种目录的字符串,后来发现拼接路径的时候出现错误导致路径非常长,在路径拷贝的时候出现了写坏栈的情况。

多打印一下栈的内容:

(gdb) x/40c $rsp-40
0x7fffffffe038: -100 '\234' 7 '\a' 64 '@' 0 '\000' 1 '\001' 0 '\000' 0 '\000' 0 '\000'
0x7fffffffe040: 72 'H' 101 'e' 108 'l' 108 'l' 111 'o' 44 ',' 32 ' ' 119 'w'
0x7fffffffe048: 111 'o' 114 'r' 108 'l' 100 'd' 33 '!' 44 ',' 49 '1' 50 '2'
0x7fffffffe050: 51 '3' 52 '4' 53 '5' 54 '6' 55 '7' 56 '8' 57 '9' 48 '0'
0x7fffffffe058: 0 '\000' 7 '\a' 64 '@' 0 '\000' 0 '\000' 0 '\000' 0 '\000' 0 '\000'

可以看出,字符串"Hello, World!,1234567890"这个字符串溢出导致栈被破坏。

我们不应该用rbp打印吗?

还记得在函数返回时,rbp会恢复为上一层调用者的bp吗?因为字符串溢出/越界,导致已经恢复不了原来的bp了。

这个bug很简单。实际上,有的coredump就是这种无心的错误啊。

尊重原创,转载请注明出处: anzhsoft  http://blog.csdn.net/anzhsoft/article/details/18762915

Linux Debugging(五): coredump 分析入门的更多相关文章

  1. 2018-2019-1 20189221《Linux内核原理与分析》第五周作业

    2018-2019-1 20189221<Linux内核原理与分析>第五周作业 实验四 实验过程 当用户态进程调用一个系统调用时,cpu切换到内核态并开始执行一个内核函数. 在Linux中 ...

  2. 2019-2020-1 20199329《Linux内核原理与分析》第五周作业

    <Linux内核原理与分析>第五周作业 一.上周问题总结: 虚拟机将c文件汇编成汇编文件时忘记添加include<stdio.h> gdb跟踪汇编过程不熟练 二.本周学习内容: ...

  3. 20169212《Linux内核原理与分析》课程总结

    20169212<Linux内核原理与分析>课程总结 每周作业链接汇总 第一周作业:完成linux基础入门实验,了解一些基础的命令操作. 第二周作业:学习MOOC课程--计算机是如何工作的 ...

  4. Linux Debugging(三)&colon; C&plus;&plus;函数调用的参数传递方法总结(通过gdb&plus;反汇编)

    上一篇文章<Linux Debugging:使用反汇编理解C++程序函数调用栈>没想到能得到那么多人的喜爱,因为那篇文章是以32位的C++普通函数(非类成员函数)为例子写的,因此只是一个特 ...

  5. Linux内核源码分析方法&lowbar;转

    Linux内核源码分析方法 转自:http://www.cnblogs.com/fanzhidongyzby/archive/2013/03/20/2970624.html 一.内核源码之我见 Lin ...

  6. 《Linux内核原理与分析》教学进程

    目录 2019-2020-1 <Linux内核原理与分析>教学进程 考核方案 第一周: 第二周: 第三周: 第四周: 第五周 第六周 第七周: 第八周 第九周 第十周 第十一周: 第十二周 ...

  7. Linux Kernel Oops异常分析

    1.PowerPC小系统内核异常分析 1.1  异常打印 Unable to handle kernel paging request for data at address 0x36fef31eFa ...

  8. Linux的任务计划--cron入门

    Linux操作系统定时任务系统 Cron 入门 cron是一个linux下的定时执行工具,可以在无需人工干预的情况下运行作业.由于Cron 是Linux的内置服务,但它不自动起来,可以用以下的方法启动 ...

  9. Linux内核源代码情景分析系列

    http://blog.sina.com.cn/s/blog_6b94d5680101vfqv.html Linux内核源代码情景分析---第五章 文件系统  5.1 概述 构成一个操作系统最重要的就 ...

随机推荐

  1. 我的权限系统设计实现MVC4 &plus; WebAPI &plus; EasyUI &plus; Knockout(一)

    一.前言 之前的博客一直都还没写到框架的实现及权限系统,今天开始写我的权限系统,我以前做过的项目基本上都有权限管理这个模块,但各个系统都会有一些不太一样,有些简单点,有些稍微复杂一点,一句话,我们做的 ...

  2. CSS3与页面布局学习笔记(八)——浏览器兼容性问题与前端性能优化方案

    一.浏览器兼容 1.1.概要 世界上没有任何一个浏览器是一样的,同样的代码在不一样的浏览器上运行就存在兼容性问题.不同浏览器其内核亦不尽相同,相同内核的版本不同,相同版本的内核浏览器品牌不一样,各种运 ...

  3. Android 对话框&lpar;Dialog&rpar;大全 建立你自己的对话框

    Android 对话框(Dialog)大全 建立你自己的对话框 原文地址: http://www.cnblogs.com/salam/archive/2010/11/15/1877512.html A ...

  4. 受限玻尔兹曼机(RBM)学习笔记(五)梯度计算公式

      去年 6 月份写的博文<Yusuke Sugomori 的 C 语言 Deep Learning 程序解读>是囫囵吞枣地读完一个关于 DBN 算法的开源代码后的笔记,当时对其中涉及的算 ...

  5. 【转】EXT JS MVC开发模式

    原文链接:EXT JS MVC开发模式 在app(亦即根目录)文件夹下面创建controller.model.store和view文件夹,从名称上就知道他们该放置什么代码了吧.然后创建Applicat ...

  6. &lbrack;Hibernate&rsqb; 注解映射例子

    Hibernate 注解(Hibernate Annotation) 是一种比较新的方式,通过在 java 简单类增加注解,来声明 java 类和数据库表的映射,作用和 xml 文件相似.hibern ...

  7. Jmeter 参数化请求实例

    Jmeter 参数化请求实例 在jmeter中的请求可以参数化,其中参数化的方式有4种: 1.CSV Data Set Config 2.数据库 3.用户自定义变量 4.用jmeter中的函数获取参数 ...

  8. windows 上传文件到 Linux 服务器

    方法一: pscp E:\javaWP\new11111.txt username@130.75.7.156:/home/

  9. C&plus;&plus; 实现 split 操作

    理由:由于 C++ 标准库里面没有字符分割函数 split ,这可太不方便了,我们利用 STL 来实现自己的 split 函数: 原型:vector<string> split(const ...

  10. 作用域&amp&semi;作用域链和with,catch语句&amp&semi;闭包

    作用域(函数) 作用域:变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期; 在一些类C编程语言中花括号内的每一段代码都有各自的作用域,而且变量在声明它们的代码段外是不可见的,称之为块 ...