使用addr2line 打印调用栈信息调试程序崩溃

首先参考:https://blog.csdn.net/gongmin856/article/details/79192259

接下来是我复制下来的代码,命名ttt.c

几个命令:

/opt/toolchain/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -g -rdynamic -funwind-tables -fasynchronous-unwind-tables ttt.c -o test_ttt

注:

  -rdynamic  该参数是链接选项,不是编译选项。这主要是对可执行程序(elf)而言的,而编译动态库时,即使没有rdynamic选项,默认也会将非静态函数放入动态符号表中(刻意隐藏的函数除外)。默认情况下,可执行程序(非动态库)文件内我们定义的非静态函数,是不放到动态符号表中的,链接时只有加上"-rdynamic"才能将所有非静态函数加到动态符号表中。这个参数很多文章里都有写。

-funwind-tables -fasynchronous-unwind-tables:这几个参数比较恶心,很多文章里都没提到,其实很重要,作用是为了backtrace这个函数,如果不加这几个参数,那么backtrace函数会返回1,那么程序test_ttt运行时的栈回溯信息里就只有一个了,如下:

=========>>>catch signal 11 <<<=========

Dump stack start...

backtrace() returned 6 addresses

[00] /mnt/usr/zc/temp/RB1/test_ttt(dump+0x14) [0x400be8] //就会仅仅只有这一行了

[01] /mnt/usr/zc/temp/RB1/test_ttt(signal_handler+0x2c) [0x400cb8]

[02] linux-vdso.so.1(__kernel_rt_sigreturn+0) [0x7f9234a270]

[03] /mnt/usr/zc/temp/RB1/test_ttt(divide+0x34) [0x400bb0]

[04] /mnt/usr/zc/temp/RB1/test_ttt(main+0xc0) [0x400da4]

[05] /lib/libc.so.6(__libc_start_main+0xe4) [0x7f921f3824]

Dump stack end...

在使用addr2line查问题的时候就是看0x400bb0这个值了

/opt/toolchain/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-addr2line -e ~/smba_share/nfs/temp/RB1/test_ttt 0x400bb0

定位行数:

/home/zhaocan/smba_share/nfs/temp/RB1/ttt.c:18

如果此时使用objdump方法:

/opt/toolchain/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-objdump -S -l ~/smba_share/nfs/temp/RB1/test_ttt > info.txt

注:

-l --line-numbers

  用文件名和行号标注相应的目标代码,仅仅和-d、-D或者-r一起使用使用-ld和使用-d的区别不是很大,在源码级调试的时候有用,要求编译时使用了-g之类的调试编译选项。

-S --source

  尽可能反汇编出源代码,尤其当编译的时候指定了-g这种调试参数时,效果比较明显。隐含了-d参数。

由上面可以看出问题发生在divide函数里,打开info.txt文件,从下往上看

0000000000400b7c <divide>: //0x400b7c + 0X34 = 0x400bb0

divide():

/home/zhaocan/smba_share/nfs/temp/RB1/ttt.c:9

#include <execinfo.h> /* for backtrace() */

#define BACKTRACE_SIZE 16

int divide(int num)

