Linux下进程崩溃时定位源代码位置

前几天领导安排一个小项目,大意是解决这样一个问题:

在Linux系统下,进程可能由于各种原因崩溃,此时我们要找到出问题的源代码在某一个文 件的具体行号,这样调试起来就会方便,高效很多,可能是公司项目要用到,想想挺有意思的,加上自己本身是个Linux狂热者,最终花了两三天解决了这个问 题,当然我的领导我们称之为专家指点了我很多,废话少说,下面是解决问题的思路和步骤以及自己的一些想法  

解 决该问题的大体思路是这样的:在Linux下,进程崩溃时内核(也就是我们所谓的操作系统)会向进程发送信号,比如我们程序运行崩溃时经常会看到 segmentation falt这样的信息,这是进程非法操作内存,内核会向进程发送SIGENV信号,那么我们凭什么可以找到进程崩溃的原因对应的源代码的位置呢,我们知道, 每个进程都有自己的堆栈,当某个进程崩溃时,堆栈里保存了一些关键信息,通过这些信息我们可以定位到出错的源代码位置,那么我们怎么来获得进程崩溃时堆栈 的信息呢,请记住,Linux是当今世界上最为强大的操作系统(不管你信不信,反正我是信了,^_^),在Linux系统里有个backtrace这些个 函数可以获得当前堆栈信息,好了,到这里问题已经解决了一半,backtrace信息中的有一个地址包含了出错代码在文件中的偏移量

需要注意的是编译时一定要加上 -g和-rdynamic参数

如果我们使用的是静态库或者出错的代码不在动态库中,那么我们可以直接用命令"addr2line -e 可执行文件名 偏移地址"打印出出错的代码行,下面是具体步骤

在测试程序的29行非法操作了内存

我们把addr2line命令放在程序里面做了,在代码中也可以看得到,下面这幅图片是程序的输出,可以看到

打印出源代码出错的行数为29

如果crash在一个动态库so里面,比较麻烦一点,此时addr2line不能直接给出代码行。因为我们都知道,so里面的地址在可执行文件装载的时候, 是可以被 reallocate的。所以,如果只有一个so的地址,要找出对应代码行的话,送给 addr2line的参数地址就是一个偏移地址,这里的偏移地址就是backtrace中的地址减去动态库加载的时候的基地址,这个基地址我们可以通过 /proc/pid/maps这个文件找到,pid是当前进程号,下面是具体步骤,跟之前的步骤类似,只不过我们为了测试,将func函数编译进了一个动 态库里面

这里我们只给出测试文件,具体怎么实现动态库,这个很容易,不在此多提,下面是测试程序的一部分

我们在/proc/pid/maps文件中找出出错动态库加载的基地址,用backtrace中的地址与基地址相减得到偏移地址就可以了,下面是程序输出

可以看到,我们用hello.c做的动态库,定位到代码出错在hello.c的第五行

下面是定位动态库错误的源代码:

 test.zip   

时间: 2024-09-11 08:03:40

Linux下进程崩溃时定位源代码位置的相关文章

Linux下传递参数时的Argument list too long错误

这篇文章是回复前几天在论坛一个朋友提出的问题,今天有空,整理了一下,发布出来,供大家参考! 当Linux下试图传递太多参数给一个系统命令(ls *; cp *; rm *; cat *; etc-)时,就会出现"Argument list too long"错误.本文将提供4种解决方法,按复杂程度由低到高排列. 方法#1: 手动把命令行参数分成较小的部分 例1 mv [a-l]* ../directory2 mv [m-z]* ../directory2 这是4种方法里最简单的,但是远

Linux下程序崩溃,ulimit,coredump,gdbserver

操作系统:Ubuntu10.04 前言:    在程序崩溃后,如何快速定位问题.    以下方法适用于开发调试阶段,不太适用成品.    本文着眼于嵌入式,PC方面更简单.    核心:gdbserver + coredump 一,安装,配置,使用 gdbserver    arm linux下安装gdb,gdbserver调试器 二,启动 coredump    linux下ulimit命令下的coredump  三,实例    1,源码 点击(此处)折叠或打开 #include <stdio

