C语言 为什么gdb抱怨我的核心文件太小,然后又不能产生有意义的堆栈跟踪?

dddzy1tm  于 2023-03-29  发布在  其他
关注(0)|答案(2)|浏览(94)

我有一个从segfault生成的核心文件。当我试图将其加载到gdb时,无论我如何加载它,或者是否使用正确的可执行文件,都没有关系-我总是从gdb收到关于核心文件被截断的警告:

$ gdb -q /u1/dbg/bin/exdoc_usermaint_pdf_compact /tmp/barry/core.exdoc_usermaint.11
Reading symbols from /u1/dbg/bin/exdoc_usermaint_pdf_compact...done.
BFD: Warning: /tmp/barry/core.exdoc_usermaint.11 is truncated: expected core file size >= 43548672, found: 31399936.

warning: core file may not match specified executable file.
Cannot access memory at address 0x7f0ebc833668
(gdb) q

我很担心这个错误:“BFD:警告:/tmp/巴里/core.exdoc_usermaint.11被截断:预期的核心文件大小〉= 43548672,找到:三一三九九九三六。”

为什么gdb会认为核心文件被截断?gdb是否正确?gdb从哪里获取核心文件的预期大小,是否可以复查?

背景:
我正在尝试改进我们生产系统上segfault的诊断。我的计划是从生产中剥离的可执行文件中提取核心文件,并将其与开发系统上的可执行文件的调试版本一起使用,以快速诊断segfault错误。在这个问题的早期版本中,我给出了许多与相似但不同的系统相关的细节,但后来我得到了一份关于我们生产系统的说明,并确定大部分细节对这个问题都不重要。
gdb版本:

$ gdb
GNU gdb (GDB) Fedora (7.0.1-50.fc12)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.

Linux版本:

$ uname -a
Linux somehost 2.6.32.23-170.fc12.x86_64 #1 SMP Mon Sep 27 17:23:59 UTC 2010 x86_64 x86_64 x86_64 GNU/Linux

我在发帖前阅读了this question(和许多其他人)。提问者的目标和我有点相似,但没有从gdb得到任何关于截断核心文件的错误。因此,与该问题相关的信息对我的问题没有帮助。

hc8w905p

hc8w905p1#

Core Dump文件格式

在现代Linux系统上,核心转储文件使用具有特定配置的ELF对象文件格式来格式化。ELF是结构化二进制文件格式,其中文件偏移用作文件中的数据块之间的引用。

对于核心转储文件,ELF文件头中的e_type字段的值为ET_CORE。
与大多数ELF文件不同,核心转储文件通过程序头提供所有数据,并且不存在节头。因此,如果您只需要处理核心文件,则可以选择在计算文件大小时忽略节头。

计算Core Dump文件大小

要计算ELF文件大小,请执行以下操作:

  • 考虑文件中的所有块:
    • 块描述(偏移量+大小)*
  • ELF文件头(0 + e_ehsize)(ELF 32为52,ELF 64为64)
  • 程序头表(e_phoff + e_phentsize * e_phnum)
  • 程序数据块(也称为“段”)(p_offset + p_filesz)
  • 节头表(e_shoff + e_shentsize * e_shnum)- * 核心文件不需要 *
  • 段数据块-(sh_offset + sh_size)- * 核心文件不需要 *
  • 删除任何sh_type为SHT_NOBITS的节头,因为这些节头仅用于记录已剥离且不再存在于文件中的数据的位置(* 核心文件不需要 *)。
  • 删除任何大小为0的块,因为它们不包含可寻址字节,因此它们的文件偏移量无关紧要。
  • 文件的结尾将是最后一个块的结尾,这是上面列出的所有剩余块的偏移量+大小的最大值。

如果您发现程序头或节头表的偏移量超过了文件的末尾,则无法计算预期的文件大小,但您将知道文件已被截断。
虽然ELF文件可能包含未寻址区域,并且长度可能超过计算的大小,但根据我有限的经验,这些文件的大小与上述方法计算的大小完全相同。

截断核心文件

gdb可能执行与上述类似的计算来计算预期的核心文件大小。
简而言之,如果gdb说你的核心文件被截断了,那么它很可能就是被截断了
内核转储文件被截断的最可能原因之一是系统ulimit。这可以在/etc/security/limits.conf中在系统范围内设置,或者使用ulimit shell命令在每个用户的基础上设置[脚注:除了我自己的系统之外,我对系统一无所知。
尝试命令“ulimit -c”来检查您的有效核心文件大小限制:

$ ulimit -c
unlimited

另外,值得注意的是,gdb实际上并没有因为截断的核心文件而拒绝操作。gdb仍然会尝试产生堆栈回溯,并且在您的情况下,只有当它试图访问堆栈上的数据并发现所寻址的特定内存位置不在截断的核心文件的末尾时才会失败。

wz3gfoph

wz3gfoph2#

突出显示stackoverflow中用于解决类似问题的答案如何获得大于2GB的核心文件。根据作者的说法,通过更改默认的/etc/systemd/coredump.conf来解决截断或覆盖问题

相关问题