Patch to support ELF coredumps

Hi,

I herewith attached a patch to support ELF coredumps.
Currently it works for Linux X86-64 core files.
Please commit it.

Here is the output of a test program

$Debug+Asserts/bin/lldb ~/test/a.out -c ~/test/core
Core file ‘/mts/home3/jacobs/test/core’ (x86_64) was loaded.
Process 0 stopped

  • thread #1: tid = 0x0000, 0x00000000004004c4 a.outfunction4(arg=0) + 16 at test.c:4, stop reason = signal SIGSEGV frame #0: 0x00000000004004c4 a.outfunction4(arg=0) + 16 at test.c:4
    1 void function4(unsigned int arg)
    2 {
    3 char *local = 0;
    → 4 *local = 0;
    5 }
    6 void function3()
    7 {
    bt
  • thread #1: tid = 0x0000, 0x00000000004004c4 a.outfunction4(arg=0) + 16 at test.c:4, stop reason = signal SIGSEGV frame #0: 0x00000000004004c4 a.outfunction4(arg=0) + 16 at test.c:4
    frame #1: 0x00000000004004d7 a.outfunction3 + 11 at test.c:8 frame #2: 0x00000000004004e7 a.outfunction2(arg=4195559) + 11 at test.c:11
    frame #3: 0x00000000004004f7 a.outfunction1(arg1=0, arg2=140736328348032, str=0x00000000004004e7) + 3 at test.c:15 frame #4: 0x0000000000400507 a.outfunction1(arg1=0, arg2=140736328348048, str=0x00000000004004f7) + 19 at test.c:15
    frame #5: 0x00007fbcdfe6c76d libc.so.6__libc_start_main + 237 frame #6: 0x00000000004003f9 a.out_start + 41

The following may be used as commit log:

Added Process plugin to support ELF coredump files.
Added member functions in ObjectFileELF to access segment headers and data.
Modified POSIX dynamic loader plugin to get AUXV data from core files if core-file is used.
Modified Linux Process plugin so that it will skip handling core files(CanDebug()).

Regards,
Samuel

elf-core.diff (43.5 KB)

That is great that this works, but this doesn't compile on MacOSX. The main issue is that in RegisterContext_x86_64.h you are conditionally compiling in the GPR structure definition with:

#ifdef __FreeBSD__
#include "Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h"
#endif

#ifdef __linux__
#include "Plugins/Process/Linux/RegisterContextLinux_x86_64.h"
#endif

This ELF core plug-in should not be tied to the system on which it is compiled. We will need to make it more flexible so it can handle a core from either system.

The Mach Core plug-in makes the ObjectFileMachO produce the thread register context in:

lldb::RegisterContextSP
ThreadMachCore::CreateRegisterContextForFrame (StackFrame *frame)
{
    lldb::RegisterContextSP reg_ctx_sp;
    uint32_t concrete_frame_idx = 0;
    
    if (frame)
        concrete_frame_idx = frame->GetConcreteFrameIndex ();

    if (concrete_frame_idx == 0)
    {
        if (!m_thread_reg_ctx_sp)
        {
            ProcessSP process_sp (GetProcess());
            
            ObjectFile *core_objfile = static_cast<ProcessMachCore *>(process_sp.get())->GetCoreObjectFile ();
            if (core_objfile)
                m_thread_reg_ctx_sp = core_objfile->GetThreadContextAtIndex (GetID(), *this);
        }
        reg_ctx_sp = m_thread_reg_ctx_sp;
    }
    else if (m_unwinder_ap.get())
    {
        reg_ctx_sp = m_unwinder_ap->CreateRegisterContextForFrame (frame);
    }
    return reg_ctx_sp;
}

Note that at frame zero (concrete_frame_idx == 0) it asks the object file create the registers with: GetThreadContextAtIndex().

Each object file format, like ELF, should know how the registers contexts for core files are saved and should be able to reproduce a register context for a thread. So I would modify ObjectFileELF to contain a virtual instance of:

lldb::RegisterContextSP
ObjectFileELF::CreateRegisterContextForFrame (StackFrame *frame);

Sorry about that. I compiled it only on a x86-64 Linux machine.

I will upload an updated diff soon.

Each object file format, like ELF, should know how the registers contexts for core files are saved and should be able to reproduce a register context for a thread. So I would modify ObjectFileELF to contain a virtual >instance of:

ELF core file’s register arrangement is depends on OS, so defining it ObjectFileELF has the same problem.

From quick look at the code, modifying “source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp” to have both FreeBSD and Linux RegiserInfo structures should solve this.However this modification would touch lot of places and I prefer this modification go as separate patch.

Another approach is copying RegisterContext_x86_64.cpp:g_register_infos and related macros to elf-core plugin but I dont want to go in this route.

So if you agree I will modify the current patch to include elf-core plugin only on Linux and FreeBSD platform.

In the 2nd phase I will send patch to include elf-core in all platforms by modifying “POSIX/RegisterContext_x86_64.cpp”.

Thanks

Samuel

Is there anyway to check the byte size of the thread context and do something intelligent so we can correctly identify the register context to be used?

The ELF file contains a machine type which isn't much help in identifying exactly what kind of machine this was generated on. Especially for ARM we would have trouble identifying the correct register context for a armv5, armv6 or armv7 core, each which might also contain completely different floating pointer registers.

I would like to be able to read ELF core files on MacOSX so I can help diagnose issues when people file bugs, so I would really like to get this working prior to checkin if possible. The ELF object file parser should be able to include the two register contexts and maybe look at the sizes (hopefully they aren't the same) and "do the right thing", no?

Greg

Is there anyway to check the byte size of the thread context and do
something intelligent so we can correctly identify the register context to
be used?

The current idea I have to differentiate FreeBSD/Linux core is to use
ELFHeader's OS/ABI field or to useELFNote section's owner field
Linux core output
$eu-readelf -n test/core
Note segment of 1368 bytes at offset 0x3f8:
  Owner Data size Type
  CORE 336 PRSTATUS
  CORE 136 PRPSINFO
  CORE 304 AUXV

FreeBSD core's output
$eu-readelf -h a.out.core | grep OS
  OS/ABI: FreeBSD

$eu-readelf -n a.out.core
Note segment of 960 bytes at offset 0x200:
  Owner Data size Type
  FreeBSD 120 PRPSINFO
  FreeBSD 224 PRSTATUS
  FreeBSD 512 FPREGSET
  FreeBSD 24 GWINDOWS

But the real problem is creating another class which abstracts and handles
the two or more ABI.

The ELF file contains a machine type which isn't much help in identifying
exactly what kind of machine this was generated on. Especially for ARM we
would have trouble identifying the correct register context for a armv5,
armv6 or armv7 core, each which might also contain completely different
floating pointer registers.

Yea - I havent looked at ARM cores. If you have ELF ARM cores please attach
readelf -a output.

I would like to be able to read ELF core files on MacOSX so I can help
diagnose issues when people file bugs, so I would really like to get this
working prior to checkin if possible. The ELF object file parser should be
able to include the two register contexts and maybe look at the sizes
(hopefully they aren't the same) and "do the right thing", no?

I will take a look again.

Thanks
Samuel