嵌入式Linux应用崩溃调试-难以追踪的栈信息

简介: 在进行嵌入式Linux应用程序开发时,经常会用到gdb对崩溃日志进行分析,一般情况下,可以直接定位到崩溃的位置。但有时分析core文件时,却看不到有意义的崩溃栈,这时问题就有点复杂了,出现这种现象的原因可能有这么几个

在进行嵌入式Linux应用程序开发时,经常会用到gdb对崩溃日志进行分析,一般情况下,可以直接定位到崩溃的位置。但有时分析core文件时,却看不到有意义的崩溃栈,这时问题就有点复杂了,出现这种现象的原因可能有这么几个:


  1. 应用程序在编译时没有指定-g选项,导致可执行程序没有调试信息。


  1. 应用程序所依赖的动态库和静态库没有调试信息。


  1. 应用程序的运行时环境没有调试信息,比如libc等。


  1. 嵌入式Linux系统应用程序运行时环境和交叉编译工具链的运行时环境版本不一致,比如,嵌入式Linux环境中所使用的libc库和交叉编译器所使用的libc库版本不一致。


对于1-3条所列出的问题,可以很容易的通过gdb提供的提示信息获得,比如,如果应用程序test编译时没有添加-g选项,当使用gdb调试时,会提示如下信息:


Reading symbols from /home/jetpack/test/test...(no debugging symbols found)...done.


对于动态库提示信息也是类似的。


今天,重点说一下,第四种情况。


下面以一个具体的场景来说明这个问题。


问题场景


第4条说的是,Linux系统运行时环境与交叉工具链环境不一致,这里就以libc中的strlen为例来说明问题。


strlen用于计算c字符串的长度,其中不包括字符串结束符'\0'。但是,strlen传入NULL指针时,会导致段错误。我们通过模拟这种场景来看一下,系统运行环境与编译环境不一致带来的问题。


下面是会导致崩溃的代码:


#include<string.h>
int main(int argc, char* argv[])
{
  int rlen = strlen(NULL);
  return 0;
}
注意:编译时指定-g,否则test没有调试信息。                                                                                                                                                                                                                     


嵌入式Linux运行环境libc信息:


root@zpd /lib$ ll libc.so.6 
lrwxrwxrwx    1 root     root            12 Jan  1 00:00 libc.so.6 -> libc-2.13.so
root@zpd /lib$ ll libc-2.13.so
-rwxr-xr-x    1 root     root            1409189 Jan  1 22:08 libc-2.13.so


交叉编译器libc信息:


lrwxrwxrwx 1 jetpack jetpack 12 3月   9 12:07 libc.so.6 -> libc-2.13.so*
-rwxr-xr-x 1 jetpack jetpack 1496962 3月  15  2012 libc-2.13.so*


将test编译之后,拷贝到嵌入式Linux环境中运行。注意,需要重新配置shell环境的ulimit关于core文件的限制,否则不会出现core文件。具体命令如下:


ulimit -c unlimited
./test
Segmentation fault (core dumped)


将core文件拷贝到开发环境,使用gdb查看core文件信息。


