aboutsummaryrefslogtreecommitdiff
path: root/packages/Python/lldbsuite/test/functionalities/postmortem
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2016-07-23 20:50:09 +0000
committerDimitry Andric <dim@FreeBSD.org>2016-07-23 20:50:09 +0000
commitf3fbd1c0586ff6ec7895991e6c28f61a503c36a8 (patch)
tree48d008fd3df8c0e73271a4b18474e0aac6dbfe33 /packages/Python/lldbsuite/test/functionalities/postmortem
parent2fc5d2d1dfaf623ce4e24cd8590565902f8c557c (diff)
Notes
Diffstat (limited to 'packages/Python/lldbsuite/test/functionalities/postmortem')
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/TestLinuxCore.py164
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/altmain.c6
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/altmain.corebin0 -> 40960 bytes
-rwxr-xr-xpackages/Python/lldbsuite/test/functionalities/postmortem/linux-core/altmain.outbin0 -> 2330 bytes
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/i386.corebin0 -> 28672 bytes
-rwxr-xr-xpackages/Python/lldbsuite/test/functionalities/postmortem/linux-core/i386.outbin0 -> 1971 bytes
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/main.c17
-rwxr-xr-xpackages/Python/lldbsuite/test/functionalities/postmortem/linux-core/make-core.sh40
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/s390x.corebin0 -> 16384 bytes
-rwxr-xr-xpackages/Python/lldbsuite/test/functionalities/postmortem/linux-core/s390x.outbin0 -> 2824 bytes
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/x86_64.corebin0 -> 40960 bytes
-rwxr-xr-xpackages/Python/lldbsuite/test/functionalities/postmortem/linux-core/x86_64.outbin0 -> 2575 bytes
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py3
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/TestWow64MiniDump.py76
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/fizzbuzz.cpp31
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/fizzbuzz_wow64.dmpbin0 -> 9280561 bytes
16 files changed, 336 insertions, 1 deletions
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/TestLinuxCore.py b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/TestLinuxCore.py
new file mode 100644
index 000000000000..fd5bb00d0565
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/TestLinuxCore.py
@@ -0,0 +1,164 @@
+"""
+Test basics of linux core file debugging.
+"""
+
+from __future__ import print_function
+
+import shutil
+import struct
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class LinuxCoreTestCase(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ _i386_pid = 32306
+ _x86_64_pid = 32259
+ _s390x_pid = 1045
+
+ _i386_regions = 4
+ _x86_64_regions = 5
+ _s390x_regions = 2
+
+ @skipIf(bugnumber="llvm.org/pr26947")
+ def test_i386(self):
+ """Test that lldb can read the process information from an i386 linux core file."""
+ self.do_test("i386", self._i386_pid, self._i386_regions)
+
+ 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", self._x86_64_pid, self._x86_64_regions)
+
+ # This seems to hang on non-s390x platforms for some reason. Disabling for now.
+ @skipIf(archs=no_match(['s390x']))
+ def test_s390x(self):
+ """Test that lldb can read the process information from an s390x linux core file."""
+ self.do_test("s390x", self._s390x_pid, self._s390x_regions)
+
+ def test_same_pid_running(self):
+ """Test that we read the information from the core correctly even if we have a running
+ process with the same PID around"""
+ try:
+ shutil.copyfile("x86_64.out", "x86_64-pid.out")
+ shutil.copyfile("x86_64.core", "x86_64-pid.core")
+ with open("x86_64-pid.core", "r+b") as f:
+ # These are offsets into the NT_PRSTATUS and NT_PRPSINFO structures in the note
+ # segment of the core file. If you update the file, these offsets may need updating
+ # as well. (Notes can be viewed with readelf --notes.)
+ for pid_offset in [0x1c4, 0x320]:
+ f.seek(pid_offset)
+ self.assertEqual(struct.unpack("<I", f.read(4))[0], self._x86_64_pid)
+
+ # We insert our own pid, and make sure the test still works.
+ f.seek(pid_offset)
+ f.write(struct.pack("<I", os.getpid()))
+ self.do_test("x86_64-pid", os.getpid(), self._x86_64_regions)
+ finally:
+ self.RemoveTempFile("x86_64-pid.out")
+ self.RemoveTempFile("x86_64-pid.core")
+
+ def test_two_cores_same_pid(self):
+ """Test that we handle the situation if we have two core files with the same PID
+ around"""
+ alttarget = self.dbg.CreateTarget("altmain.out")
+ altprocess = alttarget.LoadCore("altmain.core")
+ self.assertTrue(altprocess, PROCESS_IS_VALID)
+ self.assertEqual(altprocess.GetNumThreads(), 1)
+ self.assertEqual(altprocess.GetProcessID(), self._x86_64_pid)
+
+ altframe = altprocess.GetSelectedThread().GetFrameAtIndex(0)
+ self.assertEqual(altframe.GetFunctionName(), "_start")
+ self.assertEqual(altframe.GetLineEntry().GetLine(), line_number("altmain.c", "Frame _start"))
+
+ error = lldb.SBError()
+ F = altprocess.ReadCStringFromMemory(altframe.FindVariable("F").GetValueAsUnsigned(), 256, error)
+ self.assertTrue(error.Success())
+ self.assertEqual(F, "_start")
+
+ # without destroying this process, run the test which opens another core file with the
+ # same pid
+ self.do_test("x86_64", self._x86_64_pid, self._x86_64_regions)
+
+ 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()) / 2l
+ 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() - 1l
+ 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 do_test(self, filename, pid, region_count):
+ target = self.dbg.CreateTarget(filename + ".out")
+ process = target.LoadCore(filename + ".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]))
+
+ self.check_memory_regions(process, region_count)
+
+ self.dbg.DeleteTarget(target)
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/altmain.c b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/altmain.c
new file mode 100644
index 000000000000..da49a00996e1
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/altmain.c
@@ -0,0 +1,6 @@
+void _start(void)
+{
+ const char *F = "_start";
+ char *boom = (char *)0;
+ *boom = 47; // Frame _start
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/altmain.core b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/altmain.core
new file mode 100644
index 000000000000..423413070c7a
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/altmain.core
Binary files differ
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/altmain.out b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/altmain.out
new file mode 100755
index 000000000000..2fddf3e8f803
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/altmain.out
Binary files differ
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/i386.core b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/i386.core
new file mode 100644
index 000000000000..f8deff474d1f
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/i386.core
Binary files differ
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/i386.out b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/i386.out
new file mode 100755
index 000000000000..3cdd4eeca103
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/i386.out
Binary files differ
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/main.c b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/main.c
new file mode 100644
index 000000000000..f5bde4171ca5
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/main.c
@@ -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
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/make-core.sh b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/make-core.sh
new file mode 100755
index 000000000000..efe1b801df34
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/make-core.sh
@@ -0,0 +1,40 @@
+#! /bin/bash
+
+set -e -x
+
+file=$1
+if [ -z "$file" ]; then
+ cat <<EOF
+Please supply the main source file as the first argument.
+EOF
+ exit 1
+fi
+
+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 "$file" -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
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/s390x.core b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/s390x.core
new file mode 100644
index 000000000000..b97fc43e967d
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/s390x.core
Binary files differ
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/s390x.out b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/s390x.out
new file mode 100755
index 000000000000..640fbdc257d9
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/s390x.out
Binary files differ
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/x86_64.core b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/x86_64.core
new file mode 100644
index 000000000000..e2fa69e4558e
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/x86_64.core
Binary files differ
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/x86_64.out b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/x86_64.out
new file mode 100755
index 000000000000..842402fd519d
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/x86_64.out
Binary files differ
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py
index 1dda59ac374b..89d1974b6703 100644
--- a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py
@@ -7,8 +7,9 @@ from six import iteritems
import lldb
+from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
-import lldbsuite.test.lldbutil as lldbutil
+from lldbsuite.test import lldbutil
class MiniDumpTestCase(TestBase):
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/TestWow64MiniDump.py b/packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/TestWow64MiniDump.py
new file mode 100644
index 000000000000..08debab538f5
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/TestWow64MiniDump.py
@@ -0,0 +1,76 @@
+"""
+Test basics of a mini dump taken of a 32-bit process running in WoW64
+
+WoW64 is the subsystem that lets 32-bit processes run in 64-bit Windows. If you
+capture a mini dump of a process running under WoW64 with a 64-bit debugger, you
+end up with a dump of the WoW64 layer. In that case, LLDB must do extra work to
+get the 32-bit register contexts.
+"""
+
+from __future__ import print_function
+from six import iteritems
+
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class Wow64MiniDumpTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ @skipUnlessWindows # for now mini-dump debugging is limited to Windows hosts
+ @no_debug_info_test
+ def test_wow64_mini_dump(self):
+ """Test that lldb can read the process information from the minidump."""
+ # target create -c fizzbuzz_wow64.dmp
+ target = self.dbg.CreateTarget("")
+ process = target.LoadCore("fizzbuzz_wow64.dmp")
+ self.assertTrue(process, PROCESS_IS_VALID)
+ self.assertEqual(process.GetNumThreads(), 1)
+ self.assertEqual(process.GetProcessID(), 0x1E9C)
+
+ @skipUnlessWindows # for now mini-dump debugging is limited to Windows hosts
+ @no_debug_info_test
+ def test_thread_info_in_wow64_mini_dump(self):
+ """Test that lldb can read the thread information from the minidump."""
+ # target create -c fizzbuzz_wow64.dmp
+ target = self.dbg.CreateTarget("")
+ process = target.LoadCore("fizzbuzz_wow64.dmp")
+ # This process crashed due to an access violation (0xc0000005), but the
+ # minidump doesn't have an exception record--perhaps the crash handler
+ # ate it.
+ # TODO: See if we can recover the exception information from the TEB,
+ # which, according to Windbg, has a pointer to an exception list.
+
+ # In the dump, none of the threads are stopped, so we cannot use
+ # lldbutil.get_stopped_thread.
+ thread = process.GetThreadAtIndex(0)
+ self.assertEqual(thread.GetStopReason(), lldb.eStopReasonNone)
+
+ @skipUnlessWindows # for now mini-dump debugging is limited to Windows hosts
+ @no_debug_info_test
+ def test_stack_info_in_wow64_mini_dump(self):
+ """Test that we can see a trivial stack in a VS-generate mini dump."""
+ # target create -c fizzbuzz_no_heap.dmp
+ target = self.dbg.CreateTarget("")
+ process = target.LoadCore("fizzbuzz_wow64.dmp")
+ self.assertGreaterEqual(process.GetNumThreads(), 1)
+ # This process crashed due to an access violation (0xc0000005), but the
+ # minidump doesn't have an exception record--perhaps the crash handler
+ # ate it.
+ # TODO: See if we can recover the exception information from the TEB,
+ # which, according to Windbg, has a pointer to an exception list.
+
+ # In the dump, none of the threads are stopped, so we cannot use
+ # lldbutil.get_stopped_thread.
+ thread = process.GetThreadAtIndex(0)
+ # The crash is in main, so there should be at least one frame on the stack.
+ self.assertGreaterEqual(thread.GetNumFrames(), 1)
+ frame = thread.GetFrameAtIndex(0)
+ self.assertTrue(frame.IsValid())
+ pc = frame.GetPC()
+ eip = frame.FindRegister("pc")
+ self.assertTrue(eip.IsValid())
+ self.assertEqual(pc, eip.GetValueAsUnsigned())
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/fizzbuzz.cpp b/packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/fizzbuzz.cpp
new file mode 100644
index 000000000000..295d4a1f24db
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/fizzbuzz.cpp
@@ -0,0 +1,31 @@
+// A sample program for getting minidumps on Windows.
+
+#include <iostream>
+
+bool
+fizz(int x)
+{
+ return x % 3 == 0;
+}
+
+bool
+buzz(int x)
+{
+ return x % 5 == 0;
+}
+
+int
+main()
+{
+ int *buggy = 0;
+
+ for (int i = 1; i <= 100; ++i)
+ {
+ if (fizz(i)) std::cout << "fizz";
+ if (buzz(i)) std::cout << "buzz";
+ if (!fizz(i) && !buzz(i)) std::cout << i;
+ std::cout << '\n';
+ }
+
+ return *buggy;
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/fizzbuzz_wow64.dmp b/packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/fizzbuzz_wow64.dmp
new file mode 100644
index 000000000000..3d97186f2cd2
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/fizzbuzz_wow64.dmp
Binary files differ