Fix thread/process ID reading from linux core files

Summary:
This also adds a basic smoke test for linux core file reading. I'm checking in the core files as
well, so that the tests can run on all platforms. With some tricks I was able to produce
reasonably-sized core files (~40K).

This fixes the first part of pr26322.

Reviewers: zturner

Subscribers: lldb-commits

Differential Revision: http://reviews.llvm.org/D18176

llvm-svn: 263628
This commit is contained in:
Pavel Labath 2016-03-16 09:19:57 +00:00
parent 302f83ac4e
commit 39aab4d606
8 changed files with 96 additions and 2 deletions

View File

@ -0,0 +1,45 @@
"""
Test basics of linux core file debugging.
"""
from __future__ import print_function
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
class LinuxCoreTestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
@skipIf(bugnumber="llvm.org/pr26947")
@no_debug_info_test
def test_i386(self):
"""Test that lldb can read the process information from an i386 linux core file."""
self.do_test("i386", 32306)
@no_debug_info_test
def test_x86_64(self):
"""Test that lldb can read the process information from an x86_64 linux core file."""
self.do_test("x86_64", 32259)
def do_test(self, arch, pid):
target = self.dbg.CreateTarget(arch + ".out")
process = target.LoadCore(arch + ".core")
self.assertTrue(process, PROCESS_IS_VALID)
self.assertEqual(process.GetNumThreads(), 1)
self.assertEqual(process.GetProcessID(), pid)
thread = process.GetSelectedThread()
self.assertTrue(thread)
self.assertEqual(thread.GetThreadID(), pid)
backtrace = ["bar", "foo", "_start"]
self.assertEqual(thread.GetNumFrames(), len(backtrace))
for i in range(len(backtrace)):
frame = thread.GetFrameAtIndex(i)
self.assertTrue(frame)
self.assertEqual(frame.GetFunctionName(), backtrace[i])
self.assertEqual(frame.GetLineEntry().GetLine(),
line_number("main.c", "Frame " + backtrace[i]))
self.assertEqual(frame.FindVariable("F").GetValueAsUnsigned(), ord(backtrace[i][0]))

View File

@ -0,0 +1,17 @@
static void bar(char *boom)
{
char F = 'b';
*boom = 47; // Frame bar
}
static void foo(char *boom, void (*boomer)(char *))
{
char F = 'f';
boomer(boom); // Frame foo
}
void _start(void)
{
char F = '_';
foo(0, bar); // Frame _start
}

View File

@ -0,0 +1,32 @@
#! /bin/bash
set -e -x
if grep -q '^|' </proc/sys/kernel/core_pattern; then
cat <<EOF
Your system uses a crash report tool ($(cat /proc/sys/kernel/core_pattern)). Core files
will not be generated. Please reset /proc/sys/kernel/core_pattern (requires root
privileges) to enable core generation.
EOF
exit 1
fi
ulimit -c 1000
real_limit=$(ulimit -c)
if [ $real_limit -lt 100 ]; then
cat <<EOF
Unable to increase the core file limit. Core file may be truncated!
To fix this, increase HARD core file limit (ulimit -H -c 1000). This may require root
privileges.
EOF
fi
${CC:-cc} -nostdlib -static -g $CFLAGS main.c -o a.out
cat <<EOF
Executable file is in a.out.
Core file will be saved according to pattern $(cat /proc/sys/kernel/core_pattern).
EOF
ulimit -s 8 # Decrease stack size to 8k => smaller core files.
exec ./a.out

View File

@ -559,11 +559,10 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *
have_prstatus = true;
prstatus.Parse(note_data, arch);
thread_data->signo = prstatus.pr_cursig;
thread_data->tid = prstatus.pr_pid;
header_size = ELFLinuxPrStatus::GetSize(arch);
len = note_data.GetByteSize() - header_size;
thread_data->gpregset = DataExtractor(note_data, header_size, len);
// FIXME: Obtain actual tid on Linux
thread_data->tid = m_thread_data.size();
break;
case NT_FPREGSET:
thread_data->fpregset = note_data;
@ -572,6 +571,7 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *
have_prpsinfo = true;
prpsinfo.Parse(note_data, arch);
thread_data->name = prpsinfo.pr_fname;
SetID(prpsinfo.pr_pid);
break;
case NT_AUXV:
m_auxv = DataExtractor(note_data);