GDB和ELF

GDB和ELF

关于GDB和ELF.

GDB

gdb是GNU项目的调试工具,允许程序员看到程序执行过程中内部正在发生的事情。gdb支持的语言有很多,绝不止C++一种,关于gdb的更多信息读者可以在其官方介绍中查阅。

.core文件

在debug环境下,linux系统上当软件异常退出时候,内核会在当前工作目录下生成一个core文件。使用gdb来查看core文件,可以帮助还原异常时候发生的一些情况,比如代码crash的文件和行数。

执行ulimit -c可以查看当前系统生成.core文件的开关是否打开,如果返回0代表关闭状态。使用ulimit -c filesize命令,可以限制core文件的大小(filesize的单位为kbyte)。

生成core调试文件

当我设置了ulimit -c 1024,使用了-g生成可执行文件,执行了程序,发生了预期的crash,但是在执行目录中,仍然看不到.core相关的文件。

这种情况可以试下下面的方法。

1
cat /proc/sys/kernel/core_pattern

输出结果

xxxxxx@personal-ubuntu-0007:~/a$ cat /proc/sys/kernel/core_pattern
|/usr/share/apport/apport -p%p -s%s -c%c -d%d -P%P -u%u -g%g – %E

这种情况表明,文件的结果会被Linux的一个进程apport 吞掉,拿去检查是不是系统的bug,所以看不到core文件了。如果想要产生core文件,需要关闭该程序。

1
sudo service apport stop

再次cat /proc/sys/kernel/core_pattern 可以看到

xxxxxx@personal-ubuntu-0007:~/a$ cat /proc/sys/kernel/core_pattern
core

这个时候就正常可以调试生成core文件了。

core文件常见的信号

在 Unix/Linux 系统上,有许多不同的信号可以在不同的情况下发送给进程,以通知它们发生了某些事件。以下是一些常见的 core 信号及其含义:

SIGSEGV(Segmentation Fault):
表示进程试图访问其没有权限访问的内存区域,如非法内存访问、访问空指针等。通常会导致程序崩溃并生成 core 文件。

SIGILL(Illegal Instruction):
表示进程执行了非法指令。可能是因为代码错误、平台不兼容或者二进制文件损坏导致的。

SIGFPE(Floating Point Exception):
表示浮点运算异常,如除以零或无效的浮点操作。通常会导致程序崩溃。

SIGABRT:
由调用 abort() 函数引发,表示进程发生了致命错误。通常用于程序自身检测到无法继续执行的错误情况。

SIGBUS:
表示非法内存访问,类似于 SIGSEGV,但是涵盖了一些硬件相关的内存错误。

SIGILL:
表示进程执行了非法的指令,通常是由于代码错误或者二进制文件损坏引起的。

SIGPIPE:
当进程向一个已关闭的管道(或者 Socket)写数据时,操作系统会发送这个信号,通常用于处理进程之间的通信。

SIGSYS:
表示进程试图执行不支持的系统调用。可能是因为程序依赖于某些特定的操作系统特性,而这些特性在当前环境中不可用。

SIGTRAP:
通常用于调试器与被调试程序之间的通信。当被调试程序执行断点或陷阱指令时,会发送这个信号。

这只是一些常见的 core 信号,实际上还有许多其他信号,每个信号都有不同的含义和用途。根据需要,可以使用系统头文件 <signal.h> 中定义的常量来处理这些信号,以便在程序中适当地响应和处理这些事件。

gdb调试

  • gdb
  • file
  • run
  • core-file
  • bt
  • quit(q)

通过gdb命令进入gdb调试环境。

在调试环境中,file读取要执行文件的符号,run(r)运行可执行文件,core-file可以查看core文件,bt打印出出错的堆栈信息数据,使用quit退出gdb环境。

ELF

ELF介绍

并非所有二进制文件都可以使用gdb进行调试,前面提到我们需要使用-g参数来生成可执行文件,因为这会在输出文件中添加debug信息。

为了加深理解,有必要对二进制文件进一步探索。下面看看什么是ELF文件格式。

在linux平台,执行man elf可以查看到ELF非常详细的介绍。你会在开头看到这句话:

elf - format of Executable and Linking Format (ELF) files

ELF是一种数据格式,用来表示可执行文件和链接文件。

并不是所有系统平台都使用ELF作为可执行文件格式,目标可执行文件在不同系统平台表现为不同的格式。

  • Windows使用可移植可执行(PortableExecutable,PE)格式。

  • Mac OS-X使用Mach-O格式。

  • 现代x86-64Linux和Unix系统使用可执行可链接格式(Executable and Linkable Format,ELF)。

ELF格式的文件在Linux系统下有.axf、 .bin、 .elf、 .o、 .prx、 .puff、 .ko、 .mod和.so等等

比如常见的可重定位目标文件格式如下.

这里面.debug包含了一个调试符号表,使用了-g参数编译的结果会带有这张表。

链接中的这张图比较好的展示了ELF的相关信息

查看ELF文件

使用readelf工具,使用命令readelf -h可以查看该工具的使用方法。
下面列举几个最常用的命令。

  • -a Equivalent to: -h -l -S -s -r -d -V -A -I
  • -h Display the ELF file header
  • -l Display the program headers
  • -S Display the sections’ header
  • -g Display the section groups
  • -t Display the section details
  • -e Equivalent to: -h -l -S
  • -s Display the symbol table

section 和 Segmant

Section称为节,是指在汇编源码中经由关键字section或segment修饰、逻辑划分的指令或数据区域,汇编器会将这两个关键字修饰的区域在目标文件中编译成节,也就是说”节”最初诞生于目标文件中。

节区描述了文件的组成,可以通过readelf -S来查看。节是从链接角度来看文件组成的,链接器将.o文件链接成一个elf文件,同时生成了一个表,该表记录了各个section的区域。

Segment称为段,是链接器根据目标文件中属性相同的多个Section合并后的Section集合,这个集合称为Segment,也就是段,链接器把目标文件链接成可执行文件,因此段最终诞生于可执行文件中。我们平时所说的可执行程序内存空间中的代码段和数据段就是指的Segment。



关注博客或微信搜索公众号多媒体与图形,获取更多内容,欢迎在公众号留言交流!
扫一扫关注公众号
作者

占航

发布于

2023-03-05

更新于

2023-10-04

许可协议

评论