{

400b7c:a9bd7bfd stpx29, x30, [sp, #-48]!

400b80:910003fd movx29, sp

400b84:b9001fa0 strw0, [x29, #28]

/home/zhaocan/smba_share/nfs/temp/RB1/ttt.c:10

int ret = 0x00;

400b88:b9002fbf strwzr, [x29, #44]

/home/zhaocan/smba_share/nfs/temp/RB1/ttt.c:11

int *pTemp = NULL;

400b8c:f90013bf strxzr, [x29, #32]

/home/zhaocan/smba_share/nfs/temp/RB1/ttt.c:13

if(0 != num)

400b90:b9401fa0 ldrw0, [x29, #28]

400b94:7100001f cmpw0, #0x0

400b98:54000080 b.eq400ba8 <divide+0x2c> // b.none

/home/zhaocan/smba_share/nfs/temp/RB1/ttt.c:15

{

printf("num is not 0 !\n");

400b9c:90000000 adrpx0, 400000 <_init-0x988>

400ba0:91398000 addx0, x0, #0xe60

400ba4:97ffffa7 bl400a40 <puts@plt>

/home/zhaocan/smba_share/nfs/temp/RB1/ttt.c:18 //行数和addr2line查出来的一致

}

*pTemp = 0x01; /* 这将导致一个段错误,致使程序崩溃退出 */

400ba8:f94013a0 ldrx0, [x29, #32]

400bac:52800021 movw1, #0x1 // #1

400bb0:b9000001 strw1, [x0]

/home/zhaocan/smba_share/nfs/temp/RB1/ttt.c:20

ret = num + *pTemp;

400bb4:f94013a0 ldrx0, [x29, #32]

400bb8:b9400000 ldrw0, [x0]

400bbc:b9401fa1 ldrw1, [x29, #28]

400bc0:0b000020 addw0, w1, w0

400bc4:b9002fa0 strw0, [x29, #44]

/home/zhaocan/smba_share/nfs/temp/RB1/ttt.c:22

return ret;

400bc8:b9402fa0 ldrw0, [x29, #44]

/home/zhaocan/smba_share/nfs/temp/RB1/ttt.c:25

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: addr2line是一个Linux下的常见工具,用来将程序的地址转换为文件名和行号等位置信息。这个工具通常用在程序崩溃时进行调试,以便追踪问题出现的位置,帮助程序猿进行修复。 如果想使用addr2line,首先需要下载与安装。通常这个工具会随着编译器一起安装,所以在一般的Linux系统中这个工具是默认安装的。如果想自己手动安装,可以使用Linux系统自带的包管理器进行下载和安装,具体安装方法如下: 1. 打开终端,使用管理员权限登录 2. 输入命令 sudo apt-get update,进行包列表更新 3. 输入命令 sudo apt-get install binutils,进行addr2line安装(如果系统已经安装过binutils,则这个步骤可以省略不操作) 安装后即可使用addr2line进行调试,具体操作方法可以参考相关手册或在线教程。需要注意的是,使用addr2line可能需要一定的Linux系统及程序调试方面的知识储备,建议有一定经验的程序员进行操作。 ### 回答2: addr2line是一个用于将程序计数器地址(PC)转换为源文件和行号的GNU工具。它通常用于调试和跟踪代码中错误时查找源代码和行号。它可以通过GNU binutils包来安装和使用。在大多数Linux发行版中,binutils都已经安装,因此addr2line可以直接使用。 要下载addr2line,可以通过访问GNU binutils网站来获得它的源代码并手动构建和安装。对于大多数用户来说,最简单的方法是使用操作系统的包管理器来安装binutils。例如,在Ubuntu上可以使用apt-get命令,CentOS和Fedora上可以使用yum命令。 安装完成后,可以使用以下命令来调用addr2lineaddr2line -e <binaryfile> <address> 其中,binaryfile是要分析的二进制文件的路径,address是程序计数器地址。addr2line打印出与给定地址相关联的源文件和行号。 总的来说,addr2line是一个非常实用的工具,可以帮助开发人员在调试代码时更轻松地定位和修复问题。因此,学会下载和使用addr2line对开发人员来说至关重要。 ### 回答3: addr2line是用于将地址转换为行号和文件名的命令行工具。它通常与gdb一起使用,以便在调试过程中确定源代码行号。 要下载addr2line,首先需要安装GNU binutils。地址取决于你的操作系统。在Ubuntu上,可以使用以下命令安装: sudo apt-get install binutils 安装完成后,可以使用以下命令检查addr2line是否可用: addr2line --help 如果命令返回帮助文档,则addr2line已经成功安装。 如果你想在自己的代码中使用addr2line,则需要使用编译器生成调试信息。在GCC编译器中,可以通过以下命令生成调试信息: gcc -g -o myprogram myprogram.c 在将程序编译为可执行文件后,可以使用以下命令将地址转换为文件名和行号: addr2line -e myprogram 0x4005a5 此命令将返回myprogram中地址0x4005a5所在的文件名和行号。 总之,addr2line是一个非常实用的工具,可以帮助开发人员快速解决代码中的问题。安装过程简单,只需确保已安装GNU binutils即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值