嵌入式随笔2--core 调试技巧总结(GDB调试常见问题汇总)
0、core简介Core文件其实就是内存的映像,当程序崩溃时,存储内存的相应信息,主用用于对程序进行调试。当程序崩溃时便会产生core文件,其实准确的应该说是core dump 文件。1、core功能打开及关闭关闭或阻止core文件生成:$ulimit -c 0打开core文件生成:$ulimit -c unlimited以上配置只对当前会话起作用,下次重新登陆后,还是...
0、core简介
Core文件其实就是内存的映像,当程序崩溃时,存储内存的相应信息,主用用于对程序进行调试。当程序崩溃时便会产生core文件,其实准确的应该说是core dump 文件。
1、core功能打开及关闭
关闭或阻止core文件生成:
$ulimit -c 0
打开core文件生成:
$ulimit -c unlimited
以上配置只对当前会话起作用,下次重新登陆后,还是得重新配置。
检查core文件的选项是否打开:
$ulimit -a
2、设置转存路径及转存文件名
echo /data/coredump/core.%e.%p> /proc/sys/kernel/core_pattern
以下是参数列表:(常用的e p t)
%p - insert pid into filename 添加pid
%u - insert current uid into filename 添加当前uid
%g - insert current gid into filename 添加当前gid
%s - insert signal that caused the coredump into the filename 添加导致产生core的信号
%t - insert UNIX time that the coredump occurred into filename 添加core文件生成时的unix时间
%h - insert hostname where the coredump happened into filename 添加主机名
%e - insert coredumping executable name into filename 添加命令名
3、core调试
为了方便将应用程序及core文件放到同一目录下,使用命令gdb ./***.app core*******进入GDB调试
4、常见问题:
4.1 backtrace(bt)函数名为问号:
- 源代码和可执行程序版本不一致;
- 没有符号表,这不只是-g加上就万能,还可能涉及到具体的编译选项比如-g2 -gdwarf-2,具体查看gcc编译选项;
- gdb版本比gcc版本老,有些内容无法解析
- 动态库和应用经过strip操作,strip会删除程序和库文件中的符号
符号包括dymsym 和symtab两部分(readelf -s 命令查看)使用strip瘦身之后,只保留dymsym符号,删除掉symtab符号;
动态符号表(.dynsym) 用来保存与动态链接相关的导入导出符号,不包括模块内部的符号
.dynsym是.symtab的一个子集, 大家都有疑问, 为什么要两个信息重合的结构?
需要先了解allocable/non-allocable ELF section, ELF文件包含一些sections(如code和data)是在运行时需要的, 这些sections被称为allocable; 而其他一些sections仅仅是linker,debugger等工具需要, 在运行时并不需要, 这些sections被称为non-allocable的.
当linker构建ELF文件时, 它把allocable的数据放到一个地方, 将non-allocable的数据放到其他地方.当OS加载ELF文件时, 仅仅allocable的数据被映射到内存, non-allocable的数据仍静静地呆在文件里不被处理. strip就是用来移除某些non-allocable sections的。.symtab包含大量linker,debugger需要的数据, 但并不为runtime必需, 它是non-allocable的; .dynsym包含.symtab的一个子集, 比如共享库所需要在runtime加载的函数对应的symbols, 它世allocable的.在程序运行过程中显式被加载, 实际上就是调用dlopen,dlsym等接口显式地打开共享库, 显示地查找库中的symbol, 然后找到对应的代码去执行。
4.2堆栈被破
编译时增加gcc参数: -fstack-protector 和 -fstack-protector-all,开启堆栈保护
5、GDB调试技巧()
GDB断点设置Break 缩写B
对程序第五行打断点设置-> B 5
对多个文件的中的一个设置断点-> B gdb_test.c:5
对程序中的某个函数打断点-> B gdb_test.c:fun_A
查看断点信息-> info b
条件断点-> b gdb_test.c:5 if intvalue = 10
运行-> run 缩写 r
单步跟踪-> next 简写 n 函数调用当做一条简单语句执行
单步调试-> step 简写 s 函数调用进入函数体内
跳出函数-> finish 退出进入的函数
跳出循环-> until 简写 u 在循环体内单步调试,可以跳出循环
继续运行-> continue 简写 c 继续运行程序
查看运行时数据 print 简写 p 打印变量、字符串、表达式的值-> p count
自动显示 display 设置自动显示的变量,当程序停止时或单步调试时,变量会自动显示
info display 查看自动显示的信息
undisplay num (配合info display 使用)
delete display dnums
disable display dnums
enable display dnums
常见处理coredump流程:一般情况下,看coredump都是内存溢出导致,使用bt命令查看堆栈信息,单线程的应用就大概可以定位到异常的位置。多进程的问题定位相对复杂,在查看堆栈信息后可使用frame切换线程,配合断点、变量输出等gdb调试技巧,可以加快问题定位。
嵌入式设备,除了使用交叉编译的gdb调试工具外,其他步骤基本一致。
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐

所有评论(0)