aboutsummaryrefslogtreecommitdiff
path: root/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-01-02 19:26:05 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-01-02 19:26:05 +0000
commit14f1b3e8826ce43b978db93a62d1166055db5394 (patch)
tree0a00ad8d3498783fe0193f3b656bca17c4c8697d /packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new
parent4ee8c119c71a06dcad1e0fecc8c675e480e59337 (diff)
Notes
Diffstat (limited to 'packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new')
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpNew.py161
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/install_breakpad.cpp16
-rwxr-xr-xpackages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64bin0 -> 7279 bytes
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64.cpp12
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64.dmpbin0 -> 63592 bytes
-rwxr-xr-xpackages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64_not_crashedbin0 -> 7675 bytes
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64_not_crashed.cpp22
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64_not_crashed.dmpbin0 -> 63744 bytes
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/makefile.txt29
9 files changed, 240 insertions, 0 deletions
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpNew.py b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpNew.py
new file mode 100644
index 000000000000..44a42fdfe9d1
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpNew.py
@@ -0,0 +1,161 @@
+"""
+Test basics of Minidump debugging.
+"""
+
+from __future__ import print_function
+from six import iteritems
+
+import shutil
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class MiniDumpNewTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ NO_DEBUG_INFO_TESTCASE = True
+
+ _linux_x86_64_pid = 29917
+ _linux_x86_64_not_crashed_pid = 29939
+ _linux_x86_64_not_crashed_pid_offset = 0xD967
+
+ def test_process_info_in_minidump(self):
+ """Test that lldb can read the process information from the Minidump."""
+ # target create -c linux-x86_64.dmp
+ self.dbg.CreateTarget(None)
+ self.target = self.dbg.GetSelectedTarget()
+ self.process = self.target.LoadCore("linux-x86_64.dmp")
+ self.assertTrue(self.process, PROCESS_IS_VALID)
+ self.assertEqual(self.process.GetNumThreads(), 1)
+ self.assertEqual(self.process.GetProcessID(), self._linux_x86_64_pid)
+
+ def test_thread_info_in_minidump(self):
+ """Test that lldb can read the thread information from the Minidump."""
+ # target create -c linux-x86_64.dmp
+ self.dbg.CreateTarget(None)
+ self.target = self.dbg.GetSelectedTarget()
+ self.process = self.target.LoadCore("linux-x86_64.dmp")
+ # This process crashed due to a segmentation fault in its
+ # one and only thread.
+ self.assertEqual(self.process.GetNumThreads(), 1)
+ thread = self.process.GetThreadAtIndex(0)
+ self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal)
+ stop_description = thread.GetStopDescription(256)
+ self.assertTrue("SIGSEGV" in stop_description)
+
+ def test_stack_info_in_minidump(self):
+ """Test that we can see a trivial stack in a breakpad-generated Minidump."""
+ # target create linux-x86_64 -c linux-x86_64.dmp
+ self.dbg.CreateTarget("linux-x86_64")
+ self.target = self.dbg.GetSelectedTarget()
+ self.process = self.target.LoadCore("linux-x86_64.dmp")
+ self.assertEqual(self.process.GetNumThreads(), 1)
+ self.assertEqual(self.process.GetProcessID(), self._linux_x86_64_pid)
+ thread = self.process.GetThreadAtIndex(0)
+ # frame #0: linux-x86_64`crash()
+ # frame #1: linux-x86_64`_start
+ self.assertEqual(thread.GetNumFrames(), 2)
+ frame = thread.GetFrameAtIndex(0)
+ self.assertTrue(frame.IsValid())
+ pc = frame.GetPC()
+ eip = frame.FindRegister("pc")
+ self.assertTrue(eip.IsValid())
+ self.assertEqual(pc, eip.GetValueAsUnsigned())
+
+ def test_snapshot_minidump(self):
+ """Test that if we load a snapshot minidump file (meaning the process
+ did not crash) there is no stop reason."""
+ # target create -c linux-x86_64_not_crashed.dmp
+ self.dbg.CreateTarget(None)
+ self.target = self.dbg.GetSelectedTarget()
+ self.process = self.target.LoadCore("linux-x86_64_not_crashed.dmp")
+ self.assertEqual(self.process.GetNumThreads(), 1)
+ thread = self.process.GetThreadAtIndex(0)
+ self.assertEqual(thread.GetStopReason(), lldb.eStopReasonNone)
+ stop_description = thread.GetStopDescription(256)
+ self.assertEqual(stop_description, None)
+
+ def do_test_deeper_stack(self, binary, core, pid):
+ target = self.dbg.CreateTarget(binary)
+ process = target.LoadCore(core)
+ thread = process.GetThreadAtIndex(0)
+
+ self.assertEqual(process.GetProcessID(), pid)
+
+ expected_stack = {1: 'bar', 2: 'foo', 3: '_start'}
+ self.assertGreaterEqual(thread.GetNumFrames(), len(expected_stack))
+ for index, name in iteritems(expected_stack):
+ frame = thread.GetFrameAtIndex(index)
+ self.assertTrue(frame.IsValid())
+ function_name = frame.GetFunctionName()
+ self.assertTrue(name in function_name)
+
+ def test_deeper_stack_in_minidump(self):
+ """Test that we can examine a more interesting stack in a Minidump."""
+ # Launch with the Minidump, and inspect the stack.
+ # target create linux-x86_64_not_crashed -c linux-x86_64_not_crashed.dmp
+ self.do_test_deeper_stack("linux-x86_64_not_crashed",
+ "linux-x86_64_not_crashed.dmp",
+ self._linux_x86_64_not_crashed_pid)
+
+ def do_change_pid_in_minidump(self, core, newcore, offset, oldpid, newpid):
+ """ This assumes that the minidump is breakpad generated on Linux -
+ meaning that the PID in the file will be an ascii string part of
+ /proc/PID/status which is written in the file
+ """
+ shutil.copyfile(core, newcore)
+ with open(newcore, "rb+") as f:
+ f.seek(offset)
+ currentpid = f.read(5).decode('utf-8')
+ self.assertEqual(currentpid, oldpid)
+
+ f.seek(offset)
+ if len(newpid) < len(oldpid):
+ newpid += " " * (len(oldpid) - len(newpid))
+ newpid += "\n"
+ f.write(newpid.encode('utf-8'))
+
+ def test_deeper_stack_in_minidump_with_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"""
+ try:
+ self.do_change_pid_in_minidump("linux-x86_64_not_crashed.dmp",
+ "linux-x86_64_not_crashed-pid.dmp",
+ self._linux_x86_64_not_crashed_pid_offset,
+ str(self._linux_x86_64_not_crashed_pid),
+ str(os.getpid()))
+ self.do_test_deeper_stack("linux-x86_64_not_crashed",
+ "linux-x86_64_not_crashed-pid.dmp",
+ os.getpid())
+ finally:
+ self.RemoveTempFile("linux-x86_64_not_crashed-pid.dmp")
+
+ def test_two_cores_same_pid(self):
+ """Test that we handle the situation if we have two core files with the same PID """
+ try:
+ self.do_change_pid_in_minidump("linux-x86_64_not_crashed.dmp",
+ "linux-x86_64_not_crashed-pid.dmp",
+ self._linux_x86_64_not_crashed_pid_offset,
+ str(self._linux_x86_64_not_crashed_pid),
+ str(self._linux_x86_64_pid))
+ self.do_test_deeper_stack("linux-x86_64_not_crashed",
+ "linux-x86_64_not_crashed-pid.dmp",
+ self._linux_x86_64_pid)
+ self.test_stack_info_in_minidump()
+ finally:
+ self.RemoveTempFile("linux-x86_64_not_crashed-pid.dmp")
+
+ def test_local_variables_in_minidump(self):
+ """Test that we can examine local variables in a Minidump."""
+ # Launch with the Minidump, and inspect a local variable.
+ # target create linux-x86_64_not_crashed -c linux-x86_64_not_crashed.dmp
+ target = self.dbg.CreateTarget("linux-x86_64_not_crashed")
+ process = target.LoadCore("linux-x86_64_not_crashed.dmp")
+ thread = process.GetThreadAtIndex(0)
+ frame = thread.GetFrameAtIndex(1)
+ value = frame.EvaluateExpression('x')
+ self.assertEqual(value.GetValueAsSigned(), 3)
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/install_breakpad.cpp b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/install_breakpad.cpp
new file mode 100644
index 000000000000..c34ac17128fa
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/install_breakpad.cpp
@@ -0,0 +1,16 @@
+#include "client/linux/handler/exception_handler.h"
+
+static bool dumpCallback(const google_breakpad::MinidumpDescriptor &descriptor,
+ void *context, bool succeeded) {
+ return succeeded;
+}
+
+google_breakpad::ExceptionHandler *eh;
+
+void InstallBreakpad() {
+ google_breakpad::MinidumpDescriptor descriptor("/tmp");
+ eh = new google_breakpad::ExceptionHandler(descriptor, NULL, dumpCallback,
+ NULL, true, -1);
+}
+
+void WriteMinidump() { eh->WriteMinidump(); }
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64 b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64
new file mode 100755
index 000000000000..078d9c8fa90a
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64
Binary files differ
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64.cpp b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64.cpp
new file mode 100644
index 000000000000..61d31492940d
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64.cpp
@@ -0,0 +1,12 @@
+void crash() {
+ volatile int *a = (int *)(nullptr);
+ *a = 1;
+}
+
+extern "C" void _start();
+void InstallBreakpad();
+
+void _start() {
+ InstallBreakpad();
+ crash();
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64.dmp b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64.dmp
new file mode 100644
index 000000000000..e2ae724abe99
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64.dmp
Binary files differ
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64_not_crashed b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64_not_crashed
new file mode 100755
index 000000000000..8b38cdb48bdd
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64_not_crashed
Binary files differ
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64_not_crashed.cpp b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64_not_crashed.cpp
new file mode 100644
index 000000000000..070c565e72bd
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64_not_crashed.cpp
@@ -0,0 +1,22 @@
+void InstallBreakpad();
+void WriteMinidump();
+
+int global = 42;
+
+int bar(int x) {
+ WriteMinidump();
+ int y = 4 * x + global;
+ return y;
+}
+
+int foo(int x) {
+ int y = 2 * bar(3 * x);
+ return y;
+}
+
+extern "C" void _start();
+
+void _start() {
+ InstallBreakpad();
+ foo(1);
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64_not_crashed.dmp b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64_not_crashed.dmp
new file mode 100644
index 000000000000..ad4b61a7bbb4
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64_not_crashed.dmp
Binary files differ
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/makefile.txt b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/makefile.txt
new file mode 100644
index 000000000000..79a95d61d85e
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/makefile.txt
@@ -0,0 +1,29 @@
+# This makefile aims to make the binaries as small as possible, for us not to
+# upload huge binary blobs in the repo.
+# The binary should have debug symbols because stack unwinding doesn't work
+# correctly using the information in the Minidump only. Also we want to evaluate
+# local variables, etc.
+# Breakpad compiles as a static library, so statically linking againts it
+# makes the binary huge.
+# Dynamically linking to it does improve things, but we are still #include-ing
+# breakpad headers (which is a lot of source code for which we generate debug
+# symbols)
+# So, install_breakpad.cpp does the #include-ing and defines a global function
+# "InstallBreakpad" that does all the exception handler registration.
+# We compile install_breakpad to object file and then link it, alongside the
+# static libbreakpad, into a shared library.
+# Then the binaries dynamically link to that lib.
+# The other optimisation is not using the standard library (hence the _start
+# instead of main). We only link dynamically to some standard libraries.
+# This way we have a tiny binary (~8K) that has debug symbols and uses breakpad
+# to generate a Minidump when the binary crashes/requests such.
+#
+CC=g++
+FLAGS=-g --std=c++11
+INCLUDE=-I$HOME/breakpad/src/src/
+LINK=-L. -lbreakpad -lpthread -nostdlib -lc -lstdc++ -lgcc_s -fno-exceptions
+all:
+ $(CC) $(FLAGS) -fPIC -c install_breakpad.cpp $(INCLUDE) -o install_breakpad.o
+ ld -shared install_breakpad.o libbreakpad_client.a -o libbreakpad.so
+ $(CC) $(FLAGS) -o linux-x86_64 linux-x86_64.cpp $(LINK)
+ $(CC) $(FLAGS) -o linux-x86_64_not_crashed linux-x86_64_not_crashed.cpp $(LINK)