c - 如何轻松打包分析核心转储所需的库(即 packcore)

标签 c linux gdb coredump hp-ux

HPUX 上可用的 GDB 版本有一个名为“packcore”的命令,该命令创建一个包含核心转储、可执行文件和所有库的 tarball。我发现这在尝试在不同机器上调试核心转储时非常有用。

在 Linux 机器上的 GDB 标准版本中是否有类似的命令?

我正在寻找一个简单的命令,当生产机器上出现问题时,不一定是开发人员的人也可以运行该命令。

最佳答案

核心文件包含生成它的命令。理想情况下,这将包括相应可执行文件的完整路径。例如:

$ file core.29529 
core.29529: ELF 64-bit LSB core file x86-64, version 1 (SYSV), SVR4-style, from '/bin/sleep 60'

在 ELF 二进制文件上运行 ldd 将显示它所依赖的库:

$ ldd /bin/sleep
linux-vdso.so.1 =>  (0x00007fff1d3ff000)
libc.so.6 => /lib64/libc.so.6 (0x0000003d3ce00000)
/lib64/ld-linux-x86-64.so.2 (0x0000003d3ca00000)

现在我知道了分析核心转储所需的可执行文件和库。

这里棘手的部分是从核心文件中提取可执行路径。似乎没有一个好的工具可以直接阅读此内容。数据以 prpsinfo 结构编码(来自 /usr/include/sys/procfs.h),您可以使用 readelf 找到数据的位置大小:

$ readelf -n core.29529
Notes at offset 0x00000468 with length 0x00000558:
  Owner         Data size       Description
  CORE          0x00000150      NT_PRSTATUS (prstatus structure)
  CORE          0x00000088      NT_PRPSINFO (prpsinfo structure)
  CORE          0x00000130      NT_AUXV (auxiliary vector)
  CORE          0x00000200      NT_FPREGSET (floating point registers)

...因此理论上可以编写一个代码片段来从该结构中提取命令行并以一种使整个过程更容易自动化的方式打印出来。当然,您可以只解析 file 的输出:

$ file core.29529  | sed "s/.*from '\([^']*\)'/\1/"
/bin/sleep 60

这就是所有部分。这是将所有内容组合在一起的起点:

#!/bin/sh

core=$1
exe=$(file $core  | sed "s/.*from '\([^']*\)'/\1/" | awk '{print $1}')

libs=$(
    ldd $exe |
    awk '
        /=> \// {print $3}
        ! /=>/ {print $1}
    '
    )

cat <<EOF | tar -cah -T- -f $1-all.tar.xz
$libs
$exe
EOF

对于我的示例,如果我将此脚本命名为 packcore 并通过 sleep 命令在核心文件上运行它,我会得到以下结果:

$ packcore core.29529
tar: Removing leading `/' from member names
$ tar -c -f core.29529-all.tar.xz
core.29529
lib64/libc.so.6
lib64/ld-linux-x86-64.so.2
bin/sleep

就目前而言,这个脚本非常脆弱;我仅根据此示例输出对 ldd 的输出做出了很多假设。

关于c - 如何轻松打包分析核心转储所需的库(即 packcore),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7557283/

相关文章:

c - 如何重新加载 gdbinit?

C 使用函数而不调用其参数

c - 具有位字段的结构中的哪些位是哪些?

c - 如何在 Windows 中使用 MSVC 从命令行构建 DLL

C : scanf skips the first iteration while taking char* inputs from user through scanf

linux - Tcl/Tk 小部件和 FocusOut 在 Linux 上没有按预期工作

linux - 为什么 gdb 回溯系统调用地址与系统调用表地址不同

linux - 故障安全 wget html 脚本? (当用户使用 ~\.wgetrc 时)

linux - PCI 驱动程序获取 MAC 地址

c++ - 有没有办法让 GDB 打印一些东西告诉我一行已经执行,而不停止?