为什么 gdb 抱怨我的核心文件太小,然后无法生成有意义的堆栈跟踪?

问题描述 投票:0回答:2

我有一个由段错误生成的核心文件。当我尝试将其加载到 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/barry/core.exdoc_usermaint.11 被截断:预期核心文件大小 >= 43548672,发现:31399936。”

为什么gdb认为core文件被截断了? gdb是对的吗? gdb 从哪里获取核心文件的预期大小,我可以仔细检查它吗?

背景:

我正在尝试改进对生产系统中的段错误的诊断。我的计划是从生产中剥离的可执行文件中获取核心文件,并将它们与我们开发系统上可执行文件的调试版本一起使用,以快速诊断段错误。在这个问题的早期版本中,我提供了与相似但不同的系统相关的许多详细信息,但后来我在我们的生产系统上获得了一个帐户,并确定大多数细节对问题并不重要。

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

我在发帖之前阅读了这个问题(以及许多其他问题)。提问者的目标与我有些相似,但没有从 gdb 收到任何有关核心文件被截断的错误。因此,与该问题相关的信息对我解决问题没有帮助。

c gdb fedora coredump
2个回答
6
投票

核心转储文件格式

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

对于核心转储文件,ELF 文件头中的 e_type 字段的值为 ET_CORE。

与大多数 ELF 文件不同,核心转储文件通过程序头提供所有数据,并且不存在节头。 因此,如果您只需要处理核心文件,您可以选择在计算文件大小时忽略节标题。

计算核心转储文件大小

计算ELF文件大小:

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

如果您发现程序头或节头表的偏移量超出了文件末尾,那么您将无法计算预期的文件大小,但您会知道文件已被截断。

虽然 ELF 文件可能包含未寻址区域并且比计算的大小长,但根据我有限的经验,这些文件的大小正是通过上述方法计算的大小。

截断的核心文件

gdb 可能会执行与上述类似的计算来计算预期的核心文件大小。

简而言之,如果 gdb 说你的核心文件被截断了,那么它很可能被截断了

导致核心转储文件被截断的最可能原因之一是系统 ulimit。这可以在 /etc/security/limits.conf 中在系统范围内设置,或者使用 ulimit shell 命令在每个用户的基础上设置[脚注:除了我自己的系统之外,我对系统一无所知]。

尝试使用命令“ulimit -c”来检查您的有效核心文件大小限制:

$ ulimit -c
unlimited

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


1
投票

突出显示 来自 stackoverflow 的解决类似问题的答案。根据作者的说法,截断或覆盖问题可以通过扩展默认值来解决

/etc/systemd/coredump.conf

coredump.conf手册提供了更多信息。

© www.soinside.com 2019 - 2024. All rights reserved.