7

在我关于手动生成核心转储文件的问题之后,我决定深入研究它并弄脏我的手。

我能够构建基本的核心转储结构并将死程序的内存重新放入大 LOAD 部分中的核心转储中。在 GDB 中调试时,我的变量又回来了,这没问题。棘手的部分来了,我如何让 GDB 检索有关程序崩溃时所在位置的信息。

我知道核心转储的注释部分包含此信息(cpu 寄存器等)。这是objdump -h为“真实”核心转储提供的内容:

core.28339:     file format elf32-i386

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 note0         000001e8  00000000  00000000  000000f4  2**0
                  CONTENTS, READONLY
  1 .reg/28339    00000044  00000000  00000000  00000150  2**2
                  CONTENTS
  2 .reg          00000044  00000000  00000000  00000150  2**2
              CONTENTS
  3 .auxv         000000a0  00000000  00000000  0000023c  2**2
              CONTENTS
  4 load1a        00001000  08010000  00000000  00001000  2**12
              CONTENTS, ALLOC, LOAD, READONLY, CODE
  .. other load sections ...

感谢readelf ,我发现那些 .reg 部分包含从某些结构映射的数据:

Notes at offset 0x000000f4 with length 0x000001e8:
  Owner     Data size   Description
  CORE      0x00000090  NT_PRSTATUS (prstatus structure)
  CORE      0x0000007c  NT_PRPSINFO (prpsinfo structure)
  CORE      0x000000a0  NT_AUXV (auxiliary vector)

有人可以给我说明一下注释部分的结构吗?我尝试将这些结构直接写入我的文件,但它不起作用,我显然在这里遗漏了一些东西。我查看了Google Coredumper 代码并从中提取了一些内容,但编写注释部分并不是那么简单,欢迎任何有关其确切内容和格式的详细信息。

编辑#1:跟随第一条评论

我发现我的 Elf 文件的结构应该如下:

  • 精灵头 ElfW(Ehdr)
  • 程序头(Ehdr.e_phnum 乘以 ElfW(Phdr)),这里我基本上使用了一个 PT_NOTE 和一个 PT_LOAD 头
  • 注意部分:
    • 节的标题 (ElfW(Nhdr))
    • 部分的名称(.n_namesz 长)
    • 部分的数据(.n_descsz 长)
  • 包含我所有程序内存的程序部分

然后我必须放 3 条笔记记录,一条用于prstatus,一条用于prpsinfo,一条用于辅助向量

这似乎是正确的方法,因为readelf给我的输出与我上面通过真正的核心转储得到的输出相似。

编辑#2:得到正确的结构后

我现在正在为组成笔记记录的不同结构而苦苦挣扎。

这是在我的核心转储上运行eu-readelf --notes时得到的结果:

Note segment of 540 bytes at offset 0x74:
  Owner          Data size  Type
  CORE                 336  PRSTATUS
  CORE                 136  PRPSINFO
  CORE                   8  AUXV
    NULL

这是在真实核心转储上运行相同命令时得到的结果:

Note segment of 488 bytes at offset 0xf4:
  Owner          Data size  Type
  CORE                 144  PRSTATUS
    info.si_signo: 11, info.si_code: 0, info.si_errno: 0, cursig: 11
    sigpend: <>
    sighold: <>
    pid: 28339, ppid: 41446, pgrp: 28339, sid: 41446
    utime: 0.000000, stime: 0.000000, cutime: 0.000000, cstime: 0.000000
    orig_eax: -1, fpvalid: 0
    ebx:             -1  ecx:              0  edx:              0
    esi:              0  edi:              0  ebp:     0xffb9fcbc
    eax:             -1  eip:     0x08014b26  eflags:  0x00010286
    esp:     0xffb9fcb4
    ds: 0x002b  es: 0x002b  fs: 0x0000  gs: 0x0000  cs: 0x0023  ss: 0x002b
  CORE                 124  PRPSINFO
    state: 0, sname: R, zomb: 0, nice: 0, flag: 0x00400400
    uid: 9432, gid: 6246, pid: 28339, ppid: 41446, pgrp: 28339, sid: 41446
    fname: pikeos_app, psargs: ./pikeos_app 
  CORE                 160  AUXV
    SYSINFO: 0xf7768420
    SYSINFO_EHDR: 0xf7768000
    HWCAP: 0xbfebfbff  <fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe>
    PAGESZ: 4096
    CLKTCK: 100
    PHDR: 0x8010034
    PHENT: 32
    PHNUM: 2
    BASE: 0
    FLAGS: 0
    ENTRY: 0x80100be
    UID: 9432
    EUID: 9432
    GID: 6246
    EGID: 6246
    SECURE: 0
    RANDOM: 0xffb9ffab
    EXECFN: 0xffba1feb
    PLATFORM: 0xffb9ffbb
    NULL

有人对为什么我的笔记记录没有正确阅读有任何线索或解释吗?我认为这可能是由于偏移量不正确,但是为什么要正确列出记录呢?

谢谢 !

4

3 回答 3

4

前段时间在我将 CRIU 图像转换为核心转储的项目中遇到了同样的麻烦。它完全用python编写(甚至elf结构都在ctypes中),因此可以用作指南。请参阅https://github.com/efiop/criu-coredump。也就是说,可以在此处查看所有内容的结构https://github.com/efiop/criu-coredump/blob/master/criu_coredump/core_dump.py

于 2015-09-27T13:24:55.570 回答
1

有人可以指导我说明“注释”部分的结构吗?

笔记部分是可变大小的笔记记录的串联。每条笔记记录都以ElfW(Nhdr)结构开头,然后是(可变大小)名称(长度为.n_namesz,已填充,因此磁盘上名称的总大小可被 4 整除)和数据(长度为.n_descsz,类似填充)。

于 2013-07-31T15:01:48.473 回答
1

经过一些测试,我想通了,回答任何寻找此信息的人:

有人可以确认我正在以正确的方式构建我的 Elf 文件吗?

是的。

由于 GDB 正在接受该文件,这似乎是正确的做法。readelf -a显示的结果显示正确的结构,到目前为止很好。

我不确定应该将数据(注释和程序部分)放在我的文件中的哪个位置:是否有强制命令,或者这是我的程序头偏移量,它定义了数据的位置?

给定的偏移量Phdr.p_offset应该指向数据在 Elf 文件中的位置。它们从文件的最开头开始。

例如 :

程序头的 p_offsetPT_NOTE应设置为sizeof(ElfW(Ehdr)) + ehdr.e_phnum*sizeof(ElfW(Phdr)). ehdr.e_phnum是 Elf 文件中存在的程序头的数量。

对于PT_LOAD程序标题,这有点长,因为我们还必须添加所有注释部分的长度。对于带有包含NT_PRSTATUS,NT_PRPSINFONT_AUXV部分的注释段的“标准”核心转储,PT_LOAD 数据 ( Phdr.p_offset) 的偏移量将是:

sizeof(ElfW(Ehdr)) + ehdr.e_phnum*sizeof(ElfW(Phdr))
+ sizeof(ElfW(Nhdr)) + sizeof(name_of_section) + sizeof(struct prstatus)
+ sizeof(ElfW(Nhdr)) + sizeof(name_of_section) + sizeof(struct prpsinfo)
+ sizeof(ElfW(Nhdr)) + sizeof(name_of_section) + sizeof(struct auxv_t)
于 2013-08-01T09:25:53.797 回答