核心文件包含生成它的命令。理想情况下,这将包括相应可执行文件的完整路径。例如:
$ file core.29529
core.29529: ELF 64-bit LSB core file x86-64, version 1 (SYSV), SVR4-style, from '/bin/sleep 60'
Running ldd
ELF 二进制文件上将显示它所依赖的库:
$ 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
仅基于此示例输出。