如何将核心文件减少到线程堆栈?
我希望能够在迷你核心上运行gdb thread apply all bt
而不再需要
我正在处理大型(> 4GB)多线程Linux ELF核心文件,这些文件太大而无法回来进行分析。
我看到google-breakpad用于在进程崩溃时创建“minidump”。在google-breakpad中有两个实用程序core2md
和minidump-2-core
乍一看应该能够将核心文件转换为minidump格式,然后从minidump转换回核心文件堆栈信息。这个问题是core2md需要来自/ proc / $ PID /下的进程信息,而这不是我所拥有的。
答案 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
程序标头条目。
此外,您可以从prstatus
结构中提取堆栈指针:
struct elf_prstatus {
[...]
elf_gregset_t pr_reg; /* GP registers */
[...]
};
一旦从所有线程中提取了所有堆栈指针,就可以处理PT_LOAD
条目:
如果FileSize == 0
,此程序头不占用核心文件中的任何内存,可以忽略;
如果某个线程的堆栈指针位于虚拟内存的这个区域,这可能是一个堆栈,您可能需要保留它;
否则,您可以将其从核心文件中删除(将其替换为带有FileSize == 0
的程序标题条目。)
或者,您可能能够完全删除所有非堆栈区域的程序头条目。
另一个解决方案是编写一个核心转储器,直接生成它并在/proc/sys/kernel/core_pattern
(man core)中注册。