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调试工具外,其他步骤基本一致。

 

 

 

 

 

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