【问题标题】:Is the Executable and Linkable Format (ELF) streamable?可执行和可链接格式 (ELF) 是否可流式传输?
【发布时间】:2014-11-12 22:02:48
【问题描述】:

我想从具有大量内存占用的崩溃应用程序中提取堆栈跟踪。理想情况下,用户无需等待整个核心转储写入磁盘。

我目前的想法是在/proc/sys/kernel/core_pattern 安装一个 coredump 挂钩,它将通过标准输入解析传入的 coredump 并仅提取堆栈跟踪。但是,在内存中创建 coredump 的完整副本是不切实际的,因此流式方法会更好。

我是 ELF 格式 (http://en.wikipedia.org/wiki/Executable_and_Linkable_Format) 的新手,想知道它是否支持流解析器。我还没有编写任何类型的流解析器 - 我熟悉这个概念,但需要有关如何分析流能力格式的指针。

作为第一次尝试,我尝试了:

cat core | readelf -a

但是,readelf 似乎不支持来自标准输入的输入。

我也找到了这个 python elf 解析器,但乍一看它好像将整个 elf 读入内存: https://github.com/eliben/pyelftools

但是,如果需要,也许我可以将它们的实现用作流解析器的参考。

非常感谢!

【问题讨论】:

    标签: parsing streaming elf crash-dumps


    【解决方案1】:

    事实证明,Google 的 coredumper 记录了 ELF 核心文件格式: https://code.google.com/p/google-coredumper/source/browse/trunk/src/elfcore.c

    这段代码 sn-p 也很有帮助: http://emntech.blogspot.com/2012/08/printing-backtracestack-trace-using.html

    似乎堆栈跟踪包含在精灵的单个段中。解决方案是:

    1. 阅读精灵标题
    2. 查找 NT_PRSTATUS 类型的注释条目
    3. 从该条目中的寄存器获取栈顶地址
    4. 去那个地址
    5. 读取堆栈跟踪
    6. 忽略核心转储的其余部分

    在解析符号等方面我还有一些工作要做。但是,如果我的方法发生重大变化,我会编辑这个答案。虽然格式是否可以“流式传输”并不是真正要问的正确问题,但我确实找到了一个解决方案,让我无需将整个核心转储写入磁盘即可读取堆栈跟踪。

    编辑:

    根据How gdb reconstructs stacktrace for C++? 的答案,似乎在所有情况下重建堆栈都相当复杂。我相信这个问题的最终答案是,不,不可能从 ELF 核心中提取堆栈,并且 ELF 核心不是“可流式传输的”。

    我相信虽然堆有可能位于核心转储中并被删除。这将使堆栈保持完整,允许 gdb 仍然重建它。

    【讨论】:

    • 请注意,您找到的解决方案回溯解决方案仅适用于 32 位二进制文​​件,并且仅适用于未经优化或使用旧版本 GCC 编译的二进制文件。
    • @EmployedRussian - 您能否提供更多详细信息以说明为什么这不适用于 64 位?
    • @matthewtablet 回溯堆栈代码正在使用帧指针,默认情况下在 x86_64 上禁用并启用优化。使用较新版本的 GCC,帧指针也被禁用,同时优化 ix86(32 位)。没有帧指针的展开要复杂得多;你需要像 libunwind 这样的东西。
    • @EmployedRussian - 谢谢!这很有帮助。
    猜你喜欢
    • 1970-01-01
    • 2019-04-12
    • 2014-01-16
    • 2021-06-24
    • 1970-01-01
    • 1970-01-01
    • 2014-08-10
    • 1970-01-01
    • 2012-11-07
    相关资源
    最近更新 更多