将大型核心文件转换为“minicore”文件

时间:2012-10-04 22:33:28

标签: c++ c linux debugging gdb

如何将核心文件减少到线程堆栈?

我希望能够在迷你核心上运行gdb thread apply all bt而不再需要

我正在处理大型(> 4GB)多线程Linux ELF核心文件,这些文件太大而无法回来进行分析。

我看到google-breakpad用于在进程崩溃时创建“minidump”。在google-breakpad中有两个实用程序core2mdminidump-2-core乍一看应该能够将核心文件转换为minidump格式,然后从minidump转换回核心文件堆栈信息。这个问题是core2md需要来自/ proc / $ PID /下的进程信息,而这不是我所拥有的。

2 个答案:

答案 0 :(得分:1)

可能你最好的办法是将google breakpad集成到你的Linux进程中,这样当崩溃发生时,google breakpad会记录崩溃,而不是创建核心文件的操作系统。这将为您提供所需的信息,然后您可以使用minidump_stackwalk转储调用堆栈(方便汇总大量崩溃),也可以使用minidump-2-core创建核心文件。

令人遗憾的是,Linux似乎没有一种有效的方法来创建只有线程堆栈内容的最小核心文件。这些文件(Windows世界中的小型转储)非常有用 - 它们具有非常高的信息/大小比例,可以轻松收集数百万个故障转储。

答案 1 :(得分:1)

您可以编写一个简单的程序,从核心文件中删除大部分数据。

核心文件由代表不同VMA的PT_LOAD程序标题条目组成:

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  NOTE           0x0000000000004b80 0x0000000000000000 0x0000000000000000
                 0x0000000000009064 0x0000000000000000  R      1
  LOAD           0x000000000000dbe4 0x0000000000400000 0x0000000000000000
                 0x0000000000000000 0x000000000009d000  R E    1
  LOAD           0x000000000000dbe4 0x000000000069c000 0x0000000000000000
                 0x0000000000004000 0x0000000000004000  RW     1
  LOAD           0x0000000000011be4 0x00000000006a0000 0x0000000000000000
                 0x0000000000004000 0x0000000000004000  RW     1
  LOAD           0x0000000000015be4 0x0000000001872000 0x0000000000000000
                 0x0000000000ed4000 0x0000000000ed4000  RW     1
  LOAD           0x0000000000ee9be4 0x00007f248c000000 0x0000000000000000
                 0x0000000000021000 0x0000000000021000  RW     1
  LOAD           0x0000000000f0abe4 0x00007f2490885000 0x0000000000000000
                 0x000000000001c000 0x000000000001c000  R      1
  LOAD           0x0000000000f26be4 0x00007f24908a1000 0x0000000000000000
                 0x000000000001c000 0x000000000001c000  R      1
[...]

PT_NOTE条目包含(除其他外)有关线程状态的信息:

Displaying notes found at file offset 0x00004b80 with length 0x00009064:
  Owner                 Data size       Description
  CORE                 0x00000088       NT_PRPSINFO (prpsinfo structure)

  [Thread #1]
  CORE                 0x00000150       NT_PRSTATUS (prstatus structure)
  CORE                 0x00000200       NT_FPREGSET (floating point registers)
  LINUX                0x00000440       NT_X86_XSTATE (x86 XSAVE extended state)
  CORE                 0x00000080       NT_SIGINFO (siginfo_t data)

  [other threads ...]

PT_NOTE处理

您希望保留此PT_NOTE程序标头条目。

此外,您可以从prstatus结构中提取堆栈指针:

struct elf_prstatus {
  [...]
  elf_gregset_t pr_reg;   /* GP registers */
  [...]
};

PT_LOAD处理

一旦从所有线程中提取了所有堆栈指针,就可以处理PT_LOAD条目:

  • 如果FileSize == 0,此程序头不占用核心文件中的任何内存,可以忽略;

  • 如果某个线程的堆栈指针位于虚拟内存的这个区域,这可能是一个堆栈,您可能需要保留它;

  • 否则,您可以将其从核心文件中删除(将其替换为带有FileSize == 0的程序标题条目。)

或者,您可能能够完全删除所有非堆栈区域的程序头条目。

创建自己的核心转储程序

另一个解决方案是编写一个核心转储器,直接生成它并在/proc/sys/kernel/core_pattern(man core)中注册。