如何从核心转储文件中提取 AT_EXECFN

Posted

技术标签:

【中文标题】如何从核心转储文件中提取 AT_EXECFN【英文标题】:how to extract AT_EXECFN from a coredump file 【发布时间】:2021-05-14 05:34:02 【问题描述】:

我需要从 coredump 文件中提取 AT_EXECFN 的值。对于那些不知道这个值的人是the auxiliary vector 的一部分。在运行过程中获取此值非常简单,只需使用getauxval,但是当您拥有 ELF 核心转储文件时,我找不到任何有关如何执行此操作的信息。 I can find the NT_AUXV section of this file,但我不知道如何找到AT_EXECFN 指向的确切字符串。假设我在核心转储中找到了AT_EXECFN。根据this,我将获得一个带有 ann 地址的结构,其中存储了实际值。我的问题是如何在 coredump 文件中找到这个地址?

【问题讨论】:

【参考方案1】:

这是一个例子:

int main()  abort(); 

gcc -w -O2 t.c && ulimit -c unlimited && ./a.out
Aborted (core dumped)

首先我们可以看一下 GDB:

gdb -q ./a.out core
Reading symbols from ./a.out...
(No debugging symbols found in ./a.out)
[New LWP 86]
Core was generated by `./a.out'.
Program terminated with signal SIGABRT, Aborted.
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
50      ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.

(gdb) info auxv
33   AT_SYSINFO_EHDR      System-supplied DSO's ELF header 0x7ffd4037a000
16   AT_HWCAP             Machine-dependent CPU capability hints 0x178bfbff
...
31   AT_EXECFN            File name of executable        0x7ffd40374ff0 "./a.out"
15   AT_PLATFORM          String identifying platform    0x7ffd403739c9 "x86_64"
0    AT_NULL              End of vector                  0x0

这证明该信息实际上存在于core 中,并且还显示了预期的值。

因此,步骤是:

读取/解码NT_AUXV 注释,直到找到带有.a_type == AT_EXECFN 的条目(31)。找到指向字符串的指针($addr,在这里你会找到0x7ffd40374ff0)。

使用eu-readelf -n core 有助于验证您正在读取预期值。这是输出:

  CORE                 320  AUXV
    SYSINFO_EHDR: 0x7ffd4037a000
    HWCAP: 0x178bfbff  <fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht>
...
    EXECFN: 0x7ffd40374ff0
    PLATFORM: 0x7ffd403739c9
    NULL
使用.p_type == PT_LOAD 遍历所有程序头,直到找到带有.p_vaddr &lt;= $addr$addr &lt; .p_vaddr + .p_memsz 的程序头(即“覆盖”所需地址的LOAD 段)。在上述情况下,就是这个条目:
Program Headers:
  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
...
  LOAD           0x016000 0x00007ffd40354000 0x0000000000000000 0x021000 0x021000 RW  0x1000
...

最后您可以在core 文件.p_offset + $addr - .p_vaddr 中找到字符串的位置。使用上述数字,我们希望字符串位于文件中的偏移量 0x016000 + 0x7ffd40374ff0 - 0x00007ffd40354000 = 225264 字节处。

我们确实在那里找到了它:

dd status=none bs=1 skip=225264 count=10 if=core | xxd -g1
00000000: 2e 2f 61 2e 6f 75 74 00 00 00                    ./a.out...

【讨论】:

我不知道您是如何确定路径的实际地址的,换句话说,您是如何确定.p_offset + $addr - .p_vaddr 的?我一直在阅读文档,但无法理解您是如何得出这个公式的。 @flashburn 对不起,我不明白这个问题:我使用的所有数字:EXECFN == 0x7ffd40374ff0.p_offset == 0x016000.p_vaddr == 0x00007ffd40354000 都在答案中可见。 没关系。我想我明白了。我花了一些时间才弄清楚你是如何计算路径地址的,但我的意思是.p_offset + $addr - .p_vaddr。我不明白为什么这个公式有效,但后来我想通了。感谢您提供帮助,我真的很感激。

以上是关于如何从核心转储文件中提取 AT_EXECFN的主要内容,如果未能解决你的问题,请参考以下文章

如何从正在运行的应用程序的堆转储中提取 java 类定义?

如何调试从执行发布文件生成的核心转储文件?

如何从 linux 内核核心转储中找到“HZ”值?

如何从核心转储的反汇编函数中找到局部变量的地址并显示其值

PHP:如何从字符串转储中提取 JSON 字符串

如何使用 VSCode 调试 Linux 核心转储?