1. Reading symbols from /home/jetpack/test/test...done.
[New Thread 852]
2. warning: .dynamic section for "/home/jetpack/work/OKMX6UL-C2/fsl-linaro-toolchain/arm-fsl-linux-gnueabi/multi-libs/lib/libc.so.6" is not at the expected address (wrong library or version mismatch?)
Reading symbols from /home/jetpack/work/OKMX6UL-C2/fsl-linaro-toolchain/arm-fsl-linux-gnueabi/multi-libs/lib/libc.so.6...done.
Loaded symbols for /home/jetpack/work/OKMX6UL-C2/fsl-linaro-toolchain/arm-fsl-linux-gnueabi/multi-libs/lib/libc.so.6
Reading symbols from /home/jetpack/work/OKMX6UL-C2/fsl-linaro-toolchain/arm-fsl-linux-gnueabi/multi-libs/lib/ld-linux.so.3...done.
Loaded symbols for /home/jetpack/work/OKMX6UL-C2/fsl-linaro-toolchain/arm-fsl-linux-gnueabi/multi-libs/lib/ld-linux.so.3
Core was generated by `./test'.
Program terminated with signal 11, Segmentation fault.
#0  0x76e8d864 in tr_freehook () from /home/jetpack/work/OKMX6UL-C2/fsl-linaro-toolchain/arm-fsl-linux-gnueabi/multi-libs/lib/libc.so.6
(gdb) bt
3. #0  0x76e8d864 in tr_freehook () from /home/jetpack/work/OKMX6UL-C2/fsl-linaro-toolchain/arm-fsl-linux-gnueabi/multi-libs/lib/libc.so.6
#1  0x7ec97dd4 in ?? ()
#2  0x7ec97dd4 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)


上面是gdb通过core得到的信息,注意下面几点:


  1. test加载成功,并且其有调试信息。


  1. warning: .dynamic section for "/home/jetpack/work/OKMX6UL-C2/fsl-linaro-toolchain/arm-fsl-linux-gnueabi/multi-libs/lib/libc.so.6" is not at the expected address (wrong library or version mismatch?),说的是通过core文件的信息在交叉编译环境的libc中找不到.dynamic section,最后的结论是wrong library or version mismatch?即,库文件被损坏或者版本不一致。这是解决问题的关键。


  1. 这时如果通过bt,查看崩溃栈信息,会得到一些莫名其妙的信息,比如这里的tr_freehook。如果没有注意到2中提示的警告信息,可能会沿着这个错误的栈信息去查找问题原因,这时就会走很多的弯路,最终无功而返。


解决思路


通过第二节对于core的分析,可以看出问题的关键是运行环境和编译环境的libc版本库不一致导致的,那么解决问题的思路就明显了:


  1. 要么修改交叉编译的运行时环境。


  1. 要么修改运行时环境。


很明显,肯定是第2种思路,将交叉编译器的libc-2.13.so库拷贝到嵌入式Linux环境,替换之前的libc-2.13.so,再次运行test,得到core文件,gdb调试之,core文件信息如下:


1. Reading symbols from /home/jetpack/test/test...done.
[New Thread 858]
2. Reading symbols from /home/jetpack/work/OKMX6UL-C2/fsl-linaro-toolchain/arm-fsl-linux-gnueabi/multi-libs/lib/libc.so.6...done.
Loaded symbols for /home/jetpack/work/OKMX6UL-C2/fsl-linaro-toolchain/arm-fsl-linux-gnueabi/multi-libs/lib/libc.so.6
Reading symbols from /home/jetpack/work/OKMX6UL-C2/fsl-linaro-toolchain/arm-fsl-linux-gnueabi/multi-libs/lib/ld-linux.so.3...done.
Loaded symbols for /home/jetpack/work/OKMX6UL-C2/fsl-linaro-toolchain/arm-fsl-linux-gnueabi/multi-libs/lib/ld-linux.so.3
Core was generated by `./test'.
Program terminated with signal 11, Segmentation fault.
3. #0  0x76e5e864 in strlen () from /home/jetpack/work/OKMX6UL-C2/fsl-linaro-toolchain/arm-fsl-linux-gnueabi/multi-libs/lib/libc.so.6
(gdb) bt
#0  0x76e5e864 in strlen () from /home/jetpack/work/OKMX6UL-C2/fsl-linaro-toolchain/arm-fsl-linux-gnueabi/multi-libs/lib/libc.so.6
#1  0x00008390 in main (argc=1, argv=0x7ef85dc4) at test.c:5


对照上面的1、2、3条,可以看到第2条可以正确的加载libc.so.6库;第3条可以看到由于崩溃位置在strlen。


总结


