summaryrefslogtreecommitdiffstats
path: root/lldb/packages/Python/lldbsuite
diff options
context:
space:
mode:
authorMichal Gorny <mgorny@gentoo.org>2019-03-08 21:10:43 +0000
committerMichal Gorny <mgorny@gentoo.org>2019-03-08 21:10:43 +0000
commitc12f159788dcc791e4a415352031fb761f31c3ec (patch)
tree6bbcdf3a3a43fd093a4d92c6b9a01205acf01946 /lldb/packages/Python/lldbsuite
parent7a462ab7ae7d4fe45eace5942519bf305391e11f (diff)
downloadbcm5719-llvm-c12f159788dcc791e4a415352031fb761f31c3ec.tar.gz
bcm5719-llvm-c12f159788dcc791e4a415352031fb761f31c3ec.zip
[lldb] [Process] Add proper support for NetBSD core files with threads
Improve the support for processing NetBSD cores. Fix reading process identifier, thread information and associating the terminating signal with the correct thread. Includes test cases for single-threaded program receiving SIGSEGV, and two dual-threaded programs: one where thread receives the signal, and the other one when the whole process is signalled. Differential Revision: https://reviews.llvm.org/D32149 llvm-svn: 355736
Diffstat (limited to 'lldb/packages/Python/lldbsuite')
-rwxr-xr-xlldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.amd64bin0 -> 13616 bytes
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.amd64.corebin0 -> 101872 bytes
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.c14
-rwxr-xr-xlldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.amd64bin0 -> 15816 bytes
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.amd64.corebin0 -> 121208 bytes
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.c32
-rwxr-xr-xlldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.amd64bin0 -> 15456 bytes
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.amd64.corebin0 -> 121192 bytes
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.c30
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/GNUmakefile15
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/TestNetBSDCore.py225
11 files changed, 316 insertions, 0 deletions
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.amd64 b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.amd64
new file mode 100755
index 00000000000..56fa077bd6a
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.amd64
Binary files differ
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.amd64.core b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.amd64.core
new file mode 100644
index 00000000000..d2d40500455
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.amd64.core
Binary files differ
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.c b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.c
new file mode 100644
index 00000000000..972e9678af5
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.c
@@ -0,0 +1,14 @@
+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 main(void) {
+ char F = 'm';
+ foo(0, bar); // Frame main
+}
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.amd64 b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.amd64
new file mode 100755
index 00000000000..00f61dfce84
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.amd64
Binary files differ
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.amd64.core b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.amd64.core
new file mode 100644
index 00000000000..f9c2b562fba
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.amd64.core
Binary files differ
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.c b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.c
new file mode 100644
index 00000000000..ce583aaada9
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.c
@@ -0,0 +1,32 @@
+#include <lwp.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+
+static void bar() {
+ char F = 'b';
+ kill(getpid(), SIGSEGV); // Frame bar
+}
+
+static void foo(void (*boomer)()) {
+ char F = 'f';
+ boomer(); // Frame foo
+}
+
+static void lwp_main(void *unused) {
+ char F = 'l';
+ foo(bar); // Frame lwp_main
+}
+
+int main(int argc, char **argv) {
+ ucontext_t uc;
+ lwpid_t lid;
+ static const size_t ssize = 16 * 1024;
+ void *stack;
+
+ stack = malloc(ssize);
+ _lwp_makecontext(&uc, lwp_main, NULL, NULL, stack, ssize);
+ _lwp_create(&uc, 0, &lid);
+ _lwp_wait(lid, NULL);
+}
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.amd64 b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.amd64
new file mode 100755
index 00000000000..d304de160f0
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.amd64
Binary files differ
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.amd64.core b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.amd64.core
new file mode 100644
index 00000000000..5f68687c56e
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.amd64.core
Binary files differ
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.c b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.c
new file mode 100644
index 00000000000..1cd86631edd
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.c
@@ -0,0 +1,30 @@
+#include <lwp.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+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 lwp_main(void *unused) {
+ char F = 'l';
+ foo(0, bar); // Frame lwp_main
+}
+
+int main(int argc, char **argv) {
+ ucontext_t uc;
+ lwpid_t lid;
+ static const size_t ssize = 16 * 1024;
+ void *stack;
+
+ stack = malloc(ssize);
+ _lwp_makecontext(&uc, lwp_main, NULL, NULL, stack, ssize);
+ _lwp_create(&uc, 0, &lid);
+ _lwp_wait(lid, NULL);
+}
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/GNUmakefile b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/GNUmakefile
new file mode 100644
index 00000000000..62c719d3d2f
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/GNUmakefile
@@ -0,0 +1,15 @@
+ARCH = $(shell uname -m)
+PROGRAMS = 1lwp_SIGSEGV 2lwp_t2_SIGSEGV 2lwp_process_SIGSEGV
+EXECS = $(patsubst %,%.$(ARCH),$(PROGRAMS))
+CORES = $(patsubst %,%.core,$(EXECS))
+
+all: $(CORES) $(EXECS)
+clean:
+ rm -f $(CORES) $(EXECS)
+
+%.core: %
+ sysctl -w proc.$$$$.corename=$@; ulimit -s 16; ! ./$<
+%.$(ARCH): %.c
+ $(CC) -o $@ -g $<
+
+.PHONY: all clean
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/TestNetBSDCore.py b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/TestNetBSDCore.py
new file mode 100644
index 00000000000..ca234ecc1f6
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/TestNetBSDCore.py
@@ -0,0 +1,225 @@
+"""
+Test NetBSD core file debugging.
+"""
+
+from __future__ import division, print_function
+
+import shutil
+import signal
+import struct
+import os
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class NetBSDCoreCommonTestCase(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ def setUp(self):
+ super(NetBSDCoreCommonTestCase, self).setUp()
+ self._initial_platform = lldb.DBG.GetSelectedPlatform()
+
+ def tearDown(self):
+ lldb.DBG.SetSelectedPlatform(self._initial_platform)
+ super(NetBSDCoreCommonTestCase, self).tearDown()
+
+ def check_memory_regions(self, process, region_count):
+ region_list = process.GetMemoryRegions()
+ self.assertEqual(region_list.GetSize(), region_count)
+
+ region = lldb.SBMemoryRegionInfo()
+
+ # Check we have the right number of regions.
+ self.assertEqual(region_list.GetSize(), region_count)
+
+ # Check that getting a region beyond the last in the list fails.
+ self.assertFalse(
+ region_list.GetMemoryRegionAtIndex(
+ region_count, region))
+
+ # Check each region is valid.
+ for i in range(region_list.GetSize()):
+ # Check we can actually get this region.
+ self.assertTrue(region_list.GetMemoryRegionAtIndex(i, region))
+
+ # Every region in the list should be mapped.
+ self.assertTrue(region.IsMapped())
+
+ # Test the address at the start of a region returns it's enclosing
+ # region.
+ begin_address = region.GetRegionBase()
+ region_at_begin = lldb.SBMemoryRegionInfo()
+ error = process.GetMemoryRegionInfo(begin_address, region_at_begin)
+ self.assertEqual(region, region_at_begin)
+
+ # Test an address in the middle of a region returns it's enclosing
+ # region.
+ middle_address = (region.GetRegionBase() +
+ region.GetRegionEnd()) // 2
+ region_at_middle = lldb.SBMemoryRegionInfo()
+ error = process.GetMemoryRegionInfo(
+ middle_address, region_at_middle)
+ self.assertEqual(region, region_at_middle)
+
+ # Test the address at the end of a region returns it's enclosing
+ # region.
+ end_address = region.GetRegionEnd() - 1
+ region_at_end = lldb.SBMemoryRegionInfo()
+ error = process.GetMemoryRegionInfo(end_address, region_at_end)
+ self.assertEqual(region, region_at_end)
+
+ # Check that quering the end address does not return this region but
+ # the next one.
+ next_region = lldb.SBMemoryRegionInfo()
+ error = process.GetMemoryRegionInfo(
+ region.GetRegionEnd(), next_region)
+ self.assertNotEqual(region, next_region)
+ self.assertEqual(
+ region.GetRegionEnd(),
+ next_region.GetRegionBase())
+
+ # Check that query beyond the last region returns an unmapped region
+ # that ends at LLDB_INVALID_ADDRESS
+ last_region = lldb.SBMemoryRegionInfo()
+ region_list.GetMemoryRegionAtIndex(region_count - 1, last_region)
+ end_region = lldb.SBMemoryRegionInfo()
+ error = process.GetMemoryRegionInfo(
+ last_region.GetRegionEnd(), end_region)
+ self.assertFalse(end_region.IsMapped())
+ self.assertEqual(
+ last_region.GetRegionEnd(),
+ end_region.GetRegionBase())
+ self.assertEqual(end_region.GetRegionEnd(), lldb.LLDB_INVALID_ADDRESS)
+
+ def check_state(self, process):
+ with open(os.devnull) as devnul:
+ # sanitize test output
+ self.dbg.SetOutputFileHandle(devnul, False)
+ self.dbg.SetErrorFileHandle(devnul, False)
+
+ self.assertTrue(process.is_stopped)
+
+ # Process.Continue
+ error = process.Continue()
+ self.assertFalse(error.Success())
+ self.assertTrue(process.is_stopped)
+
+ # Thread.StepOut
+ thread = process.GetSelectedThread()
+ thread.StepOut()
+ self.assertTrue(process.is_stopped)
+
+ # command line
+ self.dbg.HandleCommand('s')
+ self.assertTrue(process.is_stopped)
+ self.dbg.HandleCommand('c')
+ self.assertTrue(process.is_stopped)
+
+ # restore file handles
+ self.dbg.SetOutputFileHandle(None, False)
+ self.dbg.SetErrorFileHandle(None, False)
+
+ def check_backtrace(self, thread, filename, backtrace):
+ self.assertGreaterEqual(thread.GetNumFrames(), len(backtrace))
+ src = filename.rpartition('.')[0] + '.c'
+ for i in range(len(backtrace)):
+ frame = thread.GetFrameAtIndex(i)
+ self.assertTrue(frame)
+ self.assertEqual(frame.GetFunctionName(), backtrace[i])
+ if not backtrace[i].startswith('_'):
+ self.assertEqual(frame.GetLineEntry().GetLine(),
+ line_number(src, "Frame " + backtrace[i]))
+ self.assertEqual(
+ frame.FindVariable("F").GetValueAsUnsigned(), ord(
+ backtrace[i][0]))
+
+ def do_test(self, filename, pid, region_count):
+ target = self.dbg.CreateTarget(filename)
+ process = target.LoadCore(filename + ".core")
+
+ self.assertTrue(process, PROCESS_IS_VALID)
+ self.assertEqual(process.GetNumThreads(), self.THREAD_COUNT)
+ self.assertEqual(process.GetProcessID(), pid)
+
+ self.check_state(process)
+
+ self.check_stack(process, pid, filename)
+
+ self.check_memory_regions(process, region_count)
+
+ self.dbg.DeleteTarget(target)
+
+
+class NetBSD1LWPCoreTestCase(NetBSDCoreCommonTestCase):
+ THREAD_COUNT = 1
+
+ def check_stack(self, process, pid, filename):
+ thread = process.GetSelectedThread()
+ self.assertTrue(thread)
+ self.assertEqual(thread.GetThreadID(), 1)
+ self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal)
+ self.assertEqual(thread.GetStopReasonDataCount(), 1)
+ self.assertEqual(thread.GetStopReasonDataAtIndex(0), signal.SIGSEGV)
+ backtrace = ["bar", "foo", "main"]
+ self.check_backtrace(thread, filename, backtrace)
+
+ @skipIfLLVMTargetMissing("X86")
+ def test_amd64(self):
+ """Test single-threaded amd64 core dump."""
+ self.do_test("1lwp_SIGSEGV.amd64", pid=693, region_count=21)
+
+
+class NetBSD2LWPT2CoreTestCase(NetBSDCoreCommonTestCase):
+ THREAD_COUNT = 2
+
+ def check_stack(self, process, pid, filename):
+ thread = process.GetSelectedThread()
+ self.assertTrue(thread)
+ self.assertEqual(thread.GetThreadID(), 2)
+ self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal)
+ self.assertEqual(thread.GetStopReasonDataCount(), 1)
+ self.assertEqual(thread.GetStopReasonDataAtIndex(0), signal.SIGSEGV)
+ backtrace = ["bar", "foo", "lwp_main"]
+ self.check_backtrace(thread, filename, backtrace)
+
+ # thread 1 should have no signal
+ thread = process.GetThreadByID(1)
+ self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal)
+ self.assertEqual(thread.GetStopReasonDataCount(), 1)
+ self.assertEqual(thread.GetStopReasonDataAtIndex(0), 0)
+
+ @skipIfLLVMTargetMissing("X86")
+ def test_amd64(self):
+ """Test double-threaded amd64 core dump where thread 2 is signalled."""
+ self.do_test("2lwp_t2_SIGSEGV.amd64", pid=622, region_count=24)
+
+
+class NetBSD2LWPProcessSigCoreTestCase(NetBSDCoreCommonTestCase):
+ THREAD_COUNT = 2
+
+ def check_stack(self, process, pid, filename):
+ thread = process.GetSelectedThread()
+ self.assertTrue(thread)
+ self.assertEqual(thread.GetThreadID(), 2)
+ self.assertEqual(thread.GetThreadID(), 2)
+ self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal)
+ self.assertEqual(thread.GetStopReasonDataCount(), 1)
+ self.assertEqual(thread.GetStopReasonDataAtIndex(0), signal.SIGSEGV)
+ backtrace = ["_kill", "bar", "foo", "lwp_main"]
+ self.check_backtrace(thread, filename, backtrace)
+
+ # thread 1 should have the same signal
+ thread = process.GetThreadByID(1)
+ self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal)
+ self.assertEqual(thread.GetStopReasonDataCount(), 1)
+ self.assertEqual(thread.GetStopReasonDataAtIndex(0), signal.SIGSEGV)
+
+ @skipIfLLVMTargetMissing("X86")
+ def test_amd64(self):
+ """Test double-threaded amd64 core dump where process is signalled."""
+ self.do_test("2lwp_process_SIGSEGV.amd64", pid=141, region_count=24)
OpenPOWER on IntegriCloud