Convert large core files to “minicore” files

时光总嘲笑我的痴心妄想 提交于 2021-02-07 18:40:19

问题


How do I reduce core files to just the threads' stacks?

I want to be able to run gdb thread apply all bt on the mini core and no more

I'm dealing with large (>4GB) multi-threaded Linux ELF core files that are too big to get back for analysis.

I've see google-breakpad which is meant to create a "minidump" when a process crashes. In google-breakpad there are two utilities core2md and minidump-2-core which at first glance should be able to convert a core file to minidump format, and then back to a core file from the minidump with just the stack information. The problem with this is that core2md requires the process information from under /proc/$PID/ and that's not something I have.


回答1:


Probably your best bet is to integrate google breakpad into your Linux process so that when a crash occurs it is google breakpad recording the crash instead of the OS creating a core file. This will get you the information that you want, and then you can either use minidump_stackwalk to dump call stacks (handy for summarizing lots of crashes) or you can use minidump-2-core to create a core file.

It is unfortunate that Linux does not seem to have an effective way to create minimal core files with just the contents of the threads' stacks. These files (minidumps in the Windows world) are extremely useful -- they have a very high information-to-size ratio which allows easy collection of millions of crash dumps.




回答2:


You can probably write a simple program which remove much of the data from the core file.

The core file is made of PT_LOAD program header entries representing the different VMAs:

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
[...]

The PT_NOTE entry contains (among other things) informations about the thread state:

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 handling

You want to keep this PT_NOTE program header entry.

Moreover you can extract the stack pointers from the prstatus structures:

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

PT_LOAD handling

Once you have extracted all the stack pointers from all threads, you can process the PT_LOAD entries:

  • if FileSize == 0, this program header does not consume any memory in the core file and can be ignored;

  • if the stack pointer of some thread is in this region of virtual memory, this is probably a stack and you might need to keep it;

  • otherwise, you might be able to remove it from the core file (replace it with a program header entry with FileSize == 0).

Alternatively, you might be able to completely remove the program header entries of all the non-stack regions.

Creating you own core dumper

Another solution would be to write a core dumper which generated this directly and register in /proc/sys/kernel/core_pattern (man core).



来源:https://stackoverflow.com/questions/12737025/convert-large-core-files-to-minicore-files

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!