forked from OSchip/llvm-project
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:
parent
302f83ac4e
commit
39aab4d606
|
@ -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]))
|
Binary file not shown.
Binary file not shown.
|
@ -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
|
||||
}
|
|
@ -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
|
Binary file not shown.
Binary file not shown.
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue