aboutsummaryrefslogtreecommitdiff
path: root/packages/Python/lldbsuite/test/functionalities/postmortem
diff options
context:
space:
mode:
Diffstat (limited to 'packages/Python/lldbsuite/test/functionalities/postmortem')
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py249
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/altmain.c (renamed from packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/altmain.c)0
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/altmain.core (renamed from packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/altmain.core)bin40960 -> 40960 bytes
-rwxr-xr-xpackages/Python/lldbsuite/test/functionalities/postmortem/elf-core/altmain.out (renamed from packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/altmain.out)bin2330 -> 2330 bytes
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/fpr_sse.cpp38
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/TestGCore.py52
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/linux-i386.corebin0 -> 12324 bytes
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/linux-x86_64.corebin0 -> 19008 bytes
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/main.cpp63
-rwxr-xr-xpackages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/main.mk5
-rwxr-xr-xpackages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/make-core.sh56
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-fpr_sse_i386.corebin0 -> 32768 bytes
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-fpr_sse_x86_64.corebin0 -> 40960 bytes
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-i386.core (renamed from packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/i386.core)bin28672 -> 28672 bytes
-rwxr-xr-xpackages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-i386.out (renamed from packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/i386.out)bin1971 -> 1971 bytes
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-s390x.core (renamed from packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/s390x.core)bin16384 -> 16384 bytes
-rwxr-xr-xpackages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-s390x.out (renamed from packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/s390x.out)bin2824 -> 2824 bytes
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-x86_64.core (renamed from packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/x86_64.core)bin40960 -> 40960 bytes
-rwxr-xr-xpackages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-x86_64.out (renamed from packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/x86_64.out)bin2575 -> 2575 bytes
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/main.c (renamed from packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/main.c)0
-rwxr-xr-xpackages/Python/lldbsuite/test/functionalities/postmortem/elf-core/make-core.sh (renamed from packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/make-core.sh)39
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/TestLinuxCoreThreads.py61
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/linux-i386.corebin0 -> 24576 bytes
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/linux-x86_64.corebin0 -> 32768 bytes
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/main.cpp63
-rwxr-xr-xpackages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/main.mk5
-rwxr-xr-xpackages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/make-core.sh64
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/TestLinuxCore.py164
-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
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py29
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/TestWow64MiniDump.py11
39 files changed, 943 insertions, 196 deletions
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py
new file mode 100644
index 000000000000..ed46ef1c847e
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py
@@ -0,0 +1,249 @@
+"""
+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(oslist=['windows'])
+ @skipIf(triple='^mips')
+ def test_i386(self):
+ """Test that lldb can read the process information from an i386 linux core file."""
+ self.do_test("linux-i386", self._i386_pid, self._i386_regions)
+
+ @skipIf(oslist=['windows'])
+ @skipIf(triple='^mips')
+ def test_x86_64(self):
+ """Test that lldb can read the process information from an x86_64 linux core file."""
+ self.do_test("linux-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']))
+ @skipIf(triple='^mips')
+ def test_s390x(self):
+ """Test that lldb can read the process information from an s390x linux core file."""
+ self.do_test("linux-s390x", self._s390x_pid, self._s390x_regions)
+
+ @skipIf(oslist=['windows'])
+ @skipIf(triple='^mips')
+ 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("linux-x86_64.out", "linux-x86_64-pid.out")
+ shutil.copyfile("linux-x86_64.core", "linux-x86_64-pid.core")
+ with open("linux-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("linux-x86_64-pid", os.getpid(), self._x86_64_regions)
+ finally:
+ self.RemoveTempFile("linux-x86_64-pid.out")
+ self.RemoveTempFile("linux-x86_64-pid.core")
+
+ @skipIf(oslist=['windows'])
+ @skipIf(triple='^mips')
+ 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("linux-x86_64", self._x86_64_pid, self._x86_64_regions)
+
+ @skipIf(oslist=['windows'])
+ @skipIf(triple='^mips')
+ def test_FPR_SSE(self):
+ # check x86_64 core file
+ target = self.dbg.CreateTarget(None)
+ self.assertTrue(target, VALID_TARGET)
+ process = target.LoadCore("linux-fpr_sse_x86_64.core")
+
+ values = {}
+ values["fctrl"] = "0x037f"
+ values["fstat"] = "0x0000"
+ values["ftag"] = "0xff"
+ values["fop"] = "0x0000"
+ values["fiseg"] = "0x00000000"
+ values["fioff"] = "0x0040011e"
+ values["foseg"] = "0x00000000"
+ values["fooff"] = "0x00000000"
+ values["mxcsr"] = "0x00001f80"
+ values["mxcsrmask"] = "0x0000ffff"
+ values["st0"] = "{0x99 0xf7 0xcf 0xfb 0x84 0x9a 0x20 0x9a 0xfd 0x3f}"
+ values["st1"] = "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0xff 0x3f}"
+ values["st2"] = "{0xfe 0x8a 0x1b 0xcd 0x4b 0x78 0x9a 0xd4 0x00 0x40}"
+ values["st3"] = "{0xac 0x79 0xcf 0xd1 0xf7 0x17 0x72 0xb1 0xfe 0x3f}"
+ values["st4"] = "{0xbc 0xf0 0x17 0x5c 0x29 0x3b 0xaa 0xb8 0xff 0x3f}"
+ values["st5"] = "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0xff 0x3f}"
+ values["st6"] = "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
+ values["st7"] = "{0x35 0xc2 0x68 0x21 0xa2 0xda 0x0f 0xc9 0x00 0x40}"
+ values["xmm0"] = "{0x29 0x31 0x64 0x46 0x29 0x31 0x64 0x46 0x29 0x31 0x64 0x46 0x29 0x31 0x64 0x46}"
+ values["xmm1"] = "{0x9c 0xed 0x86 0x64 0x9c 0xed 0x86 0x64 0x9c 0xed 0x86 0x64 0x9c 0xed 0x86 0x64}"
+ values["xmm2"] = "{0x07 0xc2 0x1f 0xd7 0x07 0xc2 0x1f 0xd7 0x07 0xc2 0x1f 0xd7 0x07 0xc2 0x1f 0xd7}"
+ values["xmm3"] = "{0xa2 0x20 0x48 0x25 0xa2 0x20 0x48 0x25 0xa2 0x20 0x48 0x25 0xa2 0x20 0x48 0x25}"
+ values["xmm4"] = "{0xeb 0x5a 0xa8 0xc4 0xeb 0x5a 0xa8 0xc4 0xeb 0x5a 0xa8 0xc4 0xeb 0x5a 0xa8 0xc4}"
+ values["xmm5"] = "{0x49 0x41 0x20 0x0b 0x49 0x41 0x20 0x0b 0x49 0x41 0x20 0x0b 0x49 0x41 0x20 0x0b}"
+ values["xmm6"] = "{0xf8 0xf1 0x8b 0x4f 0xf8 0xf1 0x8b 0x4f 0xf8 0xf1 0x8b 0x4f 0xf8 0xf1 0x8b 0x4f}"
+ values["xmm7"] = "{0x13 0xf1 0x30 0xcd 0x13 0xf1 0x30 0xcd 0x13 0xf1 0x30 0xcd 0x13 0xf1 0x30 0xcd}"
+
+ for regname, value in values.iteritems():
+ self.expect("register read {}".format(regname), substrs=["{} = {}".format(regname, value)])
+
+
+ # now check i386 core file
+ target = self.dbg.CreateTarget(None)
+ self.assertTrue(target, VALID_TARGET)
+ process = target.LoadCore("linux-fpr_sse_i386.core")
+
+ values["fioff"] = "0x080480cc"
+
+ for regname, value in values.iteritems():
+ self.expect("register read {}".format(regname), substrs=["{} = {}".format(regname, value)])
+
+ 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 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/elf-core/altmain.c
index da49a00996e1..da49a00996e1 100644
--- a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/altmain.c
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/altmain.c
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/altmain.core b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/altmain.core
index 423413070c7a..423413070c7a 100644
--- a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/altmain.core
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-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/elf-core/altmain.out
index 2fddf3e8f803..2fddf3e8f803 100755
--- a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/altmain.out
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/altmain.out
Binary files differ
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/fpr_sse.cpp b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/fpr_sse.cpp
new file mode 100644
index 000000000000..e6826fc7a097
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/fpr_sse.cpp
@@ -0,0 +1,38 @@
+// fpr_sse_x86_64.core was generated with:
+// ./make-core.sh fpr_sse.cpp
+//
+// fpr_sse_i386.core was generated with:
+// export CFLAGS=-m32
+// ./make-core.sh fpr_sse.cpp
+
+void _start(void) {
+ __asm__("fldpi;"
+ "fldz;"
+ "fld1;"
+ "fldl2e;"
+ "fldln2;"
+ "fldl2t;"
+ "fld1;"
+ "fldlg2;");
+
+ unsigned int values[8] = {
+ 0x46643129, 0x6486ed9c, 0xd71fc207, 0x254820a2,
+ 0xc4a85aeb, 0x0b204149, 0x4f8bf1f8, 0xcd30f113,
+ };
+
+ __asm__("vbroadcastss %0, %%xmm0;"
+ "vbroadcastss %1, %%xmm1;"
+ "vbroadcastss %2, %%xmm2;"
+ "vbroadcastss %3, %%xmm3;"
+ "vbroadcastss %4, %%xmm4;"
+ "vbroadcastss %5, %%xmm5;"
+ "vbroadcastss %6, %%xmm6;"
+ "vbroadcastss %7, %%xmm7;"
+
+ ::"m"(values[0]),
+ "m"(values[1]), "m"(values[2]), "m"(values[3]), "m"(values[4]),
+ "m"(values[5]), "m"(values[6]), "m"(values[7]));
+
+ volatile int *a = 0;
+ *a = 0;
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/TestGCore.py b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/TestGCore.py
new file mode 100644
index 000000000000..5a11a52e93a6
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/TestGCore.py
@@ -0,0 +1,52 @@
+"""
+Test signal reporting when debugging with linux core files.
+"""
+
+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 GCoreTestCase(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+
+ mydir = TestBase.compute_mydir(__file__)
+ _initial_platform = lldb.DBG.GetSelectedPlatform()
+
+ _i386_pid = 5586
+ _x86_64_pid = 5669
+
+ @skipIf(oslist=['windows'])
+ @skipIf(triple='^mips')
+ def test_i386(self):
+ """Test that lldb can read the process information from an i386 linux core file."""
+ self.do_test("linux-i386", self._i386_pid)
+
+ @skipIf(oslist=['windows'])
+ @skipIf(triple='^mips')
+ def test_x86_64(self):
+ """Test that lldb can read the process information from an x86_64 linux core file."""
+ self.do_test("linux-x86_64", self._x86_64_pid)
+
+ def do_test(self, filename, pid):
+ target = self.dbg.CreateTarget("")
+ process = target.LoadCore(filename + ".core")
+ self.assertTrue(process, PROCESS_IS_VALID)
+ self.assertEqual(process.GetNumThreads(), 3)
+ self.assertEqual(process.GetProcessID(), pid)
+
+ for thread in process:
+ reason = thread.GetStopReason()
+ self.assertEqual(reason, lldb.eStopReasonSignal)
+ signal = thread.GetStopReasonDataAtIndex(1)
+ # Check we got signal 19 (SIGSTOP)
+ self.assertEqual(signal, 19)
+
+ self.dbg.DeleteTarget(target)
+ lldb.DBG.SetSelectedPlatform(self._initial_platform)
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/linux-i386.core b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/linux-i386.core
new file mode 100644
index 000000000000..8f9ac87c19f2
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/linux-i386.core
Binary files differ
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/linux-x86_64.core b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/linux-x86_64.core
new file mode 100644
index 000000000000..ef673e45b219
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/linux-x86_64.core
Binary files differ
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/main.cpp b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/main.cpp
new file mode 100644
index 000000000000..9908faffb6eb
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/main.cpp
@@ -0,0 +1,63 @@
+//===-- main.cpp ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// This test verifies the correct handling of child thread exits.
+
+#include <atomic>
+#include <thread>
+#include <csignal>
+
+pseudo_barrier_t g_barrier1;
+pseudo_barrier_t g_barrier2;
+
+void *
+thread1 ()
+{
+ // Synchronize with the main thread.
+ pseudo_barrier_wait(g_barrier1);
+
+ // Synchronize with the main thread and thread2.
+ pseudo_barrier_wait(g_barrier2);
+
+ // Return
+ return NULL;
+}
+
+void *
+thread2 ()
+{
+
+ // Synchronize with thread1 and the main thread.
+ pseudo_barrier_wait(g_barrier2); // Should not reach here.
+
+ // Return
+ return NULL;
+}
+
+int main ()
+{
+
+ pseudo_barrier_init(g_barrier1, 2);
+ pseudo_barrier_init(g_barrier2, 3);
+
+ // Create a thread.
+ std::thread thread_1(thread1);
+
+ // Wait for thread1 to start.
+ pseudo_barrier_wait(g_barrier1);
+
+ // Wait for thread1 to start.
+ std::thread thread_2(thread2);
+
+ // Thread 2 is waiting for another thread to reach the barrier.
+ // This should have for ever. (So we can run gcore against this process.)
+ thread_2.join();
+
+ return 0;
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/main.mk b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/main.mk
new file mode 100755
index 000000000000..ff874a21f760
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/main.mk
@@ -0,0 +1,5 @@
+LEVEL = ../../../../make
+
+CXX_SOURCES := main.cpp
+ENABLE_THREADS := YES
+include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/make-core.sh b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/make-core.sh
new file mode 100755
index 000000000000..b6979c7790de
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/make-core.sh
@@ -0,0 +1,56 @@
+#! /bin/sh
+
+linux_check_ptrace_scope()
+{
+ if grep -q '1' </proc/sys/kernel/yama/ptrace_scope; then
+ cat <<EOF
+Your system prevents the use of PTRACE to attach to non-child processes. The core file
+cannot be generated. Please reset /proc/sys/kernel/yama/ptrace_scope to 0 (requires root
+privileges) to enable core generation via gcore.
+EOF
+ exit 1
+ fi
+}
+
+set -e -x
+
+OS=$(uname -s)
+if [ "$OS" = Linux ]; then
+ linux_check_ptrace_scope
+fi
+
+rm -f a.out
+make -f main.mk
+
+cat <<EOF
+Executable file is in a.out.
+Core file will be saved as core.<pid>.
+EOF
+
+stack_size=`ulimit -s`
+
+# Decrease stack size to 16k => smaller core files.
+# gcore won't run with the smaller stack
+ulimit -Ss 16
+
+core_dump_filter=`cat /proc/self/coredump_filter`
+echo 0 > /proc/self/coredump_filter
+
+./a.out &
+
+pid=$!
+
+echo $core_dump_filter > /proc/self/coredump_filter
+
+# Reset stack size as so there's enough space to run gcore.
+ulimit -s $stack_size
+
+echo "Sleeping for 5 seconds to wait for $pid"
+
+sleep 5
+echo "Taking core from process $pid"
+
+gcore -o core $pid
+
+echo "Killing process $pid"
+kill -9 $pid
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-fpr_sse_i386.core b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-fpr_sse_i386.core
new file mode 100644
index 000000000000..b0fdaf67ca4f
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-fpr_sse_i386.core
Binary files differ
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-fpr_sse_x86_64.core b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-fpr_sse_x86_64.core
new file mode 100644
index 000000000000..5fb39ee115b2
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-fpr_sse_x86_64.core
Binary files differ
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/i386.core b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-i386.core
index f8deff474d1f..f8deff474d1f 100644
--- a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/i386.core
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-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/elf-core/linux-i386.out
index 3cdd4eeca103..3cdd4eeca103 100755
--- a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/i386.out
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-i386.out
Binary files differ
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/s390x.core b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-s390x.core
index b97fc43e967d..b97fc43e967d 100644
--- a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/s390x.core
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-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/elf-core/linux-s390x.out
index 640fbdc257d9..640fbdc257d9 100755
--- a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/s390x.out
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-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/elf-core/linux-x86_64.core
index e2fa69e4558e..e2fa69e4558e 100644
--- a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/x86_64.core
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-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/elf-core/linux-x86_64.out
index 842402fd519d..842402fd519d 100755
--- a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/x86_64.out
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-x86_64.out
Binary files differ
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/main.c b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/main.c
index f5bde4171ca5..f5bde4171ca5 100644
--- a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/main.c
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/main.c
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/make-core.sh b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/make-core.sh
index efe1b801df34..9dd83f19c76e 100755
--- a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/make-core.sh
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/make-core.sh
@@ -1,4 +1,30 @@
-#! /bin/bash
+#! /bin/sh
+
+linux_check_core_pattern()
+{
+ 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
+}
+
+OS=$(uname -s)
+case "$OS" in
+FreeBSD)
+ core_pattern=$(sysctl -n kern.corefile)
+ ;;
+Linux)
+ core_pattern=$(cat /proc/sys/kernel/core_pattern)
+ ;;
+*)
+ echo "OS $OS not supported" >&2
+ exit 1
+ ;;
+esac
set -e -x
@@ -10,13 +36,8 @@ 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
+if [ "$OS" = Linux ]; then
+ linux_check_core_pattern
fi
ulimit -c 1000
@@ -33,7 +54,7 @@ ${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).
+Core file will be saved according to pattern $core_pattern.
EOF
ulimit -s 8 # Decrease stack size to 8k => smaller core files.
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/TestLinuxCoreThreads.py b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/TestLinuxCoreThreads.py
new file mode 100644
index 000000000000..7cc3c0775ced
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/TestLinuxCoreThreads.py
@@ -0,0 +1,61 @@
+"""
+Test signal reporting when debugging with linux core files.
+"""
+
+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 LinuxCoreThreadsTestCase(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+
+ mydir = TestBase.compute_mydir(__file__)
+ _initial_platform = lldb.DBG.GetSelectedPlatform()
+
+ _i386_pid = 5193
+ _x86_64_pid = 5222
+
+ # Thread id for the failing thread.
+ _i386_tid = 5195
+ _x86_64_tid = 5250
+
+ @skipIf(oslist=['windows'])
+ @skipIf(triple='^mips')
+ def test_i386(self):
+ """Test that lldb can read the process information from an i386 linux core file."""
+ self.do_test("linux-i386", self._i386_pid, self._i386_tid)
+
+ @skipIf(oslist=['windows'])
+ @skipIf(triple='^mips')
+ def test_x86_64(self):
+ """Test that lldb can read the process information from an x86_64 linux core file."""
+ self.do_test("linux-x86_64", self._x86_64_pid, self._x86_64_tid)
+
+ def do_test(self, filename, pid, tid):
+ target = self.dbg.CreateTarget("")
+ process = target.LoadCore(filename + ".core")
+ self.assertTrue(process, PROCESS_IS_VALID)
+ self.assertEqual(process.GetNumThreads(), 3)
+ self.assertEqual(process.GetProcessID(), pid)
+
+ for thread in process:
+ reason = thread.GetStopReason()
+ if( thread.GetThreadID() == tid ):
+ self.assertEqual(reason, lldb.eStopReasonSignal)
+ signal = thread.GetStopReasonDataAtIndex(1)
+ # Check we got signal 4 (SIGILL)
+ self.assertEqual(signal, 4)
+ else:
+ signal = thread.GetStopReasonDataAtIndex(1)
+ # Check we got no signal on the other threads
+ self.assertEqual(signal, 0)
+
+ self.dbg.DeleteTarget(target)
+ lldb.DBG.SetSelectedPlatform(self._initial_platform)
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/linux-i386.core b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/linux-i386.core
new file mode 100644
index 000000000000..86c6fb8c5ac3
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/linux-i386.core
Binary files differ
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/linux-x86_64.core b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/linux-x86_64.core
new file mode 100644
index 000000000000..fc27e5810ee5
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/linux-x86_64.core
Binary files differ
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/main.cpp b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/main.cpp
new file mode 100644
index 000000000000..826d9d3fa972
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/main.cpp
@@ -0,0 +1,63 @@
+//===-- main.cpp ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// This test verifies the correct handling of child thread exits.
+
+#include <atomic>
+#include <thread>
+#include <csignal>
+
+pseudo_barrier_t g_barrier1;
+pseudo_barrier_t g_barrier2;
+
+void *
+thread1 ()
+{
+ // Synchronize with the main thread.
+ pseudo_barrier_wait(g_barrier1);
+
+ // Synchronize with the main thread and thread2.
+ pseudo_barrier_wait(g_barrier2);
+
+ // Return
+ return NULL; // Should not reach here. (thread2 should raise SIGILL)
+}
+
+void *
+thread2 ()
+{
+ raise(SIGILL); // Raise SIGILL
+
+ // Synchronize with thread1 and the main thread.
+ pseudo_barrier_wait(g_barrier2); // Should not reach here.
+
+ // Return
+ return NULL;
+}
+
+int main ()
+{
+ pseudo_barrier_init(g_barrier1, 2);
+ pseudo_barrier_init(g_barrier2, 3);
+
+ // Create a thread.
+ std::thread thread_1(thread1);
+
+ // Wait for thread1 to start.
+ pseudo_barrier_wait(g_barrier1);
+
+ // Create another thread.
+ std::thread thread_2(thread2);
+
+ // Wait for thread2 to start.
+ // Second thread should crash but first thread and main thread may reach here.
+ pseudo_barrier_wait(g_barrier2);
+
+ return 0;
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/main.mk b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/main.mk
new file mode 100755
index 000000000000..ff874a21f760
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/main.mk
@@ -0,0 +1,5 @@
+LEVEL = ../../../../make
+
+CXX_SOURCES := main.cpp
+ENABLE_THREADS := YES
+include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/make-core.sh b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/make-core.sh
new file mode 100755
index 000000000000..ea263c86ea46
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/make-core.sh
@@ -0,0 +1,64 @@
+#! /bin/sh
+
+linux_check_core_pattern()
+{
+ 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
+}
+
+OS=$(uname -s)
+case "$OS" in
+FreeBSD)
+ core_pattern=$(sysctl -n kern.corefile)
+ ;;
+Linux)
+ core_pattern=$(cat /proc/sys/kernel/core_pattern)
+ ;;
+*)
+ echo "OS $OS not supported" >&2
+ exit 1
+ ;;
+esac
+
+set -e -x
+
+if [ "$OS" = Linux ]; then
+ linux_check_core_pattern
+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
+
+rm -f a.out
+make -f main.mk
+
+cat <<EOF
+Executable file is in a.out.
+Core file will be saved according to pattern $core_pattern.
+EOF
+
+# Save stack size and core_dump_filter
+stack_size=`ulimit -s`
+ulimit -Ss 32 # Decrease stack size to 32k => smaller core files.
+
+core_dump_filter=`cat /proc/self/coredump_filter`
+echo 0 > /proc/self/coredump_filter
+
+exec ./a.out
+
+# Reset stack size and core_dump_filter
+echo core_dump_filter > /proc/self/coredump_filter
+ulimit -s $stack_size
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/TestLinuxCore.py b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/TestLinuxCore.py
deleted file mode 100644
index fd5bb00d0565..000000000000
--- a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/TestLinuxCore.py
+++ /dev/null
@@ -1,164 +0,0 @@
-"""
-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/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)
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py
index 89d1974b6703..b89a305d0e88 100644
--- a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py
@@ -11,12 +11,12 @@ from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
+
class MiniDumpTestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
+ NO_DEBUG_INFO_TESTCASE = True
- @skipUnlessWindows # for now mini-dump debugging is limited to Windows hosts
- @no_debug_info_test
def test_process_info_in_mini_dump(self):
"""Test that lldb can read the process information from the minidump."""
# target create -c fizzbuzz_no_heap.dmp
@@ -27,23 +27,20 @@ class MiniDumpTestCase(TestBase):
self.assertEqual(self.process.GetNumThreads(), 1)
self.assertEqual(self.process.GetProcessID(), 4440)
- @skipUnlessWindows # for now mini-dump debugging is limited to Windows hosts
- @no_debug_info_test
def test_thread_info_in_mini_dump(self):
"""Test that lldb can read the thread information from the minidump."""
# target create -c fizzbuzz_no_heap.dmp
self.dbg.CreateTarget("")
self.target = self.dbg.GetSelectedTarget()
self.process = self.target.LoadCore("fizzbuzz_no_heap.dmp")
- # This process crashed due to an access violation (0xc0000005) in its one and only thread.
+ # This process crashed due to an access violation (0xc0000005) in its
+ # one and only thread.
self.assertEqual(self.process.GetNumThreads(), 1)
thread = self.process.GetThreadAtIndex(0)
self.assertEqual(thread.GetStopReason(), lldb.eStopReasonException)
- stop_description = thread.GetStopDescription(256);
- self.assertTrue("0xc0000005" in stop_description);
+ stop_description = thread.GetStopDescription(256)
+ self.assertTrue("0xc0000005" in stop_description)
- @skipUnlessWindows # for now mini-dump debugging is limited to Windows hosts
- @no_debug_info_test
def test_stack_info_in_mini_dump(self):
"""Test that we can see a trivial stack in a VS-generate mini dump."""
# target create -c fizzbuzz_no_heap.dmp
@@ -61,8 +58,7 @@ class MiniDumpTestCase(TestBase):
self.assertTrue(eip.IsValid())
self.assertEqual(pc, eip.GetValueAsUnsigned())
- @skipUnlessWindows
- @not_remote_testsuite_ready
+ @skipUnlessWindows # Minidump saving works only on windows
def test_deeper_stack_in_mini_dump(self):
"""Test that we can examine a more interesting stack in a mini dump."""
self.build()
@@ -72,7 +68,8 @@ class MiniDumpTestCase(TestBase):
# Set a breakpoint and capture a mini dump.
target = self.dbg.CreateTarget(exe)
breakpoint = target.BreakpointCreateByName("bar")
- process = target.LaunchSimple(None, None, self.get_process_working_directory())
+ process = target.LaunchSimple(
+ None, None, self.get_process_working_directory())
self.assertEqual(process.GetState(), lldb.eStateStopped)
self.assertTrue(process.SaveCore(core))
self.assertTrue(os.path.isfile(core))
@@ -83,7 +80,7 @@ class MiniDumpTestCase(TestBase):
process = target.LoadCore(core)
thread = process.GetThreadAtIndex(0)
- expected_stack = { 0: 'bar', 1: 'foo', 2: 'main' }
+ expected_stack = {0: 'bar', 1: 'foo', 2: 'main'}
self.assertGreaterEqual(thread.GetNumFrames(), len(expected_stack))
for index, name in iteritems(expected_stack):
frame = thread.GetFrameAtIndex(index)
@@ -97,8 +94,7 @@ class MiniDumpTestCase(TestBase):
if (os.path.isfile(core)):
os.unlink(core)
- @skipUnlessWindows
- @not_remote_testsuite_ready
+ @skipUnlessWindows # Minidump saving works only on windows
def test_local_variables_in_mini_dump(self):
"""Test that we can examine local variables in a mini dump."""
self.build()
@@ -108,7 +104,8 @@ class MiniDumpTestCase(TestBase):
# Set a breakpoint and capture a mini dump.
target = self.dbg.CreateTarget(exe)
breakpoint = target.BreakpointCreateByName("bar")
- process = target.LaunchSimple(None, None, self.get_process_working_directory())
+ process = target.LaunchSimple(
+ None, None, self.get_process_working_directory())
self.assertEqual(process.GetState(), lldb.eStateStopped)
self.assertTrue(process.SaveCore(core))
self.assertTrue(os.path.isfile(core))
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/TestWow64MiniDump.py b/packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/TestWow64MiniDump.py
index 08debab538f5..73ad3940aca2 100644
--- a/packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/TestWow64MiniDump.py
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/TestWow64MiniDump.py
@@ -16,12 +16,12 @@ from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
+
class Wow64MiniDumpTestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
+ NO_DEBUG_INFO_TESTCASE = True
- @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
@@ -31,8 +31,6 @@ class Wow64MiniDumpTestCase(TestBase):
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
@@ -49,8 +47,6 @@ class Wow64MiniDumpTestCase(TestBase):
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
@@ -66,7 +62,8 @@ class Wow64MiniDumpTestCase(TestBase):
# 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.
+ # 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())