Linux下进程描述(1)—进程控制块【转】

转自:http://www.cnblogs.com/33debug/p/6705391.html 进程概念介绍    进程是操作系统对运行程序的一种抽象. • 一个正在执行的程序: • 一个正在计算机上执行的程序实例: • 能分配给处理器并由处理器执行的实体: • 一个具有普以下特征的活动单元:一组指令序列的执行.一个当前状态和相关的系统资源集. 内核观点:担当分配系统资源(CPU时间,内存)的实体.进程的两个基本元素:程序代码(可能被执行的其他进程共享).数据集.进程是一种动态描述,但是并不代

linux下进程的最大线程数、进程最大数、进程打开的文件数【转】

转自:http://www.cnblogs.com/niocai/archive/2012/04/01/2428154.html ===========最大线程数============== linux 系统中单个进程的最大线程数有其最大的限制 PTHREAD_THREADS_MAX 这个限制可以在 /usr/include/bits/local_lim.h 中查看 对 linuxthreads 这个值一般是 1024,对于 nptl 则没有硬性的限制,仅仅受限于系统的资源 这个系统的资源主要就

Linux下进程内存管理之malloc和sbrk

之前自己突发兴趣想写一下malloc函数,顺便了解一下进程的内存管理.在写的过程中发现其实malloc只不过是通过调用Linux下的sbrk函数来实现内存的分配,只是在sbrk之上加了一层对所分配的内存的管理罢了,而sbrk以及brk是实现从虚拟内存到内存的映射的.在实际动手写之前先来了解一下Linux下一个进程的内存空间分配. 进程内存空间分配 Linux下每个进程所分配的虚拟内存空间是3G,但实际使用过程中不可能也没有必要为一个进程分配如此大的空间,毕竟内存是很宝贵的资源.当一个进程执行的时

精确度量Linux下进程占用多少内存的方法

在Linux中,要了解进程的信息,莫过于从 proc 文件系统中入手去看.proc的详细介绍,可以参考内核文档的解读,里面有很多内容 yum install -y kernel-doc cat /usr/share/doc/kernel-doc-3.10.0/Documentation/filesystems/proc.txt 主要内容 Table of Contents ----------------- 0 Preface 0.1 Introduction/Credits 0.2 Legal

linux下ls命令时显示目录的相关提示文字等信息

用途: 给下一任服务器管理员一些指示,以便于其管理服务器.原本打算 cd 时就提示这些内容,可是不知道怎么用子 shell 控制父 shell 的目录.不过现在这样也好,相比于cd命令,使用ls时会更想知道这个目录的更多信息. 操作步骤: 1.创建目录 ~/bin 2.创建文件 ~/bin/tipls #!/bin/bash # # ls 时显示目录提示文字 # 需要目录中有 .dirtip 文件 # root@upall.cn # 2015-03-26 11:52:56 # ls $* --c

如何解决LINUX下安装ORACLE时SWAP不足问题

当前磁盘分区及SWAP分区情况如下: [root@bys3 ~]# fdisk -l Disk /dev/sda: 21.4 GB, 21474836480 bytes 255 heads, 63 sectors/track, 2610 cylinders Units = cylinders of 16065 * 512 = 8225280 bytes Device Boot      Start         End      Blocks   Id  System /dev/sda1  

linux下cp目录时排除一个或者多个目录的实现方法

说明:/home目录里面有data目录,data目录里面有a.b.c.d.e五个目录,现在要把data目录里面除过e目录之外的所有目录拷贝到/bak目录中 方法一:终端命令行下执行以下命令 cp -R `find /home/data -type d -path /home/data/e -prune -o -print | sed 1d ` /bak########################################################脚本实现脚本存放路径/home/o