本文通过一个案例,简要说明了在嵌入式Linux应用开发时,由于运行时环境和交叉编译环境不一致导致的core文件分析失败的问题,并说明了如何解决这个问题。有的人会问,为什么会导致环境不一致呢?在构建嵌入式Linux环境时,肯定会涉及到根文件系统的构建过程,这时会将交叉编译器的环境整体拷贝到根文件系统中,这样的话就不会出现上述问题。是的,如果按照这个流程中应该不会有问题,但是,实际情况是,我们拿的是一个构建好的Linux系统,如果这时交叉编译工具链升级了,而嵌入式Linux运行时环境未升级,那问题就出现了。这时,就需要根据各种信息,来分析问题的根源了,这里就是gdb分析core时的一些警告信息。


所以,这里再次强调一下,开发过程中的任何警告信息都不能轻易放过,必须仔细分析,问题的解决线索往往蕴含其中。


相关实践学习
阿里云图数据库GDB入门与应用
图数据库(Graph Database,简称GDB)是一种支持Property Graph图模型、用于处理高度连接数据查询与存储的实时、可靠的在线数据库服务。它支持Apache TinkerPop Gremlin查询语言,可以帮您快速构建基于高度连接的数据集的应用程序。GDB非常适合社交网络、欺诈检测、推荐引擎、实时图谱、网络/IT运营这类高度互连数据集的场景。 GDB由阿里云自主研发,具备如下优势: 标准图查询语言:支持属性图,高度兼容Gremlin图查询语言。 高度优化的自研引擎:高度优化的自研图计算层和存储层,云盘多副本保障数据超高可靠,支持ACID事务。 服务高可用:支持高可用实例,节点故障迅速转移,保障业务连续性。 易运维:提供备份恢复、自动升级、监控告警、故障切换等丰富的运维功能,大幅降低运维成本。 产品主页:https://www.aliyun.com/product/gdb
相关文章
|
2天前
|
Ubuntu Linux 开发者
Ubuntu20.04搭建嵌入式linux网络加载内核、设备树和根文件系统
使用上述U-Boot命令配置并启动嵌入式设备。如果配置正确,设备将通过TFTP加载内核和设备树,并通过NFS挂载根文件系统。
29 15
|
16天前
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
79 13
|
2月前
|
缓存 监控 Linux
Python 实时获取Linux服务器信息
Python 实时获取Linux服务器信息
|
2月前
|
缓存 监控 Linux
|
2月前
|
缓存 Linux 开发者
Linux内核中的并发控制机制:深入理解与应用####
【10月更文挑战第21天】 本文旨在为读者提供一个全面的指南,探讨Linux操作系统中用于实现多线程和进程间同步的关键技术——并发控制机制。通过剖析互斥锁、自旋锁、读写锁等核心概念及其在实际场景中的应用,本文将帮助开发者更好地理解和运用这些工具来构建高效且稳定的应用程序。 ####
48 5
|
2月前
|
网络协议 Linux 虚拟化
如何在 Linux 系统中查看进程的详细信息?
如何在 Linux 系统中查看进程的详细信息?
143 1
|
2月前
|
存储 安全 关系型数据库
Linux系统在服务器领域的应用与优势###
本文深入探讨了Linux操作系统在服务器领域的广泛应用及其显著优势。通过分析其开源性、安全性、稳定性和高效性,揭示了为何Linux成为众多企业和开发者的首选服务器操作系统。文章还列举了Linux在服务器管理、性能优化和社区支持等方面的具体优势,为读者提供了全面而深入的理解。 ###
|
5月前
|
Unix Linux Ruby
在windows和linux上高效快捷地发布Dash应用
在windows和linux上高效快捷地发布Dash应用
|
5月前
|
Linux iOS开发 开发者
跨平台开发不再难:.NET Core如何让你的应用在Windows、Linux、macOS上自如游走?
【8月更文挑战第28天】本文提供了一份详尽的.NET跨平台开发指南,涵盖.NET Core简介、环境配置、项目结构、代码编写、依赖管理、构建与测试、部署及容器化等多个方面,帮助开发者掌握关键技术与最佳实践,充分利用.NET Core实现高效、便捷的跨平台应用开发与部署。
445 3
|
4月前
|
Linux API 开发工具
Linux内核开发流程指南 - 8. 获取更多信息【ChatGPT】
Linux内核开发流程指南 - 8. 获取更多信息【ChatGPT】