Skip to content

Commit

Permalink
Fix thread/process ID reading from linux core files
Browse files Browse the repository at this point in the history
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
  • Loading branch information
labath committed Mar 16, 2016
1 parent 302f83a commit 39aab4d
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 2 deletions.
@@ -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.
4 changes: 2 additions & 2 deletions lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
Expand Up @@ -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;
Expand All @@ -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);
Expand Down

0 comments on commit 39aab4d

Please sign in to comment.