diff options
Diffstat (limited to 'gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities')
880 files changed, 44209 insertions, 0 deletions
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/abbreviation/.categories b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/abbreviation/.categories new file mode 100644 index 00000000000..3a3f4df6416 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/abbreviation/.categories @@ -0,0 +1 @@ +cmdline diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/abbreviation/TestAbbreviations.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/abbreviation/TestAbbreviations.py new file mode 100644 index 00000000000..4a129bbcd3e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/abbreviation/TestAbbreviations.py @@ -0,0 +1,107 @@ +""" +Test some lldb command abbreviations and aliases for proper resolution. +""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class AbbreviationsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @no_debug_info_test + def test_command_abbreviations_and_aliases(self): + command_interpreter = self.dbg.GetCommandInterpreter() + self.assertTrue(command_interpreter, VALID_COMMAND_INTERPRETER) + result = lldb.SBCommandReturnObject() + + # Check that abbreviations are expanded to the full command. + command_interpreter.ResolveCommand("ap script", result) + self.assertTrue(result.Succeeded()) + self.assertEqual("apropos script", result.GetOutput()) + + command_interpreter.ResolveCommand("h", result) + self.assertTrue(result.Succeeded()) + self.assertEqual("help", result.GetOutput()) + + # Check resolution of abbreviations for multi-word commands. + command_interpreter.ResolveCommand("lo li", result) + self.assertTrue(result.Succeeded()) + self.assertEqual("log list", result.GetOutput()) + + command_interpreter.ResolveCommand("br s", result) + self.assertTrue(result.Succeeded()) + self.assertEqual("breakpoint set", result.GetOutput()) + + # Try an ambiguous abbreviation. + # "pl" could be "platform" or "plugin". + command_interpreter.ResolveCommand("pl", result) + self.assertFalse(result.Succeeded()) + self.assertTrue(result.GetError().startswith("Ambiguous command")) + + # Make sure an unabbreviated command is not mangled. + command_interpreter.ResolveCommand( + "breakpoint set --name main --line 123", result) + self.assertTrue(result.Succeeded()) + self.assertEqual( + "breakpoint set --name main --line 123", + result.GetOutput()) + + # Create some aliases. + self.runCmd("com a alias com al") + self.runCmd("alias gurp help") + + # Check that an alias is replaced with the actual command + command_interpreter.ResolveCommand("gurp target create", result) + self.assertTrue(result.Succeeded()) + self.assertEqual("help target create", result.GetOutput()) + + # Delete the alias and make sure it no longer has an effect. + self.runCmd("com u gurp") + command_interpreter.ResolveCommand("gurp", result) + self.assertFalse(result.Succeeded()) + + # Check aliases with text replacement. + self.runCmd("alias pltty process launch -s -o %1 -e %1") + command_interpreter.ResolveCommand("pltty /dev/tty0", result) + self.assertTrue(result.Succeeded()) + self.assertEqual( + "process launch -s -o /dev/tty0 -e /dev/tty0", + result.GetOutput()) + + self.runCmd("alias xyzzy breakpoint set -n %1 -l %2") + command_interpreter.ResolveCommand("xyzzy main 123", result) + self.assertTrue(result.Succeeded()) + self.assertEqual( + "breakpoint set -n main -l 123", + result.GetOutput().strip()) + + # And again, without enough parameters. + command_interpreter.ResolveCommand("xyzzy main", result) + self.assertFalse(result.Succeeded()) + + # Check a command that wants the raw input. + command_interpreter.ResolveCommand( + r'''sc print("\n\n\tHello!\n")''', result) + self.assertTrue(result.Succeeded()) + self.assertEqual( + r'''script print("\n\n\tHello!\n")''', + result.GetOutput()) + + # Prompt changing stuff should be tested, but this doesn't seem like the + # right test to do it in. It has nothing to do with aliases or abbreviations. + #self.runCmd("com sou ./change_prompt.lldb") + # self.expect("settings show prompt", + # startstr = 'prompt (string) = "[with-three-trailing-spaces] "') + #self.runCmd("settings clear prompt") + # self.expect("settings show prompt", + # startstr = 'prompt (string) = "(lldb) "') + #self.runCmd("se se prompt 'Sycamore> '") + # self.expect("se sh prompt", + # startstr = 'prompt (string) = "Sycamore> "') + #self.runCmd("se cl prompt") + # self.expect("set sh prompt", + # startstr = 'prompt (string) = "(lldb) "') diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/abbreviation/TestCommonShortSpellings.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/abbreviation/TestCommonShortSpellings.py new file mode 100644 index 00000000000..9e4b3bb9d2d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/abbreviation/TestCommonShortSpellings.py @@ -0,0 +1,38 @@ +""" +Test some lldb command abbreviations to make sure the common short spellings of +many commands remain available even after we add/delete commands in the future. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class CommonShortSpellingsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @no_debug_info_test + def test_abbrevs2(self): + command_interpreter = self.dbg.GetCommandInterpreter() + self.assertTrue(command_interpreter, VALID_COMMAND_INTERPRETER) + result = lldb.SBCommandReturnObject() + + abbrevs = [ + ('br s', 'breakpoint set'), + ('disp', '_regexp-display'), # a.k.a., 'display' + ('di', 'disassemble'), + ('dis', 'disassemble'), + ('ta st a', 'target stop-hook add'), + ('fr v', 'frame variable'), + ('f 1', 'frame select 1'), + ('ta st li', 'target stop-hook list'), + ] + + for (short_val, long_val) in abbrevs: + command_interpreter.ResolveCommand(short_val, result) + self.assertTrue(result.Succeeded()) + self.assertEqual(long_val, result.GetOutput()) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/alias/.categories b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/alias/.categories new file mode 100644 index 00000000000..3a3f4df6416 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/alias/.categories @@ -0,0 +1 @@ +cmdline diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/archives/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/archives/Makefile new file mode 100644 index 00000000000..4d1950cf34a --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/archives/Makefile @@ -0,0 +1,7 @@ +C_SOURCES := main.c + +MAKE_DSYM := NO +ARCHIVE_NAME := libfoo.a +ARCHIVE_C_SOURCES := a.c b.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/archives/README b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/archives/README new file mode 100644 index 00000000000..d327f4585c6 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/archives/README @@ -0,0 +1,62 @@ +a.out file refers to libfoo.a for a.o and b.o, which is what we want to accomplish for +this test case. + +[16:17:44] johnny:/Volumes/data/lldb/svn/latest/test/functionalities/archives $ dsymutil -s a.out +---------------------------------------------------------------------- +Symbol table for: 'a.out' (x86_64) +---------------------------------------------------------------------- +Index n_strx n_type n_sect n_desc n_value +======== -------- ------------------ ------ ------ ---------------- +[ 0] 00000002 64 (N_SO ) 00 0000 0000000000000000 '/Volumes/data/lldb/svn/latest/test/functionalities/archives/' +[ 1] 0000003f 64 (N_SO ) 00 0000 0000000000000000 'main.c' +[ 2] 00000046 66 (N_OSO ) 03 0001 000000004f0f780c '/Volumes/data/lldb/svn/latest/test/functionalities/archives/main.o' +[ 3] 00000001 2e (N_BNSYM ) 01 0000 0000000100000d70 +[ 4] 00000089 24 (N_FUN ) 01 0000 0000000100000d70 '_main' +[ 5] 00000001 24 (N_FUN ) 00 0000 000000000000005d +[ 6] 00000001 4e (N_ENSYM ) 01 0000 000000000000005d +[ 7] 00000001 64 (N_SO ) 01 0000 0000000000000000 +[ 8] 00000002 64 (N_SO ) 00 0000 0000000000000000 '/Volumes/data/lldb/svn/latest/test/functionalities/archives/' +[ 9] 0000008f 64 (N_SO ) 00 0000 0000000000000000 'a.c' +[ 10] 00000093 66 (N_OSO ) 03 0001 000000004f0f780c '/Volumes/data/lldb/svn/latest/test/functionalities/archives/libfoo.a(a.o)' +[ 11] 00000001 2e (N_BNSYM ) 01 0000 0000000100000dd0 +[ 12] 000000dd 24 (N_FUN ) 01 0000 0000000100000dd0 '_a' +[ 13] 00000001 24 (N_FUN ) 00 0000 0000000000000020 +[ 14] 00000001 4e (N_ENSYM ) 01 0000 0000000000000020 +[ 15] 00000001 2e (N_BNSYM ) 01 0000 0000000100000df0 +[ 16] 000000e0 24 (N_FUN ) 01 0000 0000000100000df0 '_aa' +[ 17] 00000001 24 (N_FUN ) 00 0000 0000000000000018 +[ 18] 00000001 4e (N_ENSYM ) 01 0000 0000000000000018 +[ 19] 000000e4 20 (N_GSYM ) 00 0000 0000000000000000 '___a_global' +[ 20] 00000001 64 (N_SO ) 01 0000 0000000000000000 +[ 21] 00000002 64 (N_SO ) 00 0000 0000000000000000 '/Volumes/data/lldb/svn/latest/test/functionalities/archives/' +[ 22] 000000f0 64 (N_SO ) 00 0000 0000000000000000 'b.c' +[ 23] 000000f4 66 (N_OSO ) 03 0001 000000004f0f780c '/Volumes/data/lldb/svn/latest/test/functionalities/archives/libfoo.a(b.o)' +[ 24] 00000001 2e (N_BNSYM ) 01 0000 0000000100000e10 +[ 25] 0000013e 24 (N_FUN ) 01 0000 0000000100000e10 '_b' +[ 26] 00000001 24 (N_FUN ) 00 0000 0000000000000020 +[ 27] 00000001 4e (N_ENSYM ) 01 0000 0000000000000020 +[ 28] 00000001 2e (N_BNSYM ) 01 0000 0000000100000e30 +[ 29] 00000141 24 (N_FUN ) 01 0000 0000000100000e30 '_bb' +[ 30] 00000001 24 (N_FUN ) 00 0000 0000000000000018 +[ 31] 00000001 4e (N_ENSYM ) 01 0000 0000000000000018 +[ 32] 00000145 26 (N_STSYM ) 0a 0000 000000010000104c '___b_global' +[ 33] 00000001 64 (N_SO ) 01 0000 0000000000000000 +[ 34] 00000151 0e ( SECT ) 07 0000 0000000100001000 '_pvars' +[ 35] 00000158 0e ( SECT ) 0a 0000 000000010000104c '___b_global' +[ 36] 00000164 0f ( SECT EXT) 0b 0000 0000000100001050 '_NXArgc' +[ 37] 0000016c 0f ( SECT EXT) 0b 0000 0000000100001058 '_NXArgv' +[ 38] 00000174 0f ( SECT EXT) 0a 0000 0000000100001048 '___a_global' +[ 39] 00000180 0f ( SECT EXT) 0b 0000 0000000100001068 '___progname' +[ 40] 0000018c 03 ( ABS EXT) 01 0010 0000000100000000 '__mh_execute_header' +[ 41] 000001a0 0f ( SECT EXT) 01 0000 0000000100000dd0 '_a' +[ 42] 000001a3 0f ( SECT EXT) 01 0000 0000000100000df0 '_aa' +[ 43] 000001a7 0f ( SECT EXT) 01 0000 0000000100000e10 '_b' +[ 44] 000001aa 0f ( SECT EXT) 01 0000 0000000100000e30 '_bb' +[ 45] 000001ae 0f ( SECT EXT) 0b 0000 0000000100001060 '_environ' +[ 46] 000001b7 0f ( SECT EXT) 01 0000 0000000100000d70 '_main' +[ 47] 000001bd 0f ( SECT EXT) 01 0000 0000000100000d30 'start' +[ 48] 000001c3 01 ( UNDF EXT) 00 0100 0000000000000000 '_exit' +[ 49] 000001c9 01 ( UNDF EXT) 00 0100 0000000000000000 '_printf' +[ 50] 000001d1 01 ( UNDF EXT) 00 0100 0000000000000000 'dyld_stub_binder' + + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/archives/TestBSDArchives.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/archives/TestBSDArchives.py new file mode 100644 index 00000000000..b412ac4c135 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/archives/TestBSDArchives.py @@ -0,0 +1,61 @@ +"""Test breaking inside functions defined within a BSD archive file libfoo.a.""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class BSDArchivesTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number in a(int) to break at. + self.line = line_number( + 'a.c', '// Set file and line breakpoint inside a().') + + @expectedFailureAll( + oslist=["windows"], + bugnumber="llvm.org/pr24527. Makefile.rules doesn't know how to build static libs on Windows") + def test(self): + """Break inside a() and b() defined within libfoo.a.""" + self.build() + + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Break inside a() by file and line first. + lldbutil.run_break_set_by_file_and_line( + self, "a.c", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # Break at a(int) first. + self.expect("frame variable", VARIABLES_DISPLAYED_CORRECTLY, + substrs=['(int) arg = 1']) + self.expect("frame variable __a_global", VARIABLES_DISPLAYED_CORRECTLY, + substrs=['(int) __a_global = 1']) + + # Set breakpoint for b() next. + lldbutil.run_break_set_by_symbol( + self, "b", num_expected_locations=1, sym_exact=True) + + # Continue the program, we should break at b(int) next. + self.runCmd("continue") + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + self.expect("frame variable", VARIABLES_DISPLAYED_CORRECTLY, + substrs=['(int) arg = 2']) + self.expect("frame variable __b_global", VARIABLES_DISPLAYED_CORRECTLY, + substrs=['(int) __b_global = 2']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/archives/a.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/archives/a.c new file mode 100644 index 00000000000..c8d226ab9de --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/archives/a.c @@ -0,0 +1,18 @@ +//===-- a.c -----------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +int __a_global = 1; + +int a(int arg) { + int result = arg + __a_global; + return result; // Set file and line breakpoint inside a(). +} + +int aa(int arg1) { + int result1 = arg1 - __a_global; + return result1; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/archives/b.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/archives/b.c new file mode 100644 index 00000000000..6510b978f37 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/archives/b.c @@ -0,0 +1,18 @@ +//===-- b.c -----------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +static int __b_global = 2; + +int b(int arg) { + int result = arg + __b_global; + return result; +} + +int bb(int arg1) { + int result2 = arg1 - __b_global; + return result2; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/archives/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/archives/main.c new file mode 100644 index 00000000000..1525a1a5e38 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/archives/main.c @@ -0,0 +1,16 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include <stdio.h> + +extern int a(int); +extern int b(int); +int main (int argc, char const *argv[]) +{ + printf ("a(1) returns %d\n", a(1)); + printf ("b(2) returns %d\n", b(2)); +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/asan/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/asan/Makefile new file mode 100644 index 00000000000..4913a18d8cc --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/asan/Makefile @@ -0,0 +1,4 @@ +C_SOURCES := main.c +CFLAGS_EXTRAS := -fsanitize=address -g -gcolumn-info + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/asan/TestMemoryHistory.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/asan/TestMemoryHistory.py new file mode 100644 index 00000000000..4df315127f6 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/asan/TestMemoryHistory.py @@ -0,0 +1,129 @@ +""" +Test that ASan memory history provider returns correct stack traces +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbplatform +from lldbsuite.test import lldbutil + + +class AsanTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipIfFreeBSD # llvm.org/pr21136 runtimes not yet available by default + @expectedFailureNetBSD + @skipUnlessAddressSanitizer + def test(self): + self.build() + self.asan_tests() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + self.line_malloc = line_number('main.c', '// malloc line') + self.line_malloc2 = line_number('main.c', '// malloc2 line') + self.line_free = line_number('main.c', '// free line') + self.line_breakpoint = line_number('main.c', '// break line') + + def asan_tests(self): + exe = self.getBuildArtifact("a.out") + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + self.registerSanitizerLibrariesWithTarget(target) + + self.runCmd("breakpoint set -f main.c -l %d" % self.line_breakpoint) + + # "memory history" command should not work without a process + self.expect("memory history 0", + error=True, + substrs=["invalid process"]) + + self.runCmd("run") + + stop_reason = self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason() + if stop_reason == lldb.eStopReasonExec: + # On OS X 10.10 and older, we need to re-exec to enable + # interceptors. + self.runCmd("continue") + + # the stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', 'stop reason = breakpoint']) + + # test that the ASan dylib is present + self.expect( + "image lookup -n __asan_describe_address", + "__asan_describe_address should be present", + substrs=['1 match found']) + + # test the 'memory history' command + self.expect( + "memory history 'pointer'", + substrs=[ + 'Memory allocated by Thread', + 'a.out`f1', + 'main.c:%d' % + self.line_malloc, + 'Memory deallocated by Thread', + 'a.out`f2', + 'main.c:%d' % + self.line_free]) + + # do the same using SB API + process = self.dbg.GetSelectedTarget().process + val = process.GetSelectedThread().GetSelectedFrame().EvaluateExpression("pointer") + addr = val.GetValueAsUnsigned() + threads = process.GetHistoryThreads(addr) + self.assertEqual(threads.GetSize(), 2) + + history_thread = threads.GetThreadAtIndex(0) + self.assertTrue(history_thread.num_frames >= 2) + self.assertEqual(history_thread.frames[1].GetLineEntry( + ).GetFileSpec().GetFilename(), "main.c") + self.assertEqual( + history_thread.frames[1].GetLineEntry().GetLine(), + self.line_free) + + history_thread = threads.GetThreadAtIndex(1) + self.assertTrue(history_thread.num_frames >= 2) + self.assertEqual(history_thread.frames[1].GetLineEntry( + ).GetFileSpec().GetFilename(), "main.c") + self.assertEqual( + history_thread.frames[1].GetLineEntry().GetLine(), + self.line_malloc) + + # let's free the container (SBThreadCollection) and see if the + # SBThreads still live + threads = None + self.assertTrue(history_thread.num_frames >= 2) + self.assertEqual(history_thread.frames[1].GetLineEntry( + ).GetFileSpec().GetFilename(), "main.c") + self.assertEqual( + history_thread.frames[1].GetLineEntry().GetLine(), + self.line_malloc) + + # ASan will break when a report occurs and we'll try the API then + self.runCmd("continue") + + self.expect( + "thread list", + "Process should be stopped due to ASan report", + substrs=[ + 'stopped', + 'stop reason = Use of deallocated memory']) + + # make sure the 'memory history' command still works even when we're + # generating a report now + self.expect( + "memory history 'another_pointer'", + substrs=[ + 'Memory allocated by Thread', + 'a.out`f1', + 'main.c:%d' % + self.line_malloc2]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/asan/TestReportData.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/asan/TestReportData.py new file mode 100644 index 00000000000..0ca48435e82 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/asan/TestReportData.py @@ -0,0 +1,91 @@ +""" +Test the AddressSanitizer runtime support for report breakpoint and data extraction. +""" + + + +import json +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class AsanTestReportDataCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipIfFreeBSD # llvm.org/pr21136 runtimes not yet available by default + @expectedFailureNetBSD + @skipUnlessAddressSanitizer + @skipIf(archs=['i386'], bugnumber="llvm.org/PR36710") + def test(self): + self.build() + self.asan_tests() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + self.line_malloc = line_number('main.c', '// malloc line') + self.line_malloc2 = line_number('main.c', '// malloc2 line') + self.line_free = line_number('main.c', '// free line') + self.line_breakpoint = line_number('main.c', '// break line') + self.line_crash = line_number('main.c', '// BOOM line') + self.col_crash = 16 + + def asan_tests(self): + exe = self.getBuildArtifact("a.out") + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + self.registerSanitizerLibrariesWithTarget(target) + + self.runCmd("run") + + stop_reason = self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason() + if stop_reason == lldb.eStopReasonExec: + # On OS X 10.10 and older, we need to re-exec to enable + # interceptors. + self.runCmd("continue") + + self.expect( + "thread list", + "Process should be stopped due to ASan report", + substrs=[ + 'stopped', + 'stop reason = Use of deallocated memory']) + + self.assertEqual( + self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason(), + lldb.eStopReasonInstrumentation) + + self.expect("bt", "The backtrace should show the crashing line", + substrs=['main.c:%d:%d' % (self.line_crash, self.col_crash)]) + + self.expect( + "thread info -s", + "The extended stop info should contain the ASan provided fields", + substrs=[ + "access_size", + "access_type", + "address", + "pc", + "description", + "heap-use-after-free"]) + + output_lines = self.res.GetOutput().split('\n') + json_line = '\n'.join(output_lines[2:]) + data = json.loads(json_line) + self.assertEqual(data["description"], "heap-use-after-free") + self.assertEqual(data["instrumentation_class"], "AddressSanitizer") + self.assertEqual(data["stop_type"], "fatal_error") + + # now let's try the SB API + process = self.dbg.GetSelectedTarget().process + thread = process.GetSelectedThread() + + s = lldb.SBStream() + self.assertTrue(thread.GetStopReasonExtendedInfoAsJSON(s)) + s = s.GetData() + data2 = json.loads(s) + self.assertEqual(data, data2) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/asan/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/asan/main.c new file mode 100644 index 00000000000..45f9f4f9fb7 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/asan/main.c @@ -0,0 +1,33 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include <stdio.h> +#include <stdlib.h> + +char *pointer; +char *another_pointer; + +void f1() { + pointer = malloc(10); // malloc line + another_pointer = malloc(20); // malloc2 line +} + +void f2() { + free(pointer); // free line +} + +int main (int argc, char const *argv[]) +{ + f1(); + f2(); + + printf("Hello world!\n"); // break line + + pointer[0] = 'A'; // BOOM line + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/avoids-fd-leak/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/avoids-fd-leak/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/avoids-fd-leak/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/avoids-fd-leak/TestFdLeak.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/avoids-fd-leak/TestFdLeak.py new file mode 100644 index 00000000000..a984254fff9 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/avoids-fd-leak/TestFdLeak.py @@ -0,0 +1,106 @@ +""" +Test whether a process started by lldb has no extra file descriptors open. +""" + + + +import lldb +from lldbsuite.test import lldbutil +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * + + +def python_leaky_fd_version(test): + import sys + # Python random module leaks file descriptors on some versions. + if sys.version_info >= (2, 7, 8) and sys.version_info < (2, 7, 10): + return "Python random module leaks file descriptors in this python version" + return None + + +class AvoidsFdLeakTestCase(TestBase): + + NO_DEBUG_INFO_TESTCASE = True + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailure(python_leaky_fd_version, "bugs.freebsd.org/197376") + @expectedFailureAll( + oslist=['freebsd'], + bugnumber="llvm.org/pr25624 still failing with Python 2.7.10") + # The check for descriptor leakage needs to be implemented differently + # here. + @skipIfWindows + @skipIfTargetAndroid() # Android have some other file descriptors open by the shell + @skipIfDarwinEmbedded # <rdar://problem/33888742> # debugserver on ios has an extra fd open on launch + def test_fd_leak_basic(self): + self.do_test([]) + + @expectedFailure(python_leaky_fd_version, "bugs.freebsd.org/197376") + @expectedFailureAll( + oslist=['freebsd'], + bugnumber="llvm.org/pr25624 still failing with Python 2.7.10") + # The check for descriptor leakage needs to be implemented differently + # here. + @skipIfWindows + @skipIfTargetAndroid() # Android have some other file descriptors open by the shell + @skipIfDarwinEmbedded # <rdar://problem/33888742> # debugserver on ios has an extra fd open on launch + def test_fd_leak_log(self): + self.do_test(["log enable -f '/dev/null' lldb commands"]) + + def do_test(self, commands): + self.build() + exe = self.getBuildArtifact("a.out") + + for c in commands: + self.runCmd(c) + + target = self.dbg.CreateTarget(exe) + + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + self.assertTrue( + process.GetState() == lldb.eStateExited, + "Process should have exited.") + self.assertTrue( + process.GetExitStatus() == 0, + "Process returned non-zero status. Were incorrect file descriptors passed?") + + @expectedFailure(python_leaky_fd_version, "bugs.freebsd.org/197376") + @expectedFailureAll( + oslist=['freebsd'], + bugnumber="llvm.org/pr25624 still failing with Python 2.7.10") + # The check for descriptor leakage needs to be implemented differently + # here. + @skipIfWindows + @skipIfTargetAndroid() # Android have some other file descriptors open by the shell + @skipIfDarwinEmbedded # <rdar://problem/33888742> # debugserver on ios has an extra fd open on launch + def test_fd_leak_multitarget(self): + self.build() + exe = self.getBuildArtifact("a.out") + + target = self.dbg.CreateTarget(exe) + breakpoint = target.BreakpointCreateBySourceRegex( + 'Set breakpoint here', lldb.SBFileSpec("main.c", False)) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + process1 = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process1, PROCESS_IS_VALID) + self.assertTrue( + process1.GetState() == lldb.eStateStopped, + "Process should have been stopped.") + + target2 = self.dbg.CreateTarget(exe) + process2 = target2.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process2, PROCESS_IS_VALID) + + self.assertTrue( + process2.GetState() == lldb.eStateExited, + "Process should have exited.") + self.assertTrue( + process2.GetExitStatus() == 0, + "Process returned non-zero status. Were incorrect file descriptors passed?") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/avoids-fd-leak/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/avoids-fd-leak/main.c new file mode 100644 index 00000000000..5bdf227928e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/avoids-fd-leak/main.c @@ -0,0 +1,28 @@ +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <errno.h> +#include <stdio.h> + +int +main (int argc, char const **argv) +{ + struct stat buf; + int i, rv = 0; // Set breakpoint here. + + // Make sure stdin/stdout/stderr exist. + for (i = 0; i <= 2; ++i) { + if (fstat(i, &buf) != 0) + return 1; + } + + // Make sure no other file descriptors are open. + for (i = 3; i <= 256; ++i) { + if (fstat(i, &buf) == 0 || errno != EBADF) { + fprintf(stderr, "File descriptor %d is open.\n", i); + rv = 2; + } + } + + return rv; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/backticks/.categories b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/backticks/.categories new file mode 100644 index 00000000000..3a3f4df6416 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/backticks/.categories @@ -0,0 +1 @@ +cmdline diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/backticks/TestBackticksWithoutATarget.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/backticks/TestBackticksWithoutATarget.py new file mode 100644 index 00000000000..fdef89c6e05 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/backticks/TestBackticksWithoutATarget.py @@ -0,0 +1,21 @@ +""" +Test that backticks without a target should work (not infinite looping). +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class BackticksWithNoTargetTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @no_debug_info_test + def test_backticks_no_target(self): + """A simple test of backticks without a target.""" + self.expect("print `1+2-3`", + substrs=[' = 0']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/Makefile new file mode 100644 index 00000000000..695335e068c --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/Makefile @@ -0,0 +1,4 @@ +C_SOURCES := main.c +CFLAGS_EXTRAS := -std=c99 + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/TestAddressBreakpoints.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/TestAddressBreakpoints.py new file mode 100644 index 00000000000..6b42b51d16a --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/TestAddressBreakpoints.py @@ -0,0 +1,91 @@ +""" +Test address breakpoints set with shared library of SBAddress work correctly. +""" + + + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + + +class AddressBreakpointTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + def test_address_breakpoints(self): + """Test address breakpoints set with shared library of SBAddress work correctly.""" + self.build() + self.address_breakpoints() + + def address_breakpoints(self): + """Test address breakpoints set with shared library of SBAddress work correctly.""" + exe = self.getBuildArtifact("a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create a breakpoint on main.c by name 'c'. + breakpoint = target.BreakpointCreateBySourceRegex( + "Set a breakpoint here", lldb.SBFileSpec("main.c")) + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() >= 1, + VALID_BREAKPOINT) + + # Get the breakpoint location from breakpoint after we verified that, + # indeed, it has one location. + location = breakpoint.GetLocationAtIndex(0) + self.assertTrue(location and + location.IsEnabled(), + VALID_BREAKPOINT_LOCATION) + + # Next get the address from the location, and create an address breakpoint using + # that address: + + address = location.GetAddress() + target.BreakpointDelete(breakpoint.GetID()) + + breakpoint = target.BreakpointCreateBySBAddress(address) + + # Disable ASLR. This will allow us to actually test (on platforms that support this flag) + # that the breakpoint was able to track the module. + + launch_info = lldb.SBLaunchInfo(None) + flags = launch_info.GetLaunchFlags() + flags &= ~lldb.eLaunchFlagDisableASLR + launch_info.SetLaunchFlags(flags) + + error = lldb.SBError() + + process = target.Launch(launch_info, error) + self.assertTrue(process, PROCESS_IS_VALID) + + # Did we hit our breakpoint? + from lldbsuite.test.lldbutil import get_threads_stopped_at_breakpoint + threads = get_threads_stopped_at_breakpoint(process, breakpoint) + self.assertTrue( + len(threads) == 1, + "There should be a thread stopped at our breakpoint") + + # The hit count for the breakpoint should be 1. + self.assertTrue(breakpoint.GetHitCount() == 1) + + process.Kill() + + # Now re-launch and see that we hit the breakpoint again: + launch_info.Clear() + launch_info.SetLaunchFlags(flags) + + process = target.Launch(launch_info, error) + self.assertTrue(process, PROCESS_IS_VALID) + + thread = get_threads_stopped_at_breakpoint(process, breakpoint) + self.assertTrue( + len(threads) == 1, + "There should be a thread stopped at our breakpoint") + + # The hit count for the breakpoint should now be 2. + self.assertTrue(breakpoint.GetHitCount() == 2) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/TestBadAddressBreakpoints.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/TestBadAddressBreakpoints.py new file mode 100644 index 00000000000..6d468e0fd64 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/TestBadAddressBreakpoints.py @@ -0,0 +1,42 @@ +""" +Test that breakpoints set on a bad address say they are bad. +""" + + + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + + +class BadAddressBreakpointTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + def test_bad_address_breakpoints(self): + """Test that breakpoints set on a bad address say they are bad.""" + self.build() + self.address_breakpoints() + + def address_breakpoints(self): + """Test that breakpoints set on a bad address say they are bad.""" + target, process, thread, bkpt = \ + lldbutil.run_to_source_breakpoint(self, + "Set a breakpoint here", + lldb.SBFileSpec("main.c")) + + # Now see if we can read from 0. If I can't do that, I don't + # have a good way to know what an illegal address is... + error = lldb.SBError() + + ptr = process.ReadPointerFromMemory(0x0, error) + + if not error.Success(): + bkpt = target.BreakpointCreateByAddress(0x0) + for bp_loc in bkpt: + self.assertTrue(bp_loc.IsResolved() == False) + else: + self.fail( + "Could not find an illegal address at which to set a bad breakpoint.") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/main.c new file mode 100644 index 00000000000..6b779296e18 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/main.c @@ -0,0 +1,8 @@ +#include <stdio.h> + +int +main() +{ + printf ("Set a breakpoint here.\n"); + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/auto_continue/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/auto_continue/Makefile new file mode 100644 index 00000000000..695335e068c --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/auto_continue/Makefile @@ -0,0 +1,4 @@ +C_SOURCES := main.c +CFLAGS_EXTRAS := -std=c99 + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/auto_continue/TestBreakpointAutoContinue.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/auto_continue/TestBreakpointAutoContinue.py new file mode 100644 index 00000000000..e0b727e9734 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/auto_continue/TestBreakpointAutoContinue.py @@ -0,0 +1,96 @@ +""" +Test that the breakpoint auto-continue flag works correctly. +""" + + + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + + +class BreakpointAutoContinue(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + def test_breakpoint_auto_continue(self): + """Make sure the auto continue continues with no other complications""" + self.build() + self.simple_auto_continue() + + def test_auto_continue_with_command(self): + """Add a command, make sure the command gets run""" + self.build() + self.auto_continue_with_command() + + def test_auto_continue_on_location(self): + """Set auto-continue on a location and make sure only that location continues""" + self.build() + self.auto_continue_location() + + def make_target_and_bkpt(self, additional_options=None, num_expected_loc=1, + pattern="Set a breakpoint here"): + exe = self.getBuildArtifact("a.out") + self.target = self.dbg.CreateTarget(exe) + self.assertTrue(self.target.IsValid(), "Target is not valid") + + extra_options_txt = "--auto-continue 1 " + if additional_options: + extra_options_txt += additional_options + bpno = lldbutil.run_break_set_by_source_regexp(self, pattern, + extra_options = extra_options_txt, + num_expected_locations = num_expected_loc) + return bpno + + def launch_it (self, expected_state): + error = lldb.SBError() + launch_info = lldb.SBLaunchInfo(None) + launch_info.SetWorkingDirectory(self.get_process_working_directory()) + + process = self.target.Launch(launch_info, error) + self.assertTrue(error.Success(), "Launch failed.") + + state = process.GetState() + self.assertEqual(state, expected_state, "Didn't get expected state") + + return process + + def simple_auto_continue(self): + bpno = self.make_target_and_bkpt() + process = self.launch_it(lldb.eStateExited) + + bkpt = self.target.FindBreakpointByID(bpno) + self.assertEqual(bkpt.GetHitCount(), 2, "Should have run through the breakpoint twice") + + def auto_continue_with_command(self): + bpno = self.make_target_and_bkpt("-N BKPT -C 'break modify --auto-continue 0 BKPT'") + process = self.launch_it(lldb.eStateStopped) + state = process.GetState() + self.assertEqual(state, lldb.eStateStopped, "Process should be stopped") + bkpt = self.target.FindBreakpointByID(bpno) + threads = lldbutil.get_threads_stopped_at_breakpoint(process, bkpt) + self.assertEqual(len(threads), 1, "There was a thread stopped at our breakpoint") + self.assertEqual(bkpt.GetHitCount(), 2, "Should have hit the breakpoint twice") + + def auto_continue_location(self): + bpno = self.make_target_and_bkpt(pattern="Set a[^ ]* breakpoint here", num_expected_loc=2) + bkpt = self.target.FindBreakpointByID(bpno) + bkpt.SetAutoContinue(False) + + loc = lldb.SBBreakpointLocation() + for i in range(0,2): + func_name = bkpt.location[i].GetAddress().function.name + if func_name == "main": + loc = bkpt.location[i] + + self.assertTrue(loc.IsValid(), "Didn't find a location in main") + loc.SetAutoContinue(True) + + process = self.launch_it(lldb.eStateStopped) + + threads = lldbutil.get_threads_stopped_at_breakpoint(process, bkpt) + self.assertEqual(len(threads), 1, "Didn't get one thread stopped at our breakpoint") + func_name = threads[0].frame[0].function.name + self.assertEqual(func_name, "call_me") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/auto_continue/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/auto_continue/main.c new file mode 100644 index 00000000000..a37f05e0290 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/auto_continue/main.c @@ -0,0 +1,19 @@ +#include <stdio.h> + +void +call_me() +{ + printf("Set another breakpoint here.\n"); +} + +int +main() +{ + int change_me = 0; + for (int i = 0; i < 2; i++) + { + printf ("Set a breakpoint here: %d with: %d.\n", i, change_me); + } + call_me(); + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/Makefile new file mode 100644 index 00000000000..ad42b20df4e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/Makefile @@ -0,0 +1,4 @@ +C_SOURCES := main.c +CFLAGS_EXTRAS := -std=c99 -gcolumn-info + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py new file mode 100644 index 00000000000..98fe4335cc2 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py @@ -0,0 +1,44 @@ +""" +Test setting a breakpoint by line and column. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class BreakpointByLineAndColumnTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + ## Skip gcc version less 7.1 since it doesn't support -gcolumn-info + @skipIf(compiler="gcc", compiler_version=['<', '7.1']) + def testBreakpointByLineAndColumn(self): + self.build() + main_c = lldb.SBFileSpec("main.c") + _, _, _, breakpoint = lldbutil.run_to_line_breakpoint(self, + main_c, 19, 50) + self.expect("fr v did_call", substrs='1') + in_then = False + for i in range(breakpoint.GetNumLocations()): + b_loc = breakpoint.GetLocationAtIndex(i).GetAddress().GetLineEntry() + self.assertEqual(b_loc.GetLine(), 19) + in_then |= b_loc.GetColumn() == 50 + self.assertTrue(in_then) + + ## Skip gcc version less 7.1 since it doesn't support -gcolumn-info + @skipIf(compiler="gcc", compiler_version=['<', '7.1']) + def testBreakpointByLine(self): + self.build() + main_c = lldb.SBFileSpec("main.c") + _, _, _, breakpoint = lldbutil.run_to_line_breakpoint(self, main_c, 19) + self.expect("fr v did_call", substrs='0') + in_condition = False + for i in range(breakpoint.GetNumLocations()): + b_loc = breakpoint.GetLocationAtIndex(i).GetAddress().GetLineEntry() + self.assertEqual(b_loc.GetLine(), 19) + in_condition |= b_loc.GetColumn() < 30 + self.assertTrue(in_condition) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/main.c new file mode 100644 index 00000000000..f9adad30575 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/main.c @@ -0,0 +1,22 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +int square(int x) +{ + return x * x; +} + +int main (int argc, char const *argv[]) +{ + int did_call = 0; + + // Line 20. v Column 50. + if(square(argc+1) != 0) { did_call = 1; return square(argc); } + // ^ + return square(0); +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/Makefile new file mode 100644 index 00000000000..8d669cbfd2b --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c a.c b.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py new file mode 100644 index 00000000000..77db8f745d7 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py @@ -0,0 +1,287 @@ +""" +Test lldb breakpoint command add/list/delete. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import side_effect + + +class BreakpointCommandTestCase(TestBase): + + NO_DEBUG_INFO_TESTCASE = True + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528") + def not_test_breakpoint_command_sequence(self): + """Test a sequence of breakpoint command add, list, and delete.""" + self.build() + self.breakpoint_command_sequence() + + @skipIf(oslist=["windows"], bugnumber="llvm.org/pr44431") + def test_script_parameters(self): + """Test a sequence of breakpoint command add, list, and delete.""" + self.build() + self.breakpoint_command_script_parameters() + + def test_commands_on_creation(self): + self.build() + self.breakpoint_commands_on_creation() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.line = line_number('main.c', '// Set break point at this line.') + # disable "There is a running process, kill it and restart?" prompt + self.runCmd("settings set auto-confirm true") + self.addTearDownHook( + lambda: self.runCmd("settings clear auto-confirm")) + + def test_delete_all_breakpoints(self): + """Test that deleting all breakpoints works.""" + self.build() + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_symbol(self, "main") + lldbutil.run_break_set_by_file_and_line( + self, "main.c", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + self.runCmd("breakpoint delete") + self.runCmd("process continue") + self.expect("process status", PROCESS_STOPPED, + patterns=['Process .* exited with status = 0']) + + + def breakpoint_command_sequence(self): + """Test a sequence of breakpoint command add, list, and delete.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Add three breakpoints on the same line. The first time we don't specify the file, + # since the default file is the one containing main: + lldbutil.run_break_set_by_file_and_line( + self, None, self.line, num_expected_locations=1, loc_exact=True) + lldbutil.run_break_set_by_file_and_line( + self, "main.c", self.line, num_expected_locations=1, loc_exact=True) + lldbutil.run_break_set_by_file_and_line( + self, "main.c", self.line, num_expected_locations=1, loc_exact=True) + # Breakpoint 4 - set at the same location as breakpoint 1 to test + # setting breakpoint commands on two breakpoints at a time + lldbutil.run_break_set_by_file_and_line( + self, None, self.line, num_expected_locations=1, loc_exact=True) + # Make sure relative path source breakpoints work as expected. We test + # with partial paths with and without "./" prefixes. + lldbutil.run_break_set_by_file_and_line( + self, "./main.c", self.line, + num_expected_locations=1, loc_exact=True) + lldbutil.run_break_set_by_file_and_line( + self, "breakpoint_command/main.c", self.line, + num_expected_locations=1, loc_exact=True) + lldbutil.run_break_set_by_file_and_line( + self, "./breakpoint_command/main.c", self.line, + num_expected_locations=1, loc_exact=True) + lldbutil.run_break_set_by_file_and_line( + self, "breakpoint/breakpoint_command/main.c", self.line, + num_expected_locations=1, loc_exact=True) + lldbutil.run_break_set_by_file_and_line( + self, "./breakpoint/breakpoint_command/main.c", self.line, + num_expected_locations=1, loc_exact=True) + # Test relative breakpoints with incorrect paths and make sure we get + # no breakpoint locations + lldbutil.run_break_set_by_file_and_line( + self, "invalid/main.c", self.line, + num_expected_locations=0, loc_exact=True) + lldbutil.run_break_set_by_file_and_line( + self, "./invalid/main.c", self.line, + num_expected_locations=0, loc_exact=True) + # Now add callbacks for the breakpoints just created. + self.runCmd( + "breakpoint command add -s command -o 'frame variable --show-types --scope' 1 4") + self.runCmd( + "breakpoint command add -s python -o 'import side_effect; side_effect.one_liner = \"one liner was here\"' 2") + + import side_effect + self.runCmd("command script import --allow-reload ./bktptcmd.py") + + self.runCmd( + "breakpoint command add --python-function bktptcmd.function 3") + + # Check that the breakpoint commands are correctly set. + + # The breakpoint list now only contains breakpoint 1. + self.expect( + "breakpoint list", "Breakpoints 1 & 2 created", substrs=[ + "2: file = 'main.c', line = %d, exact_match = 0, locations = 1" % + self.line], patterns=[ + "1: file = '.*main.c', line = %d, exact_match = 0, locations = 1" % + self.line]) + + self.expect( + "breakpoint list -f", + "Breakpoints 1 & 2 created", + substrs=[ + "2: file = 'main.c', line = %d, exact_match = 0, locations = 1" % + self.line], + patterns=[ + "1: file = '.*main.c', line = %d, exact_match = 0, locations = 1" % + self.line, + "1.1: .+at main.c:%d:?[0-9]*, .+unresolved, hit count = 0" % + self.line, + "2.1: .+at main.c:%d:?[0-9]*, .+unresolved, hit count = 0" % + self.line]) + + self.expect("breakpoint command list 1", "Breakpoint 1 command ok", + substrs=["Breakpoint commands:", + "frame variable --show-types --scope"]) + self.expect("breakpoint command list 2", "Breakpoint 2 command ok", + substrs=["Breakpoint commands (Python):", + "import side_effect", + "side_effect.one_liner"]) + self.expect("breakpoint command list 3", "Breakpoint 3 command ok", + substrs=["Breakpoint commands (Python):", + "bktptcmd.function(frame, bp_loc, internal_dict)"]) + + self.expect("breakpoint command list 4", "Breakpoint 4 command ok", + substrs=["Breakpoint commands:", + "frame variable --show-types --scope"]) + + self.runCmd("breakpoint delete 4") + + # Next lets try some other breakpoint kinds. First break with a regular expression + # and then specify only one file. The first time we should get two locations, + # the second time only one: + + lldbutil.run_break_set_by_regexp( + self, r"._MyFunction", num_expected_locations=2) + + lldbutil.run_break_set_by_regexp( + self, + r"._MyFunction", + extra_options="-f a.c", + num_expected_locations=1) + + lldbutil.run_break_set_by_regexp( + self, + r"._MyFunction", + extra_options="-f a.c -f b.c", + num_expected_locations=2) + + # Now try a source regex breakpoint: + lldbutil.run_break_set_by_source_regexp( + self, + r"is about to return [12]0", + extra_options="-f a.c -f b.c", + num_expected_locations=2) + + lldbutil.run_break_set_by_source_regexp( + self, + r"is about to return [12]0", + extra_options="-f a.c", + num_expected_locations=1) + + # Reset our canary variables and run the program. + side_effect.one_liner = None + side_effect.bktptcmd = None + self.runCmd("run", RUN_SUCCEEDED) + + # Check the value of canary variables. + self.assertEquals("one liner was here", side_effect.one_liner) + self.assertEquals("function was here", side_effect.bktptcmd) + + # Finish the program. + self.runCmd("process continue") + + # Remove the breakpoint command associated with breakpoint 1. + self.runCmd("breakpoint command delete 1") + + # Remove breakpoint 2. + self.runCmd("breakpoint delete 2") + + self.expect( + "breakpoint command list 1", + startstr="Breakpoint 1 does not have an associated command.") + self.expect( + "breakpoint command list 2", + error=True, + startstr="error: '2' is not a currently valid breakpoint ID.") + + # The breakpoint list now only contains breakpoint 1. + self.expect( + "breakpoint list -f", + "Breakpoint 1 exists", + patterns=[ + "1: file = '.*main.c', line = %d, exact_match = 0, locations = 1, resolved = 1" % + self.line, + "hit count = 1"]) + + # Not breakpoint 2. + self.expect( + "breakpoint list -f", + "No more breakpoint 2", + matching=False, + substrs=[ + "2: file = 'main.c', line = %d, exact_match = 0, locations = 1, resolved = 1" % + self.line]) + + # Run the program again, with breakpoint 1 remaining. + self.runCmd("run", RUN_SUCCEEDED) + + # We should be stopped again due to breakpoint 1. + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # The breakpoint should have a hit count of 2. + self.expect("breakpoint list -f", BREAKPOINT_HIT_TWICE, + substrs=['resolved, hit count = 2']) + + def breakpoint_command_script_parameters(self): + """Test that the frame and breakpoint location are being properly passed to the script breakpoint command function.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Add a breakpoint. + lldbutil.run_break_set_by_file_and_line( + self, "main.c", self.line, num_expected_locations=1, loc_exact=True) + + # Now add callbacks for the breakpoints just created. + self.runCmd("breakpoint command add -s python -o 'import side_effect; side_effect.frame = str(frame); side_effect.bp_loc = str(bp_loc)' 1") + + # Reset canary variables and run. + side_effect.frame = None + side_effect.bp_loc = None + self.runCmd("run", RUN_SUCCEEDED) + + self.expect(side_effect.frame, exe=False, startstr="frame #0:") + self.expect(side_effect.bp_loc, exe=False, + patterns=["1.* where = .*main .* resolved, hit count = 1"]) + + def breakpoint_commands_on_creation(self): + """Test that setting breakpoint commands when creating the breakpoint works""" + exe = self.getBuildArtifact("a.out") + target = self.dbg.CreateTarget(exe) + self.assertTrue(target.IsValid(), "Created an invalid target.") + + # Add a breakpoint. + lldbutil.run_break_set_by_file_and_line( + self, "main.c", self.line, num_expected_locations=1, loc_exact=True, + extra_options='-C bt -C "thread list" -C continue') + + bkpt = target.FindBreakpointByID(1) + self.assertTrue(bkpt.IsValid(), "Couldn't find breakpoint 1") + com_list = lldb.SBStringList() + bkpt.GetCommandLineCommands(com_list) + self.assertEqual(com_list.GetSize(), 3, "Got the wrong number of commands") + self.assertEqual(com_list.GetStringAtIndex(0), "bt", "First bt") + self.assertEqual(com_list.GetStringAtIndex(1), "thread list", "Next thread list") + self.assertEqual(com_list.GetStringAtIndex(2), "continue", "Last continue") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommandsFromPython.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommandsFromPython.py new file mode 100644 index 00000000000..15a31201c56 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommandsFromPython.py @@ -0,0 +1,174 @@ +""" +Test that you can set breakpoint commands successfully with the Python API's: +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import side_effect + + +class PythonBreakpointCommandSettingTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + @add_test_categories(['pyapi']) + def test_step_out_python(self): + """Test stepping out using a python breakpoint command.""" + self.build() + self.do_set_python_command_from_python() + + def test_bkpt_cmd_bad_arguments(self): + """Test what happens when pass structured data to a command:""" + self.build() + self.do_bad_args_to_python_command() + + def setUp(self): + TestBase.setUp(self) + self.main_source = "main.c" + self.main_source_spec = lldb.SBFileSpec(self.main_source) + + def do_set_python_command_from_python(self): + exe = self.getBuildArtifact("a.out") + error = lldb.SBError() + + self.target = self.dbg.CreateTarget(exe) + self.assertTrue(self.target, VALID_TARGET) + + body_bkpt = self.target.BreakpointCreateBySourceRegex( + "Set break point at this line.", self.main_source_spec) + self.assertTrue(body_bkpt, VALID_BREAKPOINT) + + func_bkpt = self.target.BreakpointCreateBySourceRegex( + "Set break point at this line.", self.main_source_spec) + self.assertTrue(func_bkpt, VALID_BREAKPOINT) + + fancy_bkpt = self.target.BreakpointCreateBySourceRegex( + "Set break point at this line.", self.main_source_spec) + self.assertTrue(fancy_bkpt, VALID_BREAKPOINT) + + fancier_bkpt = self.target.BreakpointCreateBySourceRegex( + "Set break point at this line.", self.main_source_spec) + self.assertTrue(fancier_bkpt, VALID_BREAKPOINT) + + not_so_fancy_bkpt = self.target.BreakpointCreateBySourceRegex( + "Set break point at this line.", self.main_source_spec) + self.assertTrue(not_so_fancy_bkpt, VALID_BREAKPOINT) + + # Also test that setting a source regex breakpoint with an empty file + # spec list sets it on all files: + no_files_bkpt = self.target.BreakpointCreateBySourceRegex( + "Set a breakpoint here", lldb.SBFileSpecList(), lldb.SBFileSpecList()) + self.assertTrue(no_files_bkpt, VALID_BREAKPOINT) + num_locations = no_files_bkpt.GetNumLocations() + self.assertTrue( + num_locations >= 2, + "Got at least two breakpoint locations") + got_one_in_A = False + got_one_in_B = False + for idx in range(0, num_locations): + comp_unit = no_files_bkpt.GetLocationAtIndex(idx).GetAddress().GetSymbolContext( + lldb.eSymbolContextCompUnit).GetCompileUnit().GetFileSpec() + print("Got comp unit: ", comp_unit.GetFilename()) + if comp_unit.GetFilename() == "a.c": + got_one_in_A = True + elif comp_unit.GetFilename() == "b.c": + got_one_in_B = True + + self.assertTrue(got_one_in_A, "Failed to match the pattern in A") + self.assertTrue(got_one_in_B, "Failed to match the pattern in B") + self.target.BreakpointDelete(no_files_bkpt.GetID()) + + error = lldb.SBError() + error = body_bkpt.SetScriptCallbackBody( + "import side_effect; side_effect.callback = 'callback was here'") + self.assertTrue( + error.Success(), + "Failed to set the script callback body: %s." % + (error.GetCString())) + + self.expect("command script import --allow-reload ./bktptcmd.py") + + func_bkpt.SetScriptCallbackFunction("bktptcmd.function") + + extra_args = lldb.SBStructuredData() + stream = lldb.SBStream() + stream.Print('{"side_effect" : "I am fancy"}') + extra_args.SetFromJSON(stream) + error = fancy_bkpt.SetScriptCallbackFunction("bktptcmd.another_function", extra_args) + self.assertTrue(error.Success(), "Failed to add callback %s"%(error.GetCString())) + + stream.Clear() + stream.Print('{"side_effect" : "I am so much fancier"}') + extra_args.SetFromJSON(stream) + + # Fancier's callback is set up from the command line + id = fancier_bkpt.GetID() + self.expect("breakpoint command add -F bktptcmd.a_third_function -k side_effect -v 'I am fancier' %d"%(id)) + + # Not so fancy gets an empty extra_args: + empty_args = lldb.SBStructuredData() + error = not_so_fancy_bkpt.SetScriptCallbackFunction("bktptcmd.empty_extra_args", empty_args) + self.assertTrue(error.Success(), "Failed to add callback %s"%(error.GetCString())) + + # Clear out canary variables + side_effect.bktptcmd = None + side_effect.callback = None + side_effect.fancy = None + side_effect.fancier = None + side_effect.not_so_fancy = None + + # Now launch the process, and do not stop at entry point. + self.process = self.target.LaunchSimple( + None, None, self.get_process_working_directory()) + + self.assertTrue(self.process, PROCESS_IS_VALID) + + # Now finish, and make sure the return value is correct. + threads = lldbutil.get_threads_stopped_at_breakpoint( + self.process, body_bkpt) + self.assertEquals(len(threads), 1, "Stopped at inner breakpoint.") + self.thread = threads[0] + + self.assertEquals("callback was here", side_effect.callback) + self.assertEquals("function was here", side_effect.bktptcmd) + self.assertEquals("I am fancy", side_effect.fancy) + self.assertEquals("I am fancier", side_effect.fancier) + self.assertEquals("Not so fancy", side_effect.not_so_fancy) + + def do_bad_args_to_python_command(self): + exe = self.getBuildArtifact("a.out") + error = lldb.SBError() + + self.target = self.dbg.CreateTarget(exe) + self.assertTrue(self.target, VALID_TARGET) + + + self.expect("command script import --allow-reload ./bktptcmd.py") + + bkpt = self.target.BreakpointCreateBySourceRegex( + "Set break point at this line.", self.main_source_spec) + self.assertTrue(bkpt, VALID_BREAKPOINT) + + # Pass a breakpoint command function that doesn't take extra_args, + # but pass it extra args: + + extra_args = lldb.SBStructuredData() + stream = lldb.SBStream() + stream.Print('{"side_effect" : "I am fancy"}') + extra_args.SetFromJSON(stream) + + error = bkpt.SetScriptCallbackFunction("bktptcmd.function", extra_args) + self.assertTrue(error.Fail(), "Can't pass extra args if the function doesn't take them") + + error = bkpt.SetScriptCallbackFunction("bktptcmd.useless_function", extra_args) + self.assertTrue(error.Fail(), "Can't pass extra args if the function has wrong number of args.") + + error = bkpt.SetScriptCallbackFunction("bktptcmd.nosuch_function", extra_args) + self.assertTrue(error.Fail(), "Can't pass extra args if the function doesn't exist.") + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestRegexpBreakCommand.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestRegexpBreakCommand.py new file mode 100644 index 00000000000..ed462653d24 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestRegexpBreakCommand.py @@ -0,0 +1,70 @@ +""" +Test _regexp-break command which uses regular expression matching to dispatch to other built in breakpoint commands. +""" + + + +import os +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class RegexpBreakCommandTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test(self): + """Test _regexp-break command.""" + self.build() + self.regexp_break_command() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.source = 'main.c' + self.line = line_number( + self.source, '// Set break point at this line.') + + def regexp_break_command(self): + """Test the super consie "b" command, which is analias for _regexp-break.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + break_results = lldbutil.run_break_set_command( + self, "b %d" % + self.line) + lldbutil.check_breakpoint_result( + self, + break_results, + file_name='main.c', + line_number=self.line, + num_locations=1) + + break_results = lldbutil.run_break_set_command( + self, "b %s:%d" % (self.source, self.line)) + lldbutil.check_breakpoint_result( + self, + break_results, + file_name='main.c', + line_number=self.line, + num_locations=1) + + # Check breakpoint with full file path. + full_path = os.path.join(self.getSourceDir(), self.source) + break_results = lldbutil.run_break_set_command( + self, "b %s:%d" % (full_path, self.line)) + lldbutil.check_breakpoint_result( + self, + break_results, + file_name='main.c', + line_number=self.line, + num_locations=1) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/a.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/a.c new file mode 100644 index 00000000000..870e4a6ab16 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/a.c @@ -0,0 +1,9 @@ +#include <stdio.h> + +int +a_MyFunction () +{ + // Set a breakpoint here. + printf ("a is about to return 10.\n"); + return 10; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/b.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/b.c new file mode 100644 index 00000000000..02b78e7bd85 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/b.c @@ -0,0 +1,9 @@ +#include <stdio.h> + +int +b_MyFunction () +{ + // Set a breakpoint here. + printf ("b is about to return 20.\n"); + return 20; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/bktptcmd.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/bktptcmd.py new file mode 100644 index 00000000000..e839de57fb7 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/bktptcmd.py @@ -0,0 +1,23 @@ +from __future__ import print_function +import side_effect + +def useless_function(first, second): + print("I have the wrong number of arguments.") + +def function(frame, bp_loc, dict): + side_effect.bktptcmd = "function was here" + +def another_function(frame, bp_loc, extra_args, dict): + se_value = extra_args.GetValueForKey("side_effect") + se_string = se_value.GetStringValue(100) + side_effect.fancy = se_string + +def a_third_function(frame, bp_loc, extra_args, dict): + se_value = extra_args.GetValueForKey("side_effect") + se_string = se_value.GetStringValue(100) + side_effect.fancier = se_string + +def empty_extra_args(frame, bp_loc, extra_args, dict): + if extra_args.IsValid(): + side_effect.not_so_fancy = "Extra args should not be valid" + side_effect.not_so_fancy = "Not so fancy" diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/main.c new file mode 100644 index 00000000000..8bebb9455a6 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/main.c @@ -0,0 +1,16 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +int main (int argc, char const *argv[]) +{ + // Add a body to the function, so we can set more than one + // breakpoint in it. + static volatile int var = 0; + var++; + return 0; // Set break point at this line. +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/side_effect.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/side_effect.py new file mode 100644 index 00000000000..ef4ab2b159c --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/side_effect.py @@ -0,0 +1,5 @@ +""" +A dummy module for testing the execution of various breakpoint commands. A +command will modify a global variable in this module and test will check its +value. +""" diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/Makefile new file mode 100644 index 00000000000..695335e068c --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/Makefile @@ -0,0 +1,4 @@ +C_SOURCES := main.c +CFLAGS_EXTRAS := -std=c99 + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/TestBreakpointConditions.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/TestBreakpointConditions.py new file mode 100644 index 00000000000..de9a47d8c20 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/TestBreakpointConditions.py @@ -0,0 +1,223 @@ +""" +Test breakpoint conditions with 'breakpoint modify -c <expr> id'. +""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class BreakpointConditionsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_breakpoint_condition_and_run_command(self): + """Exercise breakpoint condition with 'breakpoint modify -c <expr> id'.""" + self.build() + self.breakpoint_conditions() + + def test_breakpoint_condition_inline_and_run_command(self): + """Exercise breakpoint condition inline with 'breakpoint set'.""" + self.build() + self.breakpoint_conditions(inline=True) + + @add_test_categories(['pyapi']) + def test_breakpoint_condition_and_python_api(self): + """Use Python APIs to set breakpoint conditions.""" + self.build() + self.breakpoint_conditions_python() + + @add_test_categories(['pyapi']) + def test_breakpoint_invalid_condition_and_python_api(self): + """Use Python APIs to set breakpoint conditions.""" + self.build() + self.breakpoint_invalid_conditions_python() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to of function 'c'. + self.line1 = line_number( + 'main.c', '// Find the line number of function "c" here.') + self.line2 = line_number( + 'main.c', "// Find the line number of c's parent call here.") + + def breakpoint_conditions(self, inline=False): + """Exercise breakpoint condition with 'breakpoint modify -c <expr> id'.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + if inline: + # Create a breakpoint by function name 'c' and set the condition. + lldbutil.run_break_set_by_symbol( + self, + "c", + extra_options="-c 'val == 3'", + num_expected_locations=1, + sym_exact=True) + else: + # Create a breakpoint by function name 'c'. + lldbutil.run_break_set_by_symbol( + self, "c", num_expected_locations=1, sym_exact=True) + + # And set a condition on the breakpoint to stop on when 'val == 3'. + self.runCmd("breakpoint modify -c 'val == 3' 1") + + # Now run the program. + self.runCmd("run", RUN_SUCCEEDED) + + # The process should be stopped at this point. + self.expect("process status", PROCESS_STOPPED, + patterns=['Process .* stopped']) + + # 'frame variable --show-types val' should return 3 due to breakpoint condition. + self.expect( + "frame variable --show-types val", + VARIABLES_DISPLAYED_CORRECTLY, + startstr='(int) val = 3') + + # Also check the hit count, which should be 3, by design. + self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, + substrs=["resolved = 1", + "Condition: val == 3", + "hit count = 1"]) + + # The frame #0 should correspond to main.c:36, the executable statement + # in function name 'c'. And the parent frame should point to + # main.c:24. + self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT_CONDITION, + #substrs = ["stop reason = breakpoint"], + patterns=["frame #0.*main.c:%d" % self.line1, + "frame #1.*main.c:%d" % self.line2]) + + # Test that "breakpoint modify -c ''" clears the condition for the last + # created breakpoint, so that when the breakpoint hits, val == 1. + self.runCmd("process kill") + self.runCmd("breakpoint modify -c ''") + self.expect( + "breakpoint list -f", + BREAKPOINT_STATE_CORRECT, + matching=False, + substrs=["Condition:"]) + + # Now run the program again. + self.runCmd("run", RUN_SUCCEEDED) + + # The process should be stopped at this point. + self.expect("process status", PROCESS_STOPPED, + patterns=['Process .* stopped']) + + # 'frame variable --show-types val' should return 1 since it is the first breakpoint hit. + self.expect( + "frame variable --show-types val", + VARIABLES_DISPLAYED_CORRECTLY, + startstr='(int) val = 1') + + self.runCmd("process kill") + + def breakpoint_conditions_python(self): + """Use Python APIs to set breakpoint conditions.""" + exe = self.getBuildArtifact("a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create a breakpoint on main.c by name 'c'. + breakpoint = target.BreakpointCreateByName('c', 'a.out') + #print("breakpoint:", breakpoint) + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + # We didn't associate a thread index with the breakpoint, so it should + # be invalid. + self.assertTrue(breakpoint.GetThreadIndex() == lldb.UINT32_MAX, + "The thread index should be invalid") + # The thread name should be invalid, too. + self.assertTrue(breakpoint.GetThreadName() is None, + "The thread name should be invalid") + + # Let's set the thread index for this breakpoint and verify that it is, + # indeed, being set correctly. + # There's only one thread for the process. + breakpoint.SetThreadIndex(1) + self.assertTrue(breakpoint.GetThreadIndex() == 1, + "The thread index has been set correctly") + + # Get the breakpoint location from breakpoint after we verified that, + # indeed, it has one location. + location = breakpoint.GetLocationAtIndex(0) + self.assertTrue(location and + location.IsEnabled(), + VALID_BREAKPOINT_LOCATION) + + # Set the condition on the breakpoint location. + location.SetCondition('val == 3') + self.expect(location.GetCondition(), exe=False, + startstr='val == 3') + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + # Frame #0 should be on self.line1 and the break condition should hold. + from lldbsuite.test.lldbutil import get_stopped_thread + thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue( + thread.IsValid(), + "There should be a thread stopped due to breakpoint condition") + frame0 = thread.GetFrameAtIndex(0) + var = frame0.FindValue('val', lldb.eValueTypeVariableArgument) + self.assertTrue(frame0.GetLineEntry().GetLine() == self.line1 and + var.GetValue() == '3') + + # The hit count for the breakpoint should be 1. + self.assertTrue(breakpoint.GetHitCount() == 1) + + # Test that the condition expression didn't create a result variable: + options = lldb.SBExpressionOptions() + value = frame0.EvaluateExpression("$0", options) + self.assertTrue(value.GetError().Fail(), + "Conditions should not make result variables.") + process.Continue() + + def breakpoint_invalid_conditions_python(self): + """Use Python APIs to set breakpoint conditions.""" + exe = self.getBuildArtifact("a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create a breakpoint on main.c by name 'c'. + breakpoint = target.BreakpointCreateByName('c', 'a.out') + #print("breakpoint:", breakpoint) + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + # Set the condition on the breakpoint. + breakpoint.SetCondition('no_such_variable == not_this_one_either') + self.expect(breakpoint.GetCondition(), exe=False, + startstr='no_such_variable == not_this_one_either') + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + # Frame #0 should be on self.line1 and the break condition should hold. + from lldbsuite.test.lldbutil import get_stopped_thread + thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue( + thread.IsValid(), + "There should be a thread stopped due to breakpoint condition") + frame0 = thread.GetFrameAtIndex(0) + var = frame0.FindValue('val', lldb.eValueTypeVariableArgument) + self.assertTrue(frame0.GetLineEntry().GetLine() == self.line1) + + # The hit count for the breakpoint should be 1. + self.assertTrue(breakpoint.GetHitCount() == 1) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/main.c new file mode 100644 index 00000000000..c830b17a3ce --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/main.c @@ -0,0 +1,53 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include <stdio.h> + +// This simple program is to demonstrate the capability of the lldb command +// "breakpoint modify -c 'val == 3' breakpt-id" to break within c(int val) only +// when the value of the arg is 3. + +int a(int); +int b(int); +int c(int); + +int a(int val) +{ + if (val <= 1) + return b(val); + else if (val >= 3) + return c(val); // Find the line number of c's parent call here. + + return val; +} + +int b(int val) +{ + return c(val); +} + +int c(int val) +{ + return val + 3; // Find the line number of function "c" here. +} + +int main (int argc, char const *argv[]) +{ + int A1 = a(1); // a(1) -> b(1) -> c(1) + printf("a(1) returns %d\n", A1); + + int B2 = b(2); // b(2) -> c(2) + printf("b(2) returns %d\n", B2); + + int A3 = a(3); // a(3) -> c(3) + printf("a(3) returns %d\n", A3); + + for (int i = 0; i < 2; ++i) + printf("Loop\n"); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_hit_count/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_hit_count/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_hit_count/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_hit_count/TestBreakpointHitCount.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_hit_count/TestBreakpointHitCount.py new file mode 100644 index 00000000000..0254bf02366 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_hit_count/TestBreakpointHitCount.py @@ -0,0 +1,133 @@ +""" +Test breakpoint hit count features. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class BreakpointHitCountTestCase(TestBase): + + NO_DEBUG_INFO_TESTCASE = True + + mydir = TestBase.compute_mydir(__file__) + + @add_test_categories(['pyapi']) + def test_breakpoint_location_hit_count(self): + """Use Python APIs to check breakpoint hit count.""" + self.build() + self.do_test_breakpoint_location_hit_count() + + def test_breakpoint_one_shot(self): + """Check that one-shot breakpoints trigger only once.""" + self.build() + + exe = self.getBuildArtifact("a.out") + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + self.runCmd("tb a") + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + from lldbsuite.test.lldbutil import get_stopped_thread + thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue( + thread.IsValid(), + "There should be a thread stopped due to breakpoint") + + frame0 = thread.GetFrameAtIndex(0) + self.assertTrue(frame0.GetFunctionName() == "a(int)" or frame0.GetFunctionName() == "int a(int)"); + + process.Continue() + self.assertEqual(process.GetState(), lldb.eStateExited) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + self.a_int_body_line_no = line_number( + 'main.cpp', '// Breakpoint Location 1') + self.a_float_body_line_no = line_number( + 'main.cpp', '// Breakpoint Location 2') + + def do_test_breakpoint_location_hit_count(self): + """Use Python APIs to check breakpoint hit count.""" + exe = self.getBuildArtifact("a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Create a breakpoint in main.cpp by name 'a', + # there should be two locations. + breakpoint = target.BreakpointCreateByName('a', 'a.out') + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 2, + VALID_BREAKPOINT) + + # Verify all breakpoint locations are enabled. + location1 = breakpoint.GetLocationAtIndex(0) + self.assertTrue(location1 and + location1.IsEnabled(), + VALID_BREAKPOINT_LOCATION) + + location2 = breakpoint.GetLocationAtIndex(1) + self.assertTrue(location2 and + location2.IsEnabled(), + VALID_BREAKPOINT_LOCATION) + + # Launch the process, and do not stop at entry point. + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + # Verify 1st breakpoint location is hit. + from lldbsuite.test.lldbutil import get_stopped_thread + thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue( + thread.IsValid(), + "There should be a thread stopped due to breakpoint") + + frame0 = thread.GetFrameAtIndex(0) + location1 = breakpoint.FindLocationByAddress(frame0.GetPC()) + self.assertTrue( + frame0.GetLineEntry().GetLine() == self.a_int_body_line_no, + "Stopped in int a(int)") + self.assertTrue(location1) + self.assertEqual(location1.GetHitCount(), 1) + self.assertEqual(breakpoint.GetHitCount(), 1) + + process.Continue() + + # Verify 2nd breakpoint location is hit. + thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue( + thread.IsValid(), + "There should be a thread stopped due to breakpoint") + + frame0 = thread.GetFrameAtIndex(0) + location2 = breakpoint.FindLocationByAddress(frame0.GetPC()) + self.assertTrue( + frame0.GetLineEntry().GetLine() == self.a_float_body_line_no, + "Stopped in float a(float)") + self.assertTrue(location2) + self.assertEqual(location2.GetHitCount(), 1) + self.assertEqual(location1.GetHitCount(), 1) + self.assertEqual(breakpoint.GetHitCount(), 2) + + process.Continue() + + # Verify 2nd breakpoint location is hit again. + thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue( + thread.IsValid(), + "There should be a thread stopped due to breakpoint") + + self.assertEqual(location2.GetHitCount(), 2) + self.assertEqual(location1.GetHitCount(), 1) + self.assertEqual(breakpoint.GetHitCount(), 3) + + process.Continue() diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_hit_count/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_hit_count/main.cpp new file mode 100644 index 00000000000..9fc133f2400 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_hit_count/main.cpp @@ -0,0 +1,26 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +int a(int val) +{ + return val; // Breakpoint Location 1 +} + +float a(float val) +{ + return val; // Breakpoint Location 2 +} + +int main (int argc, char const *argv[]) +{ + int A1 = a(1); + float A2 = a(2.0f); + float A3 = a(3.0f); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ids/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ids/Makefile new file mode 100644 index 00000000000..2c00681fa22 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ids/Makefile @@ -0,0 +1,8 @@ +CXX_SOURCES := main.cpp + +ifneq (,$(findstring icc,$(CC))) + CXXFLAGS_EXTRAS := -debug inline-debug-info +endif + + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ids/TestBreakpointIDs.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ids/TestBreakpointIDs.py new file mode 100644 index 00000000000..82f554e2a2b --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ids/TestBreakpointIDs.py @@ -0,0 +1,57 @@ +""" +Test lldb breakpoint ids. +""" + + + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class BreakpointIDTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test(self): + self.build() + + exe = self.getBuildArtifact("a.out") + self.expect("file " + exe, + patterns=["Current executable set to .*a.out"]) + + bpno = lldbutil.run_break_set_by_symbol( + self, 'product', num_expected_locations=-1, sym_exact=False) + self.assertTrue(bpno == 1, "First breakpoint number is 1.") + + bpno = lldbutil.run_break_set_by_symbol( + self, 'sum', num_expected_locations=-1, sym_exact=False) + self.assertTrue(bpno == 2, "Second breakpoint number is 2.") + + bpno = lldbutil.run_break_set_by_symbol( + self, 'junk', num_expected_locations=0, sym_exact=False) + self.assertTrue(bpno == 3, "Third breakpoint number is 3.") + + self.expect( + "breakpoint disable 1.1 - 2.2 ", + COMMAND_FAILED_AS_EXPECTED, + error=True, + startstr="error: Invalid range: Ranges that specify particular breakpoint locations must be within the same major breakpoint; you specified two different major breakpoints, 1 and 2.") + + self.expect( + "breakpoint disable 2 - 2.2", + COMMAND_FAILED_AS_EXPECTED, + error=True, + startstr="error: Invalid breakpoint id range: Either both ends of range must specify a breakpoint location, or neither can specify a breakpoint location.") + + self.expect( + "breakpoint disable 2.1 - 2", + COMMAND_FAILED_AS_EXPECTED, + error=True, + startstr="error: Invalid breakpoint id range: Either both ends of range must specify a breakpoint location, or neither can specify a breakpoint location.") + + self.expect("breakpoint disable 2.1 - 2.2", + startstr="2 breakpoints disabled.") + + self.expect("breakpoint enable 2.*", + patterns=[".* breakpoints enabled."]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ids/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ids/main.cpp new file mode 100644 index 00000000000..3c98e147f22 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ids/main.cpp @@ -0,0 +1,64 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <cstdlib> +#include <string> +#include <fstream> +#include <iostream> + + +#define INLINE inline __attribute__((always_inline)) + +INLINE int +product (int x, int y) +{ + int result = x * y; + return result; +} + +INLINE int +sum (int a, int b) +{ + int result = a + b; + return result; +} + +int +strange_max (int m, int n) +{ + if (m > n) + return m; + else if (n > m) + return n; + else + return 0; +} + +int +foo (int i, int j) +{ + if (strange_max (i, j) == i) + return product (i, j); + else if (strange_max (i, j) == j) + return sum (i, j); + else + return product (sum (i, i), sum (j, j)); +} + +int +main(int argc, char const *argv[]) +{ + + int array[3]; + + array[0] = foo (1238, 78392); + array[1] = foo (379265, 23674); + array[2] = foo (872934, 234); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/TestBreakpointIgnoreCount.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/TestBreakpointIgnoreCount.py new file mode 100644 index 00000000000..3fa81aeadf9 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/TestBreakpointIgnoreCount.py @@ -0,0 +1,150 @@ +""" +Test breakpoint ignore count features. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class BreakpointIgnoreCountTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipIfWindows # This test will hang on windows llvm.org/pr21753 + def test_with_run_command(self): + """Exercise breakpoint ignore count with 'breakpoint set -i <count>'.""" + self.build() + self.breakpoint_ignore_count() + + @add_test_categories(['pyapi']) + @skipIfWindows # This test will hang on windows llvm.org/pr21753 + def test_with_python_api(self): + """Use Python APIs to set breakpoint ignore count.""" + self.build() + self.breakpoint_ignore_count_python() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to of function 'c'. + self.line1 = line_number( + 'main.c', '// Find the line number of function "c" here.') + self.line2 = line_number( + 'main.c', '// b(2) -> c(2) Find the call site of b(2).') + self.line3 = line_number( + 'main.c', '// a(3) -> c(3) Find the call site of c(3).') + self.line4 = line_number( + 'main.c', '// a(3) -> c(3) Find the call site of a(3).') + self.line5 = line_number( + 'main.c', '// Find the call site of c in main.') + + def breakpoint_ignore_count(self): + """Exercise breakpoint ignore count with 'breakpoint set -i <count>'.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Create a breakpoint in main.c at line1. + lldbutil.run_break_set_by_file_and_line( + self, + 'main.c', + self.line1, + extra_options='-i 1', + num_expected_locations=1, + loc_exact=True) + + # Now run the program. + self.runCmd("run", RUN_SUCCEEDED) + + # The process should be stopped at this point. + self.expect("process status", PROCESS_STOPPED, + patterns=['Process .* stopped']) + + # Also check the hit count, which should be 2, due to ignore count of + # 1. + self.expect("breakpoint list -f", BREAKPOINT_HIT_THRICE, + substrs=["resolved = 1", + "hit count = 2"]) + + # The frame #0 should correspond to main.c:37, the executable statement + # in function name 'c'. And frame #2 should point to main.c:45. + self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT, + #substrs = ["stop reason = breakpoint"], + patterns=["frame #0.*main.c:%d" % self.line1, + "frame #2.*main.c:%d" % self.line2]) + + # continue -i 1 is the same as setting the ignore count to 1 again, try that: + # Now run the program. + self.runCmd("process continue -i 1", RUN_SUCCEEDED) + + # The process should be stopped at this point. + self.expect("process status", PROCESS_STOPPED, + patterns=['Process .* stopped']) + + # Also check the hit count, which should be 2, due to ignore count of + # 1. + self.expect("breakpoint list -f", BREAKPOINT_HIT_THRICE, + substrs=["resolved = 1", + "hit count = 4"]) + + # The frame #0 should correspond to main.c:37, the executable statement + # in function name 'c'. And frame #2 should point to main.c:45. + self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT, + #substrs = ["stop reason = breakpoint"], + patterns=["frame #0.*main.c:%d" % self.line1, + "frame #1.*main.c:%d" % self.line5]) + + def breakpoint_ignore_count_python(self): + """Use Python APIs to set breakpoint ignore count.""" + exe = self.getBuildArtifact("a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create a breakpoint on main.c by name 'c'. + breakpoint = target.BreakpointCreateByName('c', 'a.out') + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + # Get the breakpoint location from breakpoint after we verified that, + # indeed, it has one location. + location = breakpoint.GetLocationAtIndex(0) + self.assertTrue(location and + location.IsEnabled(), + VALID_BREAKPOINT_LOCATION) + + # Set the ignore count on the breakpoint location. + location.SetIgnoreCount(2) + self.assertTrue(location.GetIgnoreCount() == 2, + "SetIgnoreCount() works correctly") + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + # Frame#0 should be on main.c:37, frame#1 should be on main.c:25, and + # frame#2 should be on main.c:48. + # lldbutil.print_stacktraces(process) + from lldbsuite.test.lldbutil import get_stopped_thread + thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue( + thread.IsValid(), + "There should be a thread stopped due to breakpoint") + frame0 = thread.GetFrameAtIndex(0) + frame1 = thread.GetFrameAtIndex(1) + frame2 = thread.GetFrameAtIndex(2) + self.assertTrue(frame0.GetLineEntry().GetLine() == self.line1 and + frame1.GetLineEntry().GetLine() == self.line3 and + frame2.GetLineEntry().GetLine() == self.line4, + STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT) + + # The hit count for the breakpoint should be 3. + self.assertTrue(breakpoint.GetHitCount() == 3) + + process.Continue() diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/main.c new file mode 100644 index 00000000000..b1ed4465c1d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/main.c @@ -0,0 +1,53 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include <stdio.h> + +// This simple program is to demonstrate the capability of the lldb command +// "breakpoint modify -i <count> breakpt-id" to set the number of times a +// breakpoint is skipped before stopping. Ignore count can also be set upon +// breakpoint creation by 'breakpoint set ... -i <count>'. + +int a(int); +int b(int); +int c(int); + +int a(int val) +{ + if (val <= 1) + return b(val); + else if (val >= 3) + return c(val); // a(3) -> c(3) Find the call site of c(3). + + return val; +} + +int b(int val) +{ + return c(val); +} + +int c(int val) +{ + return val + 3; // Find the line number of function "c" here. +} + +int main (int argc, char const *argv[]) +{ + int A1 = a(1); // a(1) -> b(1) -> c(1) + printf("a(1) returns %d\n", A1); + + int B2 = b(2); // b(2) -> c(2) Find the call site of b(2). + printf("b(2) returns %d\n", B2); + + int A3 = a(3); // a(3) -> c(3) Find the call site of a(3). + printf("a(3) returns %d\n", A3); + + int C1 = c(5); // Find the call site of c in main. + printf ("c(5) returns %d\n", C1); + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_in_delayslot/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_in_delayslot/Makefile new file mode 100644 index 00000000000..692ba173228 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_in_delayslot/Makefile @@ -0,0 +1,4 @@ +C_SOURCES := main.c + +include Makefile.rules + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_in_delayslot/TestAvoidBreakpointInDelaySlot.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_in_delayslot/TestAvoidBreakpointInDelaySlot.py new file mode 100644 index 00000000000..ff087159f61 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_in_delayslot/TestAvoidBreakpointInDelaySlot.py @@ -0,0 +1,87 @@ +""" +Test specific to MIPS +""" + +from __future__ import print_function + +import re +import unittest2 +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class AvoidBreakpointInDelaySlotAPITestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipIf(archs=no_match(re.compile('mips*'))) + def test(self): + self.build() + exe = self.getBuildArtifact("a.out") + self.expect("file " + exe, + patterns=["Current executable set to .*a.out.*"]) + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + breakpoint = target.BreakpointCreateByName('main', 'a.out') + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + list = target.FindFunctions('foo', lldb.eFunctionNameTypeAuto) + self.assertTrue(list.GetSize() == 1) + sc = list.GetContextAtIndex(0) + self.assertTrue(sc.GetSymbol().GetName() == "foo") + function = sc.GetFunction() + self.assertTrue(function) + self.function(function, target) + + def function(self, function, target): + """Iterate over instructions in function and place a breakpoint on delay slot instruction""" + # Get the list of all instructions in the function + insts = function.GetInstructions(target) + print(insts) + i = 0 + for inst in insts: + if (inst.HasDelaySlot()): + # Remember the address of branch instruction. + branchinstaddress = inst.GetAddress().GetLoadAddress(target) + + # Get next instruction i.e delay slot instruction. + delayinst = insts.GetInstructionAtIndex(i + 1) + delayinstaddr = delayinst.GetAddress().GetLoadAddress(target) + + # Set breakpoint on delay slot instruction + breakpoint = target.BreakpointCreateByAddress(delayinstaddr) + + # Verify the breakpoint. + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + # Get the location from breakpoint + location = breakpoint.GetLocationAtIndex(0) + + # Get the address where breakpoint is actually set. + bpaddr = location.GetLoadAddress() + + # Breakpoint address should be adjusted to the address of + # branch instruction. + self.assertTrue(branchinstaddress == bpaddr) + i += 1 + else: + i += 1 + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_in_delayslot/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_in_delayslot/main.c new file mode 100644 index 00000000000..bc3eceea769 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_in_delayslot/main.c @@ -0,0 +1,21 @@ +#include <stdio.h> + +foo (int a, int b) +{ + int c; + if (a<=b) + c=b-a; + else + c=b+a; + return c; +} + +int main() +{ + int a=7, b=8, c; + + c = foo(a, b); + +return 0; +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/Makefile new file mode 100644 index 00000000000..283cc1b8944 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/Makefile @@ -0,0 +1,4 @@ +C_SOURCES := a.c +CXX_SOURCES := main.cpp b.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/TestBreakpointLanguage.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/TestBreakpointLanguage.py new file mode 100644 index 00000000000..ceffb11f8b7 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/TestBreakpointLanguage.py @@ -0,0 +1,127 @@ +""" +Test that the language option for breakpoints works correctly +parser. +""" + + + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class TestBreakpointLanguage(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def check_location_file(self, bp, loc, test_name): + bp_loc = bp.GetLocationAtIndex(loc) + addr = bp_loc.GetAddress() + comp_unit = addr.GetCompileUnit() + comp_name = comp_unit.GetFileSpec().GetFilename() + return comp_name == test_name + + def test_regex_breakpoint_language(self): + """Test that the name regex breakpoint commands obey the language filter.""" + + self.build() + # Create a target by the debugger. + exe = self.getBuildArtifact("a.out") + error = lldb.SBError() + # Don't read in dependencies so we don't come across false matches that + # add unwanted breakpoint hits. + self.target = self.dbg.CreateTarget(exe, None, None, False, error) + self.assertTrue(self.target, VALID_TARGET) + + cpp_bp = self.target.BreakpointCreateByRegex( + "func_from", + lldb.eLanguageTypeC_plus_plus, + lldb.SBFileSpecList(), + lldb.SBFileSpecList()) + self.assertTrue( + cpp_bp.GetNumLocations() == 1, + "Only one C++ symbol matches") + self.assertTrue(self.check_location_file(cpp_bp, 0, "b.cpp")) + + c_bp = self.target.BreakpointCreateByRegex( + "func_from", + lldb.eLanguageTypeC, + lldb.SBFileSpecList(), + lldb.SBFileSpecList()) + self.assertTrue( + c_bp.GetNumLocations() == 1, + "Only one C symbol matches") + self.assertTrue(self.check_location_file(c_bp, 0, "a.c")) + + objc_bp = self.target.BreakpointCreateByRegex( + "func_from", + lldb.eLanguageTypeObjC, + lldb.SBFileSpecList(), + lldb.SBFileSpecList()) + self.assertTrue( + objc_bp.GetNumLocations() == 0, + "No ObjC symbol matches") + + def test_by_name_breakpoint_language(self): + """Test that the name regex breakpoint commands obey the language filter.""" + + self.build() + # Create a target by the debugger. + exe = self.getBuildArtifact("a.out") + error = lldb.SBError() + # Don't read in dependencies so we don't come across false matches that + # add unwanted breakpoint hits. + self.target = self.dbg.CreateTarget(exe, None, None, False, error) + self.assertTrue(self.target, VALID_TARGET) + + cpp_bp = self.target.BreakpointCreateByName( + "func_from_cpp", + lldb.eFunctionNameTypeAuto, + lldb.eLanguageTypeC_plus_plus, + lldb.SBFileSpecList(), + lldb.SBFileSpecList()) + self.assertTrue( + cpp_bp.GetNumLocations() == 1, + "Only one C++ symbol matches") + self.assertTrue(self.check_location_file(cpp_bp, 0, "b.cpp")) + + no_cpp_bp = self.target.BreakpointCreateByName( + "func_from_c", + lldb.eFunctionNameTypeAuto, + lldb.eLanguageTypeC_plus_plus, + lldb.SBFileSpecList(), + lldb.SBFileSpecList()) + self.assertTrue( + no_cpp_bp.GetNumLocations() == 0, + "And the C one doesn't match") + + c_bp = self.target.BreakpointCreateByName( + "func_from_c", + lldb.eFunctionNameTypeAuto, + lldb.eLanguageTypeC, + lldb.SBFileSpecList(), + lldb.SBFileSpecList()) + self.assertTrue( + c_bp.GetNumLocations() == 1, + "Only one C symbol matches") + self.assertTrue(self.check_location_file(c_bp, 0, "a.c")) + + no_c_bp = self.target.BreakpointCreateByName( + "func_from_cpp", + lldb.eFunctionNameTypeAuto, + lldb.eLanguageTypeC, + lldb.SBFileSpecList(), + lldb.SBFileSpecList()) + self.assertTrue( + no_c_bp.GetNumLocations() == 0, + "And the C++ one doesn't match") + + objc_bp = self.target.BreakpointCreateByName( + "func_from_cpp", + lldb.eFunctionNameTypeAuto, + lldb.eLanguageTypeObjC, + lldb.SBFileSpecList(), + lldb.SBFileSpecList()) + self.assertTrue( + objc_bp.GetNumLocations() == 0, + "No ObjC symbol matches") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/a.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/a.c new file mode 100644 index 00000000000..b90e2bdcca5 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/a.c @@ -0,0 +1,5 @@ +int +func_from_c () +{ + return 5; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/b.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/b.cpp new file mode 100644 index 00000000000..89373445b9a --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/b.cpp @@ -0,0 +1,5 @@ +int +func_from_cpp() +{ + return 10; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/main.cpp new file mode 100644 index 00000000000..b7d00a60202 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/main.cpp @@ -0,0 +1,11 @@ +#include <stdio.h> +extern "C" int func_from_c(); +extern int func_from_cpp(); + +int +main() +{ + func_from_c(); + func_from_cpp(); + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_locations/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_locations/Makefile new file mode 100644 index 00000000000..9645fd9cc8d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_locations/Makefile @@ -0,0 +1,7 @@ +C_SOURCES := main.c + +ifneq (,$(findstring icc,$(CC))) + CFLAGS_EXTRAS := -debug inline-debug-info +endif + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_locations/TestBreakpointLocations.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_locations/TestBreakpointLocations.py new file mode 100644 index 00000000000..334b0f0f159 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_locations/TestBreakpointLocations.py @@ -0,0 +1,196 @@ +""" +Test breakpoint commands for a breakpoint ID with multiple locations. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class BreakpointLocationsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528") + def test_enable(self): + """Test breakpoint enable/disable for a breakpoint ID with multiple locations.""" + self.build() + self.breakpoint_locations_test() + + def test_shadowed_cond_options(self): + """Test that options set on the breakpoint and location behave correctly.""" + self.build() + self.shadowed_bkpt_cond_test() + + def test_shadowed_command_options(self): + """Test that options set on the breakpoint and location behave correctly.""" + self.build() + self.shadowed_bkpt_command_test() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.line = line_number('main.c', '// Set break point at this line.') + + def set_breakpoint (self): + exe = self.getBuildArtifact("a.out") + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, "Target %s is not valid"%(exe)) + + # This should create a breakpoint with 3 locations. + + bkpt = target.BreakpointCreateByLocation("main.c", self.line) + + # The breakpoint list should show 3 locations. + self.assertEqual(bkpt.GetNumLocations(), 3, "Wrong number of locations") + + self.expect( + "breakpoint list -f", + "Breakpoint locations shown correctly", + substrs=[ + "1: file = 'main.c', line = %d, exact_match = 0, locations = 3" % + self.line], + patterns=[ + "where = a.out`func_inlined .+unresolved, hit count = 0", + "where = a.out`main .+\[inlined\].+unresolved, hit count = 0"]) + + return bkpt + + def shadowed_bkpt_cond_test(self): + """Test that options set on the breakpoint and location behave correctly.""" + # Breakpoint option propagation from bkpt to loc used to be done the first time + # a breakpoint location option was specifically set. After that the other options + # on that location would stop tracking the breakpoint. That got fixed, and this test + # makes sure only the option touched is affected. + + bkpt = self.set_breakpoint() + bkpt_cond = "1 == 0" + bkpt.SetCondition(bkpt_cond) + self.assertEqual(bkpt.GetCondition(), bkpt_cond,"Successfully set condition") + self.assertTrue(bkpt.location[0].GetCondition() == bkpt.GetCondition(), "Conditions are the same") + + # Now set a condition on the locations, make sure that this doesn't effect the bkpt: + bkpt_loc_1_cond = "1 == 1" + bkpt.location[0].SetCondition(bkpt_loc_1_cond) + self.assertEqual(bkpt.location[0].GetCondition(), bkpt_loc_1_cond, "Successfully changed location condition") + self.assertNotEqual(bkpt.GetCondition(), bkpt_loc_1_cond, "Changed location changed Breakpoint condition") + self.assertEqual(bkpt.location[1].GetCondition(), bkpt_cond, "Changed another location's condition") + + # Now make sure that setting one options doesn't fix the value of another: + bkpt.SetIgnoreCount(10) + self.assertEqual(bkpt.GetIgnoreCount(), 10, "Set the ignore count successfully") + self.assertEqual(bkpt.location[0].GetIgnoreCount(), 10, "Location doesn't track top-level bkpt.") + + # Now make sure resetting the condition to "" resets the tracking: + bkpt.location[0].SetCondition("") + bkpt_new_cond = "1 == 3" + bkpt.SetCondition(bkpt_new_cond) + self.assertEqual(bkpt.location[0].GetCondition(), bkpt_new_cond, "Didn't go back to tracking condition") + + def shadowed_bkpt_command_test(self): + """Test that options set on the breakpoint and location behave correctly.""" + # Breakpoint option propagation from bkpt to loc used to be done the first time + # a breakpoint location option was specifically set. After that the other options + # on that location would stop tracking the breakpoint. That got fixed, and this test + # makes sure only the option touched is affected. + + bkpt = self.set_breakpoint() + commands = ["AAAAAA", "BBBBBB", "CCCCCC"] + str_list = lldb.SBStringList() + str_list.AppendList(commands, len(commands)) + + bkpt.SetCommandLineCommands(str_list) + cmd_list = lldb.SBStringList() + bkpt.GetCommandLineCommands(cmd_list) + list_size = str_list.GetSize() + self.assertEqual(cmd_list.GetSize() , list_size, "Added the right number of commands") + for i in range(0,list_size): + self.assertEqual(str_list.GetStringAtIndex(i), cmd_list.GetStringAtIndex(i), "Mismatched commands.") + + commands = ["DDDDDD", "EEEEEE", "FFFFFF", "GGGGGG"] + loc_list = lldb.SBStringList() + loc_list.AppendList(commands, len(commands)) + bkpt.location[1].SetCommandLineCommands(loc_list) + loc_cmd_list = lldb.SBStringList() + bkpt.location[1].GetCommandLineCommands(loc_cmd_list) + + loc_list_size = loc_list.GetSize() + + # Check that the location has the right commands: + self.assertEqual(loc_cmd_list.GetSize() , loc_list_size, "Added the right number of commands to location") + for i in range(0,loc_list_size): + self.assertEqual(loc_list.GetStringAtIndex(i), loc_cmd_list.GetStringAtIndex(i), "Mismatched commands.") + + # Check that we didn't mess up the breakpoint level commands: + self.assertEqual(cmd_list.GetSize() , list_size, "Added the right number of commands") + for i in range(0,list_size): + self.assertEqual(str_list.GetStringAtIndex(i), cmd_list.GetStringAtIndex(i), "Mismatched commands.") + + # And check we didn't mess up another location: + untouched_loc_cmds = lldb.SBStringList() + bkpt.location[0].GetCommandLineCommands(untouched_loc_cmds) + self.assertEqual(untouched_loc_cmds.GetSize() , 0, "Changed the wrong location") + + def breakpoint_locations_test(self): + """Test breakpoint enable/disable for a breakpoint ID with multiple locations.""" + self.set_breakpoint() + + # The 'breakpoint disable 3.*' command should fail gracefully. + self.expect("breakpoint disable 3.*", + "Disabling an invalid breakpoint should fail gracefully", + error=True, + startstr="error: '3' is not a valid breakpoint ID.") + + # The 'breakpoint disable 1.*' command should disable all 3 locations. + self.expect( + "breakpoint disable 1.*", + "All 3 breakpoint locatons disabled correctly", + startstr="3 breakpoints disabled.") + + # Run the program. + self.runCmd("run", RUN_SUCCEEDED) + + # We should not stopped on any breakpoint at all. + self.expect("process status", "No stopping on any disabled breakpoint", + patterns=["^Process [0-9]+ exited with status = 0"]) + + # The 'breakpoint enable 1.*' command should enable all 3 breakpoints. + self.expect( + "breakpoint enable 1.*", + "All 3 breakpoint locatons enabled correctly", + startstr="3 breakpoints enabled.") + + # The 'breakpoint disable 1.1' command should disable 1 location. + self.expect( + "breakpoint disable 1.1", + "1 breakpoint locatons disabled correctly", + startstr="1 breakpoints disabled.") + + # Run the program again. We should stop on the two breakpoint + # locations. + self.runCmd("run", RUN_SUCCEEDED) + + # Stopped once. + self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT, + substrs=["stop reason = breakpoint 1."]) + + # Continue the program, there should be another stop. + self.runCmd("process continue") + + # Stopped again. + self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT, + substrs=["stop reason = breakpoint 1."]) + + # At this point, 1.1 has a hit count of 0 and the other a hit count of + # 1". + self.expect( + "breakpoint list -f", + "The breakpoints should report correct hit counts", + patterns=[ + "1\.1: .+ unresolved, hit count = 0 +Options: disabled", + "1\.2: .+ resolved, hit count = 1", + "1\.3: .+ resolved, hit count = 1"]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_locations/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_locations/main.c new file mode 100644 index 00000000000..7ec3ded67b7 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_locations/main.c @@ -0,0 +1,43 @@ +#include <stdio.h> + +#define INLINE inline __attribute__((always_inline)) + +int +func_not_inlined (void) +{ + printf ("Called func_not_inlined.\n"); + return 0; +} + +INLINE int +func_inlined (void) +{ + static int func_inline_call_count = 0; + printf ("Called func_inlined.\n"); + ++func_inline_call_count; + printf ("Returning func_inlined call count: %d.\n", func_inline_call_count); + return func_inline_call_count; // Set break point at this line. +} + +extern int func_inlined (void); + +int +main (int argc, char **argv) +{ + printf ("Starting...\n"); + + int (*func_ptr) (void); + func_ptr = func_inlined; + + int a = func_inlined(); + printf("First call to func_inlined() returns: %d.\n", a); + + func_not_inlined (); + + func_ptr (); + + printf("Last call to func_inlined() returns: %d.\n", func_inlined ()); + return 0; +} + + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_names/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_names/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_names/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_names/TestBreakpointNames.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_names/TestBreakpointNames.py new file mode 100644 index 00000000000..1212ad46d28 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_names/TestBreakpointNames.py @@ -0,0 +1,370 @@ +""" +Test breakpoint names. +""" + + + +import os +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class BreakpointNames(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + @add_test_categories(['pyapi']) + def test_setting_names(self): + """Use Python APIs to test that we can set breakpoint names.""" + self.build() + self.setup_target() + self.do_check_names() + + def test_illegal_names(self): + """Use Python APIs to test that we don't allow illegal names.""" + self.build() + self.setup_target() + self.do_check_illegal_names() + + def test_using_names(self): + """Use Python APIs to test that operations on names works correctly.""" + self.build() + self.setup_target() + self.do_check_using_names() + + def test_configuring_names(self): + """Use Python APIs to test that configuring options on breakpoint names works correctly.""" + self.build() + self.make_a_dummy_name() + self.setup_target() + self.do_check_configuring_names() + + def test_configuring_permissions_sb(self): + """Use Python APIs to test that configuring permissions on names works correctly.""" + self.build() + self.setup_target() + self.do_check_configuring_permissions_sb() + + def test_configuring_permissions_cli(self): + """Use Python APIs to test that configuring permissions on names works correctly.""" + self.build() + self.setup_target() + self.do_check_configuring_permissions_cli() + + def setup_target(self): + exe = self.getBuildArtifact("a.out") + + # Create a targets we are making breakpoint in and copying to: + self.target = self.dbg.CreateTarget(exe) + self.assertTrue(self.target, VALID_TARGET) + self.main_file_spec = lldb.SBFileSpec(os.path.join(self.getSourceDir(), "main.c")) + + def check_name_in_target(self, bkpt_name): + name_list = lldb.SBStringList() + self.target.GetBreakpointNames(name_list) + found_it = False + for name in name_list: + if name == bkpt_name: + found_it = True + break + self.assertTrue(found_it, "Didn't find the name %s in the target's name list:"%(bkpt_name)) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + # These are the settings we're going to be putting into names & breakpoints: + self.bp_name_string = "ABreakpoint" + self.is_one_shot = True + self.ignore_count = 1000 + self.condition = "1 == 2" + self.auto_continue = True + self.tid = 0xaaaa + self.tidx = 10 + self.thread_name = "Fooey" + self.queue_name = "Blooey" + self.cmd_list = lldb.SBStringList() + self.cmd_list.AppendString("frame var") + self.cmd_list.AppendString("bt") + self.help_string = "I do something interesting" + + + def do_check_names(self): + """Use Python APIs to check that we can set & retrieve breakpoint names""" + bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10) + bkpt_name = "ABreakpoint" + other_bkpt_name = "_AnotherBreakpoint" + + # Add a name and make sure we match it: + success = bkpt.AddName(bkpt_name) + self.assertTrue(success, "We couldn't add a legal name to a breakpoint.") + + matches = bkpt.MatchesName(bkpt_name) + self.assertTrue(matches, "We didn't match the name we just set") + + # Make sure we don't match irrelevant names: + matches = bkpt.MatchesName("NotABreakpoint") + self.assertTrue(not matches, "We matched a name we didn't set.") + + # Make sure the name is also in the target: + self.check_name_in_target(bkpt_name) + + # Add another name, make sure that works too: + bkpt.AddName(other_bkpt_name) + + matches = bkpt.MatchesName(bkpt_name) + self.assertTrue(matches, "Adding a name means we didn't match the name we just set") + self.check_name_in_target(other_bkpt_name) + + # Remove the name and make sure we no longer match it: + bkpt.RemoveName(bkpt_name) + matches = bkpt.MatchesName(bkpt_name) + self.assertTrue(not matches,"We still match a name after removing it.") + + # Make sure the name list has the remaining name: + name_list = lldb.SBStringList() + bkpt.GetNames(name_list) + num_names = name_list.GetSize() + self.assertTrue(num_names == 1, "Name list has %d items, expected 1."%(num_names)) + + name = name_list.GetStringAtIndex(0) + self.assertTrue(name == other_bkpt_name, "Remaining name was: %s expected %s."%(name, other_bkpt_name)) + + def do_check_illegal_names(self): + """Use Python APIs to check that we reject illegal names.""" + bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10) + bad_names = ["-CantStartWithADash", + "1CantStartWithANumber", + "^CantStartWithNonAlpha", + "CantHave-ADash", + "Cant Have Spaces"] + for bad_name in bad_names: + success = bkpt.AddName(bad_name) + self.assertTrue(not success,"We allowed an illegal name: %s"%(bad_name)) + bp_name = lldb.SBBreakpointName(self.target, bad_name) + self.assertFalse(bp_name.IsValid(), "We made a breakpoint name with an illegal name: %s"%(bad_name)); + + retval =lldb.SBCommandReturnObject() + self.dbg.GetCommandInterpreter().HandleCommand("break set -n whatever -N '%s'"%(bad_name), retval) + self.assertTrue(not retval.Succeeded(), "break set succeeded with: illegal name: %s"%(bad_name)) + + def do_check_using_names(self): + """Use Python APIs to check names work in place of breakpoint ID's.""" + + # Create a dummy breakpoint to use up ID 1 + _ = self.target.BreakpointCreateByLocation(self.main_file_spec, 30) + + # Create a breakpiont to test with + bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10) + bkpt_name = "ABreakpoint" + bkpt_id = bkpt.GetID() + other_bkpt_name= "_AnotherBreakpoint" + + # Add a name and make sure we match it: + success = bkpt.AddName(bkpt_name) + self.assertTrue(success, "We couldn't add a legal name to a breakpoint.") + + bkpts = lldb.SBBreakpointList(self.target) + self.target.FindBreakpointsByName(bkpt_name, bkpts) + + self.assertTrue(bkpts.GetSize() == 1, "One breakpoint matched.") + found_bkpt = bkpts.GetBreakpointAtIndex(0) + self.assertTrue(bkpt.GetID() == found_bkpt.GetID(),"The right breakpoint.") + self.assertTrue(bkpt.GetID() == bkpt_id,"With the same ID as before.") + + retval = lldb.SBCommandReturnObject() + self.dbg.GetCommandInterpreter().HandleCommand("break disable %s"%(bkpt_name), retval) + self.assertTrue(retval.Succeeded(), "break disable failed with: %s."%(retval.GetError())) + self.assertTrue(not bkpt.IsEnabled(), "We didn't disable the breakpoint.") + + # Also make sure we don't apply commands to non-matching names: + self.dbg.GetCommandInterpreter().HandleCommand("break modify --one-shot 1 %s"%(other_bkpt_name), retval) + self.assertTrue(retval.Succeeded(), "break modify failed with: %s."%(retval.GetError())) + self.assertTrue(not bkpt.IsOneShot(), "We applied one-shot to the wrong breakpoint.") + + def check_option_values(self, bp_object): + self.assertEqual(bp_object.IsOneShot(), self.is_one_shot, "IsOneShot") + self.assertEqual(bp_object.GetIgnoreCount(), self.ignore_count, "IgnoreCount") + self.assertEqual(bp_object.GetCondition(), self.condition, "Condition") + self.assertEqual(bp_object.GetAutoContinue(), self.auto_continue, "AutoContinue") + self.assertEqual(bp_object.GetThreadID(), self.tid, "Thread ID") + self.assertEqual(bp_object.GetThreadIndex(), self.tidx, "Thread Index") + self.assertEqual(bp_object.GetThreadName(), self.thread_name, "Thread Name") + self.assertEqual(bp_object.GetQueueName(), self.queue_name, "Queue Name") + set_cmds = lldb.SBStringList() + bp_object.GetCommandLineCommands(set_cmds) + self.assertEqual(set_cmds.GetSize(), self.cmd_list.GetSize(), "Size of command line commands") + for idx in range(0, set_cmds.GetSize()): + self.assertEqual(self.cmd_list.GetStringAtIndex(idx), set_cmds.GetStringAtIndex(idx), "Command %d"%(idx)) + + def make_a_dummy_name(self): + "This makes a breakpoint name in the dummy target to make sure it gets copied over" + + dummy_target = self.dbg.GetDummyTarget() + self.assertTrue(dummy_target.IsValid(), "Dummy target was not valid.") + + def cleanup (): + self.dbg.GetDummyTarget().DeleteBreakpointName(self.bp_name_string) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + # Now find it in the dummy target, and make sure these settings took: + bp_name = lldb.SBBreakpointName(dummy_target, self.bp_name_string) + # Make sure the name is right: + self.assertTrue (bp_name.GetName() == self.bp_name_string, "Wrong bp_name: %s"%(bp_name.GetName())) + bp_name.SetOneShot(self.is_one_shot) + bp_name.SetIgnoreCount(self.ignore_count) + bp_name.SetCondition(self.condition) + bp_name.SetAutoContinue(self.auto_continue) + bp_name.SetThreadID(self.tid) + bp_name.SetThreadIndex(self.tidx) + bp_name.SetThreadName(self.thread_name) + bp_name.SetQueueName(self.queue_name) + bp_name.SetCommandLineCommands(self.cmd_list) + + # Now look it up again, and make sure it got set correctly. + bp_name = lldb.SBBreakpointName(dummy_target, self.bp_name_string) + self.assertTrue(bp_name.IsValid(), "Failed to make breakpoint name.") + self.check_option_values(bp_name) + + def do_check_configuring_names(self): + """Use Python APIs to check that configuring breakpoint names works correctly.""" + other_bp_name_string = "AnotherBreakpointName" + cl_bp_name_string = "CLBreakpointName" + + # Now find the version copied in from the dummy target, and make sure these settings took: + bp_name = lldb.SBBreakpointName(self.target, self.bp_name_string) + self.assertTrue(bp_name.IsValid(), "Failed to make breakpoint name.") + self.check_option_values(bp_name) + + # Now add this name to a breakpoint, and make sure it gets configured properly + bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10) + success = bkpt.AddName(self.bp_name_string) + self.assertTrue(success, "Couldn't add this name to the breakpoint") + self.check_option_values(bkpt) + + # Now make a name from this breakpoint, and make sure the new name is properly configured: + new_name = lldb.SBBreakpointName(bkpt, other_bp_name_string) + self.assertTrue(new_name.IsValid(), "Couldn't make a valid bp_name from a breakpoint.") + self.check_option_values(bkpt) + + # Now change the name's option and make sure it gets propagated to + # the breakpoint: + new_auto_continue = not self.auto_continue + bp_name.SetAutoContinue(new_auto_continue) + self.assertEqual(bp_name.GetAutoContinue(), new_auto_continue, "Couldn't change auto-continue on the name") + self.assertEqual(bkpt.GetAutoContinue(), new_auto_continue, "Option didn't propagate to the breakpoint.") + + # Now make this same breakpoint name - but from the command line + cmd_str = "breakpoint name configure %s -o %d -i %d -c '%s' -G %d -t %d -x %d -T '%s' -q '%s' -H '%s'"%(cl_bp_name_string, + self.is_one_shot, + self.ignore_count, + self.condition, + self.auto_continue, + self.tid, + self.tidx, + self.thread_name, + self.queue_name, + self.help_string) + for cmd in self.cmd_list: + cmd_str += " -C '%s'"%(cmd) + + self.runCmd(cmd_str, check=True) + # Now look up this name again and check its options: + cl_name = lldb.SBBreakpointName(self.target, cl_bp_name_string) + self.check_option_values(cl_name) + # Also check the help string: + self.assertEqual(self.help_string, cl_name.GetHelpString(), "Help string didn't match") + # Change the name and make sure that works: + new_help = "I do something even more interesting" + cl_name.SetHelpString(new_help) + self.assertEqual(new_help, cl_name.GetHelpString(), "SetHelpString didn't") + + # We should have three names now, make sure the target can list them: + name_list = lldb.SBStringList() + self.target.GetBreakpointNames(name_list) + for name_string in [self.bp_name_string, other_bp_name_string, cl_bp_name_string]: + self.assertTrue(name_string in name_list, "Didn't find %s in names"%(name_string)) + + # Delete the name from the current target. Make sure that works and deletes the + # name from the breakpoint as well: + self.target.DeleteBreakpointName(self.bp_name_string) + name_list.Clear() + self.target.GetBreakpointNames(name_list) + self.assertTrue(self.bp_name_string not in name_list, "Didn't delete %s from a real target"%(self.bp_name_string)) + # Also make sure the name got removed from breakpoints holding it: + self.assertFalse(bkpt.MatchesName(self.bp_name_string), "Didn't remove the name from the breakpoint.") + + # Test that deleting the name we injected into the dummy target works (there's also a + # cleanup that will do this, but that won't test the result... + dummy_target = self.dbg.GetDummyTarget() + dummy_target.DeleteBreakpointName(self.bp_name_string) + name_list.Clear() + dummy_target.GetBreakpointNames(name_list) + self.assertTrue(self.bp_name_string not in name_list, "Didn't delete %s from the dummy target"%(self.bp_name_string)) + # Also make sure the name got removed from breakpoints holding it: + self.assertFalse(bkpt.MatchesName(self.bp_name_string), "Didn't remove the name from the breakpoint.") + + def check_permission_results(self, bp_name): + self.assertEqual(bp_name.GetAllowDelete(), False, "Didn't set allow delete.") + protected_bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10) + protected_id = protected_bkpt.GetID() + + unprotected_bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10) + unprotected_id = unprotected_bkpt.GetID() + + success = protected_bkpt.AddName(self.bp_name_string) + self.assertTrue(success, "Couldn't add this name to the breakpoint") + + self.target.DisableAllBreakpoints() + self.assertEqual(protected_bkpt.IsEnabled(), True, "Didnt' keep breakpoint from being disabled") + self.assertEqual(unprotected_bkpt.IsEnabled(), False, "Protected too many breakpoints from disabling.") + + # Try from the command line too: + unprotected_bkpt.SetEnabled(True) + result = lldb.SBCommandReturnObject() + self.dbg.GetCommandInterpreter().HandleCommand("break disable", result) + self.assertTrue(result.Succeeded()) + self.assertEqual(protected_bkpt.IsEnabled(), True, "Didnt' keep breakpoint from being disabled") + self.assertEqual(unprotected_bkpt.IsEnabled(), False, "Protected too many breakpoints from disabling.") + + self.target.DeleteAllBreakpoints() + bkpt = self.target.FindBreakpointByID(protected_id) + self.assertTrue(bkpt.IsValid(), "Didn't keep the breakpoint from being deleted.") + bkpt = self.target.FindBreakpointByID(unprotected_id) + self.assertFalse(bkpt.IsValid(), "Protected too many breakpoints from deletion.") + + # Remake the unprotected breakpoint and try again from the command line: + unprotected_bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10) + unprotected_id = unprotected_bkpt.GetID() + + self.dbg.GetCommandInterpreter().HandleCommand("break delete -f", result) + self.assertTrue(result.Succeeded()) + bkpt = self.target.FindBreakpointByID(protected_id) + self.assertTrue(bkpt.IsValid(), "Didn't keep the breakpoint from being deleted.") + bkpt = self.target.FindBreakpointByID(unprotected_id) + self.assertFalse(bkpt.IsValid(), "Protected too many breakpoints from deletion.") + + def do_check_configuring_permissions_sb(self): + bp_name = lldb.SBBreakpointName(self.target, self.bp_name_string) + + # Make a breakpoint name with delete disallowed: + bp_name = lldb.SBBreakpointName(self.target, self.bp_name_string) + self.assertTrue(bp_name.IsValid(), "Failed to make breakpoint name for valid name.") + + bp_name.SetAllowDelete(False) + bp_name.SetAllowDisable(False) + bp_name.SetAllowList(False) + self.check_permission_results(bp_name) + + def do_check_configuring_permissions_cli(self): + # Make the name with the right options using the command line: + self.runCmd("breakpoint name configure -L 0 -D 0 -A 0 %s"%(self.bp_name_string), check=True) + # Now look up the breakpoint we made, and check that it works. + bp_name = lldb.SBBreakpointName(self.target, self.bp_name_string) + self.assertTrue(bp_name.IsValid(), "Didn't make a breakpoint name we could find.") + self.check_permission_results(bp_name) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_names/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_names/main.c new file mode 100644 index 00000000000..b1ed4465c1d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_names/main.c @@ -0,0 +1,53 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include <stdio.h> + +// This simple program is to demonstrate the capability of the lldb command +// "breakpoint modify -i <count> breakpt-id" to set the number of times a +// breakpoint is skipped before stopping. Ignore count can also be set upon +// breakpoint creation by 'breakpoint set ... -i <count>'. + +int a(int); +int b(int); +int c(int); + +int a(int val) +{ + if (val <= 1) + return b(val); + else if (val >= 3) + return c(val); // a(3) -> c(3) Find the call site of c(3). + + return val; +} + +int b(int val) +{ + return c(val); +} + +int c(int val) +{ + return val + 3; // Find the line number of function "c" here. +} + +int main (int argc, char const *argv[]) +{ + int A1 = a(1); // a(1) -> b(1) -> c(1) + printf("a(1) returns %d\n", A1); + + int B2 = b(2); // b(2) -> c(2) Find the call site of b(2). + printf("b(2) returns %d\n", B2); + + int A3 = a(3); // a(3) -> c(3) Find the call site of a(3). + printf("a(3) returns %d\n", A3); + + int C1 = c(5); // Find the call site of c in main. + printf ("c(5) returns %d\n", C1); + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_options/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_options/Makefile new file mode 100644 index 00000000000..7df22699c57 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_options/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp foo.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_options/TestBreakpointOptions.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_options/TestBreakpointOptions.py new file mode 100644 index 00000000000..0419b4df5dd --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_options/TestBreakpointOptions.py @@ -0,0 +1,113 @@ +""" +Test breakpoint command for different options. +""" + + + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class BreakpointOptionsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test(self): + """Test breakpoint command for different options.""" + self.build() + self.breakpoint_options_test() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.line = line_number('main.cpp', '// Set break point at this line.') + + def breakpoint_options_test(self): + """Test breakpoint command for different options.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # This should create a breakpoint with 1 locations. + lldbutil.run_break_set_by_file_and_line( + self, + "main.cpp", + self.line, + extra_options="-K 1", + num_expected_locations=1) + lldbutil.run_break_set_by_file_and_line( + self, + "main.cpp", + self.line, + extra_options="-K 0", + num_expected_locations=1) + + # Run the program. + self.runCmd("run", RUN_SUCCEEDED) + + # Stopped once. + self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT, + substrs=["stop reason = breakpoint 2."]) + + # Check the list of breakpoint. + self.expect( + "breakpoint list -f", + "Breakpoint locations shown correctly", + substrs=[ + "1: file = 'main.cpp', line = %d, exact_match = 0, locations = 1" % + self.line, + "2: file = 'main.cpp', line = %d, exact_match = 0, locations = 1" % + self.line]) + + # Continue the program, there should be another stop. + self.runCmd("process continue") + + # Stopped again. + self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT, + substrs=["stop reason = breakpoint 1."]) + + # Continue the program, we should exit. + self.runCmd("process continue") + + # We should exit. + self.expect("process status", "Process exited successfully", + patterns=["^Process [0-9]+ exited with status = 0"]) + + def breakpoint_options_language_test(self): + """Test breakpoint command for language option.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # This should create a breakpoint with 1 locations. + lldbutil.run_break_set_by_symbol( + self, + 'ns::func', + sym_exact=False, + extra_options="-L c++", + num_expected_locations=1) + + # This should create a breakpoint with 0 locations. + lldbutil.run_break_set_by_symbol( + self, + 'ns::func', + sym_exact=False, + extra_options="-L c", + num_expected_locations=0) + self.runCmd("settings set target.language c") + lldbutil.run_break_set_by_symbol( + self, 'ns::func', sym_exact=False, num_expected_locations=0) + + # Run the program. + self.runCmd("run", RUN_SUCCEEDED) + + # Stopped once. + self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT, + substrs=["stop reason = breakpoint 1."]) + + # Continue the program, we should exit. + self.runCmd("process continue") + + # We should exit. + self.expect("process status", "Process exited successfully", + patterns=["^Process [0-9]+ exited with status = 0"]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_options/foo.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_options/foo.cpp new file mode 100644 index 00000000000..e5d0e09803e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_options/foo.cpp @@ -0,0 +1,12 @@ + +namespace ns { + int func(void) + { + return 0; + } +} + +extern "C" int foo(void) +{ + return ns::func(); +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_options/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_options/main.cpp new file mode 100644 index 00000000000..b2e8f523c84 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_options/main.cpp @@ -0,0 +1,4 @@ +extern "C" int foo(void); +int main (int argc, char **argv) { // Set break point at this line. + return foo(); +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/TestBreakpointSetRestart.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/TestBreakpointSetRestart.py new file mode 100644 index 00000000000..40a20a04b76 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/TestBreakpointSetRestart.py @@ -0,0 +1,50 @@ +""" +Test inferior restart when breakpoint is set on running target. +""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * + + +class BreakpointSetRestart(TestBase): + + mydir = TestBase.compute_mydir(__file__) + BREAKPOINT_TEXT = 'Set a breakpoint here' + + @skipIfNetBSD + def test_breakpoint_set_restart(self): + self.build() + + exe = self.getBuildArtifact("a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + self.dbg.SetAsync(True) + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + event = lldb.SBEvent() + # Wait for inferior to transition to running state + while self.dbg.GetListener().WaitForEvent(2, event): + if lldb.SBProcess.GetStateFromEvent(event) == lldb.eStateRunning: + break + + bp = target.BreakpointCreateBySourceRegex( + self.BREAKPOINT_TEXT, lldb.SBFileSpec('main.cpp')) + self.assertTrue( + bp.IsValid() and bp.GetNumLocations() == 1, + VALID_BREAKPOINT) + + while self.dbg.GetListener().WaitForEvent(2, event): + if lldb.SBProcess.GetStateFromEvent( + event) == lldb.eStateStopped and lldb.SBProcess.GetRestartedFromEvent(event): + continue + if lldb.SBProcess.GetStateFromEvent(event) == lldb.eStateRunning: + continue + self.fail( + "Setting a breakpoint generated an unexpected event: %s" % + lldb.SBDebugger.StateAsCString( + lldb.SBProcess.GetStateFromEvent(event))) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/main.cpp new file mode 100644 index 00000000000..46682ec264d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/main.cpp @@ -0,0 +1,24 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <chrono> +#include <stdio.h> +#include <thread> + + +int main(int argc, char const *argv[]) +{ + static bool done = false; + while (!done) + { + std::this_thread::sleep_for(std::chrono::milliseconds{100}); + } + printf("Set a breakpoint here.\n"); + return 0; +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/comp_dir_symlink/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/comp_dir_symlink/Makefile new file mode 100644 index 00000000000..7c6a18b0f24 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/comp_dir_symlink/Makefile @@ -0,0 +1,12 @@ +CXX_SOURCES := relative.cpp + +EXE := CompDirSymLink + +include Makefile.rules + +# Force relative filenames by copying it into the build directory. +relative.cpp: main.cpp + cp -f $< $@ + +clean:: + rm -rf relative.cpp diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/comp_dir_symlink/TestCompDirSymLink.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/comp_dir_symlink/TestCompDirSymLink.py new file mode 100644 index 00000000000..0e372c73249 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/comp_dir_symlink/TestCompDirSymLink.py @@ -0,0 +1,78 @@ +""" +Test breakpoint command with AT_comp_dir set to symbolic link. +""" + + +import os +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +_EXE_NAME = 'CompDirSymLink' # Must match Makefile +_SRC_FILE = 'relative.cpp' +_COMP_DIR_SYM_LINK_PROP = 'plugin.symbol-file.dwarf.comp-dir-symlink-paths' + + +class CompDirSymLinkTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.line = line_number( + os.path.join(self.getSourceDir(), "main.cpp"), + '// Set break point at this line.') + + @skipIf(hostoslist=["windows"]) + def test_symlink_paths_set(self): + pwd_symlink = self.create_src_symlink() + self.doBuild(pwd_symlink) + self.runCmd( + "settings set %s %s" % + (_COMP_DIR_SYM_LINK_PROP, pwd_symlink)) + src_path = self.getBuildArtifact(_SRC_FILE) + lldbutil.run_break_set_by_file_and_line(self, src_path, self.line) + + @skipIf(hostoslist=no_match(["linux"])) + def test_symlink_paths_set_procselfcwd(self): + os.chdir(self.getBuildDir()) + pwd_symlink = '/proc/self/cwd' + self.doBuild(pwd_symlink) + self.runCmd( + "settings set %s %s" % + (_COMP_DIR_SYM_LINK_PROP, pwd_symlink)) + src_path = self.getBuildArtifact(_SRC_FILE) + # /proc/self/cwd points to a realpath form of current directory. + src_path = os.path.realpath(src_path) + lldbutil.run_break_set_by_file_and_line(self, src_path, self.line) + + @skipIf(hostoslist=["windows"]) + def test_symlink_paths_unset(self): + pwd_symlink = self.create_src_symlink() + self.doBuild(pwd_symlink) + self.runCmd('settings clear ' + _COMP_DIR_SYM_LINK_PROP) + src_path = self.getBuildArtifact(_SRC_FILE) + self.assertRaises( + AssertionError, + lldbutil.run_break_set_by_file_and_line, + self, + src_path, + self.line) + + def create_src_symlink(self): + pwd_symlink = self.getBuildArtifact('pwd_symlink') + if os.path.exists(pwd_symlink): + os.unlink(pwd_symlink) + os.symlink(self.getBuildDir(), pwd_symlink) + self.addTearDownHook(lambda: os.remove(pwd_symlink)) + return pwd_symlink + + def doBuild(self, pwd_symlink): + self.build(None, None, {'PWD': pwd_symlink}) + + exe = self.getBuildArtifact(_EXE_NAME) + self.runCmd('file ' + exe, CURRENT_EXECUTABLE_SET) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/comp_dir_symlink/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/comp_dir_symlink/main.cpp new file mode 100644 index 00000000000..13e5e3e891f --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/comp_dir_symlink/main.cpp @@ -0,0 +1,12 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +int main (int argc, char const *argv[]) +{ + return 0; // Set break point at this line. +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/Makefile new file mode 100644 index 00000000000..2c00681fa22 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/Makefile @@ -0,0 +1,8 @@ +CXX_SOURCES := main.cpp + +ifneq (,$(findstring icc,$(CC))) + CXXFLAGS_EXTRAS := -debug inline-debug-info +endif + + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/TestConsecutiveBreakpoints.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/TestConsecutiveBreakpoints.py new file mode 100644 index 00000000000..cf36f143838 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/TestConsecutiveBreakpoints.py @@ -0,0 +1,103 @@ +""" +Test that we handle breakpoints on consecutive instructions correctly. +""" + + + +import unittest2 +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ConsecutiveBreakpointsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def prepare_test(self): + self.build() + + (self.target, self.process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint( + self, "Set breakpoint here", lldb.SBFileSpec("main.cpp")) + + # Set breakpoint to the next instruction + frame = self.thread.GetFrameAtIndex(0) + + address = frame.GetPCAddress() + instructions = self.target.ReadInstructions(address, 2) + self.assertTrue(len(instructions) == 2) + self.bkpt_address = instructions[1].GetAddress() + self.breakpoint2 = self.target.BreakpointCreateByAddress( + self.bkpt_address.GetLoadAddress(self.target)) + self.assertTrue( + self.breakpoint2 and self.breakpoint2.GetNumLocations() == 1, + VALID_BREAKPOINT) + + def finish_test(self): + # Run the process until termination + self.process.Continue() + self.assertEquals(self.process.GetState(), lldb.eStateExited) + + @no_debug_info_test + def test_continue(self): + """Test that continue stops at the second breakpoint.""" + self.prepare_test() + + self.process.Continue() + self.assertEquals(self.process.GetState(), lldb.eStateStopped) + # We should be stopped at the second breakpoint + self.thread = lldbutil.get_one_thread_stopped_at_breakpoint( + self.process, self.breakpoint2) + self.assertIsNotNone( + self.thread, + "Expected one thread to be stopped at breakpoint 2") + + self.finish_test() + + @no_debug_info_test + def test_single_step(self): + """Test that single step stops at the second breakpoint.""" + self.prepare_test() + + step_over = False + self.thread.StepInstruction(step_over) + + self.assertEquals(self.process.GetState(), lldb.eStateStopped) + self.assertEquals( + self.thread.GetFrameAtIndex(0).GetPCAddress().GetLoadAddress( + self.target), self.bkpt_address.GetLoadAddress( + self.target)) + self.thread = lldbutil.get_one_thread_stopped_at_breakpoint( + self.process, self.breakpoint2) + self.assertIsNotNone( + self.thread, + "Expected one thread to be stopped at breakpoint 2") + + self.finish_test() + + @no_debug_info_test + def test_single_step_thread_specific(self): + """Test that single step stops, even though the second breakpoint is not valid.""" + self.prepare_test() + + # Choose a thread other than the current one. A non-existing thread is + # fine. + thread_index = self.process.GetNumThreads() + 1 + self.assertFalse(self.process.GetThreadAtIndex(thread_index).IsValid()) + self.breakpoint2.SetThreadIndex(thread_index) + + step_over = False + self.thread.StepInstruction(step_over) + + self.assertEquals(self.process.GetState(), lldb.eStateStopped) + self.assertEquals( + self.thread.GetFrameAtIndex(0).GetPCAddress().GetLoadAddress( + self.target), self.bkpt_address.GetLoadAddress( + self.target)) + self.assertEquals( + self.thread.GetStopReason(), + lldb.eStopReasonPlanComplete, + "Stop reason should be 'plan complete'") + + self.finish_test() diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/main.cpp new file mode 100644 index 00000000000..94d0a0415d7 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/main.cpp @@ -0,0 +1,18 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +int +main(int argc, char const *argv[]) +{ + int a = 0; + int b = 1; + a = b + 1; // Set breakpoint here + b = a + 1; + return 0; +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp/Makefile new file mode 100644 index 00000000000..2c00681fa22 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp/Makefile @@ -0,0 +1,8 @@ +CXX_SOURCES := main.cpp + +ifneq (,$(findstring icc,$(CC))) + CXXFLAGS_EXTRAS := -debug inline-debug-info +endif + + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp/TestCPPBreakpointLocations.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp/TestCPPBreakpointLocations.py new file mode 100644 index 00000000000..be21c6eea13 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp/TestCPPBreakpointLocations.py @@ -0,0 +1,112 @@ +""" +Test lldb breakpoint ids. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestCPPBreakpointLocations(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764") + def test(self): + self.build() + self.breakpoint_id_tests() + + def verify_breakpoint_locations(self, target, bp_dict): + + name = bp_dict['name'] + names = bp_dict['loc_names'] + bp = target.BreakpointCreateByName(name) + self.assertEquals( + bp.GetNumLocations(), + len(names), + "Make sure we find the right number of breakpoint locations") + + bp_loc_names = list() + for bp_loc in bp: + bp_loc_names.append(bp_loc.GetAddress().GetFunction().GetName()) + + for name in names: + found = name in bp_loc_names + if not found: + print("Didn't find '%s' in: %s" % (name, bp_loc_names)) + self.assertTrue(found, "Make sure we find all required locations") + + def breakpoint_id_tests(self): + + # Create a target by the debugger. + exe = self.getBuildArtifact("a.out") + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + bp_dicts = [ + {'name': 'func1', 'loc_names': ['a::c::func1()', 'b::c::func1()']}, + {'name': 'func2', 'loc_names': ['a::c::func2()', 'c::d::func2()']}, + {'name': 'func3', 'loc_names': ['a::c::func3()', 'b::c::func3()', 'c::d::func3()']}, + {'name': 'c::func1', 'loc_names': ['a::c::func1()', 'b::c::func1()']}, + {'name': 'c::func2', 'loc_names': ['a::c::func2()']}, + {'name': 'c::func3', 'loc_names': ['a::c::func3()', 'b::c::func3()']}, + {'name': 'a::c::func1', 'loc_names': ['a::c::func1()']}, + {'name': 'b::c::func1', 'loc_names': ['b::c::func1()']}, + {'name': 'c::d::func2', 'loc_names': ['c::d::func2()']}, + {'name': 'a::c::func1()', 'loc_names': ['a::c::func1()']}, + {'name': 'b::c::func1()', 'loc_names': ['b::c::func1()']}, + {'name': 'c::d::func2()', 'loc_names': ['c::d::func2()']}, + ] + + for bp_dict in bp_dicts: + self.verify_breakpoint_locations(target, bp_dict) + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764") + def test_destructors(self): + self.build() + exe = self.getBuildArtifact("a.out") + target = self.dbg.CreateTarget(exe) + + # Don't skip prologue, so we can check the breakpoint address more + # easily + self.runCmd("settings set target.skip-prologue false") + try: + names = ['~c', 'c::~c', 'c::~c()'] + loc_names = {'a::c::~c()', 'b::c::~c()'} + # TODO: For windows targets we should put windows mangled names + # here + symbols = [ + '_ZN1a1cD1Ev', + '_ZN1a1cD2Ev', + '_ZN1b1cD1Ev', + '_ZN1b1cD2Ev'] + + for name in names: + bp = target.BreakpointCreateByName(name) + + bp_loc_names = {bp_loc.GetAddress().GetFunction().GetName() + for bp_loc in bp} + self.assertEquals( + bp_loc_names, + loc_names, + "Breakpoint set on the correct symbol") + + bp_addresses = {bp_loc.GetLoadAddress() for bp_loc in bp} + symbol_addresses = set() + for symbol in symbols: + sc_list = target.FindSymbols(symbol, lldb.eSymbolTypeCode) + self.assertEquals( + sc_list.GetSize(), 1, "Found symbol " + symbol) + symbol = sc_list.GetContextAtIndex(0).GetSymbol() + symbol_addresses.add( + symbol.GetStartAddress().GetLoadAddress(target)) + + self.assertEquals( + symbol_addresses, + bp_addresses, + "Breakpoint set on correct address") + finally: + self.runCmd("settings clear target.skip-prologue") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp/main.cpp new file mode 100644 index 00000000000..4afabcbd36e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp/main.cpp @@ -0,0 +1,82 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include <stdio.h> +#include <stdint.h> + +namespace a { + class c { + public: + c(); + ~c(); + void func1() + { + puts (__PRETTY_FUNCTION__); + } + void func2() + { + puts (__PRETTY_FUNCTION__); + } + void func3() + { + puts (__PRETTY_FUNCTION__); + } + }; + + c::c() {} + c::~c() {} +} + +namespace b { + class c { + public: + c(); + ~c(); + void func1() + { + puts (__PRETTY_FUNCTION__); + } + void func3() + { + puts (__PRETTY_FUNCTION__); + } + }; + + c::c() {} + c::~c() {} +} + +namespace c { + class d { + public: + d () {} + ~d() {} + void func2() + { + puts (__PRETTY_FUNCTION__); + } + void func3() + { + puts (__PRETTY_FUNCTION__); + } + }; +} + +int main (int argc, char const *argv[]) +{ + a::c ac; + b::c bc; + c::d cd; + ac.func1(); + ac.func2(); + ac.func3(); + bc.func1(); + bc.func3(); + cd.func2(); + cd.func3(); + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp_exception/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp_exception/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp_exception/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp_exception/TestCPPExceptionBreakpoint.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp_exception/TestCPPExceptionBreakpoint.py new file mode 100644 index 00000000000..ba8e94eddca --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp_exception/TestCPPExceptionBreakpoint.py @@ -0,0 +1,86 @@ +""" +Test that you can set breakpoint and hit the C++ language exception breakpoint +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestCPPExceptionBreakpoint (TestBase): + + mydir = TestBase.compute_mydir(__file__) + my_var = 10 + + @add_test_categories(['pyapi']) + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24538") + @expectedFailureNetBSD + def test_cpp_exception_breakpoint(self): + """Test setting and hitting the C++ exception breakpoint.""" + self.build() + self.do_cpp_exception_bkpt() + + @add_test_categories(['pyapi']) + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24538") + @expectedFailureNetBSD + def test_dummy_target_cpp_exception_breakpoint(self): + """Test setting and hitting the C++ exception breakpoint from dummy target.""" + self.build() + self.do_dummy_target_cpp_exception_bkpt() + + def setUp(self): + TestBase.setUp(self) + self.main_source = "main.c" + self.main_source_spec = lldb.SBFileSpec(self.main_source) + + def do_cpp_exception_bkpt(self): + exe = self.getBuildArtifact("a.out") + error = lldb.SBError() + + self.target = self.dbg.CreateTarget(exe) + self.assertTrue(self.target, VALID_TARGET) + + exception_bkpt = self.target.BreakpointCreateForException( + lldb.eLanguageTypeC_plus_plus, False, True) + self.assertTrue( + exception_bkpt.IsValid(), + "Created exception breakpoint.") + + process = self.target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + thread_list = lldbutil.get_threads_stopped_at_breakpoint( + process, exception_bkpt) + self.assertTrue(len(thread_list) == 1, + "One thread stopped at the exception breakpoint.") + + def do_dummy_target_cpp_exception_bkpt(self): + exe = self.getBuildArtifact("a.out") + error = lldb.SBError() + + dummy_exception_bkpt = self.dbg.GetDummyTarget().BreakpointCreateForException( + lldb.eLanguageTypeC_plus_plus, False, True) + self.assertTrue( + dummy_exception_bkpt.IsValid(), + "Created exception breakpoint in dummy target.") + + self.target = self.dbg.CreateTarget(exe) + self.assertTrue(self.target, VALID_TARGET) + + exception_bkpt = self.target.GetBreakpointAtIndex(0) + self.assertTrue( + exception_bkpt.IsValid(), + "Target primed with exception breakpoint from dummy target.") + + process = self.target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + thread_list = lldbutil.get_threads_stopped_at_breakpoint( + process, exception_bkpt) + self.assertTrue(len(thread_list) == 1, + "One thread stopped at the exception breakpoint.") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp_exception/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp_exception/main.cpp new file mode 100644 index 00000000000..76cb22735a7 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp_exception/main.cpp @@ -0,0 +1,13 @@ +#include <exception> + +void +throws_int () +{ + throw 5; +} + +int +main () +{ + throws_int(); +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/TestDebugBreak.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/TestDebugBreak.py new file mode 100644 index 00000000000..2164ddfb8f6 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/TestDebugBreak.py @@ -0,0 +1,57 @@ +""" +Test embedded breakpoints, like `asm int 3;` in x86 or or `__debugbreak` on Windows. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class DebugBreakTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipIf(archs=no_match(["i386", "i686", "x86_64"])) + @no_debug_info_test + def test_asm_int_3(self): + """Test that intrinsics like `__debugbreak();` and `asm {"int3"}` are treated like breakpoints.""" + self.build() + exe = self.getBuildArtifact("a.out") + + # Run the program. + target = self.dbg.CreateTarget(exe) + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + + # We've hit the first stop, so grab the frame. + self.assertEqual(process.GetState(), lldb.eStateStopped) + stop_reason = lldb.eStopReasonException if (lldbplatformutil.getPlatform( + ) == "windows" or lldbplatformutil.getPlatform() == "macosx") else lldb.eStopReasonSignal + thread = lldbutil.get_stopped_thread(process, stop_reason) + self.assertIsNotNone( + thread, "Unable to find thread stopped at the __debugbreak()") + frame = thread.GetFrameAtIndex(0) + + # We should be in funciton 'bar'. + self.assertTrue(frame.IsValid()) + function_name = frame.GetFunctionName() + self.assertTrue('bar' in function_name, + "Unexpected function name {}".format(function_name)) + + # We should be able to evaluate the parameter foo. + value = frame.EvaluateExpression('*foo') + self.assertEqual(value.GetValueAsSigned(), 42) + + # The counter should be 1 at the first stop and increase by 2 for each + # subsequent stop. + counter = 1 + while counter < 20: + value = frame.EvaluateExpression('count') + self.assertEqual(value.GetValueAsSigned(), counter) + counter += 2 + process.Continue() + + # The inferior should exit after the last iteration. + self.assertEqual(process.GetState(), lldb.eStateExited) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/main.c new file mode 100644 index 00000000000..5f936327e4e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/main.c @@ -0,0 +1,29 @@ +#ifdef _MSC_VER +#include <intrin.h> +#define BREAKPOINT_INTRINSIC() __debugbreak() +#else +#define BREAKPOINT_INTRINSIC() __asm__ __volatile__ ("int3") +#endif + +int +bar(int const *foo) +{ + int count = 0, i = 0; + for (; i < 10; ++i) + { + count += 1; + BREAKPOINT_INTRINSIC(); + count += 1; + } + return *foo; +} + +int +main(int argc, char **argv) +{ + int foo = 42; + bar(&foo); + return 0; +} + + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/dummy_target_breakpoints/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/dummy_target_breakpoints/Makefile new file mode 100644 index 00000000000..9645fd9cc8d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/dummy_target_breakpoints/Makefile @@ -0,0 +1,7 @@ +C_SOURCES := main.c + +ifneq (,$(findstring icc,$(CC))) + CFLAGS_EXTRAS := -debug inline-debug-info +endif + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/dummy_target_breakpoints/TestBreakpointsWithNoTargets.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/dummy_target_breakpoints/TestBreakpointsWithNoTargets.py new file mode 100644 index 00000000000..e3f293a4a55 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/dummy_target_breakpoints/TestBreakpointsWithNoTargets.py @@ -0,0 +1,71 @@ +""" +Test breakpoint commands set before we have a target +""" + + + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class BreakpointInDummyTarget (TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test(self): + """Test breakpoint set before we have a target. """ + self.build() + self.dummy_breakpoint_test() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.line = line_number('main.c', 'Set a breakpoint on this line.') + self.line2 = line_number('main.c', 'Set another on this line.') + + def dummy_breakpoint_test(self): + """Test breakpoint set before we have a target. """ + + # This should create a breakpoint with 3 locations. + lldbutil.run_break_set_by_file_and_line( + self, "main.c", self.line, num_expected_locations=0) + lldbutil.run_break_set_by_file_and_line( + self, "main.c", self.line2, num_expected_locations=0) + + # This is the function to remove breakpoints from the dummy target + # to get a clean slate for the next test case. + def cleanup(): + self.runCmd('breakpoint delete -D -f', check=False) + self.runCmd('breakpoint list', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # The breakpoint list should show 3 locations. + self.expect( + "breakpoint list -f", + "Breakpoint locations shown correctly", + substrs=[ + "1: file = 'main.c', line = %d, exact_match = 0, locations = 1" % + self.line, + "2: file = 'main.c', line = %d, exact_match = 0, locations = 1" % + self.line2]) + + # Run the program. + self.runCmd("run", RUN_SUCCEEDED) + + # Stopped once. + self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT, + substrs=["stop reason = breakpoint 1."]) + + # Continue the program, there should be another stop. + self.runCmd("process continue") + + # Stopped again. + self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT, + substrs=["stop reason = breakpoint 2."]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/dummy_target_breakpoints/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/dummy_target_breakpoints/main.c new file mode 100644 index 00000000000..e1f03237cd1 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/dummy_target_breakpoints/main.c @@ -0,0 +1,11 @@ +#include <stdio.h> + +int +main (int argc, char **argv) +{ + printf ("Set a breakpoint on this line.\n"); + + return 0; // Set another on this line. +} + + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/Makefile new file mode 100644 index 00000000000..4b3098cf7da --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/Makefile @@ -0,0 +1,5 @@ +DYLIB_NAME := foo +DYLIB_CXX_SOURCES := foo.cpp +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/TestBreakpointInGlobalConstructor.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/TestBreakpointInGlobalConstructor.py new file mode 100644 index 00000000000..4439607d91c --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/TestBreakpointInGlobalConstructor.py @@ -0,0 +1,46 @@ +""" +Test that we can hit breakpoints in global constructors +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestBreakpointInGlobalConstructors(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + @expectedFailureNetBSD + def test(self): + self.build() + self.line_foo = line_number('foo.cpp', '// !BR_foo') + self.line_main = line_number('main.cpp', '// !BR_main') + + target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) + self.assertTrue(target, VALID_TARGET) + + env= self.registerSharedLibrariesWithTarget(target, ["foo"]) + + bp_main = lldbutil.run_break_set_by_file_and_line( + self, 'main.cpp', self.line_main) + + bp_foo = lldbutil.run_break_set_by_file_and_line( + self, 'foo.cpp', self.line_foo, num_expected_locations=-2) + + process = target.LaunchSimple( + None, env, self.get_process_working_directory()) + + self.assertIsNotNone( + lldbutil.get_one_thread_stopped_at_breakpoint_id( + self.process(), bp_foo)) + + self.runCmd("continue") + + self.assertIsNotNone( + lldbutil.get_one_thread_stopped_at_breakpoint_id( + self.process(), bp_main)) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/foo.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/foo.cpp new file mode 100644 index 00000000000..f959a295467 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/foo.cpp @@ -0,0 +1,7 @@ +#include "foo.h" + +Foo::Foo() : x(42) { + bool some_code = x == 42; // !BR_foo +} + +Foo FooObj; diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/foo.h b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/foo.h new file mode 100644 index 00000000000..3bc63fed755 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/foo.h @@ -0,0 +1,11 @@ +#ifndef FOO_H +#define FOO_H + +struct LLDB_TEST_API Foo { + Foo(); + int x; +}; + +extern LLDB_TEST_API Foo FooObj; + +#endif diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/main.cpp new file mode 100644 index 00000000000..d1c8038dfad --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/main.cpp @@ -0,0 +1,14 @@ +#include "foo.h" + +struct Main { + Main(); + int x; +}; + +Main::Main() : x(47) { + bool some_code = x == 47; // !BR_main +} + +Main MainObj; + +int main() { return MainObj.x + FooObj.x; } diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/Makefile new file mode 100644 index 00000000000..de4ec12b13c --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/Makefile @@ -0,0 +1,4 @@ +ENABLE_THREADS := YES +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/TestHWBreakMultiThread.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/TestHWBreakMultiThread.py new file mode 100644 index 00000000000..56112b24eb5 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/TestHWBreakMultiThread.py @@ -0,0 +1,104 @@ +""" +Test hardware breakpoints for multiple threads. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +# Hardware breakpoints are supported only by platforms mentioned in oslist. +@skipUnlessPlatform(oslist=['linux']) +class HardwareBreakpointMultiThreadTestCase(TestBase): + NO_DEBUG_INFO_TESTCASE = True + + mydir = TestBase.compute_mydir(__file__) + + # LLDB supports hardware breakpoints for arm and aarch64 architectures. + @skipIf(archs=no_match(['arm', 'aarch64'])) + def test_hw_break_set_delete_multi_thread(self): + self.build() + self.setTearDownCleanup() + self.break_multi_thread('delete') + + # LLDB supports hardware breakpoints for arm and aarch64 architectures. + @skipIf(archs=no_match(['arm', 'aarch64'])) + def test_hw_break_set_disable_multi_thread(self): + self.build() + self.setTearDownCleanup() + self.break_multi_thread('disable') + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Our simple source filename. + self.source = 'main.cpp' + # Find the line number to break inside main(). + self.first_stop = line_number( + self.source, 'Starting thread creation with hardware breakpoint set') + + def break_multi_thread(self, removal_type): + """Test that lldb hardware breakpoints work for multiple threads.""" + self.runCmd("file " + self.getBuildArtifact("a.out"), + CURRENT_EXECUTABLE_SET) + + # Stop in main before creating any threads. + lldbutil.run_break_set_by_file_and_line( + self, None, self.first_stop, num_expected_locations=1) + + # Run the program. + self.runCmd("run", RUN_SUCCEEDED) + + # We should be stopped again due to the breakpoint. + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # Now set a hardware breakpoint in thread function. + self.expect("breakpoint set -b hw_break_function --hardware", + substrs=[ + 'Breakpoint', + 'hw_break_function', + 'address = 0x']) + + # We should stop in hw_break_function function for 4 threads. + count = 0 + + while count < 2 : + + self.runCmd("process continue") + + # We should be stopped in hw_break_function + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=[ + 'stop reason = breakpoint', + 'hw_break_function']) + + # Continue the loop and test that we are stopped 4 times. + count += 1 + + if removal_type == 'delete': + self.runCmd("settings set auto-confirm true") + + # Now 'breakpoint delete' should just work fine without confirmation + # prompt from the command interpreter. + self.expect("breakpoint delete", + startstr="All breakpoints removed") + + # Restore the original setting of auto-confirm. + self.runCmd("settings clear auto-confirm") + + elif removal_type == 'disable': + self.expect("breakpoint disable", + startstr="All breakpoints disabled.") + + # Continue. Program should exit without stopping anywhere. + self.runCmd("process continue") + + # Process should have stopped and exited with status = 0 + self.expect("process status", PROCESS_STOPPED, + patterns=['Process .* exited with status = 0']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/main.cpp new file mode 100644 index 00000000000..94a12c6241d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/main.cpp @@ -0,0 +1,50 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <chrono> +#include <cstdio> +#include <mutex> +#include <random> +#include <thread> + +#define NUM_OF_THREADS 4 + +std::mutex hw_break_mutex; + +void +hw_break_function (uint32_t thread_index) { + printf ("%s called by Thread #%u...\n", __FUNCTION__, thread_index); +} + + +void +thread_func (uint32_t thread_index) { + printf ("%s (thread index = %u) starting...\n", __FUNCTION__, thread_index); + + hw_break_mutex.lock(); + + hw_break_function(thread_index); // Call hw_break_function + + hw_break_mutex.unlock(); +} + + +int main (int argc, char const *argv[]) +{ + std::thread threads[NUM_OF_THREADS]; + + printf ("Starting thread creation with hardware breakpoint set...\n"); + + for (auto &thread : threads) + thread = std::thread{thread_func, std::distance(threads, &thread)}; + + for (auto &thread : threads) + thread.join(); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/inlined_breakpoints/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/inlined_breakpoints/Makefile new file mode 100644 index 00000000000..551d02feac8 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/inlined_breakpoints/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := int.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/inlined_breakpoints/TestInlinedBreakpoints.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/inlined_breakpoints/TestInlinedBreakpoints.py new file mode 100644 index 00000000000..76fefda8a9f --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/inlined_breakpoints/TestInlinedBreakpoints.py @@ -0,0 +1,66 @@ +""" +Test that inlined breakpoints (breakpoint set on a file/line included from +another source file) works correctly. +""" + + + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class InlinedBreakpointsTestCase(TestBase): + """Bug fixed: rdar://problem/8464339""" + + mydir = TestBase.compute_mydir(__file__) + + def test_with_run_command(self): + """Test 'b basic_types.cpp:176' does break (where int.cpp includes basic_type.cpp).""" + self.build() + self.inlined_breakpoints() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside basic_type.cpp. + self.line = line_number( + 'basic_type.cpp', + '// Set break point at this line.') + + def inlined_breakpoints(self): + """Test 'b basic_types.cpp:176' does break (where int.cpp includes basic_type.cpp).""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # With the inline-breakpoint-strategy, our file+line breakpoint should + # not resolve to a location. + self.runCmd('settings set target.inline-breakpoint-strategy headers') + + # Set a breakpoint and fail because it is in an inlined source + # implemenation file + lldbutil.run_break_set_by_file_and_line( + self, "basic_type.cpp", self.line, num_expected_locations=0) + + # Now enable breakpoints in implementation files and see the breakpoint + # set succeed + self.runCmd('settings set target.inline-breakpoint-strategy always') + # And add hooks to restore the settings during tearDown(). + self.addTearDownHook(lambda: self.runCmd( + "settings set target.inline-breakpoint-strategy always")) + + lldbutil.run_break_set_by_file_and_line( + self, + "basic_type.cpp", + self.line, + num_expected_locations=1, + loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + # And it should break at basic_type.cpp:176. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint', + 'basic_type.cpp:%d' % self.line]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/inlined_breakpoints/basic_type.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/inlined_breakpoints/basic_type.cpp new file mode 100644 index 00000000000..75d2c3690c8 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/inlined_breakpoints/basic_type.cpp @@ -0,0 +1,178 @@ +// This file must have the following defined before it is included: +// T defined to the type to test (int, float, etc) +// T_CSTR a C string representation of the type T ("int", "float") +// T_VALUE_1 defined to a valid initializer value for TEST_TYPE (7 for int, 2.0 for float) +// T_VALUE_2, T_VALUE_3, T_VALUE_4 defined to a valid initializer value for TEST_TYPE that is different from TEST_VALUE_1 +// T_PRINTF_FORMAT defined if T can be printed with printf +// +// An example for integers is below +#if 0 + +#define T int +#define T_CSTR "int" +#define T_VALUE_1 11001110 +#define T_VALUE_2 22002220 +#define T_VALUE_3 33003330 +#define T_VALUE_4 44044440 +#define T_PRINTF_FORMAT "%i" + +#include "basic_type.cpp" + +#endif + +#include <cstdint> +#include <cstdio> + +class a_class +{ +public: + a_class (const T& a, const T& b) : + m_a (a), + m_b (b) + { + } + + ~a_class () + { + } + + const T& + get_a() + { + return m_a; + } + + void + set_a (const T& a) + { + m_a = a; + } + + const T& + get_b() + { + return m_b; + } + + void + set_b (const T& b) + { + m_b = b; + } + +protected: + T m_a; + T m_b; +}; + +typedef struct a_struct_tag { + T a; + T b; +} a_struct_t; + + +typedef union a_union_zero_tag { + T a; + double a_double; +} a_union_zero_t; + +typedef struct a_union_nonzero_tag { + double a_double; + a_union_zero_t u; +} a_union_nonzero_t; + + +void Puts(char const *msg) +{ + std::puts(msg); +} + +int +main (int argc, char const *argv[]) +{ + T a = T_VALUE_1; + T* a_ptr = &a; + T& a_ref = a; + T a_array_bounded[2] = { T_VALUE_1, T_VALUE_2 }; + T a_array_unbounded[] = { T_VALUE_1, T_VALUE_2 }; + + a_class a_class_instance (T_VALUE_1, T_VALUE_2); + a_class *a_class_ptr = &a_class_instance; + a_class &a_class_ref = a_class_instance; + + a_struct_t a_struct = { T_VALUE_1, T_VALUE_2 }; + a_struct_t *a_struct_ptr = &a_struct; + a_struct_t &a_struct_ref = a_struct; + + // Create a union with type T at offset zero + a_union_zero_t a_union_zero; + a_union_zero.a = T_VALUE_1; + a_union_zero_t *a_union_zero_ptr = &a_union_zero; + a_union_zero_t &a_union_zero_ref = a_union_zero; + + // Create a union with type T at a non-zero offset + a_union_nonzero_t a_union_nonzero; + a_union_nonzero.u.a = T_VALUE_1; + a_union_nonzero_t *a_union_nonzero_ptr = &a_union_nonzero; + a_union_nonzero_t &a_union_nonzero_ref = a_union_nonzero; + + a_struct_t a_struct_array_bounded[2] = {{ T_VALUE_1, T_VALUE_2 }, { T_VALUE_3, T_VALUE_4 }}; + a_struct_t a_struct_array_unbounded[] = {{ T_VALUE_1, T_VALUE_2 }, { T_VALUE_3, T_VALUE_4 }}; + a_union_zero_t a_union_zero_array_bounded[2]; + a_union_zero_array_bounded[0].a = T_VALUE_1; + a_union_zero_array_bounded[1].a = T_VALUE_2; + a_union_zero_t a_union_zero_array_unbounded[] = {{ T_VALUE_1 }, { T_VALUE_2 }}; + +#ifdef T_PRINTF_FORMAT + std::printf ("%s: a = '" T_PRINTF_FORMAT "'\n", T_CSTR, a); + std::printf ("%s*: %p => *a_ptr = '" T_PRINTF_FORMAT "'\n", T_CSTR, a_ptr, *a_ptr); + std::printf ("%s&: @%p => a_ref = '" T_PRINTF_FORMAT "'\n", T_CSTR, &a_ref, a_ref); + + std::printf ("%s[2]: a_array_bounded[0] = '" T_PRINTF_FORMAT "'\n", T_CSTR, a_array_bounded[0]); + std::printf ("%s[2]: a_array_bounded[1] = '" T_PRINTF_FORMAT "'\n", T_CSTR, a_array_bounded[1]); + + std::printf ("%s[]: a_array_unbounded[0] = '" T_PRINTF_FORMAT "'\n", T_CSTR, a_array_unbounded[0]); + std::printf ("%s[]: a_array_unbounded[1] = '" T_PRINTF_FORMAT "'\n", T_CSTR, a_array_unbounded[1]); + + std::printf ("(a_class) a_class_instance.m_a = '" T_PRINTF_FORMAT "'\n", a_class_instance.get_a()); + std::printf ("(a_class) a_class_instance.m_b = '" T_PRINTF_FORMAT "'\n", a_class_instance.get_b()); + std::printf ("(a_class*) a_class_ptr = %p, a_class_ptr->m_a = '" T_PRINTF_FORMAT "'\n", a_class_ptr, a_class_ptr->get_a()); + std::printf ("(a_class*) a_class_ptr = %p, a_class_ptr->m_b = '" T_PRINTF_FORMAT "'\n", a_class_ptr, a_class_ptr->get_b()); + std::printf ("(a_class&) a_class_ref = %p, a_class_ref.m_a = '" T_PRINTF_FORMAT "'\n", &a_class_ref, a_class_ref.get_a()); + std::printf ("(a_class&) a_class_ref = %p, a_class_ref.m_b = '" T_PRINTF_FORMAT "'\n", &a_class_ref, a_class_ref.get_b()); + + std::printf ("(a_struct_t) a_struct.a = '" T_PRINTF_FORMAT "'\n", a_struct.a); + std::printf ("(a_struct_t) a_struct.b = '" T_PRINTF_FORMAT "'\n", a_struct.b); + std::printf ("(a_struct_t*) a_struct_ptr = %p, a_struct_ptr->a = '" T_PRINTF_FORMAT "'\n", a_struct_ptr, a_struct_ptr->a); + std::printf ("(a_struct_t*) a_struct_ptr = %p, a_struct_ptr->b = '" T_PRINTF_FORMAT "'\n", a_struct_ptr, a_struct_ptr->b); + std::printf ("(a_struct_t&) a_struct_ref = %p, a_struct_ref.a = '" T_PRINTF_FORMAT "'\n", &a_struct_ref, a_struct_ref.a); + std::printf ("(a_struct_t&) a_struct_ref = %p, a_struct_ref.b = '" T_PRINTF_FORMAT "'\n", &a_struct_ref, a_struct_ref.b); + + std::printf ("(a_union_zero_t) a_union_zero.a = '" T_PRINTF_FORMAT "'\n", a_union_zero.a); + std::printf ("(a_union_zero_t*) a_union_zero_ptr = %p, a_union_zero_ptr->a = '" T_PRINTF_FORMAT "'\n", a_union_zero_ptr, a_union_zero_ptr->a); + std::printf ("(a_union_zero_t&) a_union_zero_ref = %p, a_union_zero_ref.a = '" T_PRINTF_FORMAT "'\n", &a_union_zero_ref, a_union_zero_ref.a); + + std::printf ("(a_union_nonzero_t) a_union_nonzero.u.a = '" T_PRINTF_FORMAT "'\n", a_union_nonzero.u.a); + std::printf ("(a_union_nonzero_t*) a_union_nonzero_ptr = %p, a_union_nonzero_ptr->u.a = '" T_PRINTF_FORMAT "'\n", a_union_nonzero_ptr, a_union_nonzero_ptr->u.a); + std::printf ("(a_union_nonzero_t&) a_union_nonzero_ref = %p, a_union_nonzero_ref.u.a = '" T_PRINTF_FORMAT "'\n", &a_union_nonzero_ref, a_union_nonzero_ref.u.a); + + std::printf ("(a_struct_t[2]) a_struct_array_bounded[0].a = '" T_PRINTF_FORMAT "'\n", a_struct_array_bounded[0].a); + std::printf ("(a_struct_t[2]) a_struct_array_bounded[0].b = '" T_PRINTF_FORMAT "'\n", a_struct_array_bounded[0].b); + std::printf ("(a_struct_t[2]) a_struct_array_bounded[1].a = '" T_PRINTF_FORMAT "'\n", a_struct_array_bounded[1].a); + std::printf ("(a_struct_t[2]) a_struct_array_bounded[1].b = '" T_PRINTF_FORMAT "'\n", a_struct_array_bounded[1].b); + + std::printf ("(a_struct_t[]) a_struct_array_unbounded[0].a = '" T_PRINTF_FORMAT "'\n", a_struct_array_unbounded[0].a); + std::printf ("(a_struct_t[]) a_struct_array_unbounded[0].b = '" T_PRINTF_FORMAT "'\n", a_struct_array_unbounded[0].b); + std::printf ("(a_struct_t[]) a_struct_array_unbounded[1].a = '" T_PRINTF_FORMAT "'\n", a_struct_array_unbounded[1].a); + std::printf ("(a_struct_t[]) a_struct_array_unbounded[1].b = '" T_PRINTF_FORMAT "'\n", a_struct_array_unbounded[1].b); + + std::printf ("(a_union_zero_t[2]) a_union_zero_array_bounded[0].a = '" T_PRINTF_FORMAT "'\n", a_union_zero_array_bounded[0].a); + std::printf ("(a_union_zero_t[2]) a_union_zero_array_bounded[1].a = '" T_PRINTF_FORMAT "'\n", a_union_zero_array_bounded[1].a); + + std::printf ("(a_union_zero_t[]) a_union_zero_array_unbounded[0].a = '" T_PRINTF_FORMAT "'\n", a_union_zero_array_unbounded[0].a); + std::printf ("(a_union_zero_t[]) a_union_zero_array_unbounded[1].a = '" T_PRINTF_FORMAT "'\n", a_union_zero_array_unbounded[1].a); + +#endif + Puts("About to exit, break here to check values..."); // Set break point at this line. + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/inlined_breakpoints/int.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/inlined_breakpoints/int.cpp new file mode 100644 index 00000000000..922398b1c6e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/inlined_breakpoints/int.cpp @@ -0,0 +1,9 @@ +#define T int +#define T_CSTR "int" +#define T_VALUE_1 11001110 +#define T_VALUE_2 22002220 +#define T_VALUE_3 33003330 +#define T_VALUE_4 44004440 +#define T_PRINTF_FORMAT "%i" + +#include "basic_type.cpp" diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/Makefile new file mode 100644 index 00000000000..4b3098cf7da --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/Makefile @@ -0,0 +1,5 @@ +DYLIB_NAME := foo +DYLIB_CXX_SOURCES := foo.cpp +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/TestMoveNearest.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/TestMoveNearest.py new file mode 100644 index 00000000000..b8281e9c85b --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/TestMoveNearest.py @@ -0,0 +1,69 @@ +from __future__ import print_function + + +import unittest2 +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class TestMoveNearest(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.line1 = line_number('foo.h', '// !BR1') + self.line2 = line_number('foo.h', '// !BR2') + self.line_between = line_number('main.cpp', "// BR_Between") + print("BR_Between found at", self.line_between) + self.line_main = line_number('main.cpp', '// !BR_main') + + def test(self): + """Test target.move-to-nearest logic""" + + self.build() + target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) + self.assertTrue(target, VALID_TARGET) + + lldbutil.run_break_set_by_symbol(self, 'main', sym_exact=True) + environment = self.registerSharedLibrariesWithTarget(target, ["foo"]) + process = target.LaunchSimple(None, environment, self.get_process_working_directory()) + self.assertEquals(process.GetState(), lldb.eStateStopped) + + # Regardless of the -m value the breakpoint should have exactly one + # location on the foo functions + self.runCmd("settings set target.move-to-nearest-code true") + lldbutil.run_break_set_by_file_and_line(self, 'foo.h', self.line1, + loc_exact=True, extra_options="-m 1") + lldbutil.run_break_set_by_file_and_line(self, 'foo.h', self.line2, + loc_exact=True, extra_options="-m 1") + + self.runCmd("settings set target.move-to-nearest-code false") + lldbutil.run_break_set_by_file_and_line(self, 'foo.h', self.line1, + loc_exact=True, extra_options="-m 0") + lldbutil.run_break_set_by_file_and_line(self, 'foo.h', self.line2, + loc_exact=True, extra_options="-m 0") + + + # Make sure we set a breakpoint in main with -m 1 for various lines in + # the function declaration + # "int" + lldbutil.run_break_set_by_file_and_line(self, 'main.cpp', + self.line_main-1, extra_options="-m 1") + # "main()" + lldbutil.run_break_set_by_file_and_line(self, 'main.cpp', + self.line_main, extra_options="-m 1") + # "{" + lldbutil.run_break_set_by_file_and_line(self, 'main.cpp', + self.line_main+1, extra_options="-m 1") + # "return .." + lldbutil.run_break_set_by_file_and_line(self, 'main.cpp', + self.line_main+2, extra_options="-m 1") + + # Make sure we don't put move the breakpoint if it is set between two functions: + lldbutil.run_break_set_by_file_and_line(self, 'main.cpp', + self.line_between, extra_options="-m 1", num_expected_locations=0) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/foo.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/foo.cpp new file mode 100644 index 00000000000..8dad0a23f36 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/foo.cpp @@ -0,0 +1,3 @@ +#include "foo.h" + +int call_foo1() { return foo1(); } diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/foo.h b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/foo.h new file mode 100644 index 00000000000..9f0e56dd22e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/foo.h @@ -0,0 +1,5 @@ +inline int foo1() { return 1; } // !BR1 + +inline int foo2() { return 2; } // !BR2 + +LLDB_TEST_API extern int call_foo1(); diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/main.cpp new file mode 100644 index 00000000000..76a22a5420f --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/main.cpp @@ -0,0 +1,9 @@ +#include "foo.h" + +int call_foo2() { return foo2(); } +// BR_Between +int +main() // !BR_main +{ + return call_foo1() + call_foo2(); +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/objc/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/objc/Makefile new file mode 100644 index 00000000000..37dd8f40a9d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/objc/Makefile @@ -0,0 +1,6 @@ +OBJC_SOURCES := main.m + + + +LD_EXTRAS := -framework Foundation +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/objc/TestObjCBreakpoints.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/objc/TestObjCBreakpoints.py new file mode 100644 index 00000000000..2091987fd2f --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/objc/TestObjCBreakpoints.py @@ -0,0 +1,129 @@ +""" +Test that objective-c constant strings are generated correctly by the expression +parser. +""" + + + +import shutil +import subprocess +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +@skipUnlessDarwin +class TestObjCBreakpoints(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_break(self): + """Test setting Objective-C specific breakpoints (DWARF in .o files).""" + self.build() + self.setTearDownCleanup() + self.check_objc_breakpoints(False) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.main_source = "main.m" + self.line = line_number(self.main_source, '// Set breakpoint here') + + def check_category_breakpoints(self): + name_bp = self.target.BreakpointCreateByName("myCategoryFunction") + selector_bp = self.target.BreakpointCreateByName( + "myCategoryFunction", + lldb.eFunctionNameTypeSelector, + lldb.SBFileSpecList(), + lldb.SBFileSpecList()) + self.assertTrue( + name_bp.GetNumLocations() == selector_bp.GetNumLocations(), + 'Make sure setting a breakpoint by name "myCategoryFunction" sets a breakpoint even though it is in a category') + for bp_loc in selector_bp: + function_name = bp_loc.GetAddress().GetSymbol().GetName() + self.assertTrue( + " myCategoryFunction]" in function_name, + 'Make sure all function names have " myCategoryFunction]" in their names') + + category_bp = self.target.BreakpointCreateByName( + "-[MyClass(MyCategory) myCategoryFunction]") + stripped_bp = self.target.BreakpointCreateByName( + "-[MyClass myCategoryFunction]") + stripped2_bp = self.target.BreakpointCreateByName( + "[MyClass myCategoryFunction]") + self.assertTrue( + category_bp.GetNumLocations() == 1, + "Make sure we can set a breakpoint using a full objective C function name with the category included (-[MyClass(MyCategory) myCategoryFunction])") + self.assertTrue( + stripped_bp.GetNumLocations() == 1, + "Make sure we can set a breakpoint using a full objective C function name without the category included (-[MyClass myCategoryFunction])") + self.assertTrue( + stripped2_bp.GetNumLocations() == 1, + "Make sure we can set a breakpoint using a full objective C function name without the category included ([MyClass myCategoryFunction])") + + def check_objc_breakpoints(self, have_dsym): + """Test constant string generation amd comparison by the expression parser.""" + + # Set debugger into synchronous mode + self.dbg.SetAsync(False) + + # Create a target by the debugger. + exe = self.getBuildArtifact("a.out") + self.target = self.dbg.CreateTarget(exe) + self.assertTrue(self.target, VALID_TARGET) + + #---------------------------------------------------------------------- + # Set breakpoints on all selectors whose name is "count". This should + # catch breakpoints that are both C functions _and_ anything whose + # selector is "count" because just looking at "count" we can't tell + # definitively if the name is a selector or a C function + #---------------------------------------------------------------------- + name_bp = self.target.BreakpointCreateByName("count") + selector_bp = self.target.BreakpointCreateByName( + "count", + lldb.eFunctionNameTypeSelector, + lldb.SBFileSpecList(), + lldb.SBFileSpecList()) + self.assertTrue( + name_bp.GetNumLocations() >= selector_bp.GetNumLocations(), + 'Make sure we get at least the same amount of breakpoints if not more when setting by name "count"') + self.assertTrue( + selector_bp.GetNumLocations() > 50, + 'Make sure we find a lot of "count" selectors') # There are 93 on the latest MacOSX + for bp_loc in selector_bp: + function_name = bp_loc.GetAddress().GetSymbol().GetName() + self.assertTrue( + " count]" in function_name, + 'Make sure all function names have " count]" in their names') + + #---------------------------------------------------------------------- + # Set breakpoints on all selectors whose name is "isEqual:". This should + # catch breakpoints that are only ObjC selectors because no C function + # can end with a : + #---------------------------------------------------------------------- + name_bp = self.target.BreakpointCreateByName("isEqual:") + selector_bp = self.target.BreakpointCreateByName( + "isEqual:", + lldb.eFunctionNameTypeSelector, + lldb.SBFileSpecList(), + lldb.SBFileSpecList()) + self.assertTrue( + name_bp.GetNumLocations() == selector_bp.GetNumLocations(), + 'Make sure setting a breakpoint by name "isEqual:" only sets selector breakpoints') + for bp_loc in selector_bp: + function_name = bp_loc.GetAddress().GetSymbol().GetName() + self.assertTrue( + " isEqual:]" in function_name, + 'Make sure all function names have " isEqual:]" in their names') + + self.check_category_breakpoints() + + if have_dsym: + shutil.rmtree(exe + ".dSYM") + self.assertTrue(subprocess.call( + ['/usr/bin/strip', '-Sx', exe]) == 0, 'stripping dylib succeeded') + + # Check breakpoints again, this time using the symbol table only + self.check_category_breakpoints() diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/objc/main.m b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/objc/main.m new file mode 100644 index 00000000000..53567491219 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/objc/main.m @@ -0,0 +1,98 @@ +#import <Foundation/Foundation.h> +#include <unistd.h> + +@interface MyClass : NSObject +@end + +@implementation MyClass : NSObject +@end + +@implementation MyClass (MyCategory) + + +- (void) myCategoryFunction { + NSLog (@"myCategoryFunction"); +} + +@end + + + +int +Test_Selector () +{ + SEL sel = @selector(length); + printf("sel = %p\n", sel); + // Expressions to test here for selector: + // expression (char *)sel_getName(sel) + // The expression above should return "sel" as it should be just + // a uniqued C string pointer. We were seeing the result pointer being + // truncated with recent LLDBs. + return 0; // Break here for selector: tests +} + +int +Test_NSString (const char *program) +{ + NSString *str = [NSString stringWithFormat:@"Hello from '%s'", program]; + NSLog(@"NSString instance: %@", str); + printf("str = '%s'\n", [str cStringUsingEncoding: [NSString defaultCStringEncoding]]); + printf("[str length] = %zu\n", (size_t)[str length]); + printf("[str description] = %s\n", [[str description] UTF8String]); + id str_id = str; + // Expressions to test here for NSString: + // expression (char *)sel_getName(sel) + // expression [str length] + // expression [str_id length] + // expression [str description] + // expression [str_id description] + // expression str.length + // expression str.description + // expression str = @"new" + // expression str = [NSString stringWithFormat: @"%cew", 'N'] + return 0; // Break here for NSString tests +} + +NSString *my_global_str = NULL; + +int +Test_NSArray () +{ + NSMutableArray *nil_mutable_array = nil; + NSArray *array1 = [NSArray arrayWithObjects: @"array1 object1", @"array1 object2", @"array1 object3", nil]; + NSArray *array2 = [NSArray arrayWithObjects: array1, @"array2 object2", @"array2 object3", nil]; + // Expressions to test here for NSArray: + // expression [nil_mutable_array count] + // expression [array1 count] + // expression array1.count + // expression [array2 count] + // expression array2.count + id obj; + // After each object at index call, use expression and validate object + obj = [array1 objectAtIndex: 0]; // Break here for NSArray tests + obj = [array1 objectAtIndex: 1]; + obj = [array1 objectAtIndex: 2]; + + obj = [array2 objectAtIndex: 0]; + obj = [array2 objectAtIndex: 1]; + obj = [array2 objectAtIndex: 2]; + NSUInteger count = [nil_mutable_array count]; + return 0; +} + + +int main (int argc, char const *argv[]) +{ + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + Test_Selector(); // Set breakpoint here + Test_NSArray (); + Test_NSString (argv[0]); + MyClass *my_class = [[MyClass alloc] init]; + [my_class myCategoryFunction]; + printf("sizeof(id) = %zu\n", sizeof(id)); + printf("sizeof(Class) = %zu\n", sizeof(Class)); + printf("sizeof(SEL) = %zu\n", sizeof(SEL)); + + [pool release]; + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/Makefile new file mode 100644 index 00000000000..9645fd9cc8d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/Makefile @@ -0,0 +1,7 @@ +C_SOURCES := main.c + +ifneq (,$(findstring icc,$(CC))) + CFLAGS_EXTRAS := -debug inline-debug-info +endif + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/TestRequireHWBreakpoints.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/TestRequireHWBreakpoints.py new file mode 100644 index 00000000000..0bf82c4a310 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/TestRequireHWBreakpoints.py @@ -0,0 +1,110 @@ +""" +Test require hardware breakpoints. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class BreakpointLocationsTestCase(TestBase): + NO_DEBUG_INFO_TESTCASE = True + mydir = TestBase.compute_mydir(__file__) + + def test_breakpoint(self): + """Test regular breakpoints when hardware breakpoints are required.""" + self.build() + exe = self.getBuildArtifact("a.out") + target = self.dbg.CreateTarget(exe) + + self.runCmd("settings set target.require-hardware-breakpoint true") + + breakpoint = target.BreakpointCreateByLocation("main.c", 1) + self.assertTrue(breakpoint.IsHardware()) + + @skipIfWindows + @expectedFailureAll(archs="aarch64", oslist="linux", + bugnumber="https://bugs.llvm.org/show_bug.cgi?id=44055") + def test_step_range(self): + """Test stepping when hardware breakpoints are required.""" + self.build() + + _, _, thread, _ = lldbutil.run_to_line_breakpoint( + self, lldb.SBFileSpec("main.c"), 1) + + self.runCmd("settings set target.require-hardware-breakpoint true") + + # Ensure we fail in the interpreter. + self.expect("thread step-in") + self.expect("thread step-in", error=True) + + # Ensure we fail when stepping through the API. + error = lldb.SBError() + thread.StepInto('', 4, error) + self.assertTrue(error.Fail()) + self.assertTrue("Could not create hardware breakpoint for thread plan" + in error.GetCString()) + + @skipIfWindows + @expectedFailureAll(archs="aarch64", oslist="linux", + bugnumber="https://bugs.llvm.org/show_bug.cgi?id=44055") + def test_step_out(self): + """Test stepping out when hardware breakpoints are required.""" + self.build() + + _, _, thread, _ = lldbutil.run_to_line_breakpoint( + self, lldb.SBFileSpec("main.c"), 1) + + self.runCmd("settings set target.require-hardware-breakpoint true") + + # Ensure this fails in the command interpreter. + self.expect("thread step-out", error=True) + + # Ensure we fail when stepping through the API. + error = lldb.SBError() + thread.StepOut(error) + self.assertTrue(error.Fail()) + self.assertTrue("Could not create hardware breakpoint for thread plan" + in error.GetCString()) + + @skipIfWindows + @expectedFailureAll(archs="aarch64", oslist="linux", + bugnumber="https://bugs.llvm.org/show_bug.cgi?id=44055") + def test_step_over(self): + """Test stepping over when hardware breakpoints are required.""" + self.build() + + _, _, thread, _ = lldbutil.run_to_line_breakpoint( + self, lldb.SBFileSpec("main.c"), 7) + + self.runCmd("settings set target.require-hardware-breakpoint true") + + # Step over doesn't fail immediately but fails later on. + self.expect( + "thread step-over", + error=True, + substrs=[ + 'error: Could not create hardware breakpoint for thread plan.' + ]) + + @skipIfWindows + @expectedFailureAll(archs="aarch64", oslist="linux", + bugnumber="https://bugs.llvm.org/show_bug.cgi?id=44055") + def test_step_until(self): + """Test stepping until when hardware breakpoints are required.""" + self.build() + + _, _, thread, _ = lldbutil.run_to_line_breakpoint( + self, lldb.SBFileSpec("main.c"), 7) + + self.runCmd("settings set target.require-hardware-breakpoint true") + + self.expect("thread until 5", error=True) + + # Ensure we fail when stepping through the API. + error = thread.StepOverUntil(lldb.SBFrame(), lldb.SBFileSpec(), 5) + self.assertTrue(error.Fail()) + self.assertTrue("Could not create hardware breakpoint for thread plan" + in error.GetCString()) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/main.c new file mode 100644 index 00000000000..7d49a57d4c7 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/main.c @@ -0,0 +1,9 @@ +int break_on_me() { + int i = 10; + i++; + return i; +} + +int main() { + return break_on_me(); +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/Makefile new file mode 100644 index 00000000000..695335e068c --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/Makefile @@ -0,0 +1,4 @@ +C_SOURCES := main.c +CFLAGS_EXTRAS := -std=c99 + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py new file mode 100644 index 00000000000..895f4fa1e37 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py @@ -0,0 +1,224 @@ +""" +Test setting breakpoints using a scripted resolver +""" + +import os +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * + + +class TestScriptedResolver(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528") + def test_scripted_resolver(self): + """Use a scripted resolver to set a by symbol name breakpoint""" + self.build() + self.do_test() + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528") + def test_search_depths(self): + """ Make sure we are called at the right depths depending on what we return + from __get_depth__""" + self.build() + self.do_test_depths() + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528") + def test_command_line(self): + """ Test setting a resolver breakpoint from the command line """ + self.build() + self.do_test_cli() + + def test_bad_command_lines(self): + """Make sure we get appropriate errors when we give invalid key/value + options""" + self.build() + self.do_test_bad_options() + + def make_target_and_import(self): + target = lldbutil.run_to_breakpoint_make_target(self) + interp = self.dbg.GetCommandInterpreter() + error = lldb.SBError() + + script_name = os.path.join(self.getSourceDir(), "resolver.py") + source_name = os.path.join(self.getSourceDir(), "main.c") + + command = "command script import " + script_name + result = lldb.SBCommandReturnObject() + interp.HandleCommand(command, result) + self.assertTrue(result.Succeeded(), "com scr imp failed: %s"%(result.GetError())) + return target + + def make_extra_args(self): + json_string = '{"symbol":"break_on_me", "test1": "value1"}' + json_stream = lldb.SBStream() + json_stream.Print(json_string) + extra_args = lldb.SBStructuredData() + error = extra_args.SetFromJSON(json_stream) + self.assertTrue(error.Success(), "Error making SBStructuredData: %s"%(error.GetCString())) + return extra_args + + def do_test(self): + """This reads in a python file and sets a breakpoint using it.""" + + target = self.make_target_and_import() + extra_args = self.make_extra_args() + + file_list = lldb.SBFileSpecList() + module_list = lldb.SBFileSpecList() + + # Make breakpoints with this resolver using different filters, first ones that will take: + right = [] + # one with no file or module spec - this one should fire: + right.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) + + # one with the right source file and no module - should also fire: + file_list.Append(lldb.SBFileSpec("main.c")) + right.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) + # Make sure the help text shows up in the "break list" output: + self.expect("break list", substrs=["I am a python breakpoint resolver"], msg="Help is listed in break list") + + # one with the right source file and right module - should also fire: + module_list.Append(lldb.SBFileSpec("a.out")) + right.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) + + # And one with no source file but the right module: + file_list.Clear() + right.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) + + # Make sure these all got locations: + for i in range (0, len(right)): + self.assertTrue(right[i].GetNumLocations() >= 1, "Breakpoint %d has no locations."%(i)) + + # Now some ones that won't take: + + module_list.Clear() + file_list.Clear() + wrong = [] + + # one with the wrong module - should not fire: + module_list.Append(lldb.SBFileSpec("noSuchModule")) + wrong.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) + + # one with the wrong file - also should not fire: + file_list.Clear() + module_list.Clear() + file_list.Append(lldb.SBFileSpec("noFileOfThisName.xxx")) + wrong.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) + + # Now make sure the CU level iteration obeys the file filters: + file_list.Clear() + module_list.Clear() + file_list.Append(lldb.SBFileSpec("no_such_file.xxx")) + wrong.append(target.BreakpointCreateFromScript("resolver.ResolverCUDepth", extra_args, module_list, file_list)) + + # And the Module filters: + file_list.Clear() + module_list.Clear() + module_list.Append(lldb.SBFileSpec("NoSuchModule.dylib")) + wrong.append(target.BreakpointCreateFromScript("resolver.ResolverCUDepth", extra_args, module_list, file_list)) + + # Now make sure the Function level iteration obeys the file filters: + file_list.Clear() + module_list.Clear() + file_list.Append(lldb.SBFileSpec("no_such_file.xxx")) + wrong.append(target.BreakpointCreateFromScript("resolver.ResolverFuncDepth", extra_args, module_list, file_list)) + + # And the Module filters: + file_list.Clear() + module_list.Clear() + module_list.Append(lldb.SBFileSpec("NoSuchModule.dylib")) + wrong.append(target.BreakpointCreateFromScript("resolver.ResolverFuncDepth", extra_args, module_list, file_list)) + + # Make sure these didn't get locations: + for i in range(0, len(wrong)): + self.assertEqual(wrong[i].GetNumLocations(), 0, "Breakpoint %d has locations."%(i)) + + # Now run to main and ensure we hit the breakpoints we should have: + + lldbutil.run_to_breakpoint_do_run(self, target, right[0]) + + # Test the hit counts: + for i in range(0, len(right)): + self.assertEqual(right[i].GetHitCount(), 1, "Breakpoint %d has the wrong hit count"%(i)) + + for i in range(0, len(wrong)): + self.assertEqual(wrong[i].GetHitCount(), 0, "Breakpoint %d has the wrong hit count"%(i)) + + def do_test_depths(self): + """This test uses a class variable in resolver.Resolver which gets set to 1 if we saw + compile unit and 2 if we only saw modules. If the search depth is module, you get passed just + the modules with no comp_unit. If the depth is comp_unit you get comp_units. So we can use + this to test that our callback gets called at the right depth.""" + + target = self.make_target_and_import() + extra_args = self.make_extra_args() + + file_list = lldb.SBFileSpecList() + module_list = lldb.SBFileSpecList() + module_list.Append(lldb.SBFileSpec("a.out")) + + # Make a breakpoint that has no __get_depth__, check that that is converted to eSearchDepthModule: + bkpt = target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list) + self.assertTrue(bkpt.GetNumLocations() > 0, "Resolver got no locations.") + self.expect("script print(resolver.Resolver.got_files)", substrs=["2"], msg="Was only passed modules") + + # Make a breakpoint that asks for modules, check that we didn't get any files: + bkpt = target.BreakpointCreateFromScript("resolver.ResolverModuleDepth", extra_args, module_list, file_list) + self.assertTrue(bkpt.GetNumLocations() > 0, "ResolverModuleDepth got no locations.") + self.expect("script print(resolver.Resolver.got_files)", substrs=["2"], msg="Was only passed modules") + + # Make a breakpoint that asks for compile units, check that we didn't get any files: + bkpt = target.BreakpointCreateFromScript("resolver.ResolverCUDepth", extra_args, module_list, file_list) + self.assertTrue(bkpt.GetNumLocations() > 0, "ResolverCUDepth got no locations.") + self.expect("script print(resolver.Resolver.got_files)", substrs=["1"], msg="Was passed compile units") + + # Make a breakpoint that returns a bad value - we should convert that to "modules" so check that: + bkpt = target.BreakpointCreateFromScript("resolver.ResolverBadDepth", extra_args, module_list, file_list) + self.assertTrue(bkpt.GetNumLocations() > 0, "ResolverBadDepth got no locations.") + self.expect("script print(resolver.Resolver.got_files)", substrs=["2"], msg="Was only passed modules") + + # Make a breakpoint that searches at function depth: + bkpt = target.BreakpointCreateFromScript("resolver.ResolverFuncDepth", extra_args, module_list, file_list) + self.assertTrue(bkpt.GetNumLocations() > 0, "ResolverFuncDepth got no locations.") + self.expect("script print(resolver.Resolver.got_files)", substrs=["3"], msg="Was only passed modules") + self.expect("script print(resolver.Resolver.func_list)", substrs=["break_on_me", "main", "test_func"], msg="Saw all the functions") + + def do_test_cli(self): + target = self.make_target_and_import() + + lldbutil.run_break_set_by_script(self, "resolver.Resolver", extra_options="-k symbol -v break_on_me") + + # Make sure setting a resolver breakpoint doesn't pollute further breakpoint setting + # by checking the description of a regular file & line breakpoint to make sure it + # doesn't mention the Python Resolver function: + bkpt_no = lldbutil.run_break_set_by_file_and_line(self, "main.c", 12) + bkpt = target.FindBreakpointByID(bkpt_no) + strm = lldb.SBStream() + bkpt.GetDescription(strm, False) + used_resolver = "I am a python breakpoint resolver" in strm.GetData() + self.assertFalse(used_resolver, "Found the resolver description in the file & line breakpoint description.") + + # Also make sure the breakpoint was where we expected: + bp_loc = bkpt.GetLocationAtIndex(0) + bp_sc = bp_loc.GetAddress().GetSymbolContext(lldb.eSymbolContextEverything) + bp_se = bp_sc.GetLineEntry() + self.assertEqual(bp_se.GetLine(), 12, "Got the right line number") + self.assertEqual(bp_se.GetFileSpec().GetFilename(), "main.c", "Got the right filename") + + def do_test_bad_options(self): + target = self.make_target_and_import() + + self.expect("break set -P resolver.Resolver -k a_key", error = True, msg="Missing value at end", + substrs=['Key: "a_key" missing value']) + self.expect("break set -P resolver.Resolver -v a_value", error = True, msg="Missing key at end", + substrs=['Value: "a_value" missing matching key']) + self.expect("break set -P resolver.Resolver -v a_value -k a_key -v another_value", error = True, msg="Missing key among args", + substrs=['Value: "a_value" missing matching key']) + self.expect("break set -P resolver.Resolver -k a_key -k a_key -v another_value", error = True, msg="Missing value among args", + substrs=['Key: "a_key" missing value']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/main.c new file mode 100644 index 00000000000..b91ccfc1b43 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/main.c @@ -0,0 +1,21 @@ +#include <stdio.h> + +int +test_func() +{ + return printf("I am a test function."); +} + +void +break_on_me() +{ + printf("I was called.\n"); +} + +int +main() +{ + break_on_me(); + test_func(); + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/resolver.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/resolver.py new file mode 100644 index 00000000000..f3af7c09f97 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/resolver.py @@ -0,0 +1,57 @@ +import lldb + +class Resolver: + got_files = 0 + func_list = [] + + def __init__(self, bkpt, extra_args, dict): + self.bkpt = bkpt + self.extra_args = extra_args + + Resolver.func_list = [] + Resolver.got_files = 0 + + def __callback__(self, sym_ctx): + sym_name = "not_a_real_function_name" + sym_item = self.extra_args.GetValueForKey("symbol") + if sym_item.IsValid(): + sym_name = sym_item.GetStringValue(1000) + else: + print("Didn't have a value for key 'symbol'") + + if sym_ctx.compile_unit.IsValid(): + Resolver.got_files = 1 + else: + Resolver.got_files = 2 + + if sym_ctx.function.IsValid(): + Resolver.got_files = 3 + func_name = sym_ctx.function.GetName() + Resolver.func_list.append(func_name) + if sym_name == func_name: + self.bkpt.AddLocation(sym_ctx.function.GetStartAddress()) + return + + if sym_ctx.module.IsValid(): + sym = sym_ctx.module.FindSymbol(sym_name, lldb.eSymbolTypeCode) + if sym.IsValid(): + self.bkpt.AddLocation(sym.GetStartAddress()) + + def get_short_help(self): + return "I am a python breakpoint resolver" + +class ResolverModuleDepth(Resolver): + def __get_depth__ (self): + return lldb.eSearchDepthModule + +class ResolverCUDepth(Resolver): + def __get_depth__ (self): + return lldb.eSearchDepthCompUnit + +class ResolverFuncDepth(Resolver): + def __get_depth__ (self): + return lldb.eSearchDepthFunction + +class ResolverBadDepth(Resolver): + def __get_depth__ (self): + return lldb.kLastSearchDepthKind + 1 diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/TestBreakpointSerialization.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/TestBreakpointSerialization.py new file mode 100644 index 00000000000..4c6f32b0896 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/TestBreakpointSerialization.py @@ -0,0 +1,375 @@ +""" +Test breakpoint serialization. +""" + +import os +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class BreakpointSerialization(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + @add_test_categories(['pyapi']) + def test_resolvers(self): + """Use Python APIs to test that we serialize resolvers.""" + self.build() + self.setup_targets_and_cleanup() + self.do_check_resolvers() + + def test_filters(self): + """Use Python APIs to test that we serialize search filters correctly.""" + self.build() + self.setup_targets_and_cleanup() + self.do_check_filters() + + def test_options(self): + """Use Python APIs to test that we serialize breakpoint options correctly.""" + self.build() + self.setup_targets_and_cleanup() + self.do_check_options() + + def test_appending(self): + """Use Python APIs to test that we serialize breakpoint options correctly.""" + self.build() + self.setup_targets_and_cleanup() + self.do_check_appending() + + def test_name_filters(self): + """Use python APIs to test that reading in by name works correctly.""" + self.build() + self.setup_targets_and_cleanup() + self.do_check_names() + + def test_scripted_extra_args(self): + self.build() + self.setup_targets_and_cleanup() + self.do_check_extra_args() + + def setup_targets_and_cleanup(self): + def cleanup (): + self.RemoveTempFile(self.bkpts_file_path) + + if self.orig_target.IsValid(): + self.dbg.DeleteTarget(self.orig_target) + self.dbg.DeleteTarget(self.copy_target) + + self.addTearDownHook(cleanup) + self.RemoveTempFile(self.bkpts_file_path) + + exe = self.getBuildArtifact("a.out") + + # Create the targets we are making breakpoints in and copying them to: + self.orig_target = self.dbg.CreateTarget(exe) + self.assertTrue(self.orig_target, VALID_TARGET) + + self.copy_target = self.dbg.CreateTarget(exe) + self.assertTrue(self.copy_target, VALID_TARGET) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + self.bkpts_file_path = self.getBuildArtifact("breakpoints.json") + self.bkpts_file_spec = lldb.SBFileSpec(self.bkpts_file_path) + + def check_equivalence(self, source_bps, do_write = True): + + error = lldb.SBError() + + if (do_write): + error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, source_bps) + self.assertTrue(error.Success(), "Failed writing breakpoints to file: %s."%(error.GetCString())) + + copy_bps = lldb.SBBreakpointList(self.copy_target) + error = self.copy_target.BreakpointsCreateFromFile(self.bkpts_file_spec, copy_bps) + self.assertTrue(error.Success(), "Failed reading breakpoints from file: %s"%(error.GetCString())) + + num_source_bps = source_bps.GetSize() + num_copy_bps = copy_bps.GetSize() + self.assertTrue(num_source_bps == num_copy_bps, "Didn't get same number of input and output breakpoints - orig: %d copy: %d"%(num_source_bps, num_copy_bps)) + + for i in range(0, num_source_bps): + source_bp = source_bps.GetBreakpointAtIndex(i) + source_desc = lldb.SBStream() + source_bp.GetDescription(source_desc, False) + source_text = source_desc.GetData() + + # I am assuming here that the breakpoints will get written out in breakpoint ID order, and + # read back in ditto. That is true right now, and I can't see any reason to do it differently + # but if we do we can go to writing the breakpoints one by one, or sniffing the descriptions to + # see which one is which. + copy_id = source_bp.GetID() + copy_bp = copy_bps.FindBreakpointByID(copy_id) + self.assertTrue(copy_bp.IsValid(), "Could not find copy breakpoint %d."%(copy_id)) + + copy_desc = lldb.SBStream() + copy_bp.GetDescription(copy_desc, False) + copy_text = copy_desc.GetData() + + # These two should be identical. + # print ("Source text for %d is %s."%(i, source_text)) + self.assertTrue (source_text == copy_text, "Source and dest breakpoints are not identical: \nsource: %s\ndest: %s"%(source_text, copy_text)) + + def do_check_resolvers(self): + """Use Python APIs to check serialization of breakpoint resolvers""" + + empty_module_list = lldb.SBFileSpecList() + empty_cu_list = lldb.SBFileSpecList() + blubby_file_spec = lldb.SBFileSpec(os.path.join(self.getSourceDir(), "blubby.c")) + + # It isn't actually important for these purposes that these breakpoint + # actually have locations. + source_bps = lldb.SBBreakpointList(self.orig_target) + source_bps.Append(self.orig_target.BreakpointCreateByLocation("blubby.c", 666)) + # Make sure we do one breakpoint right: + self.check_equivalence(source_bps) + source_bps.Clear() + + source_bps.Append(self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list)) + source_bps.Append(self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeFull, empty_module_list,empty_cu_list)) + source_bps.Append(self.orig_target.BreakpointCreateBySourceRegex("dont really care", blubby_file_spec)) + + # And some number greater than one: + self.check_equivalence(source_bps) + + def do_check_filters(self): + """Use Python APIs to check serialization of breakpoint filters.""" + module_list = lldb.SBFileSpecList() + module_list.Append(lldb.SBFileSpec("SomeBinary")) + module_list.Append(lldb.SBFileSpec("SomeOtherBinary")) + + cu_list = lldb.SBFileSpecList() + cu_list.Append(lldb.SBFileSpec("SomeCU.c")) + cu_list.Append(lldb.SBFileSpec("AnotherCU.c")) + cu_list.Append(lldb.SBFileSpec("ThirdCU.c")) + + blubby_file_spec = lldb.SBFileSpec(os.path.join(self.getSourceDir(), "blubby.c")) + + # It isn't actually important for these purposes that these breakpoint + # actually have locations. + source_bps = lldb.SBBreakpointList(self.orig_target) + bkpt = self.orig_target.BreakpointCreateByLocation(blubby_file_spec, 666, 0, module_list) + source_bps.Append(bkpt) + + # Make sure we do one right: + self.check_equivalence(source_bps) + source_bps.Clear() + + bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeAuto, module_list, cu_list) + source_bps.Append(bkpt) + bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeFull, module_list, cu_list) + source_bps.Append(bkpt) + bkpt = self.orig_target.BreakpointCreateBySourceRegex("dont really care", blubby_file_spec) + source_bps.Append(bkpt) + + # And some number greater than one: + self.check_equivalence(source_bps) + + def do_check_options(self): + """Use Python APIs to check serialization of breakpoint options.""" + + empty_module_list = lldb.SBFileSpecList() + empty_cu_list = lldb.SBFileSpecList() + blubby_file_spec = lldb.SBFileSpec(os.path.join(self.getSourceDir(), "blubby.c")) + + # It isn't actually important for these purposes that these breakpoint + # actually have locations. + source_bps = lldb.SBBreakpointList(self.orig_target) + + bkpt = self.orig_target.BreakpointCreateByLocation( + lldb.SBFileSpec("blubby.c"), 666, 333, 0, lldb.SBFileSpecList()) + bkpt.SetEnabled(False) + bkpt.SetOneShot(True) + bkpt.SetThreadID(10) + source_bps.Append(bkpt) + + # Make sure we get one right: + self.check_equivalence(source_bps) + source_bps.Clear() + + bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list) + bkpt.SetIgnoreCount(10) + bkpt.SetThreadName("grubby") + source_bps.Append(bkpt) + + bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list) + bkpt.SetCondition("gonna remove this") + bkpt.SetCondition("") + source_bps.Append(bkpt) + + bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeFull, empty_module_list,empty_cu_list) + bkpt.SetCondition("something != something_else") + bkpt.SetQueueName("grubby") + bkpt.AddName("FirstName") + bkpt.AddName("SecondName") + bkpt.SetScriptCallbackBody('\tprint("I am a function that prints.")\n\tprint("I don\'t do anything else")\n') + source_bps.Append(bkpt) + + bkpt = self.orig_target.BreakpointCreateBySourceRegex("dont really care", blubby_file_spec) + cmd_list = lldb.SBStringList() + cmd_list.AppendString("frame var") + cmd_list.AppendString("thread backtrace") + + bkpt.SetCommandLineCommands(cmd_list) + source_bps.Append(bkpt) + + self.check_equivalence(source_bps) + + def do_check_appending(self): + """Use Python APIs to check appending to already serialized options.""" + + empty_module_list = lldb.SBFileSpecList() + empty_cu_list = lldb.SBFileSpecList() + blubby_file_spec = lldb.SBFileSpec(os.path.join(self.getSourceDir(), "blubby.c")) + + # It isn't actually important for these purposes that these breakpoint + # actually have locations. + + all_bps = lldb.SBBreakpointList(self.orig_target) + source_bps = lldb.SBBreakpointList(self.orig_target) + + bkpt = self.orig_target.BreakpointCreateByLocation( + lldb.SBFileSpec("blubby.c"), 666, 333, 0, lldb.SBFileSpecList()) + bkpt.SetEnabled(False) + bkpt.SetOneShot(True) + bkpt.SetThreadID(10) + source_bps.Append(bkpt) + all_bps.Append(bkpt) + + error = lldb.SBError() + error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, source_bps) + self.assertTrue(error.Success(), "Failed writing breakpoints to file: %s."%(error.GetCString())) + + source_bps.Clear() + + bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list) + bkpt.SetIgnoreCount(10) + bkpt.SetThreadName("grubby") + source_bps.Append(bkpt) + all_bps.Append(bkpt) + + bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeFull, empty_module_list,empty_cu_list) + bkpt.SetCondition("something != something_else") + bkpt.SetQueueName("grubby") + bkpt.AddName("FirstName") + bkpt.AddName("SecondName") + + source_bps.Append(bkpt) + all_bps.Append(bkpt) + + error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, source_bps, True) + self.assertTrue(error.Success(), "Failed appending breakpoints to file: %s."%(error.GetCString())) + + self.check_equivalence(all_bps) + + def do_check_names(self): + bkpt = self.orig_target.BreakpointCreateByLocation( + lldb.SBFileSpec("blubby.c"), 666, 333, 0, lldb.SBFileSpecList()) + good_bkpt_name = "GoodBreakpoint" + write_bps = lldb.SBBreakpointList(self.orig_target) + bkpt.AddName(good_bkpt_name) + write_bps.Append(bkpt) + + error = lldb.SBError() + error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, write_bps) + self.assertTrue(error.Success(), "Failed writing breakpoints to file: %s."%(error.GetCString())) + + copy_bps = lldb.SBBreakpointList(self.copy_target) + names_list = lldb.SBStringList() + names_list.AppendString("NoSuchName") + + error = self.copy_target.BreakpointsCreateFromFile(self.bkpts_file_spec, names_list, copy_bps) + self.assertTrue(error.Success(), "Failed reading breakpoints from file: %s"%(error.GetCString())) + self.assertTrue(copy_bps.GetSize() == 0, "Found breakpoints with a nonexistent name.") + + names_list.AppendString(good_bkpt_name) + error = self.copy_target.BreakpointsCreateFromFile(self.bkpts_file_spec, names_list, copy_bps) + self.assertTrue(error.Success(), "Failed reading breakpoints from file: %s"%(error.GetCString())) + self.assertTrue(copy_bps.GetSize() == 1, "Found the matching breakpoint.") + + def do_check_extra_args(self): + + import side_effect + interp = self.dbg.GetCommandInterpreter() + error = lldb.SBError() + + script_name = os.path.join(self.getSourceDir(), "resolver.py") + + command = "command script import " + script_name + result = lldb.SBCommandReturnObject() + interp.HandleCommand(command, result) + self.assertTrue(result.Succeeded(), "com scr imp failed: %s"%(result.GetError())) + + # First make sure a scripted breakpoint with no args works: + bkpt = self.orig_target.BreakpointCreateFromScript("resolver.Resolver", lldb.SBStructuredData(), + lldb.SBFileSpecList(), lldb.SBFileSpecList()) + self.assertTrue(bkpt.IsValid(), "Bkpt is valid") + write_bps = lldb.SBBreakpointList(self.orig_target) + + error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, write_bps) + self.assertTrue(error.Success(), "Failed writing breakpoints: %s"%(error.GetCString())) + + side_effect.g_extra_args = None + copy_bps = lldb.SBBreakpointList(self.copy_target) + error = self.copy_target.BreakpointsCreateFromFile(self.bkpts_file_spec, copy_bps) + self.assertTrue(error.Success(), "Failed reading breakpoints: %s"%(error.GetCString())) + + self.assertEqual(copy_bps.GetSize(), 1, "Got one breakpoint from file.") + no_keys = lldb.SBStringList() + side_effect.g_extra_args.GetKeys(no_keys) + self.assertEqual(no_keys.GetSize(), 0, "Should have no keys") + + self.orig_target.DeleteAllBreakpoints() + self.copy_target.DeleteAllBreakpoints() + + # Now try one with extra args: + + extra_args = lldb.SBStructuredData() + stream = lldb.SBStream() + stream.Print('{"first_arg" : "first_value", "second_arg" : "second_value"}') + extra_args.SetFromJSON(stream) + self.assertTrue(extra_args.IsValid(), "SBStructuredData is valid.") + + bkpt = self.orig_target.BreakpointCreateFromScript("resolver.Resolver", + extra_args, lldb.SBFileSpecList(), lldb.SBFileSpecList()) + self.assertTrue(bkpt.IsValid(), "Bkpt is valid") + write_bps = lldb.SBBreakpointList(self.orig_target) + + error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, write_bps) + self.assertTrue(error.Success(), "Failed writing breakpoints: %s"%(error.GetCString())) + + orig_extra_args = side_effect.g_extra_args + self.assertTrue(orig_extra_args.IsValid(), "Extra args originally valid") + + orig_keys = lldb.SBStringList() + orig_extra_args.GetKeys(orig_keys) + self.assertEqual(2, orig_keys.GetSize(), "Should have two keys") + + side_effect.g_extra_args = None + + copy_bps = lldb.SBBreakpointList(self.copy_target) + error = self.copy_target.BreakpointsCreateFromFile(self.bkpts_file_spec, copy_bps) + self.assertTrue(error.Success(), "Failed reading breakpoints: %s"%(error.GetCString())) + + self.assertEqual(copy_bps.GetSize(), 1, "Got one breakpoint from file.") + + copy_extra_args = side_effect.g_extra_args + copy_keys = lldb.SBStringList() + copy_extra_args.GetKeys(copy_keys) + self.assertEqual(2, copy_keys.GetSize(), "Copy should have two keys") + + for idx in range(0, orig_keys.GetSize()): + key = orig_keys.GetStringAtIndex(idx) + copy_value = copy_extra_args.GetValueForKey(key).GetStringValue(100) + + if key == "first_arg": + self.assertEqual(copy_value, "first_value") + elif key == "second_arg": + self.assertEqual(copy_value, "second_value") + else: + self.Fail("Unknown key: %s"%(key)) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/main.c new file mode 100644 index 00000000000..b1ed4465c1d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/main.c @@ -0,0 +1,53 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include <stdio.h> + +// This simple program is to demonstrate the capability of the lldb command +// "breakpoint modify -i <count> breakpt-id" to set the number of times a +// breakpoint is skipped before stopping. Ignore count can also be set upon +// breakpoint creation by 'breakpoint set ... -i <count>'. + +int a(int); +int b(int); +int c(int); + +int a(int val) +{ + if (val <= 1) + return b(val); + else if (val >= 3) + return c(val); // a(3) -> c(3) Find the call site of c(3). + + return val; +} + +int b(int val) +{ + return c(val); +} + +int c(int val) +{ + return val + 3; // Find the line number of function "c" here. +} + +int main (int argc, char const *argv[]) +{ + int A1 = a(1); // a(1) -> b(1) -> c(1) + printf("a(1) returns %d\n", A1); + + int B2 = b(2); // b(2) -> c(2) Find the call site of b(2). + printf("b(2) returns %d\n", B2); + + int A3 = a(3); // a(3) -> c(3) Find the call site of a(3). + printf("a(3) returns %d\n", A3); + + int C1 = c(5); // Find the call site of c in main. + printf ("c(5) returns %d\n", C1); + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/resolver.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/resolver.py new file mode 100644 index 00000000000..c3a5af596d2 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/resolver.py @@ -0,0 +1,17 @@ +import lldb +import side_effect + +class Resolver: + """This resolver class is just so I can read out the extra_args.""" + + def __init__(self, bkpt, extra_args, dict): + self.bkpt = bkpt + side_effect.g_extra_args = extra_args + + def __callback__(self, sym_ctx): + """Doesn't actually do anything.""" + return + + def get_short_help(self): + return "I am a python breakpoint resolver that does nothing" + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/side_effect.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/side_effect.py new file mode 100644 index 00000000000..868901cfce8 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/side_effect.py @@ -0,0 +1 @@ +g_extra_args = None diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/Makefile new file mode 100644 index 00000000000..af0cd3066df --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c a.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/TestSourceRegexBreakpoints.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/TestSourceRegexBreakpoints.py new file mode 100644 index 00000000000..0409c78c1b8 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/TestSourceRegexBreakpoints.py @@ -0,0 +1,103 @@ +""" +Test lldb breakpoint setting by source regular expression. +This test just tests the source file & function restrictions. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestSourceRegexBreakpoints(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_location(self): + self.build() + self.source_regex_locations() + + def test_restrictions(self): + self.build() + self.source_regex_restrictions() + + def source_regex_locations(self): + """ Test that restricting source expressions to files & to functions. """ + # Create a target by the debugger. + exe = self.getBuildArtifact("a.out") + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # First look just in main: + target_files = lldb.SBFileSpecList() + target_files.Append(lldb.SBFileSpec("a.c")) + + func_names = lldb.SBStringList() + func_names.AppendString("a_func") + + source_regex = "Set . breakpoint here" + main_break = target.BreakpointCreateBySourceRegex( + source_regex, lldb.SBFileSpecList(), target_files, func_names) + num_locations = main_break.GetNumLocations() + self.assertTrue( + num_locations == 1, + "a.c in a_func should give one breakpoint, got %d." % + (num_locations)) + + loc = main_break.GetLocationAtIndex(0) + self.assertTrue(loc.IsValid(), "Got a valid location.") + address = loc.GetAddress() + self.assertTrue( + address.IsValid(), + "Got a valid address from the location.") + + a_func_line = line_number("a.c", "Set A breakpoint here") + line_entry = address.GetLineEntry() + self.assertTrue(line_entry.IsValid(), "Got a valid line entry.") + self.assertTrue(line_entry.line == a_func_line, + "Our line number matches the one lldbtest found.") + + def source_regex_restrictions(self): + """ Test that restricting source expressions to files & to functions. """ + # Create a target by the debugger. + exe = self.getBuildArtifact("a.out") + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # First look just in main: + target_files = lldb.SBFileSpecList() + target_files.Append(lldb.SBFileSpec("main.c")) + source_regex = "Set . breakpoint here" + main_break = target.BreakpointCreateBySourceRegex( + source_regex, lldb.SBFileSpecList(), target_files, lldb.SBStringList()) + + num_locations = main_break.GetNumLocations() + self.assertTrue( + num_locations == 2, + "main.c should have 2 matches, got %d." % + (num_locations)) + + # Now look in both files: + target_files.Append(lldb.SBFileSpec("a.c")) + + main_break = target.BreakpointCreateBySourceRegex( + source_regex, lldb.SBFileSpecList(), target_files, lldb.SBStringList()) + + num_locations = main_break.GetNumLocations() + self.assertTrue( + num_locations == 4, + "main.c and a.c should have 4 matches, got %d." % + (num_locations)) + + # Now restrict it to functions: + func_names = lldb.SBStringList() + func_names.AppendString("main_func") + main_break = target.BreakpointCreateBySourceRegex( + source_regex, lldb.SBFileSpecList(), target_files, func_names) + + num_locations = main_break.GetNumLocations() + self.assertTrue( + num_locations == 2, + "main_func in main.c and a.c should have 2 matches, got %d." % + (num_locations)) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/a.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/a.c new file mode 100644 index 00000000000..056583f1c42 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/a.c @@ -0,0 +1,16 @@ +#include <stdio.h> + +#include "a.h" + +static int +main_func(int input) +{ + return printf("Set B breakpoint here: %d", input); +} + +int +a_func(int input) +{ + input += 1; // Set A breakpoint here; + return main_func(input); +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/a.h b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/a.h new file mode 100644 index 00000000000..f578ac0304c --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/a.h @@ -0,0 +1 @@ +int a_func(int); diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/main.c new file mode 100644 index 00000000000..9c8625e877f --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/main.c @@ -0,0 +1,17 @@ +#include <stdio.h> +#include "a.h" + +int +main_func(int input) +{ + return printf("Set B breakpoint here: %d.\n", input); +} + +int +main() +{ + a_func(10); + main_func(10); + printf("Set a breakpoint here:\n"); + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/Makefile new file mode 100644 index 00000000000..2c00681fa22 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/Makefile @@ -0,0 +1,8 @@ +CXX_SOURCES := main.cpp + +ifneq (,$(findstring icc,$(CC))) + CXXFLAGS_EXTRAS := -debug inline-debug-info +endif + + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/TestStepOverBreakpoint.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/TestStepOverBreakpoint.py new file mode 100644 index 00000000000..ea94fd3ec1f --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/TestStepOverBreakpoint.py @@ -0,0 +1,118 @@ +""" +Test that breakpoints do not affect stepping. +Check for correct StopReason when stepping to the line with breakpoint +which chould be eStopReasonBreakpoint in general, +and eStopReasonPlanComplete when breakpoint's condition fails. +""" + + +import unittest2 +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class StepOverBreakpointsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + TestBase.setUp(self) + + self.build() + exe = self.getBuildArtifact("a.out") + src = lldb.SBFileSpec("main.cpp") + + # Create a target by the debugger. + self.target = self.dbg.CreateTarget(exe) + self.assertTrue(self.target, VALID_TARGET) + + # Setup four breakpoints, two of them with false condition + self.line1 = line_number('main.cpp', "breakpoint_1") + self.line4 = line_number('main.cpp', "breakpoint_4") + + self.breakpoint1 = self.target.BreakpointCreateByLocation(src, self.line1) + self.assertTrue( + self.breakpoint1 and self.breakpoint1.GetNumLocations() == 1, + VALID_BREAKPOINT) + + self.breakpoint2 = self.target.BreakpointCreateBySourceRegex("breakpoint_2", src) + self.breakpoint2.GetLocationAtIndex(0).SetCondition('false') + + self.breakpoint3 = self.target.BreakpointCreateBySourceRegex("breakpoint_3", src) + self.breakpoint3.GetLocationAtIndex(0).SetCondition('false') + + self.breakpoint4 = self.target.BreakpointCreateByLocation(src, self.line4) + + # Start debugging + self.process = self.target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertIsNotNone(self.process, PROCESS_IS_VALID) + self.thread = lldbutil.get_one_thread_stopped_at_breakpoint(self.process, self.breakpoint1) + self.assertIsNotNone(self.thread, "Didn't stop at breakpoint 1.") + + def test_step_instruction(self): + # Count instructions between breakpoint_1 and breakpoint_4 + contextList = self.target.FindFunctions('main', lldb.eFunctionNameTypeAuto) + self.assertEquals(contextList.GetSize(), 1) + symbolContext = contextList.GetContextAtIndex(0) + function = symbolContext.GetFunction() + self.assertTrue(function) + instructions = function.GetInstructions(self.target) + addr_1 = self.breakpoint1.GetLocationAtIndex(0).GetAddress() + addr_4 = self.breakpoint4.GetLocationAtIndex(0).GetAddress() + + # if third argument is true then the count will be the number of + # instructions on which a breakpoint can be set. + # start = addr_1, end = addr_4, canSetBreakpoint = True + steps_expected = instructions.GetInstructionsCount(addr_1, addr_4, True) + step_count = 0 + # Step from breakpoint_1 to breakpoint_4 + while True: + self.thread.StepInstruction(True) + step_count = step_count + 1 + self.assertEquals(self.process.GetState(), lldb.eStateStopped) + self.assertTrue(self.thread.GetStopReason() == lldb.eStopReasonPlanComplete or + self.thread.GetStopReason() == lldb.eStopReasonBreakpoint) + if (self.thread.GetStopReason() == lldb.eStopReasonBreakpoint) : + # we should not stop on breakpoint_2 and _3 because they have false condition + self.assertEquals(self.thread.GetFrameAtIndex(0).GetLineEntry().GetLine(), self.line4) + # breakpoint_2 and _3 should not affect step count + self.assertTrue(step_count >= steps_expected) + break + + # Run the process until termination + self.process.Continue() + self.assertEquals(self.process.GetState(), lldb.eStateExited) + + @skipIf(bugnumber="llvm.org/pr31972", hostoslist=["windows"]) + def test_step_over(self): + #lldb.DBG.EnableLog("lldb", ["step","breakpoint"]) + + self.thread.StepOver() + # We should be stopped at the breakpoint_2 line with stop plan complete reason + self.assertEquals(self.process.GetState(), lldb.eStateStopped) + self.assertEquals(self.thread.GetStopReason(), lldb.eStopReasonPlanComplete) + + self.thread.StepOver() + # We should be stopped at the breakpoint_3 line with stop plan complete reason + self.assertEquals(self.process.GetState(), lldb.eStateStopped) + self.assertEquals(self.thread.GetStopReason(), lldb.eStopReasonPlanComplete) + + self.thread.StepOver() + # We should be stopped at the breakpoint_4 + self.assertEquals(self.process.GetState(), lldb.eStateStopped) + self.assertEquals(self.thread.GetStopReason(), lldb.eStopReasonBreakpoint) + thread1 = lldbutil.get_one_thread_stopped_at_breakpoint(self.process, self.breakpoint4) + self.assertEquals(self.thread, thread1, "Didn't stop at breakpoint 4.") + + # Check that stepping does not affect breakpoint's hit count + self.assertEquals(self.breakpoint1.GetHitCount(), 1) + self.assertEquals(self.breakpoint2.GetHitCount(), 0) + self.assertEquals(self.breakpoint3.GetHitCount(), 0) + self.assertEquals(self.breakpoint4.GetHitCount(), 1) + + # Run the process until termination + self.process.Continue() + self.assertEquals(self.process.GetState(), lldb.eStateExited) + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/main.cpp new file mode 100644 index 00000000000..8cfd34b73b5 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/main.cpp @@ -0,0 +1,12 @@ + +int func() { return 1; } + +int +main(int argc, char const *argv[]) +{ + int a = 0; // breakpoint_1 + int b = func(); // breakpoint_2 + a = b + func(); // breakpoint_3 + return 0; // breakpoint_4 +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/completion/.categories b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/completion/.categories new file mode 100644 index 00000000000..3a3f4df6416 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/completion/.categories @@ -0,0 +1 @@ +cmdline diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/completion/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/completion/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/completion/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/completion/TestCompletion.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/completion/TestCompletion.py new file mode 100644 index 00000000000..26c70c1e7fc --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/completion/TestCompletion.py @@ -0,0 +1,431 @@ +""" +Test the lldb command line completion mechanism. +""" + + + +import os +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbplatform +from lldbsuite.test import lldbutil + + +class CommandLineCompletionTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + @classmethod + def classCleanup(cls): + """Cleanup the test byproducts.""" + try: + os.remove("child_send.txt") + os.remove("child_read.txt") + except: + pass + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_at(self): + """Test that 'at' completes to 'attach '.""" + self.complete_from_to('at', 'attach ') + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_de(self): + """Test that 'de' completes to 'detach '.""" + self.complete_from_to('de', 'detach ') + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_frame_variable(self): + self.build() + self.main_source = "main.cpp" + self.main_source_spec = lldb.SBFileSpec(self.main_source) + + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + '// Break here', self.main_source_spec) + self.assertEquals(process.GetState(), lldb.eStateStopped) + # FIXME: This pulls in the debug information to make the completions work, + # but the completions should also work without. + self.runCmd("frame variable fooo") + + self.complete_from_to('frame variable fo', + 'frame variable fooo') + self.complete_from_to('frame variable fooo.', + 'frame variable fooo.') + self.complete_from_to('frame variable fooo.dd', + 'frame variable fooo.dd') + + self.complete_from_to('frame variable ptr_fooo->', + 'frame variable ptr_fooo->') + self.complete_from_to('frame variable ptr_fooo->dd', + 'frame variable ptr_fooo->dd') + + self.complete_from_to('frame variable cont', + 'frame variable container') + self.complete_from_to('frame variable container.', + 'frame variable container.MemberVar') + self.complete_from_to('frame variable container.Mem', + 'frame variable container.MemberVar') + + self.complete_from_to('frame variable ptr_cont', + 'frame variable ptr_container') + self.complete_from_to('frame variable ptr_container->', + 'frame variable ptr_container->MemberVar') + self.complete_from_to('frame variable ptr_container->Mem', + 'frame variable ptr_container->MemberVar') + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_process_attach_dash_dash_con(self): + """Test that 'process attach --con' completes to 'process attach --continue '.""" + self.complete_from_to( + 'process attach --con', + 'process attach --continue ') + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_process_launch_arch(self): + self.complete_from_to('process launch --arch ', + ['mips', + 'arm64']) + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_ambiguous_long_opt(self): + self.completions_match('breakpoint modify --th', + ['--thread-id', + '--thread-index', + '--thread-name']) + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_plugin_load(self): + self.complete_from_to('plugin load ', []) + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_log_enable(self): + self.complete_from_to('log enable ll', ['lldb']) + self.complete_from_to('log enable dw', ['dwarf']) + self.complete_from_to('log enable lldb al', ['all']) + self.complete_from_to('log enable lldb sym', ['symbol']) + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_log_enable(self): + self.complete_from_to('log disable ll', ['lldb']) + self.complete_from_to('log disable dw', ['dwarf']) + self.complete_from_to('log disable lldb al', ['all']) + self.complete_from_to('log disable lldb sym', ['symbol']) + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_log_list(self): + self.complete_from_to('log list ll', ['lldb']) + self.complete_from_to('log list dw', ['dwarf']) + self.complete_from_to('log list ll', ['lldb']) + self.complete_from_to('log list lldb dwa', ['dwarf']) + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_quoted_command(self): + self.complete_from_to('"set', + ['"settings" ']) + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_quoted_arg_with_quoted_command(self): + self.complete_from_to('"settings" "repl', + ['"replace" ']) + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_quoted_arg_without_quoted_command(self): + self.complete_from_to('settings "repl', + ['"replace" ']) + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_single_quote_command(self): + self.complete_from_to("'set", + ["'settings' "]) + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_terminated_quote_command(self): + # This should not crash, but we don't get any + # reasonable completions from this. + self.complete_from_to("'settings'", []) + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_process_launch_arch_arm(self): + self.complete_from_to('process launch --arch arm', + ['arm64']) + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_target_symbols_add_shlib(self): + # Doesn't seem to work, but at least it shouldn't crash. + self.complete_from_to('target symbols add --shlib ', []) + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_log_file(self): + # Complete in our source directory which contains a 'main.cpp' file. + src_dir = os.path.dirname(os.path.realpath(__file__)) + '/' + self.complete_from_to('log enable lldb expr -f ' + src_dir, + ['main.cpp']) + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_log_dir(self): + # Complete our source directory. + src_dir = os.path.dirname(os.path.realpath(__file__)) + self.complete_from_to('log enable lldb expr -f ' + src_dir, + [src_dir + os.sep], turn_off_re_match=True) + + # <rdar://problem/11052829> + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_infinite_loop_while_completing(self): + """Test that 'process print hello\' completes to itself and does not infinite loop.""" + self.complete_from_to('process print hello\\', 'process print hello\\', + turn_off_re_match=True) + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_watchpoint_co(self): + """Test that 'watchpoint co' completes to 'watchpoint command '.""" + self.complete_from_to('watchpoint co', 'watchpoint command ') + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_watchpoint_command_space(self): + """Test that 'watchpoint command ' completes to ['add', 'delete', 'list'].""" + self.complete_from_to( + 'watchpoint command ', [ + 'add', 'delete', 'list']) + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_watchpoint_command_a(self): + """Test that 'watchpoint command a' completes to 'watchpoint command add '.""" + self.complete_from_to( + 'watchpoint command a', + 'watchpoint command add ') + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_watchpoint_set_ex(self): + """Test that 'watchpoint set ex' completes to 'watchpoint set expression '.""" + self.complete_from_to( + 'watchpoint set ex', + 'watchpoint set expression ') + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_watchpoint_set_var(self): + """Test that 'watchpoint set var' completes to 'watchpoint set variable '.""" + self.complete_from_to('watchpoint set var', 'watchpoint set variable ') + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_help_fi(self): + """Test that 'help fi' completes to ['file', 'finish'].""" + self.complete_from_to( + 'help fi', [ + 'file', 'finish']) + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_help_watchpoint_s(self): + """Test that 'help watchpoint s' completes to 'help watchpoint set '.""" + self.complete_from_to('help watchpoint s', 'help watchpoint set ') + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_settings_append_target_er(self): + """Test that 'settings append target.er' completes to 'settings append target.error-path'.""" + self.complete_from_to( + 'settings append target.er', + 'settings append target.error-path') + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_settings_insert_after_target_en(self): + """Test that 'settings insert-after target.env' completes to 'settings insert-after target.env-vars'.""" + self.complete_from_to( + 'settings insert-after target.env', + 'settings insert-after target.env-vars') + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_settings_insert_before_target_en(self): + """Test that 'settings insert-before target.env' completes to 'settings insert-before target.env-vars'.""" + self.complete_from_to( + 'settings insert-before target.env', + 'settings insert-before target.env-vars') + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_settings_replace_target_ru(self): + """Test that 'settings replace target.ru' completes to 'settings replace target.run-args'.""" + self.complete_from_to( + 'settings replace target.ru', + 'settings replace target.run-args') + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_settings_show_term(self): + self.complete_from_to( + 'settings show term-', + 'settings show term-width') + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_settings_list_term(self): + self.complete_from_to( + 'settings list term-', + 'settings list term-width') + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_settings_remove_term(self): + self.complete_from_to( + 'settings remove term-', + 'settings remove term-width') + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_settings_s(self): + """Test that 'settings s' completes to ['set', 'show'].""" + self.complete_from_to( + 'settings s', [ + 'set', 'show']) + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_settings_set_th(self): + """Test that 'settings set thread-f' completes to 'settings set thread-format'.""" + self.complete_from_to('settings set thread-f', 'settings set thread-format') + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_settings_s_dash(self): + """Test that 'settings set --g' completes to 'settings set --global'.""" + self.complete_from_to('settings set --g', 'settings set --global') + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_settings_clear_th(self): + """Test that 'settings clear thread-f' completes to 'settings clear thread-format'.""" + self.complete_from_to( + 'settings clear thread-f', + 'settings clear thread-format') + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_settings_set_ta(self): + """Test that 'settings set ta' completes to 'settings set target.'.""" + self.complete_from_to( + 'settings set target.ma', + 'settings set target.max-') + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_settings_set_target_exec(self): + """Test that 'settings set target.exec' completes to 'settings set target.exec-search-paths '.""" + self.complete_from_to( + 'settings set target.exec', + 'settings set target.exec-search-paths') + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_settings_set_target_pr(self): + """Test that 'settings set target.pr' completes to [ + 'target.prefer-dynamic-value', 'target.process.'].""" + self.complete_from_to('settings set target.pr', + ['target.prefer-dynamic-value', + 'target.process.']) + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_settings_set_target_process(self): + """Test that 'settings set target.process' completes to 'settings set target.process.'.""" + self.complete_from_to( + 'settings set target.process', + 'settings set target.process.') + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_settings_set_target_process_dot(self): + """Test that 'settings set target.process.t' completes to 'settings set target.process.thread.'.""" + self.complete_from_to( + 'settings set target.process.t', + 'settings set target.process.thread.') + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_settings_set_target_process_thread_dot(self): + """Test that 'settings set target.process.thread.' completes to [ + 'target.process.thread.step-avoid-regexp', 'target.process.thread.trace-thread'].""" + self.complete_from_to('settings set target.process.thread.', + ['target.process.thread.step-avoid-regexp', + 'target.process.thread.trace-thread']) + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_target_space(self): + """Test that 'target ' completes to ['create', 'delete', 'list', + 'modules', 'select', 'stop-hook', 'variable'].""" + self.complete_from_to('target ', + ['create', + 'delete', + 'list', + 'modules', + 'select', + 'stop-hook', + 'variable']) + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_target_create_dash_co(self): + """Test that 'target create --co' completes to 'target variable --core '.""" + self.complete_from_to('target create --co', 'target create --core ') + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_target_va(self): + """Test that 'target va' completes to 'target variable '.""" + self.complete_from_to('target va', 'target variable ') + + def test_command_argument_completion(self): + """Test completion of command arguments""" + self.complete_from_to("watchpoint set variable -", ["-w", "-s"]) + self.complete_from_to('watchpoint set variable -w', 'watchpoint set variable -w ') + self.complete_from_to("watchpoint set variable --", ["--watch", "--size"]) + self.complete_from_to("watchpoint set variable --w", "watchpoint set variable --watch") + self.complete_from_to('watchpoint set variable -w ', ['read', 'write', 'read_write']) + self.complete_from_to("watchpoint set variable --watch ", ["read", "write", "read_write"]) + self.complete_from_to("watchpoint set variable --watch w", "watchpoint set variable --watch write") + self.complete_from_to('watchpoint set variable -w read_', 'watchpoint set variable -w read_write') + # Now try the same thing with a variable name (non-option argument) to + # test that getopts arg reshuffling doesn't confuse us. + self.complete_from_to("watchpoint set variable foo -", ["-w", "-s"]) + self.complete_from_to('watchpoint set variable foo -w', 'watchpoint set variable foo -w ') + self.complete_from_to("watchpoint set variable foo --", ["--watch", "--size"]) + self.complete_from_to("watchpoint set variable foo --w", "watchpoint set variable foo --watch") + self.complete_from_to('watchpoint set variable foo -w ', ['read', 'write', 'read_write']) + self.complete_from_to("watchpoint set variable foo --watch ", ["read", "write", "read_write"]) + self.complete_from_to("watchpoint set variable foo --watch w", "watchpoint set variable foo --watch write") + self.complete_from_to('watchpoint set variable foo -w read_', 'watchpoint set variable foo -w read_write') + + def test_completion_description_commands(self): + """Test descriptions of top-level command completions""" + self.check_completion_with_desc("", [ + ["command", "Commands for managing custom LLDB commands."], + ["breakpoint", "Commands for operating on breakpoints (see 'help b' for shorthand.)"] + ]) + + self.check_completion_with_desc("pl", [ + ["platform", "Commands to manage and create platforms."], + ["plugin", "Commands for managing LLDB plugins."] + ]) + + # Just check that this doesn't crash. + self.check_completion_with_desc("comman", []) + self.check_completion_with_desc("non-existent-command", []) + + def test_completion_description_command_options(self): + """Test descriptions of command options""" + # Short options + self.check_completion_with_desc("breakpoint set -", [ + ["-h", "Set the breakpoint on exception catcH."], + ["-w", "Set the breakpoint on exception throW."] + ]) + + # Long options. + self.check_completion_with_desc("breakpoint set --", [ + ["--on-catch", "Set the breakpoint on exception catcH."], + ["--on-throw", "Set the breakpoint on exception throW."] + ]) + + # Ambiguous long options. + self.check_completion_with_desc("breakpoint set --on-", [ + ["--on-catch", "Set the breakpoint on exception catcH."], + ["--on-throw", "Set the breakpoint on exception throW."] + ]) + + # Unknown long option. + self.check_completion_with_desc("breakpoint set --Z", [ + ]) + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24489") + def test_symbol_name(self): + self.build() + self.dbg.CreateTarget(self.getBuildArtifact("a.out")) + self.complete_from_to('breakpoint set -n Fo', + 'breakpoint set -n Foo::Bar(int,\\ int)', + turn_off_re_match=True) + # No completion for Qu because the candidate is + # (anonymous namespace)::Quux(). + self.complete_from_to('breakpoint set -n Qu', '') diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/completion/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/completion/main.cpp new file mode 100644 index 00000000000..eba81dc4c54 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/completion/main.cpp @@ -0,0 +1,24 @@ +class Foo +{ +public: + int Bar(int x, int y) + { + return x + y; + } +}; + +namespace { int Quux (void) { return 0; } } + +struct Container { int MemberVar; }; + +int main() +{ + Foo fooo; + Foo *ptr_fooo = &fooo; + fooo.Bar(1, 2); + + Container container; + Container *ptr_container = &container; + int q = Quux(); + return container.MemberVar = 3; // Break here +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/conditional_break/.lldb b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/conditional_break/.lldb new file mode 100644 index 00000000000..4be90efee23 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/conditional_break/.lldb @@ -0,0 +1,3 @@ +breakpoint set -n c +command script import -r conditional_break.py +breakpoint command add 1 -F "conditional_break.stop_if_called_from_a" diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/conditional_break/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/conditional_break/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/conditional_break/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/conditional_break/TestConditionalBreak.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/conditional_break/TestConditionalBreak.py new file mode 100644 index 00000000000..cc48a639724 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/conditional_break/TestConditionalBreak.py @@ -0,0 +1,138 @@ +""" +Test conditionally break on a function and inspect its variables. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +# rdar://problem/8532131 +# lldb not able to digest the clang-generated debug info correctly with respect to function name +# +# This class currently fails for clang as well as llvm-gcc. + + +class ConditionalBreakTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @add_test_categories(['pyapi']) + def test_with_python(self): + """Exercise some thread and frame APIs to break if c() is called by a().""" + self.build() + self.do_conditional_break() + + def test_with_command(self): + """Simulate a user using lldb commands to break on c() if called from a().""" + self.build() + self.simulate_conditional_break_by_user() + + def do_conditional_break(self): + """Exercise some thread and frame APIs to break if c() is called by a().""" + exe = self.getBuildArtifact("a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + breakpoint = target.BreakpointCreateByName("c", exe) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + + self.assertTrue(process, PROCESS_IS_VALID) + + # The stop reason of the thread should be breakpoint. + self.assertTrue(process.GetState() == lldb.eStateStopped, + STOPPED_DUE_TO_BREAKPOINT) + + # Find the line number where a's parent frame function is c. + line = line_number( + 'main.c', + "// Find the line number where c's parent frame is a here.") + + # Suppose we are only interested in the call scenario where c()'s + # immediate caller is a() and we want to find out the value passed from + # a(). + # + # The 10 in range(10) is just an arbitrary number, which means we would + # like to try for at most 10 times. + for j in range(10): + if self.TraceOn(): + print("j is: ", j) + thread = lldbutil.get_one_thread_stopped_at_breakpoint( + process, breakpoint) + self.assertIsNotNone( + thread, "Expected one thread to be stopped at the breakpoint") + + if thread.GetNumFrames() >= 2: + frame0 = thread.GetFrameAtIndex(0) + name0 = frame0.GetFunction().GetName() + frame1 = thread.GetFrameAtIndex(1) + name1 = frame1.GetFunction().GetName() + # lldbutil.print_stacktrace(thread) + self.assertTrue(name0 == "c", "Break on function c()") + if (name1 == "a"): + # By design, we know that a() calls c() only from main.c:27. + # In reality, similar logic can be used to find out the call + # site. + self.assertTrue(frame1.GetLineEntry().GetLine() == line, + "Immediate caller a() at main.c:%d" % line) + + # And the local variable 'val' should have a value of (int) + # 3. + val = frame1.FindVariable("val") + self.assertEqual("int", val.GetTypeName()) + self.assertEqual("3", val.GetValue()) + break + + process.Continue() + + def simulate_conditional_break_by_user(self): + """Simulate a user using lldb commands to break on c() if called from a().""" + + # Sourcing .lldb in the current working directory, which sets the main + # executable, sets the breakpoint on c(), and adds the callback for the + # breakpoint such that lldb only stops when the caller of c() is a(). + # the "my" package that defines the date() function. + if self.TraceOn(): + print("About to source .lldb") + + if not self.TraceOn(): + self.HideStdout() + + # Separate out the "file " + self.getBuildArtifact("a.out") command from .lldb file, for the sake of + # remote testsuite. + self.runCmd("file " + self.getBuildArtifact("a.out")) + self.runCmd("command source .lldb") + + self.runCmd("break list") + + if self.TraceOn(): + print("About to run.") + self.runCmd("run", RUN_SUCCEEDED) + + self.runCmd("break list") + + if self.TraceOn(): + print("Done running") + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', 'stop reason = breakpoint']) + + # The frame info for frame #0 points to a.out`c and its immediate caller + # (frame #1) points to a.out`a. + + self.expect("frame info", "We should stop at c()", + substrs=["a.out`c"]) + + # Select our parent frame as the current frame. + self.runCmd("frame select 1") + self.expect("frame info", "The immediate caller should be a()", + substrs=["a.out`a"]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/conditional_break/conditional_break.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/conditional_break/conditional_break.py new file mode 100644 index 00000000000..4f2746428cd --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/conditional_break/conditional_break.py @@ -0,0 +1,29 @@ +import lldb + + +def stop_if_called_from_a(frame, bp_loc, dict): + + thread = frame.GetThread() + process = thread.GetProcess() + target = process.GetTarget() + dbg = target.GetDebugger() + + # Perform synchronous interaction with the debugger. + old_async = dbg.GetAsync() + dbg.SetAsync(True) + + # We check the call frames in order to stop only when the immediate caller + # of the leaf function c() is a(). If it's not the right caller, we ask the + # command interpreter to continue execution. + + should_stop = True + if thread.GetNumFrames() >= 2: + + if (thread.frames[0].function.name == + 'c' and thread.frames[1].function.name == 'a'): + should_stop = True + else: + should_stop = False + + dbg.SetAsync(old_async) + return should_stop diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/conditional_break/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/conditional_break/main.c new file mode 100644 index 00000000000..dc528a458b3 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/conditional_break/main.c @@ -0,0 +1,53 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include <stdio.h> + +// This simple program is to demonstrate the capability of the lldb command +// "breakpoint command add" to add a set of commands to a breakpoint to be +// executed when the breakpoint is hit. +// +// In particular, we want to break within c(), but only if the immediate caller +// is a(). + +int a(int); +int b(int); +int c(int); + +int a(int val) +{ + if (val <= 1) + return b(val); + else if (val >= 3) + return c(val); // Find the line number where c's parent frame is a here. + + return val; +} + +int b(int val) +{ + return c(val); +} + +int c(int val) +{ + return val + 3; +} + +int main (int argc, char const *argv[]) +{ + int A1 = a(1); // a(1) -> b(1) -> c(1) + printf("a(1) returns %d\n", A1); + + int B2 = b(2); // b(2) -> c(2) + printf("b(2) returns %d\n", B2); + + int A3 = a(3); // a(3) -> c(3) + printf("a(3) returns %d\n", A3); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/.categories b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/.categories new file mode 100644 index 00000000000..ea135483a48 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/.categories @@ -0,0 +1 @@ +darwin-log diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/basic/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/basic/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/basic/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/basic/TestDarwinLogBasic.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/basic/TestDarwinLogBasic.py new file mode 100644 index 00000000000..6e6607ac232 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/basic/TestDarwinLogBasic.py @@ -0,0 +1,35 @@ +""" +Test basic DarwinLog functionality provided by the StructuredDataDarwinLog +plugin. + +These tests are currently only supported when running against Darwin +targets. +""" + +# System imports + +# LLDB imports +from lldbsuite.test import darwin_log +from lldbsuite.test import decorators +from lldbsuite.test import lldbtest + + +class TestDarwinLogBasic(darwin_log.DarwinLogEventBasedTestBase): + + mydir = lldbtest.TestBase.compute_mydir(__file__) + + @decorators.add_test_categories(['pyapi']) + @decorators.skipUnlessDarwin + @decorators.expectedFailureAll(archs=["i386"], bugnumber="rdar://28655626") + @decorators.expectedFailureAll(bugnumber="rdar://30645203") + def test_SBStructuredData_gets_broadcasted(self): + """Exercise SBStructuredData API.""" + + # Run the test. + log_entries = self.do_test(None, max_entry_count=2) + + # Validate that we received our two log entries. + self.assertEqual(len(log_entries), 1, + "Expected one log entry to arrive via events.") + self.assertEqual(log_entries[0]['message'], "Hello, world", + "Log message should match expected content.") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/basic/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/basic/main.c new file mode 100644 index 00000000000..c69d0ab1c35 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/basic/main.c @@ -0,0 +1,31 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <os/log.h> +#include <stdio.h> + +#include "../common/darwin_log_common.h" + +int main(int argc, char** argv) +{ + os_log_t logger = os_log_create("org.llvm.lldb.test", "basic-test"); + if (!logger) + return 1; + + // Note we cannot use the os_log() line as the breakpoint because, as of + // the initial writing of this test, we get multiple breakpoints for that + // line, which confuses the pexpect test logic. + printf("About to log\n"); // break here + os_log(logger, "Hello, world"); + + // Sleep, as the darwin log reporting doesn't always happen until a bit + // later. We need the message to come out before the process terminates. + sleep(FINAL_WAIT_SECONDS); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/common/darwin_log_common.h b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/common/darwin_log_common.h new file mode 100644 index 00000000000..de923b94911 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/common/darwin_log_common.h @@ -0,0 +1,6 @@ +// The number of seconds to wait at the end of the test inferior before +// exiting. This delay is needed to ensure the logging infrastructure +// has flushed out the message. If we finished before all messages were +// flushed, then the test will never see the unflushed messages, causing +// some test logic to fail. +#define FINAL_WAIT_SECONDS 5 diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/activity-chain/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/activity-chain/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/activity-chain/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/activity-chain/TestDarwinLogFilterMatchActivityChain.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/activity-chain/TestDarwinLogFilterMatchActivityChain.py new file mode 100644 index 00000000000..c1dfd15c6bd --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/activity-chain/TestDarwinLogFilterMatchActivityChain.py @@ -0,0 +1,120 @@ +""" +Test basic DarwinLog functionality provided by the StructuredDataDarwinLog +plugin. + +These tests are currently only supported when running against Darwin +targets. +""" + + +import lldb + +from lldbsuite.test import decorators +from lldbsuite.test import lldbtest +from lldbsuite.test import darwin_log + + +class TestDarwinLogFilterMatchActivityChain(darwin_log.DarwinLogTestBase): + + mydir = lldbtest.TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + super(TestDarwinLogFilterMatchActivityChain, self).setUp() + + # Source filename. + self.source = 'main.c' + + # Output filename. + self.exe_name = self.getBuildArtifact("a.out") + self.d = {'C_SOURCES': self.source, 'EXE': self.exe_name} + + # Locate breakpoint. + self.line = lldbtest.line_number(self.source, '// break here') + + def tearDown(self): + # Shut down the process if it's still running. + if self.child: + self.runCmd('process kill') + self.expect_prompt() + self.runCmd('quit') + + # Let parent clean up + super(TestDarwinLogFilterMatchActivityChain, self).tearDown() + + # ========================================================================== + # activity-chain filter tests + # ========================================================================== + + @decorators.skipUnlessDarwin + def test_filter_accept_activity_chain_match(self): + """Test that fall-through reject, accept full-match activity chain works.""" + self.do_test( + ["--no-match-accepts false", + "--filter \"accept activity-chain match " + "parent-activity:child-activity\""]) + + # We should only see the second log message as we only accept + # that activity. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + def test_filter_reject_activity_chain_partial_match(self): + """Test that fall-through reject, doesn't accept only partial match of activity-chain.""" + self.do_test( + ["--no-match-accepts false", + # Match the second fully. + "--filter \"accept activity-chain match parent-activity:child-activity\"", + "--filter \"accept activity-chain match parent-ac\""]) # Only partially match the first. + + # We should only see the second log message as we only accept + # that activity. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + def test_filter_reject_activity_chain_full_match(self): + """Test that fall-through accept, reject match activity-chain works.""" + self.do_test( + ["--no-match-accepts true", + "--filter \"reject activity-chain match parent-activity\""]) + + # We should only see the second log message as we rejected the first + # via activity-chain rejection. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + def test_filter_accept_activity_chain_second_rule(self): + """Test that fall-through reject, accept activity-chain on second rule works.""" + self.do_test( + ["--no-match-accepts false", + "--filter \"accept activity-chain match non-existent\"", + "--filter \"accept activity-chain match parent-activity:child-activity\""]) + + # We should only see the second message since we reject by default, + # the first filter doesn't match any, and the second filter matches + # the activity-chain of the second log message. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/activity-chain/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/activity-chain/main.c new file mode 100644 index 00000000000..fbe5106b5db --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/activity-chain/main.c @@ -0,0 +1,42 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <os/activity.h> +#include <os/log.h> +#include <stdio.h> + +#include "../../../common/darwin_log_common.h" + +int main(int argc, char** argv) +{ + os_log_t logger_sub1 = os_log_create("org.llvm.lldb.test.sub1", "cat1"); + os_log_t logger_sub2 = os_log_create("org.llvm.lldb.test.sub2", "cat2"); + if (!logger_sub1 || !logger_sub2) + return 1; + + // Note we cannot use the os_log() line as the breakpoint because, as of + // the initial writing of this test, we get multiple breakpoints for that + // line, which confuses the pexpect test logic. + printf("About to log\n"); // break here + os_activity_t parent_activity = os_activity_create("parent-activity", + OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); + os_activity_apply(parent_activity, ^{ + os_log(logger_sub1, "source-log-sub1-cat1"); + os_activity_t child_activity = os_activity_create("child-activity", + OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); + os_activity_apply(child_activity, ^{ + os_log(logger_sub2, "source-log-sub2-cat2"); + }); + }); + + // Sleep, as the darwin log reporting doesn't always happen until a bit + // later. We need the message to come out before the process terminates. + sleep(FINAL_WAIT_SECONDS); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/activity/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/activity/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/activity/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/activity/TestDarwinLogFilterMatchActivity.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/activity/TestDarwinLogFilterMatchActivity.py new file mode 100644 index 00000000000..f2587b1899a --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/activity/TestDarwinLogFilterMatchActivity.py @@ -0,0 +1,124 @@ +""" +Test basic DarwinLog functionality provided by the StructuredDataDarwinLog +plugin. + +These tests are currently only supported when running against Darwin +targets. +""" + + +import lldb + +from lldbsuite.test import decorators +from lldbsuite.test import lldbtest +from lldbsuite.test import darwin_log + + +class TestDarwinLogFilterMatchActivity(darwin_log.DarwinLogTestBase): + + mydir = lldbtest.TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + super(TestDarwinLogFilterMatchActivity, self).setUp() + + # Source filename. + self.source = 'main.c' + + # Output filename. + self.exe_name = self.getBuildArtifact("a.out") + self.d = {'C_SOURCES': self.source, 'EXE': self.exe_name} + + # Locate breakpoint. + self.line = lldbtest.line_number(self.source, '// break here') + + def tearDown(self): + # Shut down the process if it's still running. + if self.child: + self.runCmd('process kill') + self.expect_prompt() + self.runCmd('quit') + + # Let parent clean up + super(TestDarwinLogFilterMatchActivity, self).tearDown() + + # ========================================================================== + # activity filter tests + # ========================================================================== + + @decorators.skipUnlessDarwin + def test_filter_accept_activity_match(self): + """Test that fall-through reject, accept match activity works.""" + self.do_test( + ["--no-match-accepts false", + "--filter \"accept activity match child-activity\""] + ) + + # We should only see the second log message as we only accept + # that activity. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + def test_filter_reject_activity_partial_match(self): + """Test that fall-through reject, accept match activity via partial match does not accept.""" + self.do_test( + ["--no-match-accepts false", + # Fully match second message. + "--filter \"accept activity match child-activity\"", + "--filter \"accept activity match parent-\""] # Only partially match first message. + ) + + # We should only see the second log message as we only accept + # that activity. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + def test_filter_reject_activity_full_match(self): + """Test that fall-through accept, reject match activity works.""" + self.do_test( + ["--no-match-accepts true", + "--filter \"reject activity match parent-activity\""] + ) + + # We should only see the second log message as we rejected the first + # via activity rejection. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + def test_filter_accept_activity_second_rule(self): + """Test that fall-through reject, accept regex activity on second rule works.""" + self.do_test( + ["--no-match-accepts false", + "--filter \"accept activity match non-existent\"", + "--filter \"accept activity match child-activity\"" + ] + ) + + # We should only see the second message since we reject by default, + # the first filter doesn't match any, and the second filter matches + # the activity of the second log message. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/activity/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/activity/main.c new file mode 100644 index 00000000000..fbe5106b5db --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/activity/main.c @@ -0,0 +1,42 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <os/activity.h> +#include <os/log.h> +#include <stdio.h> + +#include "../../../common/darwin_log_common.h" + +int main(int argc, char** argv) +{ + os_log_t logger_sub1 = os_log_create("org.llvm.lldb.test.sub1", "cat1"); + os_log_t logger_sub2 = os_log_create("org.llvm.lldb.test.sub2", "cat2"); + if (!logger_sub1 || !logger_sub2) + return 1; + + // Note we cannot use the os_log() line as the breakpoint because, as of + // the initial writing of this test, we get multiple breakpoints for that + // line, which confuses the pexpect test logic. + printf("About to log\n"); // break here + os_activity_t parent_activity = os_activity_create("parent-activity", + OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); + os_activity_apply(parent_activity, ^{ + os_log(logger_sub1, "source-log-sub1-cat1"); + os_activity_t child_activity = os_activity_create("child-activity", + OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); + os_activity_apply(child_activity, ^{ + os_log(logger_sub2, "source-log-sub2-cat2"); + }); + }); + + // Sleep, as the darwin log reporting doesn't always happen until a bit + // later. We need the message to come out before the process terminates. + sleep(FINAL_WAIT_SECONDS); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/category/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/category/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/category/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/category/TestDarwinLogFilterMatchCategory.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/category/TestDarwinLogFilterMatchCategory.py new file mode 100644 index 00000000000..f65b6fc55a9 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/category/TestDarwinLogFilterMatchCategory.py @@ -0,0 +1,124 @@ +""" +Test basic DarwinLog functionality provided by the StructuredDataDarwinLog +plugin. + +These tests are currently only supported when running against Darwin +targets. +""" + + +import lldb + +from lldbsuite.test import decorators +from lldbsuite.test import lldbtest +from lldbsuite.test import darwin_log + + +class TestDarwinLogFilterMatchCategory(darwin_log.DarwinLogTestBase): + + mydir = lldbtest.TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + super(TestDarwinLogFilterMatchCategory, self).setUp() + + # Source filename. + self.source = 'main.c' + + # Output filename. + self.exe_name = self.getBuildArtifact("a.out") + self.d = {'C_SOURCES': self.source, 'EXE': self.exe_name} + + # Locate breakpoint. + self.line = lldbtest.line_number(self.source, '// break here') + + def tearDown(self): + # Shut down the process if it's still running. + if self.child: + self.runCmd('process kill') + self.expect_prompt() + self.runCmd('quit') + + # Let parent clean up + super(TestDarwinLogFilterMatchCategory, self).tearDown() + + # ========================================================================== + # category filter tests + # ========================================================================== + + @decorators.skipUnlessDarwin + def test_filter_accept_category_full_match(self): + """Test that fall-through reject, accept match single category works.""" + self.do_test( + ["--no-match-accepts false", + "--filter \"accept category match cat2\""] + ) + + # We should only see the second log message as we only accept + # that category. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + def test_filter_reject_category_partial_match(self): + """Test that fall-through reject, accept regex category via partial match works.""" + self.do_test( + ["--no-match-accepts false", + # Fully match the second message. + "--filter \"accept category match cat2\"", + "--filter \"accept category match at1\""] # Only partially match first message. Should not show up. + ) + + # We should only see the second log message as we only accept + # that category. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + def test_filter_reject_category_full_match(self): + """Test that fall-through accept, reject match category works.""" + self.do_test( + ["--no-match-accepts true", + "--filter \"reject category match cat1\""] + ) + + # We should only see the second log message as we rejected the first + # via category rejection. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + def test_filter_accept_category_second_rule(self): + """Test that fall-through reject, accept match category on second rule works.""" + self.do_test( + ["--no-match-accepts false", + "--filter \"accept category match non-existent\"", + "--filter \"accept category match cat2\"" + ] + ) + + # We should only see the second message since we reject by default, + # the first filter doesn't match any, and the second filter matches + # the category of the second log message. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/category/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/category/main.c new file mode 100644 index 00000000000..fbe5106b5db --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/category/main.c @@ -0,0 +1,42 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <os/activity.h> +#include <os/log.h> +#include <stdio.h> + +#include "../../../common/darwin_log_common.h" + +int main(int argc, char** argv) +{ + os_log_t logger_sub1 = os_log_create("org.llvm.lldb.test.sub1", "cat1"); + os_log_t logger_sub2 = os_log_create("org.llvm.lldb.test.sub2", "cat2"); + if (!logger_sub1 || !logger_sub2) + return 1; + + // Note we cannot use the os_log() line as the breakpoint because, as of + // the initial writing of this test, we get multiple breakpoints for that + // line, which confuses the pexpect test logic. + printf("About to log\n"); // break here + os_activity_t parent_activity = os_activity_create("parent-activity", + OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); + os_activity_apply(parent_activity, ^{ + os_log(logger_sub1, "source-log-sub1-cat1"); + os_activity_t child_activity = os_activity_create("child-activity", + OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); + os_activity_apply(child_activity, ^{ + os_log(logger_sub2, "source-log-sub2-cat2"); + }); + }); + + // Sleep, as the darwin log reporting doesn't always happen until a bit + // later. We need the message to come out before the process terminates. + sleep(FINAL_WAIT_SECONDS); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/message/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/message/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/message/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/message/TestDarwinLogFilterMatchMessage.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/message/TestDarwinLogFilterMatchMessage.py new file mode 100644 index 00000000000..0d0378aee7b --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/message/TestDarwinLogFilterMatchMessage.py @@ -0,0 +1,145 @@ +""" +Test basic DarwinLog functionality provided by the StructuredDataDarwinLog +plugin. + +These tests are currently only supported when running against Darwin +targets. +""" + + +import lldb +import re + +from lldbsuite.test import decorators +from lldbsuite.test import lldbtest +from lldbsuite.test import darwin_log + + +class TestDarwinLogFilterMatchMessage(darwin_log.DarwinLogTestBase): + + mydir = lldbtest.TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + super(TestDarwinLogFilterMatchMessage, self).setUp() + + # Source filename. + self.source = 'main.c' + + # Output filename. + self.exe_name = self.getBuildArtifact("a.out") + self.d = {'C_SOURCES': self.source, 'EXE': self.exe_name} + + # Locate breakpoint. + self.line = lldbtest.line_number(self.source, '// break here') + + self.strict_sources = True + + # Turn on process monitor logging while we work out issues. + self.enable_process_monitor_logging = True + + def tearDown(self): + # Shut down the process if it's still running. + if self.child: + self.runCmd('process kill') + self.expect_prompt() + self.runCmd('quit') + + # Let parent clean up + super(TestDarwinLogFilterMatchMessage, self).tearDown() + + # ========================================================================== + # category filter tests + # ========================================================================== + + EXPECT_REGEXES = [ + re.compile(r"log message ([^-]+)-(\S+)"), + re.compile(r"exited with status") + ] + + @decorators.skipUnlessDarwin + @decorators.expectedFailureAll(oslist=["macosx"], + bugnumber="llvm.org/pr30299") + def test_filter_accept_message_full_match(self): + """Test that fall-through reject, accept match whole message works.""" + self.do_test( + ["--no-match-accepts false", + "--filter \"accept message match log message sub2-cat2\""], + expect_regexes=self.EXPECT_REGEXES + ) + + # We should only see the second log message as we only accept + # that message contents. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + @decorators.expectedFailureAll(oslist=["macosx"], + bugnumber="llvm.org/pr30299") + def test_filter_no_accept_message_partial_match(self): + """Test that fall-through reject, match message via partial content match doesn't accept.""" + self.do_test( + ["--no-match-accepts false", + "--filter \"accept message match log message sub2-cat2\"", + "--filter \"accept message match sub1-cat1\""], + expect_regexes=self.EXPECT_REGEXES + ) + + # We should only see the second log message as the partial match on + # the first message should not pass. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + @decorators.expectedFailureAll(oslist=["macosx"], + bugnumber="llvm.org/pr30299") + def test_filter_reject_category_full_match(self): + """Test that fall-through accept, reject match message works.""" + self.do_test( + ["--no-match-accepts true", + "--filter \"reject message match log message sub1-cat1\""], + expect_regexes=self.EXPECT_REGEXES + ) + + # We should only see the second log message as we rejected the first + # via message contents rejection. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + @decorators.expectedFailureAll(oslist=["macosx"], + bugnumber="llvm.org/pr30299") + def test_filter_accept_category_second_rule(self): + """Test that fall-through reject, accept match category on second rule works.""" + self.do_test( + ["--no-match-accepts false", + "--filter \"accept message match non-existent\"", + "--filter \"accept message match log message sub2-cat2\""], + expect_regexes=self.EXPECT_REGEXES + ) + + # We should only see the second message since we reject by default, + # the first filter doesn't match any, and the second filter matches + # the category of the second log message. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/message/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/message/main.c new file mode 100644 index 00000000000..b4b26c158d3 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/message/main.c @@ -0,0 +1,34 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <os/activity.h> +#include <os/log.h> +#include <stdio.h> + +#include "../../../common/darwin_log_common.h" + +int main(int argc, char** argv) +{ + os_log_t logger_sub1 = os_log_create("org.llvm.lldb.test.sub1", "cat1"); + os_log_t logger_sub2 = os_log_create("org.llvm.lldb.test.sub2", "cat2"); + if (!logger_sub1 || !logger_sub2) + return 1; + + // Note we cannot use the os_log() line as the breakpoint because, as of + // the initial writing of this test, we get multiple breakpoints for that + // line, which confuses the pexpect test logic. + printf("About to log\n"); // break here + os_log(logger_sub1, "log message sub%d-cat%d", 1, 1); + os_log(logger_sub2, "log message sub%d-cat%d", 2, 2); + + // Sleep, as the darwin log reporting doesn't always happen until a bit + // later. We need the message to come out before the process terminates. + sleep(1); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/subsystem/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/subsystem/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/subsystem/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/subsystem/TestDarwinLogFilterMatchSubsystem.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/subsystem/TestDarwinLogFilterMatchSubsystem.py new file mode 100644 index 00000000000..6fd94fac0cb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/subsystem/TestDarwinLogFilterMatchSubsystem.py @@ -0,0 +1,124 @@ +""" +Test basic DarwinLog functionality provided by the StructuredDataDarwinLog +plugin. + +These tests are currently only supported when running against Darwin +targets. +""" + + +import lldb + +from lldbsuite.test import decorators +from lldbsuite.test import lldbtest +from lldbsuite.test import darwin_log + + +class TestDarwinLogFilterMatchSubsystem(darwin_log.DarwinLogTestBase): + + mydir = lldbtest.TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + super(TestDarwinLogFilterMatchSubsystem, self).setUp() + + # Source filename. + self.source = 'main.c' + + # Output filename. + self.exe_name = self.getBuildArtifact("a.out") + self.d = {'C_SOURCES': self.source, 'EXE': self.exe_name} + + # Locate breakpoint. + self.line = lldbtest.line_number(self.source, '// break here') + + def tearDown(self): + # Shut down the process if it's still running. + if self.child: + self.runCmd('process kill') + self.expect_prompt() + self.runCmd('quit') + + # Let parent clean up + super(TestDarwinLogFilterMatchSubsystem, self).tearDown() + + # ========================================================================== + # subsystem filter tests + # ========================================================================== + + @decorators.skipUnlessDarwin + def test_filter_accept_subsystem_full_match(self): + """Test that fall-through reject, accept match single subsystem works.""" + self.do_test( + ["--no-match-accepts false", + "--filter \"accept subsystem match org.llvm.lldb.test.sub2\""] + ) + + # We should only see the second log message as we only accept + # that subsystem. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 0) and ( + self.child.match.group(1) == "sub2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + def test_filter_reject_subsystem_partial_match(self): + """Test that fall-through reject, doesn't accept match subsystem via partial-match.""" + self.do_test( + ["--no-match-accepts false", + # Fully match second message subsystem. + "--filter \"accept subsystem match org.llvm.lldb.test.sub2\"", + "--filter \"accept subsystem match sub1\""] # Only partially match first subsystem. + ) + + # We should only see the second log message as we only accept + # that subsystem. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 0) and ( + self.child.match.group(1) == "sub2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + def test_filter_reject_subsystem_full_match(self): + """Test that fall-through accept, reject match subsystem works.""" + self.do_test( + ["--no-match-accepts true", + "--filter \"reject subsystem match org.llvm.lldb.test.sub1\""] + ) + + # We should only see the second log message as we rejected the first + # via subsystem rejection. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 0) and ( + self.child.match.group(1) == "sub2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + def test_filter_accept_subsystem_second_rule(self): + """Test that fall-through reject, accept match subsystem on second rule works.""" + self.do_test( + ["--no-match-accepts false", + "--filter \"accept subsystem match non-existent\"", + "--filter \"accept subsystem match org.llvm.lldb.test.sub2\"" + ] + ) + + # We should only see the second message since we reject by default, + # the first filter doesn't match any, and the second filter matches + # the subsystem of the second log message. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 0) and ( + self.child.match.group(1) == "sub2"), + "first log line should not be present, second log line " + "should be") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/subsystem/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/subsystem/main.c new file mode 100644 index 00000000000..fbe5106b5db --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/exact_match/subsystem/main.c @@ -0,0 +1,42 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <os/activity.h> +#include <os/log.h> +#include <stdio.h> + +#include "../../../common/darwin_log_common.h" + +int main(int argc, char** argv) +{ + os_log_t logger_sub1 = os_log_create("org.llvm.lldb.test.sub1", "cat1"); + os_log_t logger_sub2 = os_log_create("org.llvm.lldb.test.sub2", "cat2"); + if (!logger_sub1 || !logger_sub2) + return 1; + + // Note we cannot use the os_log() line as the breakpoint because, as of + // the initial writing of this test, we get multiple breakpoints for that + // line, which confuses the pexpect test logic. + printf("About to log\n"); // break here + os_activity_t parent_activity = os_activity_create("parent-activity", + OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); + os_activity_apply(parent_activity, ^{ + os_log(logger_sub1, "source-log-sub1-cat1"); + os_activity_t child_activity = os_activity_create("child-activity", + OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); + os_activity_apply(child_activity, ^{ + os_log(logger_sub2, "source-log-sub2-cat2"); + }); + }); + + // Sleep, as the darwin log reporting doesn't always happen until a bit + // later. We need the message to come out before the process terminates. + sleep(FINAL_WAIT_SECONDS); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/activity-chain/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/activity-chain/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/activity-chain/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/activity-chain/TestDarwinLogFilterRegexActivityChain.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/activity-chain/TestDarwinLogFilterRegexActivityChain.py new file mode 100644 index 00000000000..bec5a955f30 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/activity-chain/TestDarwinLogFilterRegexActivityChain.py @@ -0,0 +1,135 @@ +""" +Test basic DarwinLog functionality provided by the StructuredDataDarwinLog +plugin. + +These tests are currently only supported when running against Darwin +targets. +""" + + +import lldb + +from lldbsuite.test import decorators +from lldbsuite.test import lldbtest +from lldbsuite.test import darwin_log + + +class TestDarwinLogFilterRegexActivityChain(darwin_log.DarwinLogTestBase): + + mydir = lldbtest.TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + super(TestDarwinLogFilterRegexActivityChain, self).setUp() + + # Source filename. + self.source = 'main.c' + + # Output filename. + self.exe_name = self.getBuildArtifact("a.out") + self.d = {'C_SOURCES': self.source, 'EXE': self.exe_name} + + # Locate breakpoint. + self.line = lldbtest.line_number(self.source, '// break here') + + def tearDown(self): + # Shut down the process if it's still running. + if self.child: + self.runCmd('process kill') + self.expect_prompt() + self.runCmd('quit') + + # Let parent clean up + super(TestDarwinLogFilterRegexActivityChain, self).tearDown() + + # ========================================================================== + # activity-chain filter tests + # ========================================================================== + + @decorators.skipUnlessDarwin + def test_filter_accept_activity_chain_full_match(self): + """Test that fall-through reject, accept full-match activity chain works.""" + self.do_test( + ["--no-match-accepts false", + "--filter \"accept activity-chain regex " + "parent-activity:child-activity\""]) + + # We should only see the second log message as we only accept + # that activity. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + def test_filter_accept_activity_chain_partial_match(self): + """Test that fall-through reject, accept activity-chain via partial match works.""" + self.do_test( + ["--no-match-accepts false", + "--filter \"accept activity-chain regex :child-activity\""]) + + # We should only see the second log message as we only accept + # that activity. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + def test_filter_reject_activity_chain_full_match(self): + """Test that fall-through accept, reject activity-chain works.""" + self.do_test( + ["--no-match-accepts true", + "--filter \"reject activity-chain regex parent-activity:child-..tivity\""]) + + # We should only see the second log message as we rejected the first + # via activity-chain rejection. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat1"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + def test_filter_reject_activity_chain_partial_match(self): + """Test that fall-through accept, reject activity-chain by partial match works.""" + self.do_test( + ["--no-match-accepts true", + "--filter \"reject activity-chain regex ^p[^:]+$\""]) + + # We should only see the second log message as we rejected the first + # via activity-chain rejection. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + def test_filter_accept_activity_chain_second_rule(self): + """Test that fall-through reject, accept activity-chain on second rule works.""" + self.do_test( + ["--no-match-accepts false", + "--filter \"accept activity-chain regex non-existent\"", + "--filter \"accept activity-chain regex child-activity\""]) + + # We should only see the second message since we reject by default, + # the first filter doesn't match any, and the second filter matches + # the activity-chain of the second log message. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/activity-chain/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/activity-chain/main.c new file mode 100644 index 00000000000..fbe5106b5db --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/activity-chain/main.c @@ -0,0 +1,42 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <os/activity.h> +#include <os/log.h> +#include <stdio.h> + +#include "../../../common/darwin_log_common.h" + +int main(int argc, char** argv) +{ + os_log_t logger_sub1 = os_log_create("org.llvm.lldb.test.sub1", "cat1"); + os_log_t logger_sub2 = os_log_create("org.llvm.lldb.test.sub2", "cat2"); + if (!logger_sub1 || !logger_sub2) + return 1; + + // Note we cannot use the os_log() line as the breakpoint because, as of + // the initial writing of this test, we get multiple breakpoints for that + // line, which confuses the pexpect test logic. + printf("About to log\n"); // break here + os_activity_t parent_activity = os_activity_create("parent-activity", + OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); + os_activity_apply(parent_activity, ^{ + os_log(logger_sub1, "source-log-sub1-cat1"); + os_activity_t child_activity = os_activity_create("child-activity", + OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); + os_activity_apply(child_activity, ^{ + os_log(logger_sub2, "source-log-sub2-cat2"); + }); + }); + + // Sleep, as the darwin log reporting doesn't always happen until a bit + // later. We need the message to come out before the process terminates. + sleep(FINAL_WAIT_SECONDS); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/activity/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/activity/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/activity/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/activity/TestDarwinLogFilterRegexActivity.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/activity/TestDarwinLogFilterRegexActivity.py new file mode 100644 index 00000000000..4a4c6a21209 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/activity/TestDarwinLogFilterRegexActivity.py @@ -0,0 +1,140 @@ +""" +Test basic DarwinLog functionality provided by the StructuredDataDarwinLog +plugin. + +These tests are currently only supported when running against Darwin +targets. +""" + + +import lldb + +from lldbsuite.test import decorators +from lldbsuite.test import lldbtest +from lldbsuite.test import darwin_log + + +class TestDarwinLogFilterRegexActivity(darwin_log.DarwinLogTestBase): + + mydir = lldbtest.TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + super(TestDarwinLogFilterRegexActivity, self).setUp() + + # Source filename. + self.source = 'main.c' + + # Output filename. + self.exe_name = self.getBuildArtifact("a.out") + self.d = {'C_SOURCES': self.source, 'EXE': self.exe_name} + + # Locate breakpoint. + self.line = lldbtest.line_number(self.source, '// break here') + + def tearDown(self): + # Shut down the process if it's still running. + if self.child: + self.runCmd('process kill') + self.expect_prompt() + self.runCmd('quit') + + # Let parent clean up + super(TestDarwinLogFilterRegexActivity, self).tearDown() + + # ========================================================================== + # activity filter tests + # ========================================================================== + + @decorators.skipUnlessDarwin + def test_filter_accept_activity_full_match(self): + """Test that fall-through reject, accept regex full-match activity works.""" + self.do_test( + ["--no-match-accepts false", + "--filter \"accept activity regex child-activity\""] + ) + + # We should only see the second log message as we only accept + # that activity. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + def test_filter_accept_activity_partial_match(self): + """Test that fall-through reject, regex accept activity via partial match works.""" + self.do_test( + ["--no-match-accepts false", + "--filter \"accept activity regex child-.*\""] + ) + + # We should only see the second log message as we only accept + # that activity. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + def test_filter_reject_activity_full_match(self): + """Test that fall-through accept, reject regex activity works.""" + self.do_test( + ["--no-match-accepts true", + "--filter \"reject activity regex parent-activity\""] + ) + + # We should only see the second log message as we rejected the first + # via activity rejection. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + def test_filter_reject_activity_partial_match(self): + """Test that fall-through accept, reject regex activity by partial match works.""" + self.do_test( + ["--no-match-accepts true", + "--filter \"reject activity regex p.+-activity\""] + ) + + # We should only see the second log message as we rejected the first + # via activity rejection. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + def test_filter_accept_activity_second_rule(self): + """Test that fall-through reject, accept regex activity on second rule works.""" + self.do_test( + ["--no-match-accepts false", + "--filter \"accept activity regex non-existent\"", + "--filter \"accept activity regex child-activity\"" + ] + ) + + # We should only see the second message since we reject by default, + # the first filter doesn't match any, and the second filter matches + # the activity of the second log message. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/activity/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/activity/main.c new file mode 100644 index 00000000000..fbe5106b5db --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/activity/main.c @@ -0,0 +1,42 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <os/activity.h> +#include <os/log.h> +#include <stdio.h> + +#include "../../../common/darwin_log_common.h" + +int main(int argc, char** argv) +{ + os_log_t logger_sub1 = os_log_create("org.llvm.lldb.test.sub1", "cat1"); + os_log_t logger_sub2 = os_log_create("org.llvm.lldb.test.sub2", "cat2"); + if (!logger_sub1 || !logger_sub2) + return 1; + + // Note we cannot use the os_log() line as the breakpoint because, as of + // the initial writing of this test, we get multiple breakpoints for that + // line, which confuses the pexpect test logic. + printf("About to log\n"); // break here + os_activity_t parent_activity = os_activity_create("parent-activity", + OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); + os_activity_apply(parent_activity, ^{ + os_log(logger_sub1, "source-log-sub1-cat1"); + os_activity_t child_activity = os_activity_create("child-activity", + OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); + os_activity_apply(child_activity, ^{ + os_log(logger_sub2, "source-log-sub2-cat2"); + }); + }); + + // Sleep, as the darwin log reporting doesn't always happen until a bit + // later. We need the message to come out before the process terminates. + sleep(FINAL_WAIT_SECONDS); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/category/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/category/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/category/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/category/TestDarwinLogFilterRegexCategory.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/category/TestDarwinLogFilterRegexCategory.py new file mode 100644 index 00000000000..96336093a74 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/category/TestDarwinLogFilterRegexCategory.py @@ -0,0 +1,140 @@ +""" +Test basic DarwinLog functionality provided by the StructuredDataDarwinLog +plugin. + +These tests are currently only supported when running against Darwin +targets. +""" + + +import lldb + +from lldbsuite.test import decorators +from lldbsuite.test import lldbtest +from lldbsuite.test import darwin_log + + +class TestDarwinLogFilterRegexCategory(darwin_log.DarwinLogTestBase): + + mydir = lldbtest.TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + super(TestDarwinLogFilterRegexCategory, self).setUp() + + # Source filename. + self.source = 'main.c' + + # Output filename. + self.exe_name = self.getBuildArtifact("a.out") + self.d = {'C_SOURCES': self.source, 'EXE': self.exe_name} + + # Locate breakpoint. + self.line = lldbtest.line_number(self.source, '// break here') + + def tearDown(self): + # Shut down the process if it's still running. + if self.child: + self.runCmd('process kill') + self.expect_prompt() + self.runCmd('quit') + + # Let parent clean up + super(TestDarwinLogFilterRegexCategory, self).tearDown() + + # ========================================================================== + # category filter tests + # ========================================================================== + + @decorators.skipUnlessDarwin + def test_filter_accept_category_full_match(self): + """Test that fall-through reject, accept regex single category works.""" + self.do_test( + ["--no-match-accepts false", + "--filter \"accept category regex cat2\""] + ) + + # We should only see the second log message as we only accept + # that category. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + def test_filter_accept_category_partial_match(self): + """Test that fall-through reject, accept regex category via partial match works.""" + self.do_test( + ["--no-match-accepts false", + "--filter \"accept category regex .+2\""] + ) + + # We should only see the second log message as we only accept + # that category. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + def test_filter_reject_category_full_match(self): + """Test that fall-through accept, reject regex category works.""" + self.do_test( + ["--no-match-accepts true", + "--filter \"reject category regex cat1\""] + ) + + # We should only see the second log message as we rejected the first + # via category rejection. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + def test_filter_reject_category_partial_match(self): + """Test that fall-through accept, reject regex category by partial match works.""" + self.do_test( + ["--no-match-accepts true", + "--filter \"reject category regex t1\""] + ) + + # We should only see the second log message as we rejected the first + # via category rejection. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + def test_filter_accept_category_second_rule(self): + """Test that fall-through reject, accept regex category on second rule works.""" + self.do_test( + ["--no-match-accepts false", + "--filter \"accept category regex non-existent\"", + "--filter \"accept category regex cat2\"" + ] + ) + + # We should only see the second message since we reject by default, + # the first filter doesn't match any, and the second filter matches + # the category of the second log message. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/category/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/category/main.c new file mode 100644 index 00000000000..fbe5106b5db --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/category/main.c @@ -0,0 +1,42 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <os/activity.h> +#include <os/log.h> +#include <stdio.h> + +#include "../../../common/darwin_log_common.h" + +int main(int argc, char** argv) +{ + os_log_t logger_sub1 = os_log_create("org.llvm.lldb.test.sub1", "cat1"); + os_log_t logger_sub2 = os_log_create("org.llvm.lldb.test.sub2", "cat2"); + if (!logger_sub1 || !logger_sub2) + return 1; + + // Note we cannot use the os_log() line as the breakpoint because, as of + // the initial writing of this test, we get multiple breakpoints for that + // line, which confuses the pexpect test logic. + printf("About to log\n"); // break here + os_activity_t parent_activity = os_activity_create("parent-activity", + OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); + os_activity_apply(parent_activity, ^{ + os_log(logger_sub1, "source-log-sub1-cat1"); + os_activity_t child_activity = os_activity_create("child-activity", + OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); + os_activity_apply(child_activity, ^{ + os_log(logger_sub2, "source-log-sub2-cat2"); + }); + }); + + // Sleep, as the darwin log reporting doesn't always happen until a bit + // later. We need the message to come out before the process terminates. + sleep(FINAL_WAIT_SECONDS); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/message/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/message/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/message/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/message/TestDarwinLogFilterRegexMessage.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/message/TestDarwinLogFilterRegexMessage.py new file mode 100644 index 00000000000..2cbdb4e3e80 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/message/TestDarwinLogFilterRegexMessage.py @@ -0,0 +1,126 @@ +""" +Test basic DarwinLog functionality provided by the StructuredDataDarwinLog +plugin. + +These tests are currently only supported when running against Darwin +targets. +""" + +# System imports + + +# LLDB imports +import lldb + +from lldbsuite.test import decorators +from lldbsuite.test import lldbtest +from lldbsuite.test import darwin_log + + +class TestDarwinLogFilterRegexMessage(darwin_log.DarwinLogEventBasedTestBase): + + mydir = lldbtest.TestBase.compute_mydir(__file__) + + @decorators.skipUnlessDarwin + @decorators.expectedFailureAll(oslist=["macosx"], + bugnumber="llvm.org/pr30299") + def test_filter_accept_message_full_match(self): + """Test that fall-through reject, accept regex whole message works.""" + log_entries = self.do_test( + ["--no-match-accepts false", + # Note below, the four '\' characters are to get us two + # backslashes over on the gdb-remote side, which then + # becomes one as the cstr interprets it as an escape + # sequence. This needs to be rationalized. Initially I + # supported std::regex ECMAScript, which has the + # [[:digit:]] character classes and such. That was much + # more tenable. The backslashes have to travel through + # so many layers of escaping. (And note if you take + # off the Python raw string marker here, you need to put + # in 8 backslashes to go to two on the remote side.) + r'--filter "accept message regex log message sub2-cat\\\\d+"']) + + # We should have received at least one log entry. + self.assertIsNotNone(log_entries, + "Log entry list should not be None.") + self.assertEqual(len(log_entries), 1, + "Should receive one log entry.") + self.assertRegexpMatches(log_entries[0]["message"], r"sub2-cat2", + "First os_log call should have been skipped.") + + @decorators.skipUnlessDarwin + @decorators.expectedFailureAll(oslist=["macosx"], + bugnumber="llvm.org/pr30299") + def test_filter_accept_message_partial_match(self): + """Test that fall-through reject, accept regex message via partial + match works.""" + log_entries = self.do_test( + ["--no-match-accepts false", + "--filter \"accept message regex [^-]+2\""]) + + # We should only see the second log message as we only accept + # that message contents. + self.assertIsNotNone(log_entries, + "Log entry list should not be None.") + self.assertEqual(len(log_entries), 1, + "Should receive one log entry.") + self.assertRegexpMatches(log_entries[0]["message"], r"sub2-cat2", + "First os_log call should have been skipped.") + + @decorators.skipUnlessDarwin + @decorators.expectedFailureAll(oslist=["macosx"], + bugnumber="llvm.org/pr30299") + def test_filter_reject_message_full_match(self): + """Test that fall-through accept, reject regex message works.""" + log_entries = self.do_test( + ["--no-match-accepts true", + "--filter \"reject message regex log message sub1-cat1\""]) + + # We should only see the second log message as we rejected the first + # via message contents rejection. + self.assertIsNotNone(log_entries, + "Log entry list should not be None.") + self.assertEqual(len(log_entries), 1, + "Should receive one log entry.") + self.assertRegexpMatches(log_entries[0]["message"], r"sub2-cat2", + "First os_log call should have been skipped.") + + @decorators.skipUnlessDarwin + @decorators.expectedFailureAll(oslist=["macosx"], + bugnumber="llvm.org/pr30299") + def test_filter_reject_message_partial_match(self): + """Test that fall-through accept, reject regex message by partial + match works.""" + log_entries = self.do_test( + ["--no-match-accepts true", + "--filter \"reject message regex t1\""]) + + # We should only see the second log message as we rejected the first + # via partial message contents rejection. + self.assertIsNotNone(log_entries, + "Log entry list should not be None.") + self.assertEqual(len(log_entries), 1, + "Should receive one log entry.") + self.assertRegexpMatches(log_entries[0]["message"], r"sub2-cat2", + "First os_log call should have been skipped.") + + @decorators.skipUnlessDarwin + @decorators.expectedFailureAll(oslist=["macosx"], + bugnumber="llvm.org/pr30299") + def test_filter_accept_message_second_rule(self): + """Test that fall-through reject, accept regex message on second rule + works.""" + log_entries = self.do_test( + ["--no-match-accepts false", + "--filter \"accept message regex non-existent\"", + "--filter \"accept message regex cat2\""]) + + # We should only see the second message since we reject by default, + # the first filter doesn't match any, and the second filter matches + # the message of the second log message. + self.assertIsNotNone(log_entries, + "Log entry list should not be None.") + self.assertEqual(len(log_entries), 1, + "Should receive one log entry.") + self.assertRegexpMatches(log_entries[0]["message"], r"sub2-cat2", + "First os_log call should have been skipped.") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/message/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/message/main.c new file mode 100644 index 00000000000..b0b43018746 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/message/main.c @@ -0,0 +1,34 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <os/activity.h> +#include <os/log.h> +#include <stdio.h> + +#include "../../../common/darwin_log_common.h" + +int main(int argc, char** argv) +{ + os_log_t logger_sub1 = os_log_create("org.llvm.lldb.test.sub1", "cat1"); + os_log_t logger_sub2 = os_log_create("org.llvm.lldb.test.sub2", "cat2"); + if (!logger_sub1 || !logger_sub2) + return 1; + + // Note we cannot use the os_log() line as the breakpoint because, as of + // the initial writing of this test, we get multiple breakpoints for that + // line, which confuses the pexpect test logic. + printf("About to log\n"); // break here + os_log(logger_sub1, "log message sub%d-cat%d", 1, 1); + os_log(logger_sub2, "log message sub%d-cat%d", 2, 2); + + // Sleep, as the darwin log reporting doesn't always happen until a bit + // later. We need the message to come out before the process terminates. + sleep(FINAL_WAIT_SECONDS); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/subsystem/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/subsystem/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/subsystem/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/subsystem/TestDarwinLogFilterRegexSubsystem.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/subsystem/TestDarwinLogFilterRegexSubsystem.py new file mode 100644 index 00000000000..c5c4e98a8ee --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/subsystem/TestDarwinLogFilterRegexSubsystem.py @@ -0,0 +1,157 @@ +""" +Test basic DarwinLog functionality provided by the StructuredDataDarwinLog +plugin. + +These tests are currently only supported when running against Darwin +targets. +""" + + +import lldb + +from lldbsuite.test import decorators +from lldbsuite.test import lldbtest +from lldbsuite.test import darwin_log + + +class TestDarwinLogFilterRegexSubsystem(darwin_log.DarwinLogTestBase): + + mydir = lldbtest.TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + super(TestDarwinLogFilterRegexSubsystem, self).setUp() + + # Source filename. + self.source = 'main.c' + + # Output filename. + self.exe_name = self.getBuildArtifact("a.out") + self.d = {'C_SOURCES': self.source, 'EXE': self.exe_name} + + # Locate breakpoint. + self.line = lldbtest.line_number(self.source, '// break here') + + def tearDown(self): + # Shut down the process if it's still running. + if self.child: + self.runCmd('process kill') + self.expect_prompt() + self.runCmd('quit') + + # Let parent clean up + super(TestDarwinLogFilterRegexSubsystem, self).tearDown() + + # ========================================================================== + # basic filter tests + # ========================================================================== + + @decorators.skipUnlessDarwin + def test_fallthrough_reject(self): + """Test that a single fall-through reject regex rule rejects all logging.""" + self.do_test( + ["--no-match-accepts false"] + ) + + # We should not match any log lines. + self.assertIsNotNone(self.child.match) + self.assertFalse((len(self.child.match.groups()) > 0) and + (self.child.match.group(1) in ["sub1", "sub2"]), + "log line should not have been received") + + # ========================================================================== + # subsystem filter tests + # ========================================================================== + + @decorators.skipUnlessDarwin + def test_filter_accept_subsystem_full_match(self): + """Test that fall-through reject, accept regex single subsystem works.""" + self.do_test( + ["--no-match-accepts false", + "--filter \"accept subsystem regex org.llvm.lldb.test.sub2\""] + ) + + # We should only see the second log message as we only accept + # that subsystem. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 0) and ( + self.child.match.group(1) == "sub2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + def test_filter_accept_subsystem_partial_match(self): + """Test that fall-through reject, accept regex subsystem via partial-match works.""" + self.do_test( + ["--no-match-accepts false", + "--filter \"accept subsystem regex org.llvm.+.sub2\""] + ) + + # We should only see the second log message as we only accept + # that subsystem. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 0) and ( + self.child.match.group(1) == "sub2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + def test_filter_reject_subsystem_full_match(self): + """Test that fall-through accept, reject regex subsystem works.""" + self.do_test( + ["--no-match-accepts true", + "--filter \"reject subsystem regex org.llvm.lldb.test.sub1\""] + ) + + # We should only see the second log message as we rejected the first + # via subsystem rejection. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 0) and ( + self.child.match.group(1) == "sub2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + def test_filter_reject_subsystem_partial_match(self): + """Test that fall-through accept, reject regex subsystem by partial match works.""" + self.do_test( + ["--no-match-accepts true", + "--filter \"reject subsystem regex org.*sub1\""] + ) + + # We should only see the second log message as we rejected the first + # via subsystem rejection. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 0) and ( + self.child.match.group(1) == "sub2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + def test_filter_accept_subsystem_second_rule(self): + """Test that fall-through reject, accept regex subsystem on second rule works.""" + self.do_test( + ["--no-match-accepts false", + "--filter \"accept subsystem regex non-existent\"", + "--filter \"accept subsystem regex org.llvm.lldb.test.sub2\"" + ] + ) + + # We should only see the second message since we reject by default, + # the first filter doesn't match any, and the second filter matches + # the subsystem of the second log message. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 0) and ( + self.child.match.group(1) == "sub2"), + "first log line should not be present, second log line " + "should be") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/subsystem/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/subsystem/main.c new file mode 100644 index 00000000000..fbe5106b5db --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/filter/regex/subsystem/main.c @@ -0,0 +1,42 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <os/activity.h> +#include <os/log.h> +#include <stdio.h> + +#include "../../../common/darwin_log_common.h" + +int main(int argc, char** argv) +{ + os_log_t logger_sub1 = os_log_create("org.llvm.lldb.test.sub1", "cat1"); + os_log_t logger_sub2 = os_log_create("org.llvm.lldb.test.sub2", "cat2"); + if (!logger_sub1 || !logger_sub2) + return 1; + + // Note we cannot use the os_log() line as the breakpoint because, as of + // the initial writing of this test, we get multiple breakpoints for that + // line, which confuses the pexpect test logic. + printf("About to log\n"); // break here + os_activity_t parent_activity = os_activity_create("parent-activity", + OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); + os_activity_apply(parent_activity, ^{ + os_log(logger_sub1, "source-log-sub1-cat1"); + os_activity_t child_activity = os_activity_create("child-activity", + OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); + os_activity_apply(child_activity, ^{ + os_log(logger_sub2, "source-log-sub2-cat2"); + }); + }); + + // Sleep, as the darwin log reporting doesn't always happen until a bit + // later. We need the message to come out before the process terminates. + sleep(FINAL_WAIT_SECONDS); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/format/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/format/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/format/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/format/TestDarwinLogMessageFormat.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/format/TestDarwinLogMessageFormat.py new file mode 100644 index 00000000000..687340e5fd3 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/format/TestDarwinLogMessageFormat.py @@ -0,0 +1,187 @@ +""" +Test DarwinLog log message formatting options provided by the +StructuredDataDarwinLog plugin. + +These tests are currently only supported when running against Darwin +targets. +""" + + +import lldb +import re + +from lldbsuite.test import decorators +from lldbsuite.test import lldbtest +from lldbsuite.test import darwin_log + + +class TestDarwinLogMessageFormat(darwin_log.DarwinLogTestBase): + + mydir = lldbtest.TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + super(TestDarwinLogMessageFormat, self).setUp() + + # Source filename. + self.source = 'main.c' + + # Output filename. + self.exe_name = self.getBuildArtifact("a.out") + self.d = {'C_SOURCES': self.source, 'EXE': self.exe_name} + + # Locate breakpoint. + self.line = lldbtest.line_number(self.source, '// break here') + + def tearDown(self): + # Shut down the process if it's still running. + if self.child: + self.runCmd('process kill') + self.expect_prompt() + self.runCmd('quit') + + # Let parent clean up + super(TestDarwinLogMessageFormat, self).tearDown() + + # ========================================================================== + # Test settings around log message formatting + # ========================================================================== + + REGEXES = [ + re.compile(r"\[([^]]+)\] This is the log message."), # Match log + # with header. + re.compile(r"This is the log message."), # Match no-header content. + re.compile(r"exited with status") # Fallback if no log emitted. + ] + + @decorators.skipUnlessDarwin + def test_display_without_header_works(self): + """Test that turning off log message headers works as advertised.""" + self.do_test([], expect_regexes=self.REGEXES) + + # We should not match the first pattern as we shouldn't have header + # content. + self.assertIsNotNone(self.child.match) + self.assertFalse((len(self.child.match.groups()) > 0) and + (self.child.match.group(1) != ""), + "we should not have seen a header") + + @decorators.skipUnlessDarwin + def test_display_with_header_works(self): + """Test that displaying any header works.""" + self.do_test( + ["--timestamp-relative", "--subsystem", "--category", + "--activity-chain"], + expect_regexes=self.REGEXES, + settings_commands=[ + "display-header true" + ]) + + # We should match the first pattern as we should have header + # content. + self.assertIsNotNone(self.child.match) + self.assertTrue((len(self.child.match.groups()) > 0) and + (self.child.match.group(1) != ""), + "we should have printed a header") + + def assert_header_contains_timestamp(self, header): + fields = header.split(',') + self.assertGreater(len(fields), 0, + "there should have been header content present") + self.assertRegexpMatches(fields[0], + r"^\d+:\d{2}:\d{2}.\d{9}$", + "time field should match expected format") + + @decorators.skipUnlessDarwin + def test_header_timefield_only_works(self): + """Test that displaying a header with only the timestamp works.""" + self.do_test(["--timestamp-relative"], expect_regexes=self.REGEXES) + + # We should match the first pattern as we should have header + # content. + self.assertIsNotNone(self.child.match) + self.assertTrue((len(self.child.match.groups()) > 0) and + (self.child.match.group(1) != ""), + "we should have printed a header") + header = self.child.match.group(1) + self.assertEqual(len(header.split(',')), 1, + "there should only be one header field") + self.assert_header_contains_timestamp(header) + + @decorators.skipUnlessDarwin + def test_header_subsystem_only_works(self): + """Test that displaying a header with only the subsystem works.""" + self.do_test(["--subsystem"], expect_regexes=self.REGEXES) + + # We should match the first pattern as we should have header + # content. + self.assertIsNotNone(self.child.match) + self.assertTrue((len(self.child.match.groups()) > 0) and + (self.child.match.group(1) != ""), + "we should have printed a header") + header = self.child.match.group(1) + self.assertEqual(len(header.split(',')), 1, + "there should only be one header field") + self.assertEquals(header, + "subsystem=org.llvm.lldb.test.sub1") + + @decorators.skipUnlessDarwin + def test_header_category_only_works(self): + """Test that displaying a header with only the category works.""" + self.do_test(["--category"], expect_regexes=self.REGEXES) + + # We should match the first pattern as we should have header + # content. + self.assertIsNotNone(self.child.match) + self.assertTrue((len(self.child.match.groups()) > 0) and + (self.child.match.group(1) != ""), + "we should have printed a header") + header = self.child.match.group(1) + self.assertEqual(len(header.split(',')), 1, + "there should only be one header field") + self.assertEquals(header, + "category=cat1") + + @decorators.skipUnlessDarwin + def test_header_activity_chain_only_works(self): + """Test that displaying a header with only the activity chain works.""" + self.do_test(["--activity-chain"], expect_regexes=self.REGEXES) + + # We should match the first pattern as we should have header + # content. + self.assertIsNotNone(self.child.match) + self.assertTrue((len(self.child.match.groups()) > 0) and + (self.child.match.group(1) != ""), + "we should have printed a header") + header = self.child.match.group(1) + self.assertEqual(len(header.split(',')), 1, + "there should only be one header field") + self.assertEquals(header, + "activity-chain=parent-activity:child-activity") + + # @decorators.skipUnlessDarwin + # def test_header_activity_no_chain_only_works(self): + # """Test that displaying a header with only the activity works.""" + # self.do_test( + # [], + # expect_regexes=self.REGEXES, + # settings_commands=[ + # "display-header true", + # "format-include-timestamp false", + # "format-include-activity true", + # "format-include-category false", + # "format-include-subsystem false", + # "display-activity-chain false" + # ]) + + # # We should match the first pattern as we should have header + # # content. + # self.assertIsNotNone(self.child.match) + # self.assertTrue((len(self.child.match.groups()) > 0) and + # (self.child.match.group(1) != ""), + # "we should have printed a header") + # header = self.child.match.group(1) + # self.assertEqual(len(header.split(',')), 1, + # "there should only be one header field") + # self.assertEquals(header, + # "activity=child-activity") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/format/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/format/main.c new file mode 100644 index 00000000000..889a4e97856 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/format/main.c @@ -0,0 +1,40 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <os/activity.h> +#include <os/log.h> +#include <stdio.h> + +#include "../common/darwin_log_common.h" + +int main(int argc, char** argv) +{ + os_log_t logger_sub1 = os_log_create("org.llvm.lldb.test.sub1", "cat1"); + if (!logger_sub1) + return 1; + + // Note we cannot use the os_log() line as the breakpoint because, as of + // the initial writing of this test, we get multiple breakpoints for that + // line, which confuses the pexpect test logic. + printf("About to log\n"); // break here + os_activity_t parent_activity = os_activity_create("parent-activity", + OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); + os_activity_apply(parent_activity, ^{ + os_activity_t child_activity = os_activity_create("child-activity", + OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); + os_activity_apply(child_activity, ^{ + os_log(logger_sub1, "This is the log message."); + }); + }); + + // Sleep, as the darwin log reporting doesn't always happen until a bit + // later. We need the message to come out before the process terminates. + sleep(FINAL_WAIT_SECONDS); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/source/debug/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/source/debug/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/source/debug/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/source/debug/TestDarwinLogSourceDebug.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/source/debug/TestDarwinLogSourceDebug.py new file mode 100644 index 00000000000..57a02766683 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/source/debug/TestDarwinLogSourceDebug.py @@ -0,0 +1,78 @@ +""" +Test DarwinLog "source include debug-level" functionality provided by the +StructuredDataDarwinLog plugin. + +These tests are currently only supported when running against Darwin +targets. +""" + + +import lldb + +from lldbsuite.test import decorators +from lldbsuite.test import lldbtest +from lldbsuite.test import darwin_log + + +class TestDarwinLogSourceDebug(darwin_log.DarwinLogTestBase): + + mydir = lldbtest.TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + super(TestDarwinLogSourceDebug, self).setUp() + + # Source filename. + self.source = 'main.c' + + # Output filename. + self.exe_name = self.getBuildArtifact("a.out") + self.d = {'C_SOURCES': self.source, 'EXE': self.exe_name} + + # Locate breakpoint. + self.line = lldbtest.line_number(self.source, '// break here') + + # Indicate we want strict-sources behavior. + self.strict_sources = True + + def tearDown(self): + # Shut down the process if it's still running. + if self.child: + self.runCmd('process kill') + self.expect_prompt() + self.runCmd('quit') + + # Let parent clean up + super(TestDarwinLogSourceDebug, self).tearDown() + + # ========================================================================== + # source include/exclude debug filter tests + # ========================================================================== + + @decorators.skipUnlessDarwin + def test_source_default_exclude_debug(self): + """Test that default excluding of debug-level log messages works.""" + self.do_test([]) + + # We should only see the second log message as the first is a + # debug-level message and we're not including debug-level messages. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + def test_source_explicitly_include_debug(self): + """Test that explicitly including debug-level log messages works.""" + self.do_test(["--debug"]) + + # We should only see the second log message as the first is a + # debug-level message and we're not including debug-level messages. + self.assertIsNotNone(self.child.match) + self.assertTrue((len(self.child.match.groups()) > 1) and + (self.child.match.group(2) == "cat1"), + "first log line should be present since we're " + "including debug-level log messages") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/source/debug/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/source/debug/main.c new file mode 100644 index 00000000000..b3af8cb3476 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/source/debug/main.c @@ -0,0 +1,33 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <os/log.h> +#include <stdio.h> + +#include "../../common/darwin_log_common.h" + +int main(int argc, char** argv) +{ + os_log_t logger_sub1 = os_log_create("org.llvm.lldb.test.sub1", "cat1"); + os_log_t logger_sub2 = os_log_create("org.llvm.lldb.test.sub2", "cat2"); + if (!logger_sub1 || !logger_sub2) + return 1; + + // Note we cannot use the os_log() line as the breakpoint because, as of + // the initial writing of this test, we get multiple breakpoints for that + // line, which confuses the pexpect test logic. + printf("About to log\n"); // break here + os_log_debug(logger_sub1, "source-log-sub1-cat1"); + os_log(logger_sub2, "source-log-sub2-cat2"); + + // Sleep, as the darwin log reporting doesn't always happen until a bit + // later. We need the message to come out before the process terminates. + sleep(FINAL_WAIT_SECONDS); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/source/info/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/source/info/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/source/info/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/source/info/TestDarwinLogSourceInfo.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/source/info/TestDarwinLogSourceInfo.py new file mode 100644 index 00000000000..5a3eafa2e8c --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/source/info/TestDarwinLogSourceInfo.py @@ -0,0 +1,81 @@ +""" +Test DarwinLog "source include info-level" functionality provided by the +StructuredDataDarwinLog plugin. + +These tests are currently only supported when running against Darwin +targets. +""" + + +import lldb + +from lldbsuite.test import decorators +from lldbsuite.test import lldbtest +from lldbsuite.test import darwin_log + + +class TestDarwinLogSourceInfo(darwin_log.DarwinLogTestBase): + + mydir = lldbtest.TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + super(TestDarwinLogSourceInfo, self).setUp() + + # Source filename. + self.source = 'main.c' + + # Output filename. + self.exe_name = self.getBuildArtifact("a.out") + self.d = {'C_SOURCES': self.source, 'EXE': self.exe_name} + + # Locate breakpoint. + self.line = lldbtest.line_number(self.source, '// break here') + + # Indicate we want strict-sources behavior. + self.strict_sources = True + + def tearDown(self): + # Shut down the process if it's still running. + if self.child: + self.runCmd('process kill') + self.expect_prompt() + self.runCmd('quit') + + # Let parent clean up + super(TestDarwinLogSourceInfo, self).tearDown() + + # ========================================================================== + # source include/exclude debug filter tests + # ========================================================================== + + @decorators.skipUnlessDarwin + @decorators.expectedFailureAll(bugnumber="rdar://27316264") + def test_source_exclude_info_level(self): + """Test that default excluding of info-level log messages works.""" + self.do_test([]) + + # We should only see the second log message as the first is an + # info-level message and we're not including debug-level messages. + self.assertIsNotNone(self.child.match) + self.assertTrue( + (len( + self.child.match.groups()) > 1) and ( + self.child.match.group(2) == "cat2"), + "first log line should not be present, second log line " + "should be") + + @decorators.skipUnlessDarwin + def test_source_include_info_level(self): + """Test that explicitly including info-level log messages works.""" + self.do_test( + ["--info"] + ) + + # We should only see the second log message as the first is a + # debug-level message and we're not including debug-level messages. + self.assertIsNotNone(self.child.match) + self.assertTrue((len(self.child.match.groups()) > 1) and + (self.child.match.group(2) == "cat1"), + "first log line should be present since we're " + "including info-level log messages") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/source/info/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/source/info/main.c new file mode 100644 index 00000000000..3472a9bc507 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/darwin_log/source/info/main.c @@ -0,0 +1,33 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <os/log.h> +#include <stdio.h> + +#include "../../common/darwin_log_common.h" + +int main(int argc, char** argv) +{ + os_log_t logger_sub1 = os_log_create("org.llvm.lldb.test.sub1", "cat1"); + os_log_t logger_sub2 = os_log_create("org.llvm.lldb.test.sub2", "cat2"); + if (!logger_sub1 || !logger_sub2) + return 1; + + // Note we cannot use the os_log() line as the breakpoint because, as of + // the initial writing of this test, we get multiple breakpoints for that + // line, which confuses the pexpect test logic. + printf("About to log\n"); // break here + os_log_info(logger_sub1, "source-log-sub1-cat1"); + os_log(logger_sub2, "source-log-sub2-cat2"); + + // Sleep, as the darwin log reporting doesn't always happen until a bit + // later. We need the message to come out before the process terminates. + sleep(FINAL_WAIT_SECONDS); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/.categories b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/.categories new file mode 100644 index 00000000000..fe1da0247c6 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/.categories @@ -0,0 +1 @@ +dataformatters diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/array_typedef/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/array_typedef/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/array_typedef/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/array_typedef/TestArrayTypedef.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/array_typedef/TestArrayTypedef.py new file mode 100644 index 00000000000..1f2914ad633 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/array_typedef/TestArrayTypedef.py @@ -0,0 +1,15 @@ +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class ArrayTypedefTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + def test_array_typedef(self): + self.build() + lldbutil.run_to_source_breakpoint(self, "// break here", + lldb.SBFileSpec("main.cpp", False)) + self.expect("expr str", substrs=['"abcd"']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/array_typedef/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/array_typedef/main.cpp new file mode 100644 index 00000000000..5c581b07ace --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/array_typedef/main.cpp @@ -0,0 +1,7 @@ +typedef char MCHAR; + +int main() { + MCHAR str[5] = "abcd"; + return 0; // break here +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/boolreference/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/boolreference/Makefile new file mode 100644 index 00000000000..876340159d9 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/boolreference/Makefile @@ -0,0 +1,8 @@ +OBJCXX_SOURCES := main.mm + +CFLAGS_EXTRAS := -w + + + +LD_EXTRAS := -framework Foundation +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/boolreference/TestFormattersBoolRefPtr.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/boolreference/TestFormattersBoolRefPtr.py new file mode 100644 index 00000000000..25ecdef5948 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/boolreference/TestFormattersBoolRefPtr.py @@ -0,0 +1,77 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class DataFormatterBoolRefPtr(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipUnlessDarwin + def test_boolrefptr_with_run_command(self): + """Test the formatters we use for BOOL& and BOOL* in Objective-C.""" + self.build() + self.boolrefptr_data_formatter_commands() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.mm', '// Set break point at this line.') + + def boolrefptr_data_formatter_commands(self): + """Test the formatters we use for BOOL& and BOOL* in Objective-C.""" + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.mm", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type synth clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + isiOS = (lldbplatformutil.getPlatform() == 'ios' or lldbplatformutil.getPlatform() == 'watchos') + + # Now check that we use the right summary for BOOL& + self.expect('frame variable yes_ref', + substrs=['YES']) + self.expect('frame variable no_ref', + substrs=['NO']) + if not(isiOS): + self.expect('frame variable unset_ref', substrs=['12']) + + # Now check that we use the right summary for BOOL* + self.expect('frame variable yes_ptr', + substrs=['YES']) + self.expect('frame variable no_ptr', + substrs=['NO']) + if not(isiOS): + self.expect('frame variable unset_ptr', substrs=['12']) + + # Now check that we use the right summary for BOOL + self.expect('frame variable yes', + substrs=['YES']) + self.expect('frame variable no', + substrs=['NO']) + if not(isiOS): + self.expect('frame variable unset', substrs=['12']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/boolreference/main.mm b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/boolreference/main.mm new file mode 100644 index 00000000000..e63aa32394e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/boolreference/main.mm @@ -0,0 +1,30 @@ +//===-- main.m ------------------------------------------------*- ObjC -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#import <Foundation/Foundation.h> + +int main (int argc, const char * argv[]) +{ + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + + BOOL yes = YES; + BOOL no = NO; + BOOL unset = 12; + + BOOL &yes_ref = yes; + BOOL &no_ref = no; + BOOL &unset_ref = unset; + + BOOL* yes_ptr = &yes; + BOOL* no_ptr = &no; + BOOL* unset_ptr = &unset; + + [pool drain];// Set break point at this line. + return 0; +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/compactvectors/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/compactvectors/Makefile new file mode 100644 index 00000000000..a537b994079 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/compactvectors/Makefile @@ -0,0 +1,4 @@ +CXX_SOURCES := main.cpp +LD_EXTRAS := -framework Accelerate +include Makefile.rules + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/compactvectors/TestCompactVectors.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/compactvectors/TestCompactVectors.py new file mode 100644 index 00000000000..17344283081 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/compactvectors/TestCompactVectors.py @@ -0,0 +1,60 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class CompactVectorsFormattingTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + @skipUnlessDarwin + def test_with_run_command(self): + """Test that that file and class static variables display correctly.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type summary clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.expect( + 'frame variable', + substrs=[ + '(vFloat) valueFL = (1.25, 0, 0.25, 0)', + '(int16_t [8]) valueI16 = (1, 0, 4, 0, 0, 1, 0, 4)', + '(int32_t [4]) valueI32 = (1, 0, 4, 0)', + '(vDouble) valueDL = (1.25, 2.25)', + '(vUInt8) valueU8 = (0x01, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)', + '(vUInt16) valueU16 = (1, 0, 4, 0, 0, 1, 0, 4)', + '(vUInt32) valueU32 = (1, 2, 3, 4)', + "(vSInt8) valueS8 = (1, 0, 4, 0, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0)", + '(vSInt16) valueS16 = (1, 0, 4, 0, 0, 1, 0, 4)', + '(vSInt32) valueS32 = (4, 3, 2, 1)', + '(vBool32) valueBool32 = (0, 1, 0, 1)']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/compactvectors/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/compactvectors/main.cpp new file mode 100644 index 00000000000..f31d2a1a18a --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/compactvectors/main.cpp @@ -0,0 +1,25 @@ + //===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <Accelerate/Accelerate.h> + +int main() +{ + vFloat valueFL = {1.25,0,0.25,0}; + vDouble valueDL = {1.25,2.25}; + int16_t valueI16[8] = {1,0,4,0,0,1,0,4}; + int32_t valueI32[4] = {1,0,4,0}; + vUInt8 valueU8 = {1,0,4,0,0,1,0,4}; + vUInt16 valueU16 = {1,0,4,0,0,1,0,4}; + vUInt32 valueU32 = {1,2,3,4}; + vSInt8 valueS8 = {1,0,4,0,0,1,0,4}; + vSInt16 valueS16 = {1,0,4,0,0,1,0,4}; + vSInt32 valueS32 = {4,3,2,1}; + vBool32 valueBool32 = {false,true,false,true}; + return 0; // Set break point at this line. +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-advanced/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-advanced/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-advanced/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py new file mode 100644 index 00000000000..246ebb3d4ae --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py @@ -0,0 +1,326 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class AdvDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + def test_with_run_command(self): + """Test that that file and class static variables display correctly.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd( + "settings set target.max-children-count 256", + check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.runCmd("type summary add --summary-string \"pippo\" \"i_am_cool\"") + + self.runCmd( + "type summary add --summary-string \"pluto\" -x \"i_am_cool[a-z]*\"") + + self.expect("frame variable cool_boy", + substrs=['pippo']) + + self.expect("frame variable cooler_boy", + substrs=['pluto']) + + self.runCmd("type summary delete i_am_cool") + + self.expect("frame variable cool_boy", + substrs=['pluto']) + + self.runCmd("type summary clear") + + self.runCmd( + "type summary add --summary-string \"${var[]}\" -x \"int \\[[0-9]\\]") + + self.expect("frame variable int_array", + substrs=['1,2,3,4,5']) + + # this will fail if we don't do [] as regex correctly + self.runCmd( + 'type summary add --summary-string "${var[].integer}" "i_am_cool[]') + + self.expect("frame variable cool_array", + substrs=['1,1,1,1,6']) + + self.runCmd("type summary clear") + + self.runCmd( + "type summary add --summary-string \"${var[1-0]%x}\" \"int\"") + + self.expect("frame variable iAmInt", + substrs=['01']) + + self.runCmd( + "type summary add --summary-string \"${var[0-1]%x}\" \"int\"") + + self.expect("frame variable iAmInt", + substrs=['01']) + + self.runCmd("type summary clear") + + self.runCmd("type summary add --summary-string \"${var[0-1]%x}\" int") + self.runCmd( + "type summary add --summary-string \"${var[0-31]%x}\" float") + + self.expect("frame variable *pointer", + substrs=['0x', + '2']) + + # check fix for <rdar://problem/11338654> LLDB crashes when using a + # "type summary" that uses bitfields with no format + self.runCmd("type summary add --summary-string \"${var[0-1]}\" int") + self.expect("frame variable iAmInt", + substrs=['9 1']) + + self.expect("frame variable cool_array[3].floating", + substrs=['0x']) + + self.runCmd( + "type summary add --summary-string \"low bits are ${*var[0-1]} tgt is ${*var}\" \"int *\"") + + self.expect("frame variable pointer", + substrs=['low bits are', + 'tgt is 6']) + + self.expect( + "frame variable int_array --summary-string \"${*var[0-1]}\"", + substrs=['3']) + + self.runCmd("type summary clear") + + self.runCmd( + 'type summary add --summary-string \"${var[0-1]}\" -x \"int \[[0-9]\]\"') + + self.expect("frame variable int_array", + substrs=['1,2']) + + self.runCmd( + 'type summary add --summary-string \"${var[0-1]}\" "int []"') + + self.expect("frame variable int_array", + substrs=['1,2']) + + # Test the patterns are matched in reverse-chronological order. + self.runCmd( + 'type summary add --summary-string \"${var[2-3]}\" "int []"') + + self.expect("frame variable int_array", + substrs=['3,4']) + + self.runCmd("type summary clear") + + self.runCmd("type summary add -c -x \"i_am_cool \[[0-9]\]\"") + self.runCmd("type summary add -c i_am_cool") + + self.expect("frame variable cool_array", + substrs=['[0]', + '[1]', + '[2]', + '[3]', + '[4]', + 'integer', + 'character', + 'floating']) + + self.runCmd( + "type summary add --summary-string \"int = ${*var.int_pointer}, float = ${*var.float_pointer}\" IWrapPointers") + + self.expect("frame variable wrapper", + substrs=['int = 4', + 'float = 1.1']) + + self.runCmd( + "type summary add --summary-string \"low bits = ${*var.int_pointer[2]}\" IWrapPointers -p") + + self.expect("frame variable wrapper", + substrs=['low bits = 1']) + + self.expect("frame variable *wrap_pointer", + substrs=['low bits = 1']) + + self.runCmd("type summary clear") + + self.expect( + "frame variable int_array --summary-string \"${var[0][0-2]%hex}\"", + substrs=[ + '0x', + '7']) + + self.runCmd("type summary clear") + + self.runCmd( + "type summary add --summary-string \"${*var[].x[0-3]%hex} is a bitfield on a set of integers\" -x \"SimpleWithPointers \[[0-9]\]\"") + + self.expect( + "frame variable couple --summary-string \"${*var.sp.x[0-2]} are low bits of integer ${*var.sp.x}. If I pretend it is an array I get ${var.sp.x[0-5]}\"", + substrs=[ + '1 are low bits of integer 9.', + 'If I pretend it is an array I get [9,']) + + # if the summary has an error, we still display the value + self.expect( + "frame variable couple --summary-string \"${*var.sp.foo[0-2]\"", + substrs=[ + '(Couple) couple = {', + 'x = 0x', + 'y = 0x', + 'z = 0x', + 's = 0x']) + + self.runCmd( + "type summary add --summary-string \"${*var.sp.x[0-2]} are low bits of integer ${*var.sp.x}. If I pretend it is an array I get ${var.sp.x[0-5]}\" Couple") + + self.expect("frame variable sparray", + substrs=['[0x0000000f,0x0000000c,0x00000009]']) + + # check that we can format a variable in a summary even if a format is + # defined for its datatype + self.runCmd("type format add -f hex int") + self.runCmd( + "type summary add --summary-string \"x=${var.x%d}\" Simple") + + self.expect("frame variable a_simple_object", + substrs=['x=3']) + + self.expect("frame variable a_simple_object", matching=False, + substrs=['0x0']) + + # now check that the default is applied if we do not hand out a format + self.runCmd("type summary add --summary-string \"x=${var.x}\" Simple") + + self.expect("frame variable a_simple_object", matching=False, + substrs=['x=3']) + + self.expect("frame variable a_simple_object", matching=True, + substrs=['x=0x00000003']) + + # check that we can correctly cap the number of children shown + self.runCmd("settings set target.max-children-count 5") + + self.expect('frame variable a_long_guy', matching=True, + substrs=['a_1', + 'b_1', + 'c_1', + 'd_1', + 'e_1', + '...']) + + # check that no further stuff is printed (not ALL values are checked!) + self.expect('frame variable a_long_guy', matching=False, + substrs=['f_1', + 'g_1', + 'h_1', + 'i_1', + 'j_1', + 'q_1', + 'a_2', + 'f_2', + 't_2', + 'w_2']) + + self.runCmd("settings set target.max-children-count 1") + self.expect('frame variable a_long_guy', matching=True, + substrs=['a_1', + '...']) + self.expect('frame variable a_long_guy', matching=False, + substrs=['b_1', + 'c_1', + 'd_1', + 'e_1']) + self.expect('frame variable a_long_guy', matching=False, + substrs=['f_1', + 'g_1', + 'h_1', + 'i_1', + 'j_1', + 'q_1', + 'a_2', + 'f_2', + 't_2', + 'w_2']) + + self.runCmd("settings set target.max-children-count 30") + self.expect('frame variable a_long_guy', matching=True, + substrs=['a_1', + 'b_1', + 'c_1', + 'd_1', + 'e_1', + 'z_1', + 'a_2', + 'b_2', + 'c_2', + 'd_2', + '...']) + self.expect('frame variable a_long_guy', matching=False, + substrs=['e_2', + 'n_2', + 'r_2', + 'i_2', + 'k_2', + 'o_2']) + + # override the cap + self.expect( + 'frame variable a_long_guy --show-all-children', + matching=True, + substrs=[ + 'a_1', + 'b_1', + 'c_1', + 'd_1', + 'e_1', + 'z_1', + 'a_2', + 'b_2', + 'c_2', + 'd_2']) + self.expect( + 'frame variable a_long_guy --show-all-children', + matching=True, + substrs=[ + 'e_2', + 'n_2', + 'r_2', + 'i_2', + 'k_2', + 'o_2']) + self.expect( + 'frame variable a_long_guy --show-all-children', + matching=False, + substrs=['...']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-advanced/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-advanced/main.cpp new file mode 100644 index 00000000000..6eabbb3ae0f --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-advanced/main.cpp @@ -0,0 +1,173 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> + +struct i_am_cool +{ + int integer; + float floating; + char character; + i_am_cool(int I, float F, char C) : + integer(I), floating(F), character(C) {} + i_am_cool() : integer(1), floating(2), character('3') {} + +}; + +struct i_am_cooler +{ + i_am_cool first_cool; + i_am_cool second_cool; + float floating; + + i_am_cooler(int I1, int I2, float F1, float F2, char C1, char C2) : + first_cool(I1,F1,C1), + second_cool(I2,F2,C2), + floating((F1 + F2)/2) {} +}; + +struct IWrapPointers +{ + int* int_pointer; + float* float_pointer; + IWrapPointers() : int_pointer(new int(4)), float_pointer(new float(1.111)) {} +}; + +struct Simple +{ + int x; + float y; + char z; + Simple(int X, float Y, char Z) : + x(X), + y(Y), + z(Z) + {} +}; + +struct SimpleWithPointers +{ + int *x; + float *y; + char *z; + SimpleWithPointers(int X, float Y, char Z) : + x(new int (X)), + y(new float (Y)), + z(new char[2]) + { + z[0] = Z; + z[1] = '\0'; + } +}; + +struct Couple +{ + SimpleWithPointers sp; + Simple* s; + Couple(int X, float Y, char Z) : sp(X,Y,Z), + s(new Simple(X,Y,Z)) {} +}; + +struct VeryLong +{ + int a_1; + int b_1; + int c_1; + int d_1; + int e_1; + int f_1; + int g_1; + int h_1; + int i_1; + int j_1; + int k_1; + int l_1; + int m_1; + int n_1; + int o_1; + int p_1; + int q_1; + int r_1; + int s_1; + int t_1; + int u_1; + int v_1; + int w_1; + int x_1; + int y_1; + int z_1; + + int a_2; + int b_2; + int c_2; + int d_2; + int e_2; + int f_2; + int g_2; + int h_2; + int i_2; + int j_2; + int k_2; + int l_2; + int m_2; + int n_2; + int o_2; + int p_2; + int q_2; + int r_2; + int s_2; + int t_2; + int u_2; + int v_2; + int w_2; + int x_2; + int y_2; + int z_2; +}; + +int main (int argc, const char * argv[]) +{ + + int iAmInt = 9; + + i_am_cool cool_boy(1,0.5,3); + i_am_cooler cooler_boy(1,2,0.1,0.2,'A','B'); + + i_am_cool *cool_pointer = new i_am_cool(3,-3.141592,'E'); + + i_am_cool cool_array[5]; + + cool_array[3].floating = 5.25; + cool_array[4].integer = 6; + cool_array[2].character = 'Q'; + + int int_array[] = {1,2,3,4,5}; + + IWrapPointers wrapper; + + *int_array = -1; + + int* pointer = &cool_array[4].integer; + + IWrapPointers *wrap_pointer = &wrapper; + + Couple couple(9,9.99,'X'); + + SimpleWithPointers sparray[] = + {SimpleWithPointers(-1,-2,'3'), + SimpleWithPointers(-4,-5,'6'), + SimpleWithPointers(-7,-8,'9')}; + + Simple a_simple_object(3,0.14,'E'); + + VeryLong a_long_guy; + + return 0; // Set break point at this line. +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-caching/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-caching/Makefile new file mode 100644 index 00000000000..224ecc3c2f5 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-caching/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := a.c b.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-caching/TestDataFormatterCaching.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-caching/TestDataFormatterCaching.py new file mode 100644 index 00000000000..881913b225b --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-caching/TestDataFormatterCaching.py @@ -0,0 +1,24 @@ +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +import lldbsuite.test.lldbutil as lldbutil + + +class TestDataFormatterCaching(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_with_run_command(self): + """ + Test that hardcoded summary formatter matches aren't improperly cached. + """ + self.build() + target, process, thread, bkpt = lldbutil.run_to_source_breakpoint( + self, 'break here', lldb.SBFileSpec('a.c')) + valobj = self.frame().FindVariable('f') + self.assertEqual(valobj.GetValue(), '4') + bkpt_b = target.BreakpointCreateBySourceRegex('break here', + lldb.SBFileSpec('b.c')) + lldbutil.continue_to_breakpoint(process, bkpt_b) + valobj = self.frame().FindVariable('f4') + self.assertEqual(valobj.GetSummary(), '(1, 2, 3, 4)') diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-caching/a.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-caching/a.c new file mode 100644 index 00000000000..f2dde815518 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-caching/a.c @@ -0,0 +1,9 @@ +typedef float float4; + +int a(); + +int main() { + float4 f = 4.0f; + // break here + return a(); +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-caching/b.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-caching/b.c new file mode 100644 index 00000000000..0d37c54aa33 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-caching/b.c @@ -0,0 +1,8 @@ +typedef float float4 __attribute__((ext_vector_type(4))); +void stop() {} +int a() { + float4 f4 = {1, 2, 3, 4}; + // break here + stop(); + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-categories/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-categories/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-categories/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-categories/TestDataFormatterCategories.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-categories/TestDataFormatterCategories.py new file mode 100644 index 00000000000..07f7a538b92 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-categories/TestDataFormatterCategories.py @@ -0,0 +1,355 @@ +""" +Test lldb data formatter subsystem. +""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class CategoriesDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + @expectedFlakeyNetBSD + def test_with_run_command(self): + """Test that that file and class static variables display correctly.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case (most of these categories do not + # exist anymore, but we just make sure we delete all of them) + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type category delete Category1', check=False) + self.runCmd('type category delete Category2', check=False) + self.runCmd('type category delete NewCategory', check=False) + self.runCmd("type category delete CircleCategory", check=False) + self.runCmd( + "type category delete RectangleStarCategory", + check=False) + self.runCmd("type category delete BaseCategory", check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + # Add a summary to a new category and check that it works + self.runCmd( + "type summary add Rectangle --summary-string \"ARectangle\" -w NewCategory") + + self.expect("frame variable r1 r2 r3", matching=False, + substrs=['r1 = ARectangle', + 'r2 = ARectangle', + 'r3 = ARectangle']) + + self.runCmd("type category enable NewCategory") + + self.expect("frame variable r1 r2 r3", matching=True, + substrs=['r1 = ARectangle', + 'r2 = ARectangle', + 'r3 = ARectangle']) + + # Disable the category and check that the old stuff is there + self.runCmd("type category disable NewCategory") + + self.expect("frame variable r1 r2 r3", + substrs=['r1 = {', + 'r2 = {', + 'r3 = {']) + + # Re-enable the category and check that it works + self.runCmd("type category enable NewCategory") + + self.expect("frame variable r1 r2 r3", + substrs=['r1 = ARectangle', + 'r2 = ARectangle', + 'r3 = ARectangle']) + + # Delete the category and the old stuff should be there + self.runCmd("type category delete NewCategory") + + self.expect("frame variable r1 r2 r3", + substrs=['r1 = {', + 'r2 = {', + 'r3 = {']) + + # Add summaries to two different categories and check that we can + # switch + self.runCmd( + "type summary add --summary-string \"Width = ${var.w}, Height = ${var.h}\" Rectangle -w Category1") + self.runCmd("type summary add --python-script \"return 'Area = ' + str( int(valobj.GetChildMemberWithName('w').GetValue()) * int(valobj.GetChildMemberWithName('h').GetValue()) );\" Rectangle -w Category2") + + # check that enable A B is the same as enable B enable A + self.runCmd("type category enable Category1 Category2") + + self.expect("frame variable r1 r2 r3", + substrs=['r1 = Width = ', + 'r2 = Width = ', + 'r3 = Width = ']) + + self.runCmd("type category disable Category1") + + self.expect("frame variable r1 r2 r3", + substrs=['r1 = Area = ', + 'r2 = Area = ', + 'r3 = Area = ']) + + # switch again + + self.runCmd("type category enable Category1") + + self.expect("frame variable r1 r2 r3", + substrs=['r1 = Width = ', + 'r2 = Width = ', + 'r3 = Width = ']) + + # Re-enable the category and show that the preference is persisted + self.runCmd("type category disable Category2") + self.runCmd("type category enable Category2") + + self.expect("frame variable r1 r2 r3", + substrs=['r1 = Area = ', + 'r2 = Area = ', + 'r3 = Area = ']) + + # Now delete the favorite summary + self.runCmd("type summary delete Rectangle -w Category2") + + self.expect("frame variable r1 r2 r3", + substrs=['r1 = Width = ', + 'r2 = Width = ', + 'r3 = Width = ']) + + # Delete the summary from the default category (that does not have it) + self.runCmd("type summary delete Rectangle", check=False) + + self.expect("frame variable r1 r2 r3", + substrs=['r1 = Width = ', + 'r2 = Width = ', + 'r3 = Width = ']) + + # Now add another summary to another category and switch back and forth + self.runCmd("type category delete Category1 Category2") + + self.runCmd( + "type summary add Rectangle -w Category1 --summary-string \"Category1\"") + self.runCmd( + "type summary add Rectangle -w Category2 --summary-string \"Category2\"") + + self.runCmd("type category enable Category2") + self.runCmd("type category enable Category1") + + self.runCmd("type summary list -w Category1") + self.expect("type summary list -w NoSuchCategoryHere", + substrs=['no matching results found']) + + self.expect("frame variable r1 r2 r3", + substrs=['r1 = Category1', + 'r2 = Category1', + 'r3 = Category1']) + + self.runCmd("type category disable Category1") + + self.expect("frame variable r1 r2 r3", + substrs=['r1 = Category2', + 'r2 = Category2', + 'r3 = Category2']) + + # Check that re-enabling an enabled category works + self.runCmd("type category enable Category1") + + self.expect("frame variable r1 r2 r3", + substrs=['r1 = Category1', + 'r2 = Category1', + 'r3 = Category1']) + + self.runCmd("type category delete Category1") + self.runCmd("type category delete Category2") + + self.expect("frame variable r1 r2 r3", + substrs=['r1 = {', + 'r2 = {', + 'r3 = {']) + + # Check that multiple summaries can go into one category + self.runCmd( + "type summary add -w Category1 --summary-string \"Width = ${var.w}, Height = ${var.h}\" Rectangle") + self.runCmd( + "type summary add -w Category1 --summary-string \"Radius = ${var.r}\" Circle") + + self.runCmd("type category enable Category1") + + self.expect("frame variable r1 r2 r3", + substrs=['r1 = Width = ', + 'r2 = Width = ', + 'r3 = Width = ']) + + self.expect("frame variable c1 c2 c3", + substrs=['c1 = Radius = ', + 'c2 = Radius = ', + 'c3 = Radius = ']) + + self.runCmd("type summary delete Circle -w Category1") + + self.expect("frame variable c1 c2 c3", + substrs=['c1 = {', + 'c2 = {', + 'c3 = {']) + + # Add a regex based summary to a category + self.runCmd( + "type summary add -w Category1 --summary-string \"Radius = ${var.r}\" -x Circle") + + self.expect("frame variable r1 r2 r3", + substrs=['r1 = Width = ', + 'r2 = Width = ', + 'r3 = Width = ']) + + self.expect("frame variable c1 c2 c3", + substrs=['c1 = Radius = ', + 'c2 = Radius = ', + 'c3 = Radius = ']) + + # Delete it + self.runCmd("type summary delete Circle -w Category1") + + self.expect("frame variable c1 c2 c3", + substrs=['c1 = {', + 'c2 = {', + 'c3 = {']) + + # Change a summary inside a category and check that the change is + # reflected + self.runCmd( + "type summary add Circle -w Category1 --summary-string \"summary1\"") + + self.expect("frame variable c1 c2 c3", + substrs=['c1 = summary1', + 'c2 = summary1', + 'c3 = summary1']) + + self.runCmd( + "type summary add Circle -w Category1 --summary-string \"summary2\"") + + self.expect("frame variable c1 c2 c3", + substrs=['c1 = summary2', + 'c2 = summary2', + 'c3 = summary2']) + + # Check that our order of priority works. Start by clearing categories + self.runCmd("type category delete Category1") + + self.runCmd( + "type summary add Shape -w BaseCategory --summary-string \"AShape\"") + self.runCmd("type category enable BaseCategory") + + self.expect("print (Shape*)&c1", + substrs=['AShape']) + self.expect("print (Shape*)&r1", + substrs=['AShape']) + self.expect("print (Shape*)c_ptr", + substrs=['AShape']) + self.expect("print (Shape*)r_ptr", + substrs=['AShape']) + + self.runCmd( + "type summary add Circle -w CircleCategory --summary-string \"ACircle\"") + self.runCmd( + "type summary add Rectangle -w RectangleCategory --summary-string \"ARectangle\"") + self.runCmd("type category enable CircleCategory") + + self.expect("frame variable c1", + substrs=['ACircle']) + self.expect("frame variable c_ptr", + substrs=['ACircle']) + + self.runCmd( + "type summary add \"Rectangle *\" -w RectangleStarCategory --summary-string \"ARectangleStar\"") + self.runCmd("type category enable RectangleStarCategory") + + self.expect("frame variable c1 r1 c_ptr r_ptr", + substrs=['ACircle', + 'ARectangleStar']) + + self.runCmd("type category enable RectangleCategory") + + self.expect("frame variable c1 r1 c_ptr r_ptr", + substrs=['ACircle', + 'ACircle', + 'ARectangle']) + + # Check that abruptly deleting an enabled category does not crash us + self.runCmd("type category delete RectangleCategory") + + self.expect("frame variable c1 r1 c_ptr r_ptr", + substrs=['ACircle', + '(Rectangle) r1 = ', 'w = 5', 'h = 6', + 'ACircle', + 'ARectangleStar']) + + # check that list commands work + self.expect("type category list", + substrs=['RectangleStarCategory (enabled)']) + + self.expect("type summary list", + substrs=['ARectangleStar']) + + # Disable a category and check that it fallsback + self.runCmd("type category disable CircleCategory") + + # check that list commands work + self.expect("type category list", + substrs=['CircleCategory (disabled']) + + self.expect("frame variable c1 r_ptr", + substrs=['AShape', + 'ARectangleStar']) + + # check that filters work into categories + self.runCmd( + "type filter add Rectangle --child w --category RectangleCategory") + self.runCmd("type category enable RectangleCategory") + self.runCmd( + "type summary add Rectangle --category RectangleCategory --summary-string \" \" -e") + self.expect('frame variable r2', + substrs=['w = 9']) + self.runCmd("type summary add Rectangle --summary-string \" \" -e") + self.expect('frame variable r2', matching=False, + substrs=['h = 16']) + + # Now delete all categories + self.runCmd( + "type category delete CircleCategory RectangleStarCategory BaseCategory RectangleCategory") + + # check that a deleted category with filter does not blow us up + self.expect('frame variable r2', + substrs=['w = 9', + 'h = 16']) + + # and also validate that one can print formatters for a language + self.expect( + 'type summary list -l c++', + substrs=[ + 'vector', + 'map', + 'list', + 'string']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-categories/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-categories/main.cpp new file mode 100644 index 00000000000..e0e7c7ab9bd --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-categories/main.cpp @@ -0,0 +1,45 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> + +struct Shape +{ + bool dummy; + Shape() : dummy(true) {} +}; + +struct Rectangle : public Shape { + int w; + int h; + Rectangle(int W = 3, int H = 5) : w(W), h(H) {} +}; + +struct Circle : public Shape { + int r; + Circle(int R = 6) : r(R) {} +}; + +int main (int argc, const char * argv[]) +{ + Rectangle r1(5,6); + Rectangle r2(9,16); + Rectangle r3(4,4); + + Circle c1(5); + Circle c2(6); + Circle c3(7); + + Circle *c_ptr = new Circle(8); + Rectangle *r_ptr = new Rectangle(9,7); + + return 0; // Set break point at this line. +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-cpp/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-cpp/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-cpp/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py new file mode 100644 index 00000000000..733c427cdaa --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py @@ -0,0 +1,294 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class CppDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + @skipIf(debug_info="gmodules", + bugnumber="https://bugs.llvm.org/show_bug.cgi?id=36048") + def test_with_run_command(self): + """Test that that file and class static variables display correctly.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + self.expect("frame variable", + substrs=['(Speed) SPILookHex = 5.55' # Speed by default is 5.55. + ]) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.runCmd("type format add -C yes -f x Speed BitField") + self.runCmd("type format add -C no -f c RealNumber") + self.runCmd("type format add -C no -f x Type2") + self.runCmd("type format add -C yes -f c Type1") + + # The type format list should show our custom formats. + self.expect("type format list", + substrs=['RealNumber', + 'Speed', + 'BitField', + 'Type1', + 'Type2']) + + self.expect("frame variable", + patterns=['\(Speed\) SPILookHex = 0x[0-9a-f]+' # Speed should look hex-ish now. + ]) + + # gcc4.2 on Mac OS X skips typedef chains in the DWARF output + if self.getCompiler() in ['clang', 'llvm-gcc']: + self.expect("frame variable", + patterns=['\(SignalMask\) SMILookHex = 0x[0-9a-f]+' # SignalMask should look hex-ish now. + ]) + self.expect("frame variable", matching=False, + patterns=['\(Type4\) T4ILookChar = 0x[0-9a-f]+' # Type4 should NOT look hex-ish now. + ]) + + # Now let's delete the 'Speed' custom format. + self.runCmd("type format delete Speed") + + # The type format list should not show 'Speed' at this point. + self.expect("type format list", matching=False, + substrs=['Speed']) + + # Delete type format for 'Speed', we should expect an error message. + self.expect("type format delete Speed", error=True, + substrs=['no custom formatter for Speed']) + + self.runCmd( + "type summary add --summary-string \"arr = ${var%s}\" -x \"char \\[[0-9]+\\]\" -v") + + self.expect("frame variable strarr", + substrs=['arr = "Hello world!"']) + + self.runCmd("type summary clear") + + self.runCmd( + "type summary add --summary-string \"ptr = ${var%s}\" \"char *\" -v") + + self.expect("frame variable strptr", + substrs=['ptr = "Hello world!"']) + + self.runCmd( + "type summary add --summary-string \"arr = ${var%s}\" -x \"char \\[[0-9]+\\]\" -v") + + self.expect("frame variable strarr", + substrs=['arr = "Hello world!']) + + # check that rdar://problem/10011145 (Standard summary format for + # char[] doesn't work as the result of "expr".) is solved + self.expect("p strarr", + substrs=['arr = "Hello world!']) + + self.expect("frame variable strptr", + substrs=['ptr = "Hello world!"']) + + self.expect("p strptr", + substrs=['ptr = "Hello world!"']) + + self.expect( + "p (char*)\"1234567890123456789012345678901234567890123456789012345678901234ABC\"", + substrs=[ + '(char *) $', + ' = ptr = ', + ' "1234567890123456789012345678901234567890123456789012345678901234ABC"']) + + self.runCmd("type summary add -c Point") + + self.expect("frame variable iAmSomewhere", + substrs=['x = 4', + 'y = 6']) + + self.expect("type summary list", + substrs=['Point', + 'one-line']) + + self.runCmd("type summary add --summary-string \"y=${var.y%x}\" Point") + + self.expect("frame variable iAmSomewhere", + substrs=['y=0x']) + + self.runCmd( + "type summary add --summary-string \"y=${var.y},x=${var.x}\" Point") + + self.expect("frame variable iAmSomewhere", + substrs=['y=6', + 'x=4']) + + self.runCmd("type summary add --summary-string \"hello\" Point -e") + + self.expect("type summary list", + substrs=['Point', + 'show children']) + + self.expect("frame variable iAmSomewhere", + substrs=['hello', + 'x = 4', + '}']) + + self.runCmd( + "type summary add --summary-string \"Sign: ${var[31]%B} Exponent: ${var[23-30]%x} Mantissa: ${var[0-22]%u}\" ShowMyGuts") + + self.expect("frame variable cool_pointer->floating", + substrs=['Sign: true', + 'Exponent: 0x', + '80']) + + self.runCmd("type summary add --summary-string \"a test\" i_am_cool") + + self.expect("frame variable cool_pointer", + substrs=['a test']) + + self.runCmd( + "type summary add --summary-string \"a test\" i_am_cool --skip-pointers") + + self.expect("frame variable cool_pointer", + substrs=['a test'], + matching=False) + + self.runCmd( + "type summary add --summary-string \"${var[1-3]}\" \"int [5]\"") + + self.expect("frame variable int_array", + substrs=['2', + '3', + '4']) + + self.runCmd("type summary clear") + + self.runCmd( + "type summary add --summary-string \"${var[0-2].integer}\" \"i_am_cool *\"") + self.runCmd( + "type summary add --summary-string \"${var[2-4].integer}\" \"i_am_cool [5]\"") + + self.expect("frame variable cool_array", + substrs=['1,1,6']) + + self.expect("frame variable cool_pointer", + substrs=['3,0,0']) + + # test special symbols for formatting variables into summaries + self.runCmd( + "type summary add --summary-string \"cool object @ ${var%L}\" i_am_cool") + self.runCmd("type summary delete \"i_am_cool [5]\"") + + # this test might fail if the compiler tries to store + # these values into registers.. hopefully this is not + # going to be the case + self.expect("frame variable cool_array", + substrs=['[0] = cool object @ 0x', + '[1] = cool object @ 0x', + '[2] = cool object @ 0x', + '[3] = cool object @ 0x', + '[4] = cool object @ 0x']) + + # test getting similar output by exploiting ${var} = 'type @ location' + # for aggregates + self.runCmd("type summary add --summary-string \"${var}\" i_am_cool") + + # this test might fail if the compiler tries to store + # these values into registers.. hopefully this is not + # going to be the case + self.expect("frame variable cool_array", + substrs=['[0] = i_am_cool @ 0x', + '[1] = i_am_cool @ 0x', + '[2] = i_am_cool @ 0x', + '[3] = i_am_cool @ 0x', + '[4] = i_am_cool @ 0x']) + + # test getting same output by exploiting %T and %L together for + # aggregates + self.runCmd( + "type summary add --summary-string \"${var%T} @ ${var%L}\" i_am_cool") + + # this test might fail if the compiler tries to store + # these values into registers.. hopefully this is not + # going to be the case + self.expect("frame variable cool_array", + substrs=['[0] = i_am_cool @ 0x', + '[1] = i_am_cool @ 0x', + '[2] = i_am_cool @ 0x', + '[3] = i_am_cool @ 0x', + '[4] = i_am_cool @ 0x']) + + self.runCmd("type summary add --summary-string \"goofy\" i_am_cool") + self.runCmd( + "type summary add --summary-string \"${var.second_cool%S}\" i_am_cooler") + + self.expect("frame variable the_coolest_guy", + substrs=['(i_am_cooler) the_coolest_guy = goofy']) + + # check that unwanted type specifiers are removed + self.runCmd("type summary delete i_am_cool") + self.runCmd( + "type summary add --summary-string \"goofy\" \"class i_am_cool\"") + self.expect("frame variable the_coolest_guy", + substrs=['(i_am_cooler) the_coolest_guy = goofy']) + + self.runCmd("type summary delete i_am_cool") + self.runCmd( + "type summary add --summary-string \"goofy\" \"enum i_am_cool\"") + self.expect("frame variable the_coolest_guy", + substrs=['(i_am_cooler) the_coolest_guy = goofy']) + + self.runCmd("type summary delete i_am_cool") + self.runCmd( + "type summary add --summary-string \"goofy\" \"struct i_am_cool\"") + self.expect("frame variable the_coolest_guy", + substrs=['(i_am_cooler) the_coolest_guy = goofy']) + + # many spaces, but we still do the right thing + self.runCmd("type summary delete i_am_cool") + self.runCmd( + "type summary add --summary-string \"goofy\" \"union i_am_cool\"") + self.expect("frame variable the_coolest_guy", + substrs=['(i_am_cooler) the_coolest_guy = goofy']) + + # but that not *every* specifier is removed + self.runCmd("type summary delete i_am_cool") + self.runCmd( + "type summary add --summary-string \"goofy\" \"wrong i_am_cool\"") + self.expect("frame variable the_coolest_guy", matching=False, + substrs=['(i_am_cooler) the_coolest_guy = goofy']) + + # check that formats are not sticking since that is the behavior we + # want + self.expect("frame variable iAmInt --format hex", + substrs=['(int) iAmInt = 0x00000001']) + self.expect( + "frame variable iAmInt", + matching=False, + substrs=['(int) iAmInt = 0x00000001']) + self.expect("frame variable iAmInt", substrs=['(int) iAmInt = 1']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-cpp/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-cpp/main.cpp new file mode 100644 index 00000000000..c591313de88 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-cpp/main.cpp @@ -0,0 +1,120 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> + +typedef float RealNumber; // should show as char +typedef RealNumber Temperature; // should show as float +typedef RealNumber Speed; // should show as hex + +typedef int Counter; // should show as int +typedef int BitField; // should show as hex + +typedef BitField SignalMask; // should show as hex +typedef BitField Modifiers; // should show as hex + +typedef Counter Accumulator; // should show as int + +typedef int Type1; // should show as char +typedef Type1 Type2; // should show as hex +typedef Type2 Type3; // should show as char +typedef Type3 Type4; // should show as char + +typedef int ChildType; // should show as int +typedef int AnotherChildType; // should show as int + +struct Point { + int x; + int y; + Point(int X = 3, int Y = 2) : x(X), y(Y) {} +}; + +typedef float ShowMyGuts; + +struct i_am_cool +{ + int integer; + ShowMyGuts floating; + char character; + i_am_cool(int I, ShowMyGuts F, char C) : + integer(I), floating(F), character(C) {} + i_am_cool() : integer(1), floating(2), character('3') {} + +}; + +struct i_am_cooler +{ + i_am_cool first_cool; + i_am_cool second_cool; + ShowMyGuts floating; + + i_am_cooler(int I1, int I2, float F1, float F2, char C1, char C2) : + first_cool(I1,F1,C1), + second_cool(I2,F2,C2), + floating((F1 + F2)/2) {} +}; + +struct IUseCharStar +{ + const char* pointer; + IUseCharStar() : pointer("Hello world") {} +}; + +int main (int argc, const char * argv[]) +{ + + int iAmInt = 1; + const float& IAmFloat = float(2.45); + + RealNumber RNILookChar = 3.14; + Temperature TMILookFloat = 4.97; + Speed SPILookHex = 5.55; + + Counter CTILookInt = 6; + BitField BFILookHex = 7; + SignalMask SMILookHex = 8; + Modifiers MFILookHex = 9; + + Accumulator* ACILookInt = new Accumulator(10); + + const Type1& T1ILookChar = 11; + Type2 T2ILookHex = 12; + Type3 T3ILookChar = 13; + Type4 T4ILookChar = 14; + + AnotherChildType AHILookInt = 15; + + Speed* SPPtrILookHex = new Speed(16); + + Point iAmSomewhere(4,6); + + i_am_cool *cool_pointer = (i_am_cool*)malloc(sizeof(i_am_cool)*3); + cool_pointer[0] = i_am_cool(3,-3.141592,'E'); + cool_pointer[1] = i_am_cool(0,-3.141592,'E'); + cool_pointer[2] = i_am_cool(0,-3.141592,'E'); + + i_am_cool cool_array[5]; + + cool_array[3].floating = 5.25; + cool_array[4].integer = 6; + cool_array[2].character = 'Q'; + + int int_array[] = {1,2,3,4,5}; + + IUseCharStar iEncapsulateCharStar; + + char strarr[32] = "Hello world!"; + char* strptr = "Hello world!"; + + i_am_cooler the_coolest_guy(1,2,3.14,6.28,'E','G'); + + return 0; // Set break point at this line. +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-disabling/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-disabling/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-disabling/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-disabling/TestDataFormatterDisabling.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-disabling/TestDataFormatterDisabling.py new file mode 100644 index 00000000000..3df6027fdb3 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-disabling/TestDataFormatterDisabling.py @@ -0,0 +1,88 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class DataFormatterDisablingTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + @expectedFailureAll( + oslist=["windows"], + bugnumber="llvm.org/pr24462, Data formatters have problems on Windows") + def test_with_run_command(self): + """Check that we can properly disable all data formatter categories.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type category enable *', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + #self.runCmd('type category enable system VectorTypes libcxx gnu-libstdc++ CoreGraphics CoreServices AppKit CoreFoundation objc default', check=False) + + self.expect('type category list', substrs=['system', 'enabled', ]) + + self.expect("frame variable numbers", + substrs=['[0] = 1', '[3] = 1234']) + + self.expect('frame variable string1', substrs=['hello world']) + + # now disable them all and check that nothing is formatted + self.runCmd('type category disable *') + + self.expect("frame variable numbers", matching=False, + substrs=['[0] = 1', '[3] = 1234']) + + self.expect( + 'frame variable string1', + matching=False, + substrs=['hello world']) + + self.expect('type summary list', substrs=[ + 'Category: system (disabled)']) + + self.expect('type category list', substrs=['system', 'disabled', ]) + + # now enable and check that we are back to normal + self.runCmd("type category enable *") + + self.expect('type category list', substrs=['system', 'enabled']) + + self.expect("frame variable numbers", + substrs=['[0] = 1', '[3] = 1234']) + + self.expect('frame variable string1', substrs=['hello world']) + + self.expect('type category list', substrs=['system', 'enabled']) + + # last check - our cleanup will re-enable everything + self.runCmd('type category disable *') + self.expect('type category list', substrs=['system', 'disabled']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-disabling/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-disabling/main.cpp new file mode 100644 index 00000000000..9374642fb0d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-disabling/main.cpp @@ -0,0 +1,18 @@ +#include <vector> + +int main() +{ + + const char* string1 = "hello world"; + + std::vector<int> numbers; + numbers.push_back(1); + numbers.push_back(12); + numbers.push_back(123); + numbers.push_back(1234); + numbers.push_back(12345); + numbers.push_back(123456); + numbers.push_back(1234567); // Set break point at this line. + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-enum-format/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-enum-format/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-enum-format/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-enum-format/TestDataFormatterEnumFormat.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-enum-format/TestDataFormatterEnumFormat.py new file mode 100644 index 00000000000..ca57442e452 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-enum-format/TestDataFormatterEnumFormat.py @@ -0,0 +1,64 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class EnumFormatTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + def test_with_run_command(self): + """Test that that file and class static variables display correctly.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + self.expect("frame variable", + substrs=['(Foo) f = Case45', + '(int) x = 1', + '(int) y = 45', + '(int) z = 43' + ]) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.runCmd("type format add --type Foo int") + + # The type format list should show our custom formats. + self.expect("type format list -w default", + substrs=['int: as type Foo']) + + self.expect("frame variable", + substrs=['(Foo) f = Case45', + '(int) x = Case1', + '(int) y = Case45', + '(int) z = 43' + ]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-enum-format/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-enum-format/main.cpp new file mode 100644 index 00000000000..6a8074ff9fb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-enum-format/main.cpp @@ -0,0 +1,13 @@ +enum Foo { + Case1 = 1, + Case2 = 2, + Case45 = 45 +}; + +int main() { + Foo f = Case45; + int x = 1; + int y = 45; + int z = 43; + return 1; // Set break point at this line. +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-globals/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-globals/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-globals/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-globals/TestDataFormatterGlobals.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-globals/TestDataFormatterGlobals.py new file mode 100644 index 00000000000..72fe2fb1885 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-globals/TestDataFormatterGlobals.py @@ -0,0 +1,71 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +import lldbsuite.test.lldbutil as lldbutil + + +class GlobalsDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + @skipIf(debug_info="gmodules", + bugnumber="https://bugs.llvm.org/show_bug.cgi?id=36048") + def test_with_run_command(self): + """Test that that file and class static variables display correctly.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.runCmd("type summary add --summary-string \"JustATest\" Point") + + # Simply check we can get at global variables + self.expect("target variable g_point", + substrs=['JustATest']) + + self.expect("target variable g_point_pointer", + substrs=['(Point *) g_point_pointer =']) + + # Print some information about the variables + # (we ignore the actual values) + self.runCmd( + "type summary add --summary-string \"(x=${var.x},y=${var.y})\" Point") + + self.expect("target variable g_point", + substrs=['x=', + 'y=']) + + self.expect("target variable g_point_pointer", + substrs=['(Point *) g_point_pointer =']) + + # Test Python code on resulting SBValue + self.runCmd( + "type summary add --python-script \"return 'x=' + str(valobj.GetChildMemberWithName('x').GetValue());\" Point") + + self.expect("target variable g_point", + substrs=['x=']) + + self.expect("target variable g_point_pointer", + substrs=['(Point *) g_point_pointer =']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-globals/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-globals/main.cpp new file mode 100644 index 00000000000..0f922b31352 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-globals/main.cpp @@ -0,0 +1,26 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> + +struct Point { + int x; + int y; + Point(int X = 3, int Y = 2) : x(X), y(Y) {} +}; + +Point g_point(3,4); +Point* g_point_pointer = new Point(7,5); + +int main (int argc, const char * argv[]) +{ + return 0; // Set break point at this line. +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-named-summaries/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-named-summaries/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-named-summaries/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-named-summaries/TestDataFormatterNamedSummaries.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-named-summaries/TestDataFormatterNamedSummaries.py new file mode 100644 index 00000000000..4e4c196c298 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-named-summaries/TestDataFormatterNamedSummaries.py @@ -0,0 +1,130 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class NamedSummariesDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + def test_with_run_command(self): + """Test that that file and class static variables display correctly.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.runCmd( + "type summary add --summary-string \"AllUseIt: x=${var.x} {y=${var.y}} {z=${var.z}}\" --name AllUseIt") + self.runCmd( + "type summary add --summary-string \"First: x=${var.x} y=${var.y} dummy=${var.dummy}\" First") + self.runCmd( + "type summary add --summary-string \"Second: x=${var.x} y=${var.y%hex}\" Second") + self.runCmd( + "type summary add --summary-string \"Third: x=${var.x} z=${var.z}\" Third") + + self.expect('type summary list', substrs=['AllUseIt']) + + self.expect("frame variable first", + substrs=['First: x=12']) + + self.expect("frame variable first --summary AllUseIt", + substrs=['AllUseIt: x=12']) + + # We *DO NOT* remember the summary choice anymore + self.expect("frame variable first", matching=False, + substrs=['AllUseIt: x=12']) + self.expect("frame variable first", + substrs=['First: x=12']) + + self.runCmd("thread step-over") # 2 + + self.expect("frame variable first", + substrs=['First: x=12']) + + self.expect("frame variable first --summary AllUseIt", + substrs=['AllUseIt: x=12', + 'y=34']) + + self.expect("frame variable second --summary AllUseIt", + substrs=['AllUseIt: x=65', + 'y=43.25']) + + self.expect("frame variable third --summary AllUseIt", + substrs=['AllUseIt: x=96', + 'z=', + 'E']) + + self.runCmd("thread step-over") # 3 + + self.expect("frame variable second", + substrs=['Second: x=65', + 'y=0x']) + + # <rdar://problem/11576143> decided that invalid summaries will raise an error + # instead of just defaulting to the base summary + self.expect( + "frame variable second --summary NoSuchSummary", + error=True, + substrs=['must specify a valid named summary']) + + self.runCmd("thread step-over") + + self.runCmd( + "type summary add --summary-string \"FirstAndFriends: x=${var.x} {y=${var.y}} {z=${var.z}}\" First --name FirstAndFriends") + + self.expect("frame variable first", + substrs=['FirstAndFriends: x=12', + 'y=34']) + + self.runCmd("type summary delete First") + + self.expect("frame variable first --summary FirstAndFriends", + substrs=['FirstAndFriends: x=12', + 'y=34']) + + self.expect("frame variable first", matching=True, + substrs=['x = 12', + 'y = 34']) + + self.runCmd("type summary delete FirstAndFriends") + self.expect("type summary delete NoSuchSummary", error=True) + self.runCmd("type summary delete AllUseIt") + + self.expect("frame variable first", matching=False, + substrs=['FirstAndFriends']) + + self.runCmd("thread step-over") # 4 + + self.expect("frame variable first", matching=False, + substrs=['FirstAndFriends: x=12', + 'y=34']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-named-summaries/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-named-summaries/main.cpp new file mode 100644 index 00000000000..62ff7b22777 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-named-summaries/main.cpp @@ -0,0 +1,58 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> + +struct First +{ + int x; + int y; + float dummy; + First(int X, int Y) : + x(X), + y(Y), + dummy(3.14) + {} +}; + +struct Second +{ + int x; + float y; + Second(int X, float Y) : + x(X), + y(Y) + {} +}; + +struct Third +{ + int x; + char z; + Third(int X, char Z) : + x(X), + z(Z) + {} +}; + +int main (int argc, const char * argv[]) +{ + First first(12,34); + Second second(65,43.25); + Third *third = new Third(96,'E'); + + first.dummy = 1; // Set break point at this line. + first.dummy = 2; + first.dummy = 3; + first.dummy = 4; + first.dummy = 5; + +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/.categories b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/.categories new file mode 100644 index 00000000000..72cf07c1efe --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/.categories @@ -0,0 +1 @@ +objc diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/Makefile new file mode 100644 index 00000000000..8b322ff320b --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/Makefile @@ -0,0 +1,8 @@ +OBJC_SOURCES := main.m + +CFLAGS_EXTRAS := -w + + + +LD_EXTRAS := -framework Foundation +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/ObjCDataFormatterTestCase.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/ObjCDataFormatterTestCase.py new file mode 100644 index 00000000000..c31af352037 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/ObjCDataFormatterTestCase.py @@ -0,0 +1,42 @@ +# encoding: utf-8 +""" +Test lldb data formatter subsystem. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ObjCDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def appkit_tester_impl(self, commands): + self.build() + self.appkit_common_data_formatters_command() + commands() + + def appkit_common_data_formatters_command(self): + """Test formatters for AppKit classes.""" + self.target, process, thread, bkpt = lldbutil.run_to_source_breakpoint( + self, '// Set break point at this line.', + lldb.SBFileSpec('main.m', False)) + + # The stop reason of the thread should be breakpoint. + self.expect( + "thread list", + STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type synth clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCCF.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCCF.py new file mode 100644 index 00000000000..8671146b649 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCCF.py @@ -0,0 +1,59 @@ +# encoding: utf-8 +""" +Test lldb data formatter subsystem. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +from ObjCDataFormatterTestCase import ObjCDataFormatterTestCase + + +class ObjCDataFormatterCF(ObjCDataFormatterTestCase): + + @skipUnlessDarwin + def test_coreframeworks_and_run_command(self): + """Test formatters for Core OSX frameworks.""" + self.build() + self.target, process, thread, bkpt = lldbutil.run_to_source_breakpoint( + self, '// Set break point at this line.', + lldb.SBFileSpec('main.m', False)) + + # The stop reason of the thread should be breakpoint. + self.expect( + "thread list", + STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', 'stop reason = breakpoint']) + + # check formatters for common Objective-C types + expect_strings = [ + '(CFGregorianUnits) cf_greg_units = 1 years, 3 months, 5 days, 12 hours, 5 minutes 7 seconds', + '(CFRange) cf_range = location=4 length=4', + '(NSPoint) ns_point = (x = 4, y = 4)', + '(NSRange) ns_range = location=4, length=4', + '(NSRect) ns_rect = (origin = (x = 1, y = 1), size = (width = 5, height = 5))', + '(NSRectArray) ns_rect_arr = ((x = 1, y = 1), (width = 5, height = 5)), ...', + '(NSSize) ns_size = (width = 5, height = 7)', + '(CGSize) cg_size = (width = 1, height = 6)', + '(CGPoint) cg_point = (x = 2, y = 7)', + '(CGRect) cg_rect = (origin = (x = 1, y = 2), size = (width = 7, height = 7))', + '(Rect) rect = (t=4, l=8, b=4, r=7)', + '(Rect *) rect_ptr = (t=4, l=8, b=4, r=7)', + '(Point) point = (v=7, h=12)', '(Point *) point_ptr = (v=7, h=12)', + '1985', 'foo_selector_impl' + ] + + if self.getArchitecture() in ['i386', 'x86_64']: + expect_strings.append('(HIPoint) hi_point = (x=7, y=12)') + expect_strings.append( + '(HIRect) hi_rect = origin=(x = 3, y = 5) size=(width = 4, height = 6)' + ) + expect_strings.append( + '(RGBColor) rgb_color = red=3 green=56 blue=35') + expect_strings.append( + '(RGBColor *) rgb_color_ptr = red=3 green=56 blue=35') + + self.expect("frame variable", substrs=expect_strings) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCExpr.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCExpr.py new file mode 100644 index 00000000000..d27f0b93202 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCExpr.py @@ -0,0 +1,64 @@ +# encoding: utf-8 +""" +Test lldb data formatter subsystem. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +from ObjCDataFormatterTestCase import ObjCDataFormatterTestCase + + +class ObjCDataFormatterExpr(ObjCDataFormatterTestCase): + + @skipUnlessDarwin + def test_expr_with_run_command(self): + """Test common cases of expression parser <--> formatters interaction.""" + self.build() + self.target, process, thread, bkpt = lldbutil.run_to_source_breakpoint( + self, '// Set break point at this line.', + lldb.SBFileSpec('main.m', False)) + + # The stop reason of the thread should be breakpoint. + self.expect( + "thread list", + STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type synth clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + # check that the formatters are able to deal safely and correctly + # with ValueObjects that the expression parser returns + self.expect( + 'expression ((id)@"Hello for long enough to avoid short string types")', + matching=False, + substrs=['Hello for long enough to avoid short string types']) + + self.expect( + 'expression -d run -- ((id)@"Hello for long enough to avoid short string types")', + substrs=['Hello for long enough to avoid short string types']) + + self.expect('expr -d run -- label1', substrs=['Process Name']) + + self.expect( + 'expr -d run -- @"Hello for long enough to avoid short string types"', + substrs=['Hello for long enough to avoid short string types']) + + self.expect( + 'expr -d run --object-description -- @"Hello for long enough to avoid short string types"', + substrs=['Hello for long enough to avoid short string types']) + self.expect( + 'expr -d run --object-description -- @"Hello"', + matching=False, + substrs=['@"Hello" Hello']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCKVO.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCKVO.py new file mode 100644 index 00000000000..fae51ffd038 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCKVO.py @@ -0,0 +1,63 @@ +# encoding: utf-8 +""" +Test lldb data formatter subsystem. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +from ObjCDataFormatterTestCase import ObjCDataFormatterTestCase + + +class ObjCDataFormatterKVO(ObjCDataFormatterTestCase): + + @skipUnlessDarwin + def test_kvo_with_run_command(self): + """Test the behavior of formatters when KVO is in use.""" + self.build() + self.target, process, thread, bkpt = lldbutil.run_to_source_breakpoint( + self, '// Set break point at this line.', + lldb.SBFileSpec('main.m', False)) + + # The stop reason of the thread should be breakpoint. + self.expect( + "thread list", + STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type synth clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + # as long as KVO is implemented by subclassing, this test should succeed + # we should be able to dynamically figure out that the KVO implementor class + # is a subclass of Molecule, and use the appropriate summary for it + self.runCmd("type summary add -s JustAMoleculeHere Molecule") + self.expect('frame variable molecule', substrs=['JustAMoleculeHere']) + self.runCmd("next") + self.expect("thread list", substrs=['stopped', 'step over']) + self.expect('frame variable molecule', substrs=['JustAMoleculeHere']) + + self.runCmd("next") + # check that NSMutableDictionary's formatter is not confused when + # dealing with a KVO'd dictionary + self.expect( + 'frame variable newMutableDictionary', + substrs=[ + '(NSDictionary *) newMutableDictionary = ', + ' 21 key/value pairs' + ]) + + lldbutil.run_break_set_by_regexp(self, 'setAtoms') + + self.runCmd("continue") + self.expect("frame variable _cmd", substrs=['setAtoms:']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSBundle.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSBundle.py new file mode 100644 index 00000000000..40acc19a5da --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSBundle.py @@ -0,0 +1,31 @@ +# encoding: utf-8 +""" +Test lldb data formatter subsystem. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +from ObjCDataFormatterTestCase import ObjCDataFormatterTestCase + + +class ObjCDataFormatterNSBundle(ObjCDataFormatterTestCase): + + @skipUnlessDarwin + def test_nsbundle_with_run_command(self): + """Test formatters for NSBundle.""" + self.appkit_tester_impl(self.nsbundle_data_formatter_commands) + + def nsbundle_data_formatter_commands(self): + self.expect( + 'frame variable bundle_string bundle_url main_bundle', + substrs=[ + '(NSBundle *) bundle_string = ', + ' @"/System/Library/Frameworks/Accelerate.framework"', + '(NSBundle *) bundle_url = ', + ' @"/System/Library/Frameworks/Foundation.framework"', + '(NSBundle *) main_bundle = ', 'data-formatter-objc' + ]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSContainer.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSContainer.py new file mode 100644 index 00000000000..2bd22ff3abd --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSContainer.py @@ -0,0 +1,46 @@ +# encoding: utf-8 +""" +Test lldb data formatter subsystem. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +from ObjCDataFormatterTestCase import ObjCDataFormatterTestCase + + +class ObjCDataFormatterNSContainer(ObjCDataFormatterTestCase): + + @skipUnlessDarwin + def test_nscontainers_with_run_command(self): + """Test formatters for NS container classes.""" + self.appkit_tester_impl(self.nscontainers_data_formatter_commands) + + def nscontainers_data_formatter_commands(self): + self.expect( + 'frame variable newArray nsDictionary newDictionary nscfDictionary cfDictionaryRef newMutableDictionary cfarray_ref mutable_array_ref', + substrs=[ + '(NSArray *) newArray = ', '@"50 elements"', + '(NSDictionary *) newDictionary = ', ' 12 key/value pairs', + '(NSDictionary *) newMutableDictionary = ', + ' 21 key/value pairs', '(NSDictionary *) nsDictionary = ', + ' 2 key/value pairs', '(CFDictionaryRef) cfDictionaryRef = ', + ' 3 key/value pairs', '(CFArrayRef) cfarray_ref = ', + '@"3 elements"', '(CFMutableArrayRef) mutable_array_ref = ', + '@"11 elements"' + ]) + + self.expect( + 'frame variable iset1 iset2 imset', + substrs=['4 indexes', '512 indexes', '10 indexes']) + + self.expect( + 'frame variable binheap_ref', + substrs=['(CFBinaryHeapRef) binheap_ref = ', '@"21 items"']) + + self.expect( + 'expression -d run -- (NSArray*)[NSArray new]', + substrs=['@"0 elements"']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSData.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSData.py new file mode 100644 index 00000000000..37991ddb99d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSData.py @@ -0,0 +1,34 @@ +# encoding: utf-8 +""" +Test lldb data formatter subsystem. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +from ObjCDataFormatterTestCase import ObjCDataFormatterTestCase + + +class ObjCDataFormatterNSData(ObjCDataFormatterTestCase): + + @skipUnlessDarwin + def test_nsdata_with_run_command(self): + """Test formatters for NSData.""" + self.appkit_tester_impl(self.nsdata_data_formatter_commands) + + def nsdata_data_formatter_commands(self): + self.expect( + 'frame variable immutableData mutableData data_ref mutable_data_ref mutable_string_ref concreteData concreteMutableData', + substrs=[ + '(NSData *) immutableData = ', ' 4 bytes', + '(NSData *) mutableData = ', ' 14 bytes', + '(CFDataRef) data_ref = ', '@"5 bytes"', + '(CFMutableDataRef) mutable_data_ref = ', '@"5 bytes"', + '(CFMutableStringRef) mutable_string_ref = ', + ' @"Wish ya knew"', '(NSData *) concreteData = ', + ' 100000 bytes', '(NSMutableData *) concreteMutableData = ', + ' 100000 bytes' + ]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSDate.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSDate.py new file mode 100644 index 00000000000..a064dd7a90b --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSDate.py @@ -0,0 +1,34 @@ +# encoding: utf-8 +""" +Test lldb data formatter subsystem. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +from ObjCDataFormatterTestCase import ObjCDataFormatterTestCase + + +class ObjCDataFormatterNSDate(ObjCDataFormatterTestCase): + + @skipUnlessDarwin + def test_nsdata_with_run_command(self): + """Test formatters for NSData.""" + self.appkit_tester_impl(self.nsdata_data_formatter_commands) + + def nsdata_data_formatter_commands(self): + self.expect( + 'frame variable immutableData mutableData data_ref mutable_data_ref mutable_string_ref concreteData concreteMutableData', + substrs=[ + '(NSData *) immutableData = ', ' 4 bytes', + '(NSData *) mutableData = ', ' 14 bytes', + '(CFDataRef) data_ref = ', '@"5 bytes"', + '(CFMutableDataRef) mutable_data_ref = ', '@"5 bytes"', + '(CFMutableStringRef) mutable_string_ref = ', + ' @"Wish ya knew"', '(NSData *) concreteData = ', + ' 100000 bytes', '(NSMutableData *) concreteMutableData = ', + ' 100000 bytes' + ]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSError.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSError.py new file mode 100644 index 00000000000..df380aefd88 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSError.py @@ -0,0 +1,35 @@ +# encoding: utf-8 +""" +Test lldb data formatter subsystem. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +from ObjCDataFormatterTestCase import ObjCDataFormatterTestCase + + +class ObjCDataFormatterNSError(ObjCDataFormatterTestCase): + + @skipUnlessDarwin + def test_nserror_with_run_command(self): + """Test formatters for NSError.""" + self.appkit_tester_impl(self.nserror_data_formatter_commands) + + def nserror_data_formatter_commands(self): + self.expect( + 'frame variable nserror', substrs=['domain: @"Foobar" - code: 12']) + + self.expect( + 'frame variable nserrorptr', + substrs=['domain: @"Foobar" - code: 12']) + + self.expect( + 'frame variable nserror->_userInfo', substrs=['2 key/value pairs']) + + self.expect( + 'frame variable nserror->_userInfo --ptr-depth 1 -d run-target', + substrs=['@"a"', '@"b"', "1", "2"]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSURL.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSURL.py new file mode 100644 index 00000000000..e84818e9a70 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSURL.py @@ -0,0 +1,39 @@ +# encoding: utf-8 +""" +Test lldb data formatter subsystem. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +from ObjCDataFormatterTestCase import ObjCDataFormatterTestCase + + +class ObjCDataFormatterNSURL(ObjCDataFormatterTestCase): + + @skipUnlessDarwin + def test_nsurl_with_run_command(self): + """Test formatters for NSURL.""" + self.appkit_tester_impl(self.nsurl_data_formatter_commands) + + def nsurl_data_formatter_commands(self): + self.expect( + 'frame variable cfurl_ref cfchildurl_ref cfgchildurl_ref', + substrs=[ + '(CFURLRef) cfurl_ref = ', '@"http://www.foo.bar', + 'cfchildurl_ref = ', '@"page.html -- http://www.foo.bar', + '(CFURLRef) cfgchildurl_ref = ', + '@"?whatever -- http://www.foo.bar/page.html"' + ]) + + self.expect( + 'frame variable nsurl nsurl2 nsurl3', + substrs=[ + '(NSURL *) nsurl = ', '@"http://www.foo.bar', + '(NSURL *) nsurl2 =', '@"page.html -- http://www.foo.bar', + '(NSURL *) nsurl3 = ', + '@"?whatever -- http://www.foo.bar/page.html"' + ]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCPlain.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCPlain.py new file mode 100644 index 00000000000..f438245aad2 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCPlain.py @@ -0,0 +1,77 @@ +# encoding: utf-8 +""" +Test lldb data formatter subsystem. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +from ObjCDataFormatterTestCase import ObjCDataFormatterTestCase + + +class ObjCDataFormatterNSPlain(ObjCDataFormatterTestCase): + + @skipUnlessDarwin + def test_plain_objc_with_run_command(self): + """Test basic ObjC formatting behavior.""" + self.build() + self.target, process, thread, bkpt = lldbutil.run_to_source_breakpoint( + self, '// Set break point at this line.', + lldb.SBFileSpec('main.m', False)) + + # The stop reason of the thread should be breakpoint. + self.expect( + "thread list", + STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type synth clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.runCmd("type summary add --summary-string \"${var%@}\" MyClass") + + self.expect("frame variable object2", substrs=['MyOtherClass']) + + self.expect("frame variable *object2", substrs=['MyOtherClass']) + + # Now let's delete the 'MyClass' custom summary. + self.runCmd("type summary delete MyClass") + + # The type format list should not show 'MyClass' at this point. + self.expect("type summary list", matching=False, substrs=['MyClass']) + + self.runCmd("type summary add --summary-string \"a test\" MyClass") + + self.expect( + "frame variable *object2", + substrs=['*object2 =', 'MyClass = a test', 'backup = ']) + + self.expect( + "frame variable object2", matching=False, substrs=['a test']) + + self.expect("frame variable object", substrs=['a test']) + + self.expect("frame variable *object", substrs=['a test']) + + self.expect( + 'frame variable myclass', substrs=['(Class) myclass = NSValue']) + self.expect( + 'frame variable myclass2', + substrs=['(Class) myclass2 = ', 'NS', 'String']) + self.expect( + 'frame variable myclass3', substrs=['(Class) myclass3 = Molecule']) + self.expect( + 'frame variable myclass4', + substrs=['(Class) myclass4 = NSMutableArray']) + self.expect( + 'frame variable myclass5', substrs=['(Class) myclass5 = nil']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjNSException.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjNSException.py new file mode 100644 index 00000000000..6265c05c5b7 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjNSException.py @@ -0,0 +1,34 @@ +# encoding: utf-8 +""" +Test lldb data formatter subsystem. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +from ObjCDataFormatterTestCase import ObjCDataFormatterTestCase + + +class ObjCDataFormatterNSException(ObjCDataFormatterTestCase): + + @skipUnlessDarwin + def test_nsexception_with_run_command(self): + """Test formatters for NSException.""" + self.appkit_tester_impl(self.nsexception_data_formatter_commands) + + def nsexception_data_formatter_commands(self): + self.expect( + 'frame variable except0 except1 except2 except3', + substrs=[ + '(NSException *) except0 = ', + '@"First"', + '(NSException *) except1 = ', + '@"Second"', + '(NSException *) except2 = ', + ' @"Third"', + '(NSException *) except3 = ', + ' @"Fourth"' + ]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/cmtime/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/cmtime/Makefile new file mode 100644 index 00000000000..143997cf26e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/cmtime/Makefile @@ -0,0 +1,6 @@ +OBJC_SOURCES := main.m + +CFLAGS_EXTRAS := -w + +LD_EXTRAS := -framework CoreMedia +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/cmtime/TestDataFormatterCMTime.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/cmtime/TestDataFormatterCMTime.py new file mode 100644 index 00000000000..4c3935c851c --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/cmtime/TestDataFormatterCMTime.py @@ -0,0 +1,39 @@ +# encoding: utf-8 + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class CMTimeDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipUnlessDarwin + def test_nsindexpath_with_run_command(self): + """Test formatters for CMTime.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), + CURRENT_EXECUTABLE_SET) + + line = line_number('main.m', '// break here') + lldbutil.run_break_set_by_file_and_line( + self, "main.m", line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + self.expect( + "thread list", + STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', 'stop reason = breakpoint']) + + self.expect( + 'frame variable t1', + substrs=[ + '1 10th of a second', 'value = 1', 'timescale = 10', + 'epoch = 0' + ]) + self.expect( + 'frame variable t2', + substrs=['10 seconds', 'value = 10', 'timescale = 1', 'epoch = 0']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/cmtime/main.m b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/cmtime/main.m new file mode 100644 index 00000000000..ecf7648c3f9 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/cmtime/main.m @@ -0,0 +1,22 @@ +//===-- main.m ------------------------------------------------*- ObjC -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#import <CoreMedia/CoreMedia.h> + +int main(int argc, const char **argv) +{ + @autoreleasepool + { + CMTime t1 = CMTimeMake(1, 10); + CMTime t2 = CMTimeMake(10, 1); + + CMTimeShow(t1); // break here + CMTimeShow(t2); + } + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/main.m b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/main.m new file mode 100644 index 00000000000..f0dc2055976 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/main.m @@ -0,0 +1,632 @@ +//===-- main.m ------------------------------------------------*- ObjC -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#import <Foundation/Foundation.h> + +#if defined(__APPLE__) +#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) +#define IOS +#endif +#endif + +#if defined(IOS) +#import <Foundation/NSGeometry.h> +#else +#import <Carbon/Carbon.h> +#endif + +@interface MyClass : NSObject +{ + int i; + char c; + float f; +} + +- (id)initWithInt: (int)x andFloat:(float)y andChar:(char)z; +- (int)doIncrementByInt: (int)x; + +@end + +@interface MyOtherClass : MyClass +{ + int i2; + MyClass *backup; +} +- (id)initWithInt: (int)x andFloat:(float)y andChar:(char)z andOtherInt:(int)q; + +@end + +@implementation MyClass + +- (id)initWithInt: (int)x andFloat:(float)y andChar:(char)z +{ + self = [super init]; + if (self) { + self->i = x; + self->f = y; + self->c = z; + } + return self; +} + +- (int)doIncrementByInt: (int)x +{ + self->i += x; + return self->i; +} + +@end + +@implementation MyOtherClass + +- (id)initWithInt: (int)x andFloat:(float)y andChar:(char)z andOtherInt:(int)q +{ + self = [super initWithInt:x andFloat:y andChar:z]; + if (self) { + self->i2 = q; + self->backup = [[MyClass alloc] initWithInt:x andFloat:y andChar:z]; + } + return self; +} + +@end + +@interface Atom : NSObject { + float mass; +} +-(void)setMass:(float)newMass; +-(float)mass; +@end + +@interface Molecule : NSObject { + NSArray *atoms; +} +-(void)setAtoms:(NSArray *)newAtoms; +-(NSArray *)atoms; +@end + +@implementation Atom + +-(void)setMass:(float)newMass +{ + mass = newMass; +} +-(float)mass +{ + return mass; +} + +@end + +@implementation Molecule + +-(void)setAtoms:(NSArray *)newAtoms +{ + atoms = newAtoms; +} +-(NSArray *)atoms +{ + return atoms; +} +@end + +@interface My_KVO_Observer : NSObject +-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change + context:(void *)context; +- (id) init; +- (void) dealloc; +@end + +@implementation My_KVO_Observer +-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change + context:(void *)context { + // we do not really care about KVO'ing - do nothing + return; +} +- (id) init +{ + self = [super init]; + return self; +} + +- (void) dealloc +{ + [super dealloc]; +} +@end + +int main (int argc, const char * argv[]) +{ + + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + + MyClass *object = [[MyClass alloc] initWithInt:1 andFloat:3.14 andChar: 'E']; + + [object doIncrementByInt:3]; + + MyOtherClass *object2 = [[MyOtherClass alloc] initWithInt:2 andFloat:6.28 andChar: 'G' andOtherInt:-1]; + + [object2 doIncrementByInt:3]; + + NSNumber* num1 = [NSNumber numberWithInt:5]; + NSNumber* num2 = [NSNumber numberWithFloat:3.14]; + NSNumber* num3 = [NSNumber numberWithDouble:3.14]; + NSNumber* num4 = [NSNumber numberWithUnsignedLongLong:0xFFFFFFFFFFFFFFFE]; + NSNumber* num5 = [NSNumber numberWithChar:'A']; + NSNumber* num6 = [NSNumber numberWithUnsignedLongLong:0xFF]; + NSNumber* num7 = [NSNumber numberWithLong:0x1E8480]; + NSNumber* num8_Y = [NSNumber numberWithBool:YES]; + NSNumber* num8_N = [NSNumber numberWithBool:NO]; + NSNumber* num9 = [NSNumber numberWithShort:0x1E8480]; + NSNumber* num_at1 = @12; + NSNumber* num_at2 = @-12; + NSNumber* num_at3 = @12.5; + NSNumber* num_at4 = @-12.5; + + NSDecimalNumber* decimal_number = [NSDecimalNumber decimalNumberWithMantissa:123456 exponent:-10 isNegative:NO]; + NSDecimalNumber* decimal_number_neg = [NSDecimalNumber decimalNumberWithMantissa:123456 exponent:10 isNegative:YES]; + NSDecimalNumber* decimal_one = [NSDecimalNumber one]; + NSDecimalNumber* decimal_zero = [NSDecimalNumber zero]; + NSDecimalNumber* decimal_nan = [NSDecimalNumber notANumber]; + + NSString *str0 = [num6 stringValue]; + + NSString *str1 = [NSString stringWithCString:"A rather short ASCII NSString object is here" encoding:NSASCIIStringEncoding]; + + NSString *str2 = [NSString stringWithUTF8String:"A rather short UTF8 NSString object is here"]; + + NSString *str3 = @"A string made with the at sign is here"; + + NSString *str4 = [NSString stringWithFormat:@"This is string number %ld right here", (long)4]; + + NSRect ns_rect_4str = {{1,1},{5,5}}; + + NSString* str5 = NSStringFromRect(ns_rect_4str); + + NSString* str6 = [@"/usr/doc/README.1ST" pathExtension]; + + const unichar myCharacters[] = {0x03C3,'x','x'}; + NSString *str7 = [NSString stringWithCharacters: myCharacters + length: sizeof myCharacters / sizeof *myCharacters]; + + NSString* str8 = [@"/usr/doc/file.hasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTime" pathExtension]; + + const unichar myOtherCharacters[] = {'a',' ', 'v','e','r','y',' ', + 'm','u','c','h',' ','b','o','r','i','n','g',' ','t','a','s','k', + ' ','t','o',' ','w','r','i','t','e', ' ', 'a', ' ', 's', 't', 'r', 'i', 'n', 'g', ' ', + 't','h','i','s',' ','w','a','y','!','!',0x03C3, 0}; + NSString *str9 = [NSString stringWithCharacters: myOtherCharacters + length: sizeof myOtherCharacters / sizeof *myOtherCharacters]; + + const unichar myNextCharacters[] = {0x03C3, 0x0000}; + + NSString *str10 = [NSString stringWithFormat:@"This is a Unicode string %S number %ld right here", myNextCharacters, (long)4]; + + NSString *str11 = NSStringFromClass([str10 class]); + + NSString *label1 = @"Process Name: "; + NSString *label2 = @"Process Id: "; + NSString *processName = [[NSProcessInfo processInfo] processName]; + NSString *processID = [NSString stringWithFormat:@"%d", [[NSProcessInfo processInfo] processIdentifier]]; + NSString *str12 = [NSString stringWithFormat:@"%@ %@ %@ %@", label1, processName, label2, processID]; + + NSString *strA1 = [NSString stringWithCString:"A rather short ASCII NSString object is here" encoding:NSASCIIStringEncoding]; + + NSString *strA2 = [NSString stringWithUTF8String:"A rather short UTF8 NSString object is here"]; + + NSString *strA3 = @"A string made with the at sign is here"; + + NSString *strA4 = [NSString stringWithFormat:@"This is string number %ld right here", (long)4]; + + NSString* strA5 = NSStringFromRect(ns_rect_4str); + + NSString* strA6 = [@"/usr/doc/README.1ST" pathExtension]; + + NSString *strA7 = [NSString stringWithCharacters: myCharacters + length: sizeof myCharacters / sizeof *myCharacters]; + + NSString* strA8 = [@"/usr/doc/file.hasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTime" pathExtension]; + + NSString *strA9 = [NSString stringWithCharacters: myOtherCharacters + length: sizeof myOtherCharacters / sizeof *myOtherCharacters]; + + NSString *strA10 = [NSString stringWithFormat:@"This is a Unicode string %S number %ld right here", myNextCharacters, (long)4]; + + NSString *strA11 = NSStringFromClass([str10 class]); + + NSString *strA12 = [NSString stringWithFormat:@"%@ %@ %@ %@", label1, processName, label2, processID]; + + NSString *strB1 = [NSString stringWithCString:"A rather short ASCII NSString object is here" encoding:NSASCIIStringEncoding]; + + NSString *strB2 = [NSString stringWithUTF8String:"A rather short UTF8 NSString object is here"]; + + NSString *strB3 = @"A string made with the at sign is here"; + + NSString *strB4 = [NSString stringWithFormat:@"This is string number %ld right here", (long)4]; + + NSString* strB5 = NSStringFromRect(ns_rect_4str); + + NSString* strB6 = [@"/usr/doc/README.1ST" pathExtension]; + + NSString *strB7 = [NSString stringWithCharacters: myCharacters + length: sizeof myCharacters / sizeof *myCharacters]; + + NSString* strB8 = [@"/usr/doc/file.hasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTime" pathExtension]; + + NSString *strB9 = [NSString stringWithCharacters: myOtherCharacters + length: sizeof myOtherCharacters / sizeof *myOtherCharacters]; + + NSString *strB10 = [NSString stringWithFormat:@"This is a Unicode string %S number %ld right here", myNextCharacters, (long)4]; + + NSString *strB11 = NSStringFromClass([str10 class]); + + NSString *strB12 = [NSString stringWithFormat:@"%@ %@ %@ %@", label1, processName, label2, processID]; + + NSString *strC11 = NSStringFromClass([str10 class]); + + NSString *strC12 = [NSString stringWithFormat:@"%@ %@ %@ %@", label1, processName, label2, processID]; + + NSString *strC1 = [NSString stringWithCString:"A rather short ASCII NSString object is here" encoding:NSASCIIStringEncoding]; + + NSString *strC2 = [NSString stringWithUTF8String:"A rather short UTF8 NSString object is here"]; + + NSString *strC3 = @"A string made with the at sign is here"; + + NSString *strC4 = [NSString stringWithFormat:@"This is string number %ld right here", (long)4]; + + NSString* strC5 = NSStringFromRect(ns_rect_4str); + + NSString* strC6 = [@"/usr/doc/README.1ST" pathExtension]; + + NSString *strC7 = [NSString stringWithCharacters: myCharacters + length: sizeof myCharacters / sizeof *myCharacters]; + + NSString* strC8 = [@"/usr/doc/file.hasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTime" pathExtension]; + + NSString *strC9 = [NSString stringWithCharacters: myOtherCharacters + length: sizeof myOtherCharacters / sizeof *myOtherCharacters]; + + NSString *strC10 = [NSString stringWithFormat:@"This is a Unicode string %S number %ld right here", myNextCharacters, (long)4]; + + NSString *strD11 = NSStringFromClass([str10 class]); + + NSString *strD12 = [NSString stringWithFormat:@"%@ %@ %@ %@", label1, processName, label2, processID]; + + NSString *eAcute = [NSString stringWithFormat: @"%C", 0x00E9]; + NSString *randomHaziChar = [NSString stringWithFormat: @"%C", 0x9DC5]; + NSString *japanese = @"色は匂へど散りぬるを"; + NSString *italian = @"L'Italia è una Repubblica democratica, fondata sul lavoro. La sovranità appartiene al popolo, che la esercita nelle forme e nei limiti della Costituzione."; + NSString* french = @"Que veut cette horde d'esclaves, De traîtres, de rois conjurés?"; + NSString* german = @"Über-Ich und aus den Ansprüchen der sozialen Umwelt"; + + void* data_set[3] = {str1,str2,str3}; + + NSString *hebrew = [NSString stringWithString:@"לילה טוב"]; + + NSArray* newArray = [[NSMutableArray alloc] init]; + [newArray addObject:str1]; + [newArray addObject:str2]; + [newArray addObject:str3]; + [newArray addObject:str4]; + [newArray addObject:str5]; + [newArray addObject:str6]; + [newArray addObject:str7]; + [newArray addObject:str8]; + [newArray addObject:str9]; + [newArray addObject:str10]; + [newArray addObject:str11]; + [newArray addObject:str12]; + [newArray addObject:strA1]; + [newArray addObject:strA2]; + [newArray addObject:strA3]; + [newArray addObject:strA4]; + [newArray addObject:strA5]; + [newArray addObject:strA6]; + [newArray addObject:strA7]; + [newArray addObject:strA8]; + [newArray addObject:strA9]; + [newArray addObject:strA10]; + [newArray addObject:strA11]; + [newArray addObject:strA12]; + [newArray addObject:strB1]; + [newArray addObject:strB2]; + [newArray addObject:strB3]; + [newArray addObject:strB4]; + [newArray addObject:strB5]; + [newArray addObject:strB6]; + [newArray addObject:strB7]; + [newArray addObject:strB8]; + [newArray addObject:strB9]; + [newArray addObject:strB10]; + [newArray addObject:strB11]; + [newArray addObject:strB12]; + [newArray addObject:strC1]; + [newArray addObject:strC2]; + [newArray addObject:strC3]; + [newArray addObject:strC4]; + [newArray addObject:strC5]; + [newArray addObject:strC6]; + [newArray addObject:strC7]; + [newArray addObject:strC8]; + [newArray addObject:strC9]; + [newArray addObject:strC10]; + [newArray addObject:strC11]; + [newArray addObject:strC12]; + [newArray addObject:strD11]; + [newArray addObject:strD12]; + + NSDictionary* newDictionary = [[NSDictionary alloc] initWithObjects:newArray forKeys:newArray]; + NSDictionary *newMutableDictionary = [[NSMutableDictionary alloc] init]; + [newMutableDictionary setObject:@"foo" forKey:@"bar0"]; + [newMutableDictionary setObject:@"foo" forKey:@"bar1"]; + [newMutableDictionary setObject:@"foo" forKey:@"bar2"]; + [newMutableDictionary setObject:@"foo" forKey:@"bar3"]; + [newMutableDictionary setObject:@"foo" forKey:@"bar4"]; + [newMutableDictionary setObject:@"foo" forKey:@"bar5"]; + [newMutableDictionary setObject:@"foo" forKey:@"bar6"]; + [newMutableDictionary setObject:@"foo" forKey:@"bar7"]; + [newMutableDictionary setObject:@"foo" forKey:@"bar8"]; + [newMutableDictionary setObject:@"foo" forKey:@"bar9"]; + [newMutableDictionary setObject:@"foo" forKey:@"bar10"]; + [newMutableDictionary setObject:@"foo" forKey:@"bar11"]; + [newMutableDictionary setObject:@"foo" forKey:@"bar12"]; + [newMutableDictionary setObject:@"foo" forKey:@"bar13"]; + [newMutableDictionary setObject:@"foo" forKey:@"bar14"]; + [newMutableDictionary setObject:@"foo" forKey:@"bar15"]; + [newMutableDictionary setObject:@"foo" forKey:@"bar16"]; + [newMutableDictionary setObject:@"foo" forKey:@"bar17"]; + [newMutableDictionary setObject:@"foo" forKey:@"bar18"]; + [newMutableDictionary setObject:@"foo" forKey:@"bar19"]; + [newMutableDictionary setObject:@"foo" forKey:@"bar20"]; + + id cfKeys[2] = { @"foo", @"bar", @"baz", @"quux" }; + id cfValues[2] = { @"foo", @"bar", @"baz", @"quux" }; + NSDictionary *nsDictionary = CFBridgingRelease(CFDictionaryCreate(nil, (void *)cfKeys, (void *)cfValues, 2, nil, nil)); + CFDictionaryRef cfDictionaryRef = CFDictionaryCreate(nil, (void *)cfKeys, (void *)cfValues, 3, nil, nil); + + NSAttributedString* attrString = [[NSAttributedString alloc] initWithString:@"hello world from foo" attributes:newDictionary]; + [attrString isEqual:nil]; + NSAttributedString* mutableAttrString = [[NSMutableAttributedString alloc] initWithString:@"hello world from foo" attributes:newDictionary]; + [mutableAttrString isEqual:nil]; + + NSString* mutableString = [[NSMutableString alloc] initWithString:@"foo"]; + [mutableString insertString:@"foo said this string needs to be very long so much longer than whatever other string has been seen ever before by anyone of the mankind that of course this is still not long enough given what foo our friend foo our lovely dearly friend foo desired of us so i am adding more stuff here for the sake of it and for the joy of our friend who is named guess what just foo. hence, dear friend foo, stay safe, your string is now long enough to accommodate your testing need and I will make sure that if not we extend it with even more fuzzy random meaningless words pasted one after the other from a long tiresome friday evening spent working in my office. my office mate went home but I am still randomly typing just for the fun of seeing what happens of the length of a Mutable String in Cocoa if it goes beyond one byte.. so be it, dear " atIndex:0]; + + NSString* mutableGetConst = [NSString stringWithCString:[mutableString cString]]; + + [mutableGetConst length]; + + NSData *immutableData = [[NSData alloc] initWithBytes:"HELLO" length:4]; + NSData *mutableData = [[NSMutableData alloc] initWithBytes:"NODATA" length:6]; + + // No-copy versions of NSData initializers use NSConcreteData if over 2^16 elements are specified. + unsigned concreteLength = 100000; + void *zeroes1 = calloc(1, concreteLength); + // initWithBytesNoCopy takes ownership of the buffer. + NSData *concreteData = [[NSData alloc] initWithBytesNoCopy:zeroes1 length:concreteLength]; + void *zeroes2 = calloc(1, concreteLength); + NSMutableData *concreteMutableData = [[NSMutableData alloc] initWithBytesNoCopy:zeroes2 length:concreteLength]; + + [mutableData appendBytes:"MOREDATA" length:8]; + + [immutableData length]; + [mutableData length]; + + NSSet* nsset = [[NSSet alloc] initWithObjects:str1,str2,str3,nil]; + NSSet *nsmutableset = [[NSMutableSet alloc] initWithObjects:str1,str2,str3,nil]; + [nsmutableset addObject:str4]; + + CFDataRef data_ref = CFDataCreate(kCFAllocatorDefault, [immutableData bytes], 5); + + CFMutableDataRef mutable_data_ref = CFDataCreateMutable(kCFAllocatorDefault, 8); + CFDataAppendBytes(mutable_data_ref, [mutableData bytes], 5); + + CFMutableStringRef mutable_string_ref = CFStringCreateMutable(NULL,100); + CFStringAppend(mutable_string_ref, CFSTR("Wish ya knew")); + + CFStringRef cfstring_ref = CFSTR("HELLO WORLD"); + + CFArrayRef cfarray_ref = CFArrayCreate(NULL, data_set, 3, NULL); + CFMutableArrayRef mutable_array_ref = CFArrayCreateMutable(NULL, 16, NULL); + + CFArraySetValueAtIndex(mutable_array_ref, 0, str1); + CFArraySetValueAtIndex(mutable_array_ref, 1, str2); + CFArraySetValueAtIndex(mutable_array_ref, 2, str3); + CFArraySetValueAtIndex(mutable_array_ref, 3, str4); + CFArraySetValueAtIndex(mutable_array_ref, 0, str5); // replacing value at 0!! + CFArraySetValueAtIndex(mutable_array_ref, 4, str6); + CFArraySetValueAtIndex(mutable_array_ref, 5, str7); + CFArraySetValueAtIndex(mutable_array_ref, 6, str8); + CFArraySetValueAtIndex(mutable_array_ref, 7, str9); + CFArraySetValueAtIndex(mutable_array_ref, 8, str10); + CFArraySetValueAtIndex(mutable_array_ref, 9, str11); + CFArraySetValueAtIndex(mutable_array_ref, 10, str12); + + CFBinaryHeapRef binheap_ref = CFBinaryHeapCreate(NULL, 15, &kCFStringBinaryHeapCallBacks, NULL); + CFBinaryHeapAddValue(binheap_ref, str1); + CFBinaryHeapAddValue(binheap_ref, str2); + CFBinaryHeapAddValue(binheap_ref, str3); + CFBinaryHeapAddValue(binheap_ref, str4); + CFBinaryHeapAddValue(binheap_ref, str5); + CFBinaryHeapAddValue(binheap_ref, str6); + CFBinaryHeapAddValue(binheap_ref, str7); + CFBinaryHeapAddValue(binheap_ref, str8); + CFBinaryHeapAddValue(binheap_ref, str9); + CFBinaryHeapAddValue(binheap_ref, str10); + CFBinaryHeapAddValue(binheap_ref, str11); + CFBinaryHeapAddValue(binheap_ref, str12); + CFBinaryHeapAddValue(binheap_ref, strA1); + CFBinaryHeapAddValue(binheap_ref, strB1); + CFBinaryHeapAddValue(binheap_ref, strC1); + CFBinaryHeapAddValue(binheap_ref, strA11); + CFBinaryHeapAddValue(binheap_ref, strB11); + CFBinaryHeapAddValue(binheap_ref, strC11); + CFBinaryHeapAddValue(binheap_ref, strB12); + CFBinaryHeapAddValue(binheap_ref, strC12); + CFBinaryHeapAddValue(binheap_ref, strA12); + + CFURLRef cfurl_ref = CFURLCreateWithString(NULL, CFSTR("http://www.foo.bar/"), NULL); + CFURLRef cfchildurl_ref = CFURLCreateWithString(NULL, CFSTR("page.html"), cfurl_ref); + CFURLRef cfgchildurl_ref = CFURLCreateWithString(NULL, CFSTR("?whatever"), cfchildurl_ref); + + NSDictionary *error_userInfo = @{@"a": @1, @"b" : @2}; + NSError *nserror = [[NSError alloc] initWithDomain:@"Foobar" code:12 userInfo:error_userInfo]; + NSError **nserrorptr = &nserror; + + NSBundle* bundle_string = [[NSBundle alloc] initWithPath:@"/System/Library/Frameworks/Accelerate.framework"]; + NSBundle* bundle_url = [[NSBundle alloc] initWithURL:[[NSURL alloc] initWithString:@"file://localhost/System/Library/Frameworks/Foundation.framework"]]; + + NSBundle* main_bundle = [NSBundle mainBundle]; + + NSArray* bundles = [NSBundle allBundles]; + + NSURL *nsurl0; + + for (NSBundle* bundle in bundles) + { + nsurl0 = [bundle bundleURL]; + } + + NSException* except0 = [[NSException alloc] initWithName:@"TheGuyWhoHasNoName" reason:@"First" userInfo:nil]; + NSException* except1 = [[NSException alloc] initWithName:@"TheGuyWhoHasNoName~1" reason:@"Second" userInfo:nil]; + NSException* except2 = [[NSException alloc] initWithName:@"TheGuyWhoHasNoName`2" reason:@"Third" userInfo:nil]; + NSException* except3 = [[NSException alloc] initWithName:@"TheGuyWhoHasNoName/3" reason:@"Fourth" userInfo:nil]; + + NSURL *nsurl = [[NSURL alloc] initWithString:@"http://www.foo.bar"]; + NSURL *nsurl2 = [NSURL URLWithString:@"page.html" relativeToURL:nsurl]; + NSURL *nsurl3 = [NSURL URLWithString:@"?whatever" relativeToURL:nsurl2]; + + NSDate *date1 = [NSDate dateWithNaturalLanguageString:@"6pm April 10, 1985"]; + NSDate *date2 = [NSDate dateWithNaturalLanguageString:@"12am January 1, 2011"]; + NSDate *date3 = [NSDate date]; + NSDate *date4 = [NSDate dateWithTimeIntervalSince1970:24*60*60]; + NSDate *date5 = [NSDate dateWithTimeIntervalSinceReferenceDate: floor([[NSDate date] timeIntervalSinceReferenceDate])]; + + CFAbsoluteTime date1_abs = CFDateGetAbsoluteTime(date1); + CFAbsoluteTime date2_abs = CFDateGetAbsoluteTime(date2); + CFAbsoluteTime date3_abs = CFDateGetAbsoluteTime(date3); + CFAbsoluteTime date4_abs = CFDateGetAbsoluteTime(date4); + CFAbsoluteTime date5_abs = CFDateGetAbsoluteTime(date5); + + NSIndexSet *iset1 = [[NSIndexSet alloc] initWithIndexesInRange:NSMakeRange(1, 4)]; + NSIndexSet *iset2 = [[NSIndexSet alloc] initWithIndexesInRange:NSMakeRange(1, 512)]; + + NSMutableIndexSet *imset = [[NSMutableIndexSet alloc] init]; + [imset addIndex:1936]; + [imset addIndex:7]; + [imset addIndex:9]; + [imset addIndex:11]; + [imset addIndex:24]; + [imset addIndex:41]; + [imset addIndex:58]; + [imset addIndex:61]; + [imset addIndex:62]; + [imset addIndex:63]; + + CFTimeZoneRef cupertino = CFTimeZoneCreateWithName ( + NULL, + CFSTR("PST"), + YES); + CFTimeZoneRef home = CFTimeZoneCreateWithName ( + NULL, + CFSTR("Europe/Rome"), + YES); + CFTimeZoneRef europe = CFTimeZoneCreateWithName ( + NULL, + CFSTR("CET"), + YES); + + NSTimeZone *cupertino_ns = [NSTimeZone timeZoneWithAbbreviation:@"PST"]; + NSTimeZone *home_ns = [NSTimeZone timeZoneWithName:@"Europe/Rome"]; + NSTimeZone *europe_ns = [NSTimeZone timeZoneWithAbbreviation:@"CET"]; + + CFGregorianUnits cf_greg_units = {1,3,5,12,5,7}; + CFGregorianDate cf_greg_date = CFAbsoluteTimeGetGregorianDate(CFDateGetAbsoluteTime(date1), NULL); + CFRange cf_range = {4,4}; + NSPoint ns_point = {4,4}; + NSRange ns_range = {4,4}; + + NSRect ns_rect = {{1,1},{5,5}}; + NSRect* ns_rect_ptr = &ns_rect; + NSRectArray ns_rect_arr = &ns_rect; + NSSize ns_size = {5,7}; + NSSize* ns_size_ptr = &ns_size; + + CGSize cg_size = {1,6}; + CGPoint cg_point = {2,7}; + CGRect cg_rect = {{1,2}, {7,7}}; + +#ifndef IOS + RGBColor rgb_color = {3,56,35}; + RGBColor* rgb_color_ptr = &rgb_color; +#endif + + Rect rect = {4,8,4,7}; + Rect* rect_ptr = ▭ + + Point point = {7,12}; + Point* point_ptr = &point; + +#ifndef IOS + HIPoint hi_point = {7,12}; + HIRect hi_rect = {{3,5},{4,6}}; +#endif + + SEL foo_selector = @selector(foo_selector_impl); + + CFMutableBitVectorRef mut_bv = CFBitVectorCreateMutable(NULL, 64); + CFBitVectorSetCount(mut_bv, 50); + CFBitVectorSetBitAtIndex(mut_bv, 0, 1); + CFBitVectorSetBitAtIndex(mut_bv, 1, 1); + CFBitVectorSetBitAtIndex(mut_bv, 2, 1); + CFBitVectorSetBitAtIndex(mut_bv, 5, 1); + CFBitVectorSetBitAtIndex(mut_bv, 6, 1); + CFBitVectorSetBitAtIndex(mut_bv, 8, 1); + CFBitVectorSetBitAtIndex(mut_bv, 10, 1); + CFBitVectorSetBitAtIndex(mut_bv, 11, 1); + CFBitVectorSetBitAtIndex(mut_bv, 16, 1); + CFBitVectorSetBitAtIndex(mut_bv, 17, 1); + CFBitVectorSetBitAtIndex(mut_bv, 19, 1); + CFBitVectorSetBitAtIndex(mut_bv, 20, 1); + CFBitVectorSetBitAtIndex(mut_bv, 22, 1); + CFBitVectorSetBitAtIndex(mut_bv, 24, 1); + CFBitVectorSetBitAtIndex(mut_bv, 28, 1); + CFBitVectorSetBitAtIndex(mut_bv, 29, 1); + CFBitVectorSetBitAtIndex(mut_bv, 30, 1); + CFBitVectorSetBitAtIndex(mut_bv, 30, 1); + CFBitVectorSetBitAtIndex(mut_bv, 31, 1); + CFBitVectorSetBitAtIndex(mut_bv, 34, 1); + CFBitVectorSetBitAtIndex(mut_bv, 35, 1); + CFBitVectorSetBitAtIndex(mut_bv, 37, 1); + CFBitVectorSetBitAtIndex(mut_bv, 39, 1); + CFBitVectorSetBitAtIndex(mut_bv, 40, 1); + CFBitVectorSetBitAtIndex(mut_bv, 41, 1); + CFBitVectorSetBitAtIndex(mut_bv, 43, 1); + CFBitVectorSetBitAtIndex(mut_bv, 47, 1); + + Molecule *molecule = [Molecule new]; + + Class myclass = NSClassFromString(@"NSValue"); + Class myclass2 = [str0 class]; + Class myclass3 = [molecule class]; + Class myclass4 = NSClassFromString(@"NSMutableArray"); + Class myclass5 = [nil class]; + + NSArray *components = @[@"usr", @"blah", @"stuff"]; + NSString *path = [NSString pathWithComponents: components]; + + [molecule addObserver:[My_KVO_Observer new] forKeyPath:@"atoms" options:0 context:NULL]; // Set break point at this line. + [newMutableDictionary addObserver:[My_KVO_Observer new] forKeyPath:@"weirdKeyToKVO" options:NSKeyValueObservingOptionNew context:NULL]; + + [molecule setAtoms:nil]; + [molecule setAtoms:[NSMutableArray new]]; + + [pool drain]; + return 0; +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/nsindexpath/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/nsindexpath/Makefile new file mode 100644 index 00000000000..8b322ff320b --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/nsindexpath/Makefile @@ -0,0 +1,8 @@ +OBJC_SOURCES := main.m + +CFLAGS_EXTRAS := -w + + + +LD_EXTRAS := -framework Foundation +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/nsindexpath/TestDataFormatterNSIndexPath.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/nsindexpath/TestDataFormatterNSIndexPath.py new file mode 100644 index 00000000000..12461ab03de --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/nsindexpath/TestDataFormatterNSIndexPath.py @@ -0,0 +1,112 @@ +# encoding: utf-8 +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class NSIndexPathDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def appkit_tester_impl(self, commands): + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.m", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type synth clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + commands() + + @skipUnlessDarwin + @expectedFailureAll(archs=['i386'], bugnumber="rdar://28656605") + @expectedFailureAll(archs=['armv7', 'armv7k', 'arm64_32'], bugnumber="rdar://problem/34561607") # NSIndexPath formatter isn't working for 32-bit arm + def test_nsindexpath_with_run_command(self): + """Test formatters for NSIndexPath.""" + self.appkit_tester_impl(self.nsindexpath_data_formatter_commands) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.m', '// break here') + + def nsindexpath_data_formatter_commands(self): + # check 'frame variable' + self.expect( + 'frame variable --ptr-depth=1 -d run -- indexPath1', + substrs=['[0] = 1']) + self.expect( + 'frame variable --ptr-depth=1 -d run -- indexPath2', + substrs=[ + '[0] = 1', + '[1] = 2']) + self.expect( + 'frame variable --ptr-depth=1 -d run -- indexPath3', + substrs=[ + '[0] = 1', + '[1] = 2', + '[2] = 3']) + self.expect( + 'frame variable --ptr-depth=1 -d run -- indexPath4', + substrs=[ + '[0] = 1', + '[1] = 2', + '[2] = 3', + '[3] = 4']) + self.expect( + 'frame variable --ptr-depth=1 -d run -- indexPath5', + substrs=[ + '[0] = 1', + '[1] = 2', + '[2] = 3', + '[3] = 4', + '[4] = 5']) + + # and 'expression' + self.expect( + 'expression --ptr-depth=1 -d run -- indexPath1', + substrs=['[0] = 1']) + self.expect( + 'expression --ptr-depth=1 -d run -- indexPath2', + substrs=[ + '[0] = 1', + '[1] = 2']) + self.expect( + 'expression --ptr-depth=1 -d run -- indexPath3', + substrs=[ + '[0] = 1', + '[1] = 2', + '[2] = 3']) + self.expect('expression --ptr-depth=1 -d run -- indexPath4', + substrs=['[0] = 1', '[1] = 2', '[2] = 3', '[3] = 4']) + self.expect( + 'expression --ptr-depth=1 -d run -- indexPath5', + substrs=[ + '[0] = 1', + '[1] = 2', + '[2] = 3', + '[3] = 4', + '[4] = 5']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/nsindexpath/main.m b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/nsindexpath/main.m new file mode 100644 index 00000000000..e34cf522299 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/nsindexpath/main.m @@ -0,0 +1,30 @@ +//===-- main.m ------------------------------------------------*- ObjC -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#import <Foundation/Foundation.h> + +int main(int argc, const char **argv) +{ + @autoreleasepool + { + const NSUInteger values[] = { 1, 2, 3, 4, 5 }; + + NSIndexPath* indexPath1 = [NSIndexPath indexPathWithIndexes:values length:1]; + NSIndexPath* indexPath2 = [NSIndexPath indexPathWithIndexes:values length:2]; + NSIndexPath* indexPath3 = [NSIndexPath indexPathWithIndexes:values length:3]; + NSIndexPath* indexPath4 = [NSIndexPath indexPathWithIndexes:values length:4]; + NSIndexPath* indexPath5 = [NSIndexPath indexPathWithIndexes:values length:5]; + + NSLog(@"%@", indexPath1); // break here + NSLog(@"%@", indexPath2); + NSLog(@"%@", indexPath3); + NSLog(@"%@", indexPath4); + NSLog(@"%@", indexPath5); + } + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/nsstring/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/nsstring/Makefile new file mode 100644 index 00000000000..8b322ff320b --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/nsstring/Makefile @@ -0,0 +1,8 @@ +OBJC_SOURCES := main.m + +CFLAGS_EXTRAS := -w + + + +LD_EXTRAS := -framework Foundation +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/nsstring/TestDataFormatterNSString.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/nsstring/TestDataFormatterNSString.py new file mode 100644 index 00000000000..6480025e2e1 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/nsstring/TestDataFormatterNSString.py @@ -0,0 +1,120 @@ +# encoding: utf-8 +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class NSStringDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def appkit_tester_impl(self, commands): + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.m", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type synth clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + commands() + + @skipUnlessDarwin + @no_debug_info_test + def test_nsstring_with_run_command(self): + """Test formatters for NSString.""" + self.appkit_tester_impl(self.nsstring_data_formatter_commands) + + @skipUnlessDarwin + @no_debug_info_test + def test_rdar11106605_with_run_command(self): + """Check that Unicode characters come out of CFString summary correctly.""" + self.appkit_tester_impl(self.rdar11106605_commands) + + @skipUnlessDarwin + @no_debug_info_test + def test_nsstring_withNULS_with_run_command(self): + """Test formatters for NSString.""" + self.appkit_tester_impl(self.nsstring_withNULs_commands) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.m', '// break here') + + def rdar11106605_commands(self): + """Check that Unicode characters come out of CFString summary correctly.""" + self.expect('frame variable italian', substrs=[ + 'L\'Italia è una Repubblica democratica, fondata sul lavoro. La sovranità appartiene al popolo, che la esercita nelle forme e nei limiti della Costituzione.']) + self.expect('frame variable french', substrs=[ + 'Que veut cette horde d\'esclaves, De traîtres, de rois conjurés?']) + self.expect('frame variable german', substrs=[ + 'Über-Ich und aus den Ansprüchen der sozialen Umwelt']) + self.expect('frame variable japanese', substrs=['色は匂へど散りぬるを']) + self.expect('frame variable hebrew', substrs=['לילה טוב']) + + def nsstring_data_formatter_commands(self): + self.expect('frame variable str0 str1 str2 str3 str4 str5 str6 str8 str9 str10 str11 label1 label2 processName str12', + substrs=['(NSString *) str1 = ', ' @"A rather short ASCII NSString object is here"', + # '(NSString *) str0 = ',' @"255"', + '(NSString *) str1 = ', ' @"A rather short ASCII NSString object is here"', + '(NSString *) str2 = ', ' @"A rather short UTF8 NSString object is here"', + '(NSString *) str3 = ', ' @"A string made with the at sign is here"', + '(NSString *) str4 = ', ' @"This is string number 4 right here"', + '(NSString *) str5 = ', ' @"{{1, 1}, {5, 5}}"', + '(NSString *) str6 = ', ' @"1ST"', + '(NSString *) str8 = ', ' @"hasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTime', + '(NSString *) str9 = ', ' @"a very much boring task to write a string this way!!', + '(NSString *) str10 = ', ' @"This is a Unicode string σ number 4 right here"', + '(NSString *) str11 = ', ' @"__NSCFString"', + '(NSString *) label1 = ', ' @"Process Name: "', + '(NSString *) label2 = ', ' @"Process Id: "', + '(NSString *) str12 = ', ' @"Process Name: a.out Process Id:']) + self.expect( + 'frame variable attrString mutableAttrString mutableGetConst', + substrs=[ + '(NSAttributedString *) attrString = ', + ' @"hello world from foo"', + '(NSAttributedString *) mutableAttrString = ', + ' @"hello world from foo"', + '(NSString *) mutableGetConst = ', + ' @"foo said this string needs to be very long so much longer than whatever other string has been seen ever before by anyone of the mankind that of course this is still not long enough given what foo our friend foo our lovely dearly friend foo desired of us so i am adding more stuff here for the sake of it and for the joy of our friend who is named guess what just foo. hence, dear friend foo, stay safe, your string is now long enough to accommodate your testing need and I will make sure that if not we extend it with even more fuzzy random meaningless words pasted one after the other from a long tiresome friday evening spent working in my office. my office mate went home but I am still randomly typing just for the fun of seeing what happens of the length of a Mutable String in Cocoa if it goes beyond one byte.. so be it, dear foo"']) + + self.expect('expr -d run-target -- path', substrs=['usr/blah/stuff']) + self.expect('frame variable path', substrs=['usr/blah/stuff']) + + def nsstring_withNULs_commands(self): + """Check that the NSString formatter supports embedded NULs in the text""" + self.expect( + 'po strwithNULs', + substrs=['a very much boring task to write']) + self.expect('expr [strwithNULs length]', substrs=['54']) + self.expect('frame variable strwithNULs', substrs=[ + '@"a very much boring task to write\\0a string this way!!']) + self.expect('po strwithNULs2', substrs=[ + 'a very much boring task to write']) + self.expect('expr [strwithNULs2 length]', substrs=['52']) + self.expect('frame variable strwithNULs2', substrs=[ + '@"a very much boring task to write\\0a string this way!!']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/nsstring/main.m b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/nsstring/main.m new file mode 100644 index 00000000000..b0d926fd54e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/nsstring/main.m @@ -0,0 +1,98 @@ +//===-- main.m ------------------------------------------------*- ObjC -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#import <Foundation/Foundation.h> + +#if defined(__APPLE__) +#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) +#define IOS +#endif +#endif + +#if defined(IOS) +#import <Foundation/NSGeometry.h> +#else +#import <Carbon/Carbon.h> +#endif + +int main (int argc, const char * argv[]) +{ + + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + + NSString *str0 = [[NSNumber numberWithUnsignedLongLong:0xFF] stringValue]; + NSString *str1 = [NSString stringWithCString:"A rather short ASCII NSString object is here" encoding:NSASCIIStringEncoding]; + NSString *str2 = [NSString stringWithUTF8String:"A rather short UTF8 NSString object is here"]; + NSString *str3 = @"A string made with the at sign is here"; + NSString *str4 = [NSString stringWithFormat:@"This is string number %ld right here", (long)4]; + NSRect ns_rect_4str = {{1,1},{5,5}}; + NSString* str5 = NSStringFromRect(ns_rect_4str); + NSString* str6 = [@"/usr/doc/README.1ST" pathExtension]; + const unichar myCharacters[] = {0x03C3,'x','x'}; + NSString *str7 = [NSString stringWithCharacters: myCharacters + length: sizeof myCharacters / sizeof *myCharacters]; + NSString* str8 = [@"/usr/doc/file.hasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTime" pathExtension]; + const unichar myOtherCharacters[] = {'a',' ', 'v','e','r','y',' ', + 'm','u','c','h',' ','b','o','r','i','n','g',' ','t','a','s','k', + ' ','t','o',' ','w','r','i','t','e', ' ', 'a', ' ', 's', 't', 'r', 'i', 'n', 'g', ' ', + 't','h','i','s',' ','w','a','y','!','!',0x03C3, 0}; + NSString *str9 = [NSString stringWithCharacters: myOtherCharacters + length: sizeof myOtherCharacters / sizeof *myOtherCharacters]; + const unichar myNextCharacters[] = {0x03C3, 0x0000}; + NSString *str10 = [NSString stringWithFormat:@"This is a Unicode string %S number %ld right here", myNextCharacters, (long)4]; + NSString *str11 = NSStringFromClass([str10 class]); + NSString *label1 = @"Process Name: "; + NSString *label2 = @"Process Id: "; + NSString *processName = [[NSProcessInfo processInfo] processName]; + NSString *processID = [NSString stringWithFormat:@"%d", [[NSProcessInfo processInfo] processIdentifier]]; + NSString *str12 = [NSString stringWithFormat:@"%@ %@ %@ %@", label1, processName, label2, processID]; + NSString *eAcute = [NSString stringWithFormat: @"%C", 0x00E9]; + NSString *randomHaziChar = [NSString stringWithFormat: @"%C", 0x9DC5]; + NSString *japanese = @"色は匂へど散りぬるを"; + NSString *italian = @"L'Italia è una Repubblica democratica, fondata sul lavoro. La sovranità appartiene al popolo, che la esercita nelle forme e nei limiti della Costituzione."; + NSString* french = @"Que veut cette horde d'esclaves, De traîtres, de rois conjurés?"; + NSString* german = @"Über-Ich und aus den Ansprüchen der sozialen Umwelt"; + void* data_set[3] = {str1,str2,str3}; + NSString *hebrew = [NSString stringWithString:@"לילה טוב"]; + + NSAttributedString* attrString = [[NSAttributedString alloc] initWithString:@"hello world from foo" attributes:[NSDictionary new]]; + [attrString isEqual:nil]; + NSAttributedString* mutableAttrString = [[NSMutableAttributedString alloc] initWithString:@"hello world from foo" attributes:[NSDictionary new]]; + [mutableAttrString isEqual:nil]; + + NSString* mutableString = [[NSMutableString alloc] initWithString:@"foo"]; + [mutableString insertString:@"foo said this string needs to be very long so much longer than whatever other string has been seen ever before by anyone of the mankind that of course this is still not long enough given what foo our friend foo our lovely dearly friend foo desired of us so i am adding more stuff here for the sake of it and for the joy of our friend who is named guess what just foo. hence, dear friend foo, stay safe, your string is now long enough to accommodate your testing need and I will make sure that if not we extend it with even more fuzzy random meaningless words pasted one after the other from a long tiresome friday evening spent working in my office. my office mate went home but I am still randomly typing just for the fun of seeing what happens of the length of a Mutable String in Cocoa if it goes beyond one byte.. so be it, dear " atIndex:0]; + + NSString* mutableGetConst = [NSString stringWithCString:[mutableString cString]]; + + [mutableGetConst length]; + CFMutableStringRef mutable_string_ref = CFStringCreateMutable(NULL,100); + CFStringAppend(mutable_string_ref, CFSTR("Wish ya knew")); + CFStringRef cfstring_ref = CFSTR("HELLO WORLD"); + + NSArray *components = @[@"usr", @"blah", @"stuff"]; + NSString *path = [NSString pathWithComponents: components]; + + const unichar someOfTheseAreNUL[] = {'a',' ', 'v','e','r','y',' ', + 'm','u','c','h',' ','b','o','r','i','n','g',' ','t','a','s','k', + ' ','t','o',' ','w','r','i','t','e', 0, 'a', ' ', 's', 't', 'r', 'i', 'n', 'g', ' ', + 't','h','i','s',' ','w','a','y','!','!', 0x03C3, 0}; + NSString *strwithNULs = [NSString stringWithCharacters: someOfTheseAreNUL + length: sizeof someOfTheseAreNUL / sizeof *someOfTheseAreNUL]; + + const unichar someOfTheseAreNUL2[] = {'a',' ', 'v','e','r','y',' ', + 'm','u','c','h',' ','b','o','r','i','n','g',' ','t','a','s','k', + ' ','t','o',' ','w','r','i','t','e', 0, 'a', ' ', 's', 't', 'r', 'i', 'n', 'g', ' ', + 't','h','i','s',' ','w','a','y','!','!'}; + NSString *strwithNULs2 = [NSString stringWithCharacters: someOfTheseAreNUL2 + length: sizeof someOfTheseAreNUL2 / sizeof *someOfTheseAreNUL2]; + + [pool drain]; // break here + return 0; +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-proper-plurals/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-proper-plurals/Makefile new file mode 100644 index 00000000000..8b322ff320b --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-proper-plurals/Makefile @@ -0,0 +1,8 @@ +OBJC_SOURCES := main.m + +CFLAGS_EXTRAS := -w + + + +LD_EXTRAS := -framework Foundation +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-proper-plurals/TestFormattersOneIsSingular.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-proper-plurals/TestFormattersOneIsSingular.py new file mode 100644 index 00000000000..4611e162ada --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-proper-plurals/TestFormattersOneIsSingular.py @@ -0,0 +1,77 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class DataFormatterOneIsSingularTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipUnlessDarwin + def test_one_is_singular_with_run_command(self): + """Test that 1 item is not as reported as 1 items.""" + self.build() + self.oneness_data_formatter_commands() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.m', '// Set break point at this line.') + + def oneness_data_formatter_commands(self): + """Test that 1 item is not as reported as 1 items.""" + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.m", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type synth clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + # Now check that we are displaying Cocoa classes correctly + self.expect('frame variable key', + substrs=['@"1 element"']) + self.expect('frame variable key', matching=False, + substrs=['1 elements']) + self.expect('frame variable value', + substrs=['@"1 element"']) + self.expect('frame variable value', matching=False, + substrs=['1 elements']) + self.expect('frame variable dict', + substrs=['1 key/value pair']) + self.expect('frame variable dict', matching=False, + substrs=['1 key/value pairs']) + self.expect('frame variable imset', + substrs=['1 index']) + self.expect('frame variable imset', matching=False, + substrs=['1 indexes']) + self.expect('frame variable binheap_ref', + substrs=['@"1 item"']) + self.expect('frame variable binheap_ref', matching=False, + substrs=['1 items']) + self.expect('frame variable immutableData', + substrs=['1 byte']) + self.expect('frame variable immutableData', matching=False, + substrs=['1 bytes']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-proper-plurals/main.m b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-proper-plurals/main.m new file mode 100644 index 00000000000..dc9e5609fbe --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-proper-plurals/main.m @@ -0,0 +1,30 @@ +//===-- main.m ------------------------------------------------*- ObjC -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#import <Foundation/Foundation.h> + +int main (int argc, const char * argv[]) +{ + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + + NSArray* key = [NSArray arrayWithObjects:@"foo",nil]; + NSArray* value = [NSArray arrayWithObjects:@"key",nil]; + NSDictionary *dict = [NSDictionary dictionaryWithObjects:value forKeys:key]; + + NSMutableIndexSet *imset = [[NSMutableIndexSet alloc] init]; + [imset addIndex:4]; + + CFBinaryHeapRef binheap_ref = CFBinaryHeapCreate(NULL, 15, &kCFStringBinaryHeapCallBacks, NULL); + CFBinaryHeapAddValue(binheap_ref, CFSTR("Hello world")); + + NSData *immutableData = [[NSData alloc] initWithBytes:"HELLO" length:1]; + + [pool drain];// Set break point at this line. + return 0; +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-ptr-to-array/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-ptr-to-array/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-ptr-to-array/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-ptr-to-array/TestPtrToArrayFormatting.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-ptr-to-array/TestPtrToArrayFormatting.py new file mode 100644 index 00000000000..b3c794f3f0c --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-ptr-to-array/TestPtrToArrayFormatting.py @@ -0,0 +1,56 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class PtrToArrayDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_with_run_command(self): + """Test that LLDB handles the clang typeclass Paren correctly.""" + self.build() + self.data_formatter_commands() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + def data_formatter_commands(self): + """Test that LLDB handles the clang typeclass Paren correctly.""" + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format delete hex', check=False) + self.runCmd('type summary clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.expect('p *(int (*)[3])foo', + substrs=['(int [3]) $', '[0] = 1', '[1] = 2', '[2] = 3']) + + self.expect('p *(int (*)[3])foo', matching=False, + substrs=['01 00 00 00 02 00 00 00 03 00 00 00']) + self.expect('p *(int (*)[3])foo', matching=False, + substrs=['0x000000030000000200000001']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-ptr-to-array/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-ptr-to-array/main.cpp new file mode 100644 index 00000000000..334369576a4 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-ptr-to-array/main.cpp @@ -0,0 +1,16 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +bool bar(int const *foo) { + return foo != 0; // Set break point at this line. +} + +int main() { + int foo[] = {1,2,3}; + return bar(foo); +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-python-synth/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-python-synth/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-python-synth/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py new file mode 100644 index 00000000000..5f908f76b0a --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py @@ -0,0 +1,289 @@ +""" +Test lldb data formatter subsystem. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class PythonSynthDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipIfFreeBSD # llvm.org/pr20545 bogus output confuses buildbot parser + def test_with_run_command(self): + """Test data formatter commands.""" + self.build() + self.data_formatter_commands() + + def test_rdar10960550_with_run_command(self): + """Test data formatter commands.""" + self.build() + self.rdar10960550_formatter_commands() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + self.line2 = line_number('main.cpp', + '// Set cast break point at this line.') + self.line3 = line_number( + 'main.cpp', '// Set second cast break point at this line.') + + def data_formatter_commands(self): + """Test using Python synthetic children provider.""" + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + process = self.dbg.GetSelectedTarget().GetProcess() + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + self.runCmd('type synth clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + # print the f00_1 variable without a synth + self.expect("frame variable f00_1", + substrs=['a = 1', + 'b = 2', + 'r = 34']) + + # now set up the synth + self.runCmd("script from fooSynthProvider import *") + self.runCmd("type synth add -l fooSynthProvider foo") + self.expect("type synthetic list foo", substrs=['fooSynthProvider']) + + # note that the value of fake_a depends on target byte order + if process.GetByteOrder() == lldb.eByteOrderLittle: + fake_a_val = 0x02000000 + else: + fake_a_val = 0x00000100 + + # check that we get the two real vars and the fake_a variables + self.expect("frame variable f00_1", + substrs=['r = 34', + 'fake_a = %d' % fake_a_val, + 'a = 1']) + + # check that we do not get the extra vars + self.expect("frame variable f00_1", matching=False, + substrs=['b = 2']) + + # check access to members by name + self.expect('frame variable f00_1.fake_a', + substrs=['%d' % fake_a_val]) + + # check access to members by index + self.expect('frame variable f00_1[1]', + substrs=['%d' % fake_a_val]) + + # put synthetic children in summary in several combinations + self.runCmd( + "type summary add --summary-string \"fake_a=${svar.fake_a}\" foo") + self.expect('frame variable f00_1', + substrs=['fake_a=%d' % fake_a_val]) + self.runCmd( + "type summary add --summary-string \"fake_a=${svar[1]}\" foo") + self.expect('frame variable f00_1', + substrs=['fake_a=%d' % fake_a_val]) + + # clear the summary + self.runCmd("type summary delete foo") + + # check that the caching does not span beyond the stopoint + self.runCmd("n") + + if process.GetByteOrder() == lldb.eByteOrderLittle: + fake_a_val = 0x02000000 + else: + fake_a_val = 0x00000200 + + self.expect("frame variable f00_1", + substrs=['r = 34', + 'fake_a = %d' % fake_a_val, + 'a = 2']) + + # check that altering the object also alters fake_a + self.runCmd("expr f00_1.a = 280") + + if process.GetByteOrder() == lldb.eByteOrderLittle: + fake_a_val = 0x02000001 + else: + fake_a_val = 0x00011800 + + self.expect("frame variable f00_1", + substrs=['r = 34', + 'fake_a = %d' % fake_a_val, + 'a = 280']) + + # check that expanding a pointer does the right thing + if process.GetByteOrder() == lldb.eByteOrderLittle: + fake_a_val = 0x0d000000 + else: + fake_a_val = 0x00000c00 + + self.expect("frame variable --ptr-depth 1 f00_ptr", + substrs=['r = 45', + 'fake_a = %d' % fake_a_val, + 'a = 12']) + + # now add a filter.. it should fail + self.expect("type filter add foo --child b --child j", error=True, + substrs=['cannot add']) + + # we get the synth again.. + self.expect('frame variable f00_1', matching=False, + substrs=['b = 1', + 'j = 17']) + self.expect("frame variable --ptr-depth 1 f00_ptr", + substrs=['r = 45', + 'fake_a = %d' % fake_a_val, + 'a = 12']) + + # now delete the synth and add the filter + self.runCmd("type synth delete foo") + self.runCmd("type filter add foo --child b --child j") + + self.expect('frame variable f00_1', + substrs=['b = 2', + 'j = 18']) + self.expect("frame variable --ptr-depth 1 f00_ptr", matching=False, + substrs=['r = 45', + 'fake_a = %d' % fake_a_val, + 'a = 12']) + + # now add the synth and it should fail + self.expect("type synth add -l fooSynthProvider foo", error=True, + substrs=['cannot add']) + + # check the listing + self.expect('type synth list', matching=False, + substrs=['foo', + 'Python class fooSynthProvider']) + self.expect('type filter list', + substrs=['foo', + '.b', + '.j']) + + # delete the filter, add the synth + self.runCmd("type filter delete foo") + self.runCmd("type synth add -l fooSynthProvider foo") + + self.expect('frame variable f00_1', matching=False, + substrs=['b = 2', + 'j = 18']) + self.expect("frame variable --ptr-depth 1 f00_ptr", + substrs=['r = 45', + 'fake_a = %d' % fake_a_val, + 'a = 12']) + + # check the listing + self.expect('type synth list', + substrs=['foo', + 'Python class fooSynthProvider']) + self.expect('type filter list', matching=False, + substrs=['foo', + '.b', + '.j']) + + # delete the synth and check that we get good output + self.runCmd("type synth delete foo") + + self.expect("frame variable f00_1", + substrs=['a = 280', + 'b = 2', + 'j = 18']) + + self.expect("frame variable f00_1", matching=False, + substrs=['fake_a = ']) + + def rdar10960550_formatter_commands(self): + """Test that synthetic children persist stoppoints.""" + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + # The second breakpoint is on a multi-line expression, so the comment + # can't be on the right line... + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line2, num_expected_locations=1, loc_exact=False) + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line3, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + self.runCmd('type synth clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.runCmd("command script import ./ftsp.py --allow-reload") + self.runCmd("type synth add -l ftsp.ftsp wrapint") + + # we need to check that the VO is properly updated so that the same synthetic children are reused + # but their values change correctly across stop-points - in order to do this, self.runCmd("next") + # does not work because it forces a wipe of the stack frame - this is why we are using this more contrived + # mechanism to achieve our goal of preserving test_cast as a VO + test_cast = self.dbg.GetSelectedTarget().GetProcess( + ).GetSelectedThread().GetSelectedFrame().FindVariable('test_cast') + + str_cast = str(test_cast) + + if self.TraceOn(): + print(str_cast) + + self.assertTrue(str_cast.find('A') != -1, 'could not find A in output') + self.assertTrue(str_cast.find('B') != -1, 'could not find B in output') + self.assertTrue(str_cast.find('C') != -1, 'could not find C in output') + self.assertTrue(str_cast.find('D') != -1, 'could not find D in output') + self.assertTrue( + str_cast.find("4 = '\\0'") != -1, + 'could not find item 4 == 0') + + self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread().StepOver() + + str_cast = str(test_cast) + + if self.TraceOn(): + print(str_cast) + + # we detect that all the values of the child objects have changed - but the counter-generated item + # is still fixed at 0 because it is cached - this would fail if update(self): in ftsp returned False + # or if synthetic children were not being preserved + self.assertTrue(str_cast.find('Q') != -1, 'could not find Q in output') + self.assertTrue(str_cast.find('X') != -1, 'could not find X in output') + self.assertTrue(str_cast.find('T') != -1, 'could not find T in output') + self.assertTrue(str_cast.find('F') != -1, 'could not find F in output') + self.assertTrue( + str_cast.find("4 = '\\0'") != -1, + 'could not find item 4 == 0') diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-python-synth/fooSynthProvider.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-python-synth/fooSynthProvider.py new file mode 100644 index 00000000000..45fb00468e0 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-python-synth/fooSynthProvider.py @@ -0,0 +1,30 @@ +import lldb + + +class fooSynthProvider: + + def __init__(self, valobj, dict): + self.valobj = valobj + self.int_type = valobj.GetType().GetBasicType(lldb.eBasicTypeInt) + + def num_children(self): + return 3 + + def get_child_at_index(self, index): + if index == 0: + child = self.valobj.GetChildMemberWithName('a') + if index == 1: + child = self.valobj.CreateChildAtOffset('fake_a', 1, self.int_type) + if index == 2: + child = self.valobj.GetChildMemberWithName('r') + return child + + def get_child_index(self, name): + if name == 'a': + return 0 + if name == 'fake_a': + return 1 + return 2 + + def update(self): + return True diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-python-synth/ftsp.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-python-synth/ftsp.py new file mode 100644 index 00000000000..b96dbac6f50 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-python-synth/ftsp.py @@ -0,0 +1,40 @@ +import lldb + +counter = 0 + + +class ftsp: + + def __init__(self, valobj, dict): + self.valobj = valobj + + def num_children(self): + if self.char.IsValid(): + return 5 + return 0 + + def get_child_index(self, name): + return 0 + + def get_child_at_index(self, index): + if index == 0: + return self.x.Cast(self.char) + if index == 4: + return self.valobj.CreateValueFromExpression( + str(index), '(char)(' + str(self.count) + ')') + return self.x.CreateChildAtOffset(str(index), + index, + self.char) + + def update(self): + self.x = self.valobj.GetChildMemberWithName('x') + self.char = self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar) + global counter + self.count = counter + counter = counter + 1 + return True # important: if we return False here, or fail to return, the test will fail + + +def __lldb_init_module(debugger, dict): + global counter + counter = 0 diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-python-synth/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-python-synth/main.cpp new file mode 100644 index 00000000000..f45a2abfb9f --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-python-synth/main.cpp @@ -0,0 +1,66 @@ +struct foo +{ + int a; + int b; + int c; + int d; + int e; + int f; + int g; + int h; + int i; + int j; + int k; + int l; + int m; + int n; + int o; + int p; + int q; + int r; + + foo(int X) : + a(X), + b(X+1), + c(X+3), + d(X+5), + e(X+7), + f(X+9), + g(X+11), + h(X+13), + i(X+15), + j(X+17), + k(X+19), + l(X+21), + m(X+23), + n(X+25), + o(X+27), + p(X+29), + q(X+31), + r(X+33) {} +}; + +struct wrapint +{ + int x; + wrapint(int X) : x(X) {} +}; + +int main() +{ + foo f00_1(1); + foo *f00_ptr = new foo(12); + + f00_1.a++; // Set break point at this line. + + wrapint test_cast('A' + + 256*'B' + + 256*256*'C'+ + 256*256*256*'D'); + // Set cast break point at this line. + test_cast.x = 'Q' + + 256*'X' + + 256*256*'T'+ + 256*256*256*'F'; + return 0; // Set second cast break point at this line. +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-script/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-script/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-script/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-script/TestDataFormatterScript.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-script/TestDataFormatterScript.py new file mode 100644 index 00000000000..14387cde194 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-script/TestDataFormatterScript.py @@ -0,0 +1,182 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class ScriptDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_with_run_command(self): + """Test data formatter commands.""" + self.build() + self.data_formatter_commands() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + def data_formatter_commands(self): + """Test that that file and class static variables display correctly.""" + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + # Set the script here to ease the formatting + script = 'a = valobj.GetChildMemberWithName(\'integer\'); a_val = a.GetValue(); str = \'Hello from Python, \' + a_val + \' time\'; return str + (\'!\' if a_val == \'1\' else \'s!\');' + + self.runCmd( + "type summary add i_am_cool --python-script \"%s\"" % + script) + self.expect('type summary list i_am_cool', substrs=[script]) + + self.expect("frame variable one", + substrs=['Hello from Python', + '1 time!']) + + self.expect("frame variable two", + substrs=['Hello from Python', + '4 times!']) + + self.runCmd("n") # skip ahead to make values change + + self.expect("frame variable three", + substrs=['Hello from Python, 10 times!', + 'Hello from Python, 4 times!']) + + self.runCmd("n") # skip ahead to make values change + + self.expect("frame variable two", + substrs=['Hello from Python', + '1 time!']) + + script = 'a = valobj.GetChildMemberWithName(\'integer\'); a_val = a.GetValue(); str = \'int says \' + a_val; return str;' + + # Check that changes in the script are immediately reflected + self.runCmd( + "type summary add i_am_cool --python-script \"%s\"" % + script) + + self.expect("frame variable two", + substrs=['int says 1']) + + self.expect("frame variable twoptr", + substrs=['int says 1']) + + # Change the summary + self.runCmd( + "type summary add --summary-string \"int says ${var.integer}, and float says ${var.floating}\" i_am_cool") + + self.expect("frame variable two", + substrs=['int says 1', + 'and float says 2.71']) + # Try it for pointers + self.expect("frame variable twoptr", + substrs=['int says 1', + 'and float says 2.71']) + + # Force a failure for pointers + self.runCmd( + "type summary add i_am_cool -p --python-script \"%s\"" % + script) + + self.expect("frame variable twoptr", matching=False, + substrs=['and float says 2.71']) + + script = 'return \'Python summary\'' + + self.runCmd( + "type summary add --name test_summary --python-script \"%s\"" % + script) + + # attach the Python named summary to someone + self.expect("frame variable one --summary test_summary", + substrs=['Python summary']) + + # should not bind to the type + self.expect("frame variable two", matching=False, + substrs=['Python summary']) + + # and should not stick to the variable + self.expect("frame variable one", matching=False, + substrs=['Python summary']) + + self.runCmd( + "type summary add i_am_cool --summary-string \"Text summary\"") + + # should be temporary only + self.expect("frame variable one", matching=False, + substrs=['Python summary']) + + # use the type summary + self.expect("frame variable two", + substrs=['Text summary']) + + self.runCmd("n") # skip ahead to make values change + + # both should use the type summary now + self.expect("frame variable one", + substrs=['Text summary']) + + self.expect("frame variable two", + substrs=['Text summary']) + + # disable type summary for pointers, and make a Python regex summary + self.runCmd( + "type summary add i_am_cool -p --summary-string \"Text summary\"") + self.runCmd("type summary add -x cool --python-script \"%s\"" % script) + + # variables should stick to the type summary + self.expect("frame variable one", + substrs=['Text summary']) + + self.expect("frame variable two", + substrs=['Text summary']) + + # array and pointer should match the Python one + self.expect("frame variable twoptr", + substrs=['Python summary']) + + self.expect("frame variable array", + substrs=['Python summary']) + + # return pointers to the type summary + self.runCmd( + "type summary add i_am_cool --summary-string \"Text summary\"") + + self.expect("frame variable one", + substrs=['Text summary']) + + self.expect("frame variable two", + substrs=['Text summary']) + + self.expect("frame variable twoptr", + substrs=['Text summary']) + + self.expect("frame variable array", + substrs=['Python summary']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-script/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-script/main.cpp new file mode 100644 index 00000000000..db60981d88c --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-script/main.cpp @@ -0,0 +1,52 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> + +struct i_am_cool +{ + int integer; + float floating; + char character; + i_am_cool(int I, float F, char C) : + integer(I), floating(F), character(C) {} + i_am_cool() : integer(1), floating(2), character('3') {} + +}; + +struct i_am_cooler +{ + i_am_cool first_cool; + i_am_cool second_cool; + float floating; + + i_am_cooler(int I1, int I2, float F1, float F2, char C1, char C2) : + first_cool(I1,F1,C1), + second_cool(I2,F2,C2), + floating((F1 + F2)/2) {} +}; + +int main (int argc, const char * argv[]) +{ + i_am_cool one(1,3.14,'E'); + i_am_cool two(4,2.71,'G'); + + i_am_cool* twoptr = &two; + + i_am_cool array[5]; + + i_am_cooler three(10,4,1985,1/1/2011,'B','E'); // Set break point at this line. + + two.integer = 1; + + int dummy = 1; + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-skip-summary/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-skip-summary/Makefile new file mode 100644 index 00000000000..6bfb97cd2c2 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-skip-summary/Makefile @@ -0,0 +1,7 @@ +CXX_SOURCES := main.cpp +USE_LIBSTDCPP := 0 + + + +CXXFLAGS_EXTRAS := -O0 +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-skip-summary/TestDataFormatterSkipSummary.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-skip-summary/TestDataFormatterSkipSummary.py new file mode 100644 index 00000000000..fa13e922ce4 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-skip-summary/TestDataFormatterSkipSummary.py @@ -0,0 +1,184 @@ +""" +Test lldb data formatter subsystem. +""" + +import os +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class SkipSummaryDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll( + oslist=['freebsd'], + bugnumber="llvm.org/pr20548 fails to build on lab.llvm.org buildbot") + @expectedFailureAll( + oslist=["windows"], + bugnumber="llvm.org/pr24462, Data formatters have problems on Windows") + def test_with_run_command(self): + """Test data formatter commands.""" + self.build() + self.data_formatter_commands() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + def data_formatter_commands(self): + """Test that that file and class static variables display correctly.""" + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + #import lldbsuite.test.lldbutil as lldbutil + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + # Setup the summaries for this scenario + #self.runCmd("type summary add --summary-string \"${var._M_dataplus._M_p}\" std::string") + self.runCmd( + "type summary add --summary-string \"Level 1\" \"DeepData_1\"") + self.runCmd( + "type summary add --summary-string \"Level 2\" \"DeepData_2\" -e") + self.runCmd( + "type summary add --summary-string \"Level 3\" \"DeepData_3\"") + self.runCmd( + "type summary add --summary-string \"Level 4\" \"DeepData_4\"") + self.runCmd( + "type summary add --summary-string \"Level 5\" \"DeepData_5\"") + + # Default case, just print out summaries + self.expect('frame variable', + substrs=['(DeepData_1) data1 = Level 1', + '(DeepData_2) data2 = Level 2 {', + 'm_child1 = Level 3', + 'm_child2 = Level 3', + 'm_child3 = Level 3', + 'm_child4 = Level 3', + '}']) + + # Skip the default (should be 1) levels of summaries + self.expect('frame variable --no-summary-depth', + substrs=['(DeepData_1) data1 = {', + 'm_child1 = 0x', + '}', + '(DeepData_2) data2 = {', + 'm_child1 = Level 3', + 'm_child2 = Level 3', + 'm_child3 = Level 3', + 'm_child4 = Level 3', + '}']) + + # Now skip 2 levels of summaries + self.expect('frame variable --no-summary-depth=2', + substrs=['(DeepData_1) data1 = {', + 'm_child1 = 0x', + '}', + '(DeepData_2) data2 = {', + 'm_child1 = {', + 'm_child1 = 0x', + 'Level 4', + 'm_child2 = {', + 'm_child3 = {', + '}']) + + # Check that no "Level 3" comes out + self.expect( + 'frame variable data1.m_child1 --no-summary-depth=2', + matching=False, + substrs=['Level 3']) + + # Now expand a pointer with 2 level of skipped summaries + self.expect('frame variable data1.m_child1 --no-summary-depth=2', + substrs=['(DeepData_2 *) data1.m_child1 = 0x']) + + # Deref and expand said pointer + self.expect('frame variable *data1.m_child1 --no-summary-depth=2', + substrs=['(DeepData_2) *data1.m_child1 = {', + 'm_child2 = {', + 'm_child1 = 0x', + 'Level 4', + '}']) + + # Expand an expression, skipping 2 layers of summaries + self.expect( + 'frame variable data1.m_child1->m_child2 --no-summary-depth=2', + substrs=[ + '(DeepData_3) data1.m_child1->m_child2 = {', + 'm_child2 = {', + 'm_child1 = Level 5', + 'm_child2 = Level 5', + 'm_child3 = Level 5', + '}']) + + # Expand same expression, skipping only 1 layer of summaries + self.expect( + 'frame variable data1.m_child1->m_child2 --no-summary-depth=1', + substrs=[ + '(DeepData_3) data1.m_child1->m_child2 = {', + 'm_child1 = 0x', + 'Level 4', + 'm_child2 = Level 4', + '}']) + + # Bad debugging info on SnowLeopard gcc (Apple Inc. build 5666). + # Skip the following tests if the condition is met. + if self.getCompiler().endswith('gcc') and not self.getCompiler().endswith('llvm-gcc'): + import re + gcc_version_output = system( + [[lldbutil.which(self.getCompiler()), "-v"]])[1] + #print("my output:", gcc_version_output) + for line in gcc_version_output.split(os.linesep): + m = re.search('\(Apple Inc\. build ([0-9]+)\)', line) + #print("line:", line) + if m: + gcc_build = int(m.group(1)) + #print("gcc build:", gcc_build) + if gcc_build >= 5666: + # rdar://problem/9804600" + self.skipTest( + "rdar://problem/9804600 wrong namespace for std::string in debug info") + + # Expand same expression, skipping 3 layers of summaries + self.expect( + 'frame variable data1.m_child1->m_child2 --show-types --no-summary-depth=3', + substrs=[ + '(DeepData_3) data1.m_child1->m_child2 = {', + 'm_some_text = "Just a test"', + 'm_child2 = {', + 'm_some_text = "Just a test"']) + + # Change summary and expand, first without --no-summary-depth then with + # --no-summary-depth + self.runCmd( + "type summary add --summary-string \"${var.m_some_text}\" DeepData_5") + + self.expect('fr var data2.m_child4.m_child2.m_child2', substrs=[ + '(DeepData_5) data2.m_child4.m_child2.m_child2 = "Just a test"']) + + self.expect( + 'fr var data2.m_child4.m_child2.m_child2 --no-summary-depth', + substrs=[ + '(DeepData_5) data2.m_child4.m_child2.m_child2 = {', + 'm_some_text = "Just a test"', + '}']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-skip-summary/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-skip-summary/main.cpp new file mode 100644 index 00000000000..665c9fe75d1 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-skip-summary/main.cpp @@ -0,0 +1,57 @@ +#include <string> + +struct DeepData_5 +{ + std::string m_some_text; + DeepData_5() : + m_some_text("Just a test") {} +}; + +struct DeepData_4 +{ + DeepData_5 m_child1; + DeepData_5 m_child2; + DeepData_5 m_child3; +}; + +struct DeepData_3 +{ + DeepData_4& m_child1; + DeepData_4 m_child2; + + DeepData_3() : m_child1(* (new DeepData_4())), m_child2(DeepData_4()) {} +}; + +struct DeepData_2 +{ + DeepData_3 m_child1; + DeepData_3 m_child2; + DeepData_3 m_child3; + DeepData_3 m_child4; +}; + +struct DeepData_1 +{ + DeepData_2 *m_child1; + + DeepData_1() : + m_child1(new DeepData_2()) + {} +}; + +/* + type summary add -f "${var._M_dataplus._M_p}" std::string + type summary add -f "Level 1" "DeepData_1" + type summary add -f "Level 2" "DeepData_2" -e + type summary add -f "Level 3" "DeepData_3" + type summary add -f "Level 4" "DeepData_4" + type summary add -f "Level 5" "DeepData_5" + */ + +int main() +{ + DeepData_1 data1; + DeepData_2 data2; + + return 0; // Set break point at this line. +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-smart-array/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-smart-array/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-smart-array/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py new file mode 100644 index 00000000000..0f98eb34825 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py @@ -0,0 +1,453 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class SmartArrayDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_with_run_command(self): + """Test data formatter commands.""" + self.build() + self.data_formatter_commands() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + def data_formatter_commands(self): + """Test that that file and class static variables display correctly.""" + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + process = self.dbg.GetSelectedTarget().GetProcess() + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + +# check that we are not looping here + self.runCmd("type summary add --summary-string \"${var%V}\" SomeData") + + self.expect("frame variable data", + substrs=['SomeData @ 0x']) +# ${var%s} + self.runCmd( + "type summary add --summary-string \"ptr = ${var%s}\" \"char *\"") + + self.expect("frame variable strptr", + substrs=['ptr = \"', + 'Hello world!']) + + self.expect("frame variable other.strptr", + substrs=['ptr = \"', + 'Nested Hello world!']) + + self.runCmd( + "type summary add --summary-string \"arr = ${var%s}\" -x \"char \\[[0-9]+\\]\"") + + self.expect("frame variable strarr", + substrs=['arr = \"', + 'Hello world!']) + + self.expect("frame variable other.strarr", + substrs=['arr = \"', + 'Nested Hello world!']) + + self.expect("p strarr", + substrs=['arr = \"', + 'Hello world!']) + + self.expect("p other.strarr", + substrs=['arr = \"', + 'Nested Hello world!']) + +# ${var%c} + self.runCmd( + "type summary add --summary-string \"ptr = ${var%c}\" \"char *\"") + + self.expect("frame variable strptr", + substrs=['ptr = \"', + 'Hello world!']) + + self.expect("frame variable other.strptr", + substrs=['ptr = \"', + 'Nested Hello world!']) + + self.expect("p strptr", + substrs=['ptr = \"', + 'Hello world!']) + + self.expect("p other.strptr", + substrs=['ptr = \"', + 'Nested Hello world!']) + + self.runCmd( + "type summary add --summary-string \"arr = ${var%c}\" -x \"char \\[[0-9]+\\]\"") + + self.expect("frame variable strarr", + substrs=['arr = \"', + 'Hello world!']) + + self.expect("frame variable other.strarr", + substrs=['arr = \"', + 'Nested Hello world!']) + + self.expect("p strarr", + substrs=['arr = \"', + 'Hello world!']) + + self.expect("p other.strarr", + substrs=['arr = \"', + 'Nested Hello world!']) + +# ${var%char[]} + self.runCmd( + "type summary add --summary-string \"arr = ${var%char[]}\" -x \"char \\[[0-9]+\\]\"") + + self.expect("frame variable strarr", + substrs=['arr = \"', + 'Hello world!']) + + self.expect("frame variable other.strarr", + substrs=['arr = ', + 'Nested Hello world!']) + + self.expect("p strarr", + substrs=['arr = \"', + 'Hello world!']) + + self.expect("p other.strarr", + substrs=['arr = ', + 'Nested Hello world!']) + + self.runCmd( + "type summary add --summary-string \"ptr = ${var%char[]}\" \"char *\"") + + self.expect("frame variable strptr", + substrs=['ptr = \"', + 'Hello world!']) + + self.expect("frame variable other.strptr", + substrs=['ptr = \"', + 'Nested Hello world!']) + + self.expect("p strptr", + substrs=['ptr = \"', + 'Hello world!']) + + self.expect("p other.strptr", + substrs=['ptr = \"', + 'Nested Hello world!']) + +# ${var%a} + self.runCmd( + "type summary add --summary-string \"arr = ${var%a}\" -x \"char \\[[0-9]+\\]\"") + + self.expect("frame variable strarr", + substrs=['arr = \"', + 'Hello world!']) + + self.expect("frame variable other.strarr", + substrs=['arr = ', + 'Nested Hello world!']) + + self.expect("p strarr", + substrs=['arr = \"', + 'Hello world!']) + + self.expect("p other.strarr", + substrs=['arr = ', + 'Nested Hello world!']) + + self.runCmd( + "type summary add --summary-string \"ptr = ${var%a}\" \"char *\"") + + self.expect("frame variable strptr", + substrs=['ptr = \"', + 'Hello world!']) + + self.expect("frame variable other.strptr", + substrs=['ptr = \"', + 'Nested Hello world!']) + + self.expect("p strptr", + substrs=['ptr = \"', + 'Hello world!']) + + self.expect("p other.strptr", + substrs=['ptr = \"', + 'Nested Hello world!']) + + self.runCmd( + "type summary add --summary-string \"ptr = ${var[]%char[]}\" \"char *\"") + +# I do not know the size of the data, but you are asking for a full array slice.. +# use the ${var%char[]} to obtain a string as result + self.expect("frame variable strptr", matching=False, + substrs=['ptr = \"', + 'Hello world!']) + + self.expect("frame variable other.strptr", matching=False, + substrs=['ptr = \"', + 'Nested Hello world!']) + + self.expect("p strptr", matching=False, + substrs=['ptr = \"', + 'Hello world!']) + + self.expect("p other.strptr", matching=False, + substrs=['ptr = \"', + 'Nested Hello world!']) + +# You asked an array-style printout... + self.runCmd( + "type summary add --summary-string \"ptr = ${var[0-1]%char[]}\" \"char *\"") + + self.expect("frame variable strptr", + substrs=['ptr = ', + '[{H},{e}]']) + + self.expect("frame variable other.strptr", + substrs=['ptr = ', + '[{N},{e}]']) + + self.expect("p strptr", + substrs=['ptr = ', + '[{H},{e}]']) + + self.expect("p other.strptr", + substrs=['ptr = ', + '[{N},{e}]']) + +# using [] is required here + self.runCmd( + "type summary add --summary-string \"arr = ${var%x}\" \"int [5]\"") + + self.expect("frame variable intarr", matching=False, substrs=[ + '0x00000001,0x00000001,0x00000002,0x00000003,0x00000005']) + + self.expect("frame variable other.intarr", matching=False, substrs=[ + '0x00000009,0x00000008,0x00000007,0x00000006,0x00000005']) + + self.runCmd( + "type summary add --summary-string \"arr = ${var[]%x}\" \"int [5]\"") + + self.expect( + "frame variable intarr", + substrs=[ + 'intarr = arr =', + '0x00000001,0x00000001,0x00000002,0x00000003,0x00000005']) + + self.expect( + "frame variable other.intarr", + substrs=[ + 'intarr = arr =', + '0x00000009,0x00000008,0x00000007,0x00000006,0x00000005']) + +# printing each array item as an array + self.runCmd( + "type summary add --summary-string \"arr = ${var[]%uint32_t[]}\" \"int [5]\"") + + self.expect( + "frame variable intarr", + substrs=[ + 'intarr = arr =', + '{0x00000001},{0x00000001},{0x00000002},{0x00000003},{0x00000005}']) + + self.expect( + "frame variable other.intarr", + substrs=[ + 'intarr = arr = ', + '{0x00000009},{0x00000008},{0x00000007},{0x00000006},{0x00000005}']) + +# printing full array as an array + self.runCmd( + "type summary add --summary-string \"arr = ${var%uint32_t[]}\" \"int [5]\"") + + self.expect( + "frame variable intarr", + substrs=[ + 'intarr = arr =', + '0x00000001,0x00000001,0x00000002,0x00000003,0x00000005']) + + self.expect( + "frame variable other.intarr", + substrs=[ + 'intarr = arr =', + '0x00000009,0x00000008,0x00000007,0x00000006,0x00000005']) + +# printing each array item as an array + self.runCmd( + "type summary add --summary-string \"arr = ${var[]%float32[]}\" \"float [7]\"") + + self.expect( + "frame variable flarr", + substrs=[ + 'flarr = arr =', + '{78.5},{77.25},{78},{76.125},{76.75},{76.875},{77}']) + + self.expect( + "frame variable other.flarr", + substrs=[ + 'flarr = arr = ', + '{25.5},{25.25},{25.125},{26.75},{27.375},{27.5},{26.125}']) + +# printing full array as an array + self.runCmd( + "type summary add --summary-string \"arr = ${var%float32[]}\" \"float [7]\"") + + self.expect("frame variable flarr", + substrs=['flarr = arr =', + '78.5,77.25,78,76.125,76.75,76.875,77']) + + self.expect("frame variable other.flarr", + substrs=['flarr = arr =', + '25.5,25.25,25.125,26.75,27.375,27.5,26.125']) + +# using array smart summary strings for pointers should make no sense + self.runCmd( + "type summary add --summary-string \"arr = ${var%float32[]}\" \"float *\"") + self.runCmd( + "type summary add --summary-string \"arr = ${var%int32_t[]}\" \"int *\"") + + self.expect("frame variable flptr", matching=False, + substrs=['78.5,77.25,78,76.125,76.75,76.875,77']) + + self.expect("frame variable intptr", matching=False, + substrs=['1,1,2,3,5']) + +# use y and Y + self.runCmd( + "type summary add --summary-string \"arr = ${var%y}\" \"float [7]\"") + self.runCmd( + "type summary add --summary-string \"arr = ${var%y}\" \"int [5]\"") + + if process.GetByteOrder() == lldb.eByteOrderLittle: + self.expect( + "frame variable flarr", + substrs=[ + 'flarr = arr =', + '00 00 9d 42,00 80 9a 42,00 00 9c 42,00 40 98 42,00 80 99 42,00 c0 99 42,00 00 9a 42']) + else: + self.expect( + "frame variable flarr", + substrs=[ + 'flarr = arr =', + '42 9d 00 00,42 9a 80 00,42 9c 00 00,42 98 40 00,42 99 80 00,42 99 c0 00,42 9a 00 00']) + + if process.GetByteOrder() == lldb.eByteOrderLittle: + self.expect( + "frame variable other.flarr", + substrs=[ + 'flarr = arr =', + '00 00 cc 41,00 00 ca 41,00 00 c9 41,00 00 d6 41,00 00 db 41,00 00 dc 41,00 00 d1 41']) + else: + self.expect( + "frame variable other.flarr", + substrs=[ + 'flarr = arr =', + '41 cc 00 00,41 ca 00 00,41 c9 00 00,41 d6 00 00,41 db 00 00,41 dc 00 00,41 d1 00 00']) + + if process.GetByteOrder() == lldb.eByteOrderLittle: + self.expect( + "frame variable intarr", + substrs=[ + 'intarr = arr =', + '01 00 00 00,01 00 00 00,02 00 00 00,03 00 00 00,05 00 00 00']) + else: + self.expect( + "frame variable intarr", + substrs=[ + 'intarr = arr =', + '00 00 00 01,00 00 00 01,00 00 00 02,00 00 00 03,00 00 00 05']) + + if process.GetByteOrder() == lldb.eByteOrderLittle: + self.expect( + "frame variable other.intarr", + substrs=[ + 'intarr = arr = ', + '09 00 00 00,08 00 00 00,07 00 00 00,06 00 00 00,05 00 00 00']) + else: + self.expect( + "frame variable other.intarr", + substrs=[ + 'intarr = arr = ', + '00 00 00 09,00 00 00 08,00 00 00 07,00 00 00 06,00 00 00 05']) + + self.runCmd( + "type summary add --summary-string \"arr = ${var%Y}\" \"float [7]\"") + self.runCmd( + "type summary add --summary-string \"arr = ${var%Y}\" \"int [5]\"") + + if process.GetByteOrder() == lldb.eByteOrderLittle: + self.expect( + "frame variable flarr", + substrs=[ + 'flarr = arr =', + '00 00 9d 42', '00 80 9a 42', '00 00 9c 42', '00 40 98 42', '00 80 99 42', '00 c0 99 42', '00 00 9a 42']) + else: + self.expect( + "frame variable flarr", + substrs=[ + 'flarr = arr =', + '42 9d 00 00', '42 9a 80 00', '42 9c 00 00', '42 98 40 00', '42 99 80 00', '42 99 c0 00', '42 9a 00 00']) + + if process.GetByteOrder() == lldb.eByteOrderLittle: + self.expect( + "frame variable other.flarr", + substrs=[ + 'flarr = arr =', + '00 00 cc 41', '00 00 ca 41', '00 00 c9 41', '00 00 d6 41', '00 00 db 41', '00 00 dc 41', '00 00 d1 41']) + else: + self.expect( + "frame variable other.flarr", + substrs=[ + 'flarr = arr =', + '41 cc 00 00', '41 ca 00 00', '41 c9 00 00', '41 d6 00 00', '41 db 00 00', '41 dc 00 00', '41 d1 00 00']) + + if process.GetByteOrder() == lldb.eByteOrderLittle: + self.expect("frame variable intarr", + substrs=['intarr = arr =', + '....,01 00 00 00', + '....,05 00 00 00']) + else: + self.expect("frame variable intarr", + substrs=['intarr = arr =', + '....,00 00 00 01', + '....,00 00 00 05']) + + if process.GetByteOrder() == lldb.eByteOrderLittle: + self.expect("frame variable other.intarr", + substrs=['intarr = arr = ', + '09 00 00 00', + '....,07 00 00 00']) + else: + self.expect("frame variable other.intarr", + substrs=['intarr = arr = ', + '00 00 00 09', + '....,00 00 00 07']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-smart-array/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-smart-array/main.cpp new file mode 100644 index 00000000000..b9a517d8ceb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-smart-array/main.cpp @@ -0,0 +1,64 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> + +struct SomeData +{ + int x; +}; + +struct SomeOtherData +{ + char strarr[32]; + char *strptr; + int intarr[5]; + float flarr[7]; + + SomeOtherData() + { + strcpy(strarr,"Nested Hello world!"); + strptr = new char[128]; + strcpy(strptr,"Nested Hello world!"); + intarr[0] = 9; + intarr[1] = 8; + intarr[2] = 7; + intarr[3] = 6; + intarr[4] = 5; + + flarr[0] = 25.5; + flarr[1] = 25.25; + flarr[2] = 25.125; + flarr[3] = 26.75; + flarr[4] = 27.375; + flarr[5] = 27.5; + flarr[6] = 26.125; + } +}; + +int main (int argc, const char * argv[]) +{ + char strarr[32] = "Hello world!"; + char *strptr = NULL; + strptr = "Hello world!"; + int intarr[5] = {1,1,2,3,5}; + float flarr[7] = {78.5,77.25,78.0,76.125,76.75,76.875,77.0}; + + SomeData data; + + SomeOtherData other; + + float* flptr = flarr; + int* intptr = intarr; + + return 0; // Set break point at this line. + +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/atomic/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/atomic/Makefile new file mode 100644 index 00000000000..b016f006747 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/atomic/Makefile @@ -0,0 +1,5 @@ +CXX_SOURCES := main.cpp +CXXFLAGS_EXTRAS := -std=c++11 +USE_LIBCPP := 1 + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/atomic/TestLibCxxAtomic.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/atomic/TestLibCxxAtomic.py new file mode 100644 index 00000000000..48e77c1a885 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/atomic/TestLibCxxAtomic.py @@ -0,0 +1,60 @@ +""" +Test lldb data formatter subsystem. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class LibCxxAtomicTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def get_variable(self, name): + var = self.frame().FindVariable(name) + var.SetPreferDynamicValue(lldb.eDynamicCanRunTarget) + var.SetPreferSyntheticValue(True) + return var + + @skipIf(compiler=["gcc"]) + @add_test_categories(["libc++"]) + def test(self): + """Test that std::atomic as defined by libc++ is correctly printed by LLDB""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + bkpt = self.target().FindBreakpointByID( + lldbutil.run_break_set_by_source_regexp( + self, "Set break point at this line.")) + + self.runCmd("run", RUN_SUCCEEDED) + + lldbutil.skip_if_library_missing( + self, self.target(), lldbutil.PrintableRegex("libc\+\+")) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + s = self.get_variable('s') + i = self.get_variable('i') + + if self.TraceOn(): + print(s) + if self.TraceOn(): + print(i) + + self.assertTrue(i.GetValueAsUnsigned(0) == 5, "i == 5") + self.assertTrue(s.GetNumChildren() == 2, "s has two children") + self.assertTrue( + s.GetChildAtIndex(0).GetValueAsUnsigned(0) == 1, + "s.x == 1") + self.assertTrue( + s.GetChildAtIndex(1).GetValueAsUnsigned(0) == 2, + "s.y == 2") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/atomic/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/atomic/main.cpp new file mode 100644 index 00000000000..516331efdde --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/atomic/main.cpp @@ -0,0 +1,25 @@ +//===-- main.cpp --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <atomic> + +struct S { + int x = 1; + int y = 2; +}; + +int main () +{ + std::atomic<S> s; + s.store(S()); + std::atomic<int> i; + i.store(5); + + return 0; // Set break point at this line. +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/bitset/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/bitset/Makefile new file mode 100644 index 00000000000..680e1abfbef --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/bitset/Makefile @@ -0,0 +1,4 @@ +CXX_SOURCES := main.cpp + +USE_LIBCPP := 1 +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/bitset/TestDataFormatterLibcxxBitset.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/bitset/TestDataFormatterLibcxxBitset.py new file mode 100644 index 00000000000..26f1972257b --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/bitset/TestDataFormatterLibcxxBitset.py @@ -0,0 +1,61 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestDataFormatterLibcxxBitset(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + TestBase.setUp(self) + + primes = [1]*300 + primes[0] = primes[1] = 0 + for i in range(2, len(primes)): + for j in range(2*i, len(primes), i): + primes[j] = 0 + self.primes = primes + + def check(self, name, size): + var = self.frame().FindVariable(name) + self.assertTrue(var.IsValid()) + self.assertEqual(var.GetNumChildren(), size) + for i in range(size): + child = var.GetChildAtIndex(i) + self.assertEqual(child.GetValueAsUnsigned(), self.primes[i], + "variable: %s, index: %d"%(name, size)) + + @add_test_categories(["libc++"]) + def test_value(self): + """Test that std::bitset is displayed correctly""" + self.build() + lldbutil.run_to_source_breakpoint(self, '// break here', + lldb.SBFileSpec("main.cpp", False)) + + self.check("empty", 0) + self.check("small", 13) + self.check("large", 200) + + @add_test_categories(["libc++"]) + def test_ptr_and_ref(self): + """Test that ref and ptr to std::bitset is displayed correctly""" + self.build() + (_, process, _, bkpt) = lldbutil.run_to_source_breakpoint(self, + 'Check ref and ptr', + lldb.SBFileSpec("main.cpp", False)) + + self.check("ref", 13) + self.check("ptr", 13) + + lldbutil.continue_to_breakpoint(process, bkpt) + + self.check("ref", 200) + self.check("ptr", 200) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/bitset/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/bitset/main.cpp new file mode 100644 index 00000000000..2a1532adb4b --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/bitset/main.cpp @@ -0,0 +1,29 @@ +#include <bitset> +#include <stdio.h> + +template<std::size_t N> +void fill(std::bitset<N> &b) { + b.set(); + b[0] = b[1] = false; + for (std::size_t i = 2; i < N; ++i) { + for (std::size_t j = 2*i; j < N; j+=i) + b[j] = false; + } +} + +template<std::size_t N> +void by_ref_and_ptr(std::bitset<N> &ref, std::bitset<N> *ptr) { + // Check ref and ptr + return; +} + +int main() { + std::bitset<0> empty; + std::bitset<13> small; + fill(small); + std::bitset<200> large; + fill(large); + by_ref_and_ptr(small, &small); // break here + by_ref_and_ptr(large, &large); + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/forward_list/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/forward_list/Makefile new file mode 100644 index 00000000000..680e1abfbef --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/forward_list/Makefile @@ -0,0 +1,4 @@ +CXX_SOURCES := main.cpp + +USE_LIBCPP := 1 +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/forward_list/TestDataFormatterLibcxxForwardList.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/forward_list/TestDataFormatterLibcxxForwardList.py new file mode 100644 index 00000000000..a9983dd045e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/forward_list/TestDataFormatterLibcxxForwardList.py @@ -0,0 +1,52 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestDataFormatterLibcxxForwardList(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + TestBase.setUp(self) + self.line = line_number('main.cpp', '// break here') + ns = 'ndk' if lldbplatformutil.target_is_android() else '' + self.namespace = 'std::__' + ns + '1' + + @add_test_categories(["libc++"]) + def test(self): + """Test that std::forward_list is displayed correctly""" + self.build() + lldbutil.run_to_source_breakpoint(self, '// break here', + lldb.SBFileSpec("main.cpp", False)) + + forward_list = self.namespace + '::forward_list' + self.expect("frame variable empty", + substrs=[forward_list, + 'size=0', + '{}']) + + self.expect("frame variable one_elt", + substrs=[forward_list, + 'size=1', + '{', + '[0] = 47', + '}']) + + self.expect("frame variable five_elts", + substrs=[forward_list, + 'size=5', + '{', + '[0] = 1', + '[1] = 22', + '[2] = 333', + '[3] = 4444', + '[4] = 55555', + '}']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/forward_list/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/forward_list/main.cpp new file mode 100644 index 00000000000..73abda6e82e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/forward_list/main.cpp @@ -0,0 +1,7 @@ +#include <forward_list> + +int main() +{ + std::forward_list<int> empty{}, one_elt{47}, five_elts{1,22,333,4444,55555}; + return 0; // break here +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/Makefile new file mode 100644 index 00000000000..b016f006747 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/Makefile @@ -0,0 +1,5 @@ +CXX_SOURCES := main.cpp +CXXFLAGS_EXTRAS := -std=c++11 +USE_LIBCPP := 1 + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/TestLibCxxFunction.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/TestLibCxxFunction.py new file mode 100644 index 00000000000..9f0d3e431a3 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/TestLibCxxFunction.py @@ -0,0 +1,72 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class LibCxxFunctionTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # Run frame var for a variable twice. Verify we do not hit the cache + # the first time but do the second time. + def run_frame_var_check_cache_use(self, variable, result_to_match, skip_find_function=False): + self.runCmd("log timers reset") + self.expect("frame variable " + variable, + substrs=[variable + " = " + result_to_match]) + if not skip_find_function: + self.expect("log timers dump", + substrs=["lldb_private::CompileUnit::FindFunction"]) + + self.runCmd("log timers reset") + self.expect("frame variable " + variable, + substrs=[variable + " = " + result_to_match]) + self.expect("log timers dump", + matching=False, + substrs=["lldb_private::CompileUnit::FindFunction"]) + + + @add_test_categories(["libc++"]) + def test(self): + """Test that std::function as defined by libc++ is correctly printed by LLDB""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + bkpt = self.target().FindBreakpointByID( + lldbutil.run_break_set_by_source_regexp( + self, "Set break point at this line.")) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + self.run_frame_var_check_cache_use("foo2_f", "Lambda in File main.cpp at Line 30") + + lldbutil.continue_to_breakpoint(self.process(), bkpt) + + self.run_frame_var_check_cache_use("add_num2_f", "Lambda in File main.cpp at Line 21") + + lldbutil.continue_to_breakpoint(self.process(), bkpt) + + self.run_frame_var_check_cache_use("f2", "Lambda in File main.cpp at Line 43") + self.run_frame_var_check_cache_use("f3", "Lambda in File main.cpp at Line 47", True) + # TODO reenable this case when std::function formatter supports + # general callable object case. + #self.run_frame_var_check_cache_use("f4", "Function in File main.cpp at Line 16") + + # These cases won't hit the cache at all but also don't require + # an expensive lookup. + self.expect("frame variable f1", + substrs=['f1 = Function = foo(int, int)']) + + self.expect("frame variable f5", + substrs=['f5 = Function = Bar::add_num(int) const']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/main.cpp new file mode 100644 index 00000000000..d0c931ddc8b --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/main.cpp @@ -0,0 +1,59 @@ +//===-- main.cpp --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <functional> + +int foo(int x, int y) { + return x + y - 1; +} + +struct Bar { + int operator()() { + return 66 ; + } + int add_num(int i) const { return i + 3 ; } + int add_num2(int i) { + std::function<int (int)> add_num2_f = [](int x) { + return x+1; + }; + + return add_num2_f(i); // Set break point at this line. + } +} ; + +int foo2() { + auto f = [](int x) { + return x+1; + }; + + std::function<int (int)> foo2_f = f; + + return foo2_f(10); // Set break point at this line. +} + +int main (int argc, char *argv[]) +{ + int acc = 42; + std::function<int (int,int)> f1 = foo; + std::function<int (int)> f2 = [acc,f1] (int x) -> int { + return x+f1(acc,x); + }; + + auto f = [](int x, int y) { return x + y; }; + auto g = [](int x, int y) { return x * y; } ; + std::function<int (int,int)> f3 = argc %2 ? f : g ; + + Bar bar1 ; + std::function<int ()> f4( bar1 ) ; + std::function<int (const Bar&, int)> f5 = &Bar::add_num; + + int foo2_result = foo2(); + int bar_add_num2_result = bar1.add_num2(10); + + return f1(acc,acc) + f2(acc) + f3(acc+1,acc+2) + f4() + f5(bar1, 10); // Set break point at this line. +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/initializerlist/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/initializerlist/Makefile new file mode 100644 index 00000000000..e78030cbf75 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/initializerlist/Makefile @@ -0,0 +1,4 @@ +CXX_SOURCES := main.cpp +CXXFLAGS_EXTRAS := -std=c++11 + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/initializerlist/TestInitializerList.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/initializerlist/TestInitializerList.py new file mode 100644 index 00000000000..5fef10e6d3e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/initializerlist/TestInitializerList.py @@ -0,0 +1,45 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class InitializerListTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipIfWindows # libc++ not ported to Windows yet + @skipIf(compiler="gcc") + @expectedFailureAll( + oslist=["linux"], + bugnumber="fails on clang 3.5 and tot") + def test(self): + """Test that that file and class static variables display correctly.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + bkpt = self.target().FindBreakpointByID( + lldbutil.run_break_set_by_source_regexp( + self, "Set break point at this line.")) + + self.runCmd("run", RUN_SUCCEEDED) + + lldbutil.skip_if_library_missing( + self, self.target(), lldbutil.PrintableRegex("libc\+\+")) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + self.expect("frame variable ili", substrs=['[1] = 2', '[4] = 5']) + self.expect("frame variable ils", substrs=[ + '[4] = "surprise it is a long string!! yay!!"']) + + self.expect('image list', substrs=self.getLibcPlusPlusLibs()) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/initializerlist/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/initializerlist/main.cpp new file mode 100644 index 00000000000..6e5fa43a6b9 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/initializerlist/main.cpp @@ -0,0 +1,20 @@ +//===-- main.cpp --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <string> +#include <vector> +#include <initializer_list> + +int main () +{ + std::initializer_list<int> ili{1,2,3,4,5}; + std::initializer_list<std::string> ils{"1","2","3","4","surprise it is a long string!! yay!!"}; + + return 0; // Set break point at this line. +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/iterator/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/iterator/Makefile new file mode 100644 index 00000000000..564cbada74e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/iterator/Makefile @@ -0,0 +1,6 @@ +CXX_SOURCES := main.cpp + +USE_LIBCPP := 1 + +CXXFLAGS_EXTRAS := -O0 +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/iterator/TestDataFormatterLibccIterator.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/iterator/TestDataFormatterLibccIterator.py new file mode 100644 index 00000000000..2ff3d63d004 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/iterator/TestDataFormatterLibccIterator.py @@ -0,0 +1,73 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class LibcxxIteratorDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + ns = 'ndk' if lldbplatformutil.target_is_android() else '' + self.namespace = 'std::__' + ns + '1' + + @add_test_categories(["libc++"]) + def test_with_run_command(self): + """Test that libc++ iterators format properly.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=-1) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + self.runCmd('type synth clear', check=False) + self.runCmd( + "settings set target.max-children-count 256", + check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.expect('frame variable ivI', substrs=['item = 3']) + self.expect('expr ivI', substrs=['item = 3']) + + self.expect( + 'frame variable iimI', + substrs=[ + 'first = 43981', + 'second = 61681']) + self.expect('expr iimI', substrs=['first = 43981', 'second = 61681']) + + self.expect( + 'frame variable simI', + substrs=[ + 'first = "world"', + 'second = 42']) + self.expect('expr simI', substrs=['first = "world"', 'second = 42']) + + self.expect('frame variable svI', substrs=['item = "hello"']) + self.expect('expr svI', substrs=['item = "hello"']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/iterator/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/iterator/main.cpp new file mode 100644 index 00000000000..9d1cbfd9128 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/iterator/main.cpp @@ -0,0 +1,38 @@ +#include <string> +#include <map> +#include <vector> + +typedef std::map<int, int> intint_map; +typedef std::map<std::string, int> strint_map; + +typedef std::vector<int> int_vector; +typedef std::vector<std::string> string_vector; + +typedef intint_map::iterator iimter; +typedef strint_map::iterator simter; + +typedef int_vector::iterator ivter; +typedef string_vector::iterator svter; + +int main() +{ + intint_map iim; + iim[0xABCD] = 0xF0F1; + + strint_map sim; + sim["world"] = 42; + + int_vector iv; + iv.push_back(3); + + string_vector sv; + sv.push_back("hello"); + + iimter iimI = iim.begin(); + simter simI = sim.begin(); + + ivter ivI = iv.begin(); + svter svI = sv.begin(); + + return 0; // Set break point at this line. +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/Makefile new file mode 100644 index 00000000000..564cbada74e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/Makefile @@ -0,0 +1,6 @@ +CXX_SOURCES := main.cpp + +USE_LIBCPP := 1 + +CXXFLAGS_EXTRAS := -O0 +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/TestDataFormatterLibcxxList.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/TestDataFormatterLibcxxList.py new file mode 100644 index 00000000000..3a2d006c7de --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/TestDataFormatterLibcxxList.py @@ -0,0 +1,220 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class LibcxxListDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + self.line2 = line_number('main.cpp', + '// Set second break point at this line.') + self.line3 = line_number('main.cpp', + '// Set third break point at this line.') + self.line4 = line_number('main.cpp', + '// Set fourth break point at this line.') + + @add_test_categories(["libc++"]) + @skipIf(debug_info="gmodules", + bugnumber="https://bugs.llvm.org/show_bug.cgi?id=36048") + def test_with_run_command(self): + """Test that that file and class static variables display correctly.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=-1) + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line2, num_expected_locations=-1) + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line3, num_expected_locations=-1) + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line4, num_expected_locations=-1) + + self.runCmd("run", RUN_SUCCEEDED) + + lldbutil.skip_if_library_missing( + self, self.target(), lldbutil.PrintableRegex("libc\+\+")) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + self.runCmd('type synth clear', check=False) + self.runCmd( + "settings set target.max-children-count 256", + check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.runCmd("frame variable numbers_list --show-types") + self.runCmd( + "type summary add std::int_list std::string_list int_list string_list --summary-string \"list has ${svar%#} items\" -e") + self.runCmd("type format add -f hex int") + + self.expect("frame variable numbers_list --raw", matching=False, + substrs=['list has 0 items', + '{}']) + + self.expect("frame variable numbers_list", + substrs=['list has 0 items', + '{}']) + + self.expect("p numbers_list", + substrs=['list has 0 items', + '{}']) + + self.runCmd("n") # This gets up past the printf + self.runCmd("n") # Now advance over the first push_back. + + self.expect("frame variable numbers_list", + substrs=['list has 1 items', + '[0] = ', + '0x12345678']) + + self.runCmd("n") + self.runCmd("n") + self.runCmd("n") + + self.expect("frame variable numbers_list", + substrs=['list has 4 items', + '[0] = ', + '0x12345678', + '[1] =', + '0x11223344', + '[2] =', + '0xbeeffeed', + '[3] =', + '0x00abba00']) + + self.runCmd("n") + self.runCmd("n") + + self.expect("frame variable numbers_list", + substrs=['list has 6 items', + '[0] = ', + '0x12345678', + '0x11223344', + '0xbeeffeed', + '0x00abba00', + '[4] =', + '0x0abcdef0', + '[5] =', + '0x0cab0cab']) + + self.expect("p numbers_list", + substrs=['list has 6 items', + '[0] = ', + '0x12345678', + '0x11223344', + '0xbeeffeed', + '0x00abba00', + '[4] =', + '0x0abcdef0', + '[5] =', + '0x0cab0cab']) + + # check access-by-index + self.expect("frame variable numbers_list[0]", + substrs=['0x12345678']) + self.expect("frame variable numbers_list[1]", + substrs=['0x11223344']) + + self.runCmd("n") + + self.expect("frame variable numbers_list", + substrs=['list has 0 items', + '{}']) + + self.runCmd("n") + self.runCmd("n") + self.runCmd("n") + self.runCmd("n") + + self.expect("frame variable numbers_list", + substrs=['list has 4 items', + '[0] = ', '1', + '[1] = ', '2', + '[2] = ', '3', + '[3] = ', '4']) + + ListPtr = self.frame().FindVariable("list_ptr") + self.assertTrue(ListPtr.GetChildAtIndex( + 0).GetValueAsUnsigned(0) == 1, "[0] = 1") + + # check that MightHaveChildren() gets it right + self.assertTrue( + self.frame().FindVariable("numbers_list").MightHaveChildren(), + "numbers_list.MightHaveChildren() says False for non empty!") + + self.runCmd("type format delete int") + + self.runCmd("c") + + self.expect("frame variable text_list", + substrs=['list has 3 items', + '[0]', 'goofy', + '[1]', 'is', + '[2]', 'smart']) + + # check that MightHaveChildren() gets it right + self.assertTrue( + self.frame().FindVariable("text_list").MightHaveChildren(), + "text_list.MightHaveChildren() says False for non empty!") + + self.expect("p text_list", + substrs=['list has 3 items', + '\"goofy\"', + '\"is\"', + '\"smart\"']) + + self.runCmd("n") # This gets us past the printf + self.runCmd("n") + self.runCmd("n") + + # check access-by-index + self.expect("frame variable text_list[0]", + substrs=['goofy']) + self.expect("frame variable text_list[3]", + substrs=['!!!']) + + self.runCmd("continue") + + # check that the list provider correctly updates if elements move + countingList = self.frame().FindVariable("countingList") + countingList.SetPreferDynamicValue(True) + countingList.SetPreferSyntheticValue(True) + + self.assertTrue(countingList.GetChildAtIndex( + 0).GetValueAsUnsigned(0) == 3141, "list[0] == 3141") + self.assertTrue(countingList.GetChildAtIndex( + 1).GetValueAsUnsigned(0) == 3141, "list[1] == 3141") + + self.runCmd("continue") + + self.assertTrue( + countingList.GetChildAtIndex(0).GetValueAsUnsigned(0) == 3141, + "uniqued list[0] == 3141") + self.assertTrue( + countingList.GetChildAtIndex(1).GetValueAsUnsigned(0) == 3142, + "uniqued list[1] == 3142") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/loop/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/loop/Makefile new file mode 100644 index 00000000000..564cbada74e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/loop/Makefile @@ -0,0 +1,6 @@ +CXX_SOURCES := main.cpp + +USE_LIBCPP := 1 + +CXXFLAGS_EXTRAS := -O0 +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/loop/TestDataFormatterLibcxxListLoop.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/loop/TestDataFormatterLibcxxListLoop.py new file mode 100644 index 00000000000..1678c513e50 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/loop/TestDataFormatterLibcxxListLoop.py @@ -0,0 +1,69 @@ +""" +Test that the debugger handles loops in std::list (which can appear as a result of e.g. memory +corruption). +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class LibcxxListDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + @add_test_categories(["libc++"]) + @expectedFailureAndroid(bugnumber="llvm.org/pr32592") + def test_with_run_command(self): + self.build() + exe = self.getBuildArtifact("a.out") + target = self.dbg.CreateTarget(exe) + self.assertTrue(target and target.IsValid(), "Target is valid") + + file_spec = lldb.SBFileSpec("main.cpp", False) + breakpoint1 = target.BreakpointCreateBySourceRegex( + '// Set break point at this line.', file_spec) + self.assertTrue(breakpoint1 and breakpoint1.IsValid()) + breakpoint2 = target.BreakpointCreateBySourceRegex( + '// Set second break point at this line.', file_spec) + self.assertTrue(breakpoint2 and breakpoint2.IsValid()) + + # Run the program, it should stop at breakpoint 1. + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process and process.IsValid(), PROCESS_IS_VALID) + self.assertEqual( + len(lldbutil.get_threads_stopped_at_breakpoint(process, breakpoint1)), 1) + + # verify our list is displayed correctly + self.expect( + "frame variable *numbers_list", + substrs=[ + '[0] = 1', + '[1] = 2', + '[2] = 3', + '[3] = 4', + '[5] = 6']) + + # Continue to breakpoint 2. + process.Continue() + self.assertTrue(process and process.IsValid(), PROCESS_IS_VALID) + self.assertEqual( + len(lldbutil.get_threads_stopped_at_breakpoint(process, breakpoint2)), 1) + + # The list is now inconsistent. However, we should be able to get the first three + # elements at least (and most importantly, not crash). + self.expect( + "frame variable *numbers_list", + substrs=[ + '[0] = 1', + '[1] = 2', + '[2] = 3']) + + # Run to completion. + process.Continue() + self.assertEqual(process.GetState(), lldb.eStateExited, PROCESS_EXITED) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/loop/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/loop/main.cpp new file mode 100644 index 00000000000..e07e93838b9 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/loop/main.cpp @@ -0,0 +1,35 @@ +// Evil hack: To simulate memory corruption, we want to fiddle with some internals of std::list. +// Make those accessible to us. +#define private public +#define protected public + +#include <list> +#include <stdio.h> +#include <assert.h> + +typedef std::list<int> int_list; + +int main() +{ +#ifdef LLDB_USING_LIBCPP + int_list *numbers_list = new int_list{1,2,3,4,5,6,7,8,9,10}; + + printf("// Set break point at this line."); + +#if _LIBCPP_VERSION >= 3800 + auto *third_elem = numbers_list->__end_.__next_->__next_->__next_; + assert(third_elem->__as_node()->__value_ == 3); + auto *fifth_elem = third_elem->__next_->__next_; + assert(fifth_elem->__as_node()->__value_ == 5); +#else + auto *third_elem = numbers_list->__end_.__next_->__next_->__next_; + assert(third_elem->__value_ == 3); + auto *fifth_elem = third_elem->__next_->__next_; + assert(fifth_elem->__value_ == 5); +#endif + fifth_elem->__next_ = third_elem; +#endif + + // Any attempt to free the list will probably crash the program. Let's just leak it. + return 0; // Set second break point at this line. +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/main.cpp new file mode 100644 index 00000000000..a3ef06b18e7 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/main.cpp @@ -0,0 +1,44 @@ +#include <string> +#include <list> +#include <stdio.h> + +typedef std::list<int> int_list; +typedef std::list<std::string> string_list; + +int main() +{ + int_list numbers_list; + std::list<int>* list_ptr = &numbers_list; + + printf("// Set break point at this line."); + (numbers_list.push_back(0x12345678)); + (numbers_list.push_back(0x11223344)); + (numbers_list.push_back(0xBEEFFEED)); + (numbers_list.push_back(0x00ABBA00)); + (numbers_list.push_back(0x0ABCDEF0)); + (numbers_list.push_back(0x0CAB0CAB)); + + numbers_list.clear(); + + (numbers_list.push_back(1)); + (numbers_list.push_back(2)); + (numbers_list.push_back(3)); + (numbers_list.push_back(4)); + + string_list text_list; + (text_list.push_back(std::string("goofy"))); + (text_list.push_back(std::string("is"))); + (text_list.push_back(std::string("smart"))); + + printf("// Set second break point at this line."); + (text_list.push_back(std::string("!!!"))); + + std::list<int> countingList = {3141, 3142, 3142,3142,3142, 3142, 3142, 3141}; + countingList.sort(); + printf("// Set third break point at this line."); + countingList.unique(); + printf("// Set fourth break point at this line."); + countingList.size(); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/Makefile new file mode 100644 index 00000000000..564cbada74e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/Makefile @@ -0,0 +1,6 @@ +CXX_SOURCES := main.cpp + +USE_LIBCPP := 1 + +CXXFLAGS_EXTRAS := -O0 +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/TestDataFormatterLibccMap.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/TestDataFormatterLibccMap.py new file mode 100644 index 00000000000..d9da0c3886e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/TestDataFormatterLibccMap.py @@ -0,0 +1,324 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class LibcxxMapDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + TestBase.setUp(self) + ns = 'ndk' if lldbplatformutil.target_is_android() else '' + self.namespace = 'std::__' + ns + '1' + + @add_test_categories(["libc++"]) + def test_with_run_command(self): + """Test that that file and class static variables display correctly.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + bkpt = self.target().FindBreakpointByID( + lldbutil.run_break_set_by_source_regexp( + self, "Set break point at this line.")) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + self.runCmd('type synth clear', check=False) + self.runCmd( + "settings set target.max-children-count 256", + check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + ns = self.namespace + self.expect('p ii', + substrs=['%s::map' % ns, + 'size=0', + '{}']) + self.expect('frame var ii', + substrs=['%s::map' % ns, + 'size=0', + '{}']) + + lldbutil.continue_to_breakpoint(self.process(), bkpt) + + self.expect('p ii', + substrs=['%s::map' % ns, 'size=2', + '[0] = ', + 'first = 0', + 'second = 0', + '[1] = ', + 'first = 1', + 'second = 1']) + + self.expect('frame variable ii', + substrs=['%s::map' % ns, 'size=2', + '[0] = ', + 'first = 0', + 'second = 0', + '[1] = ', + 'first = 1', + 'second = 1']) + + lldbutil.continue_to_breakpoint(self.process(), bkpt) + + self.expect('frame variable ii', + substrs=['%s::map' % ns, 'size=4', + '[2] = ', + 'first = 2', + 'second = 0', + '[3] = ', + 'first = 3', + 'second = 1']) + + lldbutil.continue_to_breakpoint(self.process(), bkpt) + + self.expect("p ii", + substrs=['%s::map' % ns, 'size=8', + '[5] = ', + 'first = 5', + 'second = 0', + '[7] = ', + 'first = 7', + 'second = 1']) + + self.expect("frame var ii", + substrs=['%s::map' % ns, 'size=8', + '[5] = ', + 'first = 5', + 'second = 0', + '[7] = ', + 'first = 7', + 'second = 1']) + + # check access-by-index + self.expect("frame variable ii[0]", + substrs=['first = 0', + 'second = 0']) + self.expect("frame variable ii[3]", + substrs=['first =', + 'second =']) + + # check that MightHaveChildren() gets it right + self.assertTrue( + self.frame().FindVariable("ii").MightHaveChildren(), + "ii.MightHaveChildren() says False for non empty!") + + # check that the expression parser does not make use of + # synthetic children instead of running code + # TOT clang has a fix for this, which makes the expression command here succeed + # since this would make the test fail or succeed depending on clang version in use + # this is safer commented for the time being + # self.expect("expression ii[8]", matching=False, error=True, + # substrs = ['1234567']) + + self.runCmd("continue") + + self.expect('frame variable ii', + substrs=['%s::map' % ns, 'size=0', + '{}']) + + self.expect('frame variable si', + substrs=['%s::map' % ns, 'size=0', + '{}']) + + self.runCmd("continue") + + self.expect('frame variable si', + substrs=['%s::map' % ns, 'size=1', + '[0] = ', + 'first = \"zero\"', + 'second = 0']) + + lldbutil.continue_to_breakpoint(self.process(), bkpt) + + self.expect("frame variable si", + substrs=['%s::map' % ns, 'size=4', + '[0] = ', + 'first = \"zero\"', + 'second = 0', + '[1] = ', + 'first = \"one\"', + 'second = 1', + '[2] = ', + 'first = \"two\"', + 'second = 2', + '[3] = ', + 'first = \"three\"', + 'second = 3']) + + self.expect("p si", + substrs=['%s::map' % ns, 'size=4', + '[0] = ', + 'first = \"zero\"', + 'second = 0', + '[1] = ', + 'first = \"one\"', + 'second = 1', + '[2] = ', + 'first = \"two\"', + 'second = 2', + '[3] = ', + 'first = \"three\"', + 'second = 3']) + + # check that MightHaveChildren() gets it right + self.assertTrue( + self.frame().FindVariable("si").MightHaveChildren(), + "si.MightHaveChildren() says False for non empty!") + + # check access-by-index + self.expect("frame variable si[0]", + substrs=['first = ', 'one', + 'second = 1']) + + # check that the expression parser does not make use of + # synthetic children instead of running code + # TOT clang has a fix for this, which makes the expression command here succeed + # since this would make the test fail or succeed depending on clang version in use + # this is safer commented for the time being + # self.expect("expression si[0]", matching=False, error=True, + # substrs = ['first = ', 'zero']) + + lldbutil.continue_to_breakpoint(self.process(), bkpt) + + self.expect('frame variable si', + substrs=['%s::map' % ns, 'size=0', + '{}']) + + lldbutil.continue_to_breakpoint(self.process(), bkpt) + + self.expect('frame variable is', + substrs=['%s::map' % ns, 'size=0', + '{}']) + + lldbutil.continue_to_breakpoint(self.process(), bkpt) + + self.expect("frame variable is", + substrs=['%s::map' % ns, 'size=4', + '[0] = ', + 'second = \"goofy\"', + 'first = 85', + '[1] = ', + 'second = \"is\"', + 'first = 1', + '[2] = ', + 'second = \"smart\"', + 'first = 2', + '[3] = ', + 'second = \"!!!\"', + 'first = 3']) + + self.expect("p is", + substrs=['%s::map' % ns, 'size=4', + '[0] = ', + 'second = \"goofy\"', + 'first = 85', + '[1] = ', + 'second = \"is\"', + 'first = 1', + '[2] = ', + 'second = \"smart\"', + 'first = 2', + '[3] = ', + 'second = \"!!!\"', + 'first = 3']) + + # check that MightHaveChildren() gets it right + self.assertTrue( + self.frame().FindVariable("is").MightHaveChildren(), + "is.MightHaveChildren() says False for non empty!") + + # check access-by-index + self.expect("frame variable is[0]", + substrs=['first = ', + 'second =']) + + # check that the expression parser does not make use of + # synthetic children instead of running code + # TOT clang has a fix for this, which makes the expression command here succeed + # since this would make the test fail or succeed depending on clang version in use + # this is safer commented for the time being + # self.expect("expression is[0]", matching=False, error=True, + # substrs = ['first = ', 'goofy']) + + lldbutil.continue_to_breakpoint(self.process(), bkpt) + + self.expect('frame variable is', + substrs=['%s::map' % ns, 'size=0', + '{}']) + + lldbutil.continue_to_breakpoint(self.process(), bkpt) + + self.expect('frame variable ss', + substrs=['%s::map' % ns, 'size=0', + '{}']) + + lldbutil.continue_to_breakpoint(self.process(), bkpt) + + self.expect("frame variable ss", + substrs=['%s::map' % ns, 'size=3', + '[0] = ', + 'second = \"hello\"', + 'first = \"ciao\"', + '[1] = ', + 'second = \"house\"', + 'first = \"casa\"', + '[2] = ', + 'second = \"cat\"', + 'first = \"gatto\"']) + + self.expect("p ss", + substrs=['%s::map' % ns, 'size=3', + '[0] = ', + 'second = \"hello\"', + 'first = \"ciao\"', + '[1] = ', + 'second = \"house\"', + 'first = \"casa\"', + '[2] = ', + 'second = \"cat\"', + 'first = \"gatto\"']) + + # check that MightHaveChildren() gets it right + self.assertTrue( + self.frame().FindVariable("ss").MightHaveChildren(), + "ss.MightHaveChildren() says False for non empty!") + + # check access-by-index + self.expect("frame variable ss[2]", + substrs=['gatto', 'cat']) + + # check that the expression parser does not make use of + # synthetic children instead of running code + # TOT clang has a fix for this, which makes the expression command here succeed + # since this would make the test fail or succeed depending on clang version in use + # this is safer commented for the time being + # self.expect("expression ss[3]", matching=False, error=True, + # substrs = ['gatto']) + + lldbutil.continue_to_breakpoint(self.process(), bkpt) + + self.expect('frame variable ss', + substrs=['%s::map' % ns, 'size=0', + '{}']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/main.cpp new file mode 100644 index 00000000000..da6eca985d2 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/main.cpp @@ -0,0 +1,77 @@ +#include <string> +#include <map> + +#define intint_map std::map<int, int> +#define strint_map std::map<std::string, int> +#define intstr_map std::map<int, std::string> +#define strstr_map std::map<std::string, std::string> + +int g_the_foo = 0; + +int thefoo_rw(int arg = 1) +{ + if (arg < 0) + arg = 0; + if (!arg) + arg = 1; + g_the_foo += arg; + return g_the_foo; +} + +int main() +{ + intint_map ii; + + ii[0] = 0; // Set break point at this line. + ii[1] = 1; + thefoo_rw(1); // Set break point at this line. + ii[2] = 0; + ii[3] = 1; + thefoo_rw(1); // Set break point at this line. + ii[4] = 0; + ii[5] = 1; + ii[6] = 0; + ii[7] = 1; + thefoo_rw(1); // Set break point at this line. + ii[85] = 1234567; + + ii.clear(); + + strint_map si; + thefoo_rw(1); // Set break point at this line. + + si["zero"] = 0; + thefoo_rw(1); // Set break point at this line. + si["one"] = 1; + si["two"] = 2; + si["three"] = 3; + thefoo_rw(1); // Set break point at this line. + si["four"] = 4; + + si.clear(); + thefoo_rw(1); // Set break point at this line. + + intstr_map is; + thefoo_rw(1); // Set break point at this line. + is[85] = "goofy"; + is[1] = "is"; + is[2] = "smart"; + is[3] = "!!!"; + thefoo_rw(1); // Set break point at this line. + + is.clear(); + thefoo_rw(1); // Set break point at this line. + + strstr_map ss; + thefoo_rw(1); // Set break point at this line. + + ss["ciao"] = "hello"; + ss["casa"] = "house"; + ss["gatto"] = "cat"; + thefoo_rw(1); // Set break point at this line. + ss["a Mac.."] = "..is always a Mac!"; + + ss.clear(); + thefoo_rw(1); // Set break point at this line. + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/Makefile new file mode 100644 index 00000000000..564cbada74e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/Makefile @@ -0,0 +1,6 @@ +CXX_SOURCES := main.cpp + +USE_LIBCPP := 1 + +CXXFLAGS_EXTRAS := -O0 +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/TestDataFormatterLibccMultiMap.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/TestDataFormatterLibccMultiMap.py new file mode 100644 index 00000000000..39adc04e49a --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/TestDataFormatterLibccMultiMap.py @@ -0,0 +1,311 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class LibcxxMultiMapDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + TestBase.setUp(self) + ns = 'ndk' if lldbplatformutil.target_is_android() else '' + self.namespace = 'std::__' + ns + '1' + + @add_test_categories(["libc++"]) + def test_with_run_command(self): + """Test that that file and class static variables display correctly.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + bkpt = self.target().FindBreakpointByID( + lldbutil.run_break_set_by_source_regexp( + self, "Set break point at this line.")) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + self.runCmd('type synth clear', check=False) + self.runCmd( + "settings set target.max-children-count 256", + check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + multimap = self.namespace + "::multimap" + self.expect('frame variable ii', + substrs=[multimap, 'size=0', + '{}']) + + lldbutil.continue_to_breakpoint(self.process(), bkpt) + + self.expect('frame variable ii', + substrs=[multimap, 'size=2', + '[0] = ', + 'first = 0', + 'second = 0', + '[1] = ', + 'first = 1', + 'second = 1']) + + lldbutil.continue_to_breakpoint(self.process(), bkpt) + + self.expect('frame variable ii', + substrs=[multimap, 'size=4', + '[2] = ', + 'first = 2', + 'second = 0', + '[3] = ', + 'first = 3', + 'second = 1']) + + lldbutil.continue_to_breakpoint(self.process(), bkpt) + + self.expect("frame variable ii", + substrs=[multimap, 'size=8', + '[5] = ', + 'first = 5', + 'second = 0', + '[7] = ', + 'first = 7', + 'second = 1']) + + self.expect("p ii", + substrs=[multimap, 'size=8', + '[5] = ', + 'first = 5', + 'second = 0', + '[7] = ', + 'first = 7', + 'second = 1']) + + # check access-by-index + self.expect("frame variable ii[0]", + substrs=['first = 0', + 'second = 0']) + self.expect("frame variable ii[3]", + substrs=['first =', + 'second =']) + + # check that MightHaveChildren() gets it right + self.assertTrue( + self.frame().FindVariable("ii").MightHaveChildren(), + "ii.MightHaveChildren() says False for non empty!") + + # check that the expression parser does not make use of + # synthetic children instead of running code + # TOT clang has a fix for this, which makes the expression command here succeed + # since this would make the test fail or succeed depending on clang version in use + # this is safer commented for the time being + # self.expect("expression ii[8]", matching=False, error=True, + # substrs = ['1234567']) + + lldbutil.continue_to_breakpoint(self.process(), bkpt) + + self.expect('frame variable ii', + substrs=[multimap, 'size=0', + '{}']) + + self.expect('frame variable si', + substrs=[multimap, 'size=0', + '{}']) + + lldbutil.continue_to_breakpoint(self.process(), bkpt) + + self.expect('frame variable si', + substrs=[multimap, 'size=1', + '[0] = ', + 'first = \"zero\"', + 'second = 0']) + + lldbutil.continue_to_breakpoint(self.process(), bkpt) + + self.expect("frame variable si", + substrs=[multimap, 'size=4', + '[0] = ', + 'first = \"zero\"', + 'second = 0', + '[1] = ', + 'first = \"one\"', + 'second = 1', + '[2] = ', + 'first = \"two\"', + 'second = 2', + '[3] = ', + 'first = \"three\"', + 'second = 3']) + + self.expect("p si", + substrs=[multimap, 'size=4', + '[0] = ', + 'first = \"zero\"', + 'second = 0', + '[1] = ', + 'first = \"one\"', + 'second = 1', + '[2] = ', + 'first = \"two\"', + 'second = 2', + '[3] = ', + 'first = \"three\"', + 'second = 3']) + + # check that MightHaveChildren() gets it right + self.assertTrue( + self.frame().FindVariable("si").MightHaveChildren(), + "si.MightHaveChildren() says False for non empty!") + + # check access-by-index + self.expect("frame variable si[0]", + substrs=['first = ', 'one', + 'second = 1']) + + # check that the expression parser does not make use of + # synthetic children instead of running code + # TOT clang has a fix for this, which makes the expression command here succeed + # since this would make the test fail or succeed depending on clang version in use + # this is safer commented for the time being + # self.expect("expression si[0]", matching=False, error=True, + # substrs = ['first = ', 'zero']) + + lldbutil.continue_to_breakpoint(self.process(), bkpt) + + self.expect('frame variable si', + substrs=[multimap, 'size=0', + '{}']) + + lldbutil.continue_to_breakpoint(self.process(), bkpt) + + self.expect('frame variable is', + substrs=[multimap, 'size=0', + '{}']) + + lldbutil.continue_to_breakpoint(self.process(), bkpt) + + self.expect("frame variable is", + substrs=[multimap, 'size=4', + '[0] = ', + 'second = \"goofy\"', + 'first = 85', + '[1] = ', + 'second = \"is\"', + 'first = 1', + '[2] = ', + 'second = \"smart\"', + 'first = 2', + '[3] = ', + 'second = \"!!!\"', + 'first = 3']) + + self.expect("p is", + substrs=[multimap, 'size=4', + '[0] = ', + 'second = \"goofy\"', + 'first = 85', + '[1] = ', + 'second = \"is\"', + 'first = 1', + '[2] = ', + 'second = \"smart\"', + 'first = 2', + '[3] = ', + 'second = \"!!!\"', + 'first = 3']) + + # check that MightHaveChildren() gets it right + self.assertTrue( + self.frame().FindVariable("is").MightHaveChildren(), + "is.MightHaveChildren() says False for non empty!") + + # check access-by-index + self.expect("frame variable is[0]", + substrs=['first = ', + 'second =']) + + # check that the expression parser does not make use of + # synthetic children instead of running code + # TOT clang has a fix for this, which makes the expression command here succeed + # since this would make the test fail or succeed depending on clang version in use + # this is safer commented for the time being + # self.expect("expression is[0]", matching=False, error=True, + # substrs = ['first = ', 'goofy']) + + lldbutil.continue_to_breakpoint(self.process(), bkpt) + + self.expect('frame variable is', + substrs=[multimap, 'size=0', + '{}']) + + lldbutil.continue_to_breakpoint(self.process(), bkpt) + + self.expect('frame variable ss', + substrs=[multimap, 'size=0', + '{}']) + + lldbutil.continue_to_breakpoint(self.process(), bkpt) + + self.expect("frame variable ss", + substrs=[multimap, 'size=3', + '[0] = ', + 'second = \"hello\"', + 'first = \"ciao\"', + '[1] = ', + 'second = \"house\"', + 'first = \"casa\"', + '[2] = ', + 'second = \"cat\"', + 'first = \"gatto\"']) + + self.expect("p ss", + substrs=[multimap, 'size=3', + '[0] = ', + 'second = \"hello\"', + 'first = \"ciao\"', + '[1] = ', + 'second = \"house\"', + 'first = \"casa\"', + '[2] = ', + 'second = \"cat\"', + 'first = \"gatto\"']) + + # check that MightHaveChildren() gets it right + self.assertTrue( + self.frame().FindVariable("ss").MightHaveChildren(), + "ss.MightHaveChildren() says False for non empty!") + + # check access-by-index + self.expect("frame variable ss[2]", + substrs=['gatto', 'cat']) + + # check that the expression parser does not make use of + # synthetic children instead of running code + # TOT clang has a fix for this, which makes the expression command here succeed + # since this would make the test fail or succeed depending on clang version in use + # this is safer commented for the time being + # self.expect("expression ss[3]", matching=False, error=True, + # substrs = ['gatto']) + + lldbutil.continue_to_breakpoint(self.process(), bkpt) + + self.expect('frame variable ss', + substrs=[multimap, 'size=0', + '{}']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/main.cpp new file mode 100644 index 00000000000..27bdc0a5772 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/main.cpp @@ -0,0 +1,77 @@ +#include <string> +#include <map> + +#define intint_map std::multimap<int, int> +#define strint_map std::multimap<std::string, int> +#define intstr_map std::multimap<int, std::string> +#define strstr_map std::multimap<std::string, std::string> + +int g_the_foo = 0; + +int thefoo_rw(int arg = 1) +{ + if (arg < 0) + arg = 0; + if (!arg) + arg = 1; + g_the_foo += arg; + return g_the_foo; +} + +int main() +{ + intint_map ii; + + ii.emplace(0,0); // Set break point at this line. + ii.emplace(1,1); + thefoo_rw(1); // Set break point at this line. + ii.emplace(2,0); + ii.emplace(3,1); + thefoo_rw(1); // Set break point at this line. + ii.emplace(4,0); + ii.emplace(5,1); + ii.emplace(6,0); + ii.emplace(7,1); + thefoo_rw(1); // Set break point at this line. + ii.emplace(85,1234567); + + ii.clear(); + + strint_map si; + thefoo_rw(1); // Set break point at this line. + + si.emplace("zero",0); + thefoo_rw(1); // Set break point at this line. + si.emplace("one",1); + si.emplace("two",2); + si.emplace("three",3); + thefoo_rw(1); // Set break point at this line. + si.emplace("four",4); + + si.clear(); + thefoo_rw(1); // Set break point at this line. + + intstr_map is; + thefoo_rw(1); // Set break point at this line. + is.emplace(85,"goofy"); + is.emplace(1,"is"); + is.emplace(2,"smart"); + is.emplace(3,"!!!"); + thefoo_rw(1); // Set break point at this line. + + is.clear(); + thefoo_rw(1); // Set break point at this line. + + strstr_map ss; + thefoo_rw(1); // Set break point at this line. + + ss.emplace("ciao","hello"); + ss.emplace("casa","house"); + ss.emplace("gatto","cat"); + thefoo_rw(1); // Set break point at this line. + ss.emplace("a Mac..","..is always a Mac!"); + + ss.clear(); + thefoo_rw(1); // Set break point at this line. + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/Makefile new file mode 100644 index 00000000000..564cbada74e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/Makefile @@ -0,0 +1,6 @@ +CXX_SOURCES := main.cpp + +USE_LIBCPP := 1 + +CXXFLAGS_EXTRAS := -O0 +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/TestDataFormatterLibcxxMultiSet.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/TestDataFormatterLibcxxMultiSet.py new file mode 100644 index 00000000000..621b22a538c --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/TestDataFormatterLibcxxMultiSet.py @@ -0,0 +1,142 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class LibcxxMultiSetDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + TestBase.setUp(self) + ns = 'ndk' if lldbplatformutil.target_is_android() else '' + self.namespace = 'std::__' + ns + '1' + + def getVariableType(self, name): + var = self.frame().FindVariable(name) + self.assertTrue(var.IsValid()) + return var.GetType().GetCanonicalType().GetName() + + def check_ii(self, var_name): + """ This checks the value of the bitset stored in ii at the call to by_ref_and_ptr. + We use this to make sure we get the same values for ii when we look at the object + directly, and when we look at a reference to the object. """ + self.expect( + "frame variable " + var_name, + substrs=["size=7", + "[2] = 2", + "[3] = 3", + "[6] = 6"]) + self.expect("frame variable " + var_name + "[2]", substrs=[" = 2"]) + self.expect( + "p " + var_name, + substrs=[ + "size=7", + "[2] = 2", + "[3] = 3", + "[6] = 6"]) + + @add_test_categories(["libc++"]) + def test_with_run_command(self): + """Test that that file and class static variables display correctly.""" + self.build() + (self.target, process, _, bkpt) = lldbutil.run_to_source_breakpoint( + self, "Set break point at this line.", lldb.SBFileSpec("main.cpp", False)) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + self.runCmd('type synth clear', check=False) + self.runCmd( + "settings set target.max-children-count 256", + check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + ii_type = self.getVariableType("ii") + self.assertTrue(ii_type.startswith(self.namespace + "::multiset"), + "Type: " + ii_type) + + self.expect("frame variable ii", substrs=["size=0", "{}"]) + lldbutil.continue_to_breakpoint(process, bkpt) + self.expect( + "frame variable ii", + substrs=[ + "size=6", + "[0] = 0", + "[1] = 1", + "[2] = 2", + "[3] = 3", + "[4] = 4", + "[5] = 5"]) + lldbutil.continue_to_breakpoint(process, bkpt) + + self.check_ii("ii") + + lldbutil.continue_to_breakpoint(process, bkpt) + self.expect("frame variable ii", substrs=["size=0", "{}"]) + lldbutil.continue_to_breakpoint(process, bkpt) + self.expect("frame variable ii", substrs=["size=0", "{}"]) + ss_type = self.getVariableType("ss") + self.assertTrue(ss_type.startswith(self.namespace + "::multiset"), + "Type: " + ss_type) + self.expect("frame variable ss", substrs=["size=0", "{}"]) + lldbutil.continue_to_breakpoint(process, bkpt) + self.expect( + "frame variable ss", + substrs=[ + "size=2", + '[0] = "a"', + '[1] = "a very long string is right here"']) + lldbutil.continue_to_breakpoint(process, bkpt) + self.expect( + "frame variable ss", + substrs=[ + "size=4", + '[2] = "b"', + '[3] = "c"', + '[0] = "a"', + '[1] = "a very long string is right here"']) + self.expect( + "p ss", + substrs=[ + "size=4", + '[2] = "b"', + '[3] = "c"', + '[0] = "a"', + '[1] = "a very long string is right here"']) + self.expect("frame variable ss[2]", substrs=[' = "b"']) + lldbutil.continue_to_breakpoint(process, bkpt) + self.expect( + "frame variable ss", + substrs=[ + "size=3", + '[0] = "a"', + '[1] = "a very long string is right here"', + '[2] = "c"']) + + @add_test_categories(["libc++"]) + def test_ref_and_ptr(self): + """Test that the data formatters work on ref and ptr.""" + self.build() + (self.target, process, _, bkpt) = lldbutil.run_to_source_breakpoint( + self, "Stop here to check by ref and ptr.", + lldb.SBFileSpec("main.cpp", False)) + # The reference should print just like the value: + self.check_ii("ref") + + self.expect("frame variable ptr", + substrs=["ptr =", "size=7"]) + self.expect("expr ptr", + substrs=["size=7"]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/main.cpp new file mode 100644 index 00000000000..dd3d8be4ae9 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/main.cpp @@ -0,0 +1,61 @@ +#include <string> +#include <set> + +typedef std::multiset<int> intset; +typedef std::multiset<std::string> stringset; + +int g_the_foo = 0; + +int thefoo_rw(int arg = 1) +{ + if (arg < 0) + arg = 0; + if (!arg) + arg = 1; + g_the_foo += arg; + return g_the_foo; +} + +void by_ref_and_ptr(intset &ref, intset *ptr) +{ + // Stop here to check by ref and ptr + return; +} + +int main() +{ + intset ii; + thefoo_rw(1); // Set break point at this line. + + ii.insert(0); + ii.insert(1); + ii.insert(2); + ii.insert(3); + ii.insert(4); + ii.insert(5); + thefoo_rw(1); // Set break point at this line. + + ii.insert(6); + thefoo_rw(1); // Set break point at this line. + + by_ref_and_ptr(ii, &ii); + + ii.clear(); + thefoo_rw(1); // Set break point at this line. + + stringset ss; + thefoo_rw(1); // Set break point at this line. + + ss.insert("a"); + ss.insert("a very long string is right here"); + thefoo_rw(1); // Set break point at this line. + + ss.insert("b"); + ss.insert("c"); + thefoo_rw(1); // Set break point at this line. + + ss.erase("b"); + thefoo_rw(1); // Set break point at this line. + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/Makefile new file mode 100644 index 00000000000..23496eb2065 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/Makefile @@ -0,0 +1,6 @@ +CXX_SOURCES := main.cpp + +USE_LIBCPP := 1 + +CXXFLAGS_EXTRAS := -std=c++17 -fno-exceptions +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/TestDataFormatterLibcxxOptional.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/TestDataFormatterLibcxxOptional.py new file mode 100644 index 00000000000..f013d02d14f --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/TestDataFormatterLibcxxOptional.py @@ -0,0 +1,72 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class LibcxxOptionalDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @add_test_categories(["libc++"]) + ## We are skipping clang version less that 5.0 since this test requires -std=c++17 + @skipIf(oslist=no_match(["macosx"]), compiler="clang", compiler_version=['<', '5.0']) + ## We are skipping gcc version less that 5.1 since this test requires -std=c++17 + @skipIf(compiler="gcc", compiler_version=['<', '5.1']) + + def test_with_run_command(self): + """Test that that file and class static variables display correctly.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + bkpt = self.target().FindBreakpointByID( + lldbutil.run_break_set_by_source_regexp( + self, "break here")) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + self.runCmd( "frame variable has_optional" ) + + output = self.res.GetOutput() + + ## The variable has_optional tells us if the test program + ## detected we have a sufficient libc++ version to support optional + ## false means we do not and therefore should skip the test + if output.find("(bool) has_optional = false") != -1 : + self.skipTest( "Optional not supported" ) + + lldbutil.continue_to_breakpoint(self.process(), bkpt) + + self.expect("frame variable number_not_engaged", + substrs=['Has Value=false']) + + self.expect("frame variable number_engaged", + substrs=['Has Value=true', + 'Value = 42', + '}']) + + self.expect("frame var numbers", + substrs=['(optional_int_vect) numbers = Has Value=true {', + 'Value = size=4 {', + '[0] = 1', + '[1] = 2', + '[2] = 3', + '[3] = 4', + '}', + '}']) + + self.expect("frame var ostring", + substrs=['(optional_string) ostring = Has Value=true {', + 'Value = "hello"', + '}']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/main.cpp new file mode 100644 index 00000000000..16bb98c6105 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/main.cpp @@ -0,0 +1,42 @@ +#include <cstdio> +#include <string> +#include <vector> + +// If we have libc++ 4.0 or greater we should have <optional> +// According to libc++ C++1z status page https://libcxx.llvm.org/cxx1z_status.html +#if _LIBCPP_VERSION >= 4000 +#include <optional> +#define HAVE_OPTIONAL 1 +#else +#define HAVE_OPTIONAL 0 +#endif + + +int main() +{ + bool has_optional = HAVE_OPTIONAL ; + + printf( "%d\n", has_optional ) ; // break here + +#if HAVE_OPTIONAL == 1 + using int_vect = std::vector<int> ; + using optional_int = std::optional<int> ; + using optional_int_vect = std::optional<int_vect> ; + using optional_string = std::optional<std::string> ; + + optional_int number_not_engaged ; + optional_int number_engaged = 42 ; + + printf( "%d\n", *number_engaged) ; + + optional_int_vect numbers{{1,2,3,4}} ; + + printf( "%d %d\n", numbers.value()[0], numbers.value()[1] ) ; + + optional_string ostring = "hello" ; + + printf( "%s\n", ostring->c_str() ) ; +#endif + + return 0; // break here +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/queue/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/queue/Makefile new file mode 100644 index 00000000000..680e1abfbef --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/queue/Makefile @@ -0,0 +1,4 @@ +CXX_SOURCES := main.cpp + +USE_LIBCPP := 1 +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/queue/TestDataFormatterLibcxxQueue.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/queue/TestDataFormatterLibcxxQueue.py new file mode 100644 index 00000000000..b163fa56fae --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/queue/TestDataFormatterLibcxxQueue.py @@ -0,0 +1,43 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestDataFormatterLibcxxQueue(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + TestBase.setUp(self) + ns = 'ndk' if lldbplatformutil.target_is_android() else '' + self.namespace = 'std::__' + ns + '1' + + def check_variable(self, name): + var = self.frame().FindVariable(name) + self.assertTrue(var.IsValid()) + + queue = self.namespace + '::queue' + self.assertTrue(queue in var.GetTypeName()) + self.assertEqual(var.GetNumChildren(), 5) + for i in range(5): + ch = var.GetChildAtIndex(i) + self.assertTrue(ch.IsValid()) + self.assertEqual(ch.GetValueAsSigned(), i+1) + + @expectedFailureAll(bugnumber="llvm.org/pr36109", debug_info="gmodules", triple=".*-android") + @add_test_categories(["libc++"]) + def test(self): + """Test that std::queue is displayed correctly""" + self.build() + lldbutil.run_to_source_breakpoint(self, '// break here', + lldb.SBFileSpec("main.cpp", False)) + + self.check_variable('q1') + self.check_variable('q2') diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/queue/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/queue/main.cpp new file mode 100644 index 00000000000..449be8d99cf --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/queue/main.cpp @@ -0,0 +1,11 @@ +#include <queue> +#include <vector> + +using namespace std; + +int main() { + queue<int> q1{{1,2,3,4,5}}; + queue<int, std::vector<int>> q2{{1,2,3,4,5}}; + int ret = q1.size() + q2.size(); // break here + return ret; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/set/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/set/Makefile new file mode 100644 index 00000000000..564cbada74e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/set/Makefile @@ -0,0 +1,6 @@ +CXX_SOURCES := main.cpp + +USE_LIBCPP := 1 + +CXXFLAGS_EXTRAS := -O0 +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/set/TestDataFormatterLibcxxSet.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/set/TestDataFormatterLibcxxSet.py new file mode 100644 index 00000000000..738df85d051 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/set/TestDataFormatterLibcxxSet.py @@ -0,0 +1,139 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class LibcxxSetDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + TestBase.setUp(self) + ns = 'ndk' if lldbplatformutil.target_is_android() else '' + self.namespace = 'std::__' + ns + '1' + + def getVariableType(self, name): + var = self.frame().FindVariable(name) + self.assertTrue(var.IsValid()) + return var.GetType().GetCanonicalType().GetName() + + def check_ii(self, var_name): + """ This checks the value of the bitset stored in ii at the call to by_ref_and_ptr. + We use this to make sure we get the same values for ii when we look at the object + directly, and when we look at a reference to the object. """ + self.expect( + "frame variable " + var_name, + substrs=["size=7", + "[2] = 2", + "[3] = 3", + "[6] = 6"]) + self.expect("frame variable " + var_name + "[2]", substrs=[" = 2"]) + self.expect( + "p " + var_name, + substrs=[ + "size=7", + "[2] = 2", + "[3] = 3", + "[6] = 6"]) + + @add_test_categories(["libc++"]) + def test_with_run_command(self): + """Test that that file and class static variables display correctly.""" + self.build() + (self.target, process, _, bkpt) = lldbutil.run_to_source_breakpoint( + self, "Set break point at this line.", lldb.SBFileSpec("main.cpp", False)) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + self.runCmd('type synth clear', check=False) + self.runCmd( + "settings set target.max-children-count 256", + check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + ii_type = self.getVariableType("ii") + self.assertTrue(ii_type.startswith(self.namespace + "::set"), + "Type: " + ii_type) + + self.expect("frame variable ii", substrs=["size=0", "{}"]) + lldbutil.continue_to_breakpoint(process, bkpt) + self.expect( + "frame variable ii", + substrs=["size=6", + "[0] = 0", + "[1] = 1", + "[2] = 2", + "[3] = 3", + "[4] = 4", + "[5] = 5"]) + lldbutil.continue_to_breakpoint(process, bkpt) + self.check_ii("ii") + + lldbutil.continue_to_breakpoint(process, bkpt) + self.expect("frame variable ii", substrs=["size=0", "{}"]) + lldbutil.continue_to_breakpoint(process, bkpt) + self.expect("frame variable ii", substrs=["size=0", "{}"]) + + ss_type = self.getVariableType("ss") + self.assertTrue(ii_type.startswith(self.namespace + "::set"), + "Type: " + ss_type) + + self.expect("frame variable ss", substrs=["size=0", "{}"]) + lldbutil.continue_to_breakpoint(process, bkpt) + self.expect( + "frame variable ss", + substrs=["size=2", + '[0] = "a"', + '[1] = "a very long string is right here"']) + lldbutil.continue_to_breakpoint(process, bkpt) + self.expect( + "frame variable ss", + substrs=["size=4", + '[2] = "b"', + '[3] = "c"', + '[0] = "a"', + '[1] = "a very long string is right here"']) + self.expect( + "p ss", + substrs=["size=4", + '[2] = "b"', + '[3] = "c"', + '[0] = "a"', + '[1] = "a very long string is right here"']) + self.expect("frame variable ss[2]", substrs=[' = "b"']) + lldbutil.continue_to_breakpoint(process, bkpt) + self.expect( + "frame variable ss", + substrs=["size=3", + '[0] = "a"', + '[1] = "a very long string is right here"', + '[2] = "c"']) + + @add_test_categories(["libc++"]) + def test_ref_and_ptr(self): + """Test that the data formatters work on ref and ptr.""" + self.build() + (self.target, process, _, bkpt) = lldbutil.run_to_source_breakpoint( + self, "Stop here to check by ref and ptr.", + lldb.SBFileSpec("main.cpp", False)) + # The reference should print just like the value: + self.check_ii("ref") + + self.expect("frame variable ptr", + substrs=["ptr =", "size=7"]) + self.expect("expr ptr", + substrs=["size=7"]) + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/set/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/set/main.cpp new file mode 100644 index 00000000000..df39e9746c0 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/set/main.cpp @@ -0,0 +1,61 @@ +#include <string> +#include <set> + +typedef std::set<int> intset; +typedef std::set<std::string> stringset; + +int g_the_foo = 0; + +int thefoo_rw(int arg = 1) +{ + if (arg < 0) + arg = 0; + if (!arg) + arg = 1; + g_the_foo += arg; + return g_the_foo; +} + +void by_ref_and_ptr(intset &ref, intset *ptr) +{ + // Stop here to check by ref and ptr + return; +} + +int main() +{ + intset ii; + thefoo_rw(1); // Set break point at this line. + + ii.insert(0); + ii.insert(1); + ii.insert(2); + ii.insert(3); + ii.insert(4); + ii.insert(5); + thefoo_rw(1); // Set break point at this line. + + ii.insert(6); + thefoo_rw(1); // Set break point at this line. + + by_ref_and_ptr(ii, &ii); + + ii.clear(); + thefoo_rw(1); // Set break point at this line. + + stringset ss; + thefoo_rw(1); // Set break point at this line. + + ss.insert("a"); + ss.insert("a very long string is right here"); + thefoo_rw(1); // Set break point at this line. + + ss.insert("b"); + ss.insert("c"); + thefoo_rw(1); // Set break point at this line. + + ss.erase("b"); + thefoo_rw(1); // Set break point at this line. + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/Makefile new file mode 100644 index 00000000000..c7c91da728d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/Makefile @@ -0,0 +1,6 @@ +CXX_SOURCES := main.cpp + +USE_LIBCPP := 1 + +CXXFLAGS_EXTRAS := -std=c++11 -O0 +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py new file mode 100644 index 00000000000..8943b259668 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py @@ -0,0 +1,116 @@ +# coding=utf8 +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class LibcxxStringDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + ns = 'ndk' if lldbplatformutil.target_is_android() else '' + self.namespace = 'std::__' + ns + '1' + + @add_test_categories(["libc++"]) + @expectedFailureAll(bugnumber="llvm.org/pr36109", debug_info="gmodules", triple=".*-android") + def test_with_run_command(self): + """Test that that file and class static variables display correctly.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=-1) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + self.runCmd('type synth clear', check=False) + self.runCmd( + "settings set target.max-children-count 256", + check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + ns = self.namespace + self.expect( + "frame variable", + substrs=[ + '(%s::wstring) wempty = L""'%ns, + '(%s::wstring) s = L"hello world! מזל טוב!"'%ns, + '(%s::wstring) S = L"!!!!"'%ns, + '(const wchar_t *) mazeltov = 0x', + 'L"מזל טוב"', + '(%s::string) empty = ""'%ns, + '(%s::string) q = "hello world"'%ns, + '(%s::string) Q = "quite a long std::strin with lots of info inside it"'%ns, + '(%s::string) IHaveEmbeddedZeros = "a\\0b\\0c\\0d"'%ns, + '(%s::wstring) IHaveEmbeddedZerosToo = L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"'%ns, + '(%s::u16string) u16_string = u"ß水氶"'%ns, + # FIXME: This should have a 'u' prefix. + '(%s::u16string) u16_empty = ""'%ns, + '(%s::u32string) u32_string = U"🍄🍅🍆🍌"'%ns, + # FIXME: This should have a 'U' prefix. + '(%s::u32string) u32_empty = ""'%ns, + '(%s::basic_string<unsigned char, %s::char_traits<unsigned char>, ' + '%s::allocator<unsigned char> >) uchar = "aaaaa"'%(ns,ns,ns), + ]) + + self.runCmd("n") + + TheVeryLongOne = self.frame().FindVariable("TheVeryLongOne") + summaryOptions = lldb.SBTypeSummaryOptions() + summaryOptions.SetCapping(lldb.eTypeSummaryUncapped) + uncappedSummaryStream = lldb.SBStream() + TheVeryLongOne.GetSummary(uncappedSummaryStream, summaryOptions) + uncappedSummary = uncappedSummaryStream.GetData() + self.assertTrue(uncappedSummary.find("someText") > 0, + "uncappedSummary does not include the full string") + summaryOptions.SetCapping(lldb.eTypeSummaryCapped) + cappedSummaryStream = lldb.SBStream() + TheVeryLongOne.GetSummary(cappedSummaryStream, summaryOptions) + cappedSummary = cappedSummaryStream.GetData() + self.assertTrue( + cappedSummary.find("someText") <= 0, + "cappedSummary includes the full string") + + self.expect_expr("s", result_type=ns+"::wstring", result_summary='L"hello world! מזל טוב!"') + + self.expect( + "frame variable", + substrs=[ + '(%s::wstring) S = L"!!!!!"'%ns, + '(const wchar_t *) mazeltov = 0x', + 'L"מזל טוב"', + '(%s::string) q = "hello world"'%ns, + '(%s::string) Q = "quite a long std::strin with lots of info inside it"'%ns, + '(%s::string) IHaveEmbeddedZeros = "a\\0b\\0c\\0d"'%ns, + '(%s::wstring) IHaveEmbeddedZerosToo = L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"'%ns, + '(%s::u16string) u16_string = u"ß水氶"'%ns, + '(%s::u32string) u32_string = U"🍄🍅🍆🍌"'%ns, + '(%s::u32string) u32_empty = ""'%ns, + '(%s::basic_string<unsigned char, %s::char_traits<unsigned char>, ' + '%s::allocator<unsigned char> >) uchar = "aaaaa"'%(ns,ns,ns), + ]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/main.cpp new file mode 100644 index 00000000000..afb56e67f0a --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/main.cpp @@ -0,0 +1,22 @@ +#include <string> + +int main() +{ + std::wstring wempty(L""); + std::wstring s(L"hello world! מזל טוב!"); + std::wstring S(L"!!!!"); + const wchar_t *mazeltov = L"מזל טוב"; + std::string empty(""); + std::string q("hello world"); + std::string Q("quite a long std::strin with lots of info inside it"); + std::string TheVeryLongOne("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890someText1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); + std::string IHaveEmbeddedZeros("a\0b\0c\0d",7); + std::wstring IHaveEmbeddedZerosToo(L"hello world!\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監", 38); + std::u16string u16_string(u"ß水氶"); + std::u16string u16_empty(u""); + std::u32string u32_string(U"🍄🍅🍆🍌"); + std::u32string u32_empty(U""); + std::basic_string<unsigned char> uchar(5, 'a'); + S.assign(L"!!!!!"); // Set break point at this line. + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/tuple/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/tuple/Makefile new file mode 100644 index 00000000000..680e1abfbef --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/tuple/Makefile @@ -0,0 +1,4 @@ +CXX_SOURCES := main.cpp + +USE_LIBCPP := 1 +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/tuple/TestDataFormatterLibcxxTuple.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/tuple/TestDataFormatterLibcxxTuple.py new file mode 100644 index 00000000000..57b77783716 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/tuple/TestDataFormatterLibcxxTuple.py @@ -0,0 +1,50 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestDataFormatterLibcxxTuple(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + TestBase.setUp(self) + self.line = line_number('main.cpp', '// break here') + ns = 'ndk' if lldbplatformutil.target_is_android() else '' + self.namespace = 'std::__' + ns + '1' + + @add_test_categories(["libc++"]) + def test(self): + """Test that std::tuple is displayed correctly""" + self.build() + lldbutil.run_to_source_breakpoint(self, '// break here', + lldb.SBFileSpec("main.cpp", False)) + + tuple_name = self.namespace + '::tuple' + self.expect("frame variable empty", + substrs=[tuple_name, + 'size=0', + '{}']) + + self.expect("frame variable one_elt", + substrs=[tuple_name, + 'size=1', + '{', + '[0] = 47', + '}']) + + self.expect("frame variable three_elts", + substrs=[tuple_name, + 'size=3', + '{', + '[0] = 1', + '[1] = 47', + '[2] = "foo"', + '}']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/tuple/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/tuple/main.cpp new file mode 100644 index 00000000000..1c0d0f2ae77 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/tuple/main.cpp @@ -0,0 +1,11 @@ +#include <tuple> +#include <string> + +using namespace std; + +int main() { + tuple<> empty; + tuple<int> one_elt{47}; + tuple<int, long, string> three_elts{1, 47l, "foo"}; + return 0; // break here +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/unordered/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/unordered/Makefile new file mode 100644 index 00000000000..913a52fb191 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/unordered/Makefile @@ -0,0 +1,9 @@ +CXX_SOURCES := main.cpp + +# Work around "exception specification in declaration does not match previous +# declaration" errors present in older libc++ releases. This error was fixed in +# the 3.8 release. +CFLAGS_EXTRAS := -fno-exceptions + +USE_LIBCPP := 1 +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/unordered/TestDataFormatterUnordered.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/unordered/TestDataFormatterUnordered.py new file mode 100644 index 00000000000..9566af03130 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/unordered/TestDataFormatterUnordered.py @@ -0,0 +1,79 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class LibcxxUnorderedDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + TestBase.setUp(self) + ns = 'ndk' if lldbplatformutil.target_is_android() else '' + self.namespace = 'std::__' + ns + '1' + + @add_test_categories(["libc++"]) + def test_with_run_command(self): + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_source_regexp( + self, "Set break point at this line.") + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + self.runCmd('type synth clear', check=False) + self.runCmd( + "settings set target.max-children-count 256", + check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + ns = self.namespace + self.look_for_content_and_continue( + "map", ['%s::unordered_map' % + ns, 'size=5 {', 'hello', 'world', 'this', 'is', 'me']) + + self.look_for_content_and_continue( + "mmap", ['%s::unordered_multimap' % ns, 'size=6 {', 'first = 3', 'second = "this"', + 'first = 2', 'second = "hello"']) + + self.look_for_content_and_continue( + "iset", ['%s::unordered_set' % + ns, 'size=5 {', '\[\d\] = 5', '\[\d\] = 3', '\[\d\] = 2']) + + self.look_for_content_and_continue( + "sset", ['%s::unordered_set' % ns, 'size=5 {', '\[\d\] = "is"', '\[\d\] = "world"', + '\[\d\] = "hello"']) + + self.look_for_content_and_continue( + "imset", ['%s::unordered_multiset' % ns, 'size=6 {', '(\[\d\] = 3(\\n|.)+){3}', + '\[\d\] = 2', '\[\d\] = 1']) + + self.look_for_content_and_continue( + "smset", ['%s::unordered_multiset' % ns, 'size=5 {', '(\[\d\] = "is"(\\n|.)+){2}', + '(\[\d\] = "world"(\\n|.)+){2}']) + + def look_for_content_and_continue(self, var_name, patterns): + self.expect(("frame variable %s" % var_name), patterns=patterns) + self.expect(("frame variable %s" % var_name), patterns=patterns) + self.runCmd("continue") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/unordered/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/unordered/main.cpp new file mode 100644 index 00000000000..81a5763559d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/unordered/main.cpp @@ -0,0 +1,80 @@ +#include <string> +#include <unordered_map> +#include <unordered_set> + +using std::string; + +#define intstr_map std::unordered_map<int, string> +#define intstr_mmap std::unordered_multimap<int, string> + +#define int_set std::unordered_set<int> +#define str_set std::unordered_set<string> +#define int_mset std::unordered_multiset<int> +#define str_mset std::unordered_multiset<string> + +int g_the_foo = 0; + +int thefoo_rw(int arg = 1) +{ + if (arg < 0) + arg = 0; + if (!arg) + arg = 1; + g_the_foo += arg; + return g_the_foo; +} + +int main() +{ + intstr_map map; + map.emplace(1,"hello"); + map.emplace(2,"world"); + map.emplace(3,"this"); + map.emplace(4,"is"); + map.emplace(5,"me"); + thefoo_rw(); // Set break point at this line. + + intstr_mmap mmap; + mmap.emplace(1,"hello"); + mmap.emplace(2,"hello"); + mmap.emplace(2,"world"); + mmap.emplace(3,"this"); + mmap.emplace(3,"this"); + mmap.emplace(3,"this"); + thefoo_rw(); // Set break point at this line. + + int_set iset; + iset.emplace(1); + iset.emplace(2); + iset.emplace(3); + iset.emplace(4); + iset.emplace(5); + thefoo_rw(); // Set break point at this line. + + str_set sset; + sset.emplace("hello"); + sset.emplace("world"); + sset.emplace("this"); + sset.emplace("is"); + sset.emplace("me"); + thefoo_rw(); // Set break point at this line. + + int_mset imset; + imset.emplace(1); + imset.emplace(2); + imset.emplace(2); + imset.emplace(3); + imset.emplace(3); + imset.emplace(3); + thefoo_rw(); // Set break point at this line. + + str_mset smset; + smset.emplace("hello"); + smset.emplace("world"); + smset.emplace("world"); + smset.emplace("is"); + smset.emplace("is"); + thefoo_rw(); // Set break point at this line. + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/Makefile new file mode 100644 index 00000000000..7eeff740780 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/Makefile @@ -0,0 +1,6 @@ +CXX_SOURCES := main.cpp + +USE_LIBCPP := 1 + +CXXFLAGS_EXTRAS := -std=c++17 +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/TestDataFormatterLibcxxVariant.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/TestDataFormatterLibcxxVariant.py new file mode 100644 index 00000000000..a2a6b74faa4 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/TestDataFormatterLibcxxVariant.py @@ -0,0 +1,80 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class LibcxxVariantDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @add_test_categories(["libc++"]) + ## We are skipping clang version less that 5.0 since this test requires -std=c++17 + @skipIf(oslist=no_match(["macosx"]), compiler="clang", compiler_version=['<', '5.0']) + ## We are skipping gcc version less that 5.1 since this test requires -std=c++17 + @skipIf(compiler="gcc", compiler_version=['<', '5.1']) + ## std::get is unavailable for std::variant before macOS 10.14 + @skipIf(macos_version=["<", "10.14"]) + + def test_with_run_command(self): + """Test that that file and class static variables display correctly.""" + self.build() + + (self.target, self.process, _, bkpt) = lldbutil.run_to_source_breakpoint(self, '// break here', + lldb.SBFileSpec("main.cpp", False)) + + self.runCmd( "frame variable has_variant" ) + + output = self.res.GetOutput() + + ## The variable has_variant tells us if the test program + ## detected we have a sufficient libc++ version to support variant + ## false means we do not and therefore should skip the test + if output.find("(bool) has_variant = false") != -1 : + self.skipTest( "std::variant not supported" ) + + lldbutil.continue_to_breakpoint(self.process, bkpt) + + self.expect("frame variable v1", + substrs=['v1 = Active Type = int {', + 'Value = 12', + '}']) + + self.expect("frame variable v1_ref", + substrs=['v1_ref = Active Type = int : {', + 'Value = 12', + '}']) + + self.expect("frame variable v_v1", + substrs=['v_v1 = Active Type = std::__1::variant<int, double, char> {', + 'Value = Active Type = int {', + 'Value = 12', + '}', + '}']) + + lldbutil.continue_to_breakpoint(self.process, bkpt) + + self.expect("frame variable v1", + substrs=['v1 = Active Type = double {', + 'Value = 2', + '}']) + + lldbutil.continue_to_breakpoint(self.process, bkpt) + + self.expect("frame variable v2", + substrs=['v2 = Active Type = double {', + 'Value = 2', + '}']) + + self.expect("frame variable v3", + substrs=['v3 = Active Type = char {', + 'Value = \'A\'', + '}']) + + self.expect("frame variable v_no_value", + substrs=['v_no_value = No Value']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/main.cpp new file mode 100644 index 00000000000..c0bc4ae12c1 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/main.cpp @@ -0,0 +1,60 @@ +#include <cstdio> +#include <string> +#include <vector> + +// If we have libc++ 4.0 or greater we should have <variant> +// According to libc++ C++1z status page https://libcxx.llvm.org/cxx1z_status.html +#if _LIBCPP_VERSION >= 4000 +#include <variant> +#define HAVE_VARIANT 1 +#else +#define HAVE_VARIANT 0 +#endif + +struct S { + operator int() { throw 42; } +} ; + + +int main() +{ + bool has_variant = HAVE_VARIANT ; + + printf( "%d\n", has_variant ) ; // break here + +#if HAVE_VARIANT == 1 + std::variant<int, double, char> v1; + std::variant<int, double, char> &v1_ref = v1; + std::variant<int, double, char> v2; + std::variant<int, double, char> v3; + std::variant<std::variant<int,double,char>> v_v1 ; + std::variant<int, double, char> v_no_value; + + v1 = 12; // v contains int + v_v1 = v1 ; + int i = std::get<int>(v1); + printf( "%d\n", i ); // break here + + v2 = 2.0 ; + double d = std::get<double>(v2) ; + printf( "%f\n", d ); + + v3 = 'A' ; + char c = std::get<char>(v3) ; + printf( "%d\n", c ); + + // Checking v1 above and here to make sure we done maintain the incorrect + // state when we change its value. + v1 = 2.0; + d = std::get<double>(v1) ; + printf( "%f\n", d ); // break here + + try { + v_no_value.emplace<0>(S()); + } catch( ... ) {} + + printf( "%zu\n", v_no_value.index() ) ; +#endif + + return 0; // break here +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vbool/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vbool/Makefile new file mode 100644 index 00000000000..d87cf7d4027 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vbool/Makefile @@ -0,0 +1,4 @@ +CXX_SOURCES := main.cpp +USE_LIBCPP := 1 +include Makefile.rules + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vbool/TestDataFormatterLibcxxVBool.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vbool/TestDataFormatterLibcxxVBool.py new file mode 100644 index 00000000000..67e0629e6b7 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vbool/TestDataFormatterLibcxxVBool.py @@ -0,0 +1,75 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class LibcxxVBoolDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + @add_test_categories(["libc++"]) + def test_with_run_command(self): + """Test that that file and class static variables display correctly.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=-1) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + self.runCmd('type synth clear', check=False) + self.runCmd( + "settings set target.max-children-count 256", + check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.expect( + "frame variable vBool", + substrs=[ + 'size=49', + '[0] = false', + '[1] = true', + '[18] = false', + '[27] = true', + '[36] = false', + '[47] = true', + '[48] = true']) + + self.expect( + "expr vBool", + substrs=[ + 'size=49', + '[0] = false', + '[1] = true', + '[18] = false', + '[27] = true', + '[36] = false', + '[47] = true', + '[48] = true']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vbool/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vbool/main.cpp new file mode 100644 index 00000000000..026cfc863f2 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vbool/main.cpp @@ -0,0 +1,65 @@ +#include <string> +#include <vector> + +int main() +{ + std::vector<bool> vBool; + + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(true); + + printf ("size: %d", (int) vBool.size()); // Set break point at this line. + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/Makefile new file mode 100644 index 00000000000..564cbada74e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/Makefile @@ -0,0 +1,6 @@ +CXX_SOURCES := main.cpp + +USE_LIBCPP := 1 + +CXXFLAGS_EXTRAS := -O0 +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/TestDataFormatterLibcxxVector.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/TestDataFormatterLibcxxVector.py new file mode 100644 index 00000000000..649c0fee4bd --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/TestDataFormatterLibcxxVector.py @@ -0,0 +1,191 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class LibcxxVectorDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def check_numbers(self, var_name): + self.expect("frame variable " + var_name, + substrs=[var_name + ' = size=7', + '[0] = 1', + '[1] = 12', + '[2] = 123', + '[3] = 1234', + '[4] = 12345', + '[5] = 123456', + '[6] = 1234567', + '}']) + + self.expect("p " + var_name, + substrs=['$', 'size=7', + '[0] = 1', + '[1] = 12', + '[2] = 123', + '[3] = 1234', + '[4] = 12345', + '[5] = 123456', + '[6] = 1234567', + '}']) + + # check access-by-index + self.expect("frame variable " + var_name + "[0]", + substrs=['1']) + self.expect("frame variable " + var_name + "[1]", + substrs=['12']) + self.expect("frame variable " + var_name + "[2]", + substrs=['123']) + self.expect("frame variable " + var_name + "[3]", + substrs=['1234']) + + @add_test_categories(["libc++"]) + def test_with_run_command(self): + """Test that that file and class static variables display correctly.""" + self.build() + (self.target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( + self, "break here", lldb.SBFileSpec("main.cpp", False)) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + self.runCmd('type synth clear', check=False) + self.runCmd( + "settings set target.max-children-count 256", + check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + # empty vectors (and storage pointers SHOULD BOTH BE NULL..) + self.expect("frame variable numbers", + substrs=['numbers = size=0']) + + lldbutil.continue_to_breakpoint(process, bkpt) + + # first value added + self.expect("frame variable numbers", + substrs=['numbers = size=1', + '[0] = 1', + '}']) + + # add some more data + lldbutil.continue_to_breakpoint(process, bkpt) + + self.expect("frame variable numbers", + substrs=['numbers = size=4', + '[0] = 1', + '[1] = 12', + '[2] = 123', + '[3] = 1234', + '}']) + + self.expect("p numbers", + substrs=['$', 'size=4', + '[0] = 1', + '[1] = 12', + '[2] = 123', + '[3] = 1234', + '}']) + + # check access to synthetic children + self.runCmd( + "type summary add --summary-string \"item 0 is ${var[0]}\" std::int_vect int_vect") + self.expect('frame variable numbers', + substrs=['item 0 is 1']) + + self.runCmd( + "type summary add --summary-string \"item 0 is ${svar[0]}\" std::int_vect int_vect") + self.expect('frame variable numbers', + substrs=['item 0 is 1']) + # move on with synths + self.runCmd("type summary delete std::int_vect") + self.runCmd("type summary delete int_vect") + + # add some more data + lldbutil.continue_to_breakpoint(process, bkpt) + + self.check_numbers("numbers") + + # clear out the vector and see that we do the right thing once again + lldbutil.continue_to_breakpoint(process, bkpt) + + self.expect("frame variable numbers", + substrs=['numbers = size=0']) + + lldbutil.continue_to_breakpoint(process, bkpt) + + # first value added + self.expect("frame variable numbers", + substrs=['numbers = size=1', + '[0] = 7', + '}']) + + # check if we can display strings + self.expect("frame variable strings", + substrs=['goofy', + 'is', + 'smart']) + + self.expect("p strings", + substrs=['goofy', + 'is', + 'smart']) + + # test summaries based on synthetic children + self.runCmd( + "type summary add std::string_vect string_vect --summary-string \"vector has ${svar%#} items\" -e") + self.expect("frame variable strings", + substrs=['vector has 3 items', + 'goofy', + 'is', + 'smart']) + + self.expect("p strings", + substrs=['vector has 3 items', + 'goofy', + 'is', + 'smart']) + + lldbutil.continue_to_breakpoint(process, bkpt) + + self.expect("frame variable strings", + substrs=['vector has 4 items']) + + # check access-by-index + self.expect("frame variable strings[0]", + substrs=['goofy']) + self.expect("frame variable strings[1]", + substrs=['is']) + + lldbutil.continue_to_breakpoint(process, bkpt) + + self.expect("frame variable strings", + substrs=['vector has 0 items']) + + @add_test_categories(["libc++"]) + def test_ref_and_ptr(self): + """Test that that file and class static variables display correctly.""" + self.build() + (self.target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( + self, "Stop here to check by ref", lldb.SBFileSpec("main.cpp", False)) + + # The reference should display the same was as the value did + self.check_numbers("ref") + + # The pointer should just show the right number of elements: + + self.expect("frame variable ptr", substrs=['ptr =', ' size=7']) + + self.expect("p ptr", substrs=['$', 'size=7']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/main.cpp new file mode 100644 index 00000000000..0e1dbe4f03e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/main.cpp @@ -0,0 +1,41 @@ +#include <stdio.h> +#include <string> +#include <vector> +typedef std::vector<int> int_vect; +typedef std::vector<std::string> string_vect; + +template <class T> +void by_ref_and_ptr(std::vector<T> &ref, std::vector<T> *ptr) { + // Stop here to check by ref + return; +} + +int main() +{ + int_vect numbers; + (numbers.push_back(1)); // break here + (numbers.push_back(12)); // break here + (numbers.push_back(123)); + (numbers.push_back(1234)); + (numbers.push_back(12345)); // break here + (numbers.push_back(123456)); + (numbers.push_back(1234567)); + by_ref_and_ptr(numbers, &numbers); + + printf("break here"); + numbers.clear(); + + (numbers.push_back(7)); // break here + + string_vect strings; + (strings.push_back(std::string("goofy"))); + (strings.push_back(std::string("is"))); + (strings.push_back(std::string("smart"))); + printf("break here"); + (strings.push_back(std::string("!!!"))); + + printf("break here"); + strings.clear(); + + return 0; // break here +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/Makefile new file mode 100644 index 00000000000..c825977b1a5 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/Makefile @@ -0,0 +1,6 @@ +CXX_SOURCES := main.cpp + +CFLAGS_EXTRAS := -O0 +USE_LIBSTDCPP := 1 + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/TestDataFormatterStdIterator.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/TestDataFormatterStdIterator.py new file mode 100644 index 00000000000..52387a41484 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/TestDataFormatterStdIterator.py @@ -0,0 +1,71 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class StdIteratorDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + @add_test_categories(["libstdcxx"]) + def test_with_run_command(self): + """Test that libstdcpp iterators format properly.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=-1) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + self.runCmd('type synth clear', check=False) + self.runCmd( + "settings set target.max-children-count 256", + check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.expect('frame variable ivI', substrs=['item = 3']) + self.expect('expr ivI', substrs=['item = 3']) + + self.expect( + 'frame variable iimI', + substrs=[ + 'first = 0', + 'second = 12']) + self.expect('expr iimI', substrs=['first = 0', 'second = 12']) + + self.expect( + 'frame variable simI', + substrs=[ + 'first = "world"', + 'second = 42']) + self.expect('expr simI', substrs=['first = "world"', 'second = 42']) + + self.expect('frame variable svI', substrs=['item = "hello"']) + self.expect('expr svI', substrs=['item = "hello"']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/main.cpp new file mode 100644 index 00000000000..7ddffd19012 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/main.cpp @@ -0,0 +1,38 @@ +#include <string> +#include <map> +#include <vector> + +typedef std::map<int, int> intint_map; +typedef std::map<std::string, int> strint_map; + +typedef std::vector<int> int_vector; +typedef std::vector<std::string> string_vector; + +typedef intint_map::iterator iimter; +typedef strint_map::iterator simter; + +typedef int_vector::iterator ivter; +typedef string_vector::iterator svter; + +int main() +{ + intint_map iim; + iim[0] = 12; + + strint_map sim; + sim["world"] = 42; + + int_vector iv; + iv.push_back(3); + + string_vector sv; + sv.push_back("hello"); + + iimter iimI = iim.begin(); + simter simI = sim.begin(); + + ivter ivI = iv.begin(); + svter svI = sv.begin(); + + return 0; // Set break point at this line. +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/Makefile new file mode 100644 index 00000000000..c825977b1a5 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/Makefile @@ -0,0 +1,6 @@ +CXX_SOURCES := main.cpp + +CFLAGS_EXTRAS := -O0 +USE_LIBSTDCPP := 1 + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/TestDataFormatterStdList.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/TestDataFormatterStdList.py new file mode 100644 index 00000000000..c65393f39bb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/TestDataFormatterStdList.py @@ -0,0 +1,206 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class StdListDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line numbers to break at for the different tests. + self.line = line_number('main.cpp', '// Set break point at this line.') + self.optional_line = line_number( + 'main.cpp', '// Optional break point at this line.') + self.final_line = line_number( + 'main.cpp', '// Set final break point at this line.') + + @add_test_categories(["libstdcxx"]) + def test_with_run_command(self): + """Test that that file and class static variables display correctly.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=-1) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + self.runCmd('type synth clear', check=False) + self.runCmd( + "settings set target.max-children-count 256", + check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.runCmd("frame variable numbers_list --show-types") + + self.runCmd("type format add -f hex int") + + self.expect("frame variable numbers_list --raw", matching=False, + substrs=['size=0', + '{}']) + self.expect( + "frame variable &numbers_list._M_impl._M_node --raw", + matching=False, + substrs=[ + 'size=0', + '{}']) + + self.expect("frame variable numbers_list", + substrs=['size=0', + '{}']) + + self.expect("p numbers_list", + substrs=['size=0', + '{}']) + + self.runCmd("n") + + self.expect("frame variable numbers_list", + substrs=['size=1', + '[0] = ', + '0x12345678']) + + self.runCmd("n") + self.runCmd("n") + self.runCmd("n") + + self.expect("frame variable numbers_list", + substrs=['size=4', + '[0] = ', + '0x12345678', + '[1] =', + '0x11223344', + '[2] =', + '0xbeeffeed', + '[3] =', + '0x00abba00']) + + self.runCmd("n") + self.runCmd("n") + + self.expect("frame variable numbers_list", + substrs=['size=6', + '[0] = ', + '0x12345678', + '0x11223344', + '0xbeeffeed', + '0x00abba00', + '[4] =', + '0x0abcdef0', + '[5] =', + '0x0cab0cab']) + + self.expect("p numbers_list", + substrs=['size=6', + '[0] = ', + '0x12345678', + '0x11223344', + '0xbeeffeed', + '0x00abba00', + '[4] =', + '0x0abcdef0', + '[5] =', + '0x0cab0cab']) + + # check access-by-index + self.expect("frame variable numbers_list[0]", + substrs=['0x12345678']) + self.expect("frame variable numbers_list[1]", + substrs=['0x11223344']) + + # but check that expression does not rely on us + self.expect("expression numbers_list[0]", matching=False, error=True, + substrs=['0x12345678']) + + # check that MightHaveChildren() gets it right + self.assertTrue( + self.frame().FindVariable("numbers_list").MightHaveChildren(), + "numbers_list.MightHaveChildren() says False for non empty!") + + self.runCmd("n") + + self.expect("frame variable numbers_list", + substrs=['size=0', + '{}']) + + self.runCmd("n") + self.runCmd("n") + self.runCmd("n") + self.runCmd("n") + + self.expect("frame variable numbers_list", + substrs=['size=4', + '[0] = ', '1', + '[1] = ', '2', + '[2] = ', '3', + '[3] = ', '4']) + + self.runCmd("type format delete int") + + self.runCmd("n") + + self.expect("frame variable text_list", + substrs=['size=0', + '{}']) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.final_line, num_expected_locations=-1) + + self.runCmd("c", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + self.expect("frame variable text_list", + substrs=['size=4', + '[0]', 'goofy', + '[1]', 'is', + '[2]', 'smart', + '[3]', '!!!']) + + self.expect("p text_list", + substrs=['size=4', + '\"goofy\"', + '\"is\"', + '\"smart\"', + '\"!!!\"']) + + # check access-by-index + self.expect("frame variable text_list[0]", + substrs=['goofy']) + self.expect("frame variable text_list[3]", + substrs=['!!!']) + + # but check that expression does not rely on us + self.expect("expression text_list[0]", matching=False, error=True, + substrs=['goofy']) + + # check that MightHaveChildren() gets it right + self.assertTrue( + self.frame().FindVariable("text_list").MightHaveChildren(), + "text_list.MightHaveChildren() says False for non empty!") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/main.cpp new file mode 100644 index 00000000000..191acdcc97b --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/main.cpp @@ -0,0 +1,34 @@ +#include <list> +#include <string> + +typedef std::list<int> int_list; +typedef std::list<std::string> string_list; + +int main() +{ + int_list numbers_list; + + numbers_list.push_back(0x12345678); // Set break point at this line. + numbers_list.push_back(0x11223344); + numbers_list.push_back(0xBEEFFEED); + numbers_list.push_back(0x00ABBA00); + numbers_list.push_back(0x0ABCDEF0); + numbers_list.push_back(0x0CAB0CAB); + + numbers_list.clear(); + + numbers_list.push_back(1); + numbers_list.push_back(2); + numbers_list.push_back(3); + numbers_list.push_back(4); + + string_list text_list; + text_list.push_back(std::string("goofy")); // Optional break point at this line. + text_list.push_back(std::string("is")); + text_list.push_back(std::string("smart")); + + text_list.push_back(std::string("!!!")); + + return 0; // Set final break point at this line. +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/Makefile new file mode 100644 index 00000000000..bf8e6b8703f --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/Makefile @@ -0,0 +1,5 @@ +CXX_SOURCES := main.cpp + +USE_LIBSTDCPP := 1 + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/TestDataFormatterStdMap.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/TestDataFormatterStdMap.py new file mode 100644 index 00000000000..94d1b573f40 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/TestDataFormatterStdMap.py @@ -0,0 +1,331 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class StdMapDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + @add_test_categories(["libstdcxx"]) + def test_with_run_command(self): + """Test that that file and class static variables display correctly.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_source_regexp( + self, "Set break point at this line.") + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + self.runCmd('type synth clear', check=False) + self.runCmd( + "settings set target.max-children-count 256", + check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.runCmd("frame variable ii --show-types") + + self.runCmd( + "type summary add -x \"std::map<\" --summary-string \"map has ${svar%#} items\" -e") + + self.expect('frame variable ii', + substrs=['map has 0 items', + '{}']) + + self.runCmd("c") + + self.expect('frame variable ii', + substrs=['map has 2 items', + '[0] = ', + 'first = 0', + 'second = 0', + '[1] = ', + 'first = 1', + 'second = 1']) + + self.runCmd("c") + + self.expect('frame variable ii', + substrs=['map has 4 items', + '[2] = ', + 'first = 2', + 'second = 0', + '[3] = ', + 'first = 3', + 'second = 1']) + + self.runCmd("c") + + self.expect("frame variable ii", + substrs=['map has 9 items', + '[5] = ', + 'first = 5', + 'second = 0', + '[7] = ', + 'first = 7', + 'second = 1']) + + self.expect("p ii", + substrs=['map has 9 items', + '[5] = ', + 'first = 5', + 'second = 0', + '[7] = ', + 'first = 7', + 'second = 1']) + + # check access-by-index + self.expect("frame variable ii[0]", + substrs=['first = 0', + 'second = 0']) + self.expect("frame variable ii[3]", + substrs=['first =', + 'second =']) + + self.expect("frame variable ii[8]", matching=True, + substrs=['1234567']) + + # check that MightHaveChildren() gets it right + self.assertTrue( + self.frame().FindVariable("ii").MightHaveChildren(), + "ii.MightHaveChildren() says False for non empty!") + + # check that the expression parser does not make use of + # synthetic children instead of running code + # TOT clang has a fix for this, which makes the expression command here succeed + # since this would make the test fail or succeed depending on clang version in use + # this is safer commented for the time being + # self.expect("expression ii[8]", matching=False, error=True, + # substrs = ['1234567']) + + self.runCmd("c") + + self.expect('frame variable ii', + substrs=['map has 0 items', + '{}']) + + self.runCmd("frame variable si --show-types") + + self.expect('frame variable si', + substrs=['map has 0 items', + '{}']) + + self.runCmd("c") + + self.expect('frame variable si', + substrs=['map has 1 items', + '[0] = ', + 'first = \"zero\"', + 'second = 0']) + + self.runCmd("c") + + self.expect("frame variable si", + substrs=['map has 5 items', + '[0] = ', + 'first = \"zero\"', + 'second = 0', + '[1] = ', + 'first = \"one\"', + 'second = 1', + '[2] = ', + 'first = \"two\"', + 'second = 2', + '[3] = ', + 'first = \"three\"', + 'second = 3', + '[4] = ', + 'first = \"four\"', + 'second = 4']) + + self.expect("p si", + substrs=['map has 5 items', + '[0] = ', + 'first = \"zero\"', + 'second = 0', + '[1] = ', + 'first = \"one\"', + 'second = 1', + '[2] = ', + 'first = \"two\"', + 'second = 2', + '[3] = ', + 'first = \"three\"', + 'second = 3', + '[4] = ', + 'first = \"four\"', + 'second = 4']) + + # check access-by-index + self.expect("frame variable si[0]", + substrs=['first = ', 'four', + 'second = 4']) + + # check that MightHaveChildren() gets it right + self.assertTrue( + self.frame().FindVariable("si").MightHaveChildren(), + "si.MightHaveChildren() says False for non empty!") + + # check that the expression parser does not make use of + # synthetic children instead of running code + # TOT clang has a fix for this, which makes the expression command here succeed + # since this would make the test fail or succeed depending on clang version in use + # this is safer commented for the time being + # self.expect("expression si[0]", matching=False, error=True, + # substrs = ['first = ', 'zero']) + + self.runCmd("c") + + self.expect('frame variable si', + substrs=['map has 0 items', + '{}']) + + self.runCmd("frame variable is --show-types") + + self.expect('frame variable is', + substrs=['map has 0 items', + '{}']) + + self.runCmd("c") + + self.expect("frame variable is", + substrs=['map has 4 items', + '[0] = ', + 'second = \"goofy\"', + 'first = 85', + '[1] = ', + 'second = \"is\"', + 'first = 1', + '[2] = ', + 'second = \"smart\"', + 'first = 2', + '[3] = ', + 'second = \"!!!\"', + 'first = 3']) + + self.expect("p is", + substrs=['map has 4 items', + '[0] = ', + 'second = \"goofy\"', + 'first = 85', + '[1] = ', + 'second = \"is\"', + 'first = 1', + '[2] = ', + 'second = \"smart\"', + 'first = 2', + '[3] = ', + 'second = \"!!!\"', + 'first = 3']) + + # check access-by-index + self.expect("frame variable is[0]", + substrs=['first = ', + 'second =']) + + # check that MightHaveChildren() gets it right + self.assertTrue( + self.frame().FindVariable("is").MightHaveChildren(), + "is.MightHaveChildren() says False for non empty!") + + # check that the expression parser does not make use of + # synthetic children instead of running code + # TOT clang has a fix for this, which makes the expression command here succeed + # since this would make the test fail or succeed depending on clang version in use + # this is safer commented for the time being + # self.expect("expression is[0]", matching=False, error=True, + # substrs = ['first = ', 'goofy']) + + self.runCmd("c") + + self.expect('frame variable is', + substrs=['map has 0 items', + '{}']) + + self.runCmd("frame variable ss --show-types") + + self.expect('frame variable ss', + substrs=['map has 0 items', + '{}']) + + self.runCmd("c") + + self.expect("frame variable ss", + substrs=['map has 4 items', + '[0] = ', + 'second = \"hello\"', + 'first = \"ciao\"', + '[1] = ', + 'second = \"house\"', + 'first = \"casa\"', + '[2] = ', + 'second = \"cat\"', + 'first = \"gatto\"', + '[3] = ', + 'second = \"..is always a Mac!\"', + 'first = \"a Mac..\"']) + + self.expect("p ss", + substrs=['map has 4 items', + '[0] = ', + 'second = \"hello\"', + 'first = \"ciao\"', + '[1] = ', + 'second = \"house\"', + 'first = \"casa\"', + '[2] = ', + 'second = \"cat\"', + 'first = \"gatto\"', + '[3] = ', + 'second = \"..is always a Mac!\"', + 'first = \"a Mac..\"']) + + # check access-by-index + self.expect("frame variable ss[3]", + substrs=['gatto', 'cat']) + + # check that MightHaveChildren() gets it right + self.assertTrue( + self.frame().FindVariable("ss").MightHaveChildren(), + "ss.MightHaveChildren() says False for non empty!") + + # check that the expression parser does not make use of + # synthetic children instead of running code + # TOT clang has a fix for this, which makes the expression command here succeed + # since this would make the test fail or succeed depending on clang version in use + # this is safer commented for the time being + # self.expect("expression ss[3]", matching=False, error=True, + # substrs = ['gatto']) + + self.runCmd("c") + + self.expect('frame variable ss', + substrs=['map has 0 items', + '{}']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/main.cpp new file mode 100644 index 00000000000..d5e5b212782 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/main.cpp @@ -0,0 +1,55 @@ +#include <map> +#include <string> + +#define intint_map std::map<int, int> +#define strint_map std::map<std::string, int> +#define intstr_map std::map<int, std::string> +#define strstr_map std::map<std::string, std::string> + + +int main() +{ + intint_map ii; + + ii[0] = 0; // Set break point at this line. + ii[1] = 1; + ii[2] = 0;// Set break point at this line. + ii[3] = 1; + ii[4] = 0;// Set break point at this line. + ii[5] = 1; + ii[6] = 0; + ii[7] = 1; + ii[85] = 1234567; + + ii.clear();// Set break point at this line. + + strint_map si; + + si["zero"] = 0;// Set break point at this line. + si["one"] = 1;// Set break point at this line. + si["two"] = 2; + si["three"] = 3; + si["four"] = 4; + + si.clear();// Set break point at this line. + + intstr_map is; + + is[85] = "goofy";// Set break point at this line. + is[1] = "is"; + is[2] = "smart"; + is[3] = "!!!"; + + is.clear();// Set break point at this line. + + strstr_map ss; + + ss["ciao"] = "hello";// Set break point at this line. + ss["casa"] = "house"; + ss["gatto"] = "cat"; + ss["a Mac.."] = "..is always a Mac!"; + + ss.clear();// Set break point at this line. + + return 0;// Set break point at this line. +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/Makefile new file mode 100644 index 00000000000..654e4b15bd5 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/Makefile @@ -0,0 +1,6 @@ +CXX_SOURCES := main.cpp + +CXXFLAGS := -O0 +USE_LIBSTDCPP := 1 + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/TestDataFormatterStdSmartPtr.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/TestDataFormatterStdSmartPtr.py new file mode 100644 index 00000000000..df213a03c72 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/TestDataFormatterStdSmartPtr.py @@ -0,0 +1,44 @@ +""" +Test lldb data formatter subsystem. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class StdSmartPtrDataFormatterTestCase(TestBase): + mydir = TestBase.compute_mydir(__file__) + + @add_test_categories(["libstdcxx"]) + def test_with_run_command(self): + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_source_regexp( + self, "Set break point at this line.") + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', 'stop reason = breakpoint']) + + self.expect("frame variable nsp", substrs=['nsp = nullptr']) + self.expect("frame variable isp", substrs=['isp = 123']) + self.expect("frame variable ssp", substrs=['ssp = "foobar"']) + + self.expect("frame variable nwp", substrs=['nwp = nullptr']) + self.expect("frame variable iwp", substrs=['iwp = 123']) + self.expect("frame variable swp", substrs=['swp = "foobar"']) + + self.runCmd("continue") + + self.expect("frame variable nsp", substrs=['nsp = nullptr']) + self.expect("frame variable isp", substrs=['isp = nullptr']) + self.expect("frame variable ssp", substrs=['ssp = nullptr']) + + self.expect("frame variable nwp", substrs=['nwp = nullptr']) + self.expect("frame variable iwp", substrs=['iwp = nullptr']) + self.expect("frame variable swp", substrs=['swp = nullptr']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/main.cpp new file mode 100644 index 00000000000..7ba50875a6d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/main.cpp @@ -0,0 +1,20 @@ +#include <memory> +#include <string> + +int +main() +{ + std::shared_ptr<char> nsp; + std::shared_ptr<int> isp(new int{123}); + std::shared_ptr<std::string> ssp = std::make_shared<std::string>("foobar"); + + std::weak_ptr<char> nwp; + std::weak_ptr<int> iwp = isp; + std::weak_ptr<std::string> swp = ssp; + + nsp.reset(); // Set break point at this line. + isp.reset(); + ssp.reset(); + + return 0; // Set break point at this line. +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/Makefile new file mode 100644 index 00000000000..c825977b1a5 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/Makefile @@ -0,0 +1,6 @@ +CXX_SOURCES := main.cpp + +CFLAGS_EXTRAS := -O0 +USE_LIBSTDCPP := 1 + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/TestDataFormatterStdString.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/TestDataFormatterStdString.py new file mode 100644 index 00000000000..fa0e4d12398 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/TestDataFormatterStdString.py @@ -0,0 +1,85 @@ +# coding=utf8 +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class StdStringDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + @add_test_categories(["libstdcxx"]) + def test_with_run_command(self): + """Test that that file and class static variables display correctly.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=-1) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + self.runCmd('type synth clear', check=False) + self.runCmd( + "settings set target.max-children-count 256", + check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + var_wempty = self.frame().FindVariable('wempty') + var_s = self.frame().FindVariable('s') + var_S = self.frame().FindVariable('S') + var_mazeltov = self.frame().FindVariable('mazeltov') + var_empty = self.frame().FindVariable('empty') + var_q = self.frame().FindVariable('q') + var_Q = self.frame().FindVariable('Q') + var_uchar = self.frame().FindVariable('uchar') + + # TODO: This is currently broken + # self.assertEqual(var_wempty.GetSummary(), 'L""', "wempty summary wrong") + self.assertEqual( + var_s.GetSummary(), 'L"hello world! מזל טוב!"', + "s summary wrong") + self.assertEqual(var_S.GetSummary(), 'L"!!!!"', "S summary wrong") + self.assertEqual( + var_mazeltov.GetSummary(), 'L"מזל טוב"', + "mazeltov summary wrong") + self.assertEqual(var_empty.GetSummary(), '""', "empty summary wrong") + self.assertEqual( + var_q.GetSummary(), '"hello world"', + "q summary wrong") + self.assertEqual( + var_Q.GetSummary(), '"quite a long std::strin with lots of info inside it"', + "Q summary wrong") + self.assertEqual(var_uchar.GetSummary(), '"aaaaa"', "u summary wrong") + + self.runCmd("next") + + self.assertEqual( + var_S.GetSummary(), 'L"!!!!!"', + "new S summary wrong") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/main.cpp new file mode 100644 index 00000000000..73519197d8c --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/main.cpp @@ -0,0 +1,15 @@ +#include <string> + +int main() +{ + std::wstring wempty(L""); + std::wstring s(L"hello world! מזל טוב!"); + std::wstring S(L"!!!!"); + const wchar_t *mazeltov = L"מזל טוב"; + std::string empty(""); + std::string q("hello world"); + std::string Q("quite a long std::strin with lots of info inside it"); + std::basic_string<unsigned char> uchar(5, 'a'); + S.assign(L"!!!!!"); // Set break point at this line. + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/tuple/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/tuple/Makefile new file mode 100644 index 00000000000..bf8e6b8703f --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/tuple/Makefile @@ -0,0 +1,5 @@ +CXX_SOURCES := main.cpp + +USE_LIBSTDCPP := 1 + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/tuple/TestDataFormatterStdTuple.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/tuple/TestDataFormatterStdTuple.py new file mode 100644 index 00000000000..c71cffe788a --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/tuple/TestDataFormatterStdTuple.py @@ -0,0 +1,44 @@ +""" +Test lldb data formatter subsystem. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class StdTupleDataFormatterTestCase(TestBase): + mydir = TestBase.compute_mydir(__file__) + + @add_test_categories(["libstdcxx"]) + def test_with_run_command(self): + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_source_regexp( + self, "Set break point at this line.") + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', 'stop reason = breakpoint']) + + frame = self.frame() + self.assertTrue(frame.IsValid()) + + self.expect("frame variable ti", substrs=['[0] = 1']) + self.expect("frame variable ts", substrs=['[0] = "foobar"']) + self.expect("frame variable tt", substrs=['[0] = 1', '[1] = "baz"', '[2] = 2']) + + self.assertEqual(1, frame.GetValueForVariablePath("ti[0]").GetValueAsUnsigned()) + self.assertFalse(frame.GetValueForVariablePath("ti[1]").IsValid()) + + self.assertEqual('"foobar"', frame.GetValueForVariablePath("ts[0]").GetSummary()) + self.assertFalse(frame.GetValueForVariablePath("ts[1]").IsValid()) + + self.assertEqual(1, frame.GetValueForVariablePath("tt[0]").GetValueAsUnsigned()) + self.assertEqual('"baz"', frame.GetValueForVariablePath("tt[1]").GetSummary()) + self.assertEqual(2, frame.GetValueForVariablePath("tt[2]").GetValueAsUnsigned()) + self.assertFalse(frame.GetValueForVariablePath("tt[3]").IsValid()) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/tuple/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/tuple/main.cpp new file mode 100644 index 00000000000..7247742ee6b --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/tuple/main.cpp @@ -0,0 +1,9 @@ +#include <memory> +#include <string> + +int main() { + std::tuple<int> ti{1}; + std::tuple<std::string> ts{"foobar"}; + std::tuple<int, std::string, int> tt{1, "baz", 2}; + return 0; // Set break point at this line. +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/Makefile new file mode 100644 index 00000000000..bf8e6b8703f --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/Makefile @@ -0,0 +1,5 @@ +CXX_SOURCES := main.cpp + +USE_LIBSTDCPP := 1 + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/TestDataFormatterStdUniquePtr.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/TestDataFormatterStdUniquePtr.py new file mode 100644 index 00000000000..2ead4fab559 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/TestDataFormatterStdUniquePtr.py @@ -0,0 +1,93 @@ +""" +Test lldb data formatter subsystem. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class StdUniquePtrDataFormatterTestCase(TestBase): + mydir = TestBase.compute_mydir(__file__) + + @add_test_categories(["libstdcxx"]) + def test_with_run_command(self): + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_source_regexp( + self, "Set break point at this line.") + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', 'stop reason = breakpoint']) + + frame = self.frame() + self.assertTrue(frame.IsValid()) + + self.expect("frame variable nup", substrs=['nup = nullptr']) + self.expect("frame variable iup", substrs=['iup = 0x']) + self.expect("frame variable sup", substrs=['sup = 0x']) + + self.expect("frame variable ndp", substrs=['ndp = nullptr']) + self.expect("frame variable idp", substrs=['idp = 0x', 'deleter = ', 'a = 1', 'b = 2']) + self.expect("frame variable sdp", substrs=['sdp = 0x', 'deleter = ', 'a = 3', 'b = 4']) + + self.assertEqual(123, frame.GetValueForVariablePath("iup.object").GetValueAsUnsigned()) + self.assertEqual(123, frame.GetValueForVariablePath("*iup").GetValueAsUnsigned()) + self.assertFalse(frame.GetValueForVariablePath("iup.deleter").IsValid()) + + self.assertEqual('"foobar"', frame.GetValueForVariablePath("sup.object").GetSummary()) + self.assertEqual('"foobar"', frame.GetValueForVariablePath("*sup").GetSummary()) + self.assertFalse(frame.GetValueForVariablePath("sup.deleter").IsValid()) + + self.assertEqual(456, frame.GetValueForVariablePath("idp.object").GetValueAsUnsigned()) + self.assertEqual(456, frame.GetValueForVariablePath("*idp").GetValueAsUnsigned()) + self.assertEqual('"baz"', frame.GetValueForVariablePath("sdp.object").GetSummary()) + self.assertEqual('"baz"', frame.GetValueForVariablePath("*sdp").GetSummary()) + + idp_deleter = frame.GetValueForVariablePath("idp.deleter") + self.assertTrue(idp_deleter.IsValid()) + self.assertEqual(1, idp_deleter.GetChildMemberWithName("a").GetValueAsUnsigned()) + self.assertEqual(2, idp_deleter.GetChildMemberWithName("b").GetValueAsUnsigned()) + + sdp_deleter = frame.GetValueForVariablePath("sdp.deleter") + self.assertTrue(sdp_deleter.IsValid()) + self.assertEqual(3, sdp_deleter.GetChildMemberWithName("a").GetValueAsUnsigned()) + self.assertEqual(4, sdp_deleter.GetChildMemberWithName("b").GetValueAsUnsigned()) + + @skipIfFreeBSD + @skipIfWindows # libstdcpp not ported to Windows + @skipIfDarwin # doesn't compile on Darwin + @skipIfwatchOS # libstdcpp not ported to watchos + @add_test_categories(["libstdcxx"]) + def test_recursive_unique_ptr(self): + # Tests that LLDB can handle when we have a loop in the unique_ptr + # reference chain and that it correctly handles the different options + # for the frame variable command in this case. + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_source_regexp( + self, "Set break point at this line.") + self.runCmd("run", RUN_SUCCEEDED) + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', 'stop reason = breakpoint']) + + self.expect("frame variable f1->fp", + substrs=['fp = 0x']) + self.expect("frame variable --ptr-depth=1 f1->fp", + substrs=['data = 2', 'fp = 0x']) + self.expect("frame variable --ptr-depth=2 f1->fp", + substrs=['data = 2', 'fp = 0x', 'data = 1']) + + frame = self.frame() + self.assertTrue(frame.IsValid()) + self.assertEqual(2, frame.GetValueForVariablePath("f1->fp.object.data").GetValueAsUnsigned()) + self.assertEqual(2, frame.GetValueForVariablePath("f1->fp->data").GetValueAsUnsigned()) + self.assertEqual(1, frame.GetValueForVariablePath("f1->fp.object.fp.object.data").GetValueAsUnsigned()) + self.assertEqual(1, frame.GetValueForVariablePath("f1->fp->fp->data").GetValueAsUnsigned()) + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/invalid/TestDataFormatterInvalidStdUniquePtr.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/invalid/TestDataFormatterInvalidStdUniquePtr.py new file mode 100644 index 00000000000..190cf78a3b4 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/invalid/TestDataFormatterInvalidStdUniquePtr.py @@ -0,0 +1,5 @@ +import lldbsuite.test.lldbinline as lldbinline +from lldbsuite.test.decorators import * + +lldbinline.MakeInlineTest(__file__, globals(), [no_debug_info_test]) + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/invalid/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/invalid/main.cpp new file mode 100644 index 00000000000..b12cab23169 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/invalid/main.cpp @@ -0,0 +1,11 @@ +// Test that we don't crash when trying to pretty-print structures that don't +// have the layout our data formatters expect. +namespace std { +template<typename T, typename Deleter = void> +class unique_ptr {}; +} + +int main() { + std::unique_ptr<int> U; + return 0; //% self.expect("frame variable U", substrs=["unique_ptr", "{}"]) +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/main.cpp new file mode 100644 index 00000000000..dd0072764d4 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/main.cpp @@ -0,0 +1,35 @@ +#include <memory> +#include <string> + +struct Deleter { + void operator()(void *) {} + + int a; + int b; +}; + +struct Foo { + int data; + std::unique_ptr<Foo> fp; +}; + +int main() { + std::unique_ptr<char> nup; + std::unique_ptr<int> iup(new int{123}); + std::unique_ptr<std::string> sup(new std::string("foobar")); + + std::unique_ptr<char, Deleter> ndp; + std::unique_ptr<int, Deleter> idp(new int{456}, Deleter{1, 2}); + std::unique_ptr<std::string, Deleter> sdp(new std::string("baz"), + Deleter{3, 4}); + + std::unique_ptr<Foo> fp(new Foo{3}); + + // Set up a structure where we have a loop in the unique_ptr chain. + Foo* f1 = new Foo{1}; + Foo* f2 = new Foo{2}; + f1->fp.reset(f2); + f2->fp.reset(f1); + + return 0; // Set break point at this line. +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/Makefile new file mode 100644 index 00000000000..c825977b1a5 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/Makefile @@ -0,0 +1,6 @@ +CXX_SOURCES := main.cpp + +CFLAGS_EXTRAS := -O0 +USE_LIBSTDCPP := 1 + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/TestDataFormatterStdVBool.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/TestDataFormatterStdVBool.py new file mode 100644 index 00000000000..5a767b34c23 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/TestDataFormatterStdVBool.py @@ -0,0 +1,75 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class StdVBoolDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + @add_test_categories(["libstdcxx"]) + def test_with_run_command(self): + """Test that that file and class static variables display correctly.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=-1) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + self.runCmd('type synth clear', check=False) + self.runCmd( + "settings set target.max-children-count 256", + check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.expect( + "frame variable vBool", + substrs=[ + 'size=49', + '[0] = false', + '[1] = true', + '[18] = false', + '[27] = true', + '[36] = false', + '[47] = true', + '[48] = true']) + + self.expect( + "expr vBool", + substrs=[ + 'size=49', + '[0] = false', + '[1] = true', + '[18] = false', + '[27] = true', + '[36] = false', + '[47] = true', + '[48] = true']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/main.cpp new file mode 100644 index 00000000000..73956dd3fda --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/main.cpp @@ -0,0 +1,63 @@ +#include <vector> + +int main() +{ + std::vector<bool> vBool; + + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(false); + vBool.push_back(true); + vBool.push_back(true); + + return 0; // Set break point at this line. +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/Makefile new file mode 100644 index 00000000000..654e4b15bd5 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/Makefile @@ -0,0 +1,6 @@ +CXX_SOURCES := main.cpp + +CXXFLAGS := -O0 +USE_LIBSTDCPP := 1 + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/TestDataFormatterStdVector.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/TestDataFormatterStdVector.py new file mode 100644 index 00000000000..27cdf1e73ac --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/TestDataFormatterStdVector.py @@ -0,0 +1,213 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class StdVectorDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + @add_test_categories(["libstdcxx"]) + def test_with_run_command(self): + """Test that that file and class static variables display correctly.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_source_regexp( + self, "Set break point at this line.") + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + self.runCmd('type synth clear', check=False) + self.runCmd( + "settings set target.max-children-count 256", + check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + # empty vectors (and storage pointers SHOULD BOTH BE NULL..) + self.expect("frame variable numbers", + substrs=['numbers = size=0']) + + self.runCmd("c") + + # first value added + self.expect("frame variable numbers", + substrs=['numbers = size=1', + '[0] = 1', + '}']) + + # add some more data + self.runCmd("c") + + self.expect("frame variable numbers", + substrs=['numbers = size=4', + '[0] = 1', + '[1] = 12', + '[2] = 123', + '[3] = 1234', + '}']) + + self.expect("p numbers", + substrs=['$', 'size=4', + '[0] = 1', + '[1] = 12', + '[2] = 123', + '[3] = 1234', + '}']) + + # check access to synthetic children + self.runCmd( + "type summary add --summary-string \"item 0 is ${var[0]}\" std::int_vect int_vect") + self.expect('frame variable numbers', + substrs=['item 0 is 1']) + + self.runCmd( + "type summary add --summary-string \"item 0 is ${svar[0]}\" std::int_vect int_vect") + #import time + # time.sleep(19) + self.expect('frame variable numbers', + substrs=['item 0 is 1']) + # move on with synths + self.runCmd("type summary delete std::int_vect") + self.runCmd("type summary delete int_vect") + + # add some more data + self.runCmd("c") + + self.expect("frame variable numbers", + substrs=['numbers = size=7', + '[0] = 1', + '[1] = 12', + '[2] = 123', + '[3] = 1234', + '[4] = 12345', + '[5] = 123456', + '[6] = 1234567', + '}']) + + self.expect("p numbers", + substrs=['$', 'size=7', + '[0] = 1', + '[1] = 12', + '[2] = 123', + '[3] = 1234', + '[4] = 12345', + '[5] = 123456', + '[6] = 1234567', + '}']) + + # check access-by-index + self.expect("frame variable numbers[0]", + substrs=['1']) + self.expect("frame variable numbers[1]", + substrs=['12']) + self.expect("frame variable numbers[2]", + substrs=['123']) + self.expect("frame variable numbers[3]", + substrs=['1234']) + + # but check that expression does not rely on us + # (when expression gets to call into STL code correctly, we will have to find + # another way to check this) + self.expect("expression numbers[6]", matching=False, error=True, + substrs=['1234567']) + + # check that MightHaveChildren() gets it right + self.assertTrue( + self.frame().FindVariable("numbers").MightHaveChildren(), + "numbers.MightHaveChildren() says False for non empty!") + + # clear out the vector and see that we do the right thing once again + self.runCmd("c") + + self.expect("frame variable numbers", + substrs=['numbers = size=0']) + + self.runCmd("c") + + # first value added + self.expect("frame variable numbers", + substrs=['numbers = size=1', + '[0] = 7', + '}']) + + # check if we can display strings + self.runCmd("c") + + self.expect("frame variable strings", + substrs=['goofy', + 'is', + 'smart']) + + self.expect("p strings", + substrs=['goofy', + 'is', + 'smart']) + + # test summaries based on synthetic children + self.runCmd( + "type summary add std::string_vect string_vect --summary-string \"vector has ${svar%#} items\" -e") + self.expect("frame variable strings", + substrs=['vector has 3 items', + 'goofy', + 'is', + 'smart']) + + self.expect("p strings", + substrs=['vector has 3 items', + 'goofy', + 'is', + 'smart']) + + self.runCmd("c") + + self.expect("frame variable strings", + substrs=['vector has 4 items']) + + # check access-by-index + self.expect("frame variable strings[0]", + substrs=['goofy']) + self.expect("frame variable strings[1]", + substrs=['is']) + + # but check that expression does not rely on us + # (when expression gets to call into STL code correctly, we will have to find + # another way to check this) + self.expect("expression strings[0]", matching=False, error=True, + substrs=['goofy']) + + # check that MightHaveChildren() gets it right + self.assertTrue( + self.frame().FindVariable("strings").MightHaveChildren(), + "strings.MightHaveChildren() says False for non empty!") + + self.runCmd("c") + + self.expect("frame variable strings", + substrs=['vector has 0 items']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/main.cpp new file mode 100644 index 00000000000..010917995e4 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/main.cpp @@ -0,0 +1,31 @@ +#include <string> +#include <vector> +typedef std::vector<int> int_vect; +typedef std::vector<std::string> string_vect; + +int main() +{ + int_vect numbers; + numbers.push_back(1); // Set break point at this line. + numbers.push_back(12); // Set break point at this line. + numbers.push_back(123); + numbers.push_back(1234); + numbers.push_back(12345); // Set break point at this line. + numbers.push_back(123456); + numbers.push_back(1234567); + + numbers.clear(); // Set break point at this line. + + numbers.push_back(7); // Set break point at this line. + + string_vect strings; // Set break point at this line. + strings.push_back(std::string("goofy")); + strings.push_back(std::string("is")); + strings.push_back(std::string("smart")); + + strings.push_back(std::string("!!!")); // Set break point at this line. + + strings.clear(); // Set break point at this line. + + return 0;// Set break point at this line. +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synth/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synth/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synth/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synth/TestDataFormatterSynth.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synth/TestDataFormatterSynth.py new file mode 100644 index 00000000000..51d42fc5e7b --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synth/TestDataFormatterSynth.py @@ -0,0 +1,217 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class SynthDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + def test_with_run_command(self): + """Test that that file and class static variables display correctly.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + # Pick some values and check that the basics work + self.runCmd("type filter add BagOfInts --child x --child z") + self.expect("frame variable int_bag", + substrs=['x = 6', + 'z = 8']) + + # Check we can still access the missing child by summary + self.runCmd( + "type summary add BagOfInts --summary-string \"y=${var.y}\"") + self.expect('frame variable int_bag', + substrs=['y=7']) + + # Even if we have synth children, the summary prevails + self.expect("frame variable int_bag", matching=False, + substrs=['x = 6', + 'z = 8']) + + # if we skip synth and summary show y + self.expect( + "frame variable int_bag --synthetic-type false --no-summary-depth=1", + substrs=[ + 'x = 6', + 'y = 7', + 'z = 8']) + + # if we ask for raw output same happens + self.expect("frame variable int_bag --raw-output", + substrs=['x = 6', + 'y = 7', + 'z = 8']) + + # Summary+Synth must work together + self.runCmd( + "type summary add BagOfInts --summary-string \"x=${var.x}\" -e") + self.expect('frame variable int_bag', + substrs=['x=6', + 'x = 6', + 'z = 8']) + + # Same output, but using Python + self.runCmd( + "type summary add BagOfInts --python-script \"return 'x=%s' % valobj.GetChildMemberWithName('x').GetValue()\" -e") + self.expect('frame variable int_bag', + substrs=['x=6', + 'x = 6', + 'z = 8']) + + # If I skip summaries, still give me the artificial children + self.expect("frame variable int_bag --no-summary-depth=1", + substrs=['x = 6', + 'z = 8']) + + # Delete synth and check that the view reflects it immediately + self.runCmd("type filter delete BagOfInts") + self.expect("frame variable int_bag", + substrs=['x = 6', + 'y = 7', + 'z = 8']) + + # Add the synth again and check that it's honored deeper in the + # hierarchy + self.runCmd("type filter add BagOfInts --child x --child z") + self.expect('frame variable bag_bag', + substrs=['x = x=69 {', + 'x = 69', + 'z = 71', + 'y = x=66 {', + 'x = 66', + 'z = 68']) + self.expect('frame variable bag_bag', matching=False, + substrs=['y = 70', + 'y = 67']) + + # Check that a synth can expand nested stuff + self.runCmd("type filter add BagOfBags --child x.y --child y.z") + self.expect('frame variable bag_bag', + substrs=['x.y = 70', + 'y.z = 68']) + + # ...even if we get -> and . wrong + self.runCmd("type filter add BagOfBags --child x.y --child \"y->z\"") + self.expect('frame variable bag_bag', + substrs=['x.y = 70', + 'y->z = 68']) + + # ...even bitfields + self.runCmd( + "type filter add BagOfBags --child x.y --child \"y->z[1-2]\"") + self.expect('frame variable bag_bag --show-types', + substrs=['x.y = 70', + '(int:2) y->z[1-2] = 2']) + + # ...even if we format the bitfields + self.runCmd( + "type filter add BagOfBags --child x.y --child \"y->y[0-0]\"") + self.runCmd("type format add \"int:1\" -f bool") + self.expect('frame variable bag_bag --show-types', + substrs=['x.y = 70', + '(int:1) y->y[0-0] = true']) + + # ...even if we use one-liner summaries + self.runCmd("type summary add -c BagOfBags") + self.expect('frame variable bag_bag', substrs=[ + '(BagOfBags) bag_bag = (x.y = 70, y->y[0-0] = true)']) + + self.runCmd("type summary delete BagOfBags") + + # now check we are dynamic (and arrays work) + self.runCmd( + "type filter add Plenty --child bitfield --child array[0] --child array[2]") + self.expect('frame variable plenty_of_stuff', + substrs=['bitfield = 1', + 'array[0] = 5', + 'array[2] = 3']) + + self.runCmd("n") + self.expect('frame variable plenty_of_stuff', + substrs=['bitfield = 17', + 'array[0] = 5', + 'array[2] = 3']) + + # skip synthetic children + self.expect('frame variable plenty_of_stuff --synthetic-type no', + substrs=['some_values = 0x', + 'array = 0x', + 'array_size = 5']) + + # check flat printing with synthetic children + self.expect('frame variable plenty_of_stuff --flat', + substrs=['plenty_of_stuff.bitfield = 17', + '*(plenty_of_stuff.array) = 5', + '*(plenty_of_stuff.array) = 3']) + + # check that we do not lose location information for our children + self.expect('frame variable plenty_of_stuff --location', + substrs=['0x', + ': bitfield = 17']) + + # check we work across pointer boundaries + self.expect('frame variable plenty_of_stuff.some_values --ptr-depth=1', + substrs=['(BagOfInts *) plenty_of_stuff.some_values', + 'x = 5', + 'z = 7']) + + # but not if we don't want to + self.runCmd("type filter add BagOfInts --child x --child z -p") + self.expect('frame variable plenty_of_stuff.some_values --ptr-depth=1', + substrs=['(BagOfInts *) plenty_of_stuff.some_values', + 'x = 5', + 'y = 6', + 'z = 7']) + + # check we're dynamic even if nested + self.runCmd("type filter add BagOfBags --child x.z") + self.expect('frame variable bag_bag', + substrs=['x.z = 71']) + + self.runCmd("n") + self.expect('frame variable bag_bag', + substrs=['x.z = 12']) + + self.runCmd( + 'type summary add -e -s "I am always empty but have" EmptyStruct') + self.expect('frame variable es', substrs=[ + "I am always empty but have {}"]) + self.runCmd('type summary add -e -h -s "I am really empty" EmptyStruct') + self.expect('frame variable es', substrs=["I am really empty"]) + self.expect( + 'frame variable es', + substrs=["I am really empty {}"], + matching=False) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synth/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synth/main.cpp new file mode 100644 index 00000000000..acb90323b6c --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synth/main.cpp @@ -0,0 +1,85 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> + +struct BagOfInts +{ + int x; + int y; + int z; + BagOfInts(int X) : + x(X), + y(X+1), + z(X+2) {} +}; + +struct BagOfFloats +{ + float x; + float y; + float z; + BagOfFloats(float X) : + x(X+0.334), + y(X+0.500), + z(X+0.667) {} +}; + +struct BagOfBags +{ + BagOfInts x; + BagOfInts y; + BagOfFloats z; + BagOfFloats q; + BagOfBags() : + x('E'), + y('B'), + z(1.1), + q(20.11) {} +}; + +struct EmptyStruct {}; + +struct Plenty +{ + BagOfInts *some_values; + int* array; + int array_size; + int bitfield; + + Plenty(int N, bool flagA, bool flagB) : + some_values(new BagOfInts(N)), + array(new int[N]), + array_size(N), + bitfield( (flagA ? 0x01 : 0x00) | (flagB ? 0x10 : 0x00) ) + { + for (int j = 0; j < N; j++) + array[j] = N-j; + } +}; + +int main (int argc, const char * argv[]) +{ + BagOfInts int_bag(6); + BagOfFloats float_bag(2.71); + + BagOfBags bag_bag; + EmptyStruct es; + + Plenty plenty_of_stuff(5,true,false); + + plenty_of_stuff.bitfield = 0x11; // Set break point at this line. + + bag_bag.x.z = 12; + + return 0; + +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthtype/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthtype/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthtype/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthtype/TestDataFormatterSynthType.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthtype/TestDataFormatterSynthType.py new file mode 100644 index 00000000000..2c7d5b2d0e1 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthtype/TestDataFormatterSynthType.py @@ -0,0 +1,55 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class DataFormatterSynthTypeTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', 'break here') + + @skipIfFreeBSD # llvm.org/pr20545 bogus output confuses buildbot parser + def test_with_run_command(self): + """Test using Python synthetic children provider to provide a typename.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + self.runCmd('type synth clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.runCmd("script from myIntSynthProvider import *") + self.runCmd("type synth add -l myIntSynthProvider myInt") + + self.expect('frame variable x', substrs=['ThisTestPasses']) + self.expect('frame variable y', substrs=['ThisTestPasses']) + self.expect('frame variable z', substrs=['ThisTestPasses']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthtype/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthtype/main.cpp new file mode 100644 index 00000000000..accbf0a5a57 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthtype/main.cpp @@ -0,0 +1,29 @@ +class myInt { + private: int theValue; + public: myInt() : theValue(0) {} + public: myInt(int _x) : theValue(_x) {} + int val() { return theValue; } +}; + +class myArray { +public: + int array[16]; +}; + +class hasAnInt { + public: + myInt theInt; + hasAnInt() : theInt(42) {} +}; + +myInt operator + (myInt x, myInt y) { return myInt(x.val() + y.val()); } + +int main() { + myInt x{3}; + myInt y{4}; + myInt z {x+y}; + hasAnInt hi; + myArray ma; + + return z.val(); // break here +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthtype/myIntSynthProvider.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthtype/myIntSynthProvider.py new file mode 100644 index 00000000000..fa47ca2cfe6 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthtype/myIntSynthProvider.py @@ -0,0 +1,44 @@ +class myIntSynthProvider(object): + + def __init__(self, valobj, dict): + self.valobj = valobj + self.val = self.valobj.GetChildMemberWithName("theValue") + + def num_children(self): + return 0 + + def get_child_at_index(self, index): + return None + + def get_child_index(self, name): + return None + + def update(self): + return False + + def has_children(self): + return False + + def get_type_name(self): + return "ThisTestPasses" + + +class myArraySynthProvider(object): + + def __init__(self, valobj, dict): + self.valobj = valobj + self.array = self.valobj.GetChildMemberWithName("array") + + def num_children(self, max_count): + if 16 < max_count: + return 16 + return max_count + + def get_child_at_index(self, index): + return None # Keep it simple when this is not tested here. + + def get_child_index(self, name): + return None # Keep it simple when this is not tested here. + + def has_children(self): + return True diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthval/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthval/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthval/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py new file mode 100644 index 00000000000..fc7ffa0e78f --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py @@ -0,0 +1,117 @@ +""" +Test lldb data formatter subsystem. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class DataFormatterSynthValueTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', 'break here') + + @skipIfFreeBSD # llvm.org/pr20545 bogus output confuses buildbot parser + def test_with_run_command(self): + """Test using Python synthetic children provider to provide a value.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + self.runCmd('type synth clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + x = self.frame().FindVariable("x") + x.SetPreferSyntheticValue(True) + y = self.frame().FindVariable("y") + y.SetPreferSyntheticValue(True) + z = self.frame().FindVariable("z") + z.SetPreferSyntheticValue(True) + q = self.frame().FindVariable("q") + z.SetPreferSyntheticValue(True) + + x_val = x.GetValueAsUnsigned + y_val = y.GetValueAsUnsigned + z_val = z.GetValueAsUnsigned + q_val = q.GetValueAsUnsigned + + if self.TraceOn(): + print( + "x_val = %s; y_val = %s; z_val = %s; q_val = %s" % + (x_val(), y_val(), z_val(), q_val())) + + self.assertFalse(x_val() == 3, "x == 3 before synthetics") + self.assertFalse(y_val() == 4, "y == 4 before synthetics") + self.assertFalse(z_val() == 7, "z == 7 before synthetics") + self.assertFalse(q_val() == 8, "q == 8 before synthetics") + + # now set up the synth + self.runCmd("script from myIntSynthProvider import *") + self.runCmd("type synth add -l myIntSynthProvider myInt") + self.runCmd("type synth add -l myArraySynthProvider myArray") + self.runCmd("type synth add -l myIntSynthProvider myIntAndStuff") + + if self.TraceOn(): + print( + "x_val = %s; y_val = %s; z_val = %s; q_val = %s" % + (x_val(), y_val(), z_val(), q_val())) + + self.assertTrue(x_val() == 3, "x != 3 after synthetics") + self.assertTrue(y_val() == 4, "y != 4 after synthetics") + self.assertTrue(z_val() == 7, "z != 7 after synthetics") + self.assertTrue(q_val() == 8, "q != 8 after synthetics") + + self.expect("frame variable x", substrs=['3']) + self.expect( + "frame variable x", + substrs=['theValue = 3'], + matching=False) + self.expect("frame variable q", substrs=['8']) + self.expect( + "frame variable q", + substrs=['theValue = 8'], + matching=False) + + # check that an aptly defined synthetic provider does not affect + # one-lining + self.expect( + "expression struct Struct { myInt theInt{12}; }; Struct()", + substrs=['(theInt = 12)']) + + # check that we can use a synthetic value in a summary + self.runCmd("type summary add hasAnInt -s ${var.theInt}") + hi = self.frame().FindVariable("hi") + self.assertEqual(hi.GetSummary(), "42") + + ma = self.frame().FindVariable("ma") + self.assertTrue(ma.IsValid()) + self.assertEqual(ma.GetNumChildren(15), 15) + self.assertEqual(ma.GetNumChildren(16), 16) + self.assertEqual(ma.GetNumChildren(17), 16) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthval/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthval/main.cpp new file mode 100644 index 00000000000..1a5925a05a6 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthval/main.cpp @@ -0,0 +1,41 @@ +class myInt { + private: int theValue; + public: myInt() : theValue(0) {} + public: myInt(int _x) : theValue(_x) {} + int val() { return theValue; } +}; + +class myIntAndStuff { +private: + int theValue; + double theExtraFluff; +public: + myIntAndStuff() : theValue(0), theExtraFluff(1.25) {} + myIntAndStuff(int _x) : theValue(_x), theExtraFluff(1.25) {} + int val() { return theValue; } +}; + +class myArray { +public: + int array[16]; +}; + +class hasAnInt { + public: + myInt theInt; + hasAnInt() : theInt(42) {} +}; + +myInt operator + (myInt x, myInt y) { return myInt(x.val() + y.val()); } +myInt operator + (myInt x, myIntAndStuff y) { return myInt(x.val() + y.val()); } + +int main() { + myInt x{3}; + myInt y{4}; + myInt z {x+y}; + myIntAndStuff q {z.val()+1}; + hasAnInt hi; + myArray ma; + + return z.val(); // break here +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthval/myIntSynthProvider.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthval/myIntSynthProvider.py new file mode 100644 index 00000000000..82da6f9da92 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthval/myIntSynthProvider.py @@ -0,0 +1,44 @@ +class myIntSynthProvider(object): + + def __init__(self, valobj, dict): + self.valobj = valobj + self.val = self.valobj.GetChildMemberWithName("theValue") + + def num_children(self): + return 0 + + def get_child_at_index(self, index): + return None + + def get_child_index(self, name): + return None + + def update(self): + return False + + def has_children(self): + return False + + def get_value(self): + return self.val + + +class myArraySynthProvider(object): + + def __init__(self, valobj, dict): + self.valobj = valobj + self.array = self.valobj.GetChildMemberWithName("array") + + def num_children(self, max_count): + if 16 < max_count: + return 16 + return max_count + + def get_child_at_index(self, index): + return None # Keep it simple when this is not tested here. + + def get_child_index(self, name): + return None # Keep it simple when this is not tested here. + + def has_children(self): + return True diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/dump_dynamic/TestDumpDynamic.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/dump_dynamic/TestDumpDynamic.py new file mode 100644 index 00000000000..734e711fb7f --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/dump_dynamic/TestDumpDynamic.py @@ -0,0 +1,8 @@ +from __future__ import absolute_import + +from lldbsuite.test import lldbinline + +lldbinline.MakeInlineTest( + __file__, globals(), [ + lldbinline.expectedFailureAll( + oslist=["windows"], bugnumber="llvm.org/pr24663")]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/dump_dynamic/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/dump_dynamic/main.cpp new file mode 100644 index 00000000000..c59e9f0ee72 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/dump_dynamic/main.cpp @@ -0,0 +1,34 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +class Base { +public: + Base () = default; + virtual int func() { return 1; } + virtual ~Base() = default; +}; + +class Derived : public Base { +private: + int m_derived_data; +public: + Derived () : Base(), m_derived_data(0x0fedbeef) {} + virtual ~Derived() = default; + virtual int func() { return m_derived_data; } +}; + +int main (int argc, char const *argv[]) +{ + Base *base = new Derived(); + return 0; //% stream = lldb.SBStream() + //% base = self.frame().FindVariable("base") + //% base.SetPreferDynamicValue(lldb.eDynamicDontRunTarget) + //% base.GetDescription(stream) + //% if self.TraceOn(): print(stream.GetData()) + //% self.assertTrue(stream.GetData().startswith("(Derived *")) +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/format-propagation/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/format-propagation/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/format-propagation/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/format-propagation/TestFormatPropagation.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/format-propagation/TestFormatPropagation.py new file mode 100644 index 00000000000..8994831216b --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/format-propagation/TestFormatPropagation.py @@ -0,0 +1,82 @@ +""" +Check if changing Format on an SBValue correctly propagates that new format to children as it should +""" + + + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class FormatPropagationTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + # rdar://problem/14035604 + def test_with_run_command(self): + """Check for an issue where capping does not work because the Target pointer appears to be changing behind our backs.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + pass + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + # extract the parent and the children + frame = self.frame() + parent = self.frame().FindVariable("f") + self.assertTrue( + parent is not None and parent.IsValid(), + "could not find f") + X = parent.GetChildMemberWithName("X") + self.assertTrue(X is not None and X.IsValid(), "could not find X") + Y = parent.GetChildMemberWithName("Y") + self.assertTrue(Y is not None and Y.IsValid(), "could not find Y") + # check their values now + self.assertTrue(X.GetValue() == "1", "X has an invalid value") + self.assertTrue(Y.GetValue() == "2", "Y has an invalid value") + # set the format on the parent + parent.SetFormat(lldb.eFormatHex) + self.assertTrue( + X.GetValue() == "0x00000001", + "X has not changed format") + self.assertTrue( + Y.GetValue() == "0x00000002", + "Y has not changed format") + # Step and check if the values make sense still + self.runCmd("next") + self.assertTrue(X.GetValue() == "0x00000004", "X has not become 4") + self.assertTrue(Y.GetValue() == "0x00000002", "Y has not stuck as hex") + # Check that children can still make their own choices + Y.SetFormat(lldb.eFormatDecimal) + self.assertTrue(X.GetValue() == "0x00000004", "X is still hex") + self.assertTrue(Y.GetValue() == "2", "Y has not been reset") + # Make a few more changes + parent.SetFormat(lldb.eFormatDefault) + X.SetFormat(lldb.eFormatHex) + Y.SetFormat(lldb.eFormatDefault) + self.assertTrue( + X.GetValue() == "0x00000004", + "X is not hex as it asked") + self.assertTrue(Y.GetValue() == "2", "Y is not defaulted") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/format-propagation/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/format-propagation/main.cpp new file mode 100644 index 00000000000..5822fbc2a71 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/format-propagation/main.cpp @@ -0,0 +1,13 @@ +struct foo +{ + int X; + int Y; + foo(int a, int b) : X(a), Y(b) {} +}; + +int main() +{ + foo f(1,2); + f.X = 4; // Set break point at this line. + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/frameformat_smallstruct/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/frameformat_smallstruct/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/frameformat_smallstruct/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/frameformat_smallstruct/TestFrameFormatSmallStruct.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/frameformat_smallstruct/TestFrameFormatSmallStruct.py new file mode 100644 index 00000000000..a6a61f1d7bd --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/frameformat_smallstruct/TestFrameFormatSmallStruct.py @@ -0,0 +1,37 @@ +""" +Test that the user can input a format but it will not prevail over summary format's choices. +""" + + + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class FrameFormatSmallStructTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + def test_with_run_command(self): + """Test that the user can input a format but it will not prevail over summary format's choices.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + self.expect("thread list", substrs=['addPair(p=(x = 3, y = -3))']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/frameformat_smallstruct/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/frameformat_smallstruct/main.cpp new file mode 100644 index 00000000000..a77f2c42e8d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/frameformat_smallstruct/main.cpp @@ -0,0 +1,24 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +struct Pair { + int x; + int y; + + Pair(int _x, int _y) : x(_x), y(_y) {} +}; + +int addPair(Pair p) +{ + return p.x + p.y; // Set break point at this line. +} + +int main() { + Pair p1(3,-3); + return addPair(p1); +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/hexcaps/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/hexcaps/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/hexcaps/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/hexcaps/TestDataFormatterHexCaps.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/hexcaps/TestDataFormatterHexCaps.py new file mode 100644 index 00000000000..80a02d06cfe --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/hexcaps/TestDataFormatterHexCaps.py @@ -0,0 +1,86 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class DataFormatterHexCapsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + def test_with_run_command(self): + """Test that that file and class static variables display correctly.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format delete hex', check=False) + self.runCmd('type summary clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.runCmd("type format add -f uppercase int") + + self.expect('frame variable mine', + substrs=['mine = ', + 'first = 0x001122AA', 'second = 0x1122BB44']) + + self.runCmd("type format add -f hex int") + + self.expect('frame variable mine', + substrs=['mine = ', + 'first = 0x001122aa', 'second = 0x1122bb44']) + + self.runCmd("type format delete int") + + self.runCmd( + "type summary add -s \"${var.first%X} and ${var.second%x}\" foo") + + self.expect('frame variable mine', + substrs=['(foo) mine = 0x001122AA and 0x1122bb44']) + + self.runCmd( + "type summary add -s \"${var.first%X} and ${var.second%X}\" foo") + self.runCmd("next") + self.runCmd("next") + self.expect('frame variable mine', + substrs=['(foo) mine = 0xAABBCCDD and 0x1122BB44']) + + self.runCmd( + "type summary add -s \"${var.first%x} and ${var.second%X}\" foo") + self.expect('frame variable mine', + substrs=['(foo) mine = 0xaabbccdd and 0x1122BB44']) + self.runCmd("next") + self.runCmd("next") + self.runCmd( + "type summary add -s \"${var.first%x} and ${var.second%x}\" foo") + self.expect('frame variable mine', + substrs=['(foo) mine = 0xaabbccdd and 0xff00ff00']) + self.runCmd( + "type summary add -s \"${var.first%X} and ${var.second%X}\" foo") + self.expect('frame variable mine', + substrs=['(foo) mine = 0xAABBCCDD and 0xFF00FF00']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/hexcaps/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/hexcaps/main.cpp new file mode 100644 index 00000000000..fc4204b1984 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/hexcaps/main.cpp @@ -0,0 +1,27 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <stdio.h> + +struct foo +{ + int first; + int second; +}; + +int main () +{ + struct foo mine = {0x001122AA, 0x1122BB44}; + printf("main.first = 0x%8.8x, main.second = 0x%8.8x\n", mine.first, mine.second); + mine.first = 0xAABBCCDD; // Set break point at this line. + printf("main.first = 0x%8.8x, main.second = 0x%8.8x\n", mine.first, mine.second); + mine.second = 0xFF00FF00; + printf("main.first = 0x%8.8x, main.second = 0x%8.8x\n", mine.first, mine.second); + return 0; +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/language_category_updates/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/language_category_updates/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/language_category_updates/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/language_category_updates/TestDataFormatterLanguageCategoryUpdates.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/language_category_updates/TestDataFormatterLanguageCategoryUpdates.py new file mode 100644 index 00000000000..62bd058666b --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/language_category_updates/TestDataFormatterLanguageCategoryUpdates.py @@ -0,0 +1,83 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class LanguageCategoryUpdatesTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// break here') + + def test_with_run_command(self): + """Test that LLDB correctly cleans caches when language categories change.""" + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + if hasattr( + self, + 'type_category') and hasattr( + self, + 'type_specifier'): + self.type_category.DeleteTypeSummary(self.type_specifier) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + self.expect( + "frame variable", + substrs=[ + '(S)', + 'object', + '123', + '456'], + matching=True) + + self.type_category = self.dbg.GetCategory( + lldb.eLanguageTypeC_plus_plus) + type_summary = lldb.SBTypeSummary.CreateWithSummaryString( + "this is an object of type S") + self.type_specifier = lldb.SBTypeNameSpecifier('S') + self.type_category.AddTypeSummary(self.type_specifier, type_summary) + + self.expect( + "frame variable", + substrs=['this is an object of type S'], + matching=True) + + self.type_category.DeleteTypeSummary(self.type_specifier) + self.expect( + "frame variable", + substrs=['this is an object of type S'], + matching=False) + self.expect( + "frame variable", + substrs=[ + '(S)', + 'object', + '123', + '456'], + matching=True) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/language_category_updates/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/language_category_updates/main.cpp new file mode 100644 index 00000000000..86ee8d5a8e8 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/language_category_updates/main.cpp @@ -0,0 +1,19 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +struct S { + int x; + int y; + + S() : x(123), y(456) {} +}; + +int main() { + S object; + return 0; // break here +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/nsarraysynth/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/nsarraysynth/Makefile new file mode 100644 index 00000000000..8b322ff320b --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/nsarraysynth/Makefile @@ -0,0 +1,8 @@ +OBJC_SOURCES := main.m + +CFLAGS_EXTRAS := -w + + + +LD_EXTRAS := -framework Foundation +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/nsarraysynth/TestNSArraySynthetic.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/nsarraysynth/TestNSArraySynthetic.py new file mode 100644 index 00000000000..466eb5d5b7f --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/nsarraysynth/TestNSArraySynthetic.py @@ -0,0 +1,106 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class NSArraySyntheticTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.m', '// Set break point at this line.') + + @skipUnlessDarwin + def test_rdar11086338_with_run_command(self): + """Test that NSArray reports its synthetic children properly.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.m", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type synth clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + # Now check that we are displaying Cocoa classes correctly + self.expect('frame variable arr', + substrs=['@"6 elements"']) + self.expect('frame variable other_arr', + substrs=['@"4 elements"']) + self.expect( + 'frame variable arr --ptr-depth 1', + substrs=[ + '@"6 elements"', + '[0] = 0x', + '[1] = 0x', + '[2] = 0x', + '[3] = 0x', + '[4] = 0x', + '[5] = 0x']) + self.expect( + 'frame variable other_arr --ptr-depth 1', + substrs=[ + '@"4 elements"', + '[0] = 0x', + '[1] = 0x', + '[2] = 0x', + '[3] = 0x']) + self.expect( + 'frame variable arr --ptr-depth 1 -d no-run-target', + substrs=[ + '@"6 elements"', + '@"hello"', + '@"world"', + '@"this"', + '@"is"', + '@"me"', + '@"http://www.apple.com']) + self.expect( + 'frame variable other_arr --ptr-depth 1 -d no-run-target', + substrs=[ + '@"4 elements"', + '(int)5', + '@"a string"', + '@"6 elements"']) + self.expect( + 'frame variable other_arr --ptr-depth 2 -d no-run-target', + substrs=[ + '@"4 elements"', + '@"6 elements" {', + '@"hello"', + '@"world"', + '@"this"', + '@"is"', + '@"me"', + '@"http://www.apple.com']) + + self.assertTrue( + self.frame().FindVariable("arr").MightHaveChildren(), + "arr says it does not have children!") + self.assertTrue( + self.frame().FindVariable("other_arr").MightHaveChildren(), + "arr says it does not have children!") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/nsarraysynth/main.m b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/nsarraysynth/main.m new file mode 100644 index 00000000000..e65ee6f0c85 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/nsarraysynth/main.m @@ -0,0 +1,34 @@ +//===-- main.m ------------------------------------------------*- ObjC -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#import <Foundation/Foundation.h> + +int main (int argc, const char * argv[]) +{ + + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + + + NSMutableArray* arr = [[NSMutableArray alloc] init]; + [arr addObject:@"hello"]; + [arr addObject:@"world"]; + [arr addObject:@"this"]; + [arr addObject:@"is"]; + [arr addObject:@"me"]; + [arr addObject:[NSURL URLWithString:@"http://www.apple.com/"]]; + + NSDate *aDate = [NSDate distantFuture]; + NSValue *aValue = [NSNumber numberWithInt:5]; + NSString *aString = @"a string"; + + NSArray *other_arr = [NSArray arrayWithObjects:aDate, aValue, aString, arr, nil]; + + [pool drain];// Set break point at this line. + return 0; +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/nsdictionarysynth/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/nsdictionarysynth/Makefile new file mode 100644 index 00000000000..8b322ff320b --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/nsdictionarysynth/Makefile @@ -0,0 +1,8 @@ +OBJC_SOURCES := main.m + +CFLAGS_EXTRAS := -w + + + +LD_EXTRAS := -framework Foundation +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/nsdictionarysynth/TestNSDictionarySynthetic.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/nsdictionarysynth/TestNSDictionarySynthetic.py new file mode 100644 index 00000000000..b77d01a8086 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/nsdictionarysynth/TestNSDictionarySynthetic.py @@ -0,0 +1,120 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class NSDictionarySyntheticTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.m', '// Set break point at this line.') + + @skipUnlessDarwin + def test_rdar11988289_with_run_command(self): + """Test that NSDictionary reports its synthetic children properly.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.m", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type synth clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + # Now check that we are displaying Cocoa classes correctly + self.expect('frame variable dictionary', + substrs=['3 key/value pairs']) + self.expect('frame variable mutabledict', + substrs=['4 key/value pairs']) + self.expect( + 'frame variable dictionary --ptr-depth 1', + substrs=[ + '3 key/value pairs', + '[0] = ', + 'key = 0x', + 'value = 0x', + '[1] = ', + '[2] = ']) + self.expect( + 'frame variable mutabledict --ptr-depth 1', + substrs=[ + '4 key/value pairs', + '[0] = ', + 'key = 0x', + 'value = 0x', + '[1] = ', + '[2] = ', + '[3] = ']) + self.expect( + 'frame variable dictionary --ptr-depth 1 --dynamic-type no-run-target', + substrs=[ + '3 key/value pairs', + '@"bar"', + '@"2 elements"', + '@"baz"', + '2 key/value pairs']) + self.expect( + 'frame variable mutabledict --ptr-depth 1 --dynamic-type no-run-target', + substrs=[ + '4 key/value pairs', + '(int)23', + '@"123"', + '@"http://www.apple.com"', + '@"sourceofstuff"', + '3 key/value pairs']) + self.expect( + 'frame variable mutabledict --ptr-depth 2 --dynamic-type no-run-target', + substrs=[ + '4 key/value pairs', + '(int)23', + '@"123"', + '@"http://www.apple.com"', + '@"sourceofstuff"', + '3 key/value pairs', + '@"bar"', + '@"2 elements"']) + self.expect( + 'frame variable mutabledict --ptr-depth 3 --dynamic-type no-run-target', + substrs=[ + '4 key/value pairs', + '(int)23', + '@"123"', + '@"http://www.apple.com"', + '@"sourceofstuff"', + '3 key/value pairs', + '@"bar"', + '@"2 elements"', + '(int)1', + '@"two"']) + + self.assertTrue( + self.frame().FindVariable("dictionary").MightHaveChildren(), + "dictionary says it does not have children!") + self.assertTrue( + self.frame().FindVariable("mutabledict").MightHaveChildren(), + "mutable says it does not have children!") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/nsdictionarysynth/main.m b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/nsdictionarysynth/main.m new file mode 100644 index 00000000000..65faaeaba09 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/nsdictionarysynth/main.m @@ -0,0 +1,29 @@ +//===-- main.m ------------------------------------------------*- ObjC -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#import <Foundation/Foundation.h> + +int main (int argc, const char * argv[]) +{ + + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + + + NSArray* keys = @[@"foo",@"bar",@"baz"]; + NSArray* values = @[@"hello",@[@"X",@"Y"],@{@1 : @"one",@2 : @"two"}]; + NSDictionary* dictionary = [NSDictionary dictionaryWithObjects:values forKeys:keys]; + NSMutableDictionary* mutabledict = [NSMutableDictionary dictionaryWithCapacity:5]; + [mutabledict setObject:@"123" forKey:@23]; + [mutabledict setObject:[NSURL URLWithString:@"http://www.apple.com"] forKey:@"foobar"]; + [mutabledict setObject:@[@"a",@12] forKey:@57]; + [mutabledict setObject:dictionary forKey:@"sourceofstuff"]; + + [pool drain];// Set break point at this line. + return 0; +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/nssetsynth/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/nssetsynth/Makefile new file mode 100644 index 00000000000..8b322ff320b --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/nssetsynth/Makefile @@ -0,0 +1,8 @@ +OBJC_SOURCES := main.m + +CFLAGS_EXTRAS := -w + + + +LD_EXTRAS := -framework Foundation +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/nssetsynth/TestNSSetSynthetic.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/nssetsynth/TestNSSetSynthetic.py new file mode 100644 index 00000000000..2e8ca4591c9 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/nssetsynth/TestNSSetSynthetic.py @@ -0,0 +1,111 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class NSSetSyntheticTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.m', '// Set break point at this line.') + + @skipUnlessDarwin + def test_rdar12529957_with_run_command(self): + """Test that NSSet reports its synthetic children properly.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.m", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type synth clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + # Now check that we are displaying Cocoa classes correctly + self.expect('frame variable set', + substrs=['4 elements']) + self.expect('frame variable mutable', + substrs=['9 elements']) + self.expect( + 'frame variable set --ptr-depth 1 -d run -T', + substrs=[ + '4 elements', + '[0]', + '[1]', + '[2]', + '[3]', + 'hello', + 'world', + '(int)1', + '(int)2']) + self.expect( + 'frame variable mutable --ptr-depth 1 -d run -T', + substrs=[ + '9 elements', + '(int)5', + '@"3 elements"', + '@"www.apple.com"', + '(int)3', + '@"world"', + '(int)4']) + + self.runCmd("next") + self.expect('frame variable mutable', + substrs=['0 elements']) + + self.runCmd("next") + self.expect('frame variable mutable', + substrs=['4 elements']) + self.expect( + 'frame variable mutable --ptr-depth 1 -d run -T', + substrs=[ + '4 elements', + '[0]', + '[1]', + '[2]', + '[3]', + 'hello', + 'world', + '(int)1', + '(int)2']) + + self.runCmd("next") + self.expect('frame variable mutable', + substrs=['4 elements']) + self.expect( + 'frame variable mutable --ptr-depth 1 -d run -T', + substrs=[ + '4 elements', + '[0]', + '[1]', + '[2]', + '[3]', + 'hello', + 'world', + '(int)1', + '(int)2']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/nssetsynth/main.m b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/nssetsynth/main.m new file mode 100644 index 00000000000..207e23f51f9 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/nssetsynth/main.m @@ -0,0 +1,33 @@ +//===-- main.m ------------------------------------------------*- ObjC -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#import <Foundation/Foundation.h> + +int main (int argc, const char * argv[]) +{ + + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + + NSSet* set = [NSSet setWithArray:@[@1,@"hello",@2,@"world"]]; + NSMutableSet* mutable = [NSMutableSet setWithCapacity:5]; + [mutable addObject:@1]; + [mutable addObject:@2]; + [mutable addObject:@3]; + [mutable addObject:@4]; + [mutable addObject:@5]; + [mutable addObject:[NSURL URLWithString:@"www.apple.com"]]; + [mutable addObject:@[@1,@2,@3]]; + [mutable unionSet:set]; + [mutable removeAllObjects]; // Set break point at this line. + [mutable unionSet:set]; + [mutable addObject:@1]; + + [pool drain]; + return 0; +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/ostypeformatting/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/ostypeformatting/Makefile new file mode 100644 index 00000000000..876340159d9 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/ostypeformatting/Makefile @@ -0,0 +1,8 @@ +OBJCXX_SOURCES := main.mm + +CFLAGS_EXTRAS := -w + + + +LD_EXTRAS := -framework Foundation +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/ostypeformatting/TestFormattersOsType.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/ostypeformatting/TestFormattersOsType.py new file mode 100644 index 00000000000..c4180089ffa --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/ostypeformatting/TestFormattersOsType.py @@ -0,0 +1,51 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class DataFormatterOSTypeTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.mm', '// Set break point at this line.') + + @skipUnlessDarwin + def test_ostype_with_run_command(self): + """Test the formatters we use for OSType.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.mm", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type synth clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + # Now check that we use the right summary for OSType + self.expect('frame variable', + substrs=["'test'", "'best'"]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/ostypeformatting/main.mm b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/ostypeformatting/main.mm new file mode 100644 index 00000000000..18d37b70dfd --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/ostypeformatting/main.mm @@ -0,0 +1,22 @@ +//===-- main.m ------------------------------------------------*- ObjC -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#import <Foundation/Foundation.h> + +int main (int argc, const char * argv[]) +{ + + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + + OSType a = 'test'; + OSType b = 'best'; + + [pool drain];// Set break point at this line. + return 0; +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/parray/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/parray/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/parray/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/parray/TestPrintArray.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/parray/TestPrintArray.py new file mode 100644 index 00000000000..c3062646886 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/parray/TestPrintArray.py @@ -0,0 +1,132 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class PrintArrayTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_print_array(self): + """Test that expr -Z works""" + self.build() + self.printarray_data_formatter_commands() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', 'break here') + + def printarray_data_formatter_commands(self): + """Test that expr -Z works""" + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type synth clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.expect( + 'expr --element-count 3 -- data', + substrs=[ + '[0] = 1', + '[1] = 3', + '[2] = 5']) + self.expect('expr data', substrs=['int *', '$', '0x']) + self.expect( + 'expr -f binary --element-count 0 -- data', + substrs=[ + 'int *', + '$', + '0b']) + self.expect( + 'expr -f hex --element-count 3 -- data', + substrs=[ + '[0] = 0x', + '1', + '[1] = 0x', + '3', + '[2] = 0x', + '5']) + self.expect( + 'expr -f binary --element-count 2 -- data', + substrs=[ + 'int *', + '$', + '0x', + '[0] = 0b', + '1', + '[1] = 0b', + '11']) + self.expect('parray 3 data', substrs=['[0] = 1', '[1] = 3', '[2] = 5']) + self.expect( + 'parray `1 + 1 + 1` data', + substrs=[ + '[0] = 1', + '[1] = 3', + '[2] = 5']) + self.expect( + 'parray `data[1]` data', + substrs=[ + '[0] = 1', + '[1] = 3', + '[2] = 5']) + self.expect( + 'parray/x 3 data', + substrs=[ + '[0] = 0x', + '1', + '[1] = 0x', + '3', + '[2] = 0x', + '5']) + self.expect( + 'parray/x `data[1]` data', + substrs=[ + '[0] = 0x', + '1', + '[1] = 0x', + '3', + '[2] = 0x', + '5']) + + # check error conditions + self.expect( + 'expr --element-count 10 -- 123', + error=True, + substrs=['expression cannot be used with --element-count as it does not refer to a pointer']) + self.expect( + 'expr --element-count 10 -- (void*)123', + error=True, + substrs=['expression cannot be used with --element-count as it refers to a pointer to void']) + self.expect('parray data', error=True, substrs=[ + "invalid element count 'data'"]) + self.expect( + 'parray data data', + error=True, + substrs=["invalid element count 'data'"]) + self.expect('parray', error=True, substrs=[ + 'Not enough arguments provided']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/parray/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/parray/main.cpp new file mode 100644 index 00000000000..5d52383819a --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/parray/main.cpp @@ -0,0 +1,28 @@ +//===-- main.cpp -------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <functional> +#include <stdlib.h> + +template<typename ElemType> +ElemType* alloc(size_t count, std::function<ElemType(size_t)> get) +{ + ElemType *elems = new ElemType[count]; + for(size_t i = 0; i < count; i++) + elems[i] = get(i); + return elems; +} + +int main (int argc, const char * argv[]) +{ + int* data = alloc<int>(5, [] (size_t idx) -> int { + return 2 * idx + 1; + }); + return 0; // break here +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/poarray/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/poarray/Makefile new file mode 100644 index 00000000000..876340159d9 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/poarray/Makefile @@ -0,0 +1,8 @@ +OBJCXX_SOURCES := main.mm + +CFLAGS_EXTRAS := -w + + + +LD_EXTRAS := -framework Foundation +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/poarray/TestPrintObjectArray.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/poarray/TestPrintObjectArray.py new file mode 100644 index 00000000000..400607d84eb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/poarray/TestPrintObjectArray.py @@ -0,0 +1,108 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class PrintObjectArrayTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipUnlessDarwin + def test_print_array(self): + """Test that expr -O -Z works""" + self.build() + self.printarray_data_formatter_commands() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.mm', 'break here') + + def printarray_data_formatter_commands(self): + """Test that expr -O -Z works""" + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.mm", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type synth clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.expect( + 'expr --element-count 3 --object-description -- objects', + substrs=[ + '3735928559', + '4276993775', + '3203398366', + 'Hello', + 'World', + 'Two =', + '1 =']) + self.expect( + 'poarray 3 objects', + substrs=[ + '3735928559', + '4276993775', + '3203398366', + 'Hello', + 'World', + 'Two =', + '1 =']) + self.expect( + 'expr --element-count 3 --object-description --description-verbosity=full -- objects', + substrs=[ + '[0] =', + '3735928559', + '4276993775', + '3203398366', + '[1] =', + 'Hello', + 'World', + '[2] =', + 'Two =', + '1 =']) + self.expect( + 'parray 3 objects', + substrs=[ + '[0] = 0x', + '[1] = 0x', + '[2] = 0x']) + self.expect( + 'expr --element-count 3 -d run -- objects', + substrs=[ + '3 elements', + '2 elements', + '2 key/value pairs']) + self.expect( + 'expr --element-count 3 -d run --ptr-depth=1 -- objects', + substrs=[ + '3 elements', + '2 elements', + '2 key/value pairs', + '3735928559', + '4276993775', + '3203398366', + '"Hello"', + '"World"']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/poarray/main.mm b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/poarray/main.mm new file mode 100644 index 00000000000..be822dd7ab0 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/poarray/main.mm @@ -0,0 +1,29 @@ +//===-- main.cpp -------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#import <Foundation/Foundation.h> + +struct ThreeObjects +{ + id one; + id two; + id three; +}; + +int main() +{ + NSArray *array1 = @[@0xDEADBEEF, @0xFEEDBEEF, @0xBEEFFADE]; + NSArray *array2 = @[@"Hello", @"World"]; + NSDictionary *dictionary = @{@1: array2, @"Two": array2}; + ThreeObjects *tobjects = new ThreeObjects(); + tobjects->one = array1; + tobjects->two = array2; + tobjects->three = dictionary; + id* objects = (id*)tobjects; + return 0; // break here +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/ptr_ref_typedef/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/ptr_ref_typedef/Makefile new file mode 100644 index 00000000000..83eb77ec8a9 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/ptr_ref_typedef/Makefile @@ -0,0 +1,5 @@ +CXX_SOURCES := main.cpp + +CFLAGS_EXTRAS := -std=c++11 + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/ptr_ref_typedef/TestPtrRef2Typedef.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/ptr_ref_typedef/TestPtrRef2Typedef.py new file mode 100644 index 00000000000..b0f7002966c --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/ptr_ref_typedef/TestPtrRef2Typedef.py @@ -0,0 +1,64 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class PtrRef2TypedefTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set breakpoint here') + + def test_with_run_command(self): + """Test that a pointer/reference to a typedef is formatted as we want.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.runCmd('type summary add --cascade true -s "IntPointer" "int *"') + self.runCmd('type summary add --cascade true -s "IntLRef" "int &"') + self.runCmd('type summary add --cascade true -s "IntRRef" "int &&"') + + self.expect( + "frame variable x", + substrs=[ + '(Foo *) x = 0x', + 'IntPointer']) + # note: Ubuntu 12.04 x86_64 build with gcc 4.8.2 is getting a + # const after the ref that isn't showing up on FreeBSD. This + # tweak changes the behavior so that the const is not part of + # the match. + self.expect( + "frame variable y", substrs=[ + '(Foo &', ') y = 0x', 'IntLRef']) + self.expect( + "frame variable z", substrs=[ + '(Foo &&', ') z = 0x', 'IntRRef']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/ptr_ref_typedef/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/ptr_ref_typedef/main.cpp new file mode 100644 index 00000000000..4520165758d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/ptr_ref_typedef/main.cpp @@ -0,0 +1,18 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +typedef int Foo; + +int main() { + int lval = 1; + Foo* x = &lval; + Foo& y = lval; + Foo&& z = 1; + return 0; // Set breakpoint here +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/pyobjsynthprovider/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/pyobjsynthprovider/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/pyobjsynthprovider/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/pyobjsynthprovider/TestPyObjSynthProvider.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/pyobjsynthprovider/TestPyObjSynthProvider.py new file mode 100644 index 00000000000..22ce7442a62 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/pyobjsynthprovider/TestPyObjSynthProvider.py @@ -0,0 +1,68 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class PyObjectSynthProviderTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + def test_print_array(self): + """Test that expr -Z works""" + self.build() + self.provider_data_formatter_commands() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', 'break here') + + def provider_data_formatter_commands(self): + """Test that the PythonObjectSyntheticChildProvider helper class works""" + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type synth clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.runCmd('command script import provider.py') + self.runCmd( + 'type synthetic add Foo --python-class provider.SyntheticChildrenProvider') + self.expect('frame variable f.Name', substrs=['"Enrico"']) + self.expect( + 'frame variable f', + substrs=[ + 'ID = 123456', + 'Name = "Enrico"', + 'Rate = 1.25']) + self.expect( + 'expression f', + substrs=[ + 'ID = 123456', + 'Name = "Enrico"', + 'Rate = 1.25']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/pyobjsynthprovider/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/pyobjsynthprovider/main.cpp new file mode 100644 index 00000000000..4e7c633b591 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/pyobjsynthprovider/main.cpp @@ -0,0 +1,19 @@ +//===-- main.cpp -------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +struct Foo +{ + double x; + int y; + Foo() : x(3.1415), y(1234) {} +}; + +int main() { + Foo f; + return 0; // break here +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/pyobjsynthprovider/provider.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/pyobjsynthprovider/provider.py new file mode 100644 index 00000000000..c263190c102 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/pyobjsynthprovider/provider.py @@ -0,0 +1,16 @@ +import lldb +import lldb.formatters +import lldb.formatters.synth + + +class SyntheticChildrenProvider( + lldb.formatters.synth.PythonObjectSyntheticChildProvider): + + def __init__(self, value, internal_dict): + lldb.formatters.synth.PythonObjectSyntheticChildProvider.__init__( + self, value, internal_dict) + + def make_children(self): + return [("ID", 123456), + ("Name", "Enrico"), + ("Rate", 1.25)] diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/refpointer-recursion/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/refpointer-recursion/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/refpointer-recursion/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/refpointer-recursion/TestDataFormatterRefPtrRecursion.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/refpointer-recursion/TestDataFormatterRefPtrRecursion.py new file mode 100644 index 00000000000..1dc37c64f36 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/refpointer-recursion/TestDataFormatterRefPtrRecursion.py @@ -0,0 +1,40 @@ +""" +Test that ValueObjectPrinter does not cause an infinite loop when a reference to a struct that contains a pointer to itself is printed. +""" + + + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class DataFormatterRefPtrRecursionTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + def test_with_run_command(self): + """Test that ValueObjectPrinter does not cause an infinite loop when a reference to a struct that contains a pointer to itself is printed.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + self.expect("frame variable foo", substrs=[]) + self.expect("frame variable foo --ptr-depth=1", substrs=['ID = 1']) + self.expect("frame variable foo --ptr-depth=2", substrs=['ID = 1']) + self.expect("frame variable foo --ptr-depth=3", substrs=['ID = 1']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/refpointer-recursion/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/refpointer-recursion/main.cpp new file mode 100644 index 00000000000..4b576bd266d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/refpointer-recursion/main.cpp @@ -0,0 +1,21 @@ +int _ID = 0; + +class Foo { + public: + Foo *next; + int ID; + + Foo () : next(0), ID(++_ID) {} +}; + +int evalFoo(Foo& foo) +{ + return foo.ID; // Set break point at this line. +} + +int main() { + Foo f; + f.next = &f; + return evalFoo(f); +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/setvaluefromcstring/TestSetValueFromCString.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/setvaluefromcstring/TestSetValueFromCString.py new file mode 100644 index 00000000000..e08667fd24c --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/setvaluefromcstring/TestSetValueFromCString.py @@ -0,0 +1,7 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest( + __file__, globals(), [ + decorators.skipIfFreeBSD, decorators.skipIfLinux, + decorators.skipIfNetBSD, decorators.skipIfWindows]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/setvaluefromcstring/main.m b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/setvaluefromcstring/main.m new file mode 100644 index 00000000000..e66c6b15e7f --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/setvaluefromcstring/main.m @@ -0,0 +1,18 @@ +//===-- main.m ---------------------------------------------------*- ObjC -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#import <Foundation/Foundation.h> + +int main() { + NSDictionary* dic = @{@1 : @2}; + NSLog(@"hello world"); //% dic = self.frame().FindVariable("dic") + //% dic.SetPreferSyntheticValue(True) + //% dic.SetPreferDynamicValue(lldb.eDynamicCanRunTarget) + //% dic.SetValueFromCString("12") + return 0; //% dic = self.frame().FindVariable("dic") + //% self.assertTrue(dic.GetValueAsUnsigned() == 0xC, "failed to read what I wrote") +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/stringprinter/TestStringPrinter.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/stringprinter/TestStringPrinter.py new file mode 100644 index 00000000000..c76b421a1ea --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/stringprinter/TestStringPrinter.py @@ -0,0 +1,7 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest( + __file__, globals(), [ + decorators.expectedFailureAll( + oslist=["windows"], bugnumber="llvm.org/pr24772")]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/stringprinter/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/stringprinter/main.cpp new file mode 100644 index 00000000000..2631171ebf8 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/stringprinter/main.cpp @@ -0,0 +1,39 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <string> + +int main (int argc, char const *argv[]) +{ + std::string stdstring("Hello\t\tWorld\nI am here\t\tto say hello\n"); //%self.addTearDownHook(lambda x: x.runCmd("setting set escape-non-printables true")) + const char* constcharstar = stdstring.c_str(); + std::string longstring( +"I am a very long string; in fact I am longer than any reasonable length that a string should be; quite long indeed; oh my, so many words; so many letters; this is kind of like writing a poem; except in real life all that is happening" +" is just me producing a very very long set of words; there is text here, text there, text everywhere; it fills me with glee to see so much text; all around me it's just letters, and symbols, and other pleasant drawings that cause me" +" a large amount of joy upon visually seeing them with my eyes; well, this is now a lot of letters, but it is still not enough for the purpose of the test I want to test, so maybe I should copy and paste this a few times, you know.." +" for science, or something" + "I am a very long string; in fact I am longer than any reasonable length that a string should be; quite long indeed; oh my, so many words; so many letters; this is kind of like writing a poem; except in real life all that is happening" + " is just me producing a very very long set of words; there is text here, text there, text everywhere; it fills me with glee to see so much text; all around me it's just letters, and symbols, and other pleasant drawings that cause me" + " a large amount of joy upon visually seeing them with my eyes; well, this is now a lot of letters, but it is still not enough for the purpose of the test I want to test, so maybe I should copy and paste this a few times, you know.." + " for science, or something" + "I am a very long string; in fact I am longer than any reasonable length that a string should be; quite long indeed; oh my, so many words; so many letters; this is kind of like writing a poem; except in real life all that is happening" + " is just me producing a very very long set of words; there is text here, text there, text everywhere; it fills me with glee to see so much text; all around me it's just letters, and symbols, and other pleasant drawings that cause me" + " a large amount of joy upon visually seeing them with my eyes; well, this is now a lot of letters, but it is still not enough for the purpose of the test I want to test, so maybe I should copy and paste this a few times, you know.." + " for science, or something" + ); + const char* longconstcharstar = longstring.c_str(); + return 0; //% if self.TraceOn(): self.runCmd('frame variable') + //% self.assertTrue(self.frame().FindVariable('stdstring').GetSummary() == '"Hello\\t\\tWorld\\nI am here\\t\\tto say hello\\n"') + //% self.assertTrue(self.frame().FindVariable('constcharstar').GetSummary() == '"Hello\\t\\tWorld\\nI am here\\t\\tto say hello\\n"') + //% self.runCmd("setting set escape-non-printables false") + //% self.assertTrue(self.frame().FindVariable('stdstring').GetSummary() == '"Hello\t\tWorld\nI am here\t\tto say hello\n"') + //% self.assertTrue(self.frame().FindVariable('constcharstar').GetSummary() == '"Hello\t\tWorld\nI am here\t\tto say hello\n"') + //% self.assertTrue(self.frame().FindVariable('longstring').GetSummary().endswith('"...')) + //% self.assertTrue(self.frame().FindVariable('longconstcharstar').GetSummary().endswith('"...')) +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/summary-string-onfail/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/summary-string-onfail/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/summary-string-onfail/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/summary-string-onfail/Test-rdar-9974002.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/summary-string-onfail/Test-rdar-9974002.py new file mode 100644 index 00000000000..88ec1ff8c82 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/summary-string-onfail/Test-rdar-9974002.py @@ -0,0 +1,144 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class Radar9974002DataFormatterTestCase(TestBase): + + # test for rdar://problem/9974002 () + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + def test_with_run_command(self): + """Test that that file and class static variables display correctly.""" + self.build() + if "clang" in self.getCompiler() and "3.4" in self.getCompilerVersion(): + self.skipTest( + "llvm.org/pr16214 -- clang emits partial DWARF for structures referenced via typedef") + + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type summary clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.runCmd( + "type summary add -s \"${var.scalar} and ${var.pointer.first}\" container") + + self.expect('frame variable mine', + substrs=['mine = ', + '1', '<parent is NULL>']) + + self.runCmd( + "type summary add -s \"${var.scalar} and ${var.pointer}\" container") + + self.expect('frame variable mine', + substrs=['mine = ', + '1', '0x000000']) + + self.runCmd( + "type summary add -s \"${var.scalar} and ${var.pointer%S}\" container") + + self.expect('frame variable mine', + substrs=['mine = ', + '1', '0x000000']) + + self.runCmd("type summary add -s foo contained") + + self.expect('frame variable mine', + substrs=['mine = ', + '1', 'foo']) + + self.runCmd( + "type summary add -s \"${var.scalar} and ${var.pointer}\" container") + + self.expect('frame variable mine', + substrs=['mine = ', + '1', 'foo']) + + self.runCmd( + "type summary add -s \"${var.scalar} and ${var.pointer%V}\" container") + + self.expect('frame variable mine', + substrs=['mine = ', + '1', '0x000000']) + + self.runCmd( + "type summary add -s \"${var.scalar} and ${var.pointer.first}\" container") + + self.expect('frame variable mine', + substrs=['mine = ', + '1', '<parent is NULL>']) + + self.runCmd("type summary delete contained") + self.runCmd("n") + + self.expect('frame variable mine', + substrs=['mine = ', + '1', '<parent is NULL>']) + + self.runCmd( + "type summary add -s \"${var.scalar} and ${var.pointer}\" container") + + self.expect('frame variable mine', + substrs=['mine = ', + '1', '0x000000']) + + self.runCmd( + "type summary add -s \"${var.scalar} and ${var.pointer%S}\" container") + + self.expect('frame variable mine', + substrs=['mine = ', + '1', '0x000000']) + + self.runCmd("type summary add -s foo contained") + + self.expect('frame variable mine', + substrs=['mine = ', + '1', 'foo']) + + self.runCmd( + "type summary add -s \"${var.scalar} and ${var.pointer}\" container") + + self.expect('frame variable mine', + substrs=['mine = ', + '1', 'foo']) + + self.runCmd( + "type summary add -s \"${var.scalar} and ${var.pointer%V}\" container") + + self.expect('frame variable mine', + substrs=['mine = ', + '1', '0x000000']) + + self.runCmd( + "type summary add -s \"${var.scalar} and ${var.pointer.first}\" container") + + self.expect('frame variable mine', + substrs=['mine = ', + '1', '<parent is NULL>']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/summary-string-onfail/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/summary-string-onfail/main.cpp new file mode 100644 index 00000000000..9d483ebb470 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/summary-string-onfail/main.cpp @@ -0,0 +1,29 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <stdio.h> + +struct contained +{ + int first; + int second; +}; + +struct container +{ + int scalar; + struct contained *pointer; +}; + +int main () +{ + struct container mine = {1, 0}; + printf ("Mine's scalar is the only thing that is good: %d.\n", mine.scalar); // Set break point at this line. + return 0; +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/TestSyntheticCapping.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/TestSyntheticCapping.py new file mode 100644 index 00000000000..53df271fdcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/TestSyntheticCapping.py @@ -0,0 +1,85 @@ +""" +Check for an issue where capping does not work because the Target pointer appears to be changing behind our backs +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class SyntheticCappingTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + def test_with_run_command(self): + """Check for an issue where capping does not work because the Target pointer appears to be changing behind our backs.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + process = self.dbg.GetSelectedTarget().GetProcess() + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + self.runCmd('type synth clear', check=False) + self.runCmd( + "settings set target.max-children-count 256", + check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + # set up the synthetic children provider + self.runCmd("script from fooSynthProvider import *") + self.runCmd("type synth add -l fooSynthProvider foo") + + # note that the value of fake_a depends on target byte order + if process.GetByteOrder() == lldb.eByteOrderLittle: + fake_a_val = 0x02000000 + else: + fake_a_val = 0x00000100 + + # check that the synthetic children work, so we know we are doing the + # right thing + self.expect("frame variable f00_1", + substrs=['r = 34', + 'fake_a = %d' % fake_a_val, + 'a = 1']) + + # check that capping works + self.runCmd("settings set target.max-children-count 2", check=False) + + self.expect("frame variable f00_1", + substrs=['...', + 'fake_a = %d' % fake_a_val, + 'a = 1']) + + self.expect("frame variable f00_1", matching=False, + substrs=['r = 34']) + + self.runCmd("settings set target.max-children-count 256", check=False) + + self.expect("frame variable f00_1", matching=True, + substrs=['r = 34']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/fooSynthProvider.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/fooSynthProvider.py new file mode 100644 index 00000000000..124eb5d31ba --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/fooSynthProvider.py @@ -0,0 +1,27 @@ +import lldb + + +class fooSynthProvider: + + def __init__(self, valobj, dict): + self.valobj = valobj + self.int_type = valobj.GetType().GetBasicType(lldb.eBasicTypeInt) + + def num_children(self): + return 3 + + def get_child_at_index(self, index): + if index == 0: + child = self.valobj.GetChildMemberWithName('a') + if index == 1: + child = self.valobj.CreateChildAtOffset('fake_a', 1, self.int_type) + if index == 2: + child = self.valobj.GetChildMemberWithName('r') + return child + + def get_child_index(self, name): + if name == 'a': + return 0 + if name == 'fake_a': + return 1 + return 2 diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/main.cpp new file mode 100644 index 00000000000..90571b59f81 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/main.cpp @@ -0,0 +1,62 @@ +struct foo +{ + int a; + int b; + int c; + int d; + int e; + int f; + int g; + int h; + int i; + int j; + int k; + int l; + int m; + int n; + int o; + int p; + int q; + int r; + + foo(int X) : + a(X), + b(X+1), + c(X+3), + d(X+5), + e(X+7), + f(X+9), + g(X+11), + h(X+13), + i(X+15), + j(X+17), + k(X+19), + l(X+21), + m(X+23), + n(X+25), + o(X+27), + p(X+29), + q(X+31), + r(X+33) {} +}; + +struct wrapint +{ + int x; + wrapint(int X) : x(X) {} +}; + +int main() +{ + foo f00_1(1); + foo *f00_ptr = new foo(12); + + f00_1.a++; // Set break point at this line. + + wrapint test_cast('A' + + 256*'B' + + 256*256*'C'+ + 256*256*256*'D'); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/synthupdate/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/synthupdate/Makefile new file mode 100644 index 00000000000..3767ff17e35 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/synthupdate/Makefile @@ -0,0 +1,8 @@ +OBJC_SOURCES := main.m +CFLAGS_EXTRAS := -w +LD_EXTRAS := -framework Foundation + +include Makefile.rules + +clean:: + rm -rf $(wildcard *.o *.d *.dSYM *.log) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/synthupdate/TestSyntheticFilterRecompute.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/synthupdate/TestSyntheticFilterRecompute.py new file mode 100644 index 00000000000..e9e570eda58 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/synthupdate/TestSyntheticFilterRecompute.py @@ -0,0 +1,83 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class SyntheticFilterRecomputingTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.m', '// Set break point at this line.') + + @skipUnlessDarwin + def test_rdar12437442_with_run_command(self): + """Test that we update SBValues correctly as dynamic types change.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.m", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type synth clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + # Now run the bulk of the test + id_x = self.dbg.GetSelectedTarget().GetProcess( + ).GetSelectedThread().GetSelectedFrame().FindVariable("x") + id_x.SetPreferDynamicValue(lldb.eDynamicCanRunTarget) + id_x.SetPreferSyntheticValue(True) + + if self.TraceOn(): + self.runCmd("expr --dynamic-type run-target --ptr-depth 1 -- x") + + self.assertTrue( + id_x.GetSummary() == '@"5 elements"', + "array does not get correct summary") + + self.runCmd("next") + self.runCmd("frame select 0") + + id_x = self.dbg.GetSelectedTarget().GetProcess( + ).GetSelectedThread().GetSelectedFrame().FindVariable("x") + id_x.SetPreferDynamicValue(lldb.eDynamicCanRunTarget) + id_x.SetPreferSyntheticValue(True) + + if self.TraceOn(): + self.runCmd("expr --dynamic-type run-target --ptr-depth 1 -- x") + + self.assertTrue( + id_x.GetNumChildren() == 7, + "dictionary does not have 7 children") + id_x.SetPreferSyntheticValue(False) + self.assertFalse( + id_x.GetNumChildren() == 7, + "dictionary still looks synthetic") + id_x.SetPreferSyntheticValue(True) + self.assertTrue( + id_x.GetSummary() == "7 key/value pairs", + "dictionary does not get correct summary") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/synthupdate/main.m b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/synthupdate/main.m new file mode 100644 index 00000000000..eb27ff9d1e3 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/synthupdate/main.m @@ -0,0 +1,24 @@ +//===-- main.m ------------------------------------------------*- ObjC -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#import <Foundation/Foundation.h> + +int main (int argc, const char * argv[]) +{ + + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + + NSArray* foo = [NSArray arrayWithObjects:@1,@2,@3,@4,@5, nil]; + NSDictionary *bar = @{@1 : @"one",@2 : @"two", @3 : @"three", @4 : @"four", @5 : @"five", @6 : @"six", @7 : @"seven"}; + id x = foo; + x = bar; // Set break point at this line. + + [pool drain]; + return 0; +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_arg/TestTypeSummaryListArg.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_arg/TestTypeSummaryListArg.py new file mode 100644 index 00000000000..e1dc52e8394 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_arg/TestTypeSummaryListArg.py @@ -0,0 +1,44 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TypeSummaryListArgumentTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @no_debug_info_test + def test_type_summary_list_with_arg(self): + """Test that the 'type summary list' command handles command line arguments properly""" + self.expect( + 'type summary list Foo', + substrs=[ + 'Category: default', + 'Category: system']) + self.expect( + 'type summary list char', + substrs=[ + 'char *', + 'unsigned char']) + + self.expect( + 'type summary list -w default', + substrs=['system'], + matching=False) + self.expect( + 'type summary list -w system unsigned', + substrs=[ + 'default', + '0-9'], + matching=False) + self.expect( + 'type summary list -w system char', + substrs=['unsigned char *'], + matching=True) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_script/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_script/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_script/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_script/TestTypeSummaryListScript.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_script/TestTypeSummaryListScript.py new file mode 100644 index 00000000000..7d70ad3da9c --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_script/TestTypeSummaryListScript.py @@ -0,0 +1,62 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TypeSummaryListScriptTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_typesummarylist_script(self): + """Test data formatter commands.""" + self.build() + self.data_formatter_commands() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', 'Break here') + + def data_formatter_commands(self): + """Test printing out Python summary formatters.""" + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type category delete TSLSFormatters', check=False) + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + self.runCmd('type synth clear', check=False) + + self.addTearDownHook(cleanup) + + self.runCmd("command script import tslsformatters.py") + + self.expect( + "frame variable myStruct", + substrs=['A data formatter at work']) + + self.expect('type summary list', substrs=['Struct_SummaryFormatter']) + self.expect( + 'type summary list Struct', + substrs=['Struct_SummaryFormatter']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_script/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_script/main.cpp new file mode 100644 index 00000000000..2de37041f26 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_script/main.cpp @@ -0,0 +1,15 @@ +#include <stdio.h> + +typedef struct Struct +{ + int one; + int two; +} Struct; + +int +main() +{ + Struct myStruct = {10, 20}; + printf ("Break here: %d\n.", myStruct.one); + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_script/tslsformatters.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_script/tslsformatters.py new file mode 100644 index 00000000000..03fe17bfe76 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_script/tslsformatters.py @@ -0,0 +1,12 @@ +import lldb + + +def Struct_SummaryFormatter(valobj, internal_dict): + return 'A data formatter at work' + +category = lldb.debugger.CreateCategory("TSLSFormatters") +category.SetEnabled(True) +summary = lldb.SBTypeSummary.CreateWithFunctionName( + "tslsformatters.Struct_SummaryFormatter", lldb.eTypeOptionCascade) +spec = lldb.SBTypeNameSpecifier("Struct", False) +category.AddTypeSummary(spec, summary) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/typedef_array/TestTypedefArray.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/typedef_array/TestTypedefArray.py new file mode 100644 index 00000000000..7e67f73b709 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/typedef_array/TestTypedefArray.py @@ -0,0 +1,7 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest( + __file__, globals(), [ + decorators.expectedFailureAll( + compiler="gcc")]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/typedef_array/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/typedef_array/main.cpp new file mode 100644 index 00000000000..cb6dc18655f --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/typedef_array/main.cpp @@ -0,0 +1,18 @@ +//===-- main.cpp --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +typedef int Foo; + +int main() { + // CHECK: (Foo [3]) array = { + // CHECK-NEXT: (Foo) [0] = 1 + // CHECK-NEXT: (Foo) [1] = 2 + // CHECK-NEXT: (Foo) [2] = 3 + // CHECK-NEXT: } + Foo array[3] = {1,2,3}; + return 0; //% self.filecheck("frame variable array --show-types --", 'main.cpp') +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/user-format-vs-summary/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/user-format-vs-summary/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/user-format-vs-summary/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/user-format-vs-summary/TestUserFormatVsSummary.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/user-format-vs-summary/TestUserFormatVsSummary.py new file mode 100644 index 00000000000..ad4db01411f --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/user-format-vs-summary/TestUserFormatVsSummary.py @@ -0,0 +1,71 @@ +""" +Test that the user can input a format but it will not prevail over summary format's choices. +""" + + + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class UserFormatVSSummaryTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + def test_with_run_command(self): + """Test that the user can input a format but it will not prevail over summary format's choices.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + self.expect("frame variable p1", substrs=[ + '(Pair) p1 = (x = 3, y = -3)']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.runCmd('type summary add Pair -s "x=${var.x%d},y=${var.y%u}"') + + self.expect("frame variable p1", substrs=[ + '(Pair) p1 = x=3,y=4294967293']) + self.expect( + "frame variable -f x p1", + substrs=['(Pair) p1 = x=0x00000003,y=0xfffffffd'], + matching=False) + self.expect( + "frame variable -f d p1", + substrs=['(Pair) p1 = x=3,y=-3'], + matching=False) + self.expect("frame variable p1", substrs=[ + '(Pair) p1 = x=3,y=4294967293']) + + self.runCmd('type summary add Pair -s "x=${var.x%x},y=${var.y%u}"') + + self.expect("frame variable p1", substrs=[ + '(Pair) p1 = x=0x00000003,y=4294967293']) + self.expect( + "frame variable -f d p1", + substrs=['(Pair) p1 = x=3,y=-3'], + matching=False) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/user-format-vs-summary/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/user-format-vs-summary/main.cpp new file mode 100644 index 00000000000..b7ac006eb68 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/user-format-vs-summary/main.cpp @@ -0,0 +1,19 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +struct Pair { + int x; + int y; + + Pair(int _x, int _y) : x(_x), y(_y) {} +}; + +int main() { + Pair p1(3,-3); + return p1.x + p1.y; // Set break point at this line. +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/var-in-aggregate-misuse/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/var-in-aggregate-misuse/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/var-in-aggregate-misuse/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/var-in-aggregate-misuse/TestVarInAggregateMisuse.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/var-in-aggregate-misuse/TestVarInAggregateMisuse.py new file mode 100644 index 00000000000..c1ec60e9e10 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/var-in-aggregate-misuse/TestVarInAggregateMisuse.py @@ -0,0 +1,77 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class VarInAggregateMisuseTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + def test_with_run_command(self): + """Test that that file and class static variables display correctly.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type summary clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.runCmd( + "type summary add --summary-string \"SUMMARY SUCCESS ${var}\" Summarize") + + self.expect('frame variable mine_ptr', + substrs=['SUMMARY SUCCESS summarize_ptr_t @ ']) + + self.expect('frame variable *mine_ptr', + substrs=['SUMMARY SUCCESS summarize_t @']) + + self.runCmd( + "type summary add --summary-string \"SUMMARY SUCCESS ${var.first}\" Summarize") + + self.expect('frame variable mine_ptr', + substrs=['SUMMARY SUCCESS 10']) + + self.expect('frame variable *mine_ptr', + substrs=['SUMMARY SUCCESS 10']) + + self.runCmd("type summary add --summary-string \"${var}\" Summarize") + self.runCmd( + "type summary add --summary-string \"${var}\" -e TwoSummarizes") + + self.expect('frame variable', + substrs=['(TwoSummarizes) twos = TwoSummarizes @ ', + 'first = summarize_t @ ', + 'second = summarize_t @ ']) + + self.runCmd( + "type summary add --summary-string \"SUMMARY SUCCESS ${var.first}\" Summarize") + self.expect('frame variable', + substrs=['(TwoSummarizes) twos = TwoSummarizes @ ', + 'first = SUMMARY SUCCESS 1', + 'second = SUMMARY SUCCESS 3']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/var-in-aggregate-misuse/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/var-in-aggregate-misuse/main.cpp new file mode 100644 index 00000000000..e35f7f359e3 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/var-in-aggregate-misuse/main.cpp @@ -0,0 +1,40 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <stdio.h> +struct Summarize +{ + int first; + int second; +}; + +typedef struct Summarize summarize_t; +typedef summarize_t *summarize_ptr_t; + +summarize_t global_mine = {30, 40}; + +struct TwoSummarizes +{ + summarize_t first; + summarize_t second; +}; + +int +main() +{ + summarize_t mine = {10, 20}; + summarize_ptr_t mine_ptr = &mine; + + TwoSummarizes twos = { {1,2}, {3,4} }; + + printf ("Summarize: first: %d second: %d and address: 0x%p\n", mine.first, mine.second, mine_ptr); // Set break point at this line. + printf ("Global summarize: first: %d second: %d.\n", global_mine.first, global_mine.second); + return 0; +} + + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/TestDataFormatterVarScriptFormatting.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/TestDataFormatterVarScriptFormatting.py new file mode 100644 index 00000000000..c7391f432f4 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/TestDataFormatterVarScriptFormatting.py @@ -0,0 +1,56 @@ +""" +Test lldb data formatter subsystem. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class DataFormatterVarScriptFormatting(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', ' // Set breakpoint here.') + + @skipIfFreeBSD # llvm.org/pr20545 bogus output confuses buildbot parser + def test_with_run_command(self): + """Test using Python synthetic children provider.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + self.runCmd('type synth clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.runCmd("command script import helperfunc.py") + self.runCmd( + 'type summary add -x "^something<.*>$" -s "T is a ${script.var:helperfunc.f}"') + + self.expect("frame variable x", substrs=['T is a non-pointer type']) + + self.expect("frame variable y", substrs=['T is a pointer type']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/helperfunc.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/helperfunc.py new file mode 100644 index 00000000000..75654e4b4ed --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/helperfunc.py @@ -0,0 +1,6 @@ +import lldb + + +def f(value, d): + return "pointer type" if value.GetType().GetTemplateArgumentType( + 0).IsPointerType() else "non-pointer type" diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/main.cpp new file mode 100644 index 00000000000..e9a36f91196 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/main.cpp @@ -0,0 +1,8 @@ +template <typename T> +struct something {}; + +int main() { + something<int> x; + something<void*> y; + return 0; // Set breakpoint here. +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/vector-types/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/vector-types/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/vector-types/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/vector-types/TestVectorTypesFormatting.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/vector-types/TestVectorTypesFormatting.py new file mode 100644 index 00000000000..e4632afe7b9 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/vector-types/TestVectorTypesFormatting.py @@ -0,0 +1,88 @@ +""" +Check that vector types format properly +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class VectorTypesFormattingTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// break here') + + # rdar://problem/14035604 + @skipIf(compiler='gcc') # gcc don't have ext_vector_type extension + def test_with_run_command(self): + """Check that vector types format properly""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + pass + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + pass # my code never fails + + v = self.frame().FindVariable("v") + v.SetPreferSyntheticValue(True) + v.SetFormat(lldb.eFormatVectorOfFloat32) + + if self.TraceOn(): + print(v) + + self.assertTrue( + v.GetNumChildren() == 4, + "v as float32[] has 4 children") + self.assertTrue(v.GetChildAtIndex(0).GetData().float[ + 0] == 1.25, "child 0 == 1.25") + self.assertTrue(v.GetChildAtIndex(1).GetData().float[ + 0] == 1.25, "child 1 == 1.25") + self.assertTrue(v.GetChildAtIndex(2).GetData().float[ + 0] == 2.50, "child 2 == 2.50") + self.assertTrue(v.GetChildAtIndex(3).GetData().float[ + 0] == 2.50, "child 3 == 2.50") + + self.expect("expr -f int16_t[] -- v", + substrs=['(0, 16288, 0, 16288, 0, 16416, 0, 16416)']) + self.expect("expr -f uint128_t[] -- v", + substrs=['(85236745249553456609335044694184296448)']) + self.expect( + "expr -f float32[] -- v", + substrs=['(1.25, 1.25, 2.5, 2.5)']) + + oldValue = v.GetChildAtIndex(0).GetValue() + v.SetFormat(lldb.eFormatHex) + newValue = v.GetChildAtIndex(0).GetValue() + self.assertFalse(oldValue == newValue, + "values did not change along with format") + + v.SetFormat(lldb.eFormatVectorOfFloat32) + oldValueAgain = v.GetChildAtIndex(0).GetValue() + self.assertTrue( + oldValue == oldValueAgain, + "same format but different values") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/vector-types/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/vector-types/main.cpp new file mode 100644 index 00000000000..5470147f08a --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/vector-types/main.cpp @@ -0,0 +1,16 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +typedef float float4 __attribute__((ext_vector_type(4))); +typedef unsigned char vec __attribute__((ext_vector_type(16))); + +int main() { + float4 f4 = {1.25, 1.25, 2.50, 2.50}; + vec v = (vec)f4; + return 0; // break here +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/dead-strip/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/dead-strip/Makefile new file mode 100644 index 00000000000..3e7e139ddd6 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/dead-strip/Makefile @@ -0,0 +1,20 @@ +C_SOURCES := main.c + +ifeq "$(OS)" "" + OS = $(shell uname -s) +endif + +ifeq "$(OS)" "Darwin" + LD_EXTRAS = -Xlinker -dead_strip +else + CFLAGS_EXTRAS += -fdata-sections -ffunction-sections + ifeq "$(OS)" "Windows_NT" + LD_EXTRAS = -Xlinker /OPT:REF + else + LD_EXTRAS = -Wl,--gc-sections + endif +endif + +MAKE_DSYM := NO + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/dead-strip/TestDeadStrip.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/dead-strip/TestDeadStrip.py new file mode 100644 index 00000000000..bc1f3f8003f --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/dead-strip/TestDeadStrip.py @@ -0,0 +1,58 @@ +""" +Test that breakpoint works correctly in the presence of dead-code stripping. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class DeadStripTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr44429") + def test(self): + """Test breakpoint works correctly with dead-code stripping.""" + self.build() + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Break by function name f1 (live code). + lldbutil.run_break_set_by_symbol( + self, "f1", num_expected_locations=1, module_name="a.out") + + # Break by function name f2 (dead code). + lldbutil.run_break_set_by_symbol( + self, "f2", num_expected_locations=0, module_name="a.out") + + # Break by function name f3 (live code). + lldbutil.run_break_set_by_symbol( + self, "f3", num_expected_locations=1, module_name="a.out") + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint (breakpoint #1). + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'a.out`f1', + 'stop reason = breakpoint']) + + # The breakpoint should have a hit count of 1. + self.expect("breakpoint list -f 1", BREAKPOINT_HIT_ONCE, + substrs=[' resolved, hit count = 1']) + + self.runCmd("continue") + + # The stop reason of the thread should be breakpoint (breakpoint #3). + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'a.out`f3', + 'stop reason = breakpoint']) + + # The breakpoint should have a hit count of 1. + self.expect("breakpoint list -f 3", BREAKPOINT_HIT_ONCE, + substrs=[' resolved, hit count = 1']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/dead-strip/cmds.txt b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/dead-strip/cmds.txt new file mode 100644 index 00000000000..f6fd0450288 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/dead-strip/cmds.txt @@ -0,0 +1,4 @@ +b main.c:21 +b main.c:41 +lines -shlib a.out main.c +c diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/dead-strip/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/dead-strip/main.c new file mode 100644 index 00000000000..cde8c18ba36 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/dead-strip/main.c @@ -0,0 +1,52 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include <stdio.h> + + +int f1 (char *s); +int f2 (char *s); +int f3 (char *s); + + +// We want f1 to start on line 20 +int f1 (char *s) +{ + return printf("f1: %s\n", s); +} + + + + + +// We want f2 to start on line 30, this should get stripped +int f2 (char *s) +{ + return printf("f2: %s\n", s); +} + + + + + +// We want f3 to start on line 40 +int f3 (char *s) +{ + return printf("f3: %s\n", s); +} + + + + + +// We want main to start on line 50 +int main (int argc, const char * argv[]) +{ + f1("carp"); + f3("dong"); + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/deleted-executable/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/deleted-executable/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/deleted-executable/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/deleted-executable/TestDeletedExecutable.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/deleted-executable/TestDeletedExecutable.py new file mode 100644 index 00000000000..ed17d9b36b6 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/deleted-executable/TestDeletedExecutable.py @@ -0,0 +1,46 @@ +""" +Test process attach when executable was deleted. +""" + + + +import os +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestDeletedExecutable(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + @skipIfWindows # cannot delete a running executable + @expectedFailureAll(oslist=["linux"], + triple=no_match('aarch64-.*-android')) + # determining the architecture of the process fails + @expectedFailureNetBSD + def test(self): + self.build() + exe = self.getBuildArtifact("a.out") + + # Use a file as a synchronization point between test and inferior. + pid_file_path = lldbutil.append_to_process_working_directory(self, + "token_pid_%d" % (int(os.getpid()))) + self.addTearDownHook( + lambda: self.run_platform_command( + "rm %s" % + (pid_file_path))) + + # Spawn a new process + popen = self.spawnSubprocess(exe, [pid_file_path]) + self.addTearDownHook(self.cleanupSubprocesses) + + # Wait until process has fully started up. + pid = lldbutil.wait_for_file_on_target(self, pid_file_path) + + # Now we can safely remove the executable and test if we can attach. + os.remove(exe) + + self.runCmd("process attach -p " + str(popen.pid)) + self.runCmd("kill") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/deleted-executable/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/deleted-executable/main.cpp new file mode 100644 index 00000000000..af00ac263cc --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/deleted-executable/main.cpp @@ -0,0 +1,15 @@ +#include <chrono> +#include <fstream> +#include <thread> + +int main(int argc, char const *argv[]) { + lldb_enable_attach(); + + { + // Create file to signal that this process has started up. + std::ofstream f; + f.open(argv[1]); + } + + std::this_thread::sleep_for(std::chrono::seconds(60)); +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/dynamic_value_child_count/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/dynamic_value_child_count/Makefile new file mode 100644 index 00000000000..2bba8e757f7 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/dynamic_value_child_count/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := pass-to-base.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/dynamic_value_child_count/TestDynamicValueChildCount.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/dynamic_value_child_count/TestDynamicValueChildCount.py new file mode 100644 index 00000000000..e7f984081ea --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/dynamic_value_child_count/TestDynamicValueChildCount.py @@ -0,0 +1,80 @@ +""" +Test that dynamic values update their child count correctly +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class DynamicValueChildCountTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + # Find the line number to break for main.c. + + self.main_third_call_line = line_number( + 'pass-to-base.cpp', '// Break here and check b has 0 children') + self.main_fourth_call_line = line_number( + 'pass-to-base.cpp', '// Break here and check b still has 0 children') + self.main_fifth_call_line = line_number( + 'pass-to-base.cpp', '// Break here and check b has one child now') + self.main_sixth_call_line = line_number( + 'pass-to-base.cpp', '// Break here and check b has 0 children again') + + @add_test_categories(['pyapi']) + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24663") + def test_get_dynamic_vals(self): + """Test fetching C++ dynamic values from pointers & references.""" + """Get argument vals for the call stack when stopped on a breakpoint.""" + self.build(dictionary=self.getBuildFlags()) + exe = self.getBuildArtifact("a.out") + + # Create a target from the debugger. + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Set up our breakpoints: + + third_call_bpt = target.BreakpointCreateByLocation( + 'pass-to-base.cpp', self.main_third_call_line) + self.assertTrue(third_call_bpt, + VALID_BREAKPOINT) + fourth_call_bpt = target.BreakpointCreateByLocation( + 'pass-to-base.cpp', self.main_fourth_call_line) + self.assertTrue(fourth_call_bpt, + VALID_BREAKPOINT) + fifth_call_bpt = target.BreakpointCreateByLocation( + 'pass-to-base.cpp', self.main_fifth_call_line) + self.assertTrue(fifth_call_bpt, + VALID_BREAKPOINT) + sixth_call_bpt = target.BreakpointCreateByLocation( + 'pass-to-base.cpp', self.main_sixth_call_line) + self.assertTrue(sixth_call_bpt, + VALID_BREAKPOINT) + + # Now launch the process, and do not stop at the entry point. + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + + self.assertTrue(process.GetState() == lldb.eStateStopped, + PROCESS_STOPPED) + + b = self.frame().FindVariable("b").GetDynamicValue(lldb.eDynamicCanRunTarget) + self.assertTrue(b.GetNumChildren() == 0, "b has 0 children") + self.runCmd("continue") + self.assertTrue(b.GetNumChildren() == 0, "b still has 0 children") + self.runCmd("continue") + self.assertTrue(b.GetNumChildren() != 0, "b now has 1 child") + self.runCmd("continue") + self.assertTrue( + b.GetNumChildren() == 0, + "b didn't go back to 0 children") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/dynamic_value_child_count/pass-to-base.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/dynamic_value_child_count/pass-to-base.cpp new file mode 100644 index 00000000000..d9dd3529821 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/dynamic_value_child_count/pass-to-base.cpp @@ -0,0 +1,36 @@ +#include <stdio.h> +#include <memory> + +class BaseClass +{ +public: + BaseClass(); + virtual ~BaseClass() { } +}; + +class DerivedClass : public BaseClass +{ +public: + DerivedClass(); + virtual ~DerivedClass() { } +protected: + int mem; +}; + +BaseClass::BaseClass() +{ +} + +DerivedClass::DerivedClass() : BaseClass() +{ + mem = 101; +} + +int +main (int argc, char **argv) +{ + BaseClass *b = nullptr; // Break here and check b has 0 children + b = new DerivedClass(); // Break here and check b still has 0 children + b = nullptr; // Break here and check b has one child now + return 0; // Break here and check b has 0 children again +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/exec/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/exec/Makefile new file mode 100644 index 00000000000..afc520010ee --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/exec/Makefile @@ -0,0 +1,9 @@ +CXX_SOURCES := main.cpp + +all: secondprog + +include Makefile.rules + +secondprog: secondprog.cpp + $(MAKE) -f $(MAKEFILE_RULES) \ + CXX_SOURCES=secondprog.cpp EXE=secondprog diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/exec/TestExec.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/exec/TestExec.py new file mode 100644 index 00000000000..019df217713 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/exec/TestExec.py @@ -0,0 +1,113 @@ +""" +Test some lldb command abbreviations. +""" +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ExecTestCase(TestBase): + + NO_DEBUG_INFO_TESTCASE = True + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll(archs=['i386'], bugnumber="rdar://28656532") + @expectedFailureAll(oslist=["ios", "tvos", "watchos", "bridgeos"], bugnumber="rdar://problem/34559552") # this exec test has problems on ios systems + @expectedFailureNetBSD + @skipIfAsan # rdar://problem/43756823 + @skipIfWindows + def test_hitting_exec (self): + self.do_test(False) + + @expectedFailureAll(archs=['i386'], bugnumber="rdar://28656532") + @expectedFailureAll(oslist=["ios", "tvos", "watchos", "bridgeos"], bugnumber="rdar://problem/34559552") # this exec test has problems on ios systems + @expectedFailureNetBSD + @skipIfAsan # rdar://problem/43756823 + @skipIfWindows + def test_skipping_exec (self): + self.do_test(True) + + def do_test(self, skip_exec): + self.build() + exe = self.getBuildArtifact("a.out") + secondprog = self.getBuildArtifact("secondprog") + + # Create the target + target = self.dbg.CreateTarget(exe) + + # Create any breakpoints we need + breakpoint1 = target.BreakpointCreateBySourceRegex( + 'Set breakpoint 1 here', lldb.SBFileSpec("main.cpp", False)) + self.assertTrue(breakpoint1, VALID_BREAKPOINT) + breakpoint2 = target.BreakpointCreateBySourceRegex( + 'Set breakpoint 2 here', lldb.SBFileSpec("secondprog.cpp", False)) + self.assertTrue(breakpoint2, VALID_BREAKPOINT) + + # Launch the process + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + if self.TraceOn(): + self.runCmd("settings show target.process.stop-on-exec", check=False) + if skip_exec: + self.dbg.HandleCommand("settings set target.process.stop-on-exec false") + def cleanup(): + self.runCmd("settings set target.process.stop-on-exec false", + check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + # The stop reason of the thread should be breakpoint. + self.assertTrue(process.GetState() == lldb.eStateStopped, + STOPPED_DUE_TO_BREAKPOINT) + + threads = lldbutil.get_threads_stopped_at_breakpoint( + process, breakpoint1) + self.assertTrue(len(threads) == 1) + + # We had a deadlock tearing down the TypeSystemMap on exec, but only if some + # expression had been evaluated. So make sure we do that here so the teardown + # is not trivial. + + thread = threads[0] + value = thread.frames[0].EvaluateExpression("1 + 2") + self.assertTrue( + value.IsValid(), + "Expression evaluated successfully") + int_value = value.GetValueAsSigned() + self.assertTrue(int_value == 3, "Expression got the right result.") + + # Run and we should stop due to exec + process.Continue() + + if not skip_exec: + self.assertFalse(process.GetState() == lldb.eStateExited, + "Process should not have exited!") + self.assertTrue(process.GetState() == lldb.eStateStopped, + "Process should be stopped at __dyld_start") + + threads = lldbutil.get_stopped_threads( + process, lldb.eStopReasonExec) + self.assertTrue( + len(threads) == 1, + "We got a thread stopped for exec.") + + # Run and we should stop at breakpoint in main after exec + process.Continue() + + threads = lldbutil.get_threads_stopped_at_breakpoint( + process, breakpoint2) + if self.TraceOn(): + for t in process.threads: + print(t) + if t.GetStopReason() != lldb.eStopReasonBreakpoint: + self.runCmd("bt") + self.assertTrue(len(threads) == 1, + "Stopped at breakpoint in exec'ed process.") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/exec/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/exec/main.cpp new file mode 100644 index 00000000000..bec470fd13e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/exec/main.cpp @@ -0,0 +1,18 @@ +#define _POSIX_C_SOURCE 200809L + +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <libgen.h> +#include <string> +#include <unistd.h> + +int main(int argc, char const **argv) { + char *buf = strdup(argv[0]); // Set breakpoint 1 here + std::string directory_name(::dirname(buf)); + + std::string other_program = directory_name + "/secondprog"; + execve(other_program.c_str(), const_cast<char *const *>(argv), nullptr); + perror("execve"); + abort(); +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/exec/secondprog.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/exec/secondprog.cpp new file mode 100644 index 00000000000..5653471c153 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/exec/secondprog.cpp @@ -0,0 +1,5 @@ +#include <stdio.h> +int main () +{ + puts ("I am the second program."); // Set breakpoint 2 here +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/fat_archives/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/fat_archives/Makefile new file mode 100644 index 00000000000..7fed83dc9eb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/fat_archives/Makefile @@ -0,0 +1,15 @@ +SRCDIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))/ +all: a.c clean + $(CC) -arch i386 -g -c $(SRCDIR)/a.c + ar -q liba-i386.a a.o + ranlib liba-i386.a + $(CC) -arch x86_64 -g -c $(SRCDIR)/a.c + ar -q liba-x86_64.a a.o + ranlib liba-x86_64.a + lipo -create -output liba.a liba-i386.a liba-x86_64.a + $(CC) -g -c $(SRCDIR)/main.c + $(CC) -o a.out main.o -L. -la + +clean: + rm -rf a.o a.out liba-i386.a liba-x86_64.a liba.a $(wildcard *un~ .*un~ main.o *.pyc) + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/fat_archives/TestFatArchives.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/fat_archives/TestFatArchives.py new file mode 100644 index 00000000000..5fa52d31885 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/fat_archives/TestFatArchives.py @@ -0,0 +1,57 @@ +""" +Test some lldb command abbreviations. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class FatArchiveTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + @skipUnlessDarwin + def test_breakpoint_resolution_dwarf(self): + if self.getArchitecture() == 'x86_64': + self.build() + self.main() + else: + self.skipTest( + "This test requires x86_64 as the architecture for the inferior") + + def main(self): + '''This test compiles a quick example by making a fat file (universal) full of + skinny .o files and makes sure we can use them to resolve breakpoints when doing + DWARF in .o file debugging. The only thing this test needs to do is to compile and + set a breakpoint in the target and verify any breakpoint locations have valid debug + info for the function, and source file and line.''' + exe = self.getBuildArtifact("a.out") + + # Create the target + target = self.dbg.CreateTarget(exe) + + # Create a breakpoint by name + breakpoint = target.BreakpointCreateByName('foo', exe) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + # Make sure the breakpoint resolves to a function, file and line + for bp_loc in breakpoint: + # Get a section offset address (lldb.SBAddress) from the breakpoint + # location + bp_loc_addr = bp_loc.GetAddress() + line_entry = bp_loc_addr.GetLineEntry() + function = bp_loc_addr.GetFunction() + self.assertTrue( + function.IsValid(), + "Verify breakpoint in fat BSD archive has valid function debug info") + self.assertTrue( + line_entry.GetFileSpec(), + "Verify breakpoint in fat BSD archive has source file information") + self.assertTrue( + line_entry.GetLine() != 0, + "Verify breakpoint in fat BSD archive has source line information") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/fat_archives/a.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/fat_archives/a.c new file mode 100644 index 00000000000..c100f9a2c07 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/fat_archives/a.c @@ -0,0 +1,4 @@ +int foo () +{ + return 5; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/fat_archives/a.h b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/fat_archives/a.h new file mode 100644 index 00000000000..a4536647cfc --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/fat_archives/a.h @@ -0,0 +1 @@ +int foo (); diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/fat_archives/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/fat_archives/main.c new file mode 100644 index 00000000000..328319d4fb8 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/fat_archives/main.c @@ -0,0 +1,6 @@ +#include "a.h" +#include <stdio.h> +int main() +{ + printf ("%d\n", foo()); +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/float-display/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/float-display/Makefile new file mode 100644 index 00000000000..c9319d6e688 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/float-display/Makefile @@ -0,0 +1,2 @@ +C_SOURCES := main.c +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/float-display/TestFloatDisplay.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/float-display/TestFloatDisplay.py new file mode 100644 index 00000000000..48e49ed009b --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/float-display/TestFloatDisplay.py @@ -0,0 +1,5 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest( + __file__, globals(), []) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/float-display/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/float-display/main.c new file mode 100644 index 00000000000..7e89225a4cb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/float-display/main.c @@ -0,0 +1,121 @@ +float f_neg3 = 1.234567 / 1e3; +float f_neg4 = 1.234567 / 1e4; +float f_neg5 = 1.234567 / 1e5; +float f_neg6 = 1.234567 / 1e6; +float f_neg7 = 1.234567 / 1e7; +float f_neg8 = 1.234567 / 1e8; +float f_neg20 = 1.234567 / 1e20; +float f_neg30 = 1.234567 / 1e30; + +float f_3 = 1.234567 * 1e3; +float f_4 = 1.234567 * 1e4; +float f_5 = 1.234567 * 1e5; +float f_6 = 1.234567 * 1e6; +float f_7 = 1.234567 * 1e7; +float f_8 = 1.234567 * 1e8; +float f_20 = 1.234567 * 1e20; +float f_30 = 1.234567 * 1e30; + +double d_neg3 = 1.234567 / 1e3; +double d_neg4 = 1.234567 / 1e4; +double d_neg5 = 1.234567 / 1e5; +double d_neg6 = 1.234567 / 1e6; +double d_neg7 = 1.234567 / 1e7; +double d_neg8 = 1.234567 / 1e8; +double d_neg20 = 1.234567 / 1e20; +double d_neg30 = 1.234567 / 1e30; +double d_neg50 = 1.234567 / 1e50; +double d_neg250 = 1.234567 / 1e250; + +double d_3 = 1.234567 * 1e3; +double d_4 = 1.234567 * 1e4; +double d_5 = 1.234567 * 1e5; +double d_6 = 1.234567 * 1e6; +double d_7 = 1.234567 * 1e7; +double d_8 = 1.234567 * 1e8; +double d_20 = 1.234567 * 1e20; +double d_30 = 1.234567 * 1e30; +double d_50 = 1.234567 * 1e50; +double d_250 = 1.234567 * 1e250; + +int main (int argc, char const *argv[]) { + //% # Default setting should be 6. + //% self.expect("frame variable f_neg3", substrs=["0.00123456"]) + //% self.expect("frame variable f_neg4", substrs=["0.000123456"]) + //% self.expect("frame variable f_neg5", substrs=["0.0000123456"]) + //% self.expect("frame variable f_neg6", substrs=["0.00000123456"]) + //% self.expect("frame variable f_neg7", substrs=["1.234567", "E-7"]) + //% self.expect("frame variable f_neg8", substrs=["1.23456", "E-8"]) + //% self.expect("frame variable f_neg20", substrs=["E-20"]) + //% self.expect("frame variable f_neg30", substrs=["E-30"]) + //% self.expect("frame variable f_3", substrs=["1234.56"]) + //% self.expect("frame variable f_4", substrs=["12345.6"]) + //% self.expect("frame variable f_5", substrs=["123456"]) + //% self.expect("frame variable f_6", substrs=["123456"]) + //% self.expect("frame variable f_7", substrs=["123456"]) + //% self.expect("frame variable f_8", substrs=["123456"]) + //% self.expect("frame variable f_20", substrs=["E+20"]) + //% self.expect("frame variable f_30", substrs=["E+30"]) + //% self.expect("frame variable d_neg3", substrs=["0.00123456"]) + //% self.expect("frame variable d_neg4", substrs=["0.000123456"]) + //% self.expect("frame variable d_neg5", substrs=["0.0000123456"]) + //% self.expect("frame variable d_neg6", substrs=["0.00000123456"]) + //% self.expect("frame variable d_neg7", substrs=["1.23456", "E-7"]) + //% self.expect("frame variable d_neg8", substrs=["1.23456", "E-8"]) + //% self.expect("frame variable d_neg20", substrs=["1.23456", "E-20"]) + //% self.expect("frame variable d_neg30", substrs=["1.23456", "E-30"]) + //% self.expect("frame variable d_neg50", substrs=["1.23456", "E-50"]) + //% self.expect("frame variable d_neg250", substrs=["E-250"]) + //% self.expect("frame variable d_3", substrs=["1234.56"]) + //% self.expect("frame variable d_4", substrs=["12345.6"]) + //% self.expect("frame variable d_5", substrs=["123456"]) + //% self.expect("frame variable d_6", substrs=["1234567"]) + //% self.expect("frame variable d_7", substrs=["1234567"]) + //% self.expect("frame variable d_8", substrs=["1234567"]) + //% self.expect("frame variable d_20", substrs=["1.23456", "E+20"]) + //% self.expect("frame variable d_30", substrs=["1.23456", "E+30"]) + //% self.expect("frame variable d_50", substrs=["1.23456", "E+50"]) + //% self.expect("frame variable d_250", substrs=["1.23456", "E+250"]) + //% # Now change the setting to print all the zeroes. + //% # Note that changing this setting should invalidate the data visualizer + //% # cache so that the new setting is used in the following calls. + //% self.runCmd("settings set target.max-zero-padding-in-float-format 9999") + //% self.expect("frame variable f_neg3", substrs=["0.00123456"]) + //% self.expect("frame variable f_neg4", substrs=["0.000123456"]) + //% self.expect("frame variable f_neg5", substrs=["0.0000123456"]) + //% self.expect("frame variable f_neg6", substrs=["0.00000123456"]) + //% self.expect("frame variable f_neg7", substrs=["0.000000123456"]) + //% self.expect("frame variable f_neg8", substrs=["0.0000000123456"]) + //% self.expect("frame variable f_neg20", substrs=["0.0000000000000000000123456"]) + //% self.expect("frame variable f_neg30", substrs=["0.00000000000000000000000000000123456"]) + //% self.expect("frame variable f_3", substrs=["1234.56"]) + //% self.expect("frame variable f_4", substrs=["12345.6"]) + //% self.expect("frame variable f_5", substrs=["123456"]) + //% self.expect("frame variable f_6", substrs=["1234567"]) + //% self.expect("frame variable f_7", substrs=["1234567"]) + //% self.expect("frame variable f_8", substrs=["1234567"]) + //% self.expect("frame variable f_20", substrs=["E+20"]) + //% self.expect("frame variable f_30", substrs=["E+30"]) + //% self.expect("frame variable d_neg3", substrs=["0.00123456"]) + //% self.expect("frame variable d_neg4", substrs=["0.000123456"]) + //% self.expect("frame variable d_neg5", substrs=["0.0000123456"]) + //% self.expect("frame variable d_neg6", substrs=["0.00000123456"]) + //% self.expect("frame variable d_neg7", substrs=["0.000000123456"]) + //% self.expect("frame variable d_neg8", substrs=["0.0000000123456"]) + //% self.expect("frame variable d_neg20", substrs=["0.0000000000000000000123456"]) + //% self.expect("frame variable d_neg30", substrs=["0.000000000000000000000000000001234567"]) + //% self.expect("frame variable d_neg50", substrs=["0.0000000000000000000000000000000000000000000000000123456"]) + //% self.expect("frame variable d_neg250", substrs=["0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000123456"]) + //% self.expect("frame variable d_3", substrs=["1234.56"]) + //% self.expect("frame variable d_4", substrs=["12345.6"]) + //% self.expect("frame variable d_5", substrs=["123456"]) + //% self.expect("frame variable d_6", substrs=["1234567"]) + //% self.expect("frame variable d_7", substrs=["1234567"]) + //% self.expect("frame variable d_8", substrs=["1234567"]) + //% # Positive numbers are not affected by this setting. + //% self.expect("frame variable d_20", substrs=["1.23456", "E+20"]) + //% self.expect("frame variable d_30", substrs=["1.23456", "E+30"]) + //% self.expect("frame variable d_50", substrs=["1.23456", "E+50"]) + //% self.expect("frame variable d_250", substrs=["1.23456", "E+250"]) + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestArmRegisterDefinition.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestArmRegisterDefinition.py new file mode 100644 index 00000000000..28424f0f362 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestArmRegisterDefinition.py @@ -0,0 +1,131 @@ +from __future__ import print_function +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +from gdbclientutils import * + +class TestArmRegisterDefinition(GDBRemoteTestBase): + + @skipIfXmlSupportMissing + @skipIfRemote + def test(self): + """ + Test lldb's parsing of the <architecture> tag in the target.xml register + description packet. + """ + class MyResponder(MockGDBServerResponder): + + def qXferRead(self, obj, annex, offset, length): + if annex == "target.xml": + return """<?xml version="1.0"?> + <!DOCTYPE feature SYSTEM "gdb-target.dtd"> + <target> + <architecture>arm</architecture> + <feature name="org.gnu.gdb.arm.m-profile"> + <reg name="r0" bitsize="32" type="uint32" group="general"/> + <reg name="r1" bitsize="32" type="uint32" group="general"/> + <reg name="r2" bitsize="32" type="uint32" group="general"/> + <reg name="r3" bitsize="32" type="uint32" group="general"/> + <reg name="r4" bitsize="32" type="uint32" group="general"/> + <reg name="r5" bitsize="32" type="uint32" group="general"/> + <reg name="r6" bitsize="32" type="uint32" group="general"/> + <reg name="r7" bitsize="32" type="uint32" group="general"/> + <reg name="r8" bitsize="32" type="uint32" group="general"/> + <reg name="r9" bitsize="32" type="uint32" group="general"/> + <reg name="r10" bitsize="32" type="uint32" group="general"/> + <reg name="r11" bitsize="32" type="uint32" group="general"/> + <reg name="r12" bitsize="32" type="uint32" group="general"/> + <reg name="sp" bitsize="32" type="data_ptr" group="general"/> + <reg name="lr" bitsize="32" type="uint32" group="general"/> + <reg name="pc" bitsize="32" type="code_ptr" group="general"/> + <reg name="xpsr" bitsize="32" regnum="25" type="uint32" group="general"/> + <reg name="MSP" bitsize="32" regnum="26" type="uint32" group="general"/> + <reg name="PSP" bitsize="32" regnum="27" type="uint32" group="general"/> + <reg name="PRIMASK" bitsize="32" regnum="28" type="uint32" group="general"/> + <reg name="BASEPRI" bitsize="32" regnum="29" type="uint32" group="general"/> + <reg name="FAULTMASK" bitsize="32" regnum="30" type="uint32" group="general"/> + <reg name="CONTROL" bitsize="32" regnum="31" type="uint32" group="general"/> + <reg name="FPSCR" bitsize="32" type="uint32" group="float"/> + <reg name="s0" bitsize="32" type="float" group="float"/> + <reg name="s1" bitsize="32" type="float" group="float"/> + <reg name="s2" bitsize="32" type="float" group="float"/> + <reg name="s3" bitsize="32" type="float" group="float"/> + <reg name="s4" bitsize="32" type="float" group="float"/> + <reg name="s5" bitsize="32" type="float" group="float"/> + <reg name="s6" bitsize="32" type="float" group="float"/> + <reg name="s7" bitsize="32" type="float" group="float"/> + <reg name="s8" bitsize="32" type="float" group="float"/> + <reg name="s9" bitsize="32" type="float" group="float"/> + <reg name="s10" bitsize="32" type="float" group="float"/> + <reg name="s11" bitsize="32" type="float" group="float"/> + <reg name="s12" bitsize="32" type="float" group="float"/> + <reg name="s13" bitsize="32" type="float" group="float"/> + <reg name="s14" bitsize="32" type="float" group="float"/> + <reg name="s15" bitsize="32" type="float" group="float"/> + <reg name="s16" bitsize="32" type="float" group="float"/> + <reg name="s17" bitsize="32" type="float" group="float"/> + <reg name="s18" bitsize="32" type="float" group="float"/> + <reg name="s19" bitsize="32" type="float" group="float"/> + <reg name="s20" bitsize="32" type="float" group="float"/> + <reg name="s21" bitsize="32" type="float" group="float"/> + <reg name="s22" bitsize="32" type="float" group="float"/> + <reg name="s23" bitsize="32" type="float" group="float"/> + <reg name="s24" bitsize="32" type="float" group="float"/> + <reg name="s25" bitsize="32" type="float" group="float"/> + <reg name="s26" bitsize="32" type="float" group="float"/> + <reg name="s27" bitsize="32" type="float" group="float"/> + <reg name="s28" bitsize="32" type="float" group="float"/> + <reg name="s29" bitsize="32" type="float" group="float"/> + <reg name="s30" bitsize="32" type="float" group="float"/> + <reg name="s31" bitsize="32" type="float" group="float"/> + </feature> + </target>""", False + else: + return None, False + + def readRegister(self, regnum): + return "E01" + + def readRegisters(self): + return "20000000f8360020001000002fcb0008f8360020a0360020200c0020000000000000000000000000000000000000000000000000b87f0120b7d100082ed2000800000001b87f01200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + def haltReason(self): + return "S05" + + def qfThreadInfo(self): + return "mdead" + + def qC(self): + return "" + + def qSupported(self, client_supported): + return "PacketSize=4000;qXfer:memory-map:read-;QStartNoAckMode+;qXfer:threads:read+;hwbreak+;qXfer:features:read+" + + def QThreadSuffixSupported(self): + return "OK" + + def QListThreadsInStopReply(self): + return "OK" + + self.server.responder = MyResponder() + if self.TraceOn(): + self.runCmd("log enable gdb-remote packets") + self.addTearDownHook( + lambda: self.runCmd("log disable gdb-remote packets")) + + self.dbg.SetDefaultArchitecture("armv7em") + target = self.dbg.CreateTargetWithFileAndArch(None, None) + + process = self.connect(target) + + if self.TraceOn(): + interp = self.dbg.GetCommandInterpreter() + result = lldb.SBCommandReturnObject() + interp.HandleCommand("target list", result) + print(result.GetOutput()) + + r0_valobj = process.GetThreadAtIndex(0).GetFrameAtIndex(0).FindRegister("r0") + self.assertEqual(r0_valobj.GetValueAsUnsigned(), 0x20) + + pc_valobj = process.GetThreadAtIndex(0).GetFrameAtIndex(0).FindRegister("pc") + self.assertEqual(pc_valobj.GetValueAsUnsigned(), 0x0800d22e) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestGDBRemoteClient.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestGDBRemoteClient.py new file mode 100644 index 00000000000..8f0ed9a4933 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestGDBRemoteClient.py @@ -0,0 +1,127 @@ +import lldb +import binascii +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +from gdbclientutils import * + + +class TestGDBRemoteClient(GDBRemoteTestBase): + + class gPacketResponder(MockGDBServerResponder): + def readRegisters(self): + return '0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' + + def setUp(self): + super(TestGDBRemoteClient, self).setUp() + self._initial_platform = lldb.DBG.GetSelectedPlatform() + + def tearDown(self): + lldb.DBG.SetSelectedPlatform(self._initial_platform) + super(TestGDBRemoteClient, self).tearDown() + + def test_connect(self): + """Test connecting to a remote gdb server""" + target = self.createTarget("a.yaml") + process = self.connect(target) + self.assertPacketLogContains(["qProcessInfo", "qfThreadInfo"]) + + def test_attach_fail(self): + error_msg = "mock-error-msg" + + class MyResponder(MockGDBServerResponder): + # Pretend we don't have any process during the initial queries. + def qC(self): + return "E42" + + def qfThreadInfo(self): + return "OK" # No threads. + + # Then, when we are asked to attach, error out. + def vAttach(self, pid): + return "E42;" + binascii.hexlify(error_msg.encode()).decode() + + self.server.responder = MyResponder() + + target = self.dbg.CreateTarget("") + process = self.connect(target) + lldbutil.expect_state_changes(self, self.dbg.GetListener(), process, [lldb.eStateConnected]) + + error = lldb.SBError() + target.AttachToProcessWithID(lldb.SBListener(), 47, error) + self.assertEquals(error_msg, error.GetCString()) + + def test_read_registers_using_g_packets(self): + """Test reading registers using 'g' packets (default behavior)""" + self.dbg.HandleCommand( + "settings set plugin.process.gdb-remote.use-g-packet-for-reading true") + self.addTearDownHook(lambda: + self.runCmd("settings set plugin.process.gdb-remote.use-g-packet-for-reading false")) + self.server.responder = self.gPacketResponder() + target = self.createTarget("a.yaml") + process = self.connect(target) + + self.assertEquals(1, self.server.responder.packetLog.count("g")) + self.server.responder.packetLog = [] + self.read_registers(process) + # Reading registers should not cause any 'p' packets to be exchanged. + self.assertEquals( + 0, len([p for p in self.server.responder.packetLog if p.startswith("p")])) + + def test_read_registers_using_p_packets(self): + """Test reading registers using 'p' packets""" + self.dbg.HandleCommand( + "settings set plugin.process.gdb-remote.use-g-packet-for-reading false") + target = self.createTarget("a.yaml") + process = self.connect(target) + + self.read_registers(process) + self.assertFalse("g" in self.server.responder.packetLog) + self.assertGreater( + len([p for p in self.server.responder.packetLog if p.startswith("p")]), 0) + + def test_write_registers_using_P_packets(self): + """Test writing registers using 'P' packets (default behavior)""" + self.server.responder = self.gPacketResponder() + target = self.createTarget("a.yaml") + process = self.connect(target) + + self.write_registers(process) + self.assertEquals(0, len( + [p for p in self.server.responder.packetLog if p.startswith("G")])) + self.assertGreater( + len([p for p in self.server.responder.packetLog if p.startswith("P")]), 0) + + def test_write_registers_using_G_packets(self): + """Test writing registers using 'G' packets""" + + class MyResponder(self.gPacketResponder): + def readRegister(self, register): + # empty string means unsupported + return "" + + self.server.responder = MyResponder() + target = self.createTarget("a.yaml") + process = self.connect(target) + + self.write_registers(process) + self.assertEquals(0, len( + [p for p in self.server.responder.packetLog if p.startswith("P")])) + self.assertGreater(len( + [p for p in self.server.responder.packetLog if p.startswith("G")]), 0) + + def read_registers(self, process): + self.for_each_gpr( + process, lambda r: self.assertEquals("0x00000000", r.GetValue())) + + def write_registers(self, process): + self.for_each_gpr( + process, lambda r: r.SetValueFromCString("0x00000000")) + + def for_each_gpr(self, process, operation): + registers = process.GetThreadAtIndex(0).GetFrameAtIndex(0).GetRegisters() + self.assertGreater(registers.GetSize(), 0) + regSet = registers[0] + numChildren = regSet.GetNumChildren() + self.assertGreater(numChildren, 0) + for i in range(numChildren): + operation(regSet.GetChildAtIndex(i)) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestGDBRemoteLoad.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestGDBRemoteLoad.py new file mode 100644 index 00000000000..f70c854ed6d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestGDBRemoteLoad.py @@ -0,0 +1,80 @@ +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +from gdbclientutils import * + + +class TestGDBRemoteLoad(GDBRemoteTestBase): + + def setUp(self): + super(TestGDBRemoteLoad, self).setUp() + self._initial_platform = lldb.DBG.GetSelectedPlatform() + + def tearDown(self): + lldb.DBG.SetSelectedPlatform(self._initial_platform) + super(TestGDBRemoteLoad, self).tearDown() + + def test_module_load_address(self): + """Test that setting the load address of a module uses virtual addresses""" + target = self.createTarget("a.yaml") + process = self.connect(target) + module = target.GetModuleAtIndex(0) + self.assertTrue(module.IsValid()) + self.assertTrue(target.SetModuleLoadAddress(module, 0).Success()) + address = target.ResolveLoadAddress(0x2001) + self.assertTrue(address.IsValid()) + self.assertEqual(".data", address.GetSection().GetName()) + + def test_ram_load(self): + """Test loading an object file to a target's ram""" + target = self.createTarget("a.yaml") + process = self.connect(target) + self.dbg.HandleCommand("target modules load -l -s0") + self.assertPacketLogContains([ + "M1000,4:c3c3c3c3", + "M1004,2:3232" + ]) + + @skipIfXmlSupportMissing + def test_flash_load(self): + """Test loading an object file to a target's flash memory""" + + class Responder(MockGDBServerResponder): + def qSupported(self, client_supported): + return "PacketSize=3fff;QStartNoAckMode+;qXfer:memory-map:read+" + + def qXferRead(self, obj, annex, offset, length): + if obj == "memory-map": + return (self.MEMORY_MAP[offset:offset + length], + offset + length < len(self.MEMORY_MAP)) + return None, False + + def other(self, packet): + if packet[0:11] == "vFlashErase": + return "OK" + if packet[0:11] == "vFlashWrite": + return "OK" + if packet == "vFlashDone": + return "OK" + return "" + + MEMORY_MAP = """<?xml version="1.0"?> +<memory-map> + <memory type="ram" start="0x0" length="0x1000"/> + <memory type="flash" start="0x1000" length="0x1000"> + <property name="blocksize">0x100</property> + </memory> + <memory type="ram" start="0x2000" length="0x1D400"/> +</memory-map> +""" + + self.server.responder = Responder() + target = self.createTarget("a.yaml") + process = self.connect(target) + self.dbg.HandleCommand("target modules load -l -s0") + self.assertPacketLogContains([ + "vFlashErase:1000,100", + "vFlashWrite:1000:\xc3\xc3\xc3\xc3", + "vFlashWrite:1004:\x32\x32", + "vFlashDone" + ]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestJLink6Armv7RegisterDefinition.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestJLink6Armv7RegisterDefinition.py new file mode 100644 index 00000000000..f0113fd9908 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestJLink6Armv7RegisterDefinition.py @@ -0,0 +1,196 @@ +from __future__ import print_function +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +from gdbclientutils import * + +class TestJLink6Armv7RegisterDefinition(GDBRemoteTestBase): + + @skipIfXmlSupportMissing + @skipIfRemote + def test(self): + """ + Test lldb's parsing of SEGGER J-Link v6.54 register + definition for a Cortex M-4 dev board, and the fact + that the J-Link only supports g/G for reading/writing + register AND the J-Link v6.54 doesn't provide anything + but the general purpose registers.""" + class MyResponder(MockGDBServerResponder): + + def qXferRead(self, obj, annex, offset, length): + if annex == "target.xml": + return """<?xml version="1.0"?> +<!-- Copyright (C) 2008 Free Software Foundation, Inc. + + Copying and distribution of this file, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. --> + +<!DOCTYPE feature SYSTEM "gdb-target.dtd"> +<target version="1.0"> + <architecture>arm</architecture> + <feature name="org.gnu.gdb.arm.m-profile"> + <reg name="r0" bitsize="32" regnum="0" type="uint32" group="general"/> + <reg name="r1" bitsize="32" regnum="1" type="uint32" group="general"/> + <reg name="r2" bitsize="32" regnum="2" type="uint32" group="general"/> + <reg name="r3" bitsize="32" regnum="3" type="uint32" group="general"/> + <reg name="r4" bitsize="32" regnum="4" type="uint32" group="general"/> + <reg name="r5" bitsize="32" regnum="5" type="uint32" group="general"/> + <reg name="r6" bitsize="32" regnum="6" type="uint32" group="general"/> + <reg name="r7" bitsize="32" regnum="7" type="uint32" group="general"/> + <reg name="r8" bitsize="32" regnum="8" type="uint32" group="general"/> + <reg name="r9" bitsize="32" regnum="9" type="uint32" group="general"/> + <reg name="r10" bitsize="32" regnum="10" type="uint32" group="general"/> + <reg name="r11" bitsize="32" regnum="11" type="uint32" group="general"/> + <reg name="r12" bitsize="32" regnum="12" type="uint32" group="general"/> + <reg name="sp" bitsize="32" regnum="13" type="data_ptr" group="general"/> + <reg name="lr" bitsize="32" regnum="14" type="uint32" group="general"/> + <reg name="pc" bitsize="32" regnum="15" type="code_ptr" group="general"/> + <reg name="xpsr" bitsize="32" regnum="25" type="uint32" group="general"/> + </feature> + <feature name="org.gnu.gdb.arm.m-system"> + <reg name="msp" bitsize="32" regnum="26" type="uint32" group="general"/> + <reg name="psp" bitsize="32" regnum="27" type="uint32" group="general"/> + <reg name="primask" bitsize="32" regnum="28" type="uint32" group="general"/> + <reg name="basepri" bitsize="32" regnum="29" type="uint32" group="general"/> + <reg name="faultmask" bitsize="32" regnum="30" type="uint32" group="general"/> + <reg name="control" bitsize="32" regnum="31" type="uint32" group="general"/> + </feature> + <feature name="org.gnu.gdb.arm.m-float"> + <reg name="fpscr" bitsize="32" regnum="32" type="uint32" group="float"/> + <reg name="s0" bitsize="32" regnum="33" type="float" group="float"/> + <reg name="s1" bitsize="32" regnum="34" type="float" group="float"/> + <reg name="s2" bitsize="32" regnum="35" type="float" group="float"/> + <reg name="s3" bitsize="32" regnum="36" type="float" group="float"/> + <reg name="s4" bitsize="32" regnum="37" type="float" group="float"/> + <reg name="s5" bitsize="32" regnum="38" type="float" group="float"/> + <reg name="s6" bitsize="32" regnum="39" type="float" group="float"/> + <reg name="s7" bitsize="32" regnum="40" type="float" group="float"/> + <reg name="s8" bitsize="32" regnum="41" type="float" group="float"/> + <reg name="s9" bitsize="32" regnum="42" type="float" group="float"/> + <reg name="s10" bitsize="32" regnum="43" type="float" group="float"/> + <reg name="s11" bitsize="32" regnum="44" type="float" group="float"/> + <reg name="s12" bitsize="32" regnum="45" type="float" group="float"/> + <reg name="s13" bitsize="32" regnum="46" type="float" group="float"/> + <reg name="s14" bitsize="32" regnum="47" type="float" group="float"/> + <reg name="s15" bitsize="32" regnum="48" type="float" group="float"/> + <reg name="s16" bitsize="32" regnum="49" type="float" group="float"/> + <reg name="s17" bitsize="32" regnum="50" type="float" group="float"/> + <reg name="s18" bitsize="32" regnum="51" type="float" group="float"/> + <reg name="s19" bitsize="32" regnum="52" type="float" group="float"/> + <reg name="s20" bitsize="32" regnum="53" type="float" group="float"/> + <reg name="s21" bitsize="32" regnum="54" type="float" group="float"/> + <reg name="s22" bitsize="32" regnum="55" type="float" group="float"/> + <reg name="s23" bitsize="32" regnum="56" type="float" group="float"/> + <reg name="s24" bitsize="32" regnum="57" type="float" group="float"/> + <reg name="s25" bitsize="32" regnum="58" type="float" group="float"/> + <reg name="s26" bitsize="32" regnum="59" type="float" group="float"/> + <reg name="s27" bitsize="32" regnum="60" type="float" group="float"/> + <reg name="s28" bitsize="32" regnum="61" type="float" group="float"/> + <reg name="s29" bitsize="32" regnum="62" type="float" group="float"/> + <reg name="s30" bitsize="32" regnum="63" type="float" group="float"/> + <reg name="s31" bitsize="32" regnum="64" type="float" group="float"/> + <reg name="d0" bitsize="64" regnum="65" type="ieee_double" group="float"/> + <reg name="d1" bitsize="64" regnum="66" type="ieee_double" group="float"/> + <reg name="d2" bitsize="64" regnum="67" type="ieee_double" group="float"/> + <reg name="d3" bitsize="64" regnum="68" type="ieee_double" group="float"/> + <reg name="d4" bitsize="64" regnum="69" type="ieee_double" group="float"/> + <reg name="d5" bitsize="64" regnum="70" type="ieee_double" group="float"/> + <reg name="d6" bitsize="64" regnum="71" type="ieee_double" group="float"/> + <reg name="d7" bitsize="64" regnum="72" type="ieee_double" group="float"/> + <reg name="d8" bitsize="64" regnum="73" type="ieee_double" group="float"/> + <reg name="d9" bitsize="64" regnum="74" type="ieee_double" group="float"/> + <reg name="d10" bitsize="64" regnum="75" type="ieee_double" group="float"/> + <reg name="d11" bitsize="64" regnum="76" type="ieee_double" group="float"/> + <reg name="d12" bitsize="64" regnum="77" type="ieee_double" group="float"/> + <reg name="d13" bitsize="64" regnum="78" type="ieee_double" group="float"/> + <reg name="d14" bitsize="64" regnum="79" type="ieee_double" group="float"/> + <reg name="d15" bitsize="64" regnum="80" type="ieee_double" group="float"/> + </feature> +</target>""", False + else: + return None, False + + def readRegister(self, regnum): + return "E01" + + # Initial r1 bytes, in little-endian order + r1_bytes = "01000000" + + ## readRegisters only provides reg values up through xpsr (0x61000000) + ## it doesn't send up any of the exception registers or floating point + ## registers that the above register xml describes. + def readRegisters(self): + return "00000000" + self.r1_bytes + "010000000100000001000000000000008c080020a872012000000000a0790120000000008065012041ad0008a0720120692a00089e26000800000061" + + ## the J-Link accepts a register write packet with just the GPRs + ## defined. + def writeRegisters(self, registers_hex): + # Check that lldb returns the full 704 hex-byte register context, + # or the 136 hex-byte general purpose register reg ctx. + if len(registers_hex) != 704 and len(register_hex) != 136: + return "E06" + if registers_hex.startswith("0000000044332211010000000100000001000000000000008c080020a872012000000000a0790120000000008065012041ad0008a0720120692a00089e26000800000061"): + self.r1_bytes = "44332211" + return "OK" + else: + return "E07" + + def haltReason(self): + return "S05" + + def qfThreadInfo(self): + return "mdead" + + def qC(self): + return "" + + def qSupported(self, client_supported): + return "PacketSize=4000;qXfer:memory-map:read-;QStartNoAckMode+;hwbreak+;qXfer:features:read+" + + def QThreadSuffixSupported(self): + return "OK" + + def QListThreadsInStopReply(self): + return "OK" + + self.server.responder = MyResponder() + if self.TraceOn(): + self.runCmd("log enable gdb-remote packets") + self.addTearDownHook( + lambda: self.runCmd("log disable gdb-remote packets")) + + self.dbg.SetDefaultArchitecture("armv7em") + target = self.dbg.CreateTargetWithFileAndArch(None, None) + + process = self.connect(target) + + if self.TraceOn(): + interp = self.dbg.GetCommandInterpreter() + result = lldb.SBCommandReturnObject() + interp.HandleCommand("target list", result) + print(result.GetOutput()) + + r1_valobj = process.GetThreadAtIndex(0).GetFrameAtIndex(0).FindRegister("r1") + self.assertEqual(r1_valobj.GetValueAsUnsigned(), 1) + + pc_valobj = process.GetThreadAtIndex(0).GetFrameAtIndex(0).FindRegister("pc") + self.assertEqual(pc_valobj.GetValueAsUnsigned(), 0x0800269e) + + xpsr_valobj = process.GetThreadAtIndex(0).GetFrameAtIndex(0).FindRegister("xpsr") + self.assertEqual(xpsr_valobj.GetValueAsUnsigned(), 0x61000000) + + msp_valobj = process.GetThreadAtIndex(0).GetFrameAtIndex(0).FindRegister("msp") + err = msp_valobj.GetError() + self.assertTrue(err.Fail(), "lldb should not be able to fetch the msp register") + + val = b'\x11\x22\x33\x44' + error = lldb.SBError() + data = lldb.SBData() + data.SetData(error, val, lldb.eByteOrderBig, 4) + self.assertEqual(r1_valobj.SetData(data, error), True) + self.assertTrue(error.Success()) + + r1_valobj = process.GetThreadAtIndex(0).GetFrameAtIndex(0).FindRegister("r1") + self.assertEqual(r1_valobj.GetValueAsUnsigned(), 0x11223344) + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestNestedRegDefinitions.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestNestedRegDefinitions.py new file mode 100644 index 00000000000..4407e867e70 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestNestedRegDefinitions.py @@ -0,0 +1,238 @@ +from __future__ import print_function +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +from gdbclientutils import * + +class TestNestedRegDefinitions(GDBRemoteTestBase): + + @skipIfXmlSupportMissing + @skipIfRemote + def test(self): + """ + Test lldb's parsing of the <architecture> tag in the target.xml register + description packet. + """ + class MyResponder(MockGDBServerResponder): + + def qXferRead(self, obj, annex, offset, length): + if annex == "target.xml": + return """<?xml version="1.0"?><!DOCTYPE target SYSTEM "gdb-target.dtd"><target><architecture>i386:x86-64</architecture><xi:include href="i386-64bit.xml"/></target>""", False + + if annex == "i386-64bit.xml": + return """<?xml version="1.0"?> +<!-- Copyright (C) 2010-2017 Free Software Foundation, Inc. + + Copying and distribution of this file, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. --> + +<!-- I386 64bit --> + +<!DOCTYPE target SYSTEM "gdb-target.dtd"> +<feature name="org.gnu.gdb.i386.64bit"> + <xi:include href="i386-64bit-core.xml"/> + <xi:include href="i386-64bit-sse.xml"/> +</feature>""", False + + if annex == "i386-64bit-core.xml": + return """<?xml version="1.0"?> +<!-- Copyright (C) 2010-2015 Free Software Foundation, Inc. + + Copying and distribution of this file, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. --> + +<!DOCTYPE feature SYSTEM "gdb-target.dtd"> +<feature name="org.gnu.gdb.i386.core"> + <flags id="i386_eflags" size="4"> + <field name="CF" start="0" end="0"/> + <field name="" start="1" end="1"/> + <field name="PF" start="2" end="2"/> + <field name="AF" start="4" end="4"/> + <field name="ZF" start="6" end="6"/> + <field name="SF" start="7" end="7"/> + <field name="TF" start="8" end="8"/> + <field name="IF" start="9" end="9"/> + <field name="DF" start="10" end="10"/> + <field name="OF" start="11" end="11"/> + <field name="NT" start="14" end="14"/> + <field name="RF" start="16" end="16"/> + <field name="VM" start="17" end="17"/> + <field name="AC" start="18" end="18"/> + <field name="VIF" start="19" end="19"/> + <field name="VIP" start="20" end="20"/> + <field name="ID" start="21" end="21"/> + </flags> + + <reg name="rax" bitsize="64" type="int64"/> + <reg name="rbx" bitsize="64" type="int64"/> + <reg name="rcx" bitsize="64" type="int64"/> + <reg name="rdx" bitsize="64" type="int64"/> + <reg name="rsi" bitsize="64" type="int64"/> + <reg name="rdi" bitsize="64" type="int64"/> + <reg name="rbp" bitsize="64" type="data_ptr"/> + <reg name="rsp" bitsize="64" type="data_ptr"/> + <reg name="r8" bitsize="64" type="int64"/> + <reg name="r9" bitsize="64" type="int64"/> + <reg name="r10" bitsize="64" type="int64"/> + <reg name="r11" bitsize="64" type="int64"/> + <reg name="r12" bitsize="64" type="int64"/> + <reg name="r13" bitsize="64" type="int64"/> + <reg name="r14" bitsize="64" type="int64"/> + <reg name="r15" bitsize="64" type="int64"/> + + <reg name="rip" bitsize="64" type="code_ptr"/> + <reg name="eflags" bitsize="32" type="i386_eflags"/> + <reg name="cs" bitsize="32" type="int32"/> + <reg name="ss" bitsize="32" type="int32"/> + <reg name="ds" bitsize="32" type="int32"/> + <reg name="es" bitsize="32" type="int32"/> + <reg name="fs" bitsize="32" type="int32"/> + <reg name="gs" bitsize="32" type="int32"/> + + <reg name="st0" bitsize="80" type="i387_ext"/> + <reg name="st1" bitsize="80" type="i387_ext"/> + <reg name="st2" bitsize="80" type="i387_ext"/> + <reg name="st3" bitsize="80" type="i387_ext"/> + <reg name="st4" bitsize="80" type="i387_ext"/> + <reg name="st5" bitsize="80" type="i387_ext"/> + <reg name="st6" bitsize="80" type="i387_ext"/> + <reg name="st7" bitsize="80" type="i387_ext"/> + + <reg name="fctrl" bitsize="32" type="int" group="float"/> + <reg name="fstat" bitsize="32" type="int" group="float"/> + <reg name="ftag" bitsize="32" type="int" group="float"/> + <reg name="fiseg" bitsize="32" type="int" group="float"/> + <reg name="fioff" bitsize="32" type="int" group="float"/> + <reg name="foseg" bitsize="32" type="int" group="float"/> + <reg name="fooff" bitsize="32" type="int" group="float"/> + <reg name="fop" bitsize="32" type="int" group="float"/> +</feature>""", False + + if annex == "i386-64bit-sse.xml": + return """<?xml version="1.0"?> +<!-- Copyright (C) 2010-2017 Free Software Foundation, Inc. + + Copying and distribution of this file, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. --> + +<!DOCTYPE feature SYSTEM "gdb-target.dtd"> +<feature name="org.gnu.gdb.i386.64bit.sse"> + <vector id="v4f" type="ieee_single" count="4"/> + <vector id="v2d" type="ieee_double" count="2"/> + <vector id="v16i8" type="int8" count="16"/> + <vector id="v8i16" type="int16" count="8"/> + <vector id="v4i32" type="int32" count="4"/> + <vector id="v2i64" type="int64" count="2"/> + <union id="vec128"> + <field name="v4_float" type="v4f"/> + <field name="v2_double" type="v2d"/> + <field name="v16_int8" type="v16i8"/> + <field name="v8_int16" type="v8i16"/> + <field name="v4_int32" type="v4i32"/> + <field name="v2_int64" type="v2i64"/> + <field name="uint128" type="uint128"/> + </union> + <flags id="i386_mxcsr" size="4"> + <field name="IE" start="0" end="0"/> + <field name="DE" start="1" end="1"/> + <field name="ZE" start="2" end="2"/> + <field name="OE" start="3" end="3"/> + <field name="UE" start="4" end="4"/> + <field name="PE" start="5" end="5"/> + <field name="DAZ" start="6" end="6"/> + <field name="IM" start="7" end="7"/> + <field name="DM" start="8" end="8"/> + <field name="ZM" start="9" end="9"/> + <field name="OM" start="10" end="10"/> + <field name="UM" start="11" end="11"/> + <field name="PM" start="12" end="12"/> + <field name="FZ" start="15" end="15"/> + </flags> + + <reg name="xmm0" bitsize="128" type="vec128" regnum="40"/> + <reg name="xmm1" bitsize="128" type="vec128"/> + <reg name="xmm2" bitsize="128" type="vec128"/> + <reg name="xmm3" bitsize="128" type="vec128"/> + <reg name="xmm4" bitsize="128" type="vec128"/> + <reg name="xmm5" bitsize="128" type="vec128"/> + <reg name="xmm6" bitsize="128" type="vec128"/> + <reg name="xmm7" bitsize="128" type="vec128"/> + <reg name="xmm8" bitsize="128" type="vec128"/> + <reg name="xmm9" bitsize="128" type="vec128"/> + <reg name="xmm10" bitsize="128" type="vec128"/> + <reg name="xmm11" bitsize="128" type="vec128"/> + <reg name="xmm12" bitsize="128" type="vec128"/> + <reg name="xmm13" bitsize="128" type="vec128"/> + <reg name="xmm14" bitsize="128" type="vec128"/> + <reg name="xmm15" bitsize="128" type="vec128"/> + + <reg name="mxcsr" bitsize="32" type="i386_mxcsr" group="vector"/> +</feature>""", False + + return None, False + + def readRegister(self, regnum): + return "" + + def readRegisters(self): + return "0600000000000000c0b7c00080fffffff021c60080ffffff1a00000000000000020000000000000078b7c00080ffffff203f8ca090ffffff103f8ca090ffffff3025990a80ffffff809698000000000070009f0a80ffffff020000000000000000eae10080ffffff00000000000000001822d74f1a00000078b7c00080ffffff0e12410080ffff004602000008000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007f0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000801f0000" + + def haltReason(self): + return "T02thread:dead;threads:dead;" + + def qfThreadInfo(self): + return "mdead" + + def qC(self): + return "" + + def qSupported(self, client_supported): + return "PacketSize=4000;qXfer:features:read+" + + def QThreadSuffixSupported(self): + return "OK" + + def QListThreadsInStopReply(self): + return "OK" + + self.server.responder = MyResponder() + if self.TraceOn(): + self.runCmd("log enable gdb-remote packets") + self.addTearDownHook( + lambda: self.runCmd("log disable gdb-remote packets")) + + target = self.dbg.CreateTargetWithFileAndArch(None, None) + + process = self.connect(target) + + if self.TraceOn(): + interp = self.dbg.GetCommandInterpreter() + result = lldb.SBCommandReturnObject() + interp.HandleCommand("target list", result) + print(result.GetOutput()) + + rip_valobj = process.GetThreadAtIndex(0).GetFrameAtIndex(0).FindRegister("rip") + self.assertEqual(rip_valobj.GetValueAsUnsigned(), 0x00ffff800041120e) + + r15_valobj = process.GetThreadAtIndex(0).GetFrameAtIndex(0).FindRegister("r15") + self.assertEqual(r15_valobj.GetValueAsUnsigned(), 0xffffff8000c0b778) + + mxcsr_valobj = process.GetThreadAtIndex(0).GetFrameAtIndex(0).FindRegister("mxcsr") + self.assertEqual(mxcsr_valobj.GetValueAsUnsigned(), 0x00001f80) + + gpr_reg_set_name = process.GetThreadAtIndex(0).GetFrameAtIndex(0).GetRegisters().GetValueAtIndex(0).GetName() + self.assertEqual(gpr_reg_set_name, "general") + + float_reg_set_name = process.GetThreadAtIndex(0).GetFrameAtIndex(0).GetRegisters().GetValueAtIndex(1).GetName() + self.assertEqual(float_reg_set_name, "float") + + vector_reg_set_name = process.GetThreadAtIndex(0).GetFrameAtIndex(0).GetRegisters().GetValueAtIndex(2).GetName() + self.assertEqual(vector_reg_set_name, "vector") + + if self.TraceOn(): + print("rip is 0x%x" % rip_valobj.GetValueAsUnsigned()) + print("r15 is 0x%x" % r15_valobj.GetValueAsUnsigned()) + print("mxcsr is 0x%x" % mxcsr_valobj.GetValueAsUnsigned()) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestNoGPacketSupported.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestNoGPacketSupported.py new file mode 100644 index 00000000000..6a17173cba4 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestNoGPacketSupported.py @@ -0,0 +1,96 @@ +from __future__ import print_function +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +from gdbclientutils import * + + +# This test case is testing three things: +# +# 1. three register values will be provided in the ? stop packet (T11) - +# registers 0 ("rax"), 1 ("rbx"), and 3 ("rip") +# 2. ReadRegister packet will provide the value of register 2 ("rsi") +# 3. The "g" read-all-registers packet is not supported; p must be used +# to get the value of register 2 ("rsi") +# +# Forcing lldb to use the expedited registers in the stop packet and +# marking it an error to request that register value is to prevent +# performance regressions. +# +# Some gdb RSP stubs only implement p/P, they do not support g/G. +# lldb must be able to work with either. + +class TestNoGPacketSupported(GDBRemoteTestBase): + + @skipIfXmlSupportMissing + def test(self): + class MyResponder(MockGDBServerResponder): + def haltReason(self): + return "T02thread:1ff0d;threads:1ff0d;thread-pcs:000000010001bc00;00:7882773ce0ffffff;01:1122334455667788;03:00bc010001000000;" + + def threadStopInfo(self, threadnum): + return "T02thread:1ff0d;threads:1ff0d;thread-pcs:000000010001bc00;00:7882773ce0ffffff;01:1122334455667788;03:00bc010001000000;" + + def writeRegisters(self): + return "E02" + + def readRegisters(self): + return "E01" + + def readRegister(self, regnum): + # lldb will try sending "p0" to see if the p packet is supported, + # give a bogus value; in theory lldb could use this value in the + # register context and that would be valid behavior. + + # notably, don't give values for registers 1 & 3 -- lldb should + # get those from the ? stop packet ("T11") and it is a pref regression + # if lldb is asking for these register values. + if regnum == 0: + return "5555555555555555" + if regnum == 2: + return "c04825ebfe7f0000" # 0x00007ffeeb2548c0 + + return "E03" + + def writeRegister(self, regnum): + return "OK" + + def qXferRead(self, obj, annex, offset, length): + if annex == "target.xml": + return """<?xml version="1.0"?> + <target version="1.0"> + <architecture>i386:x86-64</architecture> + <feature name="org.gnu.gdb.i386.core"> + <reg name="rax" bitsize="64" regnum="0" type="code_ptr" group="general"/> + <reg name="rbx" bitsize="64" regnum="1" type="code_ptr" group="general"/> + <reg name="rsi" bitsize="64" regnum="2" type="code_ptr" group="general"/> + <reg name="rip" bitsize="64" regnum="3" type="code_ptr" group="general" altname="pc" generic="pc"/> + </feature> + </target>""", False + else: + return None, False + + self.server.responder = MyResponder() + target = self.dbg.CreateTarget('') + if self.TraceOn(): + self.runCmd("log enable gdb-remote packets") + self.addTearDownHook( + lambda: self.runCmd("log disable gdb-remote packets")) + process = self.connect(target) + + thread = process.GetThreadAtIndex(0) + frame = thread.GetFrameAtIndex(0) + rax = frame.FindRegister("rax").GetValueAsUnsigned() + rbx = frame.FindRegister("rbx").GetValueAsUnsigned() + rsi = frame.FindRegister("rsi").GetValueAsUnsigned() + pc = frame.GetPC() + rip = frame.FindRegister("rip").GetValueAsUnsigned() + + if self.TraceOn(): + print("Register values: rax == 0x%x, rbx == 0x%x, rsi == 0x%x, pc == 0x%x, rip == 0x%x" % (rax, rbx, rsi, pc, rip)) + + self.assertEqual(rax, 0xffffffe03c778278) + self.assertEqual(rbx, 0x8877665544332211) + self.assertEqual(rsi, 0x00007ffeeb2548c0) + self.assertEqual(pc, 0x10001bc00) + self.assertEqual(rip, 0x10001bc00) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestNoWatchpointSupportInfo.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestNoWatchpointSupportInfo.py new file mode 100644 index 00000000000..3bf22d376b2 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestNoWatchpointSupportInfo.py @@ -0,0 +1,66 @@ +from __future__ import print_function +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +from gdbclientutils import * + +class TestNoWatchpointSupportInfo(GDBRemoteTestBase): + + @skipIfXmlSupportMissing + @skipIfRemote + def test(self): + """ + Test lldb's parsing of the <architecture> tag in the target.xml register + description packet. + """ + class MyResponder(MockGDBServerResponder): + + def haltReason(self): + return "T02thread:1ff0d;thread-pcs:10001bc00;" + + def threadStopInfo(self, threadnum): + if threadnum == 0x1ff0d: + return "T02thread:1ff0d;thread-pcs:10001bc00;" + return "" + + def setBreakpoint(self, packet): + if packet.startswith("Z2,"): + return "OK" + + def qXferRead(self, obj, annex, offset, length): + if annex == "target.xml": + return """<?xml version="1.0"?> + <target version="1.0"> + <architecture>i386:x86-64</architecture> + <feature name="org.gnu.gdb.i386.core"> + <reg name="rip" bitsize="64" regnum="0" type="code_ptr" group="general"/> + </feature> + </target>""", False + else: + return None, False + + self.server.responder = MyResponder() + if self.TraceOn(): + self.runCmd("log enable gdb-remote packets") + self.addTearDownHook( + lambda: self.runCmd("log disable gdb-remote packets")) + self.dbg.SetDefaultArchitecture("x86_64") + target = self.dbg.CreateTargetWithFileAndArch(None, None) + + process = self.connect(target) + + if self.TraceOn(): + interp = self.dbg.GetCommandInterpreter() + result = lldb.SBCommandReturnObject() + interp.HandleCommand("target list", result) + print(result.GetOutput()) + + + err = lldb.SBError() + wp = target.WatchAddress(0x100, 8, False, True, err) + if self.TraceOn() and (err.Fail() or wp.IsValid == False): + strm = lldb.SBStream() + err.GetDescription(strm) + print("watchpoint failed: %s" % strm.GetData()) + self.assertTrue(wp.IsValid()) + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestPlatformClient.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestPlatformClient.py new file mode 100644 index 00000000000..2da8dd59e17 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestPlatformClient.py @@ -0,0 +1,67 @@ +import lldb +import binascii +import os +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +from gdbclientutils import * + +def hexlify(string): + return binascii.hexlify(string.encode()).decode() + +class TestPlatformClient(GDBRemoteTestBase): + + def test_process_list_with_all_users(self): + """Test connecting to a remote linux platform""" + + class MyResponder(MockGDBServerResponder): + def __init__(self): + MockGDBServerResponder.__init__(self) + self.currentQsProc = 0 + self.all_users = False + + def qfProcessInfo(self, packet): + if "all_users:1" in packet: + self.all_users = True + name = hexlify("/a/test_process") + args = "-".join(map(hexlify, + ["/system/bin/sh", "-c", "/data/local/tmp/lldb-server"])) + return "pid:10;ppid:1;uid:2;gid:3;euid:4;egid:5;name:" + name + ";args:" + args + ";" + else: + self.all_users = False + return "E04" + + def qsProcessInfo(self): + if self.all_users: + if self.currentQsProc == 0: + self.currentQsProc = 1 + name = hexlify("/b/another_test_process") + # This intentionally has a badly encoded argument + args = "X".join(map(hexlify, + ["/system/bin/ls", "--help"])) + return "pid:11;ppid:2;uid:3;gid:4;euid:5;egid:6;name:" + name + ";args:" + args + ";" + elif self.currentQsProc == 1: + self.currentQsProc = 0 + return "E04" + else: + return "E04" + + self.server.responder = MyResponder() + + try: + self.runCmd("platform select remote-linux") + self.runCmd("platform connect connect://localhost:%d" % + self.server.port) + self.assertTrue(self.dbg.GetSelectedPlatform().IsConnected()) + self.expect("platform process list -x", + substrs=["2 matching processes were found", "test_process", "another_test_process"]) + self.expect("platform process list -xv", + substrs=[ + "PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE ARGUMENTS", + "10 1 2 3 4 5 /system/bin/sh -c /data/local/tmp/lldb-server", + "11 2 3 4 5 6"]) + self.expect("platform process list -xv", substrs=["/system/bin/ls"], matching=False) + self.expect("platform process list", + error=True, + substrs=["error: no processes were found on the \"remote-linux\" platform"]) + finally: + self.dbg.GetSelectedPlatform().DisconnectRemote() diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestRecognizeBreakpoint.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestRecognizeBreakpoint.py new file mode 100644 index 00000000000..44e2cfa891a --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestRecognizeBreakpoint.py @@ -0,0 +1,139 @@ +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +from gdbclientutils import * + + +class TestRecognizeBreakpoint(GDBRemoteTestBase): + """ This tests the case where the gdb-remote server doesn't support any + of the thread-info packets, and just tells which thread got the stop + signal with: + T05thread:01; + There was a bug in lldb that we would set the stop reason from this + packet too early - before we had updated the thread list. So when we + later updated the thread list, we would throw away this info. Normally + we would be able to reconstruct it from the thread info, but not if the + stub doesn't support it """ + + @skipIfXmlSupportMissing + def test(self): + class MyResponder(MockGDBServerResponder): + def __init__(self): + MockGDBServerResponder.__init__(self) + self.thread_info_count = 0 + self.after_cont = False + self.current_thread = 0 + + def cont(self): + # Simulate process stopping due to a breakpoint: + self.after_cont = True + return "T05thread:01;" + + def vCont(self, packet): + self.after_cont = True + return "T05thread:01;" + + def haltReason(self): + return "T02thread:01;" + + def threadStopInfo(self, num): + return "" + + def QThreadSuffixSupported(self): + return "" + + def QListThreadsInStopReply(self): + return "" + + def setBreakpoint(self, packet): + return "OK" + + def qfThreadInfo(self): + return "m1" + + def qsThreadInfo(self): + if (self.thread_info_count % 2) == 0: + str = "m2" + else: + str = "l" + self.thread_info_count += 1 + return str + + def readRegisters(self): + if self.after_cont and self.current_thread == 1: + return "c01e990080ffffff" + else: + return "badcfe10325476980" + + def readRegister(self, regno): + return "" + + def qXferRead(self, obj, annex, offset, length): + if annex == "target.xml": + return """<?xml version="1.0"?> + <target version="1.0"> + <architecture>i386:x86-64</architecture> + <feature name="org.gnu.gdb.i386.core"> + <reg name="rip" bitsize="64" regnum="0" type="code_ptr" group="general"/> + </feature> + </target>""", False + else: + return None, False + + def selectThread(self, op, thread): + if op != 'g': + return '' + + self.current_thread = thread + return "OK" + + def other (self, packet): + if packet == "vCont?": + return "vCont;c;C;s;S" + return '' + + python_os_plugin_path = os.path.join(self.getSourceDir(), + 'operating_system_2.py') + command ="settings set target.process.python-os-plugin-path '{}'".format( + python_os_plugin_path) + self.runCmd(command) + + self.server.responder = MyResponder() + target = self.dbg.CreateTarget("") + process = self.connect(target) + + bkpt = target.BreakpointCreateByAddress(0xffffff8000991ec0) + self.assertEqual(bkpt.GetNumLocations(), 1, "Fake breakpoint was resolved.") + + # Get the initial stop, and we should have two threads. + num_threads = len(process.threads) + self.assertEqual(num_threads, 2, "Got two threads") + + thread_0 = process.threads[0] + self.assertEqual(thread_0.GetStopReason(), 1, "Thread_0 stopped for no reason") + self.assertEqual(thread_0.GetName(), "one", "Thread_0 is called one") + + thread_1 = process.threads[1] + self.assertEqual(thread_1.GetStopReason(), 5, "Thread_0 stopped for SIGSTOP") + self.assertEqual(thread_1.GetName(), "two", "Thread_0 is called two") + + # Now continue and we will fake hitting a breakpoint. + process.Continue() + + self.assertEqual(process.GetState(),lldb.eStateStopped, "Process is stopped") + num_threads = len(process.threads) + + num_threads = len(process.threads) + self.assertEqual(num_threads, 2, "Got two threads") + + thread_0 = process.threads[0] + self.assertEqual(thread_0.GetStopReason(), 1, "Thread_0 stopped for no reason") + self.assertEqual(thread_0.GetName(), "one", "Thread_0 is called one") + + thread_1 = process.threads[1] + self.assertEqual(thread_1.GetStopReason(), 3, "Thread_0 stopped for SIGTRAP") + self.assertEqual(thread_1.GetName(), "three", "Thread_0 is called three") + + self.assertTrue(thread_1.IsValid(), "Thread_1 is valid") + self.assertEqual(thread_1.GetStopReason(), lldb.eStopReasonBreakpoint, "Stopped at breakpoint") + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestRegDefinitionInParts.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestRegDefinitionInParts.py new file mode 100644 index 00000000000..c4ba19cc2b6 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestRegDefinitionInParts.py @@ -0,0 +1,160 @@ +from __future__ import print_function +import lldb +import time +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +from gdbclientutils import * + +class TestRegDefinitionInParts(GDBRemoteTestBase): + + @skipIfXmlSupportMissing + @skipIfRemote + def test(self): + """ + Test that lldb correctly fetches the target definition file + in multiple chunks if the remote server only provides the + content in small parts, and the small parts it provides is + smaller than the maximum packet size that it declared at + the start of the debug session. qemu does this. + """ + class MyResponder(MockGDBServerResponder): + + def qXferRead(self, obj, annex, offset, length): + if annex == "target.xml": + return """<?xml version="1.0"?> + <!DOCTYPE feature SYSTEM "gdb-target.dtd"> + <target version="1.0"> + <architecture>i386:x86-64</architecture> + <xi:include href="i386-64bit-core.xml"/> + </target>""", False + + if annex == "i386-64bit-core.xml" and offset == 0: + return """<?xml version="1.0"?> +<!-- Copyright (C) 2010-2015 Free Software Foundation, Inc. + + Copying and distribution of this file, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. --> + +<!DOCTYPE feature SYSTEM "gdb-target.dtd"> +<feature name="org.gnu.gdb.i386.core"> + <flags id="i386_eflags" size="4"> + <field name="CF" start="0" end="0"/> + <field name="" start="1" end="1"/> + <field name="PF" start="2" end="2"/> + <field name="AF" start="4" end="4"/> + <field name="ZF" start="6" end="6"/> + <field name="SF" start="7" end="7"/> + <field name="TF" start="8" end="8"/> + <field name="IF" start="9" end="9"/> + <field name="DF" start="10" end="10"/> + <field name="OF" start="11" end="11"/> + <field name="NT" start="14" end="14"/> + <field name="RF" start="16" end="16"/> + <field name="VM" start="17" end="17"/> + <field name="AC" start="18" end="18"/> + <field name="VIF" start="19" end="19"/> + <field name="VIP" start="20" end="20"/> + <field name="ID" start="21" end="21"/> + </flags> + + <reg name="rax" bitsize="64" type="int64"/> + <reg name="rbx" bitsize="64" type="int64"/> + <reg name="rcx" bitsize="64" type="int64"/> + <reg name="rdx" bitsize="64" type="int64"/> + <reg name="rsi" bitsize="64" type="int64"/> + <reg name="rdi" bitsize="64" type="int64"/> + <reg name="rbp" bitsize="64" type="data_ptr"/> + <reg name="rsp" bitsize="64" type="data_ptr"/> + <reg name="r8" bitsize="64" type="int64"/> + <reg name="r9" bitsize="64" type="int64"/> + <reg name="r10" bitsize="64" type="int64"/> + <reg name="r11" bitsize="64" type="int64"/> + <reg name="r12" bitsize="64" type="int64"/> + <reg name="r13" bitsize="64" type="int64"/> + <reg name="r14" bitsize="64" type="int64"/> + <reg name="r15" bitsize="64" type="int64"/> + + <reg name="rip" bitsize="64" type="code_ptr"/> + <reg name="eflags" bitsize="32" type="i386_eflags"/> + <reg name="cs" bitsize="32" type="int32"/> + <reg name="ss" bitsize="32" ty""", True + + if annex == "i386-64bit-core.xml" and offset == 2045: + return """pe="int32"/> + <reg name="ds" bitsize="32" type="int32"/> + <reg name="es" bitsize="32" type="int32"/> + <reg name="fs" bitsize="32" type="int32"/> + <reg name="gs" bitsize="32" type="int32"/> + + <reg name="st0" bitsize="80" type="i387_ext"/> + <reg name="st1" bitsize="80" type="i387_ext"/> + <reg name="st2" bitsize="80" type="i387_ext"/> + <reg name="st3" bitsize="80" type="i387_ext"/> + <reg name="st4" bitsize="80" type="i387_ext"/> + <reg name="st5" bitsize="80" type="i387_ext"/> + <reg name="st6" bitsize="80" type="i387_ext"/> + <reg name="st7" bitsize="80" type="i387_ext"/> + + <reg name="fctrl" bitsize="32" type="int" group="float"/> + <reg name="fstat" bitsize="32" type="int" group="float"/> + <reg name="ftag" bitsize="32" type="int" group="float"/> + <reg name="fiseg" bitsize="32" type="int" group="float"/> + <reg name="fioff" bitsize="32" type="int" group="float"/> + <reg name="foseg" bitsize="32" type="int" group="float"/> + <reg name="fooff" bitsize="32" type="int" group="float"/> + <reg name="fop" bitsize="32" type="int" group="float"/> +</feature>""", False + + return None, False + + def readRegister(self, regnum): + return "" + + def readRegisters(self): + return "0600000000000000c0b7c00080fffffff021c60080ffffff1a00000000000000020000000000000078b7c00080ffffff203f8ca090ffffff103f8ca090ffffff3025990a80ffffff809698000000000070009f0a80ffffff020000000000000000eae10080ffffff00000000000000001822d74f1a00000078b7c00080ffffff0e12410080ffff004602000011111111222222223333333300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007f0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000801f0000" + + def haltReason(self): + return "T02thread:dead;threads:dead;" + + def qfThreadInfo(self): + return "mdead" + + def qC(self): + return "" + + def qSupported(self, client_supported): + return "PacketSize=1000;qXfer:features:read+" + + def QThreadSuffixSupported(self): + return "OK" + + def QListThreadsInStopReply(self): + return "OK" + + self.server.responder = MyResponder() + if self.TraceOn(): + self.runCmd("log enable gdb-remote packets") + time.sleep(10) + self.addTearDownHook( + lambda: self.runCmd("log disable gdb-remote packets")) + + target = self.dbg.CreateTargetWithFileAndArch(None, None) + + process = self.connect(target) + + if self.TraceOn(): + interp = self.dbg.GetCommandInterpreter() + result = lldb.SBCommandReturnObject() + interp.HandleCommand("target list", result) + print(result.GetOutput()) + + rip_valobj = process.GetThreadAtIndex(0).GetFrameAtIndex(0).FindRegister("rip") + self.assertEqual(rip_valobj.GetValueAsUnsigned(), 0x00ffff800041120e) + + ss_valobj = process.GetThreadAtIndex(0).GetFrameAtIndex(0).FindRegister("ss") + self.assertEqual(ss_valobj.GetValueAsUnsigned(), 0x22222222) + + if self.TraceOn(): + print("rip is 0x%x" % rip_valobj.GetValueAsUnsigned()) + print("ss is 0x%x" % ss_valobj.GetValueAsUnsigned()) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestRestartBug.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestRestartBug.py new file mode 100644 index 00000000000..142861a37df --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestRestartBug.py @@ -0,0 +1,62 @@ +from __future__ import print_function +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +from gdbclientutils import * + + +class TestRestartBug(GDBRemoteTestBase): + + @expectedFailureAll(bugnumber="llvm.org/pr24530") + def test(self): + """ + Test auto-continue behavior when a process is interrupted to deliver + an "asynchronous" packet. This simulates the situation when a process + stops on its own just as lldb client is about to interrupt it. The + client should not auto-continue in this case, unless the user has + explicitly requested that we ignore signals of this type. + """ + class MyResponder(MockGDBServerResponder): + continueCount = 0 + + def setBreakpoint(self, packet): + return "OK" + + def interrupt(self): + # Simulate process stopping due to a raise(SIGINT) just as lldb + # is about to interrupt it. + return "T02reason:signal" + + def cont(self): + self.continueCount += 1 + if self.continueCount == 1: + # No response, wait for the client to interrupt us. + return None + return "W00" # Exit + + self.server.responder = MyResponder() + target = self.createTarget("a.yaml") + process = self.connect(target) + self.dbg.SetAsync(True) + process.Continue() + + # resume the process and immediately try to set another breakpoint. When using the remote + # stub, this will trigger a request to stop the process. Make sure we + # do not lose this signal. + bkpt = target.BreakpointCreateByAddress(0x1234) + self.assertTrue(bkpt.IsValid()) + self.assertEqual(bkpt.GetNumLocations(), 1) + + event = lldb.SBEvent() + while self.dbg.GetListener().WaitForEvent(2, event): + if self.TraceOn(): + print("Process changing state to:", + self.dbg.StateAsCString(process.GetStateFromEvent(event))) + if process.GetStateFromEvent(event) == lldb.eStateExited: + break + + # We should get only one continue packet as the client should not + # auto-continue after setting the breakpoint. + self.assertEqual(self.server.responder.continueCount, 1) + # And the process should end up in the stopped state. + self.assertEqual(process.GetState(), lldb.eStateStopped) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestStopPCs.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestStopPCs.py new file mode 100644 index 00000000000..c86d3e75fe8 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestStopPCs.py @@ -0,0 +1,47 @@ +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +from gdbclientutils import * + + +class TestStopPCs(GDBRemoteTestBase): + + @skipIfXmlSupportMissing + def test(self): + class MyResponder(MockGDBServerResponder): + def haltReason(self): + return "T02thread:1ff0d;threads:1ff0d,2ff0d;thread-pcs:10001bc00,10002bc00;" + + def threadStopInfo(self, threadnum): + if threadnum == 0x1ff0d: + return "T02thread:1ff0d;threads:1ff0d,2ff0d;thread-pcs:10001bc00,10002bc00;" + if threadnum == 0x2ff0d: + return "T00thread:2ff0d;threads:1ff0d,2ff0d;thread-pcs:10001bc00,10002bc00;" + + def qXferRead(self, obj, annex, offset, length): + if annex == "target.xml": + return """<?xml version="1.0"?> + <target version="1.0"> + <architecture>i386:x86-64</architecture> + <feature name="org.gnu.gdb.i386.core"> + <reg name="rip" bitsize="64" regnum="0" type="code_ptr" group="general"/> + </feature> + </target>""", False + else: + return None, False + + self.server.responder = MyResponder() + target = self.dbg.CreateTarget('') + if self.TraceOn(): + self.runCmd("log enable gdb-remote packets") + self.addTearDownHook( + lambda: self.runCmd("log disable gdb-remote packets")) + process = self.connect(target) + + self.assertEqual(process.GetNumThreads(), 2) + th0 = process.GetThreadAtIndex(0) + th1 = process.GetThreadAtIndex(1) + self.assertEqual(th0.GetThreadID(), 0x1ff0d) + self.assertEqual(th1.GetThreadID(), 0x2ff0d) + self.assertEqual(th0.GetFrameAtIndex(0).GetPC(), 0x10001bc00) + self.assertEqual(th1.GetFrameAtIndex(0).GetPC(), 0x10002bc00) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestTargetXMLArch.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestTargetXMLArch.py new file mode 100644 index 00000000000..20e575ae978 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestTargetXMLArch.py @@ -0,0 +1,145 @@ +from __future__ import print_function +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +from gdbclientutils import * + +class MyResponder(MockGDBServerResponder): + def qXferRead(self, obj, annex, offset, length): + if annex == "target.xml": + return """<?xml version="1.0"?> + <target version="1.0"> + <architecture>i386:x86-64</architecture> + <feature name="org.gnu.gdb.i386.core"> + + <flags id="i386_eflags" size="4"> + <field name="CF" start="0" end="0"/> + <field name="" start="1" end="1"/> + <field name="PF" start="2" end="2"/> + <field name="AF" start="4" end="4"/> + <field name="ZF" start="6" end="6"/> + <field name="SF" start="7" end="7"/> + <field name="TF" start="8" end="8"/> + <field name="IF" start="9" end="9"/> + <field name="DF" start="10" end="10"/> + <field name="OF" start="11" end="11"/> + <field name="NT" start="14" end="14"/> + <field name="RF" start="16" end="16"/> + <field name="VM" start="17" end="17"/> + <field name="AC" start="18" end="18"/> + <field name="VIF" start="19" end="19"/> + <field name="VIP" start="20" end="20"/> + <field name="ID" start="21" end="21"/> + </flags> + + <reg name="rax" bitsize="64" regnum="0" type="int" group="general"/> + <reg name="rbx" bitsize="64" regnum="1" type="int" group="general"/> + <reg name="rcx" bitsize="64" regnum="2" type="int" group="general"/> + <reg name="rdx" bitsize="64" regnum="3" type="int" group="general"/> + <reg name="rsi" bitsize="64" regnum="4" type="int" group="general"/> + <reg name="rdi" bitsize="64" regnum="5" type="int" group="general"/> + <reg name="rbp" bitsize="64" regnum="6" type="data_ptr" group="general"/> + <reg name="rsp" bitsize="64" regnum="7" type="data_ptr" group="general"/> + <reg name="r8" bitsize="64" regnum="8" type="int" group="general"/> + <reg name="r9" bitsize="64" regnum="9" type="int" group="general"/> + <reg name="r10" bitsize="64" regnum="10" type="int" group="general"/> + <reg name="r11" bitsize="64" regnum="11" type="int" group="general"/> + <reg name="r12" bitsize="64" regnum="12" type="int" group="general"/> + <reg name="r13" bitsize="64" regnum="13" type="int" group="general"/> + <reg name="r14" bitsize="64" regnum="14" type="int" group="general"/> + <reg name="r15" bitsize="64" regnum="15" type="int" group="general"/> + <reg name="rip" bitsize="64" regnum="16" type="code_ptr" group="general"/> + <reg name="eflags" bitsize="32" regnum="17" type="i386_eflags" group="general"/> + + <reg name="cs" bitsize="32" regnum="18" type="int" group="general"/> + <reg name="ss" bitsize="32" regnum="19" type="int" group="general"/> + <reg name="ds" bitsize="32" regnum="20" type="int" group="general"/> + <reg name="es" bitsize="32" regnum="21" type="int" group="general"/> + <reg name="fs" bitsize="32" regnum="22" type="int" group="general"/> + <reg name="gs" bitsize="32" regnum="23" type="int" group="general"/> + + <reg name="st0" bitsize="80" regnum="24" type="i387_ext" group="float"/> + <reg name="st1" bitsize="80" regnum="25" type="i387_ext" group="float"/> + <reg name="st2" bitsize="80" regnum="26" type="i387_ext" group="float"/> + <reg name="st3" bitsize="80" regnum="27" type="i387_ext" group="float"/> + <reg name="st4" bitsize="80" regnum="28" type="i387_ext" group="float"/> + <reg name="st5" bitsize="80" regnum="29" type="i387_ext" group="float"/> + <reg name="st6" bitsize="80" regnum="30" type="i387_ext" group="float"/> + <reg name="st7" bitsize="80" regnum="31" type="i387_ext" group="float"/> + + <reg name="fctrl" bitsize="32" regnum="32" type="int" group="float"/> + <reg name="fstat" bitsize="32" regnum="33" type="int" group="float"/> + <reg name="ftag" bitsize="32" regnum="34" type="int" group="float"/> + <reg name="fiseg" bitsize="32" regnum="35" type="int" group="float"/> + <reg name="fioff" bitsize="32" regnum="36" type="int" group="float"/> + <reg name="foseg" bitsize="32" regnum="37" type="int" group="float"/> + <reg name="fooff" bitsize="32" regnum="38" type="int" group="float"/> + <reg name="fop" bitsize="32" regnum="39" type="int" group="float"/> + </feature> + </target>""", False + else: + return None, False + + def qC(self): + return "QC1" + + def haltReason(self): + return "T05thread:00000001;06:9038d60f00700000;07:98b4062680ffffff;10:c0d7bf1b80ffffff;" + + def readRegister(self, register): + regs = {0x0: "00b0060000610000", + 0xa: "68fe471c80ffffff", + 0xc: "60574a1c80ffffff", + 0xd: "18f3042680ffffff", + 0xe: "be8a4d7142000000", + 0xf: "50df471c80ffffff", + 0x10: "c0d7bf1b80ffffff" } + if register in regs: + return regs[register] + else: + return "0000000000000000" + +class TestTargetXMLArch(GDBRemoteTestBase): + + @skipIfXmlSupportMissing + @expectedFailureAll(archs=["i386"]) + @skipIfRemote + def test(self): + """ + Test lldb's parsing of the <architecture> tag in the target.xml register + description packet. + """ + self.server.responder = MyResponder() + interp = self.dbg.GetCommandInterpreter() + result = lldb.SBCommandReturnObject() + if self.TraceOn(): + self.runCmd("log enable gdb-remote packets") + self.addTearDownHook( + lambda: self.runCmd("log disable gdb-remote packets")) + + target = self.dbg.CreateTarget('') + self.assertEqual('', target.GetTriple()) + process = self.connect(target) + if self.TraceOn(): + interp.HandleCommand("target list", result) + print(result.GetOutput()) + self.assertTrue(target.GetTriple().startswith('x86_64-unknown-unknown')) + + @skipIfXmlSupportMissing + @skipIfRemote + def test_register_augmentation(self): + """ + Test that we correctly associate the register info with the eh_frame + register numbers. + """ + + target = self.createTarget("basic_eh_frame.yaml") + self.server.responder = MyResponder() + + process = self.connect(target) + lldbutil.expect_state_changes(self, self.dbg.GetListener(), process, + [lldb.eStateStopped]) + self.filecheck("image show-unwind -n foo", __file__, + "--check-prefix=UNWIND") +# UNWIND: eh_frame UnwindPlan: +# UNWIND: row[0]: 0: CFA=rsp+128 => rip=[CFA-8] diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestThreadSelectionBug.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestThreadSelectionBug.py new file mode 100644 index 00000000000..09022028524 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestThreadSelectionBug.py @@ -0,0 +1,49 @@ +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +from gdbclientutils import * + + +class TestThreadSelectionBug(GDBRemoteTestBase): + def test(self): + class MyResponder(MockGDBServerResponder): + def cont(self): + # Simulate process stopping due to a raise(SIGINT) + return "T01reason:signal" + + self.server.responder = MyResponder() + target = self.createTarget("a.yaml") + process = self.connect(target) + python_os_plugin_path = os.path.join(self.getSourceDir(), + 'operating_system.py') + command = "settings set target.process.python-os-plugin-path '{}'".format( + python_os_plugin_path) + self.dbg.HandleCommand(command) + + self.assertTrue(process, PROCESS_IS_VALID) + self.assertEqual(process.GetNumThreads(), 3) + + # Verify our OS plug-in threads showed up + thread = process.GetThreadByID(0x1) + self.assertTrue( + thread.IsValid(), + "Make sure there is a thread 0x1 after we load the python OS plug-in") + thread = process.GetThreadByID(0x2) + self.assertTrue( + thread.IsValid(), + "Make sure there is a thread 0x2 after we load the python OS plug-in") + thread = process.GetThreadByID(0x3) + self.assertTrue( + thread.IsValid(), + "Make sure there is a thread 0x3 after we load the python OS plug-in") + + # Verify that a thread other than 3 is selected. + thread = process.GetSelectedThread() + self.assertNotEqual(thread.GetThreadID(), 0x3) + + # Verify that we select the thread backed by physical thread 1, rather + # than virtual thread 1. The mapping comes from the OS plugin, where we + # specified that thread 3 is backed by real thread 1. + process.Continue() + thread = process.GetSelectedThread() + self.assertEqual(thread.GetThreadID(), 0x3) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestWriteMemory.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestWriteMemory.py new file mode 100644 index 00000000000..b7f19a16bf3 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestWriteMemory.py @@ -0,0 +1,37 @@ +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +from gdbclientutils import * + + +class TestWriteMemory(GDBRemoteTestBase): + + def setUp(self): + super(TestWriteMemory, self).setUp() + self._initial_platform = lldb.DBG.GetSelectedPlatform() + + def tearDown(self): + lldb.DBG.SetSelectedPlatform(self._initial_platform) + super(TestWriteMemory, self).tearDown() + + + def test(self): + + class MyResponder(MockGDBServerResponder): + def setBreakpoint(self, packet): + return "OK" + + self.server.responder = MyResponder() + target = self.dbg.CreateTargetWithFileAndTargetTriple('', 'x86_64-pc-linux') + process = self.connect(target) + + bp = target.BreakpointCreateByAddress(0x1000) + self.assertTrue(bp.IsValid()) + self.assertEqual(bp.GetNumLocations(), 1) + bp.SetEnabled(True) + self.assertTrue(bp.IsEnabled()) + + err = lldb.SBError() + data = str("\x01\x02\x03\x04") + result = process.WriteMemory(0x1000, data, err) + self.assertEqual(result, 4) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/a.yaml b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/a.yaml new file mode 100644 index 00000000000..f4e9ff5d872 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/a.yaml @@ -0,0 +1,34 @@ +!ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_ARM +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x1000 + AddressAlign: 0x4 + Content: "c3c3c3c3" + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Address: 0x2000 + AddressAlign: 0x4 + Content: "3232" +ProgramHeaders: + - Type: PT_LOAD + Flags: [ PF_X, PF_R ] + VAddr: 0x1000 + PAddr: 0x1000 + Align: 0x4 + Sections: + - Section: .text + - Type: PT_LOAD + Flags: [ PF_R, PF_W ] + VAddr: 0x2000 + PAddr: 0x1004 + Align: 0x4 + Sections: + - Section: .data diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/basic_eh_frame.yaml b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/basic_eh_frame.yaml new file mode 100644 index 00000000000..384b9b992b4 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/basic_eh_frame.yaml @@ -0,0 +1,48 @@ +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 + Entry: 0x0000000000401000 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x0000000000401000 + AddressAlign: 0x0000000000000001 + Content: C3 + - Name: .eh_frame + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Address: 0x0000000000402000 + AddressAlign: 0x0000000000000008 + Content: 1800000000000000017A5200017810011B0C070890010E80010000001000000020000000DCEFFFFF0100000000000000 +Symbols: + - Name: .text + Type: STT_SECTION + Section: .text + Value: 0x0000000000401000 + - Name: .eh_frame + Type: STT_SECTION + Section: .eh_frame + Value: 0x0000000000402000 + - Name: _start + Binding: STB_GLOBAL + - Name: __bss_start + Section: .eh_frame + Binding: STB_GLOBAL + Value: 0x0000000000404000 + - Name: foo + Section: .text + Binding: STB_GLOBAL + Value: 0x0000000000401000 + - Name: _edata + Section: .eh_frame + Binding: STB_GLOBAL + Value: 0x0000000000404000 + - Name: _end + Section: .eh_frame + Binding: STB_GLOBAL + Value: 0x0000000000404000 +... diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/gdbclientutils.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/gdbclientutils.py new file mode 100644 index 00000000000..392aeba5bd6 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/gdbclientutils.py @@ -0,0 +1,534 @@ +import os +import os.path +import threading +import socket +import lldb +import binascii +import traceback +from lldbsuite.support import seven +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbtest_config + + +def checksum(message): + """ + Calculate the GDB server protocol checksum of the message. + + The GDB server protocol uses a simple modulo 256 sum. + """ + check = 0 + for c in message: + check += ord(c) + return check % 256 + + +def frame_packet(message): + """ + Create a framed packet that's ready to send over the GDB connection + channel. + + Framing includes surrounding the message between $ and #, and appending + a two character hex checksum. + """ + return "$%s#%02x" % (message, checksum(message)) + + +def escape_binary(message): + """ + Escape the binary message using the process described in the GDB server + protocol documentation. + + Most bytes are sent through as-is, but $, #, and { are escaped by writing + a { followed by the original byte mod 0x20. + """ + out = "" + for c in message: + d = ord(c) + if d in (0x23, 0x24, 0x7d): + out += chr(0x7d) + out += chr(d ^ 0x20) + else: + out += c + return out + + +def hex_encode_bytes(message): + """ + Encode the binary message by converting each byte into a two-character + hex string. + """ + out = "" + for c in message: + out += "%02x" % ord(c) + return out + + +def hex_decode_bytes(hex_bytes): + """ + Decode the hex string into a binary message by converting each two-character + hex string into a single output byte. + """ + out = "" + hex_len = len(hex_bytes) + while i < hex_len - 1: + out += chr(int(hex_bytes[i:i + 2]), 16) + i += 2 + return out + + +class MockGDBServerResponder: + """ + A base class for handling client packets and issuing server responses for + GDB tests. + + This handles many typical situations, while still allowing subclasses to + completely customize their responses. + + Most subclasses will be interested in overriding the other() method, which + handles any packet not recognized in the common packet handling code. + """ + + registerCount = 40 + packetLog = None + + def __init__(self): + self.packetLog = [] + + def respond(self, packet): + """ + Return the unframed packet data that the server should issue in response + to the given packet received from the client. + """ + self.packetLog.append(packet) + if packet is MockGDBServer.PACKET_INTERRUPT: + return self.interrupt() + if packet == "c": + return self.cont() + if packet.startswith("vCont;c"): + return self.vCont(packet) + if packet[0] == "g": + return self.readRegisters() + if packet[0] == "G": + # Gxxxxxxxxxxx + # Gxxxxxxxxxxx;thread:1234; + return self.writeRegisters(packet[1:].split(';')[0]) + if packet[0] == "p": + regnum = packet[1:].split(';')[0] + return self.readRegister(int(regnum, 16)) + if packet[0] == "P": + register, value = packet[1:].split("=") + return self.writeRegister(int(register, 16), value) + if packet[0] == "m": + addr, length = [int(x, 16) for x in packet[1:].split(',')] + return self.readMemory(addr, length) + if packet[0] == "M": + location, encoded_data = packet[1:].split(":") + addr, length = [int(x, 16) for x in location.split(',')] + return self.writeMemory(addr, encoded_data) + if packet[0:7] == "qSymbol": + return self.qSymbol(packet[8:]) + if packet[0:10] == "qSupported": + return self.qSupported(packet[11:].split(";")) + if packet == "qfThreadInfo": + return self.qfThreadInfo() + if packet == "qsThreadInfo": + return self.qsThreadInfo() + if packet == "qC": + return self.qC() + if packet == "QEnableErrorStrings": + return self.QEnableErrorStrings() + if packet == "?": + return self.haltReason() + if packet == "s": + return self.haltReason() + if packet[0] == "H": + return self.selectThread(packet[1], int(packet[2:], 16)) + if packet[0:6] == "qXfer:": + obj, read, annex, location = packet[6:].split(":") + offset, length = [int(x, 16) for x in location.split(',')] + data, has_more = self.qXferRead(obj, annex, offset, length) + if data is not None: + return self._qXferResponse(data, has_more) + return "" + if packet.startswith("vAttach;"): + pid = packet.partition(';')[2] + return self.vAttach(int(pid, 16)) + if packet[0] == "Z": + return self.setBreakpoint(packet) + if packet.startswith("qThreadStopInfo"): + threadnum = int (packet[15:], 16) + return self.threadStopInfo(threadnum) + if packet == "QThreadSuffixSupported": + return self.QThreadSuffixSupported() + if packet == "QListThreadsInStopReply": + return self.QListThreadsInStopReply() + if packet.startswith("qMemoryRegionInfo:"): + return self.qMemoryRegionInfo() + if packet == "qQueryGDBServer": + return self.qQueryGDBServer() + if packet == "qHostInfo": + return self.qHostInfo() + if packet == "qGetWorkingDir": + return self.qGetWorkingDir() + if packet == "qsProcessInfo": + return self.qsProcessInfo() + if packet.startswith("qfProcessInfo"): + return self.qfProcessInfo(packet) + + return self.other(packet) + + def qsProcessInfo(self): + return "E04" + + def qfProcessInfo(self, packet): + return "E04" + + def qGetWorkingDir(self): + return "2f" + + def qHostInfo(self): + return "ptrsize:8;endian:little;" + + def qQueryGDBServer(self): + return "E04" + + def interrupt(self): + raise self.UnexpectedPacketException() + + def cont(self): + raise self.UnexpectedPacketException() + + def vCont(self, packet): + raise self.UnexpectedPacketException() + + def readRegisters(self): + return "00000000" * self.registerCount + + def readRegister(self, register): + return "00000000" + + def writeRegisters(self, registers_hex): + return "OK" + + def writeRegister(self, register, value_hex): + return "OK" + + def readMemory(self, addr, length): + return "00" * length + + def writeMemory(self, addr, data_hex): + return "OK" + + def qSymbol(self, symbol_args): + return "OK" + + def qSupported(self, client_supported): + return "qXfer:features:read+;PacketSize=3fff;QStartNoAckMode+" + + def qfThreadInfo(self): + return "l" + + def qsThreadInfo(self): + return "l" + + def qC(self): + return "QC0" + + def QEnableErrorStrings(self): + return "OK" + + def haltReason(self): + # SIGINT is 2, return type is 2 digit hex string + return "S02" + + def qXferRead(self, obj, annex, offset, length): + return None, False + + def _qXferResponse(self, data, has_more): + return "%s%s" % ("m" if has_more else "l", escape_binary(data)) + + def vAttach(self, pid): + raise self.UnexpectedPacketException() + + def selectThread(self, op, thread_id): + return "OK" + + def setBreakpoint(self, packet): + raise self.UnexpectedPacketException() + + def threadStopInfo(self, threadnum): + return "" + + def other(self, packet): + # empty string means unsupported + return "" + + def QThreadSuffixSupported(self): + return "" + + def QListThreadsInStopReply(self): + return "" + + def qMemoryRegionInfo(self): + return "" + + """ + Raised when we receive a packet for which there is no default action. + Override the responder class to implement behavior suitable for the test at + hand. + """ + class UnexpectedPacketException(Exception): + pass + + +class MockGDBServer: + """ + A simple TCP-based GDB server that can test client behavior by receiving + commands and issuing custom-tailored responses. + + Responses are generated via the .responder property, which should be an + instance of a class based on MockGDBServerResponder. + """ + + responder = None + port = 0 + _socket = None + _client = None + _thread = None + _receivedData = None + _receivedDataOffset = None + _shouldSendAck = True + + def __init__(self, port = 0): + self.responder = MockGDBServerResponder() + self.port = port + self._socket = socket.socket() + + def start(self): + # Block until the socket is up, so self.port is available immediately. + # Then start a thread that waits for a client connection. + addr = ("127.0.0.1", self.port) + self._socket.bind(addr) + self.port = self._socket.getsockname()[1] + self._socket.listen(1) + self._thread = threading.Thread(target=self._run) + self._thread.start() + + def stop(self): + self._socket.close() + self._thread.join() + self._thread = None + + def _run(self): + # For testing purposes, we only need to worry about one client + # connecting just one time. + try: + # accept() is stubborn and won't fail even when the socket is + # shutdown, so we'll use a timeout + self._socket.settimeout(20.0) + client, client_addr = self._socket.accept() + self._client = client + # The connected client inherits its timeout from self._socket, + # but we'll use a blocking socket for the client + self._client.settimeout(None) + except: + return + self._shouldSendAck = True + self._receivedData = "" + self._receivedDataOffset = 0 + data = None + while True: + try: + data = seven.bitcast_to_string(self._client.recv(4096)) + if data is None or len(data) == 0: + break + self._receive(data) + except Exception as e: + print("An exception happened when receiving the response from the gdb server. Closing the client...") + traceback.print_exc() + self._client.close() + break + + def _receive(self, data): + """ + Collects data, parses and responds to as many packets as exist. + Any leftover data is kept for parsing the next time around. + """ + self._receivedData += data + try: + packet = self._parsePacket() + while packet is not None: + self._handlePacket(packet) + packet = self._parsePacket() + except self.InvalidPacketException: + self._client.close() + + def _parsePacket(self): + """ + Reads bytes from self._receivedData, returning: + - a packet's contents if a valid packet is found + - the PACKET_ACK unique object if we got an ack + - None if we only have a partial packet + + Raises an InvalidPacketException if unexpected data is received + or if checksums fail. + + Once a complete packet is found at the front of self._receivedData, + its data is removed form self._receivedData. + """ + data = self._receivedData + i = self._receivedDataOffset + data_len = len(data) + if data_len == 0: + return None + if i == 0: + # If we're looking at the start of the received data, that means + # we're looking for the start of a new packet, denoted by a $. + # It's also possible we'll see an ACK here, denoted by a + + if data[0] == '+': + self._receivedData = data[1:] + return self.PACKET_ACK + if ord(data[0]) == 3: + self._receivedData = data[1:] + return self.PACKET_INTERRUPT + if data[0] == '$': + i += 1 + else: + raise self.InvalidPacketException( + "Unexpected leading byte: %s" % data[0]) + + # If we're looking beyond the start of the received data, then we're + # looking for the end of the packet content, denoted by a #. + # Note that we pick up searching from where we left off last time + while i < data_len and data[i] != '#': + i += 1 + + # If there isn't enough data left for a checksum, just remember where + # we left off so we can pick up there the next time around + if i > data_len - 3: + self._receivedDataOffset = i + return None + + # If we have enough data remaining for the checksum, extract it and + # compare to the packet contents + packet = data[1:i] + i += 1 + try: + check = int(data[i:i + 2], 16) + except ValueError: + raise self.InvalidPacketException("Checksum is not valid hex") + i += 2 + if check != checksum(packet): + raise self.InvalidPacketException( + "Checksum %02x does not match content %02x" % + (check, checksum(packet))) + # remove parsed bytes from _receivedData and reset offset so parsing + # can start on the next packet the next time around + self._receivedData = data[i:] + self._receivedDataOffset = 0 + return packet + + def _handlePacket(self, packet): + if packet is self.PACKET_ACK: + # Ignore ACKs from the client. For the future, we can consider + # adding validation code to make sure the client only sends ACKs + # when it's supposed to. + return + response = "" + # We'll handle the ack stuff here since it's not something any of the + # tests will be concerned about, and it'll get turned off quickly anyway. + if self._shouldSendAck: + self._client.sendall(seven.bitcast_to_bytes('+')) + if packet == "QStartNoAckMode": + self._shouldSendAck = False + response = "OK" + elif self.responder is not None: + # Delegate everything else to our responder + response = self.responder.respond(packet) + # Handle packet framing since we don't want to bother tests with it. + if response is not None: + framed = frame_packet(response) + self._client.sendall(seven.bitcast_to_bytes(framed)) + + PACKET_ACK = object() + PACKET_INTERRUPT = object() + + class InvalidPacketException(Exception): + pass + +class GDBRemoteTestBase(TestBase): + """ + Base class for GDB client tests. + + This class will setup and start a mock GDB server for the test to use. + It also provides assertPacketLogContains, which simplifies the checking + of packets sent by the client. + """ + + NO_DEBUG_INFO_TESTCASE = True + mydir = TestBase.compute_mydir(__file__) + server = None + + def setUp(self): + TestBase.setUp(self) + self.server = MockGDBServer() + self.server.start() + + def tearDown(self): + # TestBase.tearDown will kill the process, but we need to kill it early + # so its client connection closes and we can stop the server before + # finally calling the base tearDown. + if self.process() is not None: + self.process().Kill() + self.server.stop() + TestBase.tearDown(self) + + def createTarget(self, yaml_path): + """ + Create a target by auto-generating the object based on the given yaml + instructions. + + This will track the generated object so it can be automatically removed + during tearDown. + """ + yaml_base, ext = os.path.splitext(yaml_path) + obj_path = self.getBuildArtifact(yaml_base) + self.yaml2obj(yaml_path, obj_path) + return self.dbg.CreateTarget(obj_path) + + def connect(self, target): + """ + Create a process by connecting to the mock GDB server. + + Includes assertions that the process was successfully created. + """ + listener = self.dbg.GetListener() + error = lldb.SBError() + url = "connect://localhost:%d" % self.server.port + process = target.ConnectRemote(listener, url, "gdb-remote", error) + self.assertTrue(error.Success(), error.description) + self.assertTrue(process, PROCESS_IS_VALID) + return process + + def assertPacketLogContains(self, packets): + """ + Assert that the mock server's packet log contains the given packets. + + The packet log includes all packets sent by the client and received + by the server. This fuction makes it easy to verify that the client + sent the expected packets to the server. + + The check does not require that the packets be consecutive, but does + require that they are ordered in the log as they ordered in the arg. + """ + i = 0 + j = 0 + log = self.server.responder.packetLog + + while i < len(packets) and j < len(log): + if log[j] == packets[i]: + i += 1 + j += 1 + if i < len(packets): + self.fail(u"Did not receive: %s\nLast 10 packets:\n\t%s" % + (packets[i], u'\n\t'.join(log))) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/operating_system.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/operating_system.py new file mode 100644 index 00000000000..83180c51492 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/operating_system.py @@ -0,0 +1,44 @@ +import lldb + + +class OperatingSystemPlugIn(object): + """Class that provides data for an instance of a LLDB 'OperatingSystemPython' plug-in class""" + + def __init__(self, process): + '''Initialization needs a valid.SBProcess object. + + This plug-in will get created after a live process is valid and has stopped for the first time. + ''' + self.process = None + self.registers = None + self.threads = None + if isinstance(process, lldb.SBProcess) and process.IsValid(): + self.process = process + self.threads = None # Will be an dictionary containing info for each thread + + def get_target(self): + return self.process.target + + def get_thread_info(self): + if not self.threads: + self.threads = [{ + 'tid': 0x1, + 'name': 'one', + 'queue': 'queue1', + 'state': 'stopped', + 'stop_reason': 'none' + }, { + 'tid': 0x2, + 'name': 'two', + 'queue': 'queue2', + 'state': 'stopped', + 'stop_reason': 'none' + }, { + 'tid': 0x3, + 'name': 'three', + 'queue': 'queue3', + 'state': 'stopped', + 'stop_reason': 'sigstop', + 'core': 0 + }] + return self.threads diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/operating_system_2.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/operating_system_2.py new file mode 100644 index 00000000000..91b2ffeecb3 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/operating_system_2.py @@ -0,0 +1,61 @@ +import lldb + + +class OperatingSystemPlugIn(object): + """Class that provides data for an instance of a LLDB 'OperatingSystemPython' plug-in class + This version stops once with threads 0x111 and 0x222, then stops a second time with threads + 0x111 and 0x333.""" + + def __init__(self, process): + '''Initialization needs a valid.SBProcess object. + + This plug-in will get created after a live process is valid and has stopped for the first time. + ''' + self.process = None + self.registers = None + self.threads = None + self.times_called = 0 + if isinstance(process, lldb.SBProcess) and process.IsValid(): + self.process = process + self.threads = None # Will be an dictionary containing info for each thread + + def get_target(self): + return self.process.target + + def get_thread_info(self): + self.times_called += 1 + + if self.times_called == 1: + self.threads = [{ + 'tid': 0x111, + 'name': 'one', + 'queue': 'queue1', + 'state': 'stopped', + 'stop_reason': 'none', + 'core': 1 + }, { + 'tid': 0x222, + 'name': 'two', + 'queue': 'queue2', + 'state': 'stopped', + 'stop_reason': 'none', + 'core': 0 + }] + else: + self.threads = [{ + 'tid': 0x111, + 'name': 'one', + 'queue': 'queue1', + 'state': 'stopped', + 'stop_reason': 'none', + 'core': 1 + }, { + 'tid': 0x333, + 'name': 'three', + 'queue': 'queue3', + 'state': 'stopped', + 'stop_reason': 'none', + 'core': 0 + }] + return self.threads + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/history/TestHistoryRecall.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/history/TestHistoryRecall.py new file mode 100644 index 00000000000..557b4a4c082 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/history/TestHistoryRecall.py @@ -0,0 +1,37 @@ +""" +Make sure the !N and !-N commands work properly. +""" + + + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + + +class TestHistoryRecall(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # If your test case doesn't stress debug info, the + # set this to true. That way it won't be run once for + # each debug info format. + NO_DEBUG_INFO_TESTCASE = True + + def test_history_recall(self): + """Test the !N and !-N functionality of the command interpreter.""" + self.sample_test() + + def sample_test(self): + interp = self.dbg.GetCommandInterpreter() + result = lldb.SBCommandReturnObject() + interp.HandleCommand("command history", result, True) + interp.HandleCommand("platform list", result, True) + + interp.HandleCommand("!0", result, False) + self.assertTrue(result.Succeeded(), "!0 command did not work: %s"%(result.GetError())) + self.assertTrue("command history" in result.GetOutput(), "!0 didn't rerun command history") + + interp.HandleCommand("!-1", result, False) + self.assertTrue(result.Succeeded(), "!-1 command did not work: %s"%(result.GetError())) + self.assertTrue("host:" in result.GetOutput(), "!-1 didn't rerun platform list.") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-assert/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-assert/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-assert/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-assert/TestInferiorAssert.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-assert/TestInferiorAssert.py new file mode 100644 index 00000000000..36fdc862294 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-assert/TestInferiorAssert.py @@ -0,0 +1,315 @@ +"""Test that lldb functions correctly after the inferior has asserted.""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test import lldbutil +from lldbsuite.test import lldbplatformutil +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * + + +class AssertingInferiorTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll( + oslist=["windows"], + bugnumber="llvm.org/pr21793: need to implement support for detecting assertion / abort on Windows") + @expectedFailureAll( + oslist=["linux"], + archs=["arm"], + bugnumber="llvm.org/pr25338") + @expectedFailureAll(bugnumber="llvm.org/pr26592", triple='^mips') + @expectedFailureNetBSD + def test_inferior_asserting(self): + """Test that lldb reliably catches the inferior asserting (command).""" + self.build() + self.inferior_asserting() + + @expectedFailureAll( + oslist=["windows"], + bugnumber="llvm.org/pr21793: need to implement support for detecting assertion / abort on Windows") + @expectedFailureAndroid( + api_levels=list( + range( + 16 + + 1))) # b.android.com/179836 + def test_inferior_asserting_register(self): + """Test that lldb reliably reads registers from the inferior after asserting (command).""" + self.build() + self.inferior_asserting_registers() + + @expectedFailureAll( + oslist=["windows"], + bugnumber="llvm.org/pr21793: need to implement support for detecting assertion / abort on Windows") + @expectedFailureAll( + oslist=["linux"], + archs=[ + "aarch64", + "arm"], + triple=no_match(".*-android"), + bugnumber="llvm.org/pr25338") + @expectedFailureAll(bugnumber="llvm.org/pr26592", triple='^mips') + @expectedFailureNetBSD + def test_inferior_asserting_disassemble(self): + """Test that lldb reliably disassembles frames after asserting (command).""" + self.build() + self.inferior_asserting_disassemble() + + @add_test_categories(['pyapi']) + @expectedFailureAll( + oslist=["windows"], + bugnumber="llvm.org/pr21793: need to implement support for detecting assertion / abort on Windows") + def test_inferior_asserting_python(self): + """Test that lldb reliably catches the inferior asserting (Python API).""" + self.build() + self.inferior_asserting_python() + + @expectedFailureAll( + oslist=["windows"], + bugnumber="llvm.org/pr21793: need to implement support for detecting assertion / abort on Windows") + @expectedFailureAll( + oslist=["linux"], + archs=["arm"], + triple=no_match(".*-android"), + bugnumber="llvm.org/pr25338") + @expectedFailureAll(bugnumber="llvm.org/pr26592", triple='^mips') + @expectedFailureNetBSD + def test_inferior_asserting_expr(self): + """Test that the lldb expression interpreter can read from the inferior after asserting (command).""" + self.build() + self.inferior_asserting_expr() + + @expectedFailureAll( + oslist=["windows"], + bugnumber="llvm.org/pr21793: need to implement support for detecting assertion / abort on Windows") + @expectedFailureAll( + oslist=["linux"], + archs=["arm"], + triple=no_match(".*-android"), + bugnumber="llvm.org/pr25338") + @expectedFailureAll(bugnumber="llvm.org/pr26592", triple='^mips') + @expectedFailureNetBSD + def test_inferior_asserting_step(self): + """Test that lldb functions correctly after stepping through a call to assert().""" + self.build() + self.inferior_asserting_step() + + def set_breakpoint(self, line): + lldbutil.run_break_set_by_file_and_line( + self, "main.c", line, num_expected_locations=1, loc_exact=True) + + def check_stop_reason(self): + matched = lldbplatformutil.match_android_device( + self.getArchitecture(), valid_api_levels=list(range(1, 16 + 1))) + if matched: + # On android until API-16 the abort() call ended in a sigsegv + # instead of in a sigabrt + stop_reason = 'stop reason = signal SIGSEGV' + else: + stop_reason = 'stop reason = signal SIGABRT' + + # The stop reason of the thread should be an abort signal or exception. + self.expect("thread list", STOPPED_DUE_TO_ASSERT, + substrs=['stopped', + stop_reason]) + + return stop_reason + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number of the call to assert. + self.line = line_number('main.c', '// Assert here.') + + def inferior_asserting(self): + """Inferior asserts upon launching; lldb should catch the event and stop.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + self.runCmd("run", RUN_SUCCEEDED) + stop_reason = self.check_stop_reason() + + # And it should report a backtrace that includes the assert site. + self.expect("thread backtrace all", + substrs=[stop_reason, 'main', 'argc', 'argv']) + + # And it should report the correct line number. + self.expect("thread backtrace all", + substrs=[stop_reason, + 'main.c:%d' % self.line]) + + def inferior_asserting_python(self): + """Inferior asserts upon launching; lldb should catch the event and stop.""" + exe = self.getBuildArtifact("a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now launch the process, and do not stop at entry point. + # Both argv and envp are null. + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + + if process.GetState() != lldb.eStateStopped: + self.fail("Process should be in the 'stopped' state, " + "instead the actual state is: '%s'" % + lldbutil.state_type_to_str(process.GetState())) + + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonSignal) + if not thread: + self.fail("Fail to stop the thread upon assert") + + if self.TraceOn(): + lldbutil.print_stacktrace(thread) + + def inferior_asserting_registers(self): + """Test that lldb can read registers after asserting.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + self.runCmd("run", RUN_SUCCEEDED) + self.check_stop_reason() + + # lldb should be able to read from registers from the inferior after + # asserting. + lldbplatformutil.check_first_register_readable(self) + + def inferior_asserting_disassemble(self): + """Test that lldb can disassemble frames after asserting.""" + exe = self.getBuildArtifact("a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Launch the process, and do not stop at the entry point. + target.LaunchSimple(None, None, self.get_process_working_directory()) + self.check_stop_reason() + + process = target.GetProcess() + self.assertTrue(process.IsValid(), "current process is valid") + + thread = process.GetThreadAtIndex(0) + self.assertTrue(thread.IsValid(), "current thread is valid") + + lastframeID = thread.GetFrameAtIndex( + thread.GetNumFrames() - 1).GetFrameID() + + isi386Arch = False + if "i386" in self.getArchitecture(): + isi386Arch = True + + # lldb should be able to disassemble frames from the inferior after + # asserting. + for frame in thread: + self.assertTrue(frame.IsValid(), "current frame is valid") + + self.runCmd("frame select " + + str(frame.GetFrameID()), RUN_SUCCEEDED) + + # Don't expect the function name to be in the disassembly as the assert + # function might be a no-return function where the PC is past the end + # of the function and in the next function. We also can't back the PC up + # because we don't know how much to back it up by on targets with opcodes + # that have differing sizes + pc_backup_offset = 1 + if frame.GetFrameID() == 0: + pc_backup_offset = 0 + if isi386Arch: + if lastframeID == frame.GetFrameID(): + pc_backup_offset = 0 + self.expect( + "disassemble -a %s" % + (frame.GetPC() - + pc_backup_offset), + substrs=['<+0>: ']) + + def check_expr_in_main(self, thread): + depth = thread.GetNumFrames() + for i in range(depth): + frame = thread.GetFrameAtIndex(i) + self.assertTrue(frame.IsValid(), "current frame is valid") + if self.TraceOn(): + print( + "Checking if function %s is main" % + frame.GetFunctionName()) + + if 'main' == frame.GetFunctionName(): + frame_id = frame.GetFrameID() + self.runCmd("frame select " + str(frame_id), RUN_SUCCEEDED) + self.expect("p argc", substrs=['(int)', ' = 1']) + self.expect("p hello_world", substrs=['Hello']) + self.expect("p argv[0]", substrs=['a.out']) + self.expect("p null_ptr", substrs=['= 0x0']) + return True + return False + + def inferior_asserting_expr(self): + """Test that the lldb expression interpreter can read symbols after asserting.""" + exe = self.getBuildArtifact("a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Launch the process, and do not stop at the entry point. + target.LaunchSimple(None, None, self.get_process_working_directory()) + self.check_stop_reason() + + process = target.GetProcess() + self.assertTrue(process.IsValid(), "current process is valid") + + thread = process.GetThreadAtIndex(0) + self.assertTrue(thread.IsValid(), "current thread is valid") + + # The lldb expression interpreter should be able to read from addresses + # of the inferior after a call to assert(). + self.assertTrue( + self.check_expr_in_main(thread), + "cannot find 'main' in the backtrace") + + def inferior_asserting_step(self): + """Test that lldb functions correctly after stepping through a call to assert().""" + exe = self.getBuildArtifact("a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Launch the process, and do not stop at the entry point. + self.set_breakpoint(self.line) + target.LaunchSimple(None, None, self.get_process_working_directory()) + + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['main.c:%d' % self.line, + 'stop reason = breakpoint']) + + self.runCmd("next") + stop_reason = self.check_stop_reason() + + # lldb should be able to read from registers from the inferior after + # asserting. + if "x86_64" in self.getArchitecture(): + self.expect("register read rbp", substrs=['rbp = 0x']) + if "i386" in self.getArchitecture(): + self.expect("register read ebp", substrs=['ebp = 0x']) + + process = target.GetProcess() + self.assertTrue(process.IsValid(), "current process is valid") + + thread = process.GetThreadAtIndex(0) + self.assertTrue(thread.IsValid(), "current thread is valid") + + # The lldb expression interpreter should be able to read from addresses + # of the inferior after a call to assert(). + self.assertTrue( + self.check_expr_in_main(thread), + "cannot find 'main' in the backtrace") + + # And it should report the correct line number. + self.expect("thread backtrace all", + substrs=[stop_reason, + 'main.c:%d' % self.line]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-assert/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-assert/main.c new file mode 100644 index 00000000000..ad2ca563424 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-assert/main.c @@ -0,0 +1,18 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include <stdio.h> +#include <assert.h> + +const char *hello_world = "Hello, assertion!"; + +int main(int argc, const char* argv[]) +{ + int *null_ptr = 0; + printf("%s\n", hello_world); + assert(null_ptr); // Assert here. +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-changed/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-changed/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-changed/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-changed/TestInferiorChanged.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-changed/TestInferiorChanged.py new file mode 100644 index 00000000000..95cdfb5591f --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-changed/TestInferiorChanged.py @@ -0,0 +1,82 @@ +"""Test lldb reloads the inferior after it was changed during the session.""" + + + +import time +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import configuration +from lldbsuite.test import lldbutil + + +class ChangedInferiorTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipIf(hostoslist=["windows"]) + @no_debug_info_test + def test_inferior_crashing(self): + """Test lldb reloads the inferior after it was changed during the session.""" + self.build() + self.inferior_crashing() + self.cleanup() + # lldb needs to recognize the inferior has changed. If lldb needs to check the + # new module timestamp, make sure it is not the same as the old one, so add a + # 1 second delay. + time.sleep(1) + d = {'C_SOURCES': 'main2.c'} + self.build(dictionary=d) + self.setTearDownCleanup(dictionary=d) + self.inferior_not_crashing() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number of the crash. + self.line1 = line_number('main.c', '// Crash here.') + self.line2 = line_number('main2.c', '// Not crash here.') + + def inferior_crashing(self): + """Inferior crashes upon launching; lldb should catch the event and stop.""" + self.exe = self.getBuildArtifact("a.out") + self.runCmd("file " + self.exe, CURRENT_EXECUTABLE_SET) + + self.runCmd("run", RUN_SUCCEEDED) + + # We should have one crashing thread + self.assertEqual( + len(lldbutil.get_crashed_threads(self, self.dbg.GetSelectedTarget().GetProcess())), + 1, + STOPPED_DUE_TO_EXC_BAD_ACCESS) + + # And it should report the correct line number. + self.expect("thread backtrace all", substrs=['main.c:%d' % self.line1]) + + def inferior_not_crashing(self): + """Test lldb reloads the inferior after it was changed during the session.""" + self.runCmd("process kill") + self.runCmd("run", RUN_SUCCEEDED) + self.runCmd("process status") + + self.assertNotEqual( + len(lldbutil.get_crashed_threads(self, self.dbg.GetSelectedTarget().GetProcess())), + 1, + "Inferior changed, but lldb did not perform a reload") + + # Break inside the main. + lldbutil.run_break_set_by_file_and_line( + self, "main2.c", self.line2, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + self.runCmd("frame variable int_ptr") + self.expect("frame variable *int_ptr", + substrs=['= 7']) + self.expect("expression *int_ptr", + substrs=['= 7']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-changed/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-changed/main.c new file mode 100644 index 00000000000..ec4824ad4ad --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-changed/main.c @@ -0,0 +1,15 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include <stdio.h> + +int main(int argc, const char* argv[]) +{ + int *null_ptr = 0; + printf("Hello, segfault!\n"); + printf("Now crash %d\n", *null_ptr); // Crash here. +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-changed/main2.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-changed/main2.c new file mode 100644 index 00000000000..a3c68f0f03d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-changed/main2.c @@ -0,0 +1,17 @@ +//===-- main2.c -------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include <stdio.h> +#include <stdlib.h> + +int main(int argc, const char* argv[]) +{ + int *int_ptr = (int *)malloc(sizeof(int)); + *int_ptr = 7; + printf("Hello, world!\n"); + printf("Now not crash %d\n", *int_ptr); // Not crash here. +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-crashing/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-crashing/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-crashing/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-crashing/TestInferiorCrashing.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-crashing/TestInferiorCrashing.py new file mode 100644 index 00000000000..ee17ecc32ea --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-crashing/TestInferiorCrashing.py @@ -0,0 +1,134 @@ +"""Test that lldb functions correctly after the inferior has crashed.""" + + + +import lldb +from lldbsuite.test import lldbutil +from lldbsuite.test import lldbplatformutil +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * + + +class CrashingInferiorTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") + @expectedFailureNetBSD + def test_inferior_crashing(self): + """Test that lldb reliably catches the inferior crashing (command).""" + self.build() + self.inferior_crashing() + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") + def test_inferior_crashing_register(self): + """Test that lldb reliably reads registers from the inferior after crashing (command).""" + self.build() + self.inferior_crashing_registers() + + @add_test_categories(['pyapi']) + def test_inferior_crashing_python(self): + """Test that lldb reliably catches the inferior crashing (Python API).""" + self.build() + self.inferior_crashing_python() + + def test_inferior_crashing_expr(self): + """Test that the lldb expression interpreter can read from the inferior after crashing (command).""" + self.build() + self.inferior_crashing_expr() + + def set_breakpoint(self, line): + lldbutil.run_break_set_by_file_and_line( + self, "main.c", line, num_expected_locations=1, loc_exact=True) + + def check_stop_reason(self): + # We should have one crashing thread + self.assertEqual( + len(lldbutil.get_crashed_threads(self, self.dbg.GetSelectedTarget().GetProcess())), + 1, + STOPPED_DUE_TO_EXC_BAD_ACCESS) + + def get_api_stop_reason(self): + return lldb.eStopReasonException + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number of the crash. + self.line = line_number('main.c', '// Crash here.') + + def inferior_crashing(self): + """Inferior crashes upon launching; lldb should catch the event and stop.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + self.runCmd("run", RUN_SUCCEEDED) + # The exact stop reason depends on the platform + if self.platformIsDarwin(): + stop_reason = 'stop reason = EXC_BAD_ACCESS' + elif self.getPlatform() == "linux" or self.getPlatform() == "freebsd": + stop_reason = 'stop reason = signal SIGSEGV' + else: + stop_reason = 'stop reason = invalid address' + self.expect("thread list", STOPPED_DUE_TO_EXC_BAD_ACCESS, + substrs=['stopped', + stop_reason]) + + # And it should report the correct line number. + self.expect("thread backtrace all", + substrs=[stop_reason, + 'main.c:%d' % self.line]) + + def inferior_crashing_python(self): + """Inferior crashes upon launching; lldb should catch the event and stop.""" + exe = self.getBuildArtifact("a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now launch the process, and do not stop at entry point. + # Both argv and envp are null. + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + + if process.GetState() != lldb.eStateStopped: + self.fail("Process should be in the 'stopped' state, " + "instead the actual state is: '%s'" % + lldbutil.state_type_to_str(process.GetState())) + + threads = lldbutil.get_crashed_threads(self, process) + self.assertEqual( + len(threads), + 1, + "Failed to stop the thread upon bad access exception") + + if self.TraceOn(): + lldbutil.print_stacktrace(threads[0]) + + def inferior_crashing_registers(self): + """Test that lldb can read registers after crashing.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + self.runCmd("run", RUN_SUCCEEDED) + self.check_stop_reason() + + # lldb should be able to read from registers from the inferior after + # crashing. + lldbplatformutil.check_first_register_readable(self) + + def inferior_crashing_expr(self): + """Test that the lldb expression interpreter can read symbols after crashing.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + self.runCmd("run", RUN_SUCCEEDED) + self.check_stop_reason() + + # The lldb expression interpreter should be able to read from addresses + # of the inferior after a crash. + self.expect("p argc", + startstr='(int) $0 = 1') + + self.expect("p hello_world", + substrs=['Hello']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-crashing/TestInferiorCrashingStep.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-crashing/TestInferiorCrashingStep.py new file mode 100644 index 00000000000..afb8c2370b3 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-crashing/TestInferiorCrashingStep.py @@ -0,0 +1,228 @@ +"""Test that lldb steps correctly after the inferior has crashed.""" + + +import lldb +from lldbsuite.test import lldbutil +from lldbsuite.test import lldbplatformutil +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * + + +class CrashingInferiorStepTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") + @expectedFailureNetBSD + def test_inferior_crashing(self): + """Test that lldb reliably catches the inferior crashing (command).""" + self.build() + self.inferior_crashing() + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") + def test_inferior_crashing_register(self): + """Test that lldb reliably reads registers from the inferior after crashing (command).""" + self.build() + self.inferior_crashing_registers() + + @add_test_categories(['pyapi']) + def test_inferior_crashing_python(self): + """Test that lldb reliably catches the inferior crashing (Python API).""" + self.build() + self.inferior_crashing_python() + + def test_inferior_crashing_expr(self): + """Test that the lldb expression interpreter can read from the inferior after crashing (command).""" + self.build() + self.inferior_crashing_expr() + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") + def test_inferior_crashing_step(self): + """Test that stepping after a crash behaves correctly.""" + self.build() + self.inferior_crashing_step() + + @skipIfTargetAndroid() # debuggerd interferes with this test on Android + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") + def test_inferior_crashing_step_after_break(self): + """Test that lldb functions correctly after stepping through a crash.""" + self.build() + self.inferior_crashing_step_after_break() + + # Inferior exits after stepping after a segfault. This is working as + # intended IMHO. + @skipIfLinux + @skipIfFreeBSD + @expectedFailureNetBSD + def test_inferior_crashing_expr_step_and_expr(self): + """Test that lldb expressions work before and after stepping after a crash.""" + self.build() + self.inferior_crashing_expr_step_expr() + + def set_breakpoint(self, line): + lldbutil.run_break_set_by_file_and_line( + self, "main.c", line, num_expected_locations=1, loc_exact=True) + + def check_stop_reason(self): + # We should have one crashing thread + self.assertEqual( + len( + lldbutil.get_crashed_threads( + self, + self.dbg.GetSelectedTarget().GetProcess())), 1, + STOPPED_DUE_TO_EXC_BAD_ACCESS) + + def get_api_stop_reason(self): + return lldb.eStopReasonException + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number of the crash. + self.line = line_number('main.c', '// Crash here.') + + def inferior_crashing(self): + """Inferior crashes upon launching; lldb should catch the event and stop.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + self.runCmd("run", RUN_SUCCEEDED) + # The exact stop reason depends on the platform + if self.platformIsDarwin(): + stop_reason = 'stop reason = EXC_BAD_ACCESS' + elif self.getPlatform() == "linux" or self.getPlatform() == "freebsd": + stop_reason = 'stop reason = signal SIGSEGV' + else: + stop_reason = 'stop reason = invalid address' + self.expect( + "thread list", + STOPPED_DUE_TO_EXC_BAD_ACCESS, + substrs=['stopped', stop_reason]) + + # And it should report the correct line number. + self.expect( + "thread backtrace all", + substrs=[stop_reason, 'main.c:%d' % self.line]) + + def inferior_crashing_python(self): + """Inferior crashes upon launching; lldb should catch the event and stop.""" + exe = self.getBuildArtifact("a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now launch the process, and do not stop at entry point. + # Both argv and envp are null. + process = target.LaunchSimple(None, None, + self.get_process_working_directory()) + + if process.GetState() != lldb.eStateStopped: + self.fail("Process should be in the 'stopped' state, " + "instead the actual state is: '%s'" % + lldbutil.state_type_to_str(process.GetState())) + + threads = lldbutil.get_crashed_threads(self, process) + self.assertEqual( + len(threads), 1, + "Failed to stop the thread upon bad access exception") + + if self.TraceOn(): + lldbutil.print_stacktrace(threads[0]) + + def inferior_crashing_registers(self): + """Test that lldb can read registers after crashing.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + self.runCmd("run", RUN_SUCCEEDED) + self.check_stop_reason() + + # lldb should be able to read from registers from the inferior after + # crashing. + lldbplatformutil.check_first_register_readable(self) + + def inferior_crashing_expr(self): + """Test that the lldb expression interpreter can read symbols after crashing.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + self.runCmd("run", RUN_SUCCEEDED) + self.check_stop_reason() + + # The lldb expression interpreter should be able to read from addresses + # of the inferior after a crash. + self.expect("p argc", startstr='(int) $0 = 1') + + self.expect("p hello_world", substrs=['Hello']) + + def inferior_crashing_step(self): + """Test that lldb functions correctly after stepping through a crash.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + self.set_breakpoint(self.line) + self.runCmd("run", RUN_SUCCEEDED) + + self.expect( + "thread list", + STOPPED_DUE_TO_BREAKPOINT, + substrs=['main.c:%d' % self.line, 'stop reason = breakpoint']) + + self.runCmd("next") + self.check_stop_reason() + + # The lldb expression interpreter should be able to read from addresses + # of the inferior after a crash. + self.expect("p argv[0]", substrs=['a.out']) + self.expect("p null_ptr", substrs=['= 0x0']) + + # lldb should be able to read from registers from the inferior after + # crashing. + lldbplatformutil.check_first_register_readable(self) + + # And it should report the correct line number. + self.expect("thread backtrace all", substrs=['main.c:%d' % self.line]) + + @expectedFailureNetBSD + def inferior_crashing_step_after_break(self): + """Test that lldb behaves correctly when stepping after a crash.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + self.runCmd("run", RUN_SUCCEEDED) + self.check_stop_reason() + + expected_state = 'exited' # Provide the exit code. + if self.platformIsDarwin(): + # TODO: Determine why 'next' and 'continue' have no effect after a + # crash. + expected_state = 'stopped' + + self.expect("next", substrs=['Process', expected_state]) + + if expected_state == 'exited': + self.expect( + "thread list", + error=True, + substrs=['Process must be launched']) + else: + self.check_stop_reason() + + def inferior_crashing_expr_step_expr(self): + """Test that lldb expressions work before and after stepping after a crash.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + self.runCmd("run", RUN_SUCCEEDED) + self.check_stop_reason() + + # The lldb expression interpreter should be able to read from addresses + # of the inferior after a crash. + self.expect("p argv[0]", substrs=['a.out']) + + self.runCmd("next") + self.check_stop_reason() + + # The lldb expression interpreter should be able to read from addresses + # of the inferior after a crash. + self.expect("p argv[0]", substrs=['a.out']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-crashing/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-crashing/main.c new file mode 100644 index 00000000000..3423ea42bee --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-crashing/main.c @@ -0,0 +1,17 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include <stdio.h> + +const char *hello_world = "Hello, segfault!"; + +int main(int argc, const char* argv[]) +{ + int *null_ptr = 0; + printf("%s\n", hello_world); + printf("Now crash %d\n", *null_ptr); // Crash here. +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-crashing/recursive-inferior/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-crashing/recursive-inferior/Makefile new file mode 100644 index 00000000000..eb07d2fbdf3 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-crashing/recursive-inferior/Makefile @@ -0,0 +1,5 @@ +C_SOURCES := main.c + +CFLAGS_EXTRAS := -fomit-frame-pointer + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-crashing/recursive-inferior/TestRecursiveInferior.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-crashing/recursive-inferior/TestRecursiveInferior.py new file mode 100644 index 00000000000..3044e5e2a76 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-crashing/recursive-inferior/TestRecursiveInferior.py @@ -0,0 +1,141 @@ +"""Test that lldb functions correctly after the inferior has crashed while in a recursive routine.""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbplatformutil +from lldbsuite.test import lldbutil + + +class CrashingRecursiveInferiorTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") + @expectedFailureNetBSD + def test_recursive_inferior_crashing(self): + """Test that lldb reliably catches the inferior crashing (command).""" + self.build() + self.recursive_inferior_crashing() + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") + def test_recursive_inferior_crashing_register(self): + """Test that lldb reliably reads registers from the inferior after crashing (command).""" + self.build() + self.recursive_inferior_crashing_registers() + + @add_test_categories(['pyapi']) + def test_recursive_inferior_crashing_python(self): + """Test that lldb reliably catches the inferior crashing (Python API).""" + self.build() + self.recursive_inferior_crashing_python() + + def test_recursive_inferior_crashing_expr(self): + """Test that the lldb expression interpreter can read from the inferior after crashing (command).""" + self.build() + self.recursive_inferior_crashing_expr() + + def set_breakpoint(self, line): + lldbutil.run_break_set_by_file_and_line( + self, "main.c", line, num_expected_locations=1, loc_exact=True) + + def check_stop_reason(self): + # We should have one crashing thread + self.assertEqual( + len(lldbutil.get_crashed_threads(self, self.dbg.GetSelectedTarget().GetProcess())), + 1, + STOPPED_DUE_TO_EXC_BAD_ACCESS) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number of the crash. + self.line = line_number('main.c', '// Crash here.') + + def recursive_inferior_crashing(self): + """Inferior crashes upon launching; lldb should catch the event and stop.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + self.runCmd("run", RUN_SUCCEEDED) + + # The exact stop reason depends on the platform + if self.platformIsDarwin(): + stop_reason = 'stop reason = EXC_BAD_ACCESS' + elif self.getPlatform() == "linux" or self.getPlatform() == "freebsd": + stop_reason = 'stop reason = signal SIGSEGV' + else: + stop_reason = 'stop reason = invalid address' + self.expect("thread list", STOPPED_DUE_TO_EXC_BAD_ACCESS, + substrs=['stopped', + stop_reason]) + + # And it should report a backtrace that includes main and the crash + # site. + self.expect( + "thread backtrace all", + substrs=[ + stop_reason, + 'main', + 'argc', + 'argv', + 'recursive_function']) + + # And it should report the correct line number. + self.expect("thread backtrace all", + substrs=[stop_reason, + 'main.c:%d' % self.line]) + + def recursive_inferior_crashing_python(self): + """Inferior crashes upon launching; lldb should catch the event and stop.""" + exe = self.getBuildArtifact("a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now launch the process, and do not stop at entry point. + # Both argv and envp are null. + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + + if process.GetState() != lldb.eStateStopped: + self.fail("Process should be in the 'stopped' state, " + "instead the actual state is: '%s'" % + lldbutil.state_type_to_str(process.GetState())) + + threads = lldbutil.get_crashed_threads(self, process) + self.assertEqual( + len(threads), + 1, + "Failed to stop the thread upon bad access exception") + + if self.TraceOn(): + lldbutil.print_stacktrace(threads[0]) + + def recursive_inferior_crashing_registers(self): + """Test that lldb can read registers after crashing.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + self.runCmd("run", RUN_SUCCEEDED) + self.check_stop_reason() + + # lldb should be able to read from registers from the inferior after + # crashing. + lldbplatformutil.check_first_register_readable(self) + + def recursive_inferior_crashing_expr(self): + """Test that the lldb expression interpreter can read symbols after crashing.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + self.runCmd("run", RUN_SUCCEEDED) + self.check_stop_reason() + + # The lldb expression interpreter should be able to read from addresses + # of the inferior after a crash. + self.expect("p i", + startstr='(int) $0 =') + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-crashing/recursive-inferior/TestRecursiveInferiorStep.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-crashing/recursive-inferior/TestRecursiveInferiorStep.py new file mode 100644 index 00000000000..e63172f917b --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-crashing/recursive-inferior/TestRecursiveInferiorStep.py @@ -0,0 +1,126 @@ +"""Test that lldb steps correctly after the inferior has crashed while in a recursive routine.""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbplatformutil +from lldbsuite.test import lldbutil + + +class CrashingRecursiveInferiorStepTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") + def test_recursive_inferior_crashing_step(self): + """Test that stepping after a crash behaves correctly.""" + self.build() + self.recursive_inferior_crashing_step() + + @skipIfTargetAndroid() # debuggerd interferes with this test on Android + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") + def test_recursive_inferior_crashing_step_after_break(self): + """Test that lldb functions correctly after stepping through a crash.""" + self.build() + self.recursive_inferior_crashing_step_after_break() + + # Inferior exits after stepping after a segfault. This is working as + # intended IMHO. + @skipIfLinux + @skipIfFreeBSD + @expectedFailureNetBSD + def test_recursive_inferior_crashing_expr_step_and_expr(self): + """Test that lldb expressions work before and after stepping after a crash.""" + self.build() + self.recursive_inferior_crashing_expr_step_expr() + + def set_breakpoint(self, line): + lldbutil.run_break_set_by_file_and_line( + self, "main.c", line, num_expected_locations=1, loc_exact=True) + + def check_stop_reason(self): + # We should have one crashing thread + self.assertEqual( + len( + lldbutil.get_crashed_threads( + self, + self.dbg.GetSelectedTarget().GetProcess())), 1, + STOPPED_DUE_TO_EXC_BAD_ACCESS) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number of the crash. + self.line = line_number('main.c', '// Crash here.') + + def recursive_inferior_crashing_step(self): + """Test that lldb functions correctly after stepping through a crash.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + self.set_breakpoint(self.line) + self.runCmd("run", RUN_SUCCEEDED) + + self.expect( + "thread list", + STOPPED_DUE_TO_BREAKPOINT, + substrs=['main.c:%d' % self.line, 'stop reason = breakpoint']) + + self.runCmd("next") + self.check_stop_reason() + + # The lldb expression interpreter should be able to read from addresses + # of the inferior after a crash. + self.expect("p i", substrs=['(int) $0 =']) + + # lldb should be able to read from registers from the inferior after + # crashing. + lldbplatformutil.check_first_register_readable(self) + + # And it should report the correct line number. + self.expect("thread backtrace all", substrs=['main.c:%d' % self.line]) + + def recursive_inferior_crashing_step_after_break(self): + """Test that lldb behaves correctly when stepping after a crash.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + self.runCmd("run", RUN_SUCCEEDED) + self.check_stop_reason() + + expected_state = 'exited' # Provide the exit code. + if self.platformIsDarwin(): + # TODO: Determine why 'next' and 'continue' have no effect after a + # crash. + expected_state = 'stopped' + + self.expect("next", substrs=['Process', expected_state]) + + if expected_state == 'exited': + self.expect( + "thread list", + error=True, + substrs=['Process must be launched']) + else: + self.check_stop_reason() + + def recursive_inferior_crashing_expr_step_expr(self): + """Test that lldb expressions work before and after stepping after a crash.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + self.runCmd("run", RUN_SUCCEEDED) + self.check_stop_reason() + + # The lldb expression interpreter should be able to read from addresses + # of the inferior after a crash. + self.expect("p null", startstr='(char *) $0 = 0x0') + + self.runCmd("next") + + # The lldb expression interpreter should be able to read from addresses + # of the inferior after a step. + self.expect("p null", startstr='(char *) $1 = 0x0') + + self.check_stop_reason() diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-crashing/recursive-inferior/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-crashing/recursive-inferior/main.c new file mode 100644 index 00000000000..25e6e8df0b9 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inferior-crashing/recursive-inferior/main.c @@ -0,0 +1,19 @@ +void recursive_function(int i) +{ + if (i < 10) + { + recursive_function(i + 1); + } + else + { + char *null=0; + *null = 0; // Crash here. + } +} + +int main(int argc, char *argv[]) +{ + recursive_function(0); + return 0; +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inline-stepping/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inline-stepping/Makefile new file mode 100644 index 00000000000..362b89d7f99 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inline-stepping/Makefile @@ -0,0 +1,8 @@ +CXX_SOURCES := calling.cpp + +ifneq (,$(findstring icc,$(CC))) + CXXFLAGS_EXTRAS := -debug inline-debug-info +endif + + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inline-stepping/TestInlineStepping.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inline-stepping/TestInlineStepping.py new file mode 100644 index 00000000000..40e29e614ad --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inline-stepping/TestInlineStepping.py @@ -0,0 +1,330 @@ +"""Test stepping over and into inlined functions.""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestInlineStepping(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @add_test_categories(['pyapi']) + @expectedFailureAll( + compiler="icc", + bugnumber="# Not really a bug. ICC combines two inlined functions.") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr32343") + @expectedFailureAll(archs=["aarch64"], oslist=["linux"], + bugnumber="llvm.org/pr44057") + def test_with_python_api(self): + """Test stepping over and into inlined functions.""" + self.build() + self.inline_stepping() + + @add_test_categories(['pyapi']) + def test_step_over_with_python_api(self): + """Test stepping over and into inlined functions.""" + self.build() + self.inline_stepping_step_over() + + @add_test_categories(['pyapi']) + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr32343") + def test_step_in_template_with_python_api(self): + """Test stepping in to templated functions.""" + self.build() + self.step_in_template() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line numbers that we will step to in main: + self.main_source = "calling.cpp" + self.source_lines = {} + functions = [ + 'caller_ref_1', + 'caller_ref_2', + 'inline_ref_1', + 'inline_ref_2', + 'called_by_inline_ref', + 'caller_trivial_1', + 'caller_trivial_2', + 'inline_trivial_1', + 'inline_trivial_2', + 'called_by_inline_trivial'] + for name in functions: + self.source_lines[name] = line_number( + self.main_source, "// In " + name + ".") + self.main_source_spec = lldb.SBFileSpec(self.main_source) + + def do_step(self, step_type, destination_line_entry, test_stack_depth): + expected_stack_depth = self.thread.GetNumFrames() + if step_type == "into": + expected_stack_depth += 1 + self.thread.StepInto() + elif step_type == "out": + expected_stack_depth -= 1 + self.thread.StepOut() + elif step_type == "over": + self.thread.StepOver() + else: + self.fail("Unrecognized step type: " + step_type) + + threads = lldbutil.get_stopped_threads( + self.process, lldb.eStopReasonPlanComplete) + if len(threads) != 1: + destination_description = lldb.SBStream() + destination_line_entry.GetDescription(destination_description) + self.fail( + "Failed to stop due to step " + + step_type + + " operation stepping to: " + + destination_description.GetData()) + + self.thread = threads[0] + + stop_line_entry = self.thread.GetFrameAtIndex(0).GetLineEntry() + self.assertTrue( + stop_line_entry.IsValid(), + "Stop line entry was not valid.") + + # Don't use the line entry equal operator because we don't care about + # the column number. + stop_at_right_place = (stop_line_entry.GetFileSpec() == destination_line_entry.GetFileSpec( + ) and stop_line_entry.GetLine() == destination_line_entry.GetLine()) + if not stop_at_right_place: + destination_description = lldb.SBStream() + destination_line_entry.GetDescription(destination_description) + + actual_description = lldb.SBStream() + stop_line_entry.GetDescription(actual_description) + + self.fail( + "Step " + + step_type + + " stopped at wrong place: expected: " + + destination_description.GetData() + + " got: " + + actual_description.GetData() + + ".") + + real_stack_depth = self.thread.GetNumFrames() + + if test_stack_depth and real_stack_depth != expected_stack_depth: + destination_description = lldb.SBStream() + destination_line_entry.GetDescription(destination_description) + self.fail( + "Step %s to %s got wrong number of frames, should be: %d was: %d." % + (step_type, + destination_description.GetData(), + expected_stack_depth, + real_stack_depth)) + + def run_step_sequence(self, step_sequence): + """This function takes a list of duples instructing how to run the program. The first element in each duple is + a source pattern for the target location, and the second is the operation that will take you from the current + source location to the target location. It will then run all the steps in the sequence. + It will check that you arrived at the expected source location at each step, and that the stack depth changed + correctly for the operation in the sequence.""" + + target_line_entry = lldb.SBLineEntry() + target_line_entry.SetFileSpec(self.main_source_spec) + + test_stack_depth = True + # Work around for <rdar://problem/16363195>, the darwin unwinder seems flakey about whether it duplicates the first frame + # or not, which makes counting stack depth unreliable. + if self.platformIsDarwin(): + test_stack_depth = False + + for step_pattern in step_sequence: + step_stop_line = line_number(self.main_source, step_pattern[0]) + target_line_entry.SetLine(step_stop_line) + self.do_step(step_pattern[1], target_line_entry, test_stack_depth) + + def inline_stepping(self): + """Use Python APIs to test stepping over and hitting breakpoints.""" + exe = self.getBuildArtifact("a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + break_1_in_main = target.BreakpointCreateBySourceRegex( + '// Stop here and step over to set up stepping over.', self.main_source_spec) + self.assertTrue(break_1_in_main, VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + self.process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + + self.assertTrue(self.process, PROCESS_IS_VALID) + + # The stop reason of the thread should be breakpoint. + threads = lldbutil.get_threads_stopped_at_breakpoint( + self.process, break_1_in_main) + + if len(threads) != 1: + self.fail("Failed to stop at first breakpoint in main.") + + self.thread = threads[0] + + # Step over the inline_value = 0 line to get us to inline_trivial_1 called from main. Doing it this way works + # around a bug in lldb where the breakpoint on the containing line of an inlined function with no return value + # gets set past the insertion line in the function. + # Then test stepping over a simple inlined function. Note, to test all the parts of the inlined stepping + # the calls inline_stepping_1 and inline_stepping_2 should line up at the same address, that way we will test + # the "virtual" stepping. + # FIXME: Put in a check to see if that is true and warn if it is not. + + step_sequence = [["// At inline_trivial_1 called from main.", "over"], + ["// At first call of caller_trivial_1 in main.", "over"]] + self.run_step_sequence(step_sequence) + + # Now step from caller_ref_1 all the way into called_by_inline_trivial + + step_sequence = [["// In caller_trivial_1.", "into"], + ["// In caller_trivial_2.", "into"], + ["// In inline_trivial_1.", "into"], + ["// In inline_trivial_2.", "into"], + ["// At caller_by_inline_trivial in inline_trivial_2.", "over"], + ["// In called_by_inline_trivial.", "into"]] + self.run_step_sequence(step_sequence) + + # Now run to the inline_trivial_1 just before the immediate step into + # inline_trivial_2: + + break_2_in_main = target.BreakpointCreateBySourceRegex( + '// At second call of caller_trivial_1 in main.', self.main_source_spec) + self.assertTrue(break_2_in_main, VALID_BREAKPOINT) + + threads = lldbutil.continue_to_breakpoint( + self.process, break_2_in_main) + self.assertTrue( + len(threads) == 1, + "Successfully ran to call site of second caller_trivial_1 call.") + self.thread = threads[0] + + step_sequence = [["// In caller_trivial_1.", "into"], + ["// In caller_trivial_2.", "into"], + ["// In inline_trivial_1.", "into"]] + self.run_step_sequence(step_sequence) + + # Then call some trivial function, and make sure we end up back where + # we were in the inlined call stack: + + frame = self.thread.GetFrameAtIndex(0) + before_line_entry = frame.GetLineEntry() + value = frame.EvaluateExpression("function_to_call()") + after_line_entry = frame.GetLineEntry() + + self.assertTrue( + before_line_entry.GetLine() == after_line_entry.GetLine(), + "Line entry before and after function calls are the same.") + + # Now make sure stepping OVER in the middle of the stack works, and + # then check finish from the inlined frame: + + step_sequence = [["// At increment in inline_trivial_1.", "over"], + ["// At increment in caller_trivial_2.", "out"]] + self.run_step_sequence(step_sequence) + + # Now run to the place in main just before the first call to + # caller_ref_1: + + break_3_in_main = target.BreakpointCreateBySourceRegex( + '// At first call of caller_ref_1 in main.', self.main_source_spec) + self.assertTrue(break_3_in_main, VALID_BREAKPOINT) + + threads = lldbutil.continue_to_breakpoint( + self.process, break_3_in_main) + self.assertTrue( + len(threads) == 1, + "Successfully ran to call site of first caller_ref_1 call.") + self.thread = threads[0] + + step_sequence = [["// In caller_ref_1.", "into"], + ["// In caller_ref_2.", "into"], + ["// In inline_ref_1.", "into"], + ["// In inline_ref_2.", "into"], + ["// In called_by_inline_ref.", "into"], + ["// In inline_ref_2.", "out"], + ["// In inline_ref_1.", "out"], + ["// At increment in inline_ref_1.", "over"], + ["// In caller_ref_2.", "out"], + ["// At increment in caller_ref_2.", "over"]] + self.run_step_sequence(step_sequence) + + def inline_stepping_step_over(self): + """Use Python APIs to test stepping over and hitting breakpoints.""" + exe = self.getBuildArtifact("a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + break_1_in_main = target.BreakpointCreateBySourceRegex( + '// At second call of caller_ref_1 in main.', self.main_source_spec) + self.assertTrue(break_1_in_main, VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + self.process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + + self.assertTrue(self.process, PROCESS_IS_VALID) + + # The stop reason of the thread should be breakpoint. + threads = lldbutil.get_threads_stopped_at_breakpoint( + self.process, break_1_in_main) + + if len(threads) != 1: + self.fail("Failed to stop at first breakpoint in main.") + + self.thread = threads[0] + + step_sequence = [["// In caller_ref_1.", "into"], + ["// In caller_ref_2.", "into"], + ["// At increment in caller_ref_2.", "over"]] + self.run_step_sequence(step_sequence) + + def step_in_template(self): + """Use Python APIs to test stepping in to templated functions.""" + exe = self.getBuildArtifact("a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + break_1_in_main = target.BreakpointCreateBySourceRegex( + '// Call max_value template', self.main_source_spec) + self.assertTrue(break_1_in_main, VALID_BREAKPOINT) + + break_2_in_main = target.BreakpointCreateBySourceRegex( + '// Call max_value specialized', self.main_source_spec) + self.assertTrue(break_2_in_main, VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + self.process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(self.process, PROCESS_IS_VALID) + + # The stop reason of the thread should be breakpoint. + threads = lldbutil.get_threads_stopped_at_breakpoint( + self.process, break_1_in_main) + + if len(threads) != 1: + self.fail("Failed to stop at first breakpoint in main.") + + self.thread = threads[0] + + step_sequence = [["// In max_value template", "into"]] + self.run_step_sequence(step_sequence) + + threads = lldbutil.continue_to_breakpoint( + self.process, break_2_in_main) + self.assertEqual( + len(threads), + 1, + "Successfully ran to call site of second caller_trivial_1 call.") + self.thread = threads[0] + + step_sequence = [["// In max_value specialized", "into"]] + self.run_step_sequence(step_sequence) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inline-stepping/calling.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inline-stepping/calling.cpp new file mode 100644 index 00000000000..9982fbf4273 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/inline-stepping/calling.cpp @@ -0,0 +1,136 @@ +#include <algorithm> +#include <cstdio> +#include <string> + +inline int inline_ref_1 (int &value) __attribute__((always_inline)); +inline int inline_ref_2 (int &value) __attribute__((always_inline)); + +int caller_ref_1 (int &value); +int caller_ref_2 (int &value); + +int called_by_inline_ref (int &value); + +inline void inline_trivial_1 () __attribute__((always_inline)); +inline void inline_trivial_2 () __attribute__((always_inline)); + +void caller_trivial_1 (); +void caller_trivial_2 (); + +void called_by_inline_trivial (); + +static int inline_value; + +int +function_to_call () +{ + return inline_value; +} + +int +caller_ref_1 (int &value) +{ + int increment = caller_ref_2(value); // In caller_ref_1. + value += increment; // At increment in caller_ref_1. + return value; +} + +int +caller_ref_2 (int &value) +{ + int increment = inline_ref_1 (value); // In caller_ref_2. + value += increment; // At increment in caller_ref_2. + return value; +} + +int +called_by_inline_ref (int &value) +{ + value += 1; // In called_by_inline_ref. + return value; +} + +int +inline_ref_1 (int &value) +{ + int increment = inline_ref_2(value); // In inline_ref_1. + value += increment; // At increment in inline_ref_1. + return value; +} + +int +inline_ref_2 (int &value) +{ + int increment = called_by_inline_ref (value); // In inline_ref_2. + value += 1; // At increment in inline_ref_2. + return value; +} + +void +caller_trivial_1 () +{ + caller_trivial_2(); // In caller_trivial_1. + inline_value += 1; +} + +void +caller_trivial_2 () +{ + inline_trivial_1 (); // In caller_trivial_2. + inline_value += 1; // At increment in caller_trivial_2. +} + +void +called_by_inline_trivial () +{ + inline_value += 1; // In called_by_inline_trivial. +} + +void +inline_trivial_1 () +{ + inline_trivial_2(); // In inline_trivial_1. + inline_value += 1; // At increment in inline_trivial_1. +} + +void +inline_trivial_2 () +{ + inline_value += 1; // In inline_trivial_2. + called_by_inline_trivial (); // At caller_by_inline_trivial in inline_trivial_2. +} + +template<typename T> T +max_value(const T& lhs, const T& rhs) +{ + return std::max(lhs, rhs); // In max_value template +} + +template<> std::string +max_value(const std::string& lhs, const std::string& rhs) +{ + return (lhs.size() > rhs.size()) ? lhs : rhs; // In max_value specialized +} + +int +main (int argc, char **argv) +{ + + inline_value = 0; // Stop here and step over to set up stepping over. + + inline_trivial_1 (); // At inline_trivial_1 called from main. + + caller_trivial_1(); // At first call of caller_trivial_1 in main. + + caller_trivial_1(); // At second call of caller_trivial_1 in main. + + caller_ref_1 (argc); // At first call of caller_ref_1 in main. + + caller_ref_1 (argc); // At second call of caller_ref_1 in main. + + function_to_call (); // Make sure debug info for this function gets generated. + + max_value(123, 456); // Call max_value template + max_value(std::string("abc"), std::string("0022")); // Call max_value specialized + + return 0; // About to return from main. +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/jitloader_gdb/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/jitloader_gdb/Makefile new file mode 100644 index 00000000000..357b1f83684 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/jitloader_gdb/Makefile @@ -0,0 +1,9 @@ +C_SOURCES := main.c + +all: a.out simple + +include Makefile.rules + +simple: + $(MAKE) -f $(MAKEFILE_RULES) \ + C_SOURCES=simple.c EXE=simple diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/jitloader_gdb/TestJITLoaderGDB.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/jitloader_gdb/TestJITLoaderGDB.py new file mode 100644 index 00000000000..4bd4150185c --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/jitloader_gdb/TestJITLoaderGDB.py @@ -0,0 +1,118 @@ +"""Test for the JITLoaderGDB interface""" + + +import unittest2 +import os +import lldb +from lldbsuite.test import lldbutil +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * + +file_index = 0 + +class JITLoaderGDBTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipTestIfFn( + lambda: "Skipped because the test crashes the test runner", + bugnumber="llvm.org/pr24702") + @unittest2.expectedFailure("llvm.org/pr24702") + def test_bogus_values(self): + """Test that we handle inferior misusing the GDB JIT interface""" + self.build() + exe = self.getBuildArtifact("a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # launch the process, do not stop at entry point. + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + # The inferior will now pass bogus values over the interface. Make sure + # we don't crash. + + self.assertEqual(process.GetState(), lldb.eStateExited) + self.assertEqual(process.GetExitStatus(), 0) + + def gen_log_file(self): + global file_index + ++file_index + logfile = os.path.join( + self.getBuildDir(), + "jitintgdb-" + self.getArchitecture() + "-" + + str(file_index) + ".txt") + + def cleanup(): + if os.path.exists(logfile): + os.unlink(logfile) + self.addTearDownHook(cleanup) + return logfile + + def test_jit_int_default(self): + self.expect("settings show plugin.jit-loader.gdb.enable", + substrs=["plugin.jit-loader.gdb.enable (enum) = default"]) + + @skipIfWindows # This test fails on Windows during C code build + def test_jit_int_on(self): + """Tests interface with 'enable' settings 'on'""" + self.build() + exe = self.getBuildArtifact("simple") + + logfile = self.gen_log_file() + self.runCmd("log enable -f %s lldb jit" % (logfile)) + self.runCmd("settings set plugin.jit-loader.gdb.enable on") + def cleanup(): + self.runCmd("log disable lldb") + self.runCmd("settings set plugin.jit-loader.gdb.enable default") + self.addTearDownHook(cleanup) + + # launch the process + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + self.assertEqual(process.GetState(), lldb.eStateExited) + self.assertEqual(process.GetExitStatus(), 0) + + logcontent = "" + if os.path.exists(logfile): + logcontent = open(logfile).read() + self.assertIn( + "SetJITBreakpoint setting JIT breakpoint", logcontent) + + @skipIfWindows # This test fails on Windows during C code build + def test_jit_int_off(self): + """Tests interface with 'enable' settings 'off'""" + self.build() + exe = self.getBuildArtifact("simple") + + logfile = self.gen_log_file() + self.runCmd("log enable -f %s lldb jit" % (logfile)) + self.runCmd("settings set plugin.jit-loader.gdb.enable off") + def cleanup(): + self.runCmd("log disable lldb") + self.runCmd("settings set plugin.jit-loader.gdb.enable default") + self.addTearDownHook(cleanup) + + # launch the process + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + self.assertEqual(process.GetState(), lldb.eStateExited) + self.assertEqual(process.GetExitStatus(), 0) + + if os.path.exists(logfile): + logcontent = open(logfile).read() + self.assertNotIn( + "SetJITBreakpoint setting JIT breakpoint", logcontent) + else: + self.assertTrue(false) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/jitloader_gdb/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/jitloader_gdb/main.c new file mode 100644 index 00000000000..6a8ec50e663 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/jitloader_gdb/main.c @@ -0,0 +1,44 @@ +#include <inttypes.h> + +// GDB JIT interface +enum JITAction { JIT_NOACTION, JIT_REGISTER_FN, JIT_UNREGISTER_FN }; + +struct JITCodeEntry +{ + struct JITCodeEntry* next; + struct JITCodeEntry* prev; + const char *symfile_addr; + uint64_t symfile_size; +}; + +struct JITDescriptor +{ + uint32_t version; + uint32_t action_flag; + struct JITCodeEntry* relevant_entry; + struct JITCodeEntry* first_entry; +}; + +struct JITDescriptor __jit_debug_descriptor = { 1, JIT_NOACTION, 0, 0 }; + +void __jit_debug_register_code() +{ +} +// end GDB JIT interface + +struct JITCodeEntry entry; + +int main() +{ + // Create a code entry with a bogus size + entry.next = entry.prev = 0; + entry.symfile_addr = (char *)&entry; + entry.symfile_size = (uint64_t)47<<32; + + __jit_debug_descriptor.relevant_entry = __jit_debug_descriptor.first_entry = &entry; + __jit_debug_descriptor.action_flag = JIT_REGISTER_FN; + + __jit_debug_register_code(); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/jitloader_gdb/simple.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/jitloader_gdb/simple.c new file mode 100644 index 00000000000..77b1a2ad812 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/jitloader_gdb/simple.c @@ -0,0 +1,20 @@ +#include <inttypes.h> + +// GDB JIT interface stub +struct +{ + uint32_t version; + uint32_t action_flag; + void* relevant_entry; + void* first_entry; +} __jit_debug_descriptor = { 1, 0, 0, 0 }; + +void __jit_debug_register_code() +{ +} +// end GDB JIT interface stub + +int main() +{ + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/lazy-loading/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/lazy-loading/Makefile new file mode 100644 index 00000000000..3d0b98f13f3 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/lazy-loading/Makefile @@ -0,0 +1,2 @@ +CXX_SOURCES := main.cpp +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/lazy-loading/TestLazyLoading.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/lazy-loading/TestLazyLoading.py new file mode 100644 index 00000000000..dddd4dceb37 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/lazy-loading/TestLazyLoading.py @@ -0,0 +1,236 @@ +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +""" +This test ensures that we only create Clang AST nodes in our module AST +when we actually need them. + +All tests in this file behave like this: + 1. Use LLDB to do something (expression evaluation, breakpoint setting, etc.). + 2. Check that certain Clang AST nodes were not loaded during the previous + step. +""" + +class TestCase(TestBase): + + NO_DEBUG_INFO_TESTCASE = True + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + TestBase.setUp(self) + # Only build this test once. + self.build() + + # Clang declaration kind we are looking for. + class_decl_kind = "CXXRecordDecl" + # FIXME: This shouldn't be a CXXRecordDecl, but that's how we model + # structs in Clang. + struct_decl_kind = "CXXRecordDecl" + + # The decls we use in this program in the format that + # decl_in_line and decl_completed_in_line expect (which is a pair of + # node type and the unqualified declaration name. + struct_first_member_decl = [struct_decl_kind, "StructFirstMember"] + struct_behind_ptr_decl = [struct_decl_kind, "StructBehindPointer"] + struct_behind_ref_decl = [struct_decl_kind, "StructBehindRef"] + struct_member_decl = [struct_decl_kind, "StructMember"] + some_struct_decl = [struct_decl_kind, "SomeStruct"] + other_struct_decl = [struct_decl_kind, "OtherStruct"] + class_in_namespace_decl = [class_decl_kind, "ClassInNamespace"] + class_we_enter_decl = [class_decl_kind, "ClassWeEnter"] + class_member_decl = [struct_decl_kind, "ClassMember"] + unused_class_member_decl = [struct_decl_kind, "UnusedClassMember"] + unused_class_member_ptr_decl = [struct_decl_kind, "UnusedClassMemberPtr"] + + def assert_no_decls_loaded(self): + """ + Asserts that no known declarations in this test are loaded + into the module's AST. + """ + self.assert_decl_not_loaded(self.struct_first_member_decl) + self.assert_decl_not_loaded(self.struct_behind_ptr_decl) + self.assert_decl_not_loaded(self.struct_behind_ref_decl) + self.assert_decl_not_loaded(self.struct_member_decl) + self.assert_decl_not_loaded(self.some_struct_decl) + self.assert_decl_not_loaded(self.other_struct_decl) + self.assert_decl_not_loaded(self.class_in_namespace_decl) + self.assert_decl_not_loaded(self.class_member_decl) + self.assert_decl_not_loaded(self.unused_class_member_decl) + + def get_ast_dump(self): + """Returns the dumped Clang AST of the module as a string""" + res = lldb.SBCommandReturnObject() + ci = self.dbg.GetCommandInterpreter() + ci.HandleCommand('target modules dump ast a.out', res) + self.assertTrue(res.Succeeded()) + return res.GetOutput() + + def decl_in_line(self, line, decl): + """ + Returns true iff the given line declares the given Clang decl. + The line is expected to be in the form of Clang's AST dump. + """ + line = line.rstrip() + "\n" + decl_kind = "-" + decl[0] + " " + # Either the decl is somewhere in the line or at the end of + # the line. + decl_name = " " + decl[1] + " " + decl_name_eol = " " + decl[1] + "\n" + if not decl_kind in line: + return False + return decl_name in line or decl_name_eol in line + + def decl_completed_in_line(self, line, decl): + """ + Returns true iff the given line declares the given Clang decl and + the decl was completed (i.e., it has no undeserialized declarations + in it). + """ + return self.decl_in_line(line, decl) and not "<undeserialized declarations>" in line + + # The following asserts are used for checking if certain Clang declarations + # were loaded or not since the target was created. + + def assert_decl_loaded(self, decl): + """ + Asserts the given decl is currently loaded. + Note: This test is about checking that types/declarations are not + loaded. If this assert fails it is usually fine to turn it into a + assert_decl_not_loaded or assert_decl_not_completed assuming LLDB's + functionality has not suffered by not loading this declaration. + """ + ast = self.get_ast_dump() + found = False + for line in ast.splitlines(): + if self.decl_in_line(line, decl): + found = True + self.assertTrue(self.decl_completed_in_line(line, decl), + "Should have called assert_decl_not_completed") + self.assertTrue(found, "Declaration no longer loaded " + str(decl) + + ".\nAST:\n" + ast) + + def assert_decl_not_completed(self, decl): + """ + Asserts that the given decl is currently not completed in the module's + AST. It may be loaded but then can can only contain undeserialized + declarations. + """ + ast = self.get_ast_dump() + found = False + for line in ast.splitlines(): + error_msg = "Unexpected completed decl: '" + line + "'.\nAST:\n" + ast + self.assertFalse(self.decl_completed_in_line(line, decl), error_msg) + + def assert_decl_not_loaded(self, decl): + """ + Asserts that the given decl is currently not loaded in the module's + AST. + """ + ast = self.get_ast_dump() + found = False + for line in ast.splitlines(): + error_msg = "Unexpected loaded decl: '" + line + "'\nAST:\n" + ast + self.assertFalse(self.decl_in_line(line, decl), error_msg) + + + def clean_setup(self, location): + """ + Runs to the line with the source line with the given location string + and ensures that our module AST is empty. + """ + lldbutil.run_to_source_breakpoint(self, + "// Location: " + location, lldb.SBFileSpec("main.cpp")) + # Make sure no declarations are loaded initially. + self.assert_no_decls_loaded() + + @add_test_categories(["dwarf"]) + def test_arithmetic_expression_in_main(self): + """ Runs a simple arithmetic expression which should load nothing. """ + self.clean_setup(location="multiple locals function") + + self.expect("expr 1 + (int)2.0", substrs=['(int) $0']) + + # This should not have loaded any decls. + self.assert_no_decls_loaded() + + @add_test_categories(["dwarf"]) + def test_printing_local_variable_in_other_struct_func(self): + """ + Prints a local variable and makes sure no unrelated types are loaded. + """ + self.clean_setup(location="other struct function") + + self.expect("expr other_struct_var", substrs=['(OtherStruct) $0']) + # The decl we run on was loaded. + self.assert_decl_loaded(self.other_struct_decl) + + # This should not have loaded anything else. + self.assert_decl_not_loaded(self.some_struct_decl) + self.assert_decl_not_loaded(self.class_in_namespace_decl) + + @add_test_categories(["dwarf"]) + def test_printing_struct_with_multiple_locals(self): + """ + Prints a local variable and checks that we don't load other local + variables. + """ + self.clean_setup(location="multiple locals function") + + self.expect("expr struct_var", substrs=['(SomeStruct) $0']) + + # We loaded SomeStruct and its member types for printing. + self.assert_decl_loaded(self.some_struct_decl) + self.assert_decl_loaded(self.struct_behind_ptr_decl) + self.assert_decl_loaded(self.struct_behind_ref_decl) + + # FIXME: We don't use these variables, but we seem to load all local + # local variables. + self.assert_decl_not_completed(self.other_struct_decl) + self.assert_decl_not_completed(self.class_in_namespace_decl) + + @add_test_categories(["dwarf"]) + def test_addr_of_struct(self): + """ + Prints the address of a local variable (which is a struct). + """ + self.clean_setup(location="multiple locals function") + + self.expect("expr &struct_var", substrs=['(SomeStruct *) $0']) + + # We loaded SomeStruct. + self.assert_decl_loaded(self.some_struct_decl) + + # The member declarations should not be completed. + self.assert_decl_not_completed(self.struct_behind_ptr_decl) + self.assert_decl_not_completed(self.struct_behind_ref_decl) + + # FIXME: The first member was behind a pointer so it shouldn't be + # completed. Somehow LLDB really wants to load the first member, so + # that is why have it defined here. + self.assert_decl_loaded(self.struct_first_member_decl) + + # FIXME: We don't use these variables, but we seem to load all local + # local variables. + self.assert_decl_not_completed(self.other_struct_decl) + self.assert_decl_not_completed(self.class_in_namespace_decl) + + @add_test_categories(["dwarf"]) + def test_class_function_access_member(self): + self.clean_setup(location="class function") + + self.expect("expr member", substrs=['(ClassMember) $0']) + + # We loaded the current class we touched. + self.assert_decl_loaded(self.class_we_enter_decl) + # We loaded the unused members of this class. + self.assert_decl_loaded(self.unused_class_member_decl) + self.assert_decl_not_completed(self.unused_class_member_ptr_decl) + # We loaded the member we used. + self.assert_decl_loaded(self.class_member_decl) + + # This should not have loaded anything else. + self.assert_decl_not_loaded(self.other_struct_decl) + self.assert_decl_not_loaded(self.some_struct_decl) + self.assert_decl_not_loaded(self.class_in_namespace_decl) + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/lazy-loading/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/lazy-loading/main.cpp new file mode 100644 index 00000000000..34d62b483b6 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/lazy-loading/main.cpp @@ -0,0 +1,69 @@ +//----------------------------------------------------------------------------// +// Struct loading declarations. + +struct StructFirstMember { int i; }; +struct StructBehindPointer { int i; }; +struct StructBehindRef { int i; }; +struct StructMember { int i; }; + +StructBehindRef struct_instance; + +struct SomeStruct { + StructFirstMember *first; + StructBehindPointer *ptr; + StructMember member; + StructBehindRef &ref = struct_instance; +}; + +struct OtherStruct { + int member_int; +}; + +//----------------------------------------------------------------------------// +// Class loading declarations. + +struct ClassMember { int i; }; +struct UnusedClassMember { int i; }; +struct UnusedClassMemberPtr { int i; }; + +namespace NS { +class ClassInNamespace { + int i; +}; +class ClassWeEnter { +public: + int dummy; // Prevent bug where LLDB always completes first member. + ClassMember member; + UnusedClassMember unused_member; + UnusedClassMemberPtr *unused_member_ptr; + int enteredFunction() { + return member.i; // Location: class function + } +}; +}; + +//----------------------------------------------------------------------------// +// Function we can stop in. + +int functionWithOtherStruct() { + OtherStruct other_struct_var; + other_struct_var.member_int++; // Location: other struct function + return other_struct_var.member_int; +} + +int functionWithMultipleLocals() { + SomeStruct struct_var; + OtherStruct other_struct_var; + NS::ClassInNamespace namespace_class; + other_struct_var.member_int++; // Location: multiple locals function + return other_struct_var.member_int; +} + +int main(int argc, char **argv) { + NS::ClassWeEnter c; + c.enteredFunction(); + + functionWithOtherStruct(); + functionWithMultipleLocals(); + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/.categories b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/.categories new file mode 100644 index 00000000000..c00c25822e4 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/.categories @@ -0,0 +1 @@ +basic_process diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/Makefile new file mode 100644 index 00000000000..00054aabd4a --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/Makefile @@ -0,0 +1,32 @@ +LD_EXTRAS := -L. -lloadunload_d +CXX_SOURCES := main.cpp +USE_LIBDL := 1 + +a.out: lib_b lib_a lib_c lib_d hidden_lib_d + +include Makefile.rules + +lib_a: lib_b + $(MAKE) -f $(MAKEFILE_RULES) \ + DYLIB_ONLY=YES DYLIB_CXX_SOURCES=a.cpp DYLIB_NAME=loadunload_a \ + LD_EXTRAS="-L. -lloadunload_b" + +lib_b: + $(MAKE) -f $(MAKEFILE_RULES) \ + DYLIB_ONLY=YES DYLIB_CXX_SOURCES=b.cpp DYLIB_NAME=loadunload_b + +lib_c: + $(MAKE) -f $(MAKEFILE_RULES) \ + DYLIB_ONLY=YES DYLIB_CXX_SOURCES=c.cpp DYLIB_NAME=loadunload_c + +lib_d: + $(MAKE) -f $(MAKEFILE_RULES) \ + DYLIB_ONLY=YES DYLIB_CXX_SOURCES=d.cpp DYLIB_NAME=loadunload_d +ifeq ($(OS),Darwin) + install_name_tool -id @executable_path/libloadunload_d.dylib libloadunload_d.dylib +endif + +hidden_lib_d: + mkdir -p hidden + $(MAKE) VPATH=$(SRCDIR)/hidden -C hidden -f $(MAKEFILE_RULES) \ + DYLIB_ONLY=YES DYLIB_CXX_SOURCES=d.cpp DYLIB_NAME=loadunload_d diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/TestLoadUnload.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/TestLoadUnload.py new file mode 100644 index 00000000000..ae0934c7461 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/TestLoadUnload.py @@ -0,0 +1,452 @@ +""" +Test that breakpoint by symbol name works correctly with dynamic libs. +""" + +from __future__ import print_function + + +import os +import re +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +@skipIfWindows # Windows doesn't have dlopen and friends, dynamic libraries work differently +class LoadUnloadTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + self.setup_test() + # Invoke the default build rule. + self.build() + # Find the line number to break for main.cpp. + self.line = line_number( + 'main.cpp', + '// Set break point at this line for test_lldb_process_load_and_unload_commands().') + self.line_d_function = line_number( + 'd.cpp', '// Find this line number within d_dunction().') + + def setup_test(self): + lldbutil.mkdir_p(self.getBuildArtifact("hidden")) + if not self.platformIsDarwin(): + if not lldb.remote_platform and "LD_LIBRARY_PATH" in os.environ: + self.runCmd( + "settings set target.env-vars " + + self.dylibPath + + "=" + + os.environ["LD_LIBRARY_PATH"] + + ":" + + self.getBuildDir()) + else: + if lldb.remote_platform: + wd = lldb.remote_platform.GetWorkingDirectory() + else: + wd = self.getBuildDir() + self.runCmd( + "settings set target.env-vars " + + self.dylibPath + + "=" + + wd) + + def copy_shlibs_to_remote(self, hidden_dir=False): + """ Copies the shared libs required by this test suite to remote. + Does nothing in case of non-remote platforms. + """ + if lldb.remote_platform: + ext = 'so' + if self.platformIsDarwin(): + ext = 'dylib' + + shlibs = ['libloadunload_a.' + ext, 'libloadunload_b.' + ext, + 'libloadunload_c.' + ext, 'libloadunload_d.' + ext] + wd = lldb.remote_platform.GetWorkingDirectory() + cwd = os.getcwd() + for f in shlibs: + err = lldb.remote_platform.Put( + lldb.SBFileSpec(self.getBuildArtifact(f)), + lldb.SBFileSpec(os.path.join(wd, f))) + if err.Fail(): + raise RuntimeError( + "Unable copy '%s' to '%s'.\n>>> %s" % + (f, wd, err.GetCString())) + if hidden_dir: + shlib = 'libloadunload_d.' + ext + hidden_dir = os.path.join(wd, 'hidden') + hidden_file = os.path.join(hidden_dir, shlib) + err = lldb.remote_platform.MakeDirectory(hidden_dir) + if err.Fail(): + raise RuntimeError( + "Unable to create a directory '%s'." % hidden_dir) + err = lldb.remote_platform.Put( + lldb.SBFileSpec(os.path.join('hidden', shlib)), + lldb.SBFileSpec(hidden_file)) + if err.Fail(): + raise RuntimeError( + "Unable copy 'libloadunload_d.so' to '%s'.\n>>> %s" % + (wd, err.GetCString())) + + def setSvr4Support(self, enabled): + self.runCmd( + "settings set plugin.process.gdb-remote.use-libraries-svr4 {enabled}".format( + enabled="true" if enabled else "false" + ) + ) + + # libloadunload_d.so does not appear in the image list because executable + # dependencies are resolved relative to the debuggers PWD. Bug? + @expectedFailureAll(oslist=["linux"]) + @skipIfFreeBSD # llvm.org/pr14424 - missing FreeBSD Makefiles/testcase support + @not_remote_testsuite_ready + @skipIfWindows # Windows doesn't have dlopen and friends, dynamic libraries work differently + @expectedFailureNetBSD + def test_modules_search_paths(self): + """Test target modules list after loading a different copy of the library libd.dylib, and verifies that it works with 'target modules search-paths add'.""" + if self.platformIsDarwin(): + dylibName = 'libloadunload_d.dylib' + else: + dylibName = 'libloadunload_d.so' + + # The directory with the dynamic library we did not link to. + new_dir = os.path.join(self.getBuildDir(), "hidden") + + old_dylib = os.path.join(self.getBuildDir(), dylibName) + new_dylib = os.path.join(new_dir, dylibName) + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + self.expect("target modules list", + substrs=[old_dylib]) + # self.expect("target modules list -t 3", + # patterns = ["%s-[^-]*-[^-]*" % self.getArchitecture()]) + # Add an image search path substitution pair. + self.runCmd( + "target modules search-paths add %s %s" % + (self.getBuildDir(), new_dir)) + + self.expect("target modules search-paths list", + substrs=[self.getBuildDir(), new_dir]) + + self.expect( + "target modules search-paths query %s" % + self.getBuildDir(), + "Image search path successfully transformed", + substrs=[new_dir]) + + # Obliterate traces of libd from the old location. + os.remove(old_dylib) + # Inform (DY)LD_LIBRARY_PATH of the new path, too. + env_cmd_string = "settings set target.env-vars " + self.dylibPath + "=" + new_dir + if self.TraceOn(): + print("Set environment to: ", env_cmd_string) + self.runCmd(env_cmd_string) + self.runCmd("settings show target.env-vars") + + remove_dyld_path_cmd = "settings remove target.env-vars " + self.dylibPath + self.addTearDownHook( + lambda: self.dbg.HandleCommand(remove_dyld_path_cmd)) + + self.runCmd("run") + + self.expect( + "target modules list", + "LLDB successfully locates the relocated dynamic library", + substrs=[new_dylib]) + + # libloadunload_d.so does not appear in the image list because executable + # dependencies are resolved relative to the debuggers PWD. Bug? + @expectedFailureAll(oslist=["linux"]) + @skipIfFreeBSD # llvm.org/pr14424 - missing FreeBSD Makefiles/testcase support + @expectedFailureAndroid # wrong source file shows up for hidden library + @skipIfWindows # Windows doesn't have dlopen and friends, dynamic libraries work differently + @skipIfDarwinEmbedded + @expectedFailureNetBSD + def test_dyld_library_path(self): + """Test (DY)LD_LIBRARY_PATH after moving libd.dylib, which defines d_function, somewhere else.""" + self.copy_shlibs_to_remote(hidden_dir=True) + + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Shut off ANSI color usage so we don't get ANSI escape sequences + # mixed in with stop locations. + self.dbg.SetUseColor(False) + + if self.platformIsDarwin(): + dylibName = 'libloadunload_d.dylib' + dsymName = 'libloadunload_d.dylib.dSYM' + else: + dylibName = 'libloadunload_d.so' + + # The directory to relocate the dynamic library and its debugging info. + special_dir = "hidden" + if lldb.remote_platform: + wd = lldb.remote_platform.GetWorkingDirectory() + else: + wd = self.getBuildDir() + + old_dir = wd + new_dir = os.path.join(wd, special_dir) + old_dylib = os.path.join(old_dir, dylibName) + + remove_dyld_path_cmd = "settings remove target.env-vars " \ + + self.dylibPath + self.addTearDownHook( + lambda: self.dbg.HandleCommand(remove_dyld_path_cmd)) + + # For now we don't track (DY)LD_LIBRARY_PATH, so the old + # library will be in the modules list. + self.expect("target modules list", + substrs=[os.path.basename(old_dylib)], + matching=True) + + lldbutil.run_break_set_by_file_and_line( + self, "d.cpp", self.line_d_function, num_expected_locations=1) + # After run, make sure the non-hidden library is picked up. + self.expect("run", substrs=["return", "700"]) + + self.runCmd("continue") + + # Add the hidden directory first in the search path. + env_cmd_string = ("settings set target.env-vars %s=%s" % + (self.dylibPath, new_dir)) + if not self.platformIsDarwin(): + env_cmd_string += ":" + wd + self.runCmd(env_cmd_string) + + # This time, the hidden library should be picked up. + self.expect("run", substrs=["return", "12345"]) + + @expectedFailureAll( + bugnumber="llvm.org/pr25805", + hostoslist=["windows"], + triple='.*-android') + @skipIfFreeBSD # llvm.org/pr14424 - missing FreeBSD Makefiles/testcase support + @skipIfWindows # Windows doesn't have dlopen and friends, dynamic libraries work differently + def test_lldb_process_load_and_unload_commands(self): + self.setSvr4Support(False) + self.run_lldb_process_load_and_unload_commands() + + @expectedFailureAll( + bugnumber="llvm.org/pr25805", + hostoslist=["windows"], + triple='.*-android') + @skipIfFreeBSD # llvm.org/pr14424 - missing FreeBSD Makefiles/testcase support + @skipIfWindows # Windows doesn't have dlopen and friends, dynamic libraries work differently + def test_lldb_process_load_and_unload_commands_with_svr4(self): + self.setSvr4Support(True) + self.run_lldb_process_load_and_unload_commands() + + def run_lldb_process_load_and_unload_commands(self): + """Test that lldb process load/unload command work correctly.""" + self.copy_shlibs_to_remote() + + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Break at main.cpp before the call to dlopen(). + # Use lldb's process load command to load the dylib, instead. + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + ctx = self.platformContext + dylibName = ctx.shlib_prefix + 'loadunload_a.' + ctx.shlib_extension + localDylibPath = self.getBuildArtifact(dylibName) + if lldb.remote_platform: + wd = lldb.remote_platform.GetWorkingDirectory() + remoteDylibPath = lldbutil.join_remote_paths(wd, dylibName) + else: + remoteDylibPath = localDylibPath + + # Make sure that a_function does not exist at this point. + self.expect( + "image lookup -n a_function", + "a_function should not exist yet", + error=True, + matching=False, + patterns=["1 match found"]) + + # Use lldb 'process load' to load the dylib. + self.expect( + "process load %s --install=%s" % (localDylibPath, remoteDylibPath), + "%s loaded correctly" % dylibName, + patterns=[ + 'Loading "%s".*ok' % re.escape(localDylibPath), + 'Image [0-9]+ loaded']) + + # Search for and match the "Image ([0-9]+) loaded" pattern. + output = self.res.GetOutput() + pattern = re.compile("Image ([0-9]+) loaded") + for l in output.split(os.linesep): + #print("l:", l) + match = pattern.search(l) + if match: + break + index = match.group(1) + + # Now we should have an entry for a_function. + self.expect( + "image lookup -n a_function", + "a_function should now exist", + patterns=[ + "1 match found .*%s" % + dylibName]) + + # Use lldb 'process unload' to unload the dylib. + self.expect( + "process unload %s" % + index, + "%s unloaded correctly" % + dylibName, + patterns=[ + "Unloading .* with index %s.*ok" % + index]) + + self.runCmd("process continue") + + @skipIfFreeBSD # llvm.org/pr14424 - missing FreeBSD Makefiles/testcase support + def test_load_unload(self): + self.setSvr4Support(False) + self.run_load_unload() + + @skipIfFreeBSD # llvm.org/pr14424 - missing FreeBSD Makefiles/testcase support + def test_load_unload_with_svr4(self): + self.setSvr4Support(True) + self.run_load_unload() + + def run_load_unload(self): + """Test breakpoint by name works correctly with dlopen'ing.""" + self.copy_shlibs_to_remote() + + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Break by function name a_function (not yet loaded). + lldbutil.run_break_set_by_symbol( + self, "a_function", num_expected_locations=0) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint and at a_function. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'a_function', + 'stop reason = breakpoint']) + + # The breakpoint should have a hit count of 1. + self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, + substrs=[' resolved, hit count = 1']) + + # Issue the 'contnue' command. We should stop agaian at a_function. + # The stop reason of the thread should be breakpoint and at a_function. + self.runCmd("continue") + + # rdar://problem/8508987 + # The a_function breakpoint should be encountered twice. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'a_function', + 'stop reason = breakpoint']) + + # The breakpoint should have a hit count of 2. + self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, + substrs=[' resolved, hit count = 2']) + + @skipIfFreeBSD # llvm.org/pr14424 - missing FreeBSD Makefiles/testcase support + @skipIfWindows # Windows doesn't have dlopen and friends, dynamic libraries work differently + @expectedFailureAll(archs="aarch64", oslist="linux", + bugnumber="https://bugs.llvm.org/show_bug.cgi?id=27806") + def test_step_over_load(self): + self.setSvr4Support(False) + self.run_step_over_load() + + @skipIfFreeBSD # llvm.org/pr14424 - missing FreeBSD Makefiles/testcase support + @skipIfWindows # Windows doesn't have dlopen and friends, dynamic libraries work differently + @expectedFailureAll(archs="aarch64", oslist="linux", + bugnumber="https://bugs.llvm.org/show_bug.cgi?id=27806") + def test_step_over_load_with_svr4(self): + self.setSvr4Support(True) + self.run_step_over_load() + + def run_step_over_load(self): + """Test stepping over code that loads a shared library works correctly.""" + self.copy_shlibs_to_remote() + + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Break by function name a_function (not yet loaded). + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint and at a_function. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + self.runCmd( + "thread step-over", + "Stepping over function that loads library") + + # The stop reason should be step end. + self.expect("thread list", "step over succeeded.", + substrs=['stopped', + 'stop reason = step over']) + + # We can't find a breakpoint location for d_init before launching because + # executable dependencies are resolved relative to the debuggers PWD. Bug? + @expectedFailureAll(oslist=["linux"], triple=no_match('aarch64-.*-android')) + @skipIfFreeBSD # llvm.org/pr14424 - missing FreeBSD Makefiles/testcase support + @skipIfWindows # Windows doesn't have dlopen and friends, dynamic libraries work differently + @expectedFailureNetBSD + def test_static_init_during_load(self): + """Test that we can set breakpoints correctly in static initializers""" + self.copy_shlibs_to_remote() + + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + a_init_bp_num = lldbutil.run_break_set_by_symbol( + self, "a_init", num_expected_locations=0) + b_init_bp_num = lldbutil.run_break_set_by_symbol( + self, "b_init", num_expected_locations=0) + d_init_bp_num = lldbutil.run_break_set_by_symbol( + self, "d_init", num_expected_locations=1) + + self.runCmd("run", RUN_SUCCEEDED) + + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'd_init', + 'stop reason = breakpoint %d' % d_init_bp_num]) + + self.runCmd("continue") + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'b_init', + 'stop reason = breakpoint %d' % b_init_bp_num]) + self.expect("thread backtrace", + substrs=['b_init', + 'dlopen', + 'main']) + + self.runCmd("continue") + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'a_init', + 'stop reason = breakpoint %d' % a_init_bp_num]) + self.expect("thread backtrace", + substrs=['a_init', + 'dlopen', + 'main']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/a.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/a.cpp new file mode 100644 index 00000000000..ec34f9b974d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/a.cpp @@ -0,0 +1,21 @@ +//===-- a.c -----------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +extern int b_function (); + +int a_init() +{ + return 234; +} + +int a_global = a_init(); + +extern "C" int +a_function () +{ + return b_function (); +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/b.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/b.cpp new file mode 100644 index 00000000000..9db93841ab7 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/b.cpp @@ -0,0 +1,20 @@ +//===-- b.c -----------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +int b_init() +{ + return 345; +} + +int b_global = b_init(); + +int +b_function () +{ + return 500; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/c.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/c.cpp new file mode 100644 index 00000000000..cf0c146621e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/c.cpp @@ -0,0 +1,12 @@ +//===-- c.c -----------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +extern "C" int +c_function () +{ + return 600; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/cmds.txt b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/cmds.txt new file mode 100644 index 00000000000..1e4b198dc0d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/cmds.txt @@ -0,0 +1,2 @@ +breakpoint set -n a_function +run diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/d.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/d.cpp new file mode 100644 index 00000000000..a2135c50713 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/d.cpp @@ -0,0 +1,20 @@ +//===-- c.c -----------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +int d_init() +{ + return 123; +} + +int d_global = d_init(); + +int +d_function () +{ // Find this line number within d_dunction(). + return 700; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/hidden/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/hidden/Makefile new file mode 100644 index 00000000000..17fe6582a9e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/hidden/Makefile @@ -0,0 +1,7 @@ +LIB_PREFIX := loadunload_ + +DYLIB_NAME := $(LIB_PREFIX)d +DYLIB_CXX_SOURCES := d.cpp +DYLIB_ONLY := YES + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/hidden/d.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/hidden/d.cpp new file mode 100644 index 00000000000..d03d3c9f8c7 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/hidden/d.cpp @@ -0,0 +1,20 @@ +//===-- c.c -----------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +int d_init() +{ + return 456; +} + +int d_global = d_init(); + +int +d_function () +{ // Find this line number within d_dunction(). + return 12345; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/main.cpp new file mode 100644 index 00000000000..815f030d857 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_unload/main.cpp @@ -0,0 +1,79 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include <stdio.h> +#include <dlfcn.h> +#include <limits.h> +#include <string.h> +#include <unistd.h> +#include <libgen.h> +#include <stdlib.h> + +int +main (int argc, char const *argv[]) +{ +#if defined (__APPLE__) + const char *a_name = "@executable_path/libloadunload_a.dylib"; + const char *c_name = "@executable_path/libloadunload_c.dylib"; +#else + const char *a_name = "libloadunload_a.so"; + const char *c_name = "libloadunload_c.so"; +#endif + void *a_dylib_handle = NULL; + void *c_dylib_handle = NULL; + int (*a_function) (void); + + a_dylib_handle = dlopen (a_name, RTLD_NOW); // Set break point at this line for test_lldb_process_load_and_unload_commands(). + if (a_dylib_handle == NULL) + { + fprintf (stderr, "%s\n", dlerror()); + exit (1); + } + + a_function = (int (*) ()) dlsym (a_dylib_handle, "a_function"); + if (a_function == NULL) + { + fprintf (stderr, "%s\n", dlerror()); + exit (2); + } + printf ("First time around, got: %d\n", a_function ()); + dlclose (a_dylib_handle); + + c_dylib_handle = dlopen (c_name, RTLD_NOW); + if (c_dylib_handle == NULL) + { + fprintf (stderr, "%s\n", dlerror()); + exit (3); + } + a_function = (int (*) ()) dlsym (c_dylib_handle, "c_function"); + if (a_function == NULL) + { + fprintf (stderr, "%s\n", dlerror()); + exit (4); + } + + a_dylib_handle = dlopen (a_name, RTLD_NOW); + if (a_dylib_handle == NULL) + { + fprintf (stderr, "%s\n", dlerror()); + exit (5); + } + + a_function = (int (*) ()) dlsym (a_dylib_handle, "a_function"); + if (a_function == NULL) + { + fprintf (stderr, "%s\n", dlerror()); + exit (6); + } + printf ("Second time around, got: %d\n", a_function ()); + dlclose (a_dylib_handle); + + int d_function(void); + printf ("d_function returns: %d\n", d_function()); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/.categories b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/.categories new file mode 100644 index 00000000000..c00c25822e4 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/.categories @@ -0,0 +1 @@ +basic_process diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/Makefile new file mode 100644 index 00000000000..814a9601375 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/Makefile @@ -0,0 +1,11 @@ +CXX_SOURCES := main.cpp +USE_LIBDL := 1 + +all: hidden_lib a.out + +include Makefile.rules + +hidden_lib: + $(MAKE) VPATH=$(SRCDIR)/hidden -C hidden -f $(MAKEFILE_RULES) \ + DYLIB_ONLY=YES DYLIB_CXX_SOURCES=d.cpp DYLIB_NAME=loadunload + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/TestLoadUsingPaths.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/TestLoadUsingPaths.py new file mode 100644 index 00000000000..0adb3d09b60 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/TestLoadUsingPaths.py @@ -0,0 +1,141 @@ +""" +Test that SBProcess.LoadImageUsingPaths works correctly. +""" + + + +import os +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +@skipIfWindows # The Windows platform doesn't implement DoLoadImage. +class LoadUsingPathsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Make the hidden directory in the build hierarchy: + lldbutil.mkdir_p(self.getBuildArtifact("hidden")) + + # Invoke the default build rule. + self.build() + + ext = 'so' + if self.platformIsDarwin(): + ext = 'dylib' + self.lib_name = 'libloadunload.' + ext + + self.wd = os.path.realpath(self.getBuildDir()) + self.hidden_dir = os.path.join(self.wd, 'hidden') + self.hidden_lib = os.path.join(self.hidden_dir, self.lib_name) + + @skipIfFreeBSD # llvm.org/pr14424 - missing FreeBSD Makefiles/testcase support + @not_remote_testsuite_ready + @skipIfWindows # Windows doesn't have dlopen and friends, dynamic libraries work differently + @expectedFlakeyNetBSD + def test_load_using_paths(self): + """Test that we can load a module by providing a set of search paths.""" + if self.platformIsDarwin(): + dylibName = 'libloadunload_d.dylib' + else: + dylibName = 'libloadunload_d.so' + + # The directory with the dynamic library we did not link to. + path_dir = os.path.join(self.getBuildDir(), "hidden") + + (target, process, thread, + _) = lldbutil.run_to_source_breakpoint(self, + "Break here to do the load using paths", + lldb.SBFileSpec("main.cpp")) + error = lldb.SBError() + lib_spec = lldb.SBFileSpec(self.lib_name) + paths = lldb.SBStringList() + paths.AppendString(self.wd) + paths.AppendString(os.path.join(self.wd, "no_such_dir")) + + out_spec = lldb.SBFileSpec() + + # First try with no correct directories on the path, and make sure that doesn't blow up: + token = process.LoadImageUsingPaths(lib_spec, paths, out_spec, error) + self.assertEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Only looked on the provided path.") + + # Now add the correct dir to the paths list and try again: + paths.AppendString(self.hidden_dir) + token = process.LoadImageUsingPaths(lib_spec, paths, out_spec, error) + + self.assertNotEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Got a valid token") + self.assertEqual(out_spec, lldb.SBFileSpec(self.hidden_lib), "Found the expected library") + + # Make sure this really is in the image list: + loaded_module = target.FindModule(out_spec) + + self.assertTrue(loaded_module.IsValid(), "The loaded module is in the image list.") + + # Now see that we can call a function in the loaded module. + value = thread.frames[0].EvaluateExpression("d_function()", lldb.SBExpressionOptions()) + self.assertTrue(value.GetError().Success(), "Got a value from the expression") + ret_val = value.GetValueAsSigned() + self.assertEqual(ret_val, 12345, "Got the right value") + + # Make sure the token works to unload it: + process.UnloadImage(token) + + # Make sure this really is no longer in the image list: + loaded_module = target.FindModule(out_spec) + + self.assertFalse(loaded_module.IsValid(), "The unloaded module is no longer in the image list.") + + # Make sure a relative path also works: + paths.Clear() + paths.AppendString(os.path.join(self.wd, "no_such_dir")) + paths.AppendString(self.wd) + relative_spec = lldb.SBFileSpec(os.path.join("hidden", self.lib_name)) + + out_spec = lldb.SBFileSpec() + token = process.LoadImageUsingPaths(relative_spec, paths, out_spec, error) + + self.assertNotEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Got a valid token with relative path") + self.assertEqual(out_spec, lldb.SBFileSpec(self.hidden_lib), "Found the expected library with relative path") + + process.UnloadImage(token) + + # Make sure the presence of an empty path doesn't mess anything up: + paths.Clear() + paths.AppendString("") + paths.AppendString(os.path.join(self.wd, "no_such_dir")) + paths.AppendString(self.wd) + relative_spec = lldb.SBFileSpec(os.path.join("hidden", self.lib_name)) + + out_spec = lldb.SBFileSpec() + token = process.LoadImageUsingPaths(relative_spec, paths, out_spec, error) + + self.assertNotEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Got a valid token with included empty path") + self.assertEqual(out_spec, lldb.SBFileSpec(self.hidden_lib), "Found the expected library with included empty path") + + process.UnloadImage(token) + + + + # Finally, passing in an absolute path should work like the basename: + # This should NOT work because we've taken hidden_dir off the paths: + abs_spec = lldb.SBFileSpec(os.path.join(self.hidden_dir, self.lib_name)) + + token = process.LoadImageUsingPaths(lib_spec, paths, out_spec, error) + self.assertEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Only looked on the provided path.") + + # But it should work when we add the dir: + # Now add the correct dir to the paths list and try again: + paths.AppendString(self.hidden_dir) + token = process.LoadImageUsingPaths(lib_spec, paths, out_spec, error) + + self.assertNotEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Got a valid token") + self.assertEqual(out_spec, lldb.SBFileSpec(self.hidden_lib), "Found the expected library") + + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/hidden/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/hidden/Makefile new file mode 100644 index 00000000000..5e22c8a8ea7 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/hidden/Makefile @@ -0,0 +1,5 @@ +DYLIB_NAME := loadunload +DYLIB_CXX_SOURCES := d.cpp +DYLIB_ONLY := YES + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/hidden/d.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/hidden/d.cpp new file mode 100644 index 00000000000..d03d3c9f8c7 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/hidden/d.cpp @@ -0,0 +1,20 @@ +//===-- c.c -----------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +int d_init() +{ + return 456; +} + +int d_global = d_init(); + +int +d_function () +{ // Find this line number within d_dunction(). + return 12345; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/main.cpp new file mode 100644 index 00000000000..432774d36b5 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/main.cpp @@ -0,0 +1,15 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include <stdio.h> + +int +main (int argc, char const *argv[]) +{ + printf("Break here to do the load using paths."); + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/longjmp/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/longjmp/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/longjmp/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/longjmp/TestLongjmp.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/longjmp/TestLongjmp.py new file mode 100644 index 00000000000..fa7ffa64432 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/longjmp/TestLongjmp.py @@ -0,0 +1,85 @@ +""" +Test the use of setjmp/longjmp for non-local goto operations in a single-threaded inferior. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class LongjmpTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipIfDarwin # llvm.org/pr16769: LLDB on Mac OS X dies in function ReadRegisterBytes in GDBRemoteRegisterContext.cpp + @skipIfFreeBSD # llvm.org/pr17214 + @expectedFailureAll(oslist=["linux"], bugnumber="llvm.org/pr20231") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") + @expectedFlakeyNetBSD + def test_step_out(self): + """Test stepping when the inferior calls setjmp/longjmp, in particular, thread step-out.""" + self.build() + self.step_out() + + @skipIfDarwin # llvm.org/pr16769: LLDB on Mac OS X dies in function ReadRegisterBytes in GDBRemoteRegisterContext.cpp + @skipIfFreeBSD # llvm.org/pr17214 + @expectedFailureAll(oslist=["linux"], bugnumber="llvm.org/pr20231") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") + @skipIfNetBSD + def test_step_over(self): + """Test stepping when the inferior calls setjmp/longjmp, in particular, thread step-over a longjmp.""" + self.build() + self.step_over() + + @skipIfDarwin # llvm.org/pr16769: LLDB on Mac OS X dies in function ReadRegisterBytes in GDBRemoteRegisterContext.cpp + @skipIfFreeBSD # llvm.org/pr17214 + @expectedFailureAll(oslist=["linux"], bugnumber="llvm.org/pr20231") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") + @expectedFlakeyNetBSD + def test_step_back_out(self): + """Test stepping when the inferior calls setjmp/longjmp, in particular, thread step-out after thread step-in.""" + self.build() + self.step_back_out() + + def start_test(self, symbol): + exe = self.getBuildArtifact("a.out") + + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Break in main(). + lldbutil.run_break_set_by_symbol( + self, symbol, num_expected_locations=-1) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', 'stop reason = breakpoint']) + + def check_status(self): + # Note: Depending on the generated mapping of DWARF to assembly, + # the process may have stopped or exited. + self.expect("process status", PROCESS_STOPPED, + patterns=['Process .* exited with status = 0']) + + def step_out(self): + self.start_test("do_jump") + self.runCmd("thread step-out", RUN_SUCCEEDED) + self.check_status() + + def step_over(self): + self.start_test("do_jump") + self.runCmd("thread step-over", RUN_SUCCEEDED) + self.runCmd("thread step-over", RUN_SUCCEEDED) + self.check_status() + + def step_back_out(self): + self.start_test("main") + + self.runCmd("thread step-over", RUN_SUCCEEDED) + self.runCmd("thread step-in", RUN_SUCCEEDED) + self.runCmd("thread step-out", RUN_SUCCEEDED) + self.check_status() diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/longjmp/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/longjmp/main.c new file mode 100644 index 00000000000..ce1af7038c2 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/longjmp/main.c @@ -0,0 +1,30 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include <setjmp.h> +#include <stdio.h> +#include <time.h> + +jmp_buf j; + +void do_jump(void) +{ + // We can't let the compiler know this will always happen or it might make + // optimizations that break our test. + if (!clock()) + longjmp(j, 1); // non-local goto +} + +int main (void) +{ + if (setjmp(j) == 0) + do_jump(); + else + return 0; // destination of longjmp + + return 1; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory-region/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory-region/Makefile new file mode 100644 index 00000000000..31f2d5e8fc2 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory-region/Makefile @@ -0,0 +1,6 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules + +clean:: + rm -rf $(wildcard *.o *.d *.dSYM) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory-region/TestMemoryRegion.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory-region/TestMemoryRegion.py new file mode 100644 index 00000000000..283cc945ed0 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory-region/TestMemoryRegion.py @@ -0,0 +1,58 @@ +""" +Test the 'memory region' command. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class MemoryCommandRegion(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + def setUp(self): + TestBase.setUp(self) + # Find the line number to break for main.c. + self.line = line_number( + 'main.cpp', + '// Run here before printing memory regions') + + def test(self): + self.build() + + # Set breakpoint in main and run + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=-1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + interp = self.dbg.GetCommandInterpreter() + result = lldb.SBCommandReturnObject() + + # Test that the first 'memory region' command prints the usage. + interp.HandleCommand("memory region", result) + self.assertFalse(result.Succeeded()) + self.assertRegexpMatches(result.GetError(), "Usage: memory region ADDR") + + # Now let's print the memory region starting at 0 which should always work. + interp.HandleCommand("memory region 0x0", result) + self.assertTrue(result.Succeeded()) + self.assertRegexpMatches(result.GetOutput(), "\\[0x0+-") + + # Keep printing memory regions until we printed all of them. + while True: + interp.HandleCommand("memory region", result) + if not result.Succeeded(): + break + + # Now that we reached the end, 'memory region' should again print the usage. + interp.HandleCommand("memory region", result) + self.assertFalse(result.Succeeded()) + self.assertRegexpMatches(result.GetError(), "Usage: memory region ADDR") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory-region/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory-region/main.cpp new file mode 100644 index 00000000000..116c10a6c3e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory-region/main.cpp @@ -0,0 +1,6 @@ +#include <iostream> + +int main (int argc, char const **argv) { + std::cout << "Program with sections" << std::endl; + return 0; // Run here before printing memory regions +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory/cache/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory/cache/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory/cache/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory/cache/TestMemoryCache.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory/cache/TestMemoryCache.py new file mode 100644 index 00000000000..8a1523495b4 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory/cache/TestMemoryCache.py @@ -0,0 +1,62 @@ +""" +Test the MemoryCache L1 flush. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class MemoryCacheTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.line = line_number('main.cpp', '// Set break point at this line.') + + @skipIfWindows # This is flakey on Windows: llvm.org/pr38373 + def test_memory_cache(self): + """Test the MemoryCache class with a sequence of 'memory read' and 'memory write' operations.""" + self.build() + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Break in main() after the variables are assigned values. + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', 'stop reason = breakpoint']) + + # The breakpoint should have a hit count of 1. + self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, + substrs=[' resolved, hit count = 1']) + + # Read a chunk of memory containing &my_ints[0]. The number of bytes read + # must be greater than m_L2_cache_line_byte_size to make sure the L1 + # cache is used. + self.runCmd('memory read -f d -c 201 `&my_ints - 100`') + + # Check the value of my_ints[0] is the same as set in main.cpp. + line = self.res.GetOutput().splitlines()[100] + self.assertTrue(0x00000042 == int(line.split(':')[1], 0)) + + # Change the value of my_ints[0] in memory. + self.runCmd("memory write -s 4 `&my_ints` AA") + + # Re-read the chunk of memory. The cache line should have been + # flushed because of the 'memory write'. + self.runCmd('memory read -f d -c 201 `&my_ints - 100`') + + # Check the value of my_ints[0] have been updated correctly. + line = self.res.GetOutput().splitlines()[100] + self.assertTrue(0x000000AA == int(line.split(':')[1], 0)) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory/cache/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory/cache/main.cpp new file mode 100644 index 00000000000..d47107cef87 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory/cache/main.cpp @@ -0,0 +1,13 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +int main () +{ + int my_ints[] = {0x42}; + return 0; // Set break point at this line. +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory/find/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory/find/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory/find/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory/find/TestMemoryFind.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory/find/TestMemoryFind.py new file mode 100644 index 00000000000..66d43665dc7 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory/find/TestMemoryFind.py @@ -0,0 +1,66 @@ +""" +Test the 'memory find' command. +""" + + + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * + + +class MemoryFindTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.line = line_number('main.cpp', '// break here') + + def test_memory_find(self): + """Test the 'memory find' command.""" + self.build() + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Break in main() after the variables are assigned values. + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', 'stop reason = breakpoint']) + + # The breakpoint should have a hit count of 1. + self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, + substrs=[' resolved, hit count = 1']) + + # Test the memory find commands. + + self.expect( + 'memory find -s "in const" `stringdata` `stringdata+(int)strlen(stringdata)`', + substrs=[ + 'data found at location: 0x', + '69 6e 20 63', + 'in const']) + + self.expect( + 'memory find -e "(uint8_t)0x22" `&bytedata[0]` `&bytedata[15]`', + substrs=[ + 'data found at location: 0x', + '22 33 44 55 66']) + + self.expect( + 'memory find -e "(uint8_t)0x22" `&bytedata[0]` `&bytedata[2]`', + substrs=['data not found within the range.']) + + self.expect('memory find -s "nothere" `stringdata` `stringdata+5`', + substrs=['data not found within the range.']) + + self.expect('memory find -s "nothere" `stringdata` `stringdata+10`', + substrs=['data not found within the range.']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory/find/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory/find/main.cpp new file mode 100644 index 00000000000..5f4545daabd --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory/find/main.cpp @@ -0,0 +1,16 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include <stdio.h> +#include <stdint.h> + +int main (int argc, char const *argv[]) +{ + const char* stringdata = "hello world; I like to write text in const char pointers"; + uint8_t bytedata[] = {0xAA,0xBB,0xCC,0xDD,0xEE,0xFF,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99}; + return 0; // break here +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory/read/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory/read/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory/read/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory/read/TestMemoryRead.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory/read/TestMemoryRead.py new file mode 100644 index 00000000000..72d55dfa51f --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory/read/TestMemoryRead.py @@ -0,0 +1,133 @@ +""" +Test the 'memory read' command. +""" + + + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class MemoryReadTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.line = line_number('main.cpp', '// Set break point at this line.') + + def test_memory_read(self): + """Test the 'memory read' command with plain and vector formats.""" + self.build() + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Break in main() after the variables are assigned values. + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', 'stop reason = breakpoint']) + + # The breakpoint should have a hit count of 1. + self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, + substrs=[' resolved, hit count = 1']) + + # Test the memory read commands. + + # (lldb) memory read -f d -c 1 `&argc` + # 0x7fff5fbff9a0: 1 + self.runCmd("memory read -f d -c 1 `&argc`") + + # Find the starting address for variable 'argc' to verify later that the + # '--format uint32_t[] --size 4 --count 4' option increments the address + # correctly. + line = self.res.GetOutput().splitlines()[0] + items = line.split(':') + address = int(items[0], 0) + argc = int(items[1], 0) + self.assertTrue(address > 0 and argc == 1) + + # (lldb) memory read --format uint32_t[] --size 4 --count 4 `&argc` + # 0x7fff5fbff9a0: {0x00000001} + # 0x7fff5fbff9a4: {0x00000000} + # 0x7fff5fbff9a8: {0x0ec0bf27} + # 0x7fff5fbff9ac: {0x215db505} + self.runCmd( + "memory read --format uint32_t[] --size 4 --count 4 `&argc`") + lines = self.res.GetOutput().splitlines() + for i in range(4): + if i == 0: + # Verify that the printout for argc is correct. + self.assertTrue( + argc == int( + lines[i].split(':')[1].strip(' {}'), 0)) + addr = int(lines[i].split(':')[0], 0) + # Verify that the printout for addr is incremented correctly. + self.assertTrue(addr == (address + i * 4)) + + # (lldb) memory read --format char[] --size 7 --count 1 `&my_string` + # 0x7fff5fbff990: {abcdefg} + self.expect( + "memory read --format char[] --size 7 --count 1 `&my_string`", + substrs=['abcdefg']) + + # (lldb) memory read --format 'hex float' --size 16 `&argc` + # 0x7fff5fbff5b0: error: unsupported byte size (16) for hex float + # format + self.expect( + "memory read --format 'hex float' --size 16 `&argc`", + substrs=['unsupported byte size (16) for hex float format']) + + self.expect( + "memory read --format 'float' --count 1 --size 8 `&my_double`", + substrs=['1234.']) + + # (lldb) memory read --format 'float' --count 1 --size 20 `&my_double` + # 0x7fff5fbff598: error: unsupported byte size (20) for float format + self.expect( + "memory read --format 'float' --count 1 --size 20 `&my_double`", + substrs=['unsupported byte size (20) for float format']) + + self.expect('memory read --type int --count 5 `&my_ints[0]`', + substrs=['(int) 0x', '2', '4', '6', '8', '10']) + + self.expect( + 'memory read --type int --count 5 --format hex `&my_ints[0]`', + substrs=[ + '(int) 0x', + '0x', + '0a']) + + self.expect( + 'memory read --type int --count 5 --offset 5 `&my_ints[0]`', + substrs=[ + '(int) 0x', + '12', + '14', + '16', + '18', + '20']) + + # the gdb format specifier and the size in characters for + # the returned values including the 0x prefix. + variations = [['b', 4], ['h', 6], ['w', 10], ['g', 18]] + for v in variations: + formatter = v[0] + expected_object_length = v[1] + self.runCmd( + "memory read --gdb-format 4%s &my_uint64s" % formatter) + lines = self.res.GetOutput().splitlines() + objects_read = [] + for l in lines: + objects_read.extend(l.split(':')[1].split()) + # Check that we got back 4 0x0000 etc bytes + for o in objects_read: + self.assertTrue (len(o) == expected_object_length) + self.assertTrue(len(objects_read) == 4) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory/read/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory/read/main.cpp new file mode 100644 index 00000000000..3c1ab5e3f33 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/memory/read/main.cpp @@ -0,0 +1,20 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include <stdio.h> +#include <stdint.h> + +int main (int argc, char const *argv[]) +{ + char my_string[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 0}; + double my_double = 1234.5678; + int my_ints[] = {2,4,6,8,10,12,14,16,18,20,22}; + uint64_t my_uint64s[] = {0, 1, 2, 3, 4, 5, 6, 7}; + printf("my_string=%s\n", my_string); // Set break point at this line. + printf("my_double=%g\n", my_double); + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/mtc/simple/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/mtc/simple/Makefile new file mode 100644 index 00000000000..f27f57aeebf --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/mtc/simple/Makefile @@ -0,0 +1,14 @@ +OBJC_SOURCES := main.m +UI_FRAMEWORK = AppKit + +ifneq ("$(SDKROOT)", "") + ifeq (,$(findstring macOS,$(SDKROOT))) + ifeq (,$(findstring MacOS,$(SDKROOT))) + UI_FRAMEWORK = UIKit + endif + endif +endif + +LD_EXTRAS = -lobjc -framework Foundation -framework $(UI_FRAMEWORK) + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/mtc/simple/TestMTCSimple.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/mtc/simple/TestMTCSimple.py new file mode 100644 index 00000000000..e3751e02c45 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/mtc/simple/TestMTCSimple.py @@ -0,0 +1,58 @@ +""" +Tests basic Main Thread Checker support (detecting a main-thread-only violation). +""" + +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbplatformutil import * +import json + + +class MTCSimpleTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipUnlessDarwin + def test(self): + self.mtc_dylib_path = findMainThreadCheckerDylib() + if self.mtc_dylib_path == "": + self.skipTest("This test requires libMainThreadChecker.dylib") + + self.build() + self.mtc_tests() + + @skipIf(archs=['i386']) + def mtc_tests(self): + self.assertTrue(self.mtc_dylib_path != "") + + # Load the test + exe = self.getBuildArtifact("a.out") + self.expect("file " + exe, patterns=["Current executable set to .*a.out"]) + + self.runCmd("env DYLD_INSERT_LIBRARIES=%s" % self.mtc_dylib_path) + self.runCmd("run") + + process = self.dbg.GetSelectedTarget().process + thread = process.GetSelectedThread() + frame = thread.GetSelectedFrame() + + view = "NSView" if lldbplatformutil.getPlatform() == "macosx" else "UIView" + + self.expect("thread info", + substrs=['stop reason = -[' + view + + ' superview] must be used from main thread only']) + + self.expect( + "thread info -s", + substrs=["instrumentation_class", "api_name", "class_name", "selector", "description"]) + self.assertEqual(thread.GetStopReason(), lldb.eStopReasonInstrumentation) + output_lines = self.res.GetOutput().split('\n') + json_line = '\n'.join(output_lines[2:]) + data = json.loads(json_line) + self.assertEqual(data["instrumentation_class"], "MainThreadChecker") + self.assertEqual(data["api_name"], "-[" + view + " superview]") + self.assertEqual(data["class_name"], view) + self.assertEqual(data["selector"], "superview") + self.assertEqual(data["description"], "-[" + view + " superview] must be used from main thread only") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/mtc/simple/main.m b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/mtc/simple/main.m new file mode 100644 index 00000000000..a967dee4692 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/mtc/simple/main.m @@ -0,0 +1,21 @@ +#import <Foundation/Foundation.h> +#if __has_include(<AppKit/AppKit.h>) +#import <AppKit/AppKit.h> +#define XXView NSView +#else +#import <UIKit/UIKit.h> +#define XXView UIView +#endif + +int main() { + XXView *view = [[XXView alloc] init]; + dispatch_group_t g = dispatch_group_create(); + dispatch_group_enter(g); + [NSThread detachNewThreadWithBlock:^{ + @autoreleasepool { + [view superview]; + } + dispatch_group_leave(g); + }]; + dispatch_group_wait(g, DISPATCH_TIME_FOREVER); +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/multidebugger_commands/TestMultipleDebuggersCommands.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/multidebugger_commands/TestMultipleDebuggersCommands.py new file mode 100644 index 00000000000..845950758f8 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/multidebugger_commands/TestMultipleDebuggersCommands.py @@ -0,0 +1,52 @@ +""" +Test that commands do not try and hold on to stale CommandInterpreters in a multiple debuggers scenario +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class MultipleDebuggersCommandsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @no_debug_info_test + def test_multipledebuggers_commands(self): + """Test that commands do not try and hold on to stale CommandInterpreters in a multiple debuggers scenario""" + source_init_files = False + magic_text = "The following commands may relate to 'env'" + + debugger_1 = lldb.SBDebugger.Create(source_init_files) + interpreter_1 = debugger_1.GetCommandInterpreter() + + retobj = lldb.SBCommandReturnObject() + interpreter_1.HandleCommand("apropos env", retobj) + self.assertTrue( + magic_text in str(retobj), + "[interpreter_1]: the output does not contain the correct words") + + if self.TraceOn(): + print(str(retobj)) + + lldb.SBDebugger.Destroy(debugger_1) + + # now do this again with a different debugger - we shouldn't crash + + debugger_2 = lldb.SBDebugger.Create(source_init_files) + interpreter_2 = debugger_2.GetCommandInterpreter() + + retobj = lldb.SBCommandReturnObject() + interpreter_2.HandleCommand("apropos env", retobj) + self.assertTrue( + magic_text in str(retobj), + "[interpreter_2]: the output does not contain the correct words") + + if self.TraceOn(): + print(str(retobj)) + + lldb.SBDebugger.Destroy(debugger_2) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/multiword-commands/TestMultiWordCommands.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/multiword-commands/TestMultiWordCommands.py new file mode 100644 index 00000000000..80b144f58d5 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/multiword-commands/TestMultiWordCommands.py @@ -0,0 +1,33 @@ +""" +Test multiword commands ('platform' in this case). +""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * + +class MultiwordCommandsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @no_debug_info_test + def test_ambiguous_subcommand(self): + self.expect("platform s", error=True, + substrs=["ambiguous command 'platform s'. Possible completions:", + "\tselect\n", + "\tshell\n", + "\tsettings\n"]) + + @no_debug_info_test + def test_empty_subcommand(self): + self.expect("platform \"\"", error=True, substrs=["Need to specify a non-empty subcommand."]) + + @no_debug_info_test + def test_help(self): + # <multiword> help brings up help. + self.expect("platform help", + substrs=["Commands to manage and create platforms.", + "Syntax: platform [", + "The following subcommands are supported:", + "connect", + "Select the current platform"]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/non-overlapping-index-variable-i/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/non-overlapping-index-variable-i/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/non-overlapping-index-variable-i/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/non-overlapping-index-variable-i/TestIndexVariable.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/non-overlapping-index-variable-i/TestIndexVariable.py new file mode 100644 index 00000000000..d5424c0bb40 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/non-overlapping-index-variable-i/TestIndexVariable.py @@ -0,0 +1,47 @@ +"""Test evaluating expressions which ref. index variable 'i' which just goes +from out of scope to in scope when stopped at the breakpoint.""" + + + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class NonOverlappingIndexVariableCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + TestBase.setUp(self) + self.source = 'main.cpp' + self.line_to_break = line_number( + self.source, '// Set breakpoint here.') + + # rdar://problem/9890530 + def test_eval_index_variable(self): + """Test expressions of variable 'i' which appears in two for loops.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), + CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, + self.source, + self.line_to_break, + num_expected_locations=1, + loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + self.runCmd('frame variable i') + self.runCmd('expr i') + self.runCmd('expr ptr[0]->point.x') + self.runCmd('expr ptr[0]->point.y') + self.runCmd('expr ptr[i]->point.x') + self.runCmd('expr ptr[i]->point.y') diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/non-overlapping-index-variable-i/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/non-overlapping-index-variable-i/main.cpp new file mode 100644 index 00000000000..2b8406a631b --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/non-overlapping-index-variable-i/main.cpp @@ -0,0 +1,45 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +class Point { +public: + int x; + int y; + Point(int a, int b): + x(a), + y(b) + {} +}; + +class Data { +public: + int id; + Point point; + Data(int i): + id(i), + point(0, 0) + {} +}; + +int main(int argc, char const *argv[]) { + Data *data[1000]; + Data **ptr = data; + for (int i = 0; i < 1000; ++i) { + ptr[i] = new Data(i); + ptr[i]->point.x = i; + ptr[i]->point.y = i+1; + } + + for (int i = 0; i < 1000; ++i) { + bool dump = argc > 1; // Set breakpoint here. + // Evaluate a couple of expressions (2*1000 = 2000 exprs): + // expr ptr[i]->point.x + // expr ptr[i]->point.y + } + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/object-file/TestImageListMultiArchitecture.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/object-file/TestImageListMultiArchitecture.py new file mode 100644 index 00000000000..1ad90e4fce5 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/object-file/TestImageListMultiArchitecture.py @@ -0,0 +1,45 @@ +""" +Test lldb 'image list' on object files across multiple architectures. +This exercises classes like ObjectFileELF and their support for opening +foreign-architecture object files. +""" + + + +import os.path +import re + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestImageListMultiArchitecture(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @no_debug_info_test + @skipIfRemote + def test_image_list_shows_multiple_architectures(self): + """Test that image list properly shows the correct architecture for a set of different architecture object files.""" + images = { + "hello-freebsd-10.0-x86_64-clang-3.3": re.compile(r"x86_64-(\*)?-freebsd10.0(-unknown)? x86_64"), + "hello-freebsd-10.0-x86_64-gcc-4.7.3": re.compile(r"x86_64-(\*)?-freebsd10.0(-unknown)? x86_64"), + "hello-netbsd-6.1-x86_64-gcc-4.5.3": re.compile(r"x86_64-(\*)?-netbsd6.1.4(-unknown)? x86_64"), + "hello-ubuntu-14.04-x86_64-gcc-4.8.2": re.compile(r"x86_64-(\*)?-linux(-unknown)? x86_64"), + "hello-ubuntu-14.04-x86_64-clang-3.5pre": re.compile(r"x86_64-(\*)?-linux(-unknown)? x86_64"), + } + + for image_name in images: + file_name = os.path.abspath( + os.path.join( + os.path.dirname(__file__), + "bin", + image_name)) + expected_triple_and_arch_regex = images[image_name] + + self.runCmd("file {}".format(file_name)) + self.match("image list -t -A", [expected_triple_and_arch_regex]) + # Revert to the host platform after all of this is done + self.runCmd("platform select host") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/object-file/bin/hello-freebsd-10.0-x86_64-clang-3.3 b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/object-file/bin/hello-freebsd-10.0-x86_64-clang-3.3 Binary files differnew file mode 100644 index 00000000000..cea323639b4 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/object-file/bin/hello-freebsd-10.0-x86_64-clang-3.3 diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/object-file/bin/hello-freebsd-10.0-x86_64-gcc-4.7.3 b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/object-file/bin/hello-freebsd-10.0-x86_64-gcc-4.7.3 Binary files differnew file mode 100644 index 00000000000..38f43f8acb9 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/object-file/bin/hello-freebsd-10.0-x86_64-gcc-4.7.3 diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/object-file/bin/hello-netbsd-6.1-x86_64-gcc-4.5.3 b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/object-file/bin/hello-netbsd-6.1-x86_64-gcc-4.5.3 Binary files differnew file mode 100644 index 00000000000..6d531320ae9 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/object-file/bin/hello-netbsd-6.1-x86_64-gcc-4.5.3 diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/object-file/bin/hello-ubuntu-14.04-x86_64-clang-3.5pre b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/object-file/bin/hello-ubuntu-14.04-x86_64-clang-3.5pre Binary files differnew file mode 100644 index 00000000000..8bdcf4d5b59 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/object-file/bin/hello-ubuntu-14.04-x86_64-clang-3.5pre diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/object-file/bin/hello-ubuntu-14.04-x86_64-gcc-4.8.2 b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/object-file/bin/hello-ubuntu-14.04-x86_64-gcc-4.8.2 Binary files differnew file mode 100644 index 00000000000..01efbb061b7 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/object-file/bin/hello-ubuntu-14.04-x86_64-gcc-4.8.2 diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/object-file/bin/hello-unknown-kalimba_arch4-kcc-36 b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/object-file/bin/hello-unknown-kalimba_arch4-kcc-36 Binary files differnew file mode 100644 index 00000000000..8e4dd8c883c --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/object-file/bin/hello-unknown-kalimba_arch4-kcc-36 diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/object-file/bin/hello-unknown-kalimba_arch5-kcc-39 b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/object-file/bin/hello-unknown-kalimba_arch5-kcc-39 Binary files differnew file mode 100644 index 00000000000..f80268a08e5 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/object-file/bin/hello-unknown-kalimba_arch5-kcc-39 diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/object-file/bin/hello.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/object-file/bin/hello.c new file mode 100644 index 00000000000..8c804005afe --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/object-file/bin/hello.c @@ -0,0 +1,8 @@ +#include <stdio.h> + +int main(int argc, char **argv) +{ + printf("Hello, world\n"); + return 0; +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/object-file/bin/hello.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/object-file/bin/hello.cpp new file mode 100644 index 00000000000..8c804005afe --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/object-file/bin/hello.cpp @@ -0,0 +1,8 @@ +#include <stdio.h> + +int main(int argc, char **argv) +{ + printf("Hello, world\n"); + return 0; +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/param_entry_vals/basic_entry_values_x86_64/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/param_entry_vals/basic_entry_values_x86_64/Makefile new file mode 100644 index 00000000000..db8fa57abb9 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/param_entry_vals/basic_entry_values_x86_64/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp +CXXFLAGS_EXTRAS := -O2 -glldb -Xclang -femit-debug-entry-values +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/param_entry_vals/basic_entry_values_x86_64/TestBasicEntryValuesX86_64.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/param_entry_vals/basic_entry_values_x86_64/TestBasicEntryValuesX86_64.py new file mode 100644 index 00000000000..e0285e6d626 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/param_entry_vals/basic_entry_values_x86_64/TestBasicEntryValuesX86_64.py @@ -0,0 +1,13 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators +from lldbsuite.test import lldbplatformutil + +supported_platforms = ["linux"] +supported_platforms.extend(lldbplatformutil.getDarwinOSTriples()) + +lldbinline.MakeInlineTest(__file__, globals(), + [decorators.skipUnlessPlatform(supported_platforms), + decorators.skipIf(compiler="clang", compiler_version=['<', '10.0']), + decorators.skipUnlessArch('x86_64'), + decorators.skipUnlessHasCallSiteInfo, + decorators.skipIf(dwarf_version=['<', '4'])]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/param_entry_vals/basic_entry_values_x86_64/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/param_entry_vals/basic_entry_values_x86_64/main.cpp new file mode 100644 index 00000000000..9aac6e94783 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/param_entry_vals/basic_entry_values_x86_64/main.cpp @@ -0,0 +1,248 @@ +// Note: This test requires the SysV AMD64 ABI to be in use, and requires +// compiler support for DWARF entry values. + +// Inhibit dead-arg-elim by using 'x'. +template<typename T> __attribute__((noinline)) void use(T x) { + asm volatile ("" + /* Outputs */ : + /* Inputs */ : "g"(x) + /* Clobbers */ : + ); +} + +// Destroy %rsi in the current frame. +#define DESTROY_RSI \ + asm volatile ("xorq %%rsi, %%rsi" \ + /* Outputs */ : \ + /* Inputs */ : \ + /* Clobbers */ : "rsi" \ + ); + +// Destroy %rbx in the current frame. +#define DESTROY_RBX \ + asm volatile ("xorq %%rbx, %%rbx" \ + /* Outputs */ : \ + /* Inputs */ : \ + /* Clobbers */ : "rbx" \ + ); + +struct S1 { + int field1 = 123; + int *field2 = &field1; +}; + +__attribute__((noinline)) +void func1(int &sink, int x) { + use(x); + + // Destroy 'x' in the current frame. + DESTROY_RSI; + + // NOTE: Currently, we do not generate DW_OP_entry_value for the 'x', + // since it gets copied into a register that is not callee saved, + // and we can not guarantee that its value has not changed. + + ++sink; + + // Destroy 'sink' in the current frame. + DESTROY_RBX; + + //% self.filecheck("image lookup -va $pc", "main.cpp", "-check-prefix=FUNC1-DESC") + // FUNC1-DESC: name = "sink", type = "int &", location = DW_OP_entry_value(DW_OP_reg5 RDI) +} + +__attribute__((noinline)) +void func2(int &sink, int x) { + use(x); + + // Destroy 'x' in the current frame. + DESTROY_RSI; + + //% self.filecheck("expr x", "main.cpp", "-check-prefix=FUNC2-EXPR-FAIL", expect_cmd_failure=True) + // FUNC2-EXPR-FAIL: couldn't get the value of variable x: variable not available + + ++sink; + + // Destroy 'sink' in the current frame. + DESTROY_RBX; + + //% self.filecheck("expr sink", "main.cpp", "-check-prefix=FUNC2-EXPR") + // FUNC2-EXPR: ${{.*}} = 2 +} + +__attribute__((noinline)) +void func3(int &sink, int *p) { + use(p); + + // Destroy 'p' in the current frame. + DESTROY_RSI; + + //% self.filecheck("expr *p", "main.cpp", "-check-prefix=FUNC3-EXPR") + // FUNC3-EXPR: (int) ${{.*}} = 123 + + ++sink; +} + +__attribute__((noinline)) +void func4_amb(int &sink, int x) { + use(x); + + // Destroy 'x' in the current frame. + DESTROY_RSI; + + //% self.filecheck("expr x", "main.cpp", "-check-prefix=FUNC4-EXPR-FAIL", expect_cmd_failure=True) + // FUNC4-EXPR-FAIL: couldn't get the value of variable x: variable not available + + ++sink; + + // Destroy 'sink' in the current frame. + DESTROY_RBX; + + //% self.filecheck("expr sink", "main.cpp", "-check-prefix=FUNC4-EXPR", expect_cmd_failure=True) + // FUNC4-EXPR: couldn't get the value of variable sink: Could not evaluate DW_OP_entry_value. +} + +__attribute__((noinline)) +void func5_amb() {} + +__attribute__((noinline)) +void func6(int &sink, int x) { + if (sink > 0) + func4_amb(sink, x); /* tail (taken) */ + else + func5_amb(); /* tail */ +} + +__attribute__((noinline)) +void func7(int &sink, int x) { + //% self.filecheck("bt", "main.cpp", "-check-prefix=FUNC7-BT") + // FUNC7-BT: func7 + // FUNC7-BT-NEXT: [inlined] func8_inlined + // FUNC7-BT-NEXT: [inlined] func9_inlined + // FUNC7-BT-NEXT: func10 + use(x); + + // Destroy 'x' in the current frame. + DESTROY_RSI; + + //% self.filecheck("expr x", "main.cpp", "-check-prefix=FUNC7-EXPR-FAIL", expect_cmd_failure=True) + // FUNC7-EXPR-FAIL: couldn't get the value of variable x: variable not available + + ++sink; + + // Destroy 'sink' in the current frame. + DESTROY_RBX; + + //% self.filecheck("expr sink", "main.cpp", "-check-prefix=FUNC7-EXPR") + // FUNC7-EXPR: ${{.*}} = 4 +} + +__attribute__((always_inline)) +void func8_inlined(int &sink, int x) { + func7(sink, x); +} + +__attribute__((always_inline)) +void func9_inlined(int &sink, int x) { + func8_inlined(sink, x); +} + +__attribute__((noinline, disable_tail_calls)) +void func10(int &sink, int x) { + func9_inlined(sink, x); +} + +__attribute__((noinline)) +void func11_tailcalled(int &sink, int x) { + //% self.filecheck("bt", "main.cpp", "-check-prefix=FUNC11-BT") + // FUNC11-BT: func11_tailcalled{{.*}} + // FUNC11-BT-NEXT: func12{{.*}} [artificial] + use(x); + + // Destroy 'x' in the current frame. + DESTROY_RSI; + + //% self.filecheck("expr x", "main.cpp", "-check-prefix=FUNC11-EXPR-FAIL", expect_cmd_failure=True) + // FUNC11-EXPR-FAIL: couldn't get the value of variable x: variable not available + + ++sink; + + // Destroy 'sink' in the current frame. + DESTROY_RBX; + + //% self.filecheck("expr sink", "main.cpp", "-check-prefix=FUNC11-EXPR") + // FUNC11-EXPR: ${{.*}} = 5 +} + +__attribute__((noinline)) +void func12(int &sink, int x) { + func11_tailcalled(sink, x); +} + +__attribute__((noinline)) +void func13(int &sink, int x) { + //% self.filecheck("bt", "main.cpp", "-check-prefix=FUNC13-BT") + // FUNC13-BT: func13{{.*}} + // FUNC13-BT-NEXT: func14{{.*}} + use(x); + + // Destroy 'x' in the current frame. + DESTROY_RSI; + + //% self.filecheck("expr x", "main.cpp", "-check-prefix=FUNC13-EXPR-FAIL", expect_cmd_failure=True) + // FUNC13-EXPR-FAIL: couldn't get the value of variable x: variable not available + + use(sink); + + // Destroy 'sink' in the current frame. + DESTROY_RBX; + + //% self.filecheck("expr sink", "main.cpp", "-check-prefix=FUNC13-EXPR") + // FUNC13-EXPR: ${{.*}} = 5 +} + +__attribute__((noinline, disable_tail_calls)) +void func14(int &sink, void (*target_no_tailcall)(int &, int)) { + // Move the call target into a register that won't get clobbered. Do this + // by calling the same indirect target twice, and hoping that regalloc is + // 'smart' enough to stash the call target in a non-clobbered register. + // + // llvm.org/PR43926 tracks work in the compiler to emit call targets which + // describe non-clobbered values. + target_no_tailcall(sink, 123); + target_no_tailcall(sink, 123); +} + +__attribute__((disable_tail_calls)) +int main() { + int sink = 0; + S1 s1; + + // Test location dumping for DW_OP_entry_value. + func1(sink, 123); + + // Test evaluation of "DW_OP_constu" in the parent frame. + func2(sink, 123); + + // Test evaluation of "DW_OP_fbreg -24, DW_OP_deref" in the parent frame. + // Disabled for now, see: llvm.org/PR43343 +#if 0 + func3(sink, s1.field2); +#endif + + // The sequences `main -> func4 -> func{5,6}_amb -> sink` are both plausible. + // Test that lldb doesn't attempt to guess which one occurred: entry value + // evaluation should fail. + func6(sink, 123); + + // Test that evaluation can "see through" inlining. + func10(sink, 123); + + // Test that evaluation can "see through" tail calls. + func12(sink, 123); + + // Test that evaluation can "see through" an indirect tail call. + func14(sink, func13); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/paths/TestPaths.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/paths/TestPaths.py new file mode 100644 index 00000000000..5c21622d03d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/paths/TestPaths.py @@ -0,0 +1,50 @@ +""" +Test some lldb command abbreviations. +""" + + +import lldb +import os +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestPaths(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @no_debug_info_test + def test_paths(self): + '''Test to make sure no file names are set in the lldb.SBFileSpec objects returned by lldb.SBHostOS.GetLLDBPath() for paths that are directories''' + dir_path_types = [lldb.ePathTypeLLDBShlibDir, + lldb.ePathTypeSupportExecutableDir, + lldb.ePathTypeHeaderDir, + lldb.ePathTypePythonDir, + lldb.ePathTypeLLDBSystemPlugins, + lldb.ePathTypeLLDBUserPlugins, + lldb.ePathTypeLLDBTempSystemDir, + lldb.ePathTypeClangDir] + + for path_type in dir_path_types: + f = lldb.SBHostOS.GetLLDBPath(path_type) + # No directory path types should have the filename set + self.assertTrue(f.GetFilename() is None) + + @no_debug_info_test + def test_directory_doesnt_end_with_slash(self): + current_directory_spec = lldb.SBFileSpec(os.path.curdir) + current_directory_string = current_directory_spec.GetDirectory() + self.assertNotEqual(current_directory_string[-1:], '/') + + @skipUnlessPlatform(["windows"]) + @no_debug_info_test + def test_windows_double_slash(self): + '''Test to check the path with double slash is handled correctly ''' + # Create a path and see if lldb gets the directory and file right + fspec = lldb.SBFileSpec("C:\\dummy1\\dummy2//unknown_file", True) + self.assertEqual( + os.path.normpath( + fspec.GetDirectory()), + os.path.normpath("C:/dummy1/dummy2")) + self.assertEqual(fspec.GetFilename(), "unknown_file") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/plugins/command_plugin/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/plugins/command_plugin/Makefile new file mode 100644 index 00000000000..3119c370784 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/plugins/command_plugin/Makefile @@ -0,0 +1,6 @@ +DYLIB_CXX_SOURCES := plugin.cpp +DYLIB_NAME := plugin +DYLIB_ONLY := YES +MAKE_DSYM := NO + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/plugins/command_plugin/TestPluginCommands.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/plugins/command_plugin/TestPluginCommands.py new file mode 100644 index 00000000000..e81d4076574 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/plugins/command_plugin/TestPluginCommands.py @@ -0,0 +1,78 @@ +""" +Test that plugins that load commands work correctly. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class PluginCommandTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + TestBase.setUp(self) + self.generateSource('plugin.cpp') + + @skipIfNoSBHeaders + # Requires a compatible arch and platform to link against the host's built + # lldb lib. + @skipIfHostIncompatibleWithRemote + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") + @no_debug_info_test + def test_load_plugin(self): + """Test that plugins that load commands work correctly.""" + + plugin_name = "plugin" + if sys.platform.startswith("darwin"): + plugin_lib_name = "lib%s.dylib" % plugin_name + else: + plugin_lib_name = "lib%s.so" % plugin_name + + # Invoke the library build rule. + self.buildLibrary("plugin.cpp", plugin_name) + + debugger = lldb.SBDebugger.Create() + + retobj = lldb.SBCommandReturnObject() + + retval = debugger.GetCommandInterpreter().HandleCommand( + "plugin load %s" % self.getBuildArtifact(plugin_lib_name), retobj) + + retobj.Clear() + + retval = debugger.GetCommandInterpreter().HandleCommand( + "plugin_loaded_command child abc def ghi", retobj) + + if self.TraceOn(): + print(retobj.GetOutput()) + + self.expect(retobj, substrs=['abc def ghi'], exe=False) + + retobj.Clear() + + # check that abbreviations work correctly in plugin commands. + retval = debugger.GetCommandInterpreter().HandleCommand( + "plugin_loaded_ ch abc def ghi", retobj) + + if self.TraceOn(): + print(retobj.GetOutput()) + + self.expect(retobj, substrs=['abc def ghi'], exe=False) + + @no_debug_info_test + def test_invalid_plugin_invocation(self): + self.expect("plugin load a b", + error=True, startstr="error: 'plugin load' requires one argument") + self.expect("plugin load", + error=True, startstr="error: 'plugin load' requires one argument") + + @no_debug_info_test + def test_invalid_plugin_target(self): + self.expect("plugin load ThisIsNotAValidPluginName", + error=True, startstr="error: no such file") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/plugins/command_plugin/plugin.cpp.template b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/plugins/command_plugin/plugin.cpp.template new file mode 100644 index 00000000000..1667c0d721e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/plugins/command_plugin/plugin.cpp.template @@ -0,0 +1,53 @@ +//===-- plugin.cpp -------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +/* +An example plugin for LLDB that provides a new foo command with a child subcommand +Compile this into a dylib foo.dylib and load by placing in appropriate locations on disk or +by typing plugin load foo.dylib at the LLDB command line +*/ + +%include_SB_APIs% + +namespace lldb { + bool + PluginInitialize (lldb::SBDebugger debugger); +} + +class ChildCommand : public lldb::SBCommandPluginInterface +{ +public: + virtual bool + DoExecute (lldb::SBDebugger debugger, + char** command, + lldb::SBCommandReturnObject &result) + { + if (command) + { + const char* arg = *command; + while (arg) + { + result.Printf("%s ",arg); + arg = *(++command); + } + result.Printf("\n"); + return true; + } + return false; + } + +}; + +bool +lldb::PluginInitialize (lldb::SBDebugger debugger) +{ + lldb::SBCommandInterpreter interpreter = debugger.GetCommandInterpreter(); + lldb::SBCommand foo = interpreter.AddMultiwordCommand("plugin_loaded_command",NULL); + foo.AddCommand("child",new ChildCommand(),"a child of plugin_loaded_command"); + return true; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/plugins/python_os_plugin/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/plugins/python_os_plugin/Makefile new file mode 100644 index 00000000000..c9319d6e688 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/plugins/python_os_plugin/Makefile @@ -0,0 +1,2 @@ +C_SOURCES := main.c +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/plugins/python_os_plugin/TestPythonOSPlugin.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/plugins/python_os_plugin/TestPythonOSPlugin.py new file mode 100644 index 00000000000..5c4b42084c2 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/plugins/python_os_plugin/TestPythonOSPlugin.py @@ -0,0 +1,195 @@ +""" +Test that the Python operating system plugin works correctly +""" + + + +import os +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class PluginPythonOSPlugin(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + def test_python_os_plugin(self): + """Test that the Python operating system plugin works correctly""" + self.build() + self.run_python_os_funcionality() + + def run_python_os_step(self): + """Test that the Python operating system plugin works correctly when single stepping a virtual thread""" + self.build() + self.run_python_os_step() + + def verify_os_thread_registers(self, thread): + frame = thread.GetFrameAtIndex(0) + registers = frame.GetRegisters().GetValueAtIndex(0) + reg_value = thread.GetThreadID() + 1 + for reg in registers: + self.assertTrue( + reg.GetValueAsUnsigned() == reg_value, + "Verify the registers contains the correct value") + reg_value = reg_value + 1 + + def run_python_os_funcionality(self): + """Test that the Python operating system plugin works correctly""" + + # Set debugger into synchronous mode + self.dbg.SetAsync(False) + + # Create a target by the debugger. + exe = self.getBuildArtifact("a.out") + python_os_plugin_path = os.path.join(self.getSourceDir(), + "operating_system.py") + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Set breakpoints inside and outside methods that take pointers to the + # containing struct. + lldbutil.run_break_set_by_source_regexp(self, "// Set breakpoint here") + + # Register our shared libraries for remote targets so they get + # automatically uploaded + arguments = None + environment = None + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple( + arguments, environment, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + # Make sure there are no OS plug-in created thread when we first stop + # at our breakpoint in main + thread = process.GetThreadByID(0x111111111) + self.assertFalse( + thread.IsValid(), + "Make sure there is no thread 0x111111111 before we load the python OS plug-in") + thread = process.GetThreadByID(0x222222222) + self.assertFalse( + thread.IsValid(), + "Make sure there is no thread 0x222222222 before we load the python OS plug-in") + thread = process.GetThreadByID(0x333333333) + self.assertFalse( + thread.IsValid(), + "Make sure there is no thread 0x333333333 before we load the python OS plug-in") + + # Now load the python OS plug-in which should update the thread list and we should have + # OS plug-in created threads with the IDs: 0x111111111, 0x222222222, + # 0x333333333 + command = "settings set target.process.python-os-plugin-path '%s'" % python_os_plugin_path + self.dbg.HandleCommand(command) + + # Verify our OS plug-in threads showed up + thread = process.GetThreadByID(0x111111111) + self.assertTrue( + thread.IsValid(), + "Make sure there is a thread 0x111111111 after we load the python OS plug-in") + self.verify_os_thread_registers(thread) + thread = process.GetThreadByID(0x222222222) + self.assertTrue( + thread.IsValid(), + "Make sure there is a thread 0x222222222 after we load the python OS plug-in") + self.verify_os_thread_registers(thread) + thread = process.GetThreadByID(0x333333333) + self.assertTrue( + thread.IsValid(), + "Make sure there is a thread 0x333333333 after we load the python OS plug-in") + self.verify_os_thread_registers(thread) + + # Now clear the OS plug-in path to make the OS plug-in created threads + # dissappear + self.dbg.HandleCommand( + "settings clear target.process.python-os-plugin-path") + + # Verify the threads are gone after unloading the python OS plug-in + thread = process.GetThreadByID(0x111111111) + self.assertFalse( + thread.IsValid(), + "Make sure there is no thread 0x111111111 after we unload the python OS plug-in") + thread = process.GetThreadByID(0x222222222) + self.assertFalse( + thread.IsValid(), + "Make sure there is no thread 0x222222222 after we unload the python OS plug-in") + thread = process.GetThreadByID(0x333333333) + self.assertFalse( + thread.IsValid(), + "Make sure there is no thread 0x333333333 after we unload the python OS plug-in") + + def run_python_os_step(self): + """Test that the Python operating system plugin works correctly and allows single stepping of a virtual thread that is backed by a real thread""" + + # Set debugger into synchronous mode + self.dbg.SetAsync(False) + + # Create a target by the debugger. + exe = self.getBuildArtifact("a.out") + python_os_plugin_path = os.path.join(self.getSourceDir(), + "operating_system2.py") + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Set breakpoints inside and outside methods that take pointers to the + # containing struct. + lldbutil.run_break_set_by_source_regexp(self, "// Set breakpoint here") + + # Register our shared libraries for remote targets so they get + # automatically uploaded + arguments = None + environment = None + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple( + arguments, environment, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + # Make sure there are no OS plug-in created thread when we first stop + # at our breakpoint in main + thread = process.GetThreadByID(0x111111111) + self.assertFalse( + thread.IsValid(), + "Make sure there is no thread 0x111111111 before we load the python OS plug-in") + + # Now load the python OS plug-in which should update the thread list and we should have + # OS plug-in created threads with the IDs: 0x111111111, 0x222222222, + # 0x333333333 + command = "settings set target.process.python-os-plugin-path '%s'" % python_os_plugin_path + self.dbg.HandleCommand(command) + + # Verify our OS plug-in threads showed up + thread = process.GetThreadByID(0x111111111) + self.assertTrue( + thread.IsValid(), + "Make sure there is a thread 0x111111111 after we load the python OS plug-in") + + frame = thread.GetFrameAtIndex(0) + self.assertTrue( + frame.IsValid(), + "Make sure we get a frame from thread 0x111111111") + line_entry = frame.GetLineEntry() + + self.assertTrue( + line_entry.GetFileSpec().GetFilename() == 'main.c', + "Make sure we stopped on line 5 in main.c") + self.assertTrue( + line_entry.GetLine() == 5, + "Make sure we stopped on line 5 in main.c") + + # Now single step thread 0x111111111 and make sure it does what we need + # it to + thread.StepOver() + + frame = thread.GetFrameAtIndex(0) + self.assertTrue( + frame.IsValid(), + "Make sure we get a frame from thread 0x111111111") + line_entry = frame.GetLineEntry() + + self.assertTrue( + line_entry.GetFileSpec().GetFilename() == 'main.c', + "Make sure we stepped from line 5 to line 6 in main.c") + self.assertTrue(line_entry.GetLine() == 6, + "Make sure we stepped from line 5 to line 6 in main.c") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/plugins/python_os_plugin/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/plugins/python_os_plugin/main.c new file mode 100644 index 00000000000..faa6dd58ecd --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/plugins/python_os_plugin/main.c @@ -0,0 +1,7 @@ +#include <stdio.h> + +int main (int argc, char const *argv[], char const *envp[]) +{ + puts("stop here"); // Set breakpoint here + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/plugins/python_os_plugin/operating_system.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/plugins/python_os_plugin/operating_system.py new file mode 100644 index 00000000000..394c24b4a88 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/plugins/python_os_plugin/operating_system.py @@ -0,0 +1,128 @@ +#!/usr/bin/python + +import lldb +import struct + + +class OperatingSystemPlugIn(object): + """Class that provides data for an instance of a LLDB 'OperatingSystemPython' plug-in class""" + + def __init__(self, process): + '''Initialization needs a valid.SBProcess object. + + This plug-in will get created after a live process is valid and has stopped for the + first time.''' + self.process = None + self.registers = None + self.threads = None + if isinstance(process, lldb.SBProcess) and process.IsValid(): + self.process = process + self.threads = None # Will be an dictionary containing info for each thread + + def get_target(self): + # NOTE: Don't use "lldb.target" when trying to get your target as the "lldb.target" + # tracks the current target in the LLDB command interpreter which isn't the + # correct thing to use for this plug-in. + return self.process.target + + def create_thread(self, tid, context): + if tid == 0x444444444: + thread_info = { + 'tid': tid, + 'name': 'four', + 'queue': 'queue4', + 'state': 'stopped', + 'stop_reason': 'none'} + self.threads.append(thread_info) + return thread_info + return None + + def get_thread_info(self): + if not self.threads: + # The sample dictionary below shows the values that can be returned for a thread + # tid => thread ID (mandatory) + # name => thread name (optional key/value pair) + # queue => thread dispatch queue name (optional key/value pair) + # state => thred state (mandatory, set to 'stopped' for now) + # stop_reason => thread stop reason. (mandatory, usually set to 'none') + # Possible values include: + # 'breakpoint' if the thread is stopped at a breakpoint + # 'none' thread is just stopped because the process is stopped + # 'trace' the thread just single stepped + # The usual value for this while threads are in memory is 'none' + # register_data_addr => the address of the register data in memory (optional key/value pair) + # Specifying this key/value pair for a thread will avoid a call to get_register_data() + # and can be used when your registers are in a thread context structure that is contiguous + # in memory. Don't specify this if your register layout in memory doesn't match the layout + # described by the dictionary returned from a call to the + # get_register_info() method. + self.threads = [{'tid': 0x111111111, + 'name': 'one', + 'queue': 'queue1', + 'state': 'stopped', + 'stop_reason': 'breakpoint'}, + {'tid': 0x222222222, + 'name': 'two', + 'queue': 'queue2', + 'state': 'stopped', + 'stop_reason': 'none'}, + {'tid': 0x333333333, + 'name': 'three', + 'queue': 'queue3', + 'state': 'stopped', + 'stop_reason': 'trace'}] + return self.threads + + def get_register_info(self): + if self.registers is None: + self.registers = dict() + self.registers['sets'] = ['GPR'] + self.registers['registers'] = [ + {'name': 'rax', 'bitsize': 64, 'offset': 0, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 0, 'dwarf': 0}, + {'name': 'rbx', 'bitsize': 64, 'offset': 8, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 3, 'dwarf': 3}, + {'name': 'rcx', 'bitsize': 64, 'offset': 16, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 2, 'dwarf': 2, 'generic': 'arg4', 'alt-name': 'arg4', }, + {'name': 'rdx', 'bitsize': 64, 'offset': 24, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 1, 'dwarf': 1, 'generic': 'arg3', 'alt-name': 'arg3', }, + {'name': 'rdi', 'bitsize': 64, 'offset': 32, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 5, 'dwarf': 5, 'generic': 'arg1', 'alt-name': 'arg1', }, + {'name': 'rsi', 'bitsize': 64, 'offset': 40, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 4, 'dwarf': 4, 'generic': 'arg2', 'alt-name': 'arg2', }, + {'name': 'rbp', 'bitsize': 64, 'offset': 48, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 6, 'dwarf': 6, 'generic': 'fp', 'alt-name': 'fp', }, + {'name': 'rsp', 'bitsize': 64, 'offset': 56, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 7, 'dwarf': 7, 'generic': 'sp', 'alt-name': 'sp', }, + {'name': 'r8', 'bitsize': 64, 'offset': 64, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 8, 'dwarf': 8, 'generic': 'arg5', 'alt-name': 'arg5', }, + {'name': 'r9', 'bitsize': 64, 'offset': 72, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 9, 'dwarf': 9, 'generic': 'arg6', 'alt-name': 'arg6', }, + {'name': 'r10', 'bitsize': 64, 'offset': 80, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 10, 'dwarf': 10}, + {'name': 'r11', 'bitsize': 64, 'offset': 88, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 11, 'dwarf': 11}, + {'name': 'r12', 'bitsize': 64, 'offset': 96, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 12, 'dwarf': 12}, + {'name': 'r13', 'bitsize': 64, 'offset': 104, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 13, 'dwarf': 13}, + {'name': 'r14', 'bitsize': 64, 'offset': 112, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 14, 'dwarf': 14}, + {'name': 'r15', 'bitsize': 64, 'offset': 120, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 15, 'dwarf': 15}, + {'name': 'rip', 'bitsize': 64, 'offset': 128, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 16, 'dwarf': 16, 'generic': 'pc', 'alt-name': 'pc'}, + {'name': 'rflags', 'bitsize': 64, 'offset': 136, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'generic': 'flags', 'alt-name': 'flags'}, + {'name': 'cs', 'bitsize': 64, 'offset': 144, 'encoding': 'uint', 'format': 'hex', 'set': 0}, + {'name': 'fs', 'bitsize': 64, 'offset': 152, 'encoding': 'uint', 'format': 'hex', 'set': 0}, + {'name': 'gs', 'bitsize': 64, 'offset': 160, 'encoding': 'uint', 'format': 'hex', 'set': 0}, + ] + return self.registers + + def get_register_data(self, tid): + return struct.pack( + '21Q', + tid + 1, + tid + 2, + tid + 3, + tid + 4, + tid + 5, + tid + 6, + tid + 7, + tid + 8, + tid + 9, + tid + 10, + tid + 11, + tid + 12, + tid + 13, + tid + 14, + tid + 15, + tid + 16, + tid + 17, + tid + 18, + tid + 19, + tid + 20, + tid + 21) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/plugins/python_os_plugin/operating_system2.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/plugins/python_os_plugin/operating_system2.py new file mode 100644 index 00000000000..438538ca922 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/plugins/python_os_plugin/operating_system2.py @@ -0,0 +1,116 @@ +#!/usr/bin/python + +import lldb +import struct + + +class OperatingSystemPlugIn(object): + """Class that provides data for an instance of a LLDB 'OperatingSystemPython' plug-in class""" + + def __init__(self, process): + '''Initialization needs a valid.SBProcess object. + + This plug-in will get created after a live process is valid and has stopped for the + first time.''' + self.process = None + self.registers = None + self.threads = None + if isinstance(process, lldb.SBProcess) and process.IsValid(): + self.process = process + self.threads = None # Will be an dictionary containing info for each thread + + def get_target(self): + # NOTE: Don't use "lldb.target" when trying to get your target as the "lldb.target" + # tracks the current target in the LLDB command interpreter which isn't the + # correct thing to use for this plug-in. + return self.process.target + + def create_thread(self, tid, context): + if tid == 0x444444444: + thread_info = { + 'tid': tid, + 'name': 'four', + 'queue': 'queue4', + 'state': 'stopped', + 'stop_reason': 'none'} + self.threads.append(thread_info) + return thread_info + return None + + def get_thread_info(self): + if not self.threads: + # The sample dictionary below shows the values that can be returned for a thread + # tid => thread ID (mandatory) + # name => thread name (optional key/value pair) + # queue => thread dispatch queue name (optional key/value pair) + # state => thred state (mandatory, set to 'stopped' for now) + # stop_reason => thread stop reason. (mandatory, usually set to 'none') + # Possible values include: + # 'breakpoint' if the thread is stopped at a breakpoint + # 'none' thread is just stopped because the process is stopped + # 'trace' the thread just single stepped + # The usual value for this while threads are in memory is 'none' + # register_data_addr => the address of the register data in memory (optional key/value pair) + # Specifying this key/value pair for a thread will avoid a call to get_register_data() + # and can be used when your registers are in a thread context structure that is contiguous + # in memory. Don't specify this if your register layout in memory doesn't match the layout + # described by the dictionary returned from a call to the + # get_register_info() method. + self.threads = [ + {'tid': 0x111111111, 'core': 0} + ] + return self.threads + + def get_register_info(self): + if self.registers is None: + self.registers = dict() + self.registers['sets'] = ['GPR'] + self.registers['registers'] = [ + {'name': 'rax', 'bitsize': 64, 'offset': 0, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 0, 'dwarf': 0}, + {'name': 'rbx', 'bitsize': 64, 'offset': 8, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 3, 'dwarf': 3}, + {'name': 'rcx', 'bitsize': 64, 'offset': 16, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 2, 'dwarf': 2, 'generic': 'arg4', 'alt-name': 'arg4', }, + {'name': 'rdx', 'bitsize': 64, 'offset': 24, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 1, 'dwarf': 1, 'generic': 'arg3', 'alt-name': 'arg3', }, + {'name': 'rdi', 'bitsize': 64, 'offset': 32, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 5, 'dwarf': 5, 'generic': 'arg1', 'alt-name': 'arg1', }, + {'name': 'rsi', 'bitsize': 64, 'offset': 40, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 4, 'dwarf': 4, 'generic': 'arg2', 'alt-name': 'arg2', }, + {'name': 'rbp', 'bitsize': 64, 'offset': 48, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 6, 'dwarf': 6, 'generic': 'fp', 'alt-name': 'fp', }, + {'name': 'rsp', 'bitsize': 64, 'offset': 56, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 7, 'dwarf': 7, 'generic': 'sp', 'alt-name': 'sp', }, + {'name': 'r8', 'bitsize': 64, 'offset': 64, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 8, 'dwarf': 8, 'generic': 'arg5', 'alt-name': 'arg5', }, + {'name': 'r9', 'bitsize': 64, 'offset': 72, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 9, 'dwarf': 9, 'generic': 'arg6', 'alt-name': 'arg6', }, + {'name': 'r10', 'bitsize': 64, 'offset': 80, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 10, 'dwarf': 10}, + {'name': 'r11', 'bitsize': 64, 'offset': 88, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 11, 'dwarf': 11}, + {'name': 'r12', 'bitsize': 64, 'offset': 96, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 12, 'dwarf': 12}, + {'name': 'r13', 'bitsize': 64, 'offset': 104, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 13, 'dwarf': 13}, + {'name': 'r14', 'bitsize': 64, 'offset': 112, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 14, 'dwarf': 14}, + {'name': 'r15', 'bitsize': 64, 'offset': 120, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 15, 'dwarf': 15}, + {'name': 'rip', 'bitsize': 64, 'offset': 128, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 16, 'dwarf': 16, 'generic': 'pc', 'alt-name': 'pc'}, + {'name': 'rflags', 'bitsize': 64, 'offset': 136, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'generic': 'flags', 'alt-name': 'flags'}, + {'name': 'cs', 'bitsize': 64, 'offset': 144, 'encoding': 'uint', 'format': 'hex', 'set': 0}, + {'name': 'fs', 'bitsize': 64, 'offset': 152, 'encoding': 'uint', 'format': 'hex', 'set': 0}, + {'name': 'gs', 'bitsize': 64, 'offset': 160, 'encoding': 'uint', 'format': 'hex', 'set': 0}, + ] + return self.registers + + def get_register_data(self, tid): + return struct.pack( + '21Q', + tid + 1, + tid + 2, + tid + 3, + tid + 4, + tid + 5, + tid + 6, + tid + 7, + tid + 8, + tid + 9, + tid + 10, + tid + 11, + tid + 12, + tid + 13, + tid + 14, + tid + 15, + tid + 16, + tid + 17, + tid + 18, + tid + 19, + tid + 20, + tid + 21) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py new file mode 100644 index 00000000000..c2746bf1a80 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py @@ -0,0 +1,379 @@ +""" +Test basics of linux core file debugging. +""" + +from __future__ import division, print_function + +import shutil +import struct +import os + +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 + _mips64_n64_pid = 25619 + _mips64_n32_pid = 3670 + _mips_o32_pid = 3532 + _ppc64le_pid = 28147 + + _i386_regions = 4 + _x86_64_regions = 5 + _s390x_regions = 2 + _mips_regions = 5 + _ppc64le_regions = 2 + + def setUp(self): + super(LinuxCoreTestCase, self).setUp() + self._initial_platform = lldb.DBG.GetSelectedPlatform() + + def tearDown(self): + lldb.DBG.SetSelectedPlatform(self._initial_platform) + super(LinuxCoreTestCase, self).tearDown() + + @skipIf(triple='^mips') + @skipIfLLVMTargetMissing("X86") + 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, "a.out") + + @skipIfLLVMTargetMissing("Mips") + def test_mips_o32(self): + """Test that lldb can read the process information from an MIPS O32 linux core file.""" + self.do_test("linux-mipsel-gnuabio32", self._mips_o32_pid, + self._mips_regions, "linux-mipsel-gn") + + @skipIfLLVMTargetMissing("Mips") + def test_mips_n32(self): + """Test that lldb can read the process information from an MIPS N32 linux core file """ + self.do_test("linux-mips64el-gnuabin32", self._mips64_n32_pid, + self._mips_regions, "linux-mips64el-") + + @skipIfLLVMTargetMissing("Mips") + def test_mips_n64(self): + """Test that lldb can read the process information from an MIPS N64 linux core file """ + self.do_test("linux-mips64el-gnuabi64", self._mips64_n64_pid, + self._mips_regions, "linux-mips64el-") + + @skipIf(triple='^mips') + @skipIfLLVMTargetMissing("PowerPC") + def test_ppc64le(self): + """Test that lldb can read the process information from an ppc64le linux core file.""" + self.do_test("linux-ppc64le", self._ppc64le_pid, self._ppc64le_regions, + "linux-ppc64le.ou") + + @skipIf(triple='^mips') + @skipIfLLVMTargetMissing("X86") + 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, + "a.out") + + @skipIf(triple='^mips') + @skipIfLLVMTargetMissing("SystemZ") + 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, + "a.out") + + @skipIf(triple='^mips') + @skipIfLLVMTargetMissing("X86") + 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""" + exe_file = self.getBuildArtifact("linux-x86_64-pid.out") + core_file = self.getBuildArtifact("linux-x86_64-pid.core") + shutil.copyfile("linux-x86_64.out", exe_file) + shutil.copyfile("linux-x86_64.core", core_file) + with open(core_file, "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(self.getBuildArtifact("linux-x86_64-pid"), os.getpid(), + self._x86_64_regions, "a.out") + + @skipIf(triple='^mips') + @skipIfLLVMTargetMissing("X86") + 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, + "a.out") + + @skipIf(triple='^mips') + @skipIfLLVMTargetMissing("X86") + 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"] = "0x00ff" + 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.items(): + 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.items(): + self.expect("register read {}".format(regname), substrs=["{} = {}".format(regname, value)]) + + @skipIf(triple='^mips') + @skipIfLLVMTargetMissing("X86") + def test_i386_sysroot(self): + """Test that lldb can find the exe for an i386 linux core file using the sysroot.""" + + # Copy linux-i386.out to tmp_sysroot/home/labath/test/a.out (since it was compiled as + # /home/labath/test/a.out) + tmp_sysroot = os.path.join(self.getBuildDir(), "lldb_i386_mock_sysroot") + executable = os.path.join(tmp_sysroot, "home", "labath", "test", "a.out") + lldbutil.mkdir_p(os.path.dirname(executable)) + shutil.copyfile("linux-i386.out", executable) + + # Set sysroot and load core + self.runCmd("platform select remote-linux --sysroot '%s'" % tmp_sysroot) + target = self.dbg.CreateTarget(None) + self.assertTrue(target, VALID_TARGET) + process = target.LoadCore("linux-i386.core") + + # Check that we found a.out from the sysroot + self.check_all(process, self._i386_pid, self._i386_regions, "a.out") + + self.dbg.DeleteTarget(target) + + @skipIf(triple='^mips') + @skipIfLLVMTargetMissing("ARM") + def test_arm_core(self): + # check 32 bit ARM core file + target = self.dbg.CreateTarget(None) + self.assertTrue(target, VALID_TARGET) + process = target.LoadCore("linux-arm.core") + + values = {} + values["r0"] = "0x00000000" + values["r1"] = "0x00000001" + values["r2"] = "0x00000002" + values["r3"] = "0x00000003" + values["r4"] = "0x00000004" + values["r5"] = "0x00000005" + values["r6"] = "0x00000006" + values["r7"] = "0x00000007" + values["r8"] = "0x00000008" + values["r9"] = "0x00000009" + values["r10"] = "0x0000000a" + values["r11"] = "0x0000000b" + values["r12"] = "0x0000000c" + values["sp"] = "0x0000000d" + values["lr"] = "0x0000000e" + values["pc"] = "0x0000000f" + values["cpsr"] = "0x00000010" + for regname, value in values.items(): + 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 check_state(self, process): + with open(os.devnull) as devnul: + # sanitize test output + self.dbg.SetOutputFileHandle(devnul, False) + self.dbg.SetErrorFileHandle(devnul, False) + + self.assertTrue(process.is_stopped) + + # Process.Continue + error = process.Continue() + self.assertFalse(error.Success()) + self.assertTrue(process.is_stopped) + + # Thread.StepOut + thread = process.GetSelectedThread() + thread.StepOut() + self.assertTrue(process.is_stopped) + + # command line + self.dbg.HandleCommand('s') + self.assertTrue(process.is_stopped) + self.dbg.HandleCommand('c') + self.assertTrue(process.is_stopped) + + # restore file handles + self.dbg.SetOutputFileHandle(None, False) + self.dbg.SetErrorFileHandle(None, False) + + def check_stack(self, process, pid, thread_name): + thread = process.GetSelectedThread() + self.assertTrue(thread) + self.assertEqual(thread.GetThreadID(), pid) + self.assertEqual(thread.GetName(), thread_name) + 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])) + + def check_all(self, process, pid, region_count, thread_name): + self.assertTrue(process, PROCESS_IS_VALID) + self.assertEqual(process.GetNumThreads(), 1) + self.assertEqual(process.GetProcessID(), pid) + + self.check_state(process) + + self.check_stack(process, pid, thread_name) + + self.check_memory_regions(process, region_count) + + def do_test(self, filename, pid, region_count, thread_name): + target = self.dbg.CreateTarget(filename + ".out") + process = target.LoadCore(filename + ".core") + + self.check_all(process, pid, region_count, thread_name) + + self.dbg.DeleteTarget(target) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/altmain.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/altmain.c new file mode 100644 index 00000000000..da49a00996e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-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/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/altmain.out b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/altmain.out Binary files differnew file mode 100755 index 00000000000..2fddf3e8f80 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/altmain.out diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/fpr_sse.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/fpr_sse.cpp new file mode 100644 index 00000000000..e6826fc7a09 --- /dev/null +++ b/gnu/llvm/lldb/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/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/TestGCore.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/TestGCore.py new file mode 100644 index 00000000000..ca863d25048 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/TestGCore.py @@ -0,0 +1,54 @@ +""" +Test signal reporting when debugging with linux core files. +""" + + + +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__) + def setUp(self): + super(GCoreTestCase, self).setUp() + self._initial_platform = lldb.DBG.GetSelectedPlatform() + + def tearDown(self): + lldb.DBG.SetSelectedPlatform(self._initial_platform) + super(GCoreTestCase, self).tearDown() + + _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) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/main.cpp new file mode 100644 index 00000000000..a8e5f34d14e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/main.cpp @@ -0,0 +1,62 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// This test verifies the correct handling of child thread exits. + +#include "pseudo_barrier.h" +#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/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/main.mk b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/main.mk new file mode 100755 index 00000000000..566938ca0cc --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/main.mk @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp +ENABLE_THREADS := YES +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/make-core.sh b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/make-core.sh new file mode 100755 index 00000000000..b6979c7790d --- /dev/null +++ b/gnu/llvm/lldb/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/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-i386.out b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-i386.out Binary files differnew file mode 100755 index 00000000000..3cdd4eeca10 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-i386.out diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-mips64el-gnuabi64.out b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-mips64el-gnuabi64.out Binary files differnew file mode 100755 index 00000000000..a230aa4251a --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-mips64el-gnuabi64.out diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-mips64el-gnuabin32.out b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-mips64el-gnuabin32.out Binary files differnew file mode 100755 index 00000000000..d1293a71a85 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-mips64el-gnuabin32.out diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-mipsel-gnuabio32.out b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-mipsel-gnuabio32.out Binary files differnew file mode 100755 index 00000000000..dc809c8da48 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-mipsel-gnuabio32.out diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-ppc64le.out b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-ppc64le.out Binary files differnew file mode 100755 index 00000000000..05c69fd291b --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-ppc64le.out diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-s390x.out b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-s390x.out Binary files differnew file mode 100755 index 00000000000..640fbdc257d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-s390x.out diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-x86_64.out b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-x86_64.out Binary files differnew file mode 100755 index 00000000000..842402fd519 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/linux-x86_64.out diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/main.c new file mode 100644 index 00000000000..f5bde4171ca --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-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/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/make-core.sh b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/make-core.sh new file mode 100755 index 00000000000..9dd83f19c76 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/make-core.sh @@ -0,0 +1,61 @@ +#! /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 + +file=$1 +if [ -z "$file" ]; then + cat <<EOF +Please supply the main source file as the first argument. +EOF + exit 1 +fi + +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 + +${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 $core_pattern. +EOF + +ulimit -s 8 # Decrease stack size to 8k => smaller core files. +exec ./a.out diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/TestLinuxCoreThreads.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/TestLinuxCoreThreads.py new file mode 100644 index 00000000000..4be7ebe3122 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/TestLinuxCoreThreads.py @@ -0,0 +1,75 @@ +""" +Test signal reporting when debugging with linux core files. +""" + + + +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__) + + def setUp(self): + super(LinuxCoreThreadsTestCase, self).setUp() + self._initial_platform = lldb.DBG.GetSelectedPlatform() + + def tearDown(self): + lldb.DBG.SetSelectedPlatform(self._initial_platform) + super(LinuxCoreThreadsTestCase, self).tearDown() + + _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: + # Verify that if we try to read memory from a PT_LOAD that has + # p_filesz of zero that we don't get bytes from the next section + # that actually did have bytes. The addresses below were found by + # dumping the program headers of linux-i386.core and + # linux-x86_64.core and verifying that they had a p_filesz of zero. + mem_err = lldb.SBError() + if process.GetAddressByteSize() == 4: + bytes_read = process.ReadMemory(0x8048000, 4, mem_err) + else: + bytes_read = process.ReadMemory(0x400000, 4, mem_err) + self.assertEqual(bytes_read, None) + 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) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/main.cpp new file mode 100644 index 00000000000..dd83558bd69 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/main.cpp @@ -0,0 +1,62 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// This test verifies the correct handling of child thread exits. + +#include "pseudo_barrier.h" +#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/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/main.mk b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/main.mk new file mode 100755 index 00000000000..566938ca0cc --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/main.mk @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp +ENABLE_THREADS := YES +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/make-core.sh b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/make-core.sh new file mode 100755 index 00000000000..ea263c86ea4 --- /dev/null +++ b/gnu/llvm/lldb/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/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/mach-core/TestMachCore.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/mach-core/TestMachCore.py new file mode 100644 index 00000000000..7680b55e60d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/mach-core/TestMachCore.py @@ -0,0 +1,69 @@ +""" +Test basics of mach core file debugging. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class MachCoreTestCase(TestBase): + NO_DEBUG_INFO_TESTCASE = True + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + super(MachCoreTestCase, self).setUp() + self._initial_platform = lldb.DBG.GetSelectedPlatform() + + def tearDown(self): + lldb.DBG.SetSelectedPlatform(self._initial_platform) + super(MachCoreTestCase, self).tearDown() + + # This was originally marked as expected failure on Windows, but it has + # started timing out instead, so the expectedFailure attribute no longer + # correctly tracks it: llvm.org/pr37371 + @skipIfWindows + def test_selected_thread(self): + """Test that the right thread is selected after a core is loaded.""" + # Create core form YAML. + self.yaml2obj("test.core.yaml", self.getBuildArtifact("test.core")) + + # Set debugger into synchronous mode + self.dbg.SetAsync(False) + + # Create a target by the debugger. + target = self.dbg.CreateTarget("") + + # Load OS plugin. + python_os_plugin_path = os.path.join(self.getSourceDir(), + 'operating_system.py') + command = "settings set target.process.python-os-plugin-path '{}'".format( + python_os_plugin_path) + self.dbg.HandleCommand(command) + + # Load core. + process = target.LoadCore(self.getBuildArtifact("test.core")) + self.assertTrue(process, PROCESS_IS_VALID) + self.assertEqual(process.GetNumThreads(), 3) + + # Verify our OS plug-in threads showed up + thread = process.GetThreadByID(0x111111111) + self.assertTrue(thread.IsValid( + ), "Make sure there is a thread 0x111111111 after we load the python OS plug-in" + ) + thread = process.GetThreadByID(0x222222222) + self.assertTrue(thread.IsValid( + ), "Make sure there is a thread 0x222222222 after we load the python OS plug-in" + ) + thread = process.GetThreadByID(0x333333333) + self.assertTrue(thread.IsValid( + ), "Make sure there is a thread 0x333333333 after we load the python OS plug-in" + ) + + # Verify that the correct thread is selected + thread = process.GetSelectedThread() + self.assertEqual(thread.GetThreadID(), 0x333333333) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/mach-core/operating_system.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/mach-core/operating_system.py new file mode 100644 index 00000000000..95a5bdc9dd8 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/mach-core/operating_system.py @@ -0,0 +1,44 @@ +import lldb + + +class OperatingSystemPlugIn(object): + """Class that provides data for an instance of a LLDB 'OperatingSystemPython' plug-in class""" + + def __init__(self, process): + '''Initialization needs a valid.SBProcess object. + + This plug-in will get created after a live process is valid and has stopped for the first time. + ''' + self.process = None + self.registers = None + self.threads = None + if isinstance(process, lldb.SBProcess) and process.IsValid(): + self.process = process + self.threads = None # Will be an dictionary containing info for each thread + + def get_target(self): + return self.process.target + + def get_thread_info(self): + if not self.threads: + self.threads = [{ + 'tid': 0x111111111, + 'name': 'one', + 'queue': 'queue1', + 'state': 'stopped', + 'stop_reason': 'none' + }, { + 'tid': 0x222222222, + 'name': 'two', + 'queue': 'queue2', + 'state': 'stopped', + 'stop_reason': 'none' + }, { + 'tid': 0x333333333, + 'name': 'three', + 'queue': 'queue3', + 'state': 'stopped', + 'stop_reason': 'sigstop', + 'core': 0 + }] + return self.threads diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/mach-core/test.core.yaml b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/mach-core/test.core.yaml new file mode 100644 index 00000000000..84ce54e45e1 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/mach-core/test.core.yaml @@ -0,0 +1,853 @@ +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x01000007 + cpusubtype: 0x00000003 + filetype: 0x00000004 + ncmds: 59 + sizeofcmds: 4384 + flags: 0x00000000 + reserved: 0x00000000 +LoadCommands: + - cmd: LC_THREAD + cmdsize: 208 + PayloadBytes: + - 0x04 + - 0x00 + - 0x00 + - 0x00 + - 0x2A + - 0x00 + - 0x00 + - 0x00 + - 0x01 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x80 + - 0xF7 + - 0xBF + - 0xEF + - 0xFE + - 0x7F + - 0x00 + - 0x00 + - 0x20 + - 0xF6 + - 0xBF + - 0xEF + - 0xFE + - 0x7F + - 0x00 + - 0x00 + - 0x01 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x10 + - 0xF6 + - 0xBF + - 0xEF + - 0xFE + - 0x7F + - 0x00 + - 0x00 + - 0xF0 + - 0xF5 + - 0xBF + - 0xEF + - 0xFE + - 0x7F + - 0x00 + - 0x00 + - 0xF0 + - 0xF5 + - 0xBF + - 0xEF + - 0xFE + - 0x7F + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0xFF + - 0xFF + - 0xFF + - 0xFF + - 0xC8 + - 0xB0 + - 0x70 + - 0xA7 + - 0xFF + - 0x7F + - 0x00 + - 0x00 + - 0xD0 + - 0xB0 + - 0x70 + - 0xA7 + - 0xFF + - 0x7F + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0xA0 + - 0x0F + - 0x00 + - 0x00 + - 0x01 + - 0x00 + - 0x00 + - 0x00 + - 0x46 + - 0x02 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x2B + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x06 + - 0x00 + - 0x00 + - 0x00 + - 0x04 + - 0x00 + - 0x00 + - 0x00 + - 0x03 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x10 + - 0x00 + - 0x02 + - 0xA7 + - 0xFF + - 0x7F + - 0x00 + - 0x00 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 4294967296 + vmsize: 4096 + fileoff: 8192 + filesize: 4096 + maxprot: 5 + initprot: 5 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 4294971392 + vmsize: 4096 + fileoff: 12288 + filesize: 4096 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 4294975488 + vmsize: 307200 + fileoff: 16384 + filesize: 307200 + maxprot: 5 + initprot: 5 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 4295282688 + vmsize: 12288 + fileoff: 323584 + filesize: 12288 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 4295294976 + vmsize: 217088 + fileoff: 335872 + filesize: 217088 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 4295512064 + vmsize: 110592 + fileoff: 552960 + filesize: 110592 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 4295622656 + vmsize: 8192 + fileoff: 663552 + filesize: 8192 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 4295630848 + vmsize: 8192 + fileoff: 671744 + filesize: 8192 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 4295639040 + vmsize: 4096 + fileoff: 679936 + filesize: 4096 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 4295643136 + vmsize: 4096 + fileoff: 684032 + filesize: 4096 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 4295651328 + vmsize: 24576 + fileoff: 688128 + filesize: 24576 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 4295684096 + vmsize: 24576 + fileoff: 712704 + filesize: 24576 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 4295712768 + vmsize: 4096 + fileoff: 737280 + filesize: 4096 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 4295716864 + vmsize: 8192 + fileoff: 741376 + filesize: 8192 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 4296015872 + vmsize: 1048576 + fileoff: 749568 + filesize: 1048576 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 4297064448 + vmsize: 1048576 + fileoff: 1798144 + filesize: 1048576 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 4298113024 + vmsize: 1048576 + fileoff: 2846720 + filesize: 1048576 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 4303355904 + vmsize: 8388608 + fileoff: 3895296 + filesize: 8388608 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140732912369664 + vmsize: 8388608 + fileoff: 12283904 + filesize: 8388608 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140734252867584 + vmsize: 811999232 + fileoff: 20672512 + filesize: 811999232 + maxprot: 5 + initprot: 5 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735863480320 + vmsize: 20553728 + fileoff: 832671744 + filesize: 20553728 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735884034048 + vmsize: 2097152 + fileoff: 853225472 + filesize: 2097152 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735886131200 + vmsize: 2097152 + fileoff: 855322624 + filesize: 2097152 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735888228352 + vmsize: 2097152 + fileoff: 857419776 + filesize: 2097152 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735890325504 + vmsize: 2097152 + fileoff: 859516928 + filesize: 2097152 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735892422656 + vmsize: 2097152 + fileoff: 861614080 + filesize: 2097152 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735894519808 + vmsize: 2097152 + fileoff: 863711232 + filesize: 2097152 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735896616960 + vmsize: 2097152 + fileoff: 865808384 + filesize: 2097152 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735898714112 + vmsize: 2097152 + fileoff: 867905536 + filesize: 2097152 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735900811264 + vmsize: 2097152 + fileoff: 870002688 + filesize: 2097152 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735902908416 + vmsize: 10485760 + fileoff: 872099840 + filesize: 10485760 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735913394176 + vmsize: 4194304 + fileoff: 882585600 + filesize: 4194304 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735917588480 + vmsize: 2097152 + fileoff: 886779904 + filesize: 2097152 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735919685632 + vmsize: 2097152 + fileoff: 888877056 + filesize: 2097152 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735921782784 + vmsize: 4194304 + fileoff: 890974208 + filesize: 4194304 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735925977088 + vmsize: 4194304 + fileoff: 895168512 + filesize: 4194304 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735930171392 + vmsize: 6291456 + fileoff: 899362816 + filesize: 6291456 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735936462848 + vmsize: 2097152 + fileoff: 905654272 + filesize: 2097152 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735938560000 + vmsize: 2097152 + fileoff: 907751424 + filesize: 2097152 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735940657152 + vmsize: 2097152 + fileoff: 909848576 + filesize: 2097152 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735942754304 + vmsize: 2097152 + fileoff: 911945728 + filesize: 2097152 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735944851456 + vmsize: 6291456 + fileoff: 914042880 + filesize: 6291456 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735951142912 + vmsize: 2097152 + fileoff: 920334336 + filesize: 2097152 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735953240064 + vmsize: 4194304 + fileoff: 922431488 + filesize: 4194304 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735957434368 + vmsize: 2097152 + fileoff: 926625792 + filesize: 2097152 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735959531520 + vmsize: 2097152 + fileoff: 928722944 + filesize: 2097152 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735961628672 + vmsize: 20971520 + fileoff: 930820096 + filesize: 20971520 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735982600192 + vmsize: 6291456 + fileoff: 951791616 + filesize: 6291456 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735988891648 + vmsize: 2097152 + fileoff: 958083072 + filesize: 2097152 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735990988800 + vmsize: 2097152 + fileoff: 960180224 + filesize: 2097152 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735993085952 + vmsize: 2097152 + fileoff: 962277376 + filesize: 2097152 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735995183104 + vmsize: 2097152 + fileoff: 964374528 + filesize: 2097152 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735997280256 + vmsize: 2097152 + fileoff: 966471680 + filesize: 2097152 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140735999377408 + vmsize: 2097152 + fileoff: 968568832 + filesize: 2097152 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140736001474560 + vmsize: 1302528 + fileoff: 970665984 + filesize: 1302528 + maxprot: 3 + initprot: 3 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140736937222144 + vmsize: 219267072 + fileoff: 971968512 + filesize: 219267072 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140737486258176 + vmsize: 4096 + fileoff: 1191235584 + filesize: 4096 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: '' + vmaddr: 140737487028224 + vmsize: 4096 + fileoff: 1191239680 + filesize: 4096 + maxprot: 5 + initprot: 5 + nsects: 0 + flags: 0 +... diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpNew.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpNew.py new file mode 100644 index 00000000000..62b6c80e0b3 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpNew.py @@ -0,0 +1,463 @@ +""" +Test basics of Minidump debugging. +""" + +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 setUp(self): + super(MiniDumpNewTestCase, self).setUp() + self._initial_platform = lldb.DBG.GetSelectedPlatform() + + def tearDown(self): + lldb.DBG.SetSelectedPlatform(self._initial_platform) + super(MiniDumpNewTestCase, self).tearDown() + + def process_from_yaml(self, yaml_file): + minidump_path = self.getBuildArtifact(os.path.basename(yaml_file) + ".dmp") + self.yaml2obj(yaml_file, minidump_path) + self.target = self.dbg.CreateTarget(None) + self.process = self.target.LoadCore(minidump_path) + return self.process + + def check_state(self): + with open(os.devnull) as devnul: + # sanitize test output + self.dbg.SetOutputFileHandle(devnul, False) + self.dbg.SetErrorFileHandle(devnul, False) + + self.assertTrue(self.process.is_stopped) + + # Process.Continue + error = self.process.Continue() + self.assertFalse(error.Success()) + self.assertTrue(self.process.is_stopped) + + # Thread.StepOut + thread = self.process.GetSelectedThread() + thread.StepOut() + self.assertTrue(self.process.is_stopped) + + # command line + self.dbg.HandleCommand('s') + self.assertTrue(self.process.is_stopped) + self.dbg.HandleCommand('c') + self.assertTrue(self.process.is_stopped) + + # restore file handles + self.dbg.SetOutputFileHandle(None, False) + self.dbg.SetErrorFileHandle(None, False) + + def test_loadcore_error_status(self): + """Test the SBTarget.LoadCore(core, error) overload.""" + minidump_path = self.getBuildArtifact("linux-x86_64.dmp") + self.yaml2obj("linux-x86_64.yaml", minidump_path) + self.target = self.dbg.CreateTarget(None) + error = lldb.SBError() + self.process = self.target.LoadCore(minidump_path, error) + self.assertTrue(self.process, PROCESS_IS_VALID) + self.assertTrue(error.Success()) + + def test_loadcore_error_status_failure(self): + """Test the SBTarget.LoadCore(core, error) overload.""" + self.target = self.dbg.CreateTarget(None) + error = lldb.SBError() + self.process = self.target.LoadCore("non-existent.dmp", error) + self.assertFalse(self.process, PROCESS_IS_VALID) + self.assertTrue(error.Fail()) + + def test_process_info_in_minidump(self): + """Test that lldb can read the process information from the Minidump.""" + self.process_from_yaml("linux-x86_64.yaml") + self.assertTrue(self.process, PROCESS_IS_VALID) + self.assertEqual(self.process.GetNumThreads(), 1) + self.assertEqual(self.process.GetProcessID(), self._linux_x86_64_pid) + self.check_state() + + def test_memory_region_name(self): + self.process_from_yaml("regions-linux-map.yaml") + result = lldb.SBCommandReturnObject() + addr_region_name_pairs = [ + ("0x400d9000", "/system/bin/app_process"), + ("0x400db000", "/system/bin/app_process"), + ("0x400dd000", "/system/bin/linker"), + ("0x400ed000", "/system/bin/linker"), + ("0x400ee000", "/system/bin/linker"), + ("0x400fb000", "/system/lib/liblog.so"), + ("0x400fc000", "/system/lib/liblog.so"), + ("0x400fd000", "/system/lib/liblog.so"), + ("0x400ff000", "/system/lib/liblog.so"), + ("0x40100000", "/system/lib/liblog.so"), + ("0x40101000", "/system/lib/libc.so"), + ("0x40122000", "/system/lib/libc.so"), + ("0x40123000", "/system/lib/libc.so"), + ("0x40167000", "/system/lib/libc.so"), + ("0x40169000", "/system/lib/libc.so"), + ] + ci = self.dbg.GetCommandInterpreter() + for (addr, region_name) in addr_region_name_pairs: + command = 'memory region ' + addr + ci.HandleCommand(command, result, False) + message = 'Ensure memory "%s" shows up in output for "%s"' % ( + region_name, command) + self.assertTrue(region_name in result.GetOutput(), message) + + def test_thread_info_in_minidump(self): + """Test that lldb can read the thread information from the Minidump.""" + self.process_from_yaml("linux-x86_64.yaml") + self.check_state() + # 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.check_state() + 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()) + self.assertTrue(frame.GetModule().IsValid()) + pc = frame.GetPC() + eip = frame.FindRegister("pc") + self.assertTrue(eip.IsValid()) + self.assertEqual(pc, eip.GetValueAsUnsigned()) + + def test_snapshot_minidump_dump_requested(self): + """Test that if we load a snapshot minidump file (meaning the process + did not crash) with exception code "DUMP_REQUESTED" 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.check_state() + 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, "") + + def test_snapshot_minidump_null_exn_code(self): + """Test that if we load a snapshot minidump file (meaning the process + did not crash) with exception code zero there is no stop reason.""" + self.process_from_yaml("linux-x86_64_null_signal.yaml") + self.check_state() + 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, "") + + def check_register_unsigned(self, set, name, expected): + reg_value = set.GetChildMemberWithName(name) + self.assertTrue(reg_value.IsValid(), + 'Verify we have a register named "%s"' % (name)) + self.assertEqual(reg_value.GetValueAsUnsigned(), expected, + 'Verify "%s" == %i' % (name, expected)) + + def check_register_string_value(self, set, name, expected, format): + reg_value = set.GetChildMemberWithName(name) + self.assertTrue(reg_value.IsValid(), + 'Verify we have a register named "%s"' % (name)) + if format is not None: + reg_value.SetFormat(format) + self.assertEqual(reg_value.GetValue(), expected, + 'Verify "%s" has string value "%s"' % (name, + expected)) + + def test_arm64_registers(self): + """Test ARM64 registers from a breakpad created minidump.""" + self.process_from_yaml("arm64-macos.yaml") + self.check_state() + 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, "") + registers = thread.GetFrameAtIndex(0).GetRegisters() + # Verify the GPR registers are all correct + # Verify x0 - x31 register values + gpr = registers.GetValueAtIndex(0) + for i in range(32): + v = i+1 | i+2 << 32 | i+3 << 48 + w = i+1 + self.check_register_unsigned(gpr, 'x%i' % (i), v) + self.check_register_unsigned(gpr, 'w%i' % (i), w) + # Verify arg1 - arg8 register values + for i in range(1, 9): + v = i | i+1 << 32 | i+2 << 48 + self.check_register_unsigned(gpr, 'arg%i' % (i), v) + i = 29 + v = i+1 | i+2 << 32 | i+3 << 48 + self.check_register_unsigned(gpr, 'fp', v) + i = 30 + v = i+1 | i+2 << 32 | i+3 << 48 + self.check_register_unsigned(gpr, 'lr', v) + i = 31 + v = i+1 | i+2 << 32 | i+3 << 48 + self.check_register_unsigned(gpr, 'sp', v) + self.check_register_unsigned(gpr, 'pc', 0x1000) + self.check_register_unsigned(gpr, 'cpsr', 0x11223344) + self.check_register_unsigned(gpr, 'psr', 0x11223344) + + # Verify the FPR registers are all correct + fpr = registers.GetValueAtIndex(1) + for i in range(32): + v = "0x" + d = "0x" + s = "0x" + h = "0x" + for j in range(i+15, i-1, -1): + v += "%2.2x" % (j) + for j in range(i+7, i-1, -1): + d += "%2.2x" % (j) + for j in range(i+3, i-1, -1): + s += "%2.2x" % (j) + for j in range(i+1, i-1, -1): + h += "%2.2x" % (j) + self.check_register_string_value(fpr, "v%i" % (i), v, + lldb.eFormatHex) + self.check_register_string_value(fpr, "d%i" % (i), d, + lldb.eFormatHex) + self.check_register_string_value(fpr, "s%i" % (i), s, + lldb.eFormatHex) + self.check_register_string_value(fpr, "h%i" % (i), h, + lldb.eFormatHex) + self.check_register_unsigned(gpr, 'fpsr', 0x55667788) + self.check_register_unsigned(gpr, 'fpcr', 0x99aabbcc) + + def verify_arm_registers(self, apple=False): + """ + Verify values of all ARM registers from a breakpad created + minidump. + """ + if apple: + self.process_from_yaml("arm-macos.yaml") + else: + self.process_from_yaml("arm-linux.yaml") + self.check_state() + 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, "") + registers = thread.GetFrameAtIndex(0).GetRegisters() + # Verify the GPR registers are all correct + # Verify x0 - x31 register values + gpr = registers.GetValueAtIndex(0) + for i in range(1, 16): + self.check_register_unsigned(gpr, 'r%i' % (i), i+1) + # Verify arg1 - arg4 register values + for i in range(1, 5): + self.check_register_unsigned(gpr, 'arg%i' % (i), i) + if apple: + self.check_register_unsigned(gpr, 'fp', 0x08) + else: + self.check_register_unsigned(gpr, 'fp', 0x0c) + self.check_register_unsigned(gpr, 'lr', 0x0f) + self.check_register_unsigned(gpr, 'sp', 0x0e) + self.check_register_unsigned(gpr, 'pc', 0x10) + self.check_register_unsigned(gpr, 'cpsr', 0x11223344) + + # Verify the FPR registers are all correct + fpr = registers.GetValueAtIndex(1) + # Check d0 - d31 + self.check_register_unsigned(gpr, 'fpscr', 0x55667788aabbccdd) + for i in range(32): + value = (i+1) | (i+1) << 8 | (i+1) << 32 | (i+1) << 48 + self.check_register_unsigned(fpr, "d%i" % (i), value) + # Check s0 - s31 + for i in range(32): + i_val = (i >> 1) + 1 + if i & 1: + value = "%#8.8x" % (i_val | i_val << 16) + else: + value = "%#8.8x" % (i_val | i_val << 8) + self.check_register_string_value(fpr, "s%i" % (i), value, + lldb.eFormatHex) + # Check q0 - q15 + for i in range(15): + a = i * 2 + 1 + b = a + 1 + value = ("0x00%2.2x00%2.2x0000%2.2x%2.2x" + "00%2.2x00%2.2x0000%2.2x%2.2x") % (b, b, b, b, a, a, a, a) + self.check_register_string_value(fpr, "q%i" % (i), value, + lldb.eFormatHex) + + def test_linux_arm_registers(self): + """Test Linux ARM registers from a breakpad created minidump. + + The frame pointer is R11 for linux. + """ + self.verify_arm_registers(apple=False) + + def test_apple_arm_registers(self): + """Test Apple ARM registers from a breakpad created minidump. + + The frame pointer is R7 for linux. + """ + self.verify_arm_registers(apple=True) + + 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) + + @skipIfLLVMTargetMissing("X86") + 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""" + new_core = self.getBuildArtifact("linux-x86_64_not_crashed-pid.dmp") + self.do_change_pid_in_minidump("linux-x86_64_not_crashed.dmp", + new_core, + 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", new_core, os.getpid()) + + def test_two_cores_same_pid(self): + """Test that we handle the situation if we have two core files with the same PID """ + new_core = self.getBuildArtifact("linux-x86_64_not_crashed-pid.dmp") + self.do_change_pid_in_minidump("linux-x86_64_not_crashed.dmp", + new_core, + 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", + new_core, self._linux_x86_64_pid) + self.test_stack_info_in_minidump() + + 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 + self.target = self.dbg.CreateTarget("linux-x86_64_not_crashed") + self.process = self.target.LoadCore("linux-x86_64_not_crashed.dmp") + self.check_state() + thread = self.process.GetThreadAtIndex(0) + frame = thread.GetFrameAtIndex(1) + value = frame.EvaluateExpression('x') + self.assertEqual(value.GetValueAsSigned(), 3) + + def test_memory_regions_in_minidump(self): + """Test memory regions from a Minidump""" + self.process_from_yaml("regions-linux-map.yaml") + self.check_state() + + regions_count = 19 + region_info_list = self.process.GetMemoryRegions() + self.assertEqual(region_info_list.GetSize(), regions_count) + + def check_region(index, start, end, read, write, execute, mapped, name): + region_info = lldb.SBMemoryRegionInfo() + self.assertTrue( + self.process.GetMemoryRegionInfo(start, region_info).Success()) + self.assertEqual(start, region_info.GetRegionBase()) + self.assertEqual(end, region_info.GetRegionEnd()) + self.assertEqual(read, region_info.IsReadable()) + self.assertEqual(write, region_info.IsWritable()) + self.assertEqual(execute, region_info.IsExecutable()) + self.assertEqual(mapped, region_info.IsMapped()) + self.assertEqual(name, region_info.GetName()) + + # Ensure we have the same regions as SBMemoryRegionInfoList contains. + if index >= 0 and index < regions_count: + region_info_from_list = lldb.SBMemoryRegionInfo() + self.assertTrue(region_info_list.GetMemoryRegionAtIndex( + index, region_info_from_list)) + self.assertEqual(region_info_from_list, region_info) + + a = "/system/bin/app_process" + b = "/system/bin/linker" + c = "/system/lib/liblog.so" + d = "/system/lib/libc.so" + n = None + max_int = 0xffffffffffffffff + + # Test address before the first entry comes back with nothing mapped up + # to first valid region info + check_region(-1, 0x00000000, 0x400d9000, False, False, False, False, n) + check_region( 0, 0x400d9000, 0x400db000, True, False, True, True, a) + check_region( 1, 0x400db000, 0x400dc000, True, False, False, True, a) + check_region( 2, 0x400dc000, 0x400dd000, True, True, False, True, n) + check_region( 3, 0x400dd000, 0x400ec000, True, False, True, True, b) + check_region( 4, 0x400ec000, 0x400ed000, True, False, False, True, n) + check_region( 5, 0x400ed000, 0x400ee000, True, False, False, True, b) + check_region( 6, 0x400ee000, 0x400ef000, True, True, False, True, b) + check_region( 7, 0x400ef000, 0x400fb000, True, True, False, True, n) + check_region( 8, 0x400fb000, 0x400fc000, True, False, True, True, c) + check_region( 9, 0x400fc000, 0x400fd000, True, True, True, True, c) + check_region(10, 0x400fd000, 0x400ff000, True, False, True, True, c) + check_region(11, 0x400ff000, 0x40100000, True, False, False, True, c) + check_region(12, 0x40100000, 0x40101000, True, True, False, True, c) + check_region(13, 0x40101000, 0x40122000, True, False, True, True, d) + check_region(14, 0x40122000, 0x40123000, True, True, True, True, d) + check_region(15, 0x40123000, 0x40167000, True, False, True, True, d) + check_region(16, 0x40167000, 0x40169000, True, False, False, True, d) + check_region(17, 0x40169000, 0x4016b000, True, True, False, True, d) + check_region(18, 0x4016b000, 0x40176000, True, True, False, True, n) + check_region(-1, 0x40176000, max_int, False, False, False, False, n) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpUUID.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpUUID.py new file mode 100644 index 00000000000..ca0ad5f67b2 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpUUID.py @@ -0,0 +1,195 @@ +""" +Test basics of Minidump debugging. +""" + +from six import iteritems + + +import lldb +import os +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class MiniDumpUUIDTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + def setUp(self): + super(MiniDumpUUIDTestCase, self).setUp() + self._initial_platform = lldb.DBG.GetSelectedPlatform() + + def tearDown(self): + lldb.DBG.SetSelectedPlatform(self._initial_platform) + super(MiniDumpUUIDTestCase, self).tearDown() + + def verify_module(self, module, verify_path, verify_uuid): + uuid = module.GetUUIDString() + self.assertEqual(verify_path, module.GetFileSpec().fullpath) + self.assertEqual(verify_uuid, uuid) + + def get_minidump_modules(self, yaml_file): + minidump_path = self.getBuildArtifact(os.path.basename(yaml_file) + ".dmp") + self.yaml2obj(yaml_file, minidump_path) + self.target = self.dbg.CreateTarget(None) + self.process = self.target.LoadCore(minidump_path) + return self.target.modules + + def test_zero_uuid_modules(self): + """ + Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid, + but contains a PDB70 value whose age is zero and whose UUID values are + all zero. Prior to a fix all such modules would be duplicated to the + first one since the UUIDs claimed to be valid and all zeroes. Now we + ensure that the UUID is not valid for each module and that we have + each of the modules in the target after loading the core + """ + modules = self.get_minidump_modules("linux-arm-zero-uuids.yaml") + self.assertEqual(2, len(modules)) + self.verify_module(modules[0], "/file/does/not/exist/a", None) + self.verify_module(modules[1], "/file/does/not/exist/b", None) + + def test_uuid_modules_no_age(self): + """ + Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid, + and contains a PDB70 value whose age is zero and whose UUID values are + valid. Ensure we decode the UUID and don't include the age field in the UUID. + """ + modules = self.get_minidump_modules("linux-arm-uuids-no-age.yaml") + modules = self.target.modules + self.assertEqual(2, len(modules)) + self.verify_module(modules[0], "/tmp/a", "01020304-0506-0708-090A-0B0C0D0E0F10") + self.verify_module(modules[1], "/tmp/b", "0A141E28-323C-4650-5A64-6E78828C96A0") + + def test_uuid_modules_no_age_apple(self): + """ + Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid, + and contains a PDB70 value whose age is zero and whose UUID values are + valid. Ensure we decode the UUID and don't include the age field in the UUID. + Also ensure that the first uint32_t is byte swapped, along with the next + two uint16_t values. Breakpad incorrectly byte swaps these values when it + saves Darwin minidump files. + """ + modules = self.get_minidump_modules("macos-arm-uuids-no-age.yaml") + modules = self.target.modules + self.assertEqual(2, len(modules)) + self.verify_module(modules[0], "/tmp/a", "04030201-0605-0807-090A-0B0C0D0E0F10") + self.verify_module(modules[1], "/tmp/b", "281E140A-3C32-5046-5A64-6E78828C96A0") + + def test_uuid_modules_with_age(self): + """ + Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid, + and contains a PDB70 value whose age is valid and whose UUID values are + valid. Ensure we decode the UUID and include the age field in the UUID. + """ + modules = self.get_minidump_modules("linux-arm-uuids-with-age.yaml") + self.assertEqual(2, len(modules)) + self.verify_module(modules[0], "/tmp/a", "01020304-0506-0708-090A-0B0C0D0E0F10-10101010") + self.verify_module(modules[1], "/tmp/b", "0A141E28-323C-4650-5A64-6E78828C96A0-20202020") + + def test_uuid_modules_elf_build_id_16(self): + """ + Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid, + and contains a ELF build ID whose value is valid and is 16 bytes long. + """ + modules = self.get_minidump_modules("linux-arm-uuids-elf-build-id-16.yaml") + self.assertEqual(2, len(modules)) + self.verify_module(modules[0], "/tmp/a", "01020304-0506-0708-090A-0B0C0D0E0F10") + self.verify_module(modules[1], "/tmp/b", "0A141E28-323C-4650-5A64-6E78828C96A0") + + def test_uuid_modules_elf_build_id_20(self): + """ + Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid, + and contains a ELF build ID whose value is valid and is 20 bytes long. + """ + modules = self.get_minidump_modules("linux-arm-uuids-elf-build-id-20.yaml") + self.assertEqual(2, len(modules)) + self.verify_module(modules[0], "/tmp/a", "01020304-0506-0708-090A-0B0C0D0E0F10-11121314") + self.verify_module(modules[1], "/tmp/b", "0A141E28-323C-4650-5A64-6E78828C96A0-AAB4BEC8") + + def test_uuid_modules_elf_build_id_zero(self): + """ + Test multiple modules having a MINIDUMP_MODULE.CvRecord that is valid, + and contains a ELF build ID whose value is all zero. + """ + modules = self.get_minidump_modules("linux-arm-uuids-elf-build-id-zero.yaml") + self.assertEqual(2, len(modules)) + self.verify_module(modules[0], "/not/exist/a", None) + self.verify_module(modules[1], "/not/exist/b", None) + + def test_uuid_modules_elf_build_id_same(self): + """ + Test multiple modules having a MINIDUMP_MODULE.CvRecord that is + valid, and contains a ELF build ID whose value is the same. There + is an assert in the PlaceholderObjectFile that was firing when we + encountered this which was crashing the process that was checking + if PlaceholderObjectFile.m_base was the same as the address this + fake module was being loaded at. We need to ensure we don't crash + in such cases and that we add both modules even though they have + the same UUID. + """ + modules = self.get_minidump_modules("linux-arm-same-uuids.yaml") + self.assertEqual(2, len(modules)) + self.verify_module(modules[0], "/file/does/not/exist/a", + '11223344-1122-3344-1122-334411223344-11223344') + self.verify_module(modules[1], "/file/does/not/exist/b", + '11223344-1122-3344-1122-334411223344-11223344') + + @expectedFailureAll(oslist=["windows"]) + def test_partial_uuid_match(self): + """ + Breakpad has been known to create minidump files using CvRecord in each + module whose signature is set to PDB70 where the UUID only contains the + first 16 bytes of a 20 byte ELF build ID. Code was added to + ProcessMinidump.cpp to deal with this and allows partial UUID matching. + + This test verifies that if we have a minidump with a 16 byte UUID, that + we are able to associate a symbol file with a 20 byte UUID only if the + first 16 bytes match. In this case we will see the path from the file + we found in the test directory and the 20 byte UUID from the actual + file, not the 16 byte shortened UUID from the minidump. + """ + so_path = self.getBuildArtifact("libuuidmatch.so") + self.yaml2obj("libuuidmatch.yaml", so_path) + cmd = 'settings set target.exec-search-paths "%s"' % (os.path.dirname(so_path)) + self.dbg.HandleCommand(cmd) + modules = self.get_minidump_modules("linux-arm-partial-uuids-match.yaml") + self.assertEqual(1, len(modules)) + self.verify_module(modules[0], so_path, + "7295E17C-6668-9E05-CBB5-DEE5003865D5-5267C116") + + def test_partial_uuid_mismatch(self): + """ + Breakpad has been known to create minidump files using CvRecord in each + module whose signature is set to PDB70 where the UUID only contains the + first 16 bytes of a 20 byte ELF build ID. Code was added to + ProcessMinidump.cpp to deal with this and allows partial UUID matching. + + This test verifies that if we have a minidump with a 16 byte UUID, that + we are not able to associate a symbol file with a 20 byte UUID only if + any of the first 16 bytes do not match. In this case we will see the UUID + from the minidump file and the path from the minidump file. + """ + so_path = self.getBuildArtifact("libuuidmismatch.so") + self.yaml2obj("libuuidmismatch.yaml", so_path) + cmd = 'settings set target.exec-search-paths "%s"' % (os.path.dirname(so_path)) + self.dbg.HandleCommand(cmd) + modules = self.get_minidump_modules("linux-arm-partial-uuids-mismatch.yaml") + self.assertEqual(1, len(modules)) + self.verify_module(modules[0], + "/invalid/path/on/current/system/libuuidmismatch.so", + "7295E17C-6668-9E05-CBB5-DEE5003865D5") + + def test_relative_module_name(self): + old_cwd = os.getcwd() + self.addTearDownHook(lambda: os.chdir(old_cwd)) + os.chdir(self.getBuildDir()) + name = "file-with-a-name-unlikely-to-exist-in-the-current-directory.so" + open(name, "a").close() + modules = self.get_minidump_modules( + self.getSourcePath("relative_module_name.yaml")) + self.assertEqual(1, len(modules)) + self.verify_module(modules[0], name, None) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm-linux.yaml b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm-linux.yaml new file mode 100644 index 00000000000..072b4de411f --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm-linux.yaml @@ -0,0 +1,18 @@ +--- !minidump +Streams: + - Type: SystemInfo + Processor Arch: ARM + Platform ID: Linux + CSD Version: ABC123 + CPU: + CPUID: 0x00000000 + - Type: MiscInfo + Content: 00000000010000007B000000000000000000000000000000 + - Type: ThreadList + Threads: + - Thread Id: 0x00001000 + Context: 060000400100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F0000001000000044332211DDCCBBAA887766550101000001000100020200000200020003030000030003000404000004000400050500000500050006060000060006000707000007000700080800000800080009090000090009000A0A00000A000A000B0B00000B000B000C0C00000C000C000D0D00000D000D000E0E00000E000E000F0F00000F000F0010100000100010001111000011001100121200001200120013130000130013001414000014001400151500001500150016160000160016001717000017001700181800001800180019190000190019001A1A00001A001A001B1B00001B001B001C1C00001C001C001D1D00001D001D001E1E00001E001E001F1F00001F001F0020200000200020000000000001000100020002000300030004000400050005000600060007000700 + Stack: + Start of Memory Range: 0x0000000000000000 + Content: '' +... diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm-macos.yaml b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm-macos.yaml new file mode 100644 index 00000000000..b194492f6f0 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm-macos.yaml @@ -0,0 +1,18 @@ +--- !minidump +Streams: + - Type: SystemInfo + Processor Arch: ARM + Platform ID: MacOSX + CSD Version: ABC123 + CPU: + CPUID: 0x00000000 + - Type: MiscInfo + Content: 00000000010000007B000000000000000000000000000000 + - Type: ThreadList + Threads: + - Thread Id: 0x00001000 + Context: 060000400100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F0000001000000044332211DDCCBBAA887766550101000001000100020200000200020003030000030003000404000004000400050500000500050006060000060006000707000007000700080800000800080009090000090009000A0A00000A000A000B0B00000B000B000C0C00000C000C000D0D00000D000D000E0E00000E000E000F0F00000F000F0010100000100010001111000011001100121200001200120013130000130013001414000014001400151500001500150016160000160016001717000017001700181800001800180019190000190019001A1A00001A001A001B1B00001B001B001C1C00001C001C001D1D00001D001D001E1E00001E001E001F1F00001F001F0020200000200020000000000001000100020002000300030004000400050005000600060007000700 + Stack: + Start of Memory Range: 0x0000000000000000 + Content: '' +... diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm64-macos.yaml b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm64-macos.yaml new file mode 100644 index 00000000000..70817f14da5 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm64-macos.yaml @@ -0,0 +1,18 @@ +--- !minidump +Streams: + - Type: SystemInfo + Processor Arch: BP_ARM64 + Platform ID: MacOSX + CSD Version: '15E216' + CPU: + CPUID: 0x00000000 + - Type: MiscInfo + Content: 00000000010000007B000000000000000000000000000000 + - Type: ThreadList + Threads: + - Thread Id: 0x00001000 + Context: 060000800000000001000000020003000200000003000400030000000400050004000000050006000500000006000700060000000700080007000000080009000800000009000A00090000000A000B000A0000000B000C000B0000000C000D000C0000000D000E000D0000000E000F000E0000000F0010000F00000010001100100000001100120011000000120013001200000013001400130000001400150014000000150016001500000016001700160000001700180017000000180019001800000019001A00190000001A001B001A0000001B001C001B0000001C001D001C0000001D001E001D0000001E001F001E0000001F0020001F00000020002100200000002100220000100000000000004433221188776655CCBBAA99000102030405060708090A0B0C0D0E0F0102030405060708090A0B0C0D0E0F1002030405060708090A0B0C0D0E0F1011030405060708090A0B0C0D0E0F1011120405060708090A0B0C0D0E0F1011121305060708090A0B0C0D0E0F1011121314060708090A0B0C0D0E0F1011121314150708090A0B0C0D0E0F1011121314151608090A0B0C0D0E0F1011121314151617090A0B0C0D0E0F1011121314151617180A0B0C0D0E0F101112131415161718190B0C0D0E0F101112131415161718191A0C0D0E0F101112131415161718191A1B0D0E0F101112131415161718191A1B1C0E0F101112131415161718191A1B1C1D0F101112131415161718191A1B1C1D1E101112131415161718191A1B1C1D1E1F1112131415161718191A1B1C1D1E1F2012131415161718191A1B1C1D1E1F2021131415161718191A1B1C1D1E1F2021221415161718191A1B1C1D1E1F2021222315161718191A1B1C1D1E1F2021222324161718191A1B1C1D1E1F2021222324251718191A1B1C1D1E1F2021222324252618191A1B1C1D1E1F2021222324252627191A1B1C1D1E1F2021222324252627281A1B1C1D1E1F202122232425262728291B1C1D1E1F202122232425262728292A1C1D1E1F202122232425262728292A2B1D1E1F202122232425262728292A2B2C1E1F202122232425262728292A2B2C2D1F202122232425262728292A2B2C2D2E + Stack: + Start of Memory Range: 0x0000000000000000 + Content: '' +... diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/install_breakpad.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/install_breakpad.cpp new file mode 100644 index 00000000000..c34ac17128f --- /dev/null +++ b/gnu/llvm/lldb/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/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/libuuidmatch.yaml b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/libuuidmatch.yaml new file mode 100644 index 00000000000..3610694d4db --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/libuuidmatch.yaml @@ -0,0 +1,14 @@ +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_ARM + Flags: [ EF_ARM_SOFT_FLOAT, EF_ARM_EABI_VER5 ] +Sections: + - Name: .note.gnu.build-id + Type: SHT_NOTE + Flags: [ SHF_ALLOC ] + Address: 0x0000000000000114 + AddressAlign: 0x0000000000000004 + Content: 040000001400000003000000474E55007295E17C66689E05CBB5DEE5003865D55267C116 diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/libuuidmismatch.yaml b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/libuuidmismatch.yaml new file mode 100644 index 00000000000..5fef636228e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/libuuidmismatch.yaml @@ -0,0 +1,14 @@ +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_ARM + Flags: [ EF_ARM_SOFT_FLOAT, EF_ARM_EABI_VER5 ] +Sections: + - Name: .note.gnu.build-id + Type: SHT_NOTE + Flags: [ SHF_ALLOC ] + Address: 0x0000000000000114 + AddressAlign: 0x0000000000000004 + Content: 040000001400000003000000474E55008295E17C66689E05CBB5DEE5003865D55267C116 diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-partial-uuids-match.yaml b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-partial-uuids-match.yaml new file mode 100644 index 00000000000..edb0001ff27 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-partial-uuids-match.yaml @@ -0,0 +1,15 @@ +--- !minidump +Streams: + - Type: SystemInfo + Processor Arch: ARM + Platform ID: Linux + CSD Version: '15E216' + CPU: + CPUID: 0x00000000 + - Type: ModuleList + Modules: + - Base of Image: 0x0000000000001000 + Size of Image: 0x00001000 + Module Name: '/invalid/path/on/current/system/libuuidmatch.so' + CodeView Record: 525344537295E17C66689E05CBB5DEE5003865D50000000000 +... diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-partial-uuids-mismatch.yaml b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-partial-uuids-mismatch.yaml new file mode 100644 index 00000000000..0b56a967bf6 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-partial-uuids-mismatch.yaml @@ -0,0 +1,15 @@ +--- !minidump +Streams: + - Type: SystemInfo + Processor Arch: ARM + Platform ID: Linux + CSD Version: '15E216' + CPU: + CPUID: 0x00000000 + - Type: ModuleList + Modules: + - Base of Image: 0x0000000000001000 + Size of Image: 0x00001000 + Module Name: '/invalid/path/on/current/system/libuuidmismatch.so' + CodeView Record: 525344537295E17C66689E05CBB5DEE5003865D50000000000 +... diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-same-uuids.yaml b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-same-uuids.yaml new file mode 100644 index 00000000000..21c5220e415 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-same-uuids.yaml @@ -0,0 +1,21 @@ +--- !minidump +Streams: + - Type: SystemInfo + Processor Arch: AMD64 + Platform ID: Linux + CSD Version: '15E216' + CPU: + Vendor ID: GenuineIntel + Version Info: 0x00000000 + Feature Info: 0x00000000 + - Type: ModuleList + Modules: + - Base of Image: 0x0000000000001000 + Size of Image: 0x00001000 + Module Name: '/file/does/not/exist/a' + CodeView Record: '52534453112233441122334411223344112233441122334411' + - Base of Image: 0x0000000000003000 + Size of Image: 0x00001000 + Module Name: '/file/does/not/exist/b' + CodeView Record: '52534453112233441122334411223344112233441122334411' +... diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-16.yaml b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-16.yaml new file mode 100644 index 00000000000..f4c18b93334 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-16.yaml @@ -0,0 +1,19 @@ +--- !minidump +Streams: + - Type: SystemInfo + Processor Arch: ARM + Platform ID: Linux + CSD Version: '15E216' + CPU: + CPUID: 0x00000000 + - Type: ModuleList + Modules: + - Base of Image: 0x0000000000001000 + Size of Image: 0x00001000 + Module Name: '/tmp/a' + CodeView Record: 4C4570420102030405060708090A0B0C0D0E0F10 + - Base of Image: 0x0000000000001000 + Size of Image: 0x00001000 + Module Name: '/tmp/b' + CodeView Record: 4C4570420A141E28323C46505A646E78828C96A0 +... diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-20.yaml b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-20.yaml new file mode 100644 index 00000000000..e3c170fc335 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-20.yaml @@ -0,0 +1,19 @@ +--- !minidump +Streams: + - Type: SystemInfo + Processor Arch: ARM + Platform ID: Linux + CSD Version: '15E216' + CPU: + CPUID: 0x00000000 + - Type: ModuleList + Modules: + - Base of Image: 0x0000000000001000 + Size of Image: 0x00001000 + Module Name: '/tmp/a' + CodeView Record: 4C4570420102030405060708090A0B0C0D0E0F1011121314 + - Base of Image: 0x0000000000001000 + Size of Image: 0x00001000 + Module Name: '/tmp/b' + CodeView Record: 4C4570420A141E28323C46505A646E78828C96A0AAB4BEC8 +... diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-zero.yaml b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-zero.yaml new file mode 100644 index 00000000000..5bde77efaa7 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-elf-build-id-zero.yaml @@ -0,0 +1,19 @@ +--- !minidump +Streams: + - Type: SystemInfo + Processor Arch: ARM + Platform ID: Linux + CSD Version: '15E216' + CPU: + CPUID: 0x00000000 + - Type: ModuleList + Modules: + - Base of Image: 0x0000000000001000 + Size of Image: 0x00001000 + Module Name: '/not/exist/a' + CodeView Record: 4C45704200000000000000000000000000000000 + - Base of Image: 0x0000000000001000 + Size of Image: 0x00001000 + Module Name: '/not/exist/b' + CodeView Record: 4C45704200000000000000000000000000000000 +... diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-no-age.yaml b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-no-age.yaml new file mode 100644 index 00000000000..7b80fd51abd --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-no-age.yaml @@ -0,0 +1,19 @@ +--- !minidump +Streams: + - Type: SystemInfo + Processor Arch: ARM + Platform ID: Linux + CSD Version: '15E216' + CPU: + CPUID: 0x00000000 + - Type: ModuleList + Modules: + - Base of Image: 0x0000000000001000 + Size of Image: 0x00001000 + Module Name: '/tmp/a' + CodeView Record: 525344530102030405060708090A0B0C0D0E0F100000000000 + - Base of Image: 0x0000000000001000 + Size of Image: 0x00001000 + Module Name: '/tmp/b' + CodeView Record: 525344530A141E28323C46505A646E78828C96A00000000000 +... diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-with-age.yaml b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-with-age.yaml new file mode 100644 index 00000000000..083b313254e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-uuids-with-age.yaml @@ -0,0 +1,19 @@ +--- !minidump +Streams: + - Type: SystemInfo + Processor Arch: ARM + Platform ID: Linux + CSD Version: '15E216' + CPU: + CPUID: 0x00000000 + - Type: ModuleList + Modules: + - Base of Image: 0x0000000000001000 + Size of Image: 0x00001000 + Module Name: '/tmp/a' + CodeView Record: 525344530102030405060708090A0B0C0D0E0F101010101000 + - Base of Image: 0x0000000000001000 + Size of Image: 0x00001000 + Module Name: '/tmp/b' + CodeView Record: 525344530A141E28323C46505A646E78828C96A02020202000 +... diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-zero-uuids.yaml b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-zero-uuids.yaml new file mode 100644 index 00000000000..7ca887cdf2c --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-arm-zero-uuids.yaml @@ -0,0 +1,21 @@ +--- !minidump +Streams: + - Type: SystemInfo + Processor Arch: AMD64 + Platform ID: Linux + CSD Version: '15E216' + CPU: + Vendor ID: GenuineIntel + Version Info: 0x00000000 + Feature Info: 0x00000000 + - Type: ModuleList + Modules: + - Base of Image: 0x0000000000001000 + Size of Image: 0x00001000 + Module Name: '/file/does/not/exist/a' + CodeView Record: '52534453000000000000000000000000000000000000000000' + - Base of Image: 0x0000000000001000 + Size of Image: 0x00001000 + Module Name: '/file/does/not/exist/b' + CodeView Record: '52534453000000000000000000000000000000000000000000' +... diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64 b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64 Binary files differnew file mode 100755 index 00000000000..078d9c8fa90 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64 diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64.cpp new file mode 100644 index 00000000000..61d31492940 --- /dev/null +++ b/gnu/llvm/lldb/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/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64.dmp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64.dmp Binary files differnew file mode 100644 index 00000000000..e2ae724abe9 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64.dmp diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64.yaml b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64.yaml new file mode 100644 index 00000000000..21ea3ba5dea --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64.yaml @@ -0,0 +1,44 @@ +--- !minidump +Streams: + - Type: ThreadList + Threads: + - Thread Id: 0x000074DD + Context: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B0010000000000033000000000000000000000002020100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040109600000000000100000000000000000000000000000068E7D0C8FF7F000068E7D0C8FF7F000097E6D0C8FF7F000010109600000000000000000000000000020000000000000088E4D0C8FF7F0000603FFF85C77F0000F00340000000000080E7D0C8FF7F000000000000000000000000000000000000E0034000000000007F0300000000000000000000000000000000000000000000801F0000FFFF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF252525252525252525252525252525250000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + Stack: + Start of Memory Range: 0x00007FFFC8D0E000 + Content: DEADBEEFBAADF00D + - Type: ModuleList + Modules: + - Base of Image: 0x0000000000400000 + Size of Image: 0x00001000 + Module Name: '/tmp/test/linux-x86_64' + CodeView Record: 4C457042E35C283BC327C28762DB788BF5A4078BE2351448 + - Type: Exception + Thread ID: 0x000074DD + Exception Record: + Exception Code: 0x0000000B + Thread Context: 00000000 + - Type: SystemInfo + Processor Arch: AMD64 + Processor Level: 6 + Processor Revision: 15876 + Number of Processors: 40 + Platform ID: Linux + CSD Version: 'Linux 3.13.0-91-generic' + CPU: + Vendor ID: GenuineIntel + Version Info: 0x00000000 + Feature Info: 0x00000000 + - Type: LinuxProcStatus + Text: | + Name: linux-x86_64 + State: t (tracing stop) + Tgid: 29917 + Ngid: 0 + Pid: 29917 + PPid: 29370 + TracerPid: 29918 + Uid: 1001 1001 1001 1001 + Gid: 1001 1001 1001 1001 + +... diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64_not_crashed b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64_not_crashed Binary files differnew file mode 100755 index 00000000000..8b38cdb48bd --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64_not_crashed diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64_not_crashed.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64_not_crashed.cpp new file mode 100644 index 00000000000..070c565e72b --- /dev/null +++ b/gnu/llvm/lldb/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/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64_not_crashed.dmp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64_not_crashed.dmp Binary files differnew file mode 100644 index 00000000000..ad4b61a7bbb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64_not_crashed.dmp diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64_null_signal.yaml b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64_null_signal.yaml new file mode 100644 index 00000000000..93b3fd0e8aa --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/linux-x86_64_null_signal.yaml @@ -0,0 +1,25 @@ +--- !minidump +Streams: + - Type: ThreadList + Threads: + - Thread Id: 0x00002177 + Context: 0000 + Stack: + Start of Memory Range: 0x00007FFE2F689000 + Content: 00000000 + - Type: Exception + Thread ID: 0x00002177 + Exception Record: + Exception Code: 0x00000000 + Exception Address: 0x0000000000400582 + Thread Context: 0000 + - Type: SystemInfo + Processor Arch: AMD64 + Platform ID: Linux + - Type: LinuxProcStatus + Text: | + Name: busyloop + Umask: 0002 + State: t (tracing stop) + Pid: 8567 +... diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/macos-arm-uuids-no-age.yaml b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/macos-arm-uuids-no-age.yaml new file mode 100644 index 00000000000..57e291ee1b1 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/macos-arm-uuids-no-age.yaml @@ -0,0 +1,21 @@ +--- !minidump +Streams: + - Type: SystemInfo + Processor Arch: AMD64 + Platform ID: MacOSX + CSD Version: '15E216' + CPU: + Vendor ID: GenuineIntel + Version Info: 0x00000000 + Feature Info: 0x00000000 + - Type: ModuleList + Modules: + - Base of Image: 0x0000000000001000 + Size of Image: 0x00001000 + Module Name: '/tmp/a' + CodeView Record: 525344530102030405060708090A0B0C0D0E0F100000000000 + - Base of Image: 0x0000000000001000 + Size of Image: 0x00001000 + Module Name: '/tmp/b' + CodeView Record: 525344530A141E28323C46505A646E78828C96A00000000000 +... diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/makefile.txt b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/makefile.txt new file mode 100644 index 00000000000..79a95d61d85 --- /dev/null +++ b/gnu/llvm/lldb/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/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/regions-linux-map.yaml b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/regions-linux-map.yaml new file mode 100644 index 00000000000..3c0961eba07 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/regions-linux-map.yaml @@ -0,0 +1,33 @@ +--- !minidump +Streams: + - Type: SystemInfo + Processor Arch: ARM64 + Platform ID: Linux + CSD Version: '15E216' + CPU: + CPUID: 0x00000000 + - Type: MiscInfo + Content: 00000000010000007B000000000000000000000000000000 + - Type: LinuxMaps + Text: | + 400d9000-400db000 r-xp 00000000 b3:04 227 /system/bin/app_process + 400db000-400dc000 r--p 00001000 b3:04 227 /system/bin/app_process + 400dc000-400dd000 rw-p 00000000 00:00 0 + 400dd000-400ec000 r-xp 00000000 b3:04 300 /system/bin/linker + 400ec000-400ed000 r--p 00000000 00:00 0 + 400ed000-400ee000 r--p 0000f000 b3:04 300 /system/bin/linker + 400ee000-400ef000 rw-p 00010000 b3:04 300 /system/bin/linker + 400ef000-400fb000 rw-p 00000000 00:00 0 + 400fb000-400fc000 r-xp 00000000 b3:04 1096 /system/lib/liblog.so + 400fc000-400fd000 rwxp 00001000 b3:04 1096 /system/lib/liblog.so + 400fd000-400ff000 r-xp 00002000 b3:04 1096 /system/lib/liblog.so + 400ff000-40100000 r--p 00003000 b3:04 1096 /system/lib/liblog.so + 40100000-40101000 rw-p 00004000 b3:04 1096 /system/lib/liblog.so + 40101000-40122000 r-xp 00000000 b3:04 955 /system/lib/libc.so + 40122000-40123000 rwxp 00021000 b3:04 955 /system/lib/libc.so + 40123000-40167000 r-xp 00022000 b3:04 955 /system/lib/libc.so + 40167000-40169000 r--p 00065000 b3:04 955 /system/lib/libc.so + 40169000-4016b000 rw-p 00067000 b3:04 955 /system/lib/libc.so + 4016b000-40176000 rw-p 00000000 00:00 0 + +... diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/relative_module_name.yaml b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/relative_module_name.yaml new file mode 100644 index 00000000000..23f2b490280 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/relative_module_name.yaml @@ -0,0 +1,17 @@ +--- !minidump +Streams: + - Type: SystemInfo + Processor Arch: AMD64 + Platform ID: Linux + CSD Version: '15E216' + CPU: + Vendor ID: GenuineIntel + Version Info: 0x00000000 + Feature Info: 0x00000000 + - Type: ModuleList + Modules: + - Base of Image: 0x0000000000001000 + Size of Image: 0x00001000 + Module Name: 'file-with-a-name-unlikely-to-exist-in-the-current-directory.so' + CodeView Record: '' +... diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/Makefile new file mode 100644 index 00000000000..65e9dd2fa9e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/Makefile @@ -0,0 +1,4 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py new file mode 100644 index 00000000000..c3301fb323c --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py @@ -0,0 +1,176 @@ +""" +Test basics of mini dump debugging. +""" + +from six import iteritems + + +import lldb +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 + + 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 + self.dbg.CreateTarget("") + self.target = self.dbg.GetSelectedTarget() + self.process = self.target.LoadCore("fizzbuzz_no_heap.dmp") + self.assertTrue(self.process, PROCESS_IS_VALID) + self.assertEqual(self.process.GetNumThreads(), 1) + self.assertEqual(self.process.GetProcessID(), 4440) + + 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. + 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) + + def test_modules_in_mini_dump(self): + """Test that lldb can read the list of modules 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") + self.assertTrue(self.process, PROCESS_IS_VALID) + expected_modules = [ + { + 'filename' : r"C:\Users\amccarth\Documents\Visual Studio 2013\Projects\fizzbuzz\Debug/fizzbuzz.exe", + 'uuid' : '0F45B791-9A96-46F9-BF8F-2D6076EA421A-00000011', + }, + { + 'filename' : r"C:\Windows\SysWOW64/ntdll.dll", + 'uuid' : 'BBB0846A-402C-4052-A16B-67650BBFE6B0-00000002', + }, + { + 'filename' : r"C:\Windows\SysWOW64/kernel32.dll", + 'uuid' : 'E5CB7E1B-005E-4113-AB98-98D6913B52D8-00000002', + }, + { + 'filename' : r"C:\Windows\SysWOW64/KERNELBASE.dll", + 'uuid' : '0BF95241-CB0D-4BD4-AC5D-186A6452E522-00000001', + }, + { + 'filename' : r"C:\Windows\System32/MSVCP120D.dll", + 'uuid' : '3C05516E-57E7-40EB-8D3F-9722C5BD80DD-00000001', + }, + { + 'filename' : r"C:\Windows\System32/MSVCR120D.dll", + 'uuid' : '6382FB86-46C4-4046-AE42-8D97B3F91FF2-00000001', + }, + ] + self.assertEqual(self.target.GetNumModules(), len(expected_modules)) + for module, expected in zip(self.target.modules, expected_modules): + self.assertTrue(module.IsValid()) + self.assertEqual(module.file.fullpath, expected['filename']) + self.assertEqual(module.GetUUIDString(), expected['uuid']) + + def test_breakpad_uuid_matching(self): + """Test that the uuid computation algorithms in minidump and breakpad + files match.""" + self.target = self.dbg.CreateTarget("") + self.process = self.target.LoadCore("fizzbuzz_no_heap.dmp") + self.assertTrue(self.process, PROCESS_IS_VALID) + self.expect("target symbols add fizzbuzz.syms", substrs=["symbol file", + "fizzbuzz.syms", "has been added to", "fizzbuzz.exe"]), + self.assertTrue(self.target.modules[0].FindSymbol("main")) + + @skipIfLLVMTargetMissing("X86") + 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 + self.dbg.CreateTarget("") + self.target = self.dbg.GetSelectedTarget() + self.process = self.target.LoadCore("fizzbuzz_no_heap.dmp") + self.assertEqual(self.process.GetNumThreads(), 1) + thread = self.process.GetThreadAtIndex(0) + + pc_list = [ 0x00164d14, 0x00167c79, 0x00167e6d, 0x7510336a, 0x77759882, 0x77759855] + + self.assertEqual(thread.GetNumFrames(), len(pc_list)) + for i in range(len(pc_list)): + frame = thread.GetFrameAtIndex(i) + self.assertTrue(frame.IsValid()) + self.assertEqual(frame.GetPC(), pc_list[i]) + self.assertTrue(frame.GetModule().IsValid()) + + @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() + exe = self.getBuildArtifact("a.out") + core = self.getBuildArtifact("core.dmp") + try: + # 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()) + self.assertEqual(process.GetState(), lldb.eStateStopped) + self.assertTrue(process.SaveCore(core)) + self.assertTrue(os.path.isfile(core)) + self.assertTrue(process.Kill().Success()) + + # Launch with the mini dump, and inspect the stack. + target = self.dbg.CreateTarget(None) + process = target.LoadCore(core) + thread = process.GetThreadAtIndex(0) + + 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) + self.assertTrue(frame.IsValid()) + function_name = frame.GetFunctionName() + self.assertTrue(name in function_name) + + finally: + # Clean up the mini dump file. + self.assertTrue(self.dbg.DeleteTarget(target)) + if (os.path.isfile(core)): + os.unlink(core) + + @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() + exe = self.getBuildArtifact("a.out") + core = self.getBuildArtifact("core.dmp") + try: + # 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()) + self.assertEqual(process.GetState(), lldb.eStateStopped) + self.assertTrue(process.SaveCore(core)) + self.assertTrue(os.path.isfile(core)) + self.assertTrue(process.Kill().Success()) + + # Launch with the mini dump, and inspect a local variable. + target = self.dbg.CreateTarget(None) + process = target.LoadCore(core) + thread = process.GetThreadAtIndex(0) + frame = thread.GetFrameAtIndex(0) + value = frame.EvaluateExpression('x') + self.assertEqual(value.GetValueAsSigned(), 3) + + finally: + # Clean up the mini dump file. + self.assertTrue(self.dbg.DeleteTarget(target)) + if (os.path.isfile(core)): + os.unlink(core) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/fizzbuzz.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/fizzbuzz.cpp new file mode 100644 index 00000000000..295d4a1f24d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/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/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/fizzbuzz.syms b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/fizzbuzz.syms new file mode 100644 index 00000000000..cab06c1c9d5 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/fizzbuzz.syms @@ -0,0 +1,2 @@ +MODULE windows x86 0F45B7919A9646F9BF8F2D6076EA421A11 fizzbuzz.pdb
+PUBLIC 1000 0 main
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/fizzbuzz_no_heap.dmp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/fizzbuzz_no_heap.dmp Binary files differnew file mode 100644 index 00000000000..19008c91fc3 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/fizzbuzz_no_heap.dmp diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/main.cpp new file mode 100644 index 00000000000..4037ea522ca --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/main.cpp @@ -0,0 +1,21 @@ +int global = 42; + +int +bar(int x) +{ + int y = 4*x + global; + return y; +} + +int +foo(int x) +{ + int y = 2*bar(3*x); + return y; +} + +int +main() +{ + return 0 * foo(1); +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.aarch64 b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.aarch64 Binary files differnew file mode 100755 index 00000000000..de0208c756d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.aarch64 diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.amd64 b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.amd64 Binary files differnew file mode 100755 index 00000000000..56fa077bd6a --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.amd64 diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.c new file mode 100644 index 00000000000..972e9678af5 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/1lwp_SIGSEGV.c @@ -0,0 +1,14 @@ +static void bar(char *boom) { + char F = 'b'; + *boom = 47; // Frame bar +} + +static void foo(char *boom, void (*boomer)(char *)) { + char F = 'f'; + boomer(boom); // Frame foo +} + +void main(void) { + char F = 'm'; + foo(0, bar); // Frame main +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.aarch64 b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.aarch64 Binary files differnew file mode 100755 index 00000000000..8781f033c5a --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.aarch64 diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.amd64 b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.amd64 Binary files differnew file mode 100755 index 00000000000..32a49852215 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.amd64 diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.c new file mode 100644 index 00000000000..fcbfa8a6b51 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.c @@ -0,0 +1,37 @@ +#include <lwp.h> +#include <stddef.h> +#include <stdlib.h> +#include <unistd.h> +#include <signal.h> + +volatile int sem = 0; + +static void bar() { + char F = 'b'; + sem = 1; + while (1) continue; // Frame bar +} + +static void foo(void (*boomer)()) { + char F = 'f'; + boomer(); // Frame foo +} + +static void lwp_main(void *unused) { + char F = 'l'; + foo(bar); // Frame lwp_main +} + +int main(int argc, char **argv) { + ucontext_t uc; + lwpid_t lid; + static const size_t ssize = 16 * 1024; + void *stack; + + stack = malloc(ssize); + _lwp_makecontext(&uc, lwp_main, NULL, NULL, stack, ssize); + _lwp_create(&uc, 0, &lid); + while (sem != 1) continue; + kill(getpid(), SIGSEGV); + _lwp_wait(lid, NULL); +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.aarch64 b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.aarch64 Binary files differnew file mode 100755 index 00000000000..89394a7c084 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.aarch64 diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.amd64 b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.amd64 Binary files differnew file mode 100755 index 00000000000..d304de160f0 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.amd64 diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.c new file mode 100644 index 00000000000..1cd86631edd --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.c @@ -0,0 +1,30 @@ +#include <lwp.h> +#include <stddef.h> +#include <stdlib.h> + +static void bar(char *boom) { + char F = 'b'; + *boom = 47; // Frame bar +} + +static void foo(char *boom, void (*boomer)(char *)) { + char F = 'f'; + boomer(boom); // Frame foo +} + +void lwp_main(void *unused) { + char F = 'l'; + foo(0, bar); // Frame lwp_main +} + +int main(int argc, char **argv) { + ucontext_t uc; + lwpid_t lid; + static const size_t ssize = 16 * 1024; + void *stack; + + stack = malloc(ssize); + _lwp_makecontext(&uc, lwp_main, NULL, NULL, stack, ssize); + _lwp_create(&uc, 0, &lid); + _lwp_wait(lid, NULL); +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/GNUmakefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/GNUmakefile new file mode 100644 index 00000000000..62c719d3d2f --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/GNUmakefile @@ -0,0 +1,15 @@ +ARCH = $(shell uname -m) +PROGRAMS = 1lwp_SIGSEGV 2lwp_t2_SIGSEGV 2lwp_process_SIGSEGV +EXECS = $(patsubst %,%.$(ARCH),$(PROGRAMS)) +CORES = $(patsubst %,%.core,$(EXECS)) + +all: $(CORES) $(EXECS) +clean: + rm -f $(CORES) $(EXECS) + +%.core: % + sysctl -w proc.$$$$.corename=$@; ulimit -s 16; ! ./$< +%.$(ARCH): %.c + $(CC) -o $@ -g $< + +.PHONY: all clean diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/TestNetBSDCore.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/TestNetBSDCore.py new file mode 100644 index 00000000000..067b04d997d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/netbsd-core/TestNetBSDCore.py @@ -0,0 +1,237 @@ +""" +Test NetBSD core file debugging. +""" + +from __future__ import division, print_function + +import signal +import os + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class NetBSDCoreCommonTestCase(TestBase): + NO_DEBUG_INFO_TESTCASE = True + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + super(NetBSDCoreCommonTestCase, self).setUp() + self._initial_platform = lldb.DBG.GetSelectedPlatform() + + def tearDown(self): + lldb.DBG.SetSelectedPlatform(self._initial_platform) + super(NetBSDCoreCommonTestCase, self).tearDown() + + def check_memory_regions(self, process, region_count): + region_list = process.GetMemoryRegions() + self.assertEqual(region_list.GetSize(), region_count) + + region = lldb.SBMemoryRegionInfo() + + # Check we have the right number of regions. + self.assertEqual(region_list.GetSize(), region_count) + + # Check that getting a region beyond the last in the list fails. + self.assertFalse( + region_list.GetMemoryRegionAtIndex( + region_count, region)) + + # Check each region is valid. + for i in range(region_list.GetSize()): + # Check we can actually get this region. + self.assertTrue(region_list.GetMemoryRegionAtIndex(i, region)) + + # Every region in the list should be mapped. + self.assertTrue(region.IsMapped()) + + # Test the address at the start of a region returns it's enclosing + # region. + begin_address = region.GetRegionBase() + region_at_begin = lldb.SBMemoryRegionInfo() + error = process.GetMemoryRegionInfo(begin_address, region_at_begin) + self.assertEqual(region, region_at_begin) + + # Test an address in the middle of a region returns it's enclosing + # region. + middle_address = (region.GetRegionBase() + + region.GetRegionEnd()) // 2 + region_at_middle = lldb.SBMemoryRegionInfo() + error = process.GetMemoryRegionInfo( + middle_address, region_at_middle) + self.assertEqual(region, region_at_middle) + + # Test the address at the end of a region returns it's enclosing + # region. + end_address = region.GetRegionEnd() - 1 + region_at_end = lldb.SBMemoryRegionInfo() + error = process.GetMemoryRegionInfo(end_address, region_at_end) + self.assertEqual(region, region_at_end) + + # Check that quering the end address does not return this region but + # the next one. + next_region = lldb.SBMemoryRegionInfo() + error = process.GetMemoryRegionInfo( + region.GetRegionEnd(), next_region) + self.assertNotEqual(region, next_region) + self.assertEqual( + region.GetRegionEnd(), + next_region.GetRegionBase()) + + # Check that query beyond the last region returns an unmapped region + # that ends at LLDB_INVALID_ADDRESS + last_region = lldb.SBMemoryRegionInfo() + region_list.GetMemoryRegionAtIndex(region_count - 1, last_region) + end_region = lldb.SBMemoryRegionInfo() + error = process.GetMemoryRegionInfo( + last_region.GetRegionEnd(), end_region) + self.assertFalse(end_region.IsMapped()) + self.assertEqual( + last_region.GetRegionEnd(), + end_region.GetRegionBase()) + self.assertEqual(end_region.GetRegionEnd(), lldb.LLDB_INVALID_ADDRESS) + + def check_state(self, process): + with open(os.devnull) as devnul: + # sanitize test output + self.dbg.SetOutputFileHandle(devnul, False) + self.dbg.SetErrorFileHandle(devnul, False) + + self.assertTrue(process.is_stopped) + + # Process.Continue + error = process.Continue() + self.assertFalse(error.Success()) + self.assertTrue(process.is_stopped) + + # Thread.StepOut + thread = process.GetSelectedThread() + thread.StepOut() + self.assertTrue(process.is_stopped) + + # command line + self.dbg.HandleCommand('s') + self.assertTrue(process.is_stopped) + self.dbg.HandleCommand('c') + self.assertTrue(process.is_stopped) + + # restore file handles + self.dbg.SetOutputFileHandle(None, False) + self.dbg.SetErrorFileHandle(None, False) + + def check_backtrace(self, thread, filename, backtrace): + self.assertGreaterEqual(thread.GetNumFrames(), len(backtrace)) + src = filename.rpartition('.')[0] + '.c' + for i in range(len(backtrace)): + frame = thread.GetFrameAtIndex(i) + self.assertTrue(frame) + if not backtrace[i].startswith('_'): + self.assertEqual(frame.GetFunctionName(), backtrace[i]) + self.assertEqual(frame.GetLineEntry().GetLine(), + line_number(src, "Frame " + backtrace[i])) + self.assertEqual( + frame.FindVariable("F").GetValueAsUnsigned(), ord( + backtrace[i][0])) + + def do_test(self, filename, pid, region_count): + target = self.dbg.CreateTarget(filename) + process = target.LoadCore(filename + ".core") + + self.assertTrue(process, PROCESS_IS_VALID) + self.assertEqual(process.GetNumThreads(), self.THREAD_COUNT) + self.assertEqual(process.GetProcessID(), pid) + + self.check_state(process) + + self.check_stack(process, pid, filename) + + self.check_memory_regions(process, region_count) + + self.dbg.DeleteTarget(target) + + +class NetBSD1LWPCoreTestCase(NetBSDCoreCommonTestCase): + THREAD_COUNT = 1 + + def check_stack(self, process, pid, filename): + thread = process.GetSelectedThread() + self.assertTrue(thread) + self.assertEqual(thread.GetThreadID(), 1) + self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal) + self.assertEqual(thread.GetStopReasonDataCount(), 1) + self.assertEqual(thread.GetStopReasonDataAtIndex(0), signal.SIGSEGV) + backtrace = ["bar", "foo", "main"] + self.check_backtrace(thread, filename, backtrace) + + @skipIfLLVMTargetMissing("AArch64") + def test_aarch64(self): + """Test single-threaded aarch64 core dump.""" + self.do_test("1lwp_SIGSEGV.aarch64", pid=8339, region_count=32) + + @skipIfLLVMTargetMissing("X86") + def test_amd64(self): + """Test single-threaded amd64 core dump.""" + self.do_test("1lwp_SIGSEGV.amd64", pid=693, region_count=21) + + +class NetBSD2LWPT2CoreTestCase(NetBSDCoreCommonTestCase): + THREAD_COUNT = 2 + + def check_stack(self, process, pid, filename): + thread = process.GetSelectedThread() + self.assertTrue(thread) + self.assertEqual(thread.GetThreadID(), 2) + self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal) + self.assertEqual(thread.GetStopReasonDataCount(), 1) + self.assertEqual(thread.GetStopReasonDataAtIndex(0), signal.SIGSEGV) + backtrace = ["bar", "foo", "lwp_main"] + self.check_backtrace(thread, filename, backtrace) + + # thread 1 should have no signal + thread = process.GetThreadByID(1) + self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal) + self.assertEqual(thread.GetStopReasonDataCount(), 1) + self.assertEqual(thread.GetStopReasonDataAtIndex(0), 0) + + @skipIfLLVMTargetMissing("AArch64") + def test_aarch64(self): + """Test double-threaded aarch64 core dump where thread 2 is signalled.""" + self.do_test("2lwp_t2_SIGSEGV.aarch64", pid=14142, region_count=31) + + @skipIfLLVMTargetMissing("X86") + def test_amd64(self): + """Test double-threaded amd64 core dump where thread 2 is signalled.""" + self.do_test("2lwp_t2_SIGSEGV.amd64", pid=622, region_count=24) + + +class NetBSD2LWPProcessSigCoreTestCase(NetBSDCoreCommonTestCase): + THREAD_COUNT = 2 + + def check_stack(self, process, pid, filename): + thread = process.GetSelectedThread() + self.assertTrue(thread) + self.assertEqual(thread.GetThreadID(), 2) + self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal) + self.assertEqual(thread.GetStopReasonDataCount(), 1) + self.assertEqual(thread.GetStopReasonDataAtIndex(0), signal.SIGSEGV) + backtrace = ["bar", "foo", "lwp_main"] + self.check_backtrace(thread, filename, backtrace) + + # thread 1 should have the same signal + thread = process.GetThreadByID(1) + self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal) + self.assertEqual(thread.GetStopReasonDataCount(), 1) + self.assertEqual(thread.GetStopReasonDataAtIndex(0), signal.SIGSEGV) + + @skipIfLLVMTargetMissing("AArch64") + def test_aarch64(self): + """Test double-threaded aarch64 core dump where process is signalled.""" + self.do_test("2lwp_process_SIGSEGV.aarch64", pid=1403, region_count=30) + + @skipIfLLVMTargetMissing("X86") + def test_amd64(self): + """Test double-threaded amd64 core dump where process is signalled.""" + self.do_test("2lwp_process_SIGSEGV.amd64", pid=665, region_count=24) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/TestWow64MiniDump.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/TestWow64MiniDump.py new file mode 100644 index 00000000000..cbfc8525ea2 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/TestWow64MiniDump.py @@ -0,0 +1,72 @@ +""" +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 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__) + NO_DEBUG_INFO_TESTCASE = True + + 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) + + 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) + + 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/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/fizzbuzz.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/fizzbuzz.cpp new file mode 100644 index 00000000000..295d4a1f24d --- /dev/null +++ b/gnu/llvm/lldb/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/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/fizzbuzz_wow64.dmp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/fizzbuzz_wow64.dmp Binary files differnew file mode 100644 index 00000000000..3d97186f2cd --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/fizzbuzz_wow64.dmp diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/pre_run_dylibs/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/pre_run_dylibs/Makefile new file mode 100644 index 00000000000..032f9cda29c --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/pre_run_dylibs/Makefile @@ -0,0 +1,4 @@ +DYLIB_NAME := unlikely_name +DYLIB_CXX_SOURCES := foo.cpp +CXX_SOURCES := main.cpp +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/pre_run_dylibs/TestPreRunDylibs.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/pre_run_dylibs/TestPreRunDylibs.py new file mode 100644 index 00000000000..1ac18a771f1 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/pre_run_dylibs/TestPreRunDylibs.py @@ -0,0 +1,33 @@ + +import unittest2 +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * + +class TestPreRunLibraries(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + @skipIf(oslist=no_match(['darwin','macos'])) + def test(self): + """Test that we find directly linked dylib pre-run.""" + + self.build() + target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) + self.assertTrue(target, VALID_TARGET) + + # I don't know what the name of a shared library + # extension is in general, so instead of using FindModule, + # I'll iterate through the module and do a basename match. + found_it = False + for module in target.modules: + file_name = module.GetFileSpec().GetFilename() + if file_name.find("unlikely_name") != -1: + found_it = True + break + + self.assertTrue(found_it, "Couldn't find unlikely_to_occur_name in loaded libraries.") + + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/pre_run_dylibs/foo.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/pre_run_dylibs/foo.cpp new file mode 100644 index 00000000000..8dad0a23f36 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/pre_run_dylibs/foo.cpp @@ -0,0 +1,3 @@ +#include "foo.h" + +int call_foo1() { return foo1(); } diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/pre_run_dylibs/foo.h b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/pre_run_dylibs/foo.h new file mode 100644 index 00000000000..060b91f5a5e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/pre_run_dylibs/foo.h @@ -0,0 +1,6 @@ +LLDB_TEST_API inline int foo1() { return 1; } // !BR1 + +LLDB_TEST_API inline int foo2() { return 2; } // !BR2 + +LLDB_TEST_API extern int call_foo1(); +LLDB_TEST_API extern int call_foo2(); diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/pre_run_dylibs/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/pre_run_dylibs/main.cpp new file mode 100644 index 00000000000..c9295a5c7d3 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/pre_run_dylibs/main.cpp @@ -0,0 +1,9 @@ +#include "foo.h" + +int call_foo2() { return foo2(); } + +int +main() // !BR_main +{ + return call_foo1() + call_foo2(); +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/process_group/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/process_group/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/process_group/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/process_group/TestChangeProcessGroup.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/process_group/TestChangeProcessGroup.py new file mode 100644 index 00000000000..fe541c7832c --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/process_group/TestChangeProcessGroup.py @@ -0,0 +1,90 @@ +"""Test that we handle inferiors which change their process group""" + + + +import os +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ChangeProcessGroupTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break for main.c. + self.line = line_number('main.c', '// Set breakpoint here') + + @skipIfFreeBSD # Times out on FreeBSD llvm.org/pr23731 + @skipIfWindows # setpgid call does not exist on Windows + @expectedFailureAndroid("http://llvm.org/pr23762", api_levels=[16]) + @expectedFailureNetBSD + def test_setpgid(self): + self.build() + exe = self.getBuildArtifact("a.out") + + # Use a file as a synchronization point between test and inferior. + pid_file_path = lldbutil.append_to_process_working_directory(self, + "pid_file_%d" % (int(time.time()))) + self.addTearDownHook( + lambda: self.run_platform_command( + "rm %s" % + (pid_file_path))) + + popen = self.spawnSubprocess(exe, [pid_file_path]) + self.addTearDownHook(self.cleanupSubprocesses) + + pid = lldbutil.wait_for_file_on_target(self, pid_file_path) + + # make sure we cleanup the forked child also + def cleanupChild(): + if lldb.remote_platform: + lldb.remote_platform.Kill(int(pid)) + else: + if os.path.exists("/proc/" + pid): + os.kill(int(pid), signal.SIGKILL) + self.addTearDownHook(cleanupChild) + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + listener = lldb.SBListener("my.attach.listener") + error = lldb.SBError() + process = target.AttachToProcessWithID(listener, int(pid), error) + self.assertTrue(error.Success() and process, PROCESS_IS_VALID) + + # set a breakpoint just before the setpgid() call + lldbutil.run_break_set_by_file_and_line( + self, 'main.c', self.line, num_expected_locations=-1) + + thread = process.GetSelectedThread() + + # release the child from its loop + value = thread.GetSelectedFrame().EvaluateExpression("release_child_flag = 1") + self.assertTrue(value.IsValid() and value.GetValueAsUnsigned(0) == 1) + process.Continue() + + # make sure the child's process group id is different from its pid + value = thread.GetSelectedFrame().EvaluateExpression("(int)getpgid(0)") + self.assertTrue(value.IsValid()) + self.assertNotEqual(value.GetValueAsUnsigned(0), int(pid)) + + # step over the setpgid() call + thread.StepOver() + self.assertEqual(thread.GetStopReason(), lldb.eStopReasonPlanComplete) + + # verify that the process group has been set correctly + # this also checks that we are still in full control of the child + value = thread.GetSelectedFrame().EvaluateExpression("(int)getpgid(0)") + self.assertTrue(value.IsValid()) + self.assertEqual(value.GetValueAsUnsigned(0), int(pid)) + + # run to completion + process.Continue() + self.assertEqual(process.GetState(), lldb.eStateExited) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/process_group/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/process_group/main.c new file mode 100644 index 00000000000..7e986bbac65 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/process_group/main.c @@ -0,0 +1,71 @@ +#include <stdio.h> +#include <unistd.h> +#include <sys/wait.h> + +volatile int release_child_flag = 0; + +int main(int argc, char const *argv[]) +{ + pid_t child = fork(); + if (child == -1) + { + perror("fork"); + return 1; + } + + if (child > 0) + { // parent + if (argc < 2) + { + fprintf(stderr, "Need pid filename.\n"); + return 2; + } + + // Let the test suite know the child's pid. + FILE *pid_file = fopen(argv[1], "w"); + if (pid_file == NULL) + { + perror("fopen"); + return 3; + } + + fprintf(pid_file, "%d\n", child); + if (fclose(pid_file) == EOF) + { + perror("fclose"); + return 4; + } + + // And wait for the child to finish it's work. + int status = 0; + pid_t wpid = wait(&status); + if (wpid == -1) + { + perror("wait"); + return 5; + } + if (wpid != child) + { + fprintf(stderr, "wait() waited for wrong child\n"); + return 6; + } + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) + { + fprintf(stderr, "child did not exit correctly\n"); + return 7; + } + } + else + { // child + lldb_enable_attach(); + + while (! release_child_flag) // Wait for debugger to attach + sleep(1); + + printf("Child's previous process group is: %d\n", getpgid(0)); + setpgid(0, 0); // Set breakpoint here + printf("Child's process group set to: %d\n", getpgid(0)); + } + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/process_save_core/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/process_save_core/Makefile new file mode 100644 index 00000000000..65e9dd2fa9e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/process_save_core/Makefile @@ -0,0 +1,4 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/process_save_core/TestProcessSaveCore.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/process_save_core/TestProcessSaveCore.py new file mode 100644 index 00000000000..d561af02d30 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/process_save_core/TestProcessSaveCore.py @@ -0,0 +1,65 @@ +""" +Test saving a core file (or mini dump). +""" + + +import os +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ProcessSaveCoreTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @not_remote_testsuite_ready + @skipUnlessWindows + def test_cannot_save_core_unless_process_stopped(self): + """Test that SaveCore fails if the process isn't stopped.""" + self.build() + exe = self.getBuildArtifact("a.out") + core = self.getBuildArtifact("core.dmp") + target = self.dbg.CreateTarget(exe) + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertNotEqual(process.GetState(), lldb.eStateStopped) + error = process.SaveCore(core) + self.assertTrue(error.Fail()) + + @not_remote_testsuite_ready + @skipUnlessWindows + def test_save_windows_mini_dump(self): + """Test that we can save a Windows mini dump.""" + self.build() + exe = self.getBuildArtifact("a.out") + core = self.getBuildArtifact("core.dmp") + try: + target = self.dbg.CreateTarget(exe) + breakpoint = target.BreakpointCreateByName("bar") + 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)) + self.assertTrue(process.Kill().Success()) + + # To verify, we'll launch with the mini dump, and ensure that we see + # the executable in the module list. + target = self.dbg.CreateTarget(None) + process = target.LoadCore(core) + files = [ + target.GetModuleAtIndex(i).GetFileSpec() for i in range( + 0, target.GetNumModules())] + paths = [ + os.path.join( + f.GetDirectory(), + f.GetFilename()) for f in files] + self.assertTrue(exe in paths) + + finally: + # Clean up the mini dump file. + self.assertTrue(self.dbg.DeleteTarget(target)) + if (os.path.isfile(core)): + os.unlink(core) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/process_save_core/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/process_save_core/main.cpp new file mode 100644 index 00000000000..4037ea522ca --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/process_save_core/main.cpp @@ -0,0 +1,21 @@ +int global = 42; + +int +bar(int x) +{ + int y = 4*x + global; + return y; +} + +int +foo(int x) +{ + int y = 2*bar(3*x); + return y; +} + +int +main() +{ + return 0 * foo(1); +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/ptr_refs/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/ptr_refs/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/ptr_refs/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/ptr_refs/TestPtrRefs.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/ptr_refs/TestPtrRefs.py new file mode 100644 index 00000000000..8ca26398fca --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/ptr_refs/TestPtrRefs.py @@ -0,0 +1,46 @@ +""" +Test the ptr_refs tool on Darwin +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestPtrRefs(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipUnlessDarwin + def test_ptr_refs(self): + """Test format string functionality.""" + self.build() + exe = self.getBuildArtifact("a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + main_file_spec = lldb.SBFileSpec('main.c') + breakpoint = target.BreakpointCreateBySourceRegex( + 'break', main_file_spec) + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + # Frame #0 should be on self.line1 and the break condition should hold. + thread = lldbutil.get_stopped_thread( + process, lldb.eStopReasonBreakpoint) + self.assertTrue( + thread.IsValid(), + "There should be a thread stopped due to breakpoint condition") + + frame = thread.GetFrameAtIndex(0) + + self.dbg.HandleCommand("script import lldb.macosx.heap") + self.expect("ptr_refs my_ptr", substrs=["malloc", "stack"]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/ptr_refs/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/ptr_refs/main.c new file mode 100644 index 00000000000..f46862efd8b --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/ptr_refs/main.c @@ -0,0 +1,26 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +struct referent { + const char *p; +}; + +int main (int argc, char const *argv[]) +{ + const char *my_ptr = strdup("hello"); + struct referent *r = malloc(sizeof(struct referent)); + r->p = my_ptr; + + printf("%p\n", r); // break here + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/recursion/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/recursion/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/recursion/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/recursion/TestValueObjectRecursion.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/recursion/TestValueObjectRecursion.py new file mode 100644 index 00000000000..e949f1a1a07 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/recursion/TestValueObjectRecursion.py @@ -0,0 +1,67 @@ +""" +Test lldb data formatter subsystem. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class ValueObjectRecursionTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + def test_with_run_command(self): + """Test that deeply nested ValueObjects still work.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + root = self.frame().FindVariable("root") + child = root.GetChildAtIndex(1) + if self.TraceOn(): + print(root) + print(child) + for i in range(0, 15000): + child = child.GetChildAtIndex(1) + if self.TraceOn(): + print(child) + self.assertTrue( + child.IsValid(), + "could not retrieve the deep ValueObject") + self.assertTrue( + child.GetChildAtIndex(0).IsValid(), + "the deep ValueObject has no value") + self.assertTrue( + child.GetChildAtIndex(0).GetValueAsUnsigned() != 0, + "the deep ValueObject has a zero value") + self.assertTrue( + child.GetChildAtIndex(1).GetValueAsUnsigned() != 0, + "the deep ValueObject has no next") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/recursion/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/recursion/main.cpp new file mode 100644 index 00000000000..bd5278ace7d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/recursion/main.cpp @@ -0,0 +1,40 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> + +struct node; +struct node { + int value; + node* next; + node () : value(1),next(NULL) {} + node (int v) : value(v), next(NULL) {} +}; + +void make_tree(node* root, int count) +{ + int countdown=1; + if (!root) + return; + root->value = countdown; + while (count > 0) + { + root->next = new node(++countdown); + root = root->next; + count--; + } +} + +int main (int argc, const char * argv[]) +{ + node root(1); + make_tree(&root,25000); + return 0; // Set break point at this line. +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/rerun/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/rerun/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/rerun/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/rerun/TestRerun.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/rerun/TestRerun.py new file mode 100644 index 00000000000..d2e5701f28e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/rerun/TestRerun.py @@ -0,0 +1,60 @@ +""" +Test that argdumper is a viable launching strategy. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestRerun(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test(self): + self.build() + exe = self.getBuildArtifact("a.out") + + self.runCmd("target create %s" % exe) + + # Create the target + target = self.dbg.CreateTarget(exe) + + # Create any breakpoints we need + breakpoint = target.BreakpointCreateBySourceRegex( + 'break here', lldb.SBFileSpec("main.cpp", False)) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + self.runCmd("process launch 1 2 3") + + process = self.process() + thread = lldbutil.get_one_thread_stopped_at_breakpoint( + process, breakpoint) + self.assertIsNotNone( + thread, "Process should be stopped at a breakpoint in main") + self.assertTrue(thread.IsValid(), "Stopped thread is not valid") + + self.expect("frame variable argv[1]", substrs=['1']) + self.expect("frame variable argv[2]", substrs=['2']) + self.expect("frame variable argv[3]", substrs=['3']) + + # Let program exit + self.runCmd("continue") + + # Re-run with no args and make sure we still run with 1 2 3 as arguments as + # they should have been stored in "target.run-args" + self.runCmd("process launch") + + process = self.process() + thread = lldbutil.get_one_thread_stopped_at_breakpoint( + process, breakpoint) + + self.assertIsNotNone( + thread, "Process should be stopped at a breakpoint in main") + self.assertTrue(thread.IsValid(), "Stopped thread is not valid") + + self.expect("frame variable argv[1]", substrs=['1']) + self.expect("frame variable argv[2]", substrs=['2']) + self.expect("frame variable argv[3]", substrs=['3']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/rerun/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/rerun/main.cpp new file mode 100644 index 00000000000..cbef8d1e6da --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/rerun/main.cpp @@ -0,0 +1,5 @@ +int +main (int argc, char const **argv) +{ + return 0; // break here +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/return-value/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/return-value/Makefile new file mode 100644 index 00000000000..138642ce206 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/return-value/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := call-func.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/return-value/TestReturnValue.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/return-value/TestReturnValue.py new file mode 100644 index 00000000000..a5439b11a18 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/return-value/TestReturnValue.py @@ -0,0 +1,279 @@ +""" +Test getting return-values correctly when stepping out +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ReturnValueTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def affected_by_pr33042(self): + return ("clang" in self.getCompiler() and self.getArchitecture() == + "aarch64" and self.getPlatform() == "linux") + + def affected_by_pr44132(self): + return (self.getArchitecture() == "aarch64" and self.getPlatform() == "linux") + + # ABIMacOSX_arm can't fetch simple values inside a structure + def affected_by_radar_34562999(self): + return (self.getArchitecture() == 'armv7' or self.getArchitecture() == 'armv7k') and self.platformIsDarwin() + + @expectedFailureAll(oslist=["freebsd"], archs=["i386"]) + @expectedFailureAll(oslist=["macosx"], archs=["i386"], bugnumber="<rdar://problem/28719652>") + @expectedFailureAll( + oslist=["linux"], + compiler="clang", + compiler_version=[ + "<=", + "3.6"], + archs=["i386"]) + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") + @add_test_categories(['pyapi']) + def test_with_python(self): + """Test getting return values from stepping out.""" + self.build() + exe = self.getBuildArtifact("a.out") + (self.target, self.process, thread, inner_sint_bkpt) = lldbutil.run_to_name_breakpoint(self, "inner_sint", exe_name = exe) + + error = lldb.SBError() + + # inner_sint returns the variable value, so capture that here: + in_int = thread.GetFrameAtIndex(0).FindVariable( + "value").GetValueAsSigned(error) + self.assertTrue(error.Success()) + + thread.StepOut() + + self.assertTrue(self.process.GetState() == lldb.eStateStopped) + self.assertTrue(thread.GetStopReason() == lldb.eStopReasonPlanComplete) + + frame = thread.GetFrameAtIndex(0) + fun_name = frame.GetFunctionName() + self.assertTrue(fun_name == "outer_sint(int)") + + return_value = thread.GetStopReturnValue() + self.assertTrue(return_value.IsValid()) + + ret_int = return_value.GetValueAsSigned(error) + self.assertTrue(error.Success()) + self.assertTrue(in_int == ret_int) + + # Run again and we will stop in inner_sint the second time outer_sint is called. + # Then test stepping out two frames at once: + + thread_list = lldbutil.continue_to_breakpoint(self.process, inner_sint_bkpt) + self.assertTrue(len(thread_list) == 1) + thread = thread_list[0] + + # We are done with the inner_sint breakpoint: + self.target.BreakpointDelete(inner_sint_bkpt.GetID()) + + frame = thread.GetFrameAtIndex(1) + fun_name = frame.GetFunctionName() + self.assertTrue(fun_name == "outer_sint(int)") + in_int = frame.FindVariable("value").GetValueAsSigned(error) + self.assertTrue(error.Success()) + + thread.StepOutOfFrame(frame) + + self.assertTrue(self.process.GetState() == lldb.eStateStopped) + self.assertTrue(thread.GetStopReason() == lldb.eStopReasonPlanComplete) + frame = thread.GetFrameAtIndex(0) + fun_name = frame.GetFunctionName() + self.assertTrue(fun_name == "main") + + ret_value = thread.GetStopReturnValue() + self.assertTrue(return_value.IsValid()) + ret_int = ret_value.GetValueAsSigned(error) + self.assertTrue(error.Success()) + self.assertTrue(2 * in_int == ret_int) + + # Now try some simple returns that have different types: + inner_float_bkpt = self.target.BreakpointCreateByName( + "inner_float(float)", exe) + self.assertTrue(inner_float_bkpt, VALID_BREAKPOINT) + self.process.Continue() + thread_list = lldbutil.get_threads_stopped_at_breakpoint( + self.process, inner_float_bkpt) + self.assertTrue(len(thread_list) == 1) + thread = thread_list[0] + + self.target.BreakpointDelete(inner_float_bkpt.GetID()) + + frame = thread.GetFrameAtIndex(0) + in_value = frame.FindVariable("value") + in_float = float(in_value.GetValue()) + thread.StepOut() + + self.assertTrue(self.process.GetState() == lldb.eStateStopped) + self.assertTrue(thread.GetStopReason() == lldb.eStopReasonPlanComplete) + + frame = thread.GetFrameAtIndex(0) + fun_name = frame.GetFunctionName() + self.assertTrue(fun_name == "outer_float(float)") + + #return_value = thread.GetStopReturnValue() + #self.assertTrue(return_value.IsValid()) + #return_float = float(return_value.GetValue()) + + #self.assertTrue(in_float == return_float) + + if not self.affected_by_radar_34562999() and not self.affected_by_pr44132(): + self.return_and_test_struct_value("return_one_int") + self.return_and_test_struct_value("return_two_int") + self.return_and_test_struct_value("return_three_int") + self.return_and_test_struct_value("return_four_int") + if not self.affected_by_pr33042(): + self.return_and_test_struct_value("return_five_int") + + self.return_and_test_struct_value("return_two_double") + self.return_and_test_struct_value("return_one_double_two_float") + self.return_and_test_struct_value("return_one_int_one_float_one_int") + + self.return_and_test_struct_value("return_one_pointer") + self.return_and_test_struct_value("return_two_pointer") + self.return_and_test_struct_value("return_one_float_one_pointer") + self.return_and_test_struct_value("return_one_int_one_pointer") + self.return_and_test_struct_value("return_three_short_one_float") + + self.return_and_test_struct_value("return_one_int_one_double") + self.return_and_test_struct_value("return_one_int_one_double_one_int") + self.return_and_test_struct_value( + "return_one_short_one_double_one_short") + self.return_and_test_struct_value("return_one_float_one_int_one_float") + self.return_and_test_struct_value("return_two_float") + # I am leaving out the packed test until we have a way to tell CLANG + # about alignment when reading DWARF for packed types. + #self.return_and_test_struct_value ("return_one_int_one_double_packed") + self.return_and_test_struct_value("return_one_int_one_long") + + @expectedFailureAll(oslist=["freebsd"], archs=["i386"]) + @expectedFailureAll(oslist=["macosx"], archs=["i386"], bugnumber="<rdar://problem/28719652>") + @expectedFailureAll( + oslist=["linux"], + compiler="clang", + compiler_version=[ + "<=", + "3.6"], + archs=["i386"]) + @expectedFailureAll(compiler=["gcc"], archs=["x86_64", "i386"]) + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") + @skipIfDarwinEmbedded # <rdar://problem/33976032> ABIMacOSX_arm64 doesn't get structs this big correctly + def test_vector_values(self): + self.build() + exe = self.getBuildArtifact("a.out") + error = lldb.SBError() + + self.target = self.dbg.CreateTarget(exe) + self.assertTrue(self.target, VALID_TARGET) + + main_bktp = self.target.BreakpointCreateByName("main", exe) + self.assertTrue(main_bktp, VALID_BREAKPOINT) + + self.process = self.target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertEqual(len(lldbutil.get_threads_stopped_at_breakpoint( + self.process, main_bktp)), 1) + + self.return_and_test_struct_value("return_vector_size_float32_8") + self.return_and_test_struct_value("return_vector_size_float32_16") + if not self.affected_by_pr44132(): + self.return_and_test_struct_value("return_vector_size_float32_32") + self.return_and_test_struct_value("return_ext_vector_size_float32_2") + self.return_and_test_struct_value("return_ext_vector_size_float32_4") + if not self.affected_by_pr44132(): + self.return_and_test_struct_value("return_ext_vector_size_float32_8") + + # limit the nested struct and class tests to only x86_64 + @skipIf(archs=no_match(['x86_64'])) + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") + def test_for_cpp_support(self): + self.build() + exe = self.getBuildArtifact("a.out") + (self.target, self.process, thread, inner_sint_bkpt) = lldbutil.run_to_name_breakpoint(self, "inner_sint", exe_name = exe) + + error = lldb.SBError() + + self.target = self.dbg.CreateTarget(exe) + self.assertTrue(self.target, VALID_TARGET) + + main_bktp = self.target.BreakpointCreateByName("main", exe) + self.assertTrue(main_bktp, VALID_BREAKPOINT) + + self.process = self.target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertEqual(len(lldbutil.get_threads_stopped_at_breakpoint( + self.process, main_bktp)), 1) + # nested struct tests + self.return_and_test_struct_value("return_nested_one_float_three_base") + self.return_and_test_struct_value("return_double_nested_one_float_one_nested") + self.return_and_test_struct_value("return_nested_float_struct") + # class test + self.return_and_test_struct_value("return_base_class_one_char") + self.return_and_test_struct_value("return_nested_class_float_and_base") + self.return_and_test_struct_value("return_double_nested_class_float_and_nested") + self.return_and_test_struct_value("return_base_class") + self.return_and_test_struct_value("return_derived_class") + + @skipIf(compiler="clang", compiler_version=['<', '7.0']) + def return_and_test_struct_value(self, func_name): + """Pass in the name of the function to return from - takes in value, returns value.""" + + # Set the breakpoint, run to it, finish out. + bkpt = self.target.BreakpointCreateByName(func_name) + self.assertTrue(bkpt.GetNumResolvedLocations() > 0) + + self.process.Continue() + + thread_list = lldbutil.get_threads_stopped_at_breakpoint( + self.process, bkpt) + + self.assertTrue(len(thread_list) == 1) + thread = thread_list[0] + + self.target.BreakpointDelete(bkpt.GetID()) + + in_value = thread.GetFrameAtIndex(0).FindVariable("value") + + self.assertTrue(in_value.IsValid()) + num_in_children = in_value.GetNumChildren() + + # This is a little hokey, but if we don't get all the children now, then + # once we've stepped we won't be able to get them? + + for idx in range(0, num_in_children): + in_child = in_value.GetChildAtIndex(idx) + in_child_str = in_child.GetValue() + + thread.StepOut() + + self.assertTrue(self.process.GetState() == lldb.eStateStopped) + self.assertTrue(thread.GetStopReason() == lldb.eStopReasonPlanComplete) + + # Assuming all these functions step out to main. Could figure out the caller dynamically + # if that would add something to the test. + frame = thread.GetFrameAtIndex(0) + fun_name = frame.GetFunctionName() + self.assertTrue(fun_name == "main") + + frame = thread.GetFrameAtIndex(0) + ret_value = thread.GetStopReturnValue() + + self.assertTrue(ret_value.IsValid()) + + num_ret_children = ret_value.GetNumChildren() + self.assertTrue(num_in_children == num_ret_children) + for idx in range(0, num_ret_children): + in_child = in_value.GetChildAtIndex(idx) + ret_child = ret_value.GetChildAtIndex(idx) + in_child_str = in_child.GetValue() + ret_child_str = ret_child.GetValue() + + self.assertEqual(in_child_str, ret_child_str) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/return-value/call-func.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/return-value/call-func.cpp new file mode 100644 index 00000000000..c538e8479a9 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/return-value/call-func.cpp @@ -0,0 +1,607 @@ +// Some convenient things to return: +static char *g_first_pointer = "I am the first"; +static char *g_second_pointer = "I am the second"; + +// First we have some simple functions that return standard types, ints, floats and doubles. +// We have a function calling a function in a few cases to test that if you stop in the +// inner function then do "up/fin" you get the return value from the outer-most frame. + +int +inner_sint (int value) +{ + return value; +} + +int +outer_sint (int value) +{ + int outer_value = 2 * inner_sint (value); + return outer_value; +} + +float +inner_float (float value) +{ + return value; +} + +float +outer_float (float value) +{ + float outer_value = 2 * inner_float(value); + return outer_value; +} + +double +return_double (double value) +{ + return value; +} + +long double +return_long_double (long double value) +{ + return value; +} + +char * +return_pointer (char *value) +{ + return value; +} + +struct one_int +{ + int one_field; +}; + +struct one_int +return_one_int (struct one_int value) +{ + return value; +} + +struct two_int +{ + int first_field; + int second_field; +}; + +struct two_int +return_two_int (struct two_int value) +{ + return value; +} + +struct three_int +{ + int first_field; + int second_field; + int third_field; +}; + +struct three_int +return_three_int (struct three_int value) +{ + return value; +} + +struct four_int +{ + int first_field; + int second_field; + int third_field; + int fourth_field; +}; + +struct four_int +return_four_int (struct four_int value) +{ + return value; +} + +struct five_int +{ + int first_field; + int second_field; + int third_field; + int fourth_field; + int fifth_field; +}; + +struct five_int +return_five_int (struct five_int value) +{ + return value; +} + +struct one_int_one_double +{ + int first_field; + double second_field; +}; + +struct one_int_one_double +return_one_int_one_double (struct one_int_one_double value) +{ + return value; +} + +struct one_int_one_double_one_int +{ + int one_field; + double second_field; + int third_field; +}; + +struct one_int_one_double_one_int +return_one_int_one_double_one_int (struct one_int_one_double_one_int value) +{ + return value; +} + +struct one_short_one_double_one_short +{ + int one_field; + double second_field; + int third_field; +}; + +struct one_short_one_double_one_short +return_one_short_one_double_one_short (struct one_short_one_double_one_short value) +{ + return value; +} + +struct three_short_one_float +{ + short one_field; + short second_field; + short third_field; + float fourth_field; +}; + +struct three_short_one_float +return_three_short_one_float (struct three_short_one_float value) +{ + return value; +} + +struct one_int_one_float_one_int +{ + int one_field; + float second_field; + int third_field; +}; + +struct one_int_one_float_one_int +return_one_int_one_float_one_int (struct one_int_one_float_one_int value) +{ + return value; +} + +struct one_float_one_int_one_float +{ + float one_field; + int second_field; + float third_field; +}; + +struct one_float_one_int_one_float +return_one_float_one_int_one_float (struct one_float_one_int_one_float value) +{ + return value; +} + +struct one_double_two_float +{ + double one_field; + float second_field; + float third_field; +}; + +struct one_double_two_float +return_one_double_two_float (struct one_double_two_float value) +{ + return value; +} + +struct two_double +{ + double first_field; + double second_field; +}; + +struct two_double +return_two_double (struct two_double value) +{ + return value; +} + +struct two_float +{ + float first_field; + float second_field; +}; + +struct two_float +return_two_float (struct two_float value) +{ + return value; +} + +struct one_int_one_double_packed +{ + int first_field; + double second_field; +} __attribute__((__packed__)); + +struct one_int_one_double_packed +return_one_int_one_double_packed (struct one_int_one_double_packed value) +{ + return value; +} + +struct one_int_one_long +{ + int first_field; + long second_field; +}; + +struct one_int_one_long +return_one_int_one_long (struct one_int_one_long value) +{ + return value; +} + +struct one_pointer +{ + char *first_field; +}; + +struct one_pointer +return_one_pointer (struct one_pointer value) +{ + return value; +} + +struct two_pointer +{ + char *first_field; + char *second_field; +}; + +struct two_pointer +return_two_pointer (struct two_pointer value) +{ + return value; +} + +struct one_float_one_pointer +{ + float first_field; + char *second_field; +}; + +struct one_float_one_pointer +return_one_float_one_pointer (struct one_float_one_pointer value) +{ + return value; +} + +struct one_int_one_pointer +{ + int first_field; + char *second_field; +}; + +struct one_int_one_pointer +return_one_int_one_pointer (struct one_int_one_pointer value) +{ + return value; +} + +struct base_one_char { + char c; +}; + +struct nested_one_float_three_base { + float f; + struct base_one_char b1; + struct base_one_char b2; + struct base_one_char b3; +}; // returned in RAX for both SysV and Windows + +struct nested_one_float_three_base +return_nested_one_float_three_base (struct nested_one_float_three_base value) +{ + return value; +} + +struct double_nested_one_float_one_nested { + float f; + struct nested_one_float_three_base ns; +}; // SysV-ABI: returned in XMM0 + RAX +// Windows-ABI: returned in memory + +struct double_nested_one_float_one_nested +return_double_nested_one_float_one_nested(struct double_nested_one_float_one_nested value) +{ + return value; +} + +struct base_float_struct { + float f1; + float f2; +}; + +struct nested_float_struct { + double d; + struct base_float_struct bfs; +}; // SysV-ABI: return in xmm0 + xmm1 +// Windows-ABI: returned in memory + +struct nested_float_struct +return_nested_float_struct (struct nested_float_struct value) +{ + return value; +} + +struct six_double_three_int { + double d1; // 8 + double d2; // 8 + int i1; // 4 + double d3; // 8 + double d4; // 8 + int i2; // 4 + double d5; // 8 + double d6; // 8 + int i3; // 4 +}; // returned in memeory on both SysV and Windows + +struct six_double_three_int +return_six_double_three_int (struct six_double_three_int value) { + return value; +} + +typedef float vector_size_float32_8 __attribute__((__vector_size__(8))); +typedef float vector_size_float32_16 __attribute__((__vector_size__(16))); +typedef float vector_size_float32_32 __attribute__((__vector_size__(32))); + +typedef float ext_vector_size_float32_2 __attribute__((ext_vector_type(2))); +typedef float ext_vector_size_float32_4 __attribute__((ext_vector_type(4))); +typedef float ext_vector_size_float32_8 __attribute__((ext_vector_type(8))); + +vector_size_float32_8 +return_vector_size_float32_8 (vector_size_float32_8 value) +{ + return value; +} + +vector_size_float32_16 +return_vector_size_float32_16 (vector_size_float32_16 value) +{ + return value; +} + +vector_size_float32_32 +return_vector_size_float32_32 (vector_size_float32_32 value) +{ + return value; +} + +ext_vector_size_float32_2 +return_ext_vector_size_float32_2 (ext_vector_size_float32_2 value) +{ + return value; +} + +ext_vector_size_float32_4 +return_ext_vector_size_float32_4 (ext_vector_size_float32_4 value) +{ + return value; +} + +ext_vector_size_float32_8 +return_ext_vector_size_float32_8 (ext_vector_size_float32_8 value) +{ + return value; +} + +class base_class_one_char { +public: + char c = '!'; +}; // returned in RAX for both ABI + +base_class_one_char +return_base_class_one_char(base_class_one_char value) { + return value; +} + +class nested_class_float_and_base { +public: + float f = 0.1; + base_class_one_char b; +}; // returned in RAX for both ABI + +nested_class_float_and_base +return_nested_class_float_and_base(nested_class_float_and_base value) { + return value; +} + +class double_nested_class_float_and_nested { +public: + float f = 0.2; + nested_class_float_and_base n; +}; // SysV-ABI: returned in XMM0 + RAX +// Windows-ABI: returned in memory + +double_nested_class_float_and_nested +return_double_nested_class_float_and_nested( + double_nested_class_float_and_nested value) { + return value; +} + +class base_class { +public: + base_class() { + c = 'a'; + c2 = 'b'; + } +private: + char c; +protected: + char c2; +}; // returned in RAX for both ABI + +base_class +return_base_class(base_class value) { + return value; +} + +class sub_class : base_class { +public: + sub_class() { + c2 = '&'; + i = 10; + } +private: + int i; +}; // size 8; should be returned in RAX +// Since it's in register, lldb won't be able to get the +// fields in base class, expected to fail. + +sub_class +return_sub_class(sub_class value) { + return value; +} + +class abstract_class { +public: + virtual char getChar() = 0; +private: + int i = 8; +protected: + char c = '!'; +}; + +class derived_class : abstract_class { +public: + derived_class() { + c = '?'; + } + char getChar() { + return this->c; + } +private: + char c2 = '$'; +}; // size: 16; contains non POD member, returned in memory + +derived_class +return_derived_class(derived_class value) { + return value; +} + +int +main () +{ + int first_int = 123456; + int second_int = 234567; + + outer_sint (first_int); + outer_sint (second_int); + + float first_float_value = 12.34; + float second_float_value = 23.45; + + outer_float (first_float_value); + outer_float (second_float_value); + + double double_value = -23.45; + + return_double (double_value); + + return_pointer(g_first_pointer); + + long double long_double_value = -3456789.987654321; + + return_long_double (long_double_value); + + // Okay, now the structures: + return_one_int ((struct one_int) {10}); + return_two_int ((struct two_int) {10, 20}); + return_three_int ((struct three_int) {10, 20, 30}); + return_four_int ((struct four_int) {10, 20, 30, 40}); + return_five_int ((struct five_int) {10, 20, 30, 40, 50}); + + return_two_double ((struct two_double) {10.0, 20.0}); + return_one_double_two_float ((struct one_double_two_float) {10.0, 20.0, 30.0}); + return_one_int_one_float_one_int ((struct one_int_one_float_one_int) {10, 20.0, 30}); + + return_one_pointer ((struct one_pointer) {g_first_pointer}); + return_two_pointer ((struct two_pointer) {g_first_pointer, g_second_pointer}); + return_one_float_one_pointer ((struct one_float_one_pointer) {10.0, g_first_pointer}); + return_one_int_one_pointer ((struct one_int_one_pointer) {10, g_first_pointer}); + return_three_short_one_float ((struct three_short_one_float) {10, 20, 30, 40.0}); + + return_one_int_one_double ((struct one_int_one_double) {10, 20.0}); + return_one_int_one_double_one_int ((struct one_int_one_double_one_int) {10, 20.0, 30}); + return_one_short_one_double_one_short ((struct one_short_one_double_one_short) {10, 20.0, 30}); + return_one_float_one_int_one_float ((struct one_float_one_int_one_float) {10.0, 20, 30.0}); + return_two_float ((struct two_float) { 10.0, 20.0}); + return_one_int_one_double_packed ((struct one_int_one_double_packed) {10, 20.0}); + return_one_int_one_long ((struct one_int_one_long) {10, 20}); + + return_nested_one_float_three_base((struct nested_one_float_three_base) { + 10.0, + (struct base_one_char) { + 'x' + }, + (struct base_one_char) { + 'y' + }, + (struct base_one_char) { + 'z' + } + }); + return_double_nested_one_float_one_nested((struct double_nested_one_float_one_nested) { + 10.0, + (struct nested_one_float_three_base) { + 20.0, + (struct base_one_char) { + 'x' + }, + (struct base_one_char) { + 'y' + }, + (struct base_one_char) { + 'z' + } + }}); + return_nested_float_struct((struct nested_float_struct) { + 10.0, + (struct base_float_struct) { + 20.0, + 30.0 + }}); + return_six_double_three_int((struct six_double_three_int) { + 10.0, 20.0, 1, 30.0, 40.0, 2, 50.0, 60.0, 3}); + + return_base_class_one_char(base_class_one_char()); + return_nested_class_float_and_base(nested_class_float_and_base()); + return_double_nested_class_float_and_nested(double_nested_class_float_and_nested()); + return_base_class(base_class()); + // this is expected to fail + return_sub_class(sub_class()); + return_derived_class(derived_class()); + + return_vector_size_float32_8 (( vector_size_float32_8 ){1.5, 2.25}); + return_vector_size_float32_16 (( vector_size_float32_16 ){1.5, 2.25, 4.125, 8.0625}); + return_vector_size_float32_32 (( vector_size_float32_32 ){1.5, 2.25, 4.125, 8.0625, 7.89, 8.52, 6.31, 9.12}); + + return_ext_vector_size_float32_2 ((ext_vector_size_float32_2){ 16.5, 32.25}); + return_ext_vector_size_float32_4 ((ext_vector_size_float32_4){ 16.5, 32.25, 64.125, 128.0625}); + return_ext_vector_size_float32_8 ((ext_vector_size_float32_8){ 16.5, 32.25, 64.125, 128.0625, 1.59, 3.57, 8.63, 9.12 }); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/set-data/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/set-data/Makefile new file mode 100644 index 00000000000..37dd8f40a9d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/set-data/Makefile @@ -0,0 +1,6 @@ +OBJC_SOURCES := main.m + + + +LD_EXTRAS := -framework Foundation +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/set-data/TestSetData.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/set-data/TestSetData.py new file mode 100644 index 00000000000..5b0a7bd07fe --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/set-data/TestSetData.py @@ -0,0 +1,68 @@ +""" +Set the contents of variables and registers using raw data +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class SetDataTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipUnlessDarwin + def test_set_data(self): + """Test setting the contents of variables and registers using raw data.""" + self.build() + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + self.runCmd("br s -p First") + self.runCmd("br s -p Second") + + self.runCmd("run", RUN_SUCCEEDED) + + self.expect("p myFoo.x", VARIABLES_DISPLAYED_CORRECTLY, + substrs=['2']) + + process = self.dbg.GetSelectedTarget().GetProcess() + frame = process.GetSelectedThread().GetFrameAtIndex(0) + + x = frame.FindVariable("myFoo").GetChildMemberWithName("x") + + my_data = lldb.SBData.CreateDataFromSInt32Array( + lldb.eByteOrderLittle, 8, [4]) + err = lldb.SBError() + + self.assertTrue(x.SetData(my_data, err)) + + self.runCmd("continue") + + self.expect("p myFoo.x", VARIABLES_DISPLAYED_CORRECTLY, + substrs=['4']) + + frame = process.GetSelectedThread().GetFrameAtIndex(0) + + x = frame.FindVariable("string") + + if process.GetAddressByteSize() == 8: + my_data = lldb.SBData.CreateDataFromUInt64Array( + process.GetByteOrder(), 8, [0]) + else: + my_data = lldb.SBData.CreateDataFromUInt32Array( + process.GetByteOrder(), 4, [0]) + + err = lldb.SBError() + + self.assertTrue(x.SetData(my_data, err)) + + self.expect( + "fr var -d run-target string", + VARIABLES_DISPLAYED_CORRECTLY, + substrs=[ + 'NSString *', + 'nil']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/set-data/main.m b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/set-data/main.m new file mode 100644 index 00000000000..e1e69dc5571 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/set-data/main.m @@ -0,0 +1,19 @@ +#import <Foundation/Foundation.h> + +int main () +{ + @autoreleasepool + { + struct foo { + int x; + int y; + } myFoo; + + myFoo.x = 2; + myFoo.y = 3; // First breakpoint + + NSString *string = [NSString stringWithFormat:@"%s", "Hello world!"]; + + NSLog(@"%d %@", myFoo.x, string); // Second breakpoint + } +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/show_location/TestShowLocationDwarf5.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/show_location/TestShowLocationDwarf5.py new file mode 100644 index 00000000000..1d4bc6f1345 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/show_location/TestShowLocationDwarf5.py @@ -0,0 +1,36 @@ +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * + +# This test checks that source code location is shown correctly +# when DWARF5 debug information is used. + +class TestTargetSourceMap(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipIf(archs="aarch64", oslist="linux", + bugnumber="https://bugs.llvm.org/show_bug.cgi?id=44180") + def test_source_map(self): + # Set the target soure map to map "./" to the current test directory. + yaml_path = os.path.join(self.getSourceDir(), "a.yaml") + yaml_base, ext = os.path.splitext(yaml_path) + obj_path = self.getBuildArtifact(yaml_base) + self.yaml2obj(yaml_path, obj_path) + + def cleanup(): + if os.path.exists(obj_path): + os.unlink(obj_path) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + # Create a target with the object file we just created from YAML + target = self.dbg.CreateTarget(obj_path) + + # Check we are able to show the locations properly. + self.expect("b main", VALID_BREAKPOINT_LOCATION, + substrs=['main + 13 at test.cpp:2:3, address = 0x000000000040052d']) + + self.expect("b foo", VALID_BREAKPOINT_LOCATION, + substrs=['foo() + 4 at test.cpp:6:1, address = 0x0000000000400534']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/show_location/a.yaml b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/show_location/a.yaml new file mode 100644 index 00000000000..27b119d3df6 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/show_location/a.yaml @@ -0,0 +1,58 @@ +# This file is a shorten version of the output +# produced with the following invocations and input: +# ./clang test.cpp -g -gdwarf-5 -o test.exe +# ./obj2yaml test.exe > test.yaml +# +# // test.cpp +# int main() { +# return 0; +# } +# +# void foo() { +# } + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 + Entry: 0x0000000000400440 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x0000000000400440 + AddressAlign: 0x0000000000000010 + Content: 31ED4989D15E4889E24883E4F0505449C7C0B005400048C7C14005400048C7C720054000E8B7FFFFFFF4660F1F44000055B820204000483D202040004889E57417B8000000004885C0740D5DBF20204000FFE00F1F4400005DC3660F1F440000BE20204000554881EE202040004889E548C1FE034889F048C1E83F4801C648D1FE7415B8000000004885C0740B5DBF20204000FFE00F1F005DC3660F1F440000803D391B0000007517554889E5E87EFFFFFFC605271B0000015DC30F1F440000F3C30F1F4000662E0F1F840000000000554889E55DEB89660F1F840000000000554889E531C0C745FC000000005DC390554889E55DC3662E0F1F840000000000415741564189FF415541544C8D25B618000055488D2DB6180000534989F64989D54C29E54883EC0848C1FD03E87FFEFFFF4885ED742031DB0F1F8400000000004C89EA4C89F64489FF41FF14DC4883C3014839EB75EA4883C4085B5D415C415D415E415FC390662E0F1F840000000000F3C3 + - Name: .debug_str_offsets + Type: SHT_PROGBITS + AddressAlign: 0x0000000000000001 + Content: 200000000500000000000000230000002C0000004A0000004F000000530000005B000000 + - Name: .debug_str + Type: SHT_PROGBITS + Flags: [ SHF_MERGE, SHF_STRINGS ] + AddressAlign: 0x0000000000000001 + Content: 636C616E672076657273696F6E20382E302E3020287472756E6B203334313935382900746573742E637070002F686F6D652F756D622F4C4C564D2F6275696C645F6C6C64622F62696E006D61696E00696E74005F5A33666F6F7600666F6F00 + - Name: .debug_abbrev + Type: SHT_PROGBITS + AddressAlign: 0x0000000000000001 + Content: 011101252513050325721710171B25110112060000022E0011011206401803253A0B3B0B49133F190000032E001101120640186E2503253A0B3B0B3F19000004240003253E0B0B0B000000 + - Name: .debug_info + Type: SHT_PROGBITS + AddressAlign: 0x0000000000000001 + Content: 50000000050001080000000001000400010800000000000000022005400000000000160000000220054000000000000F00000001560301014F000000033005400000000000060000000156050601050404050400 + - Name: .debug_macinfo + Type: SHT_PROGBITS + AddressAlign: 0x0000000000000001 + Content: '00' + - Name: .debug_line + Type: SHT_PROGBITS + AddressAlign: 0x0000000000000001 + Content: 70000000050008004C000000010101FB0E0D00010101010000000100000101011F010000000003011F020F051E021E00000000FD7C0F2E46BA561F7BDA351B04E677091E00000000FD7C0F2E46BA561F7BDA351B04E6770900090220054000000000000105030AC905003F05010A4B0202000101 + - Name: .debug_line_str + Type: SHT_PROGBITS + Flags: [ SHF_MERGE, SHF_STRINGS ] + AddressAlign: 0x0000000000000001 + Content: 2F686F6D652F756D622F4C4C564D2F6275696C645F6C6C64622F62696E00746573742E63707000 +... diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/TestSendSignal.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/TestSendSignal.py new file mode 100644 index 00000000000..ca268af63c4 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/TestSendSignal.py @@ -0,0 +1,112 @@ +"""Test that lldb command 'process signal SIGUSR1' to send a signal to the inferior works.""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class SendSignalTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.line = line_number('main.c', 'Put breakpoint here') + + @expectedFailureAll( + oslist=['freebsd'], + bugnumber="llvm.org/pr23318: does not report running state") + @expectedFailureNetBSD(bugnumber='llvm.org/pr43959') + @skipIfWindows # Windows does not support signals + def test_with_run_command(self): + """Test that lldb command 'process signal SIGUSR1' sends a signal to the inferior process.""" + self.build() + exe = self.getBuildArtifact("a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create a breakpoint on main.c by name 'c'. + breakpoint = target.BreakpointCreateByLocation('main.c', self.line) + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + # Get the breakpoint location from breakpoint after we verified that, + # indeed, it has one location. + location = breakpoint.GetLocationAtIndex(0) + self.assertTrue(location and + location.IsEnabled(), + VALID_BREAKPOINT_LOCATION) + + # Now launch the process, no arguments & do not stop at entry point. + launch_info = lldb.SBLaunchInfo([exe]) + launch_info.SetWorkingDirectory(self.get_process_working_directory()) + + process_listener = lldb.SBListener("signal_test_listener") + launch_info.SetListener(process_listener) + error = lldb.SBError() + process = target.Launch(launch_info, error) + self.assertTrue(process, PROCESS_IS_VALID) + + self.runCmd("process handle -n False -p True -s True SIGUSR1") + + thread = lldbutil.get_stopped_thread( + process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), "We hit the first breakpoint.") + + # After resuming the process, send it a SIGUSR1 signal. + + self.setAsync(True) + + self.assertTrue( + process_listener.IsValid(), + "Got a good process listener") + + # Disable our breakpoint, we don't want to hit it anymore... + breakpoint.SetEnabled(False) + + # Now continue: + process.Continue() + + # If running remote test, there should be a connected event + if lldb.remote_platform: + self.match_state(process_listener, lldb.eStateConnected) + + self.match_state(process_listener, lldb.eStateRunning) + + # Now signal the process, and make sure it stops: + process.Signal(lldbutil.get_signal_number('SIGUSR1')) + + self.match_state(process_listener, lldb.eStateStopped) + + # Now make sure the thread was stopped with a SIGUSR1: + threads = lldbutil.get_stopped_threads(process, lldb.eStopReasonSignal) + self.assertTrue(len(threads) == 1, "One thread stopped for a signal.") + thread = threads[0] + + self.assertTrue( + thread.GetStopReasonDataCount() >= 1, + "There was data in the event.") + self.assertTrue( + thread.GetStopReasonDataAtIndex(0) == lldbutil.get_signal_number('SIGUSR1'), + "The stop signal was SIGUSR1") + + def match_state(self, process_listener, expected_state): + num_seconds = 5 + broadcaster = self.process().GetBroadcaster() + event_type_mask = lldb.SBProcess.eBroadcastBitStateChanged + event = lldb.SBEvent() + got_event = process_listener.WaitForEventForBroadcasterWithType( + num_seconds, broadcaster, event_type_mask, event) + self.assertTrue(got_event, "Got an event") + state = lldb.SBProcess.GetStateFromEvent(event) + self.assertTrue(state == expected_state, + "It was the %s state." % + lldb.SBDebugger_StateAsCString(expected_state)) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/handle-abrt/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/handle-abrt/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/handle-abrt/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/handle-abrt/TestHandleAbort.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/handle-abrt/TestHandleAbort.py new file mode 100644 index 00000000000..5f3eb31c83a --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/handle-abrt/TestHandleAbort.py @@ -0,0 +1,70 @@ +"""Test that we can unwind out of a SIGABRT handler""" + + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class HandleAbortTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + @skipIfWindows # signals do not exist on Windows + @expectedFailureNetBSD + def test_inferior_handle_sigabrt(self): + """Inferior calls abort() and handles the resultant SIGABRT. + Stopped at a breakpoint in the handler, verify that the backtrace + includes the function that called abort().""" + self.build() + exe = self.getBuildArtifact("a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # launch + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + self.assertEqual(process.GetState(), lldb.eStateStopped) + signo = process.GetUnixSignals().GetSignalNumberFromName("SIGABRT") + + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonSignal) + self.assertTrue( + thread and thread.IsValid(), + "Thread should be stopped due to a signal") + self.assertTrue( + thread.GetStopReasonDataCount() >= 1, + "There should be data in the event.") + self.assertEqual(thread.GetStopReasonDataAtIndex(0), + signo, "The stop signal should be SIGABRT") + + # Continue to breakpoint in abort handler + bkpt = target.FindBreakpointByID( + lldbutil.run_break_set_by_source_regexp(self, "Set a breakpoint here")) + threads = lldbutil.continue_to_breakpoint(process, bkpt) + self.assertEqual(len(threads), 1, "Expected single thread") + thread = threads[0] + + # Expect breakpoint in 'handler' + frame = thread.GetFrameAtIndex(0) + self.assertEqual(frame.GetDisplayFunctionName(), "handler", "Unexpected break?") + + # Expect that unwinding should find 'abort_caller' + foundFoo = False + for frame in thread: + if frame.GetDisplayFunctionName() == "abort_caller": + foundFoo = True + + self.assertTrue(foundFoo, "Unwinding did not find func that called abort") + + # Continue until we exit. + process.Continue() + self.assertEqual(process.GetState(), lldb.eStateExited) + self.assertEqual(process.GetExitStatus(), 0) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/handle-abrt/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/handle-abrt/main.c new file mode 100644 index 00000000000..c2daea1e84e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/handle-abrt/main.c @@ -0,0 +1,25 @@ +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> + +void handler(int sig) +{ + printf("Set a breakpoint here.\n"); + exit(0); +} + +void abort_caller() { + abort(); +} + +int main() +{ + if (signal(SIGABRT, handler) == SIG_ERR) + { + perror("signal"); + return 1; + } + + abort_caller(); + return 2; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/handle-segv/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/handle-segv/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/handle-segv/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/handle-segv/TestHandleSegv.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/handle-segv/TestHandleSegv.py new file mode 100644 index 00000000000..30ae201ed14 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/handle-segv/TestHandleSegv.py @@ -0,0 +1,47 @@ +"""Test that we can debug inferiors that handle SIGSEGV by themselves""" + + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class HandleSegvTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipIfWindows # signals do not exist on Windows + @skipIfDarwin + @expectedFailureNetBSD + def test_inferior_handle_sigsegv(self): + self.build() + exe = self.getBuildArtifact("a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # launch + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + self.assertEqual(process.GetState(), lldb.eStateStopped) + signo = process.GetUnixSignals().GetSignalNumberFromName("SIGSEGV") + + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonSignal) + self.assertTrue( + thread and thread.IsValid(), + "Thread should be stopped due to a signal") + self.assertTrue( + thread.GetStopReasonDataCount() >= 1, + "There was data in the event.") + self.assertEqual(thread.GetStopReasonDataAtIndex(0), + signo, "The stop signal was SIGSEGV") + + # Continue until we exit. + process.Continue() + self.assertEqual(process.GetState(), lldb.eStateExited) + self.assertEqual(process.GetExitStatus(), 0) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/handle-segv/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/handle-segv/main.c new file mode 100644 index 00000000000..27d9b8e500a --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/handle-segv/main.c @@ -0,0 +1,58 @@ +#include <sys/mman.h> +#include <signal.h> +#include <stdio.h> +#include <unistd.h> + +enum { + kMmapSize = 0x1000, + kMagicValue = 47, +}; + +void *address; +volatile sig_atomic_t signaled = 0; + +void handler(int sig) +{ + signaled = 1; + if (munmap(address, kMmapSize) != 0) + { + perror("munmap"); + _exit(5); + } + + void* newaddr = mmap(address, kMmapSize, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_FIXED | MAP_PRIVATE, -1, 0); + if (newaddr != address) + { + fprintf(stderr, "Newly mmaped address (%p) does not equal old address (%p).\n", + newaddr, address); + _exit(6); + } + *(int*)newaddr = kMagicValue; +} + +int main() +{ + if (signal(SIGSEGV, handler) == SIG_ERR) + { + perror("signal"); + return 1; + } + + address = mmap(NULL, kMmapSize, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0); + if (address == MAP_FAILED) + { + perror("mmap"); + return 2; + } + + // This should first trigger a segfault. Our handler will make the memory readable and write + // the magic value into memory. + if (*(int*)address != kMagicValue) + return 3; + + if (! signaled) + return 4; + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/main.c new file mode 100644 index 00000000000..77e76050341 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/main.c @@ -0,0 +1,27 @@ +#include <signal.h> +#include <stdio.h> +#include <unistd.h> + +void handler_usr1 (int i) +{ + puts ("got signal usr1"); +} + +void handler_alrm (int i) +{ + puts ("got signal ALRM"); +} + +int main () +{ + int i = 0; + + signal (SIGUSR1, handler_usr1); + signal (SIGALRM, handler_alrm); + + puts ("Put breakpoint here"); + + while (i++ < 20) + sleep (1); +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/raise/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/raise/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/raise/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/raise/TestRaise.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/raise/TestRaise.py new file mode 100644 index 00000000000..70271e43cff --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/raise/TestRaise.py @@ -0,0 +1,190 @@ +"""Test that we handle inferiors that send signals to themselves""" + + + +import lldb +import re +from lldbsuite.test.lldbplatformutil import getDarwinOSTriples +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +@skipIfWindows # signals do not exist on Windows +class RaiseTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + @skipIfNetBSD # Hangs on NetBSD + def test_sigstop(self): + self.build() + self.signal_test('SIGSTOP', False) + # passing of SIGSTOP is not correctly handled, so not testing that + # scenario: https://llvm.org/bugs/show_bug.cgi?id=23574 + + @skipIfDarwin # darwin does not support real time signals + @skipIfTargetAndroid() + def test_sigsigrtmin(self): + self.build() + self.signal_test('SIGRTMIN', True) + + @skipIfNetBSD # Hangs on NetBSD + def test_sigtrap(self): + self.build() + self.signal_test('SIGTRAP', True) + + def launch(self, target, signal): + # launch the process, do not stop at entry point. + process = target.LaunchSimple( + [signal], None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + self.assertEqual(process.GetState(), lldb.eStateStopped) + thread = lldbutil.get_stopped_thread( + process, lldb.eStopReasonBreakpoint) + self.assertTrue( + thread.IsValid(), + "Thread should be stopped due to a breakpoint") + return process + + def set_handle(self, signal, pass_signal, stop_at_signal, notify_signal): + return_obj = lldb.SBCommandReturnObject() + self.dbg.GetCommandInterpreter().HandleCommand( + "process handle %s -p %s -s %s -n %s" % + (signal, pass_signal, stop_at_signal, notify_signal), return_obj) + self.assertTrue( + return_obj.Succeeded(), + "Setting signal handling failed") + + def signal_test(self, signal, test_passing): + """Test that we handle inferior raising signals""" + exe = self.getBuildArtifact("a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + lldbutil.run_break_set_by_symbol(self, "main") + + # launch + process = self.launch(target, signal) + signo = process.GetUnixSignals().GetSignalNumberFromName(signal) + + # retrieve default signal disposition + return_obj = lldb.SBCommandReturnObject() + self.dbg.GetCommandInterpreter().HandleCommand( + "process handle %s " % signal, return_obj) + match = re.match( + 'NAME *PASS *STOP *NOTIFY.*(false|true) *(false|true) *(false|true)', + return_obj.GetOutput(), + re.IGNORECASE | re.DOTALL) + if not match: + self.fail('Unable to retrieve default signal disposition.') + default_pass = match.group(1) + default_stop = match.group(2) + default_notify = match.group(3) + + # Make sure we stop at the signal + self.set_handle(signal, "false", "true", "true") + process.Continue() + self.assertEqual(process.GetState(), lldb.eStateStopped) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonSignal) + self.assertTrue( + thread.IsValid(), + "Thread should be stopped due to a signal") + self.assertTrue( + thread.GetStopReasonDataCount() >= 1, + "There was data in the event.") + self.assertEqual(thread.GetStopReasonDataAtIndex(0), signo, + "The stop signal was %s" % signal) + + # Continue until we exit. + process.Continue() + self.assertEqual(process.GetState(), lldb.eStateExited) + self.assertEqual(process.GetExitStatus(), 0) + + # launch again + process = self.launch(target, signal) + + # Make sure we do not stop at the signal. We should still get the + # notification. + self.set_handle(signal, "false", "false", "true") + self.expect( + "process continue", + substrs=[ + "stopped and restarted", + signal]) + self.assertEqual(process.GetState(), lldb.eStateExited) + self.assertEqual(process.GetExitStatus(), 0) + + # launch again + process = self.launch(target, signal) + + # Make sure we do not stop at the signal, and we do not get the + # notification. + self.set_handle(signal, "false", "false", "false") + self.expect( + "process continue", + substrs=["stopped and restarted"], + matching=False) + self.assertEqual(process.GetState(), lldb.eStateExited) + self.assertEqual(process.GetExitStatus(), 0) + + if not test_passing: + # reset signal handling to default + self.set_handle(signal, default_pass, default_stop, default_notify) + return + + # launch again + process = self.launch(target, signal) + + # Make sure we stop at the signal + self.set_handle(signal, "true", "true", "true") + process.Continue() + self.assertEqual(process.GetState(), lldb.eStateStopped) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonSignal) + self.assertTrue( + thread.IsValid(), + "Thread should be stopped due to a signal") + self.assertTrue( + thread.GetStopReasonDataCount() >= 1, + "There was data in the event.") + self.assertEqual( + thread.GetStopReasonDataAtIndex(0), + process.GetUnixSignals().GetSignalNumberFromName(signal), + "The stop signal was %s" % + signal) + + # Continue until we exit. The process should receive the signal. + process.Continue() + self.assertEqual(process.GetState(), lldb.eStateExited) + self.assertEqual(process.GetExitStatus(), signo) + + # launch again + process = self.launch(target, signal) + + # Make sure we do not stop at the signal. We should still get the notification. Process + # should receive the signal. + self.set_handle(signal, "true", "false", "true") + self.expect( + "process continue", + substrs=[ + "stopped and restarted", + signal]) + self.assertEqual(process.GetState(), lldb.eStateExited) + self.assertEqual(process.GetExitStatus(), signo) + + # launch again + process = self.launch(target, signal) + + # Make sure we do not stop at the signal, and we do not get the notification. Process + # should receive the signal. + self.set_handle(signal, "true", "false", "false") + self.expect( + "process continue", + substrs=["stopped and restarted"], + matching=False) + self.assertEqual(process.GetState(), lldb.eStateExited) + self.assertEqual(process.GetExitStatus(), signo) + + # reset signal handling to default + self.set_handle(signal, default_pass, default_stop, default_notify) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/raise/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/raise/main.c new file mode 100644 index 00000000000..4203fe5d4c8 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/signal/raise/main.c @@ -0,0 +1,49 @@ +#include <signal.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +void handler(int signo) +{ + _exit(signo); +} + +int main (int argc, char *argv[]) +{ + if (signal(SIGTRAP, handler) == SIG_ERR) + { + perror("signal(SIGTRAP)"); + return 1; + } +#ifndef __APPLE__ + // Real time signals not supported on apple platforms. + if (signal(SIGRTMIN, handler) == SIG_ERR) + { + perror("signal(SIGRTMIN)"); + return 1; + } +#endif + + if (argc < 2) + { + puts("Please specify a signal to raise"); + return 1; + } + + if (strcmp(argv[1], "SIGSTOP") == 0) + raise(SIGSTOP); + else if (strcmp(argv[1], "SIGTRAP") == 0) + raise(SIGTRAP); +#ifndef __APPLE__ + else if (strcmp(argv[1], "SIGRTMIN") == 0) + raise(SIGRTMIN); +#endif + else + { + printf("Unknown signal: %s\n", argv[1]); + return 1; + } + + return 0; +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/source-map/TestTargetSourceMap.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/source-map/TestTargetSourceMap.py new file mode 100644 index 00000000000..80c4877ad32 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/source-map/TestTargetSourceMap.py @@ -0,0 +1,43 @@ +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * + + +class TestTargetSourceMap(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @no_debug_info_test + def test_source_map(self): + """Test target.source-map' functionality.""" + # Set the target soure map to map "./" to the current test directory + src_dir = self.getSourceDir() + src_path = os.path.join(src_dir, "main.c") + yaml_path = os.path.join(src_dir, "a.yaml") + yaml_base, ext = os.path.splitext(yaml_path) + obj_path = self.getBuildArtifact("main.o") + self.yaml2obj(yaml_path, obj_path) + + # Create a target with the object file we just created from YAML + target = self.dbg.CreateTarget(obj_path) + + # Set a breakpoint before we remap source and verify that it fails + bp = target.BreakpointCreateByLocation(src_path, 2) + self.assertTrue(bp.GetNumLocations() == 0, + "make sure no breakpoints were resolved without map") + src_map_cmd = 'settings set target.source-map . "%s"' % (src_dir) + self.dbg.HandleCommand(src_map_cmd) + + # Set a breakpoint after we remap source and verify that it succeeds + bp = target.BreakpointCreateByLocation(src_path, 2) + self.assertTrue(bp.GetNumLocations() == 1, + "make sure breakpoint was resolved with map") + + # Now make sure that we can actually FIND the source file using this + # remapping: + retval = lldb.SBCommandReturnObject() + self.dbg.GetCommandInterpreter().HandleCommand("source list -f main.c -l 2", retval) + self.assertTrue(retval.Succeeded(), "source list didn't succeed.") + self.assertTrue(retval.GetOutput() != None, "We got no ouput from source list") + self.assertTrue("return" in retval.GetOutput(), "We didn't find the source file...") + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/source-map/Trivial/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/source-map/Trivial/main.c new file mode 100644 index 00000000000..921907253c2 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/source-map/Trivial/main.c @@ -0,0 +1,7 @@ +int main() +{ + return 0; +} +int main () { + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/source-map/a.yaml b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/source-map/a.yaml new file mode 100644 index 00000000000..d14e9a3b832 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/source-map/a.yaml @@ -0,0 +1,410 @@ +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x01000007 + cpusubtype: 0x00000003 + filetype: 0x00000001 + ncmds: 4 + sizeofcmds: 1160 + flags: 0x00002000 + reserved: 0x00000000 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 1032 + segname: '' + vmaddr: 0 + vmsize: 744 + fileoff: 1192 + filesize: 744 + maxprot: 7 + initprot: 7 + nsects: 12 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x0000000000000000 + size: 22 + offset: 0x000004A8 + align: 4 + reloff: 0x00000000 + nreloc: 0 + flags: 0x80000400 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_str + segname: __DWARF + addr: 0x0000000000000016 + size: 108 + offset: 0x000004BE + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x02000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_abbrev + segname: __DWARF + addr: 0x0000000000000082 + size: 83 + offset: 0x0000052A + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x02000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_info + segname: __DWARF + addr: 0x00000000000000D5 + size: 126 + offset: 0x0000057D + align: 0 + reloff: 0x00000790 + nreloc: 2 + flags: 0x02000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_macinfo + segname: __DWARF + addr: 0x0000000000000153 + size: 1 + offset: 0x000005FB + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x02000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __apple_names + segname: __DWARF + addr: 0x0000000000000154 + size: 60 + offset: 0x000005FC + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x02000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __apple_objc + segname: __DWARF + addr: 0x0000000000000190 + size: 36 + offset: 0x00000638 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x02000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __apple_namespac + segname: __DWARF + addr: 0x00000000000001B4 + size: 36 + offset: 0x0000065C + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x02000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __apple_types + segname: __DWARF + addr: 0x00000000000001D8 + size: 102 + offset: 0x00000680 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x02000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __compact_unwind + segname: __LD + addr: 0x0000000000000240 + size: 32 + offset: 0x000006E8 + align: 3 + reloff: 0x000007A0 + nreloc: 1 + flags: 0x02000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __eh_frame + segname: __TEXT + addr: 0x0000000000000260 + size: 64 + offset: 0x00000708 + align: 3 + reloff: 0x00000000 + nreloc: 0 + flags: 0x6800000B + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_line + segname: __DWARF + addr: 0x00000000000002A0 + size: 72 + offset: 0x00000748 + align: 0 + reloff: 0x000007A8 + nreloc: 1 + flags: 0x02000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - cmd: LC_BUILD_VERSION + cmdsize: 24 + platform: 1 + minos: 658944 + sdk: 658944 + ntools: 0 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 1968 + nsyms: 1 + stroff: 1984 + strsize: 8 + - cmd: LC_DYSYMTAB + cmdsize: 80 + ilocalsym: 0 + nlocalsym: 0 + iextdefsym: 0 + nextdefsym: 1 + iundefsym: 1 + nundefsym: 0 + tocoff: 0 + ntoc: 0 + modtaboff: 0 + nmodtab: 0 + extrefsymoff: 0 + nextrefsyms: 0 + indirectsymoff: 0 + nindirectsyms: 0 + extreloff: 0 + nextrel: 0 + locreloff: 0 + nlocrel: 0 +LinkEditData: + NameList: + - n_strx: 1 + n_type: 0x0F + n_sect: 1 + n_desc: 0 + n_value: 0 + StringTable: + - '' + - _main + - '' +DWARF: + debug_str: + - 'Apple LLVM version 10.0.1 (clang-1001.0.37.3)' + - './Trivial/main.c' + - '.' + - main + - int + - argc + - argv + - char + debug_abbrev: + - Code: 0x00000001 + Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_producer + Form: DW_FORM_strp + - Attribute: DW_AT_language + Form: DW_FORM_data2 + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_stmt_list + Form: DW_FORM_sec_offset + - Attribute: DW_AT_comp_dir + Form: DW_FORM_strp + - Attribute: DW_AT_low_pc + Form: DW_FORM_addr + - Attribute: DW_AT_high_pc + Form: DW_FORM_data4 + - Code: 0x00000002 + Tag: DW_TAG_subprogram + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_low_pc + Form: DW_FORM_addr + - Attribute: DW_AT_high_pc + Form: DW_FORM_data4 + - Attribute: DW_AT_frame_base + Form: DW_FORM_exprloc + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_decl_file + Form: DW_FORM_data1 + - Attribute: DW_AT_decl_line + Form: DW_FORM_data1 + - Attribute: DW_AT_prototyped + Form: DW_FORM_flag_present + - Attribute: DW_AT_type + Form: DW_FORM_ref4 + - Attribute: DW_AT_external + Form: DW_FORM_flag_present + - Code: 0x00000003 + Tag: DW_TAG_formal_parameter + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_location + Form: DW_FORM_exprloc + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_decl_file + Form: DW_FORM_data1 + - Attribute: DW_AT_decl_line + Form: DW_FORM_data1 + - Attribute: DW_AT_type + Form: DW_FORM_ref4 + - Code: 0x00000004 + Tag: DW_TAG_base_type + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_encoding + Form: DW_FORM_data1 + - Attribute: DW_AT_byte_size + Form: DW_FORM_data1 + - Code: 0x00000005 + Tag: DW_TAG_pointer_type + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_type + Form: DW_FORM_ref4 + - Code: 0x00000006 + Tag: DW_TAG_const_type + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_type + Form: DW_FORM_ref4 + debug_info: + - Length: + TotalLength: 122 + Version: 4 + AbbrOffset: 0 + AddrSize: 8 + Entries: + - AbbrCode: 0x00000001 + Values: + - Value: 0x0000000000000000 + - Value: 0x000000000000000C + - Value: 0x000000000000002E + - Value: 0x0000000000000000 + - Value: 0x000000000000003F + - Value: 0x0000000000000000 + - Value: 0x0000000000000016 + - AbbrCode: 0x00000002 + Values: + - Value: 0x0000000000000000 + - Value: 0x0000000000000016 + - Value: 0x0000000000000001 + BlockData: + - 0x56 + - Value: 0x0000000000000054 + - Value: 0x0000000000000001 + - Value: 0x0000000000000001 + - Value: 0x0000000000000001 + - Value: 0x0000000000000060 + - Value: 0x0000000000000001 + - AbbrCode: 0x00000003 + Values: + - Value: 0x0000000000000002 + BlockData: + - 0x91 + - 0x78 + - Value: 0x000000000000005D + - Value: 0x0000000000000001 + - Value: 0x0000000000000001 + - Value: 0x0000000000000060 + - AbbrCode: 0x00000003 + Values: + - Value: 0x0000000000000002 + BlockData: + - 0x91 + - 0x70 + - Value: 0x0000000000000062 + - Value: 0x0000000000000001 + - Value: 0x0000000000000001 + - Value: 0x0000000000000067 + - AbbrCode: 0x00000000 + Values: [] + - AbbrCode: 0x00000004 + Values: + - Value: 0x0000000000000059 + - Value: 0x0000000000000005 + - Value: 0x0000000000000004 + - AbbrCode: 0x00000005 + Values: + - Value: 0x000000000000006C + - AbbrCode: 0x00000005 + Values: + - Value: 0x0000000000000071 + - AbbrCode: 0x00000006 + Values: + - Value: 0x0000000000000076 + - AbbrCode: 0x00000004 + Values: + - Value: 0x0000000000000067 + - Value: 0x0000000000000006 + - Value: 0x0000000000000001 + - AbbrCode: 0x00000000 + Values: [] + debug_line: + - Length: + TotalLength: 68 + Version: 4 + PrologueLength: 40 + MinInstLength: 1 + MaxOpsPerInst: 1 + DefaultIsStmt: 1 + LineBase: 251 + LineRange: 14 + OpcodeBase: 13 + StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ] + IncludeDirs: + - './Trivial' + Files: + - Name: main.c + DirIdx: 1 + ModTime: 0 + Length: 0 + Opcodes: + - Opcode: DW_LNS_extended_op + ExtLen: 9 + SubOpcode: DW_LNE_set_address + Data: 0 + - Opcode: DW_LNS_copy + Data: 0 + - Opcode: DW_LNS_set_column + Data: 3 + - Opcode: DW_LNS_set_prologue_end + Data: 3 + - Opcode: DW_LNS_const_add_pc + Data: 3 + - Opcode: 0x3D + Data: 3 + - Opcode: DW_LNS_advance_pc + Data: 2 + - Opcode: DW_LNS_extended_op + ExtLen: 1 + SubOpcode: DW_LNE_end_sequence + Data: 2 +... diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/stats_api/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/stats_api/Makefile new file mode 100644 index 00000000000..c9319d6e688 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/stats_api/Makefile @@ -0,0 +1,2 @@ +C_SOURCES := main.c +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/stats_api/TestStatisticsAPI.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/stats_api/TestStatisticsAPI.py new file mode 100644 index 00000000000..d4903b5269a --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/stats_api/TestStatisticsAPI.py @@ -0,0 +1,34 @@ +# Test the SBAPI for GetStatistics() + +import json +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestStatsAPI(TestBase): + mydir = TestBase.compute_mydir(__file__) + + def test_stats_api(self): + self.build() + exe = self.getBuildArtifact("a.out") + target = self.dbg.CreateTarget(exe) + + # Test enabling/disabling stats + self.assertFalse(target.GetCollectingStats()) + target.SetCollectingStats(True) + self.assertTrue(target.GetCollectingStats()) + target.SetCollectingStats(False) + self.assertFalse(target.GetCollectingStats()) + + # Test the function to get the statistics in JSON'ish. + stats = target.GetStatistics() + stream = lldb.SBStream() + res = stats.GetAsJSON(stream) + stats_json = sorted(json.loads(stream.GetData())) + self.assertEqual(len(stats_json), 4) + self.assertTrue("Number of expr evaluation failures" in stats_json) + self.assertTrue("Number of expr evaluation successes" in stats_json) + self.assertTrue("Number of frame var failures" in stats_json) + self.assertTrue("Number of frame var successes" in stats_json) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/stats_api/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/stats_api/main.c new file mode 100644 index 00000000000..03b2213bb9a --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/stats_api/main.c @@ -0,0 +1,3 @@ +int main(void) { + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/step-avoids-no-debug/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/step-avoids-no-debug/Makefile new file mode 100644 index 00000000000..374e58b89a8 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/step-avoids-no-debug/Makefile @@ -0,0 +1,6 @@ +C_SOURCES := with-debug.c without-debug.c + +include Makefile.rules + +without-debug.o: without-debug.c + $(CC) $(CFLAGS_NO_DEBUG) -c $< diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/step-avoids-no-debug/TestStepNoDebug.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/step-avoids-no-debug/TestStepNoDebug.py new file mode 100644 index 00000000000..629efb5d99b --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/step-avoids-no-debug/TestStepNoDebug.py @@ -0,0 +1,152 @@ +""" +Test thread step-in, step-over and step-out work with the "Avoid no debug" option. +""" + + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class StepAvoidsNoDebugTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @add_test_categories(['pyapi']) + def test_step_out_with_python(self): + """Test stepping out using avoid-no-debug with dsyms.""" + self.build() + self.get_to_starting_point() + self.do_step_out_past_nodebug() + + @add_test_categories(['pyapi']) + @decorators.expectedFailureAll( + compiler="gcc", bugnumber="llvm.org/pr28549") + @decorators.expectedFailureAll( + compiler="clang", + compiler_version=[ + ">=", + "3.9"], + archs=["i386"], + bugnumber="llvm.org/pr28549") + def test_step_over_with_python(self): + """Test stepping over using avoid-no-debug with dwarf.""" + self.build() + self.get_to_starting_point() + self.do_step_over_past_nodebug() + + @add_test_categories(['pyapi']) + @decorators.expectedFailureAll( + compiler="gcc", bugnumber="llvm.org/pr28549") + @decorators.expectedFailureAll( + compiler="clang", + compiler_version=[ + ">=", + "3.9"], + archs=["i386"], + bugnumber="llvm.org/pr28549") + @expectedFailureAll(oslist=["ios", "tvos", "bridgeos"], bugnumber="<rdar://problem/34026777>") # lldb doesn't step past last source line in function on arm64 + @expectedFailureAll(archs=["aarch64"], oslist=["linux"], + bugnumber="llvm.org/pr44057") + def test_step_in_with_python(self): + """Test stepping in using avoid-no-debug with dwarf.""" + self.build() + self.get_to_starting_point() + self.do_step_in_past_nodebug() + + def setUp(self): + TestBase.setUp(self) + self.main_source = "with-debug.c" + self.main_source_spec = lldb.SBFileSpec("with-debug.c") + self.dbg.HandleCommand( + "settings set target.process.thread.step-out-avoid-nodebug true") + + def tearDown(self): + self.dbg.HandleCommand( + "settings set target.process.thread.step-out-avoid-nodebug false") + TestBase.tearDown(self) + + def hit_correct_line(self, pattern): + target_line = line_number(self.main_source, pattern) + self.assertTrue( + target_line != 0, + "Could not find source pattern " + + pattern) + cur_line = self.thread.frames[0].GetLineEntry().GetLine() + self.assertTrue( + cur_line == target_line, + "Stepped to line %d instead of expected %d with pattern '%s'." % + (cur_line, + target_line, + pattern)) + + def hit_correct_function(self, pattern): + name = self.thread.frames[0].GetFunctionName() + self.assertTrue( + pattern in name, "Got to '%s' not the expected function '%s'." % + (name, pattern)) + + def get_to_starting_point(self): + exe = self.getBuildArtifact("a.out") + error = lldb.SBError() + + self.target = self.dbg.CreateTarget(exe) + self.assertTrue(self.target, VALID_TARGET) + + inner_bkpt = self.target.BreakpointCreateBySourceRegex( + "Stop here and step out of me", self.main_source_spec) + self.assertTrue(inner_bkpt, VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + self.process = self.target.LaunchSimple( + None, None, self.get_process_working_directory()) + + self.assertTrue(self.process, PROCESS_IS_VALID) + + # Now finish, and make sure the return value is correct. + threads = lldbutil.get_threads_stopped_at_breakpoint( + self.process, inner_bkpt) + self.assertTrue(len(threads) == 1, "Stopped at inner breakpoint.") + self.thread = threads[0] + + def do_step_out_past_nodebug(self): + # The first step out takes us to the called_from_nodebug frame, just to make sure setting + # step-out-avoid-nodebug doesn't change the behavior in frames with + # debug info. + self.thread.StepOut() + self.hit_correct_line( + "intermediate_return_value = called_from_nodebug_actual(some_value)") + self.thread.StepOut() + self.hit_correct_line( + "int return_value = no_debug_caller(5, called_from_nodebug)") + + def do_step_over_past_nodebug(self): + self.thread.StepOver() + self.hit_correct_line( + "intermediate_return_value = called_from_nodebug_actual(some_value)") + self.thread.StepOver() + self.hit_correct_line("return intermediate_return_value") + self.thread.StepOver() + # Note, lldb doesn't follow gdb's distinction between "step-out" and "step-over/step-in" + # when exiting a frame. In all cases we leave the pc at the point where we exited the + # frame. In gdb, step-over/step-in move to the end of the line they stepped out to. + # If we ever change this we will need to fix this test. + self.hit_correct_line( + "int return_value = no_debug_caller(5, called_from_nodebug)") + + def do_step_in_past_nodebug(self): + self.thread.StepInto() + self.hit_correct_line( + "intermediate_return_value = called_from_nodebug_actual(some_value)") + self.thread.StepInto() + self.hit_correct_line("return intermediate_return_value") + self.thread.StepInto() + # Note, lldb doesn't follow gdb's distinction between "step-out" and "step-over/step-in" + # when exiting a frame. In all cases we leave the pc at the point where we exited the + # frame. In gdb, step-over/step-in move to the end of the line they stepped out to. + # If we ever change this we will need to fix this test. + self.hit_correct_line( + "int return_value = no_debug_caller(5, called_from_nodebug)") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/step-avoids-no-debug/with-debug.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/step-avoids-no-debug/with-debug.c new file mode 100644 index 00000000000..c7ac309d2c1 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/step-avoids-no-debug/with-debug.c @@ -0,0 +1,29 @@ +#include <stdio.h> + +typedef int (*debug_callee) (int); + +extern int no_debug_caller (int, debug_callee); + +int +called_from_nodebug_actual(int some_value) +{ + int return_value = 0; + return_value = printf ("Length: %d.\n", some_value); + return return_value; // Stop here and step out of me +} + +int +called_from_nodebug(int some_value) +{ + int intermediate_return_value = 0; + intermediate_return_value = called_from_nodebug_actual(some_value); + return intermediate_return_value; +} + +int +main() +{ + int return_value = no_debug_caller(5, called_from_nodebug); + printf ("I got: %d.\n", return_value); + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/step-avoids-no-debug/without-debug.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/step-avoids-no-debug/without-debug.c new file mode 100644 index 00000000000..d71d74af5e9 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/step-avoids-no-debug/without-debug.c @@ -0,0 +1,17 @@ +typedef int (*debug_callee) (int); + +int +no_debug_caller_intermediate(int input, debug_callee callee) +{ + int return_value = 0; + return_value = callee(input); + return return_value; +} + +int +no_debug_caller (int input, debug_callee callee) +{ + int return_value = 0; + return_value = no_debug_caller_intermediate (input, callee); + return return_value; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/step_scripted/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/step_scripted/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/step_scripted/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/step_scripted/Steps.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/step_scripted/Steps.py new file mode 100644 index 00000000000..4133cbbe608 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/step_scripted/Steps.py @@ -0,0 +1,83 @@ +import lldb + +class StepWithChild: + def __init__(self, thread_plan): + self.thread_plan = thread_plan + self.child_thread_plan = self.queue_child_thread_plan() + + def explains_stop(self, event): + return False + + def should_stop(self, event): + if not self.child_thread_plan.IsPlanComplete(): + return False + + self.thread_plan.SetPlanComplete(True) + + return True + + def should_step(self): + return False + + def queue_child_thread_plan(self): + return None + +class StepOut(StepWithChild): + def __init__(self, thread_plan, dict): + StepWithChild.__init__(self, thread_plan) + + def queue_child_thread_plan(self): + return self.thread_plan.QueueThreadPlanForStepOut(0) + +class StepScripted(StepWithChild): + def __init__(self, thread_plan, dict): + StepWithChild.__init__(self, thread_plan) + + def queue_child_thread_plan(self): + return self.thread_plan.QueueThreadPlanForStepScripted("Steps.StepOut") + +# This plan does a step-over until a variable changes value. +class StepUntil(StepWithChild): + def __init__(self, thread_plan, args_data, dict): + self.frame = thread_plan.GetThread().frames[0] + self.target = thread_plan.GetThread().GetProcess().GetTarget() + func_entry = args_data.GetValueForKey("variable_name") + + if not func_entry.IsValid(): + print("Did not get a valid entry for variable_name") + func_name = func_entry.GetStringValue(100) + + self.value = self.frame.FindVariable(func_name) + if self.value.GetError().Fail(): + print("Failed to get foo value: %s"%(self.value.GetError().GetCString())) + else: + print("'foo' value: %d"%(self.value.GetValueAsUnsigned())) + + StepWithChild.__init__(self, thread_plan) + + + def queue_child_thread_plan(self): + le = self.frame.GetLineEntry() + start_addr = le.GetStartAddress() + start = start_addr.GetLoadAddress(self.target) + end = le.GetEndAddress().GetLoadAddress(self.target) + return self.thread_plan.QueueThreadPlanForStepOverRange(start_addr, + end - start) + + def should_stop(self, event): + if not self.child_thread_plan.IsPlanComplete(): + return False + + # If we've stepped out of this frame, stop. + if not self.frame.IsValid(): + return True + + if not self.value.IsValid(): + return True + + print("Got next value: %d"%(self.value.GetValueAsUnsigned())) + if not self.value.GetValueDidChange(): + self.child_thread_plan = self.queue_child_thread_plan() + return False + else: + return True diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/step_scripted/TestStepScripted.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/step_scripted/TestStepScripted.py new file mode 100644 index 00000000000..eb1b5822580 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/step_scripted/TestStepScripted.py @@ -0,0 +1,108 @@ +""" +Tests stepping with scripted thread plans. +""" + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class StepScriptedTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + def setUp(self): + TestBase.setUp(self) + self.main_source_file = lldb.SBFileSpec("main.c") + self.runCmd("command script import Steps.py") + + def test_standard_step_out(self): + """Tests stepping with the scripted thread plan laying over a standard + thread plan for stepping out.""" + self.build() + self.step_out_with_scripted_plan("Steps.StepOut") + + def test_scripted_step_out(self): + """Tests stepping with the scripted thread plan laying over an another + scripted thread plan for stepping out.""" + self.build() + self.step_out_with_scripted_plan("Steps.StepScripted") + + def step_out_with_scripted_plan(self, name): + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + "Set a breakpoint here", + self.main_source_file) + + frame = thread.GetFrameAtIndex(0) + self.assertEqual("foo", frame.GetFunctionName()) + + err = thread.StepUsingScriptedThreadPlan(name) + self.assertTrue(err.Success(), err.GetCString()) + + frame = thread.GetFrameAtIndex(0) + self.assertEqual("main", frame.GetFunctionName()) + + + def test_misspelled_plan_name(self): + """Test that we get a useful error if we misspell the plan class name""" + self.build() + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + "Set a breakpoint here", + self.main_source_file) + stop_id = process.GetStopID() + # Pass a non-existent class for the plan class: + err = thread.StepUsingScriptedThreadPlan("NoSuchModule.NoSuchPlan") + + # Make sure we got a good error: + self.assertTrue(err.Fail(), "We got a failure state") + msg = err.GetCString() + self.assertTrue("NoSuchModule.NoSuchPlan" in msg, "Mentioned missing class") + + # Make sure we didn't let the process run: + self.assertEqual(stop_id, process.GetStopID(), "Process didn't run") + + def test_checking_variable(self): + """Test that we can call SBValue API's from a scripted thread plan - using SBAPI's to step""" + self.do_test_checking_variable(False) + + def test_checking_variable_cli(self): + """Test that we can call SBValue API's from a scripted thread plan - using cli to step""" + self.do_test_checking_variable(True) + + def do_test_checking_variable(self, use_cli): + self.build() + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + "Set a breakpoint here", + self.main_source_file) + + frame = thread.GetFrameAtIndex(0) + self.assertEqual("foo", frame.GetFunctionName()) + foo_val = frame.FindVariable("foo") + self.assertTrue(foo_val.GetError().Success(), "Got the foo variable") + self.assertEqual(foo_val.GetValueAsUnsigned(), 10, "foo starts at 10") + + if use_cli: + result = lldb.SBCommandReturnObject() + self.dbg.GetCommandInterpreter().HandleCommand( + "thread step-scripted -C Steps.StepUntil -k variable_name -v foo", + result) + self.assertTrue(result.Succeeded()) + else: + args_data = lldb.SBStructuredData() + data = lldb.SBStream() + data.Print('{"variable_name" : "foo"}') + error = args_data.SetFromJSON(data) + self.assertTrue(error.Success(), "Made the args_data correctly") + + err = thread.StepUsingScriptedThreadPlan("Steps.StepUntil", args_data, True) + self.assertTrue(err.Success(), err.GetCString()) + + # We should not have exited: + self.assertEqual(process.GetState(), lldb.eStateStopped, "We are stopped") + + # We should still be in foo: + self.assertEqual("foo", frame.GetFunctionName()) + + # And foo should have changed: + self.assertTrue(foo_val.GetValueDidChange(), "Foo changed") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/step_scripted/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/step_scripted/main.c new file mode 100644 index 00000000000..bfd8a35d556 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/step_scripted/main.c @@ -0,0 +1,13 @@ +#include <stdio.h> + +void foo() { + int foo = 10; + printf("%d\n", foo); // Set a breakpoint here. + foo = 20; + printf("%d\n", foo); +} + +int main() { + foo(); + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/Makefile new file mode 100644 index 00000000000..666a6c36554 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/Makefile @@ -0,0 +1,4 @@ +CXX_SOURCES := main.cpp + +CXXFLAGS_EXTRAS := -g -O2 -glldb +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/TestAmbiguousTailCallSeq1.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/TestAmbiguousTailCallSeq1.py new file mode 100644 index 00000000000..fbd629672be --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/TestAmbiguousTailCallSeq1.py @@ -0,0 +1,6 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), + [decorators.skipUnlessHasCallSiteInfo, + decorators.skipIf(dwarf_version=['<', '4'])]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/main.cpp new file mode 100644 index 00000000000..b59c063ade2 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/main.cpp @@ -0,0 +1,32 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +volatile int x; + +void __attribute__((noinline)) sink() { + x++; //% self.filecheck("bt", "main.cpp") + // CHECK-NOT: func{{[23]}}_amb +} + +void __attribute__((noinline)) func3_amb() { sink(); /* tail */ } + +void __attribute__((noinline)) func2_amb() { sink(); /* tail */ } + +void __attribute__((noinline)) func1() { + if (x > 0) + func2_amb(); /* tail */ + else + func3_amb(); /* tail */ +} + +int __attribute__((disable_tail_calls)) main(int argc, char **) { + // The sequences `main -> func1 -> f{2,3}_amb -> sink` are both plausible. Test + // that lldb doesn't attempt to guess which one occurred. + func1(); + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/Makefile new file mode 100644 index 00000000000..666a6c36554 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/Makefile @@ -0,0 +1,4 @@ +CXX_SOURCES := main.cpp + +CXXFLAGS_EXTRAS := -g -O2 -glldb +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/TestAmbiguousTailCallSeq2.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/TestAmbiguousTailCallSeq2.py new file mode 100644 index 00000000000..fbd629672be --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/TestAmbiguousTailCallSeq2.py @@ -0,0 +1,6 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), + [decorators.skipUnlessHasCallSiteInfo, + decorators.skipIf(dwarf_version=['<', '4'])]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/main.cpp new file mode 100644 index 00000000000..21c89199b9f --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/main.cpp @@ -0,0 +1,37 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +volatile int x; + +void __attribute__((noinline)) sink() { + x++; //% self.filecheck("bt", "main.cpp") + // CHECK-NOT: func{{[23]}} +} + +void func2(); + +void __attribute__((noinline)) func1() { + if (x < 1) + func2(); + else + sink(); +} + +void __attribute__((noinline)) func2() { + if (x < 1) + sink(); + else + func1(); +} + +int main() { + // Tail recursion creates ambiguous execution histories. + x = 0; + func1(); + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/Makefile new file mode 100644 index 00000000000..666a6c36554 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/Makefile @@ -0,0 +1,4 @@ +CXX_SOURCES := main.cpp + +CXXFLAGS_EXTRAS := -g -O2 -glldb +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/TestDisambiguateCallSite.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/TestDisambiguateCallSite.py new file mode 100644 index 00000000000..fbd629672be --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/TestDisambiguateCallSite.py @@ -0,0 +1,6 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), + [decorators.skipUnlessHasCallSiteInfo, + decorators.skipIf(dwarf_version=['<', '4'])]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/main.cpp new file mode 100644 index 00000000000..d4578c67a26 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/main.cpp @@ -0,0 +1,31 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +volatile int x; + +void __attribute__((noinline)) sink() { + x++; //% self.filecheck("bt", "main.cpp", "-implicit-check-not=artificial") + // CHECK: frame #0: 0x{{[0-9a-f]+}} a.out`sink() at main.cpp:[[@LINE-1]]:4 [opt] + // CHECK-NEXT: func2{{.*}} [opt] [artificial] + // CHECK-NEXT: main{{.*}} [opt] +} + +void __attribute__((noinline)) func2() { + sink(); /* tail */ +} + +void __attribute__((noinline)) func1() { sink(); /* tail */ } + +int __attribute__((disable_tail_calls)) main(int argc, char **) { + // The sequences `main -> f{1,2} -> sink` are both plausible. Test that + // return-pc call site info allows lldb to pick the correct sequence. + func2(); + if (argc == 100) + func1(); + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/Makefile new file mode 100644 index 00000000000..666a6c36554 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/Makefile @@ -0,0 +1,4 @@ +CXX_SOURCES := main.cpp + +CXXFLAGS_EXTRAS := -g -O2 -glldb +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/TestDisambiguatePathsToCommonSink.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/TestDisambiguatePathsToCommonSink.py new file mode 100644 index 00000000000..fbd629672be --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/TestDisambiguatePathsToCommonSink.py @@ -0,0 +1,6 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), + [decorators.skipUnlessHasCallSiteInfo, + decorators.skipIf(dwarf_version=['<', '4'])]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/main.cpp new file mode 100644 index 00000000000..6284ef40811 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/main.cpp @@ -0,0 +1,37 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +volatile int x; + +void __attribute__((noinline)) sink2() { + x++; //% self.filecheck("bt", "main.cpp", "-check-prefix=FROM-FUNC1") + // FROM-FUNC1: frame #0: 0x{{[0-9a-f]+}} a.out`sink{{.*}} at main.cpp:[[@LINE-1]]:{{.*}} [opt] + // FROM-FUNC1-NEXT: sink({{.*}} [opt] + // FROM-FUNC1-NEXT: func1{{.*}} [opt] [artificial] + // FROM-FUNC1-NEXT: main{{.*}} [opt] +} + +void __attribute__((noinline)) sink(bool called_from_main) { + if (called_from_main) { + x++; //% self.filecheck("bt", "main.cpp", "-check-prefix=FROM-MAIN") + // FROM-MAIN: frame #0: 0x{{[0-9a-f]+}} a.out`sink{{.*}} at main.cpp:[[@LINE-1]]:{{.*}} [opt] + // FROM-MAIN-NEXT: main{{.*}} [opt] + } else { + sink2(); + } +} + +void __attribute__((noinline)) func1() { sink(false); /* tail */ } + +int __attribute__((disable_tail_calls)) main(int argc, char **) { + // When func1 tail-calls sink, make sure that the former appears in the + // backtrace. + sink(true); + func1(); + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/Makefile new file mode 100644 index 00000000000..666a6c36554 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/Makefile @@ -0,0 +1,4 @@ +CXX_SOURCES := main.cpp + +CXXFLAGS_EXTRAS := -g -O2 -glldb +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/TestDisambiguateTailCallSeq.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/TestDisambiguateTailCallSeq.py new file mode 100644 index 00000000000..fbd629672be --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/TestDisambiguateTailCallSeq.py @@ -0,0 +1,6 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), + [decorators.skipUnlessHasCallSiteInfo, + decorators.skipIf(dwarf_version=['<', '4'])]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/main.cpp new file mode 100644 index 00000000000..7816385dda0 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/main.cpp @@ -0,0 +1,30 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +volatile int x; + +void __attribute__((noinline)) sink() { + x++; //% self.filecheck("bt", "main.cpp", "-implicit-check-not=artificial") + // CHECK: frame #0: 0x{{[0-9a-f]+}} a.out`sink() at main.cpp:[[@LINE-1]]:4 [opt] + // CHECK-NEXT: func3{{.*}} [opt] [artificial] + // CHECK-NEXT: func1{{.*}} [opt] [artificial] + // CHECK-NEXT: main{{.*}} [opt] +} + +void __attribute__((noinline)) func3() { sink(); /* tail */ } + +void __attribute__((noinline)) func2() { sink(); /* tail */ } + +void __attribute__((noinline)) func1() { func3(); /* tail */ } + +int __attribute__((disable_tail_calls)) main(int argc, char **) { + // The sequences `main -> func1 -> f{2,3} -> sink` are both plausible. Test + // that lldb picks the latter sequence. + func1(); + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/Makefile new file mode 100644 index 00000000000..666a6c36554 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/Makefile @@ -0,0 +1,4 @@ +CXX_SOURCES := main.cpp + +CXXFLAGS_EXTRAS := -g -O2 -glldb +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/TestInliningAndTailCalls.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/TestInliningAndTailCalls.py new file mode 100644 index 00000000000..fbd629672be --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/TestInliningAndTailCalls.py @@ -0,0 +1,6 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), + [decorators.skipUnlessHasCallSiteInfo, + decorators.skipIf(dwarf_version=['<', '4'])]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/main.cpp new file mode 100644 index 00000000000..a592d51169d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/main.cpp @@ -0,0 +1,49 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +volatile int x; + +void __attribute__((noinline)) tail_call_sink() { + x++; //% self.filecheck("bt", "main.cpp", "-check-prefix=TAIL-CALL-SINK") + // TAIL-CALL-SINK: frame #0: 0x{{[0-9a-f]+}} a.out`tail_call_sink() at main.cpp:[[@LINE-1]]:4 [opt] + // TAIL-CALL-SINK-NEXT: func3{{.*}} [opt] [artificial] + // TAIL-CALL-SINK-NEXT: main{{.*}} [opt] + + // TODO: The backtrace should include inlinable_function_which_tail_calls. +} + +void __attribute__((always_inline)) inlinable_function_which_tail_calls() { + tail_call_sink(); +} + +void __attribute__((noinline)) func3() { + inlinable_function_which_tail_calls(); +} + +void __attribute__((always_inline)) inline_sink() { + x++; //% self.filecheck("bt", "main.cpp", "-check-prefix=INLINE-SINK") + // INLINE-SINK: frame #0: 0x{{[0-9a-f]+}} a.out`func2() [inlined] inline_sink() at main.cpp:[[@LINE-1]]:4 [opt] + // INLINE-SINK-NEXT: func2{{.*}} [opt] + // INLINE-SINK-NEXT: func1{{.*}} [opt] [artificial] + // INLINE-SINK-NEXT: main{{.*}} [opt] +} + +void __attribute__((noinline)) func2() { inline_sink(); /* inlined */ } + +void __attribute__((noinline)) func1() { func2(); /* tail */ } + +int __attribute__((disable_tail_calls)) main() { + // First, call a function that tail-calls a function, which itself inlines + // a third function. + func1(); + + // Next, call a function which contains an inlined tail-call. + func3(); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/Makefile new file mode 100644 index 00000000000..666a6c36554 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/Makefile @@ -0,0 +1,4 @@ +CXX_SOURCES := main.cpp + +CXXFLAGS_EXTRAS := -g -O2 -glldb +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/TestTailCallFrameSBAPI.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/TestTailCallFrameSBAPI.py new file mode 100644 index 00000000000..e597b8d1696 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/TestTailCallFrameSBAPI.py @@ -0,0 +1,65 @@ +""" +Test SB API support for identifying artificial (tail call) frames. +""" + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * + +class TestTailCallFrameSBAPI(TestBase): + mydir = TestBase.compute_mydir(__file__) + + @skipIf(compiler="clang", compiler_version=['<', '8.0']) + @skipIf(dwarf_version=['<', '4']) + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr26265") + def test_tail_call_frame_sbapi(self): + self.build() + self.do_test() + + def do_test(self): + exe = self.getBuildArtifact("a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + breakpoint = target.BreakpointCreateBySourceRegex("break here", + lldb.SBFileSpec("main.cpp")) + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + error = lldb.SBError() + launch_info = lldb.SBLaunchInfo(None) + process = target.Launch(launch_info, error) + self.assertTrue(process, PROCESS_IS_VALID) + + # Did we hit our breakpoint? + threads = lldbutil.get_threads_stopped_at_breakpoint(process, + breakpoint) + self.assertEqual( + len(threads), 1, + "There should be a thread stopped at our breakpoint") + + self.assertEqual(breakpoint.GetHitCount(), 1) + + thread = threads[0] + + # Here's what we expect to see in the backtrace: + # frame #0: ... a.out`sink() at main.cpp:13:4 [opt] + # frame #1: ... a.out`func3() at main.cpp:14:1 [opt] [artificial] + # frame #2: ... a.out`func2() at main.cpp:18:62 [opt] + # frame #3: ... a.out`func1() at main.cpp:18:85 [opt] [artificial] + # frame #4: ... a.out`main at main.cpp:23:3 [opt] + names = ["sink", "func3", "func2", "func1", "main"] + artificiality = [False, True, False, True, False] + for idx, (name, is_artificial) in enumerate(zip(names, artificiality)): + frame = thread.GetFrameAtIndex(idx) + + # Use a relaxed substring check because function dislpay names are + # platform-dependent. E.g we see "void sink(void)" on Windows, but + # "sink()" on Darwin. This seems like a bug -- just work around it + # for now. + self.assertTrue(name in frame.GetDisplayFunctionName()) + self.assertEqual(frame.IsArtificial(), is_artificial) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/main.cpp new file mode 100644 index 00000000000..5a2775b0dea --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/main.cpp @@ -0,0 +1,24 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +volatile int x; + +void __attribute__((noinline)) sink() { + x++; /* break here */ +} + +void __attribute__((noinline)) func3() { sink(); /* tail */ } + +void __attribute__((disable_tail_calls, noinline)) func2() { func3(); /* regular */ } + +void __attribute__((noinline)) func1() { func2(); /* tail */ } + +int __attribute__((disable_tail_calls)) main() { + func1(); /* regular */ + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/Makefile new file mode 100644 index 00000000000..666a6c36554 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/Makefile @@ -0,0 +1,4 @@ +CXX_SOURCES := main.cpp + +CXXFLAGS_EXTRAS := -g -O2 -glldb +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/TestArtificialFrameStepOutMessage.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/TestArtificialFrameStepOutMessage.py new file mode 100644 index 00000000000..fbd629672be --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/TestArtificialFrameStepOutMessage.py @@ -0,0 +1,6 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), + [decorators.skipUnlessHasCallSiteInfo, + decorators.skipIf(dwarf_version=['<', '4'])]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/main.cpp new file mode 100644 index 00000000000..df43bcc98ea --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/main.cpp @@ -0,0 +1,27 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +volatile int x; + +void __attribute__((noinline)) sink() { + x++; //% self.filecheck("finish", "main.cpp", "-implicit-check-not=artificial") + // CHECK: stop reason = step out + // CHECK-NEXT: Stepped out past: frame #1: 0x{{[0-9a-f]+}} a.out`func3{{.*}} [opt] [artificial] + // CHECK: frame #0: 0x{{[0-9a-f]+}} a.out`func2{{.*}} [opt] +} + +void __attribute__((noinline)) func3() { sink(); /* tail */ } + +void __attribute__((disable_tail_calls, noinline)) func2() { func3(); /* regular */ } + +void __attribute__((noinline)) func1() { func2(); /* tail */ } + +int __attribute__((disable_tail_calls)) main() { + func1(); /* regular */ + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/Makefile new file mode 100644 index 00000000000..666a6c36554 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/Makefile @@ -0,0 +1,4 @@ +CXX_SOURCES := main.cpp + +CXXFLAGS_EXTRAS := -g -O2 -glldb +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/TestSteppingOutWithArtificialFrames.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/TestSteppingOutWithArtificialFrames.py new file mode 100644 index 00000000000..24fc2ba6956 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/TestSteppingOutWithArtificialFrames.py @@ -0,0 +1,92 @@ +""" +Test SB API support for identifying artificial (tail call) frames. +""" + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * + +class TestArtificialFrameThreadStepOut1(TestBase): + mydir = TestBase.compute_mydir(__file__) + + # If your test case doesn't stress debug info, the + # set this to true. That way it won't be run once for + # each debug info format. + NO_DEBUG_INFO_TESTCASE = True + + def prepare_thread(self): + exe = self.getBuildArtifact("a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + breakpoint = target.BreakpointCreateBySourceRegex("break here", + lldb.SBFileSpec("main.cpp")) + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + error = lldb.SBError() + launch_info = lldb.SBLaunchInfo(None) + process = target.Launch(launch_info, error) + self.assertTrue(process, PROCESS_IS_VALID) + + # Did we hit our breakpoint? + threads = lldbutil.get_threads_stopped_at_breakpoint(process, + breakpoint) + self.assertEqual( + len(threads), 1, + "There should be a thread stopped at our breakpoint") + + self.assertEqual(breakpoint.GetHitCount(), 1) + + thread = threads[0] + + # Here's what we expect to see in the backtrace: + # frame #0: ... a.out`sink() at main.cpp:13:4 [opt] + # frame #1: ... a.out`func3() at main.cpp:14:1 [opt] [artificial] + # frame #2: ... a.out`func2() at main.cpp:18:62 [opt] + # frame #3: ... a.out`func1() at main.cpp:18:85 [opt] [artificial] + # frame #4: ... a.out`main at main.cpp:23:3 [opt] + return thread + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr26265") + def test_stepping_out_past_artificial_frame(self): + self.build() + thread = self.prepare_thread() + + # Frame #0's ancestor is artificial. Stepping out should move to + # frame #2, because we behave as-if artificial frames were not present. + thread.StepOut() + frame2 = thread.GetSelectedFrame() + self.assertEqual(frame2.GetDisplayFunctionName(), "func2()") + self.assertFalse(frame2.IsArtificial()) + + # Ditto: stepping out of frame #2 should move to frame #4. + thread.StepOut() + frame4 = thread.GetSelectedFrame() + self.assertEqual(frame4.GetDisplayFunctionName(), "main") + self.assertFalse(frame2.IsArtificial()) + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr26265") + def test_return_past_artificial_frame(self): + self.build() + thread = self.prepare_thread() + + value = lldb.SBValue() + + # Frame #0's ancestor is artificial. Returning from frame #0 should move + # to frame #2. + thread.ReturnFromFrame(thread.GetSelectedFrame(), value) + frame2 = thread.GetSelectedFrame() + self.assertEqual(frame2.GetDisplayFunctionName(), "func2()") + self.assertFalse(frame2.IsArtificial()) + + # Ditto: stepping out of frame #2 should move to frame #4. + thread.ReturnFromFrame(thread.GetSelectedFrame(), value) + frame4 = thread.GetSelectedFrame() + self.assertEqual(frame4.GetDisplayFunctionName(), "main") + self.assertFalse(frame2.IsArtificial()) + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/main.cpp new file mode 100644 index 00000000000..4a647031ef1 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/main.cpp @@ -0,0 +1,24 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +volatile int x; + +void __attribute__((noinline)) sink() { + x++; // break here +} + +void __attribute__((noinline)) func3() { sink(); /* tail */ } + +void __attribute__((disable_tail_calls, noinline)) func2() { func3(); /* regular */ } + +void __attribute__((noinline)) func1() { func2(); /* tail */ } + +int __attribute__((disable_tail_calls)) main() { + func1(); /* regular */ + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/Makefile new file mode 100644 index 00000000000..666a6c36554 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/Makefile @@ -0,0 +1,4 @@ +CXX_SOURCES := main.cpp + +CXXFLAGS_EXTRAS := -g -O2 -glldb +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/TestUnambiguousTailCalls.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/TestUnambiguousTailCalls.py new file mode 100644 index 00000000000..fbd629672be --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/TestUnambiguousTailCalls.py @@ -0,0 +1,6 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), + [decorators.skipUnlessHasCallSiteInfo, + decorators.skipIf(dwarf_version=['<', '4'])]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/main.cpp new file mode 100644 index 00000000000..edfe59777c6 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/main.cpp @@ -0,0 +1,29 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +volatile int x; + +void __attribute__((noinline)) sink() { + x++; //% self.filecheck("bt", "main.cpp", "-implicit-check-not=artificial") + // CHECK: frame #0: 0x{{[0-9a-f]+}} a.out`sink() at main.cpp:[[@LINE-1]]:4 [opt] + // CHECK-NEXT: frame #1: 0x{{[0-9a-f]+}} a.out`func3{{.*}} [opt] [artificial] + // CHECK-NEXT: frame #2: 0x{{[0-9a-f]+}} a.out`func2{{.*}} [opt] + // CHECK-NEXT: frame #3: 0x{{[0-9a-f]+}} a.out`func1{{.*}} [opt] [artificial] + // CHECK-NEXT: frame #4: 0x{{[0-9a-f]+}} a.out`main{{.*}} [opt] +} + +void __attribute__((noinline)) func3() { sink(); /* tail */ } + +void __attribute__((disable_tail_calls, noinline)) func2() { func3(); /* regular */ } + +void __attribute__((noinline)) func1() { func2(); /* tail */ } + +int __attribute__((disable_tail_calls)) main() { + func1(); /* regular */ + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/target-new-solib-notifications/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/target-new-solib-notifications/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/target-new-solib-notifications/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/target-new-solib-notifications/TestModuleLoadedNotifys.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/target-new-solib-notifications/TestModuleLoadedNotifys.py new file mode 100644 index 00000000000..b3db5f7a85d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/target-new-solib-notifications/TestModuleLoadedNotifys.py @@ -0,0 +1,111 @@ +""" +Test how many times newly loaded binaries are notified; +they should be delivered in batches instead of one-by-one. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class ModuleLoadedNotifysTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + # DyanmicLoaderDarwin should batch up notifications about + # newly added/removed libraries. Other DynamicLoaders may + # not be written this way. + @skipUnlessDarwin + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.line = line_number('main.cpp', '// breakpoint') + + def test_launch_notifications(self): + """Test that lldb broadcasts newly loaded libraries in batches.""" + self.build() + exe = self.getBuildArtifact("a.out") + self.dbg.SetAsync(False) + + listener = self.dbg.GetListener() + listener.StartListeningForEventClass( + self.dbg, + lldb.SBTarget.GetBroadcasterClassName(), + lldb.SBTarget.eBroadcastBitModulesLoaded | lldb.SBTarget.eBroadcastBitModulesUnloaded) + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # break on main + breakpoint = target.BreakpointCreateByName('main', 'a.out') + + event = lldb.SBEvent() + # CreateTarget() generated modules-loaded events; consume them & toss + while listener.GetNextEvent(event): + True + + error = lldb.SBError() + process = target.Launch(listener, + None, # argv + None, # envp + None, # stdin_path + None, # stdout_path + None, # stderr_path + None, # working directory + 0, # launch flags + False, # Stop at entry + error) # error + + self.assertTrue( + process.GetState() == lldb.eStateStopped, + PROCESS_STOPPED) + + total_solibs_added = 0 + total_solibs_removed = 0 + total_modules_added_events = 0 + total_modules_removed_events = 0 + while listener.GetNextEvent(event): + if lldb.SBTarget.EventIsTargetEvent(event): + if event.GetType() == lldb.SBTarget.eBroadcastBitModulesLoaded: + solib_count = lldb.SBTarget.GetNumModulesFromEvent(event) + total_modules_added_events += 1 + total_solibs_added += solib_count + if self.TraceOn(): + # print all of the binaries that have been added + added_files = [] + i = 0 + while i < solib_count: + module = lldb.SBTarget.GetModuleAtIndexFromEvent(i, event) + added_files.append(module.GetFileSpec().GetFilename()) + i = i + 1 + print("Loaded files: %s" % (', '.join(added_files))) + + if event.GetType() == lldb.SBTarget.eBroadcastBitModulesUnloaded: + solib_count = lldb.SBTarget.GetNumModulesFromEvent(event) + total_modules_removed_events += 1 + total_solibs_removed += solib_count + if self.TraceOn(): + # print all of the binaries that have been removed + removed_files = [] + i = 0 + while i < solib_count: + module = lldb.SBTarget.GetModuleAtIndexFromEvent(i, event) + removed_files.append(module.GetFileSpec().GetFilename()) + i = i + 1 + print("Unloaded files: %s" % (', '.join(removed_files))) + + + # This is testing that we get back a small number of events with the loaded + # binaries in batches. Check that we got back more than 1 solib per event. + # In practice on Darwin today, we get back two events for a do-nothing c + # program: a.out and dyld, and then all the rest of the system libraries. + + avg_solibs_added_per_event = int(float(total_solibs_added) / float(total_modules_added_events)) + self.assertGreater(avg_solibs_added_per_event, 1) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/target-new-solib-notifications/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/target-new-solib-notifications/main.cpp new file mode 100644 index 00000000000..00130c93b88 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/target-new-solib-notifications/main.cpp @@ -0,0 +1,6 @@ +#include <stdio.h> +int main () +{ + puts("running"); // breakpoint here + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/target_var/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/target_var/Makefile new file mode 100644 index 00000000000..806c96740af --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/target_var/Makefile @@ -0,0 +1,8 @@ +include Makefile.rules + +a.out: globals.ll + $(CC) $(CFLAGS) -g -c $^ -o globals.o + $(LD) $(LDFLAGS) -g globals.o -o $@ + +clean:: + rm -rf globals.o a.out *.dSYM diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/target_var/TestTargetVar.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/target_var/TestTargetVar.py new file mode 100644 index 00000000000..f8c2a690147 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/target_var/TestTargetVar.py @@ -0,0 +1,22 @@ +""" +Test that target var can resolve complex DWARF expressions. +""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class targetCommandTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipUnlessDarwin + @skipIfDarwinEmbedded # needs x86_64 + @skipIf(debug_info="gmodules") # not relevant + @skipIf(compiler="clang", compiler_version=['<', '7.0']) + def testTargetVarExpr(self): + self.build() + lldbutil.run_to_name_breakpoint(self, 'main') + self.expect("target variable i", substrs=['i', '42']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/target_var/globals.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/target_var/globals.c new file mode 100644 index 00000000000..26619284964 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/target_var/globals.c @@ -0,0 +1,6 @@ +int i = 42; +int *p = &i; + +int main() { + return *p; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/target_var/globals.ll b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/target_var/globals.ll new file mode 100644 index 00000000000..192d4e12698 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/target_var/globals.ll @@ -0,0 +1,42 @@ +source_filename = "globals.c" +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.14.0" + +@i = global i32 42, align 4 +@p = global i32* @i, align 8, !dbg !0, !dbg !6 + +; Function Attrs: noinline nounwind optnone ssp uwtable +define i32 @main() #0 !dbg !15 { +entry: + %retval = alloca i32, align 4 + store i32 0, i32* %retval, align 4 + %0 = load i32*, i32** @p, align 8, !dbg !18 + %1 = load i32, i32* %0, align 4, !dbg !18 + ret i32 %1, !dbg !18 +} + +attributes #0 = { noinline nounwind optnone ssp uwtable } + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!10, !11, !12, !13} +!llvm.ident = !{!14} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression(DW_OP_deref)) +!1 = distinct !DIGlobalVariable(name: "i", scope: !2, file: !3, line: 1, type: !9, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, emissionKind: FullDebug, globals: !5) +!3 = !DIFile(filename: "globals.c", directory: "/") +!4 = !{} +!5 = !{!0, !6} +!6 = !DIGlobalVariableExpression(var: !7, expr: !DIExpression()) +!7 = distinct !DIGlobalVariable(name: "p", scope: !2, file: !3, line: 2, type: !8, isLocal: false, isDefinition: true) +!8 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !9, size: 64) +!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!10 = !{i32 2, !"Dwarf Version", i32 4} +!11 = !{i32 2, !"Debug Info Version", i32 3} +!12 = !{i32 1, !"wchar_size", i32 4} +!13 = !{i32 7, !"PIC Level", i32 2} +!14 = !{!"clang version 8.0.0 (trunk 340838) (llvm/trunk 340843)"} +!15 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 4, type: !16, isLocal: false, isDefinition: true, scopeLine: 4, isOptimized: false, unit: !2, retainedNodes: !4) +!16 = !DISubroutineType(types: !17) +!17 = !{!9} +!18 = !DILocation(line: 5, scope: !15) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/testid/TestTestId.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/testid/TestTestId.py new file mode 100644 index 00000000000..b3d331773f8 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/testid/TestTestId.py @@ -0,0 +1,16 @@ +""" +Add a test to verify our test instance returns something non-None for +an id(). Other parts of the test running infrastructure are counting on this. +""" + +from lldbsuite.test.lldbtest import TestBase + +class TestIdTestCase(TestBase): + + NO_DEBUG_INFO_TESTCASE = True + + mydir = TestBase.compute_mydir(__file__) + + def test_id_exists(self): + self.assertIsNotNone(self.id(), "Test instance should have an id()") + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/backtrace_all/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/backtrace_all/Makefile new file mode 100644 index 00000000000..cd092b77256 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/backtrace_all/Makefile @@ -0,0 +1,5 @@ +CXXFLAGS_EXTRAS := -std=c++11 +CXX_SOURCES := ParallelTask.cpp +ENABLE_THREADS := YES + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/backtrace_all/ParallelTask.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/backtrace_all/ParallelTask.cpp new file mode 100644 index 00000000000..8e0f76f691b --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/backtrace_all/ParallelTask.cpp @@ -0,0 +1,152 @@ +#include <cstdint> +#include <thread> +#include <vector> +#include <queue> +#include <functional> +#include <future> +#include <iostream> +#include <cassert> + +class TaskPoolImpl +{ +public: + TaskPoolImpl(uint32_t num_threads) : + m_stop(false) + { + for (uint32_t i = 0; i < num_threads; ++i) + m_threads.emplace_back(Worker, this); + } + + ~TaskPoolImpl() + { + Stop(); + } + + template<typename F, typename... Args> + std::future<typename std::result_of<F(Args...)>::type> + AddTask(F&& f, Args&&... args) + { + auto task = std::make_shared<std::packaged_task<typename std::result_of<F(Args...)>::type()>>( + std::bind(std::forward<F>(f), std::forward<Args>(args)...)); + + std::unique_lock<std::mutex> lock(m_tasks_mutex); + assert(!m_stop && "Can't add task to TaskPool after it is stopped"); + m_tasks.emplace([task](){ (*task)(); }); + lock.unlock(); + m_tasks_cv.notify_one(); + + return task->get_future(); + } + + void + Stop() + { + std::unique_lock<std::mutex> lock(m_tasks_mutex); + m_stop = true; + m_tasks_mutex.unlock(); + m_tasks_cv.notify_all(); + for (auto& t : m_threads) + t.join(); + } + +private: + static void + Worker(TaskPoolImpl* pool) + { + while (true) + { + std::unique_lock<std::mutex> lock(pool->m_tasks_mutex); + if (pool->m_tasks.empty()) + pool->m_tasks_cv.wait(lock, [pool](){ return !pool->m_tasks.empty() || pool->m_stop; }); + if (pool->m_tasks.empty()) + break; + + std::function<void()> f = pool->m_tasks.front(); + pool->m_tasks.pop(); + lock.unlock(); + + f(); + } + } + + std::queue<std::function<void()>> m_tasks; + std::mutex m_tasks_mutex; + std::condition_variable m_tasks_cv; + bool m_stop; + std::vector<std::thread> m_threads; +}; + +class TaskPool +{ +public: + // Add a new task to the thread pool and return a std::future belongs for the newly created task. + // The caller of this function have to wait on the future for this task to complete. + template<typename F, typename... Args> + static std::future<typename std::result_of<F(Args...)>::type> + AddTask(F&& f, Args&&... args) + { + return GetImplementation().AddTask(std::forward<F>(f), std::forward<Args>(args)...); + } + + // Run all of the specified tasks on the thread pool and wait until all of them are finished + // before returning + template<typename... T> + static void + RunTasks(T&&... t) + { + RunTaskImpl<T...>::Run(std::forward<T>(t)...); + } + +private: + static TaskPoolImpl& + GetImplementation() + { + static TaskPoolImpl g_task_pool_impl(std::thread::hardware_concurrency()); + return g_task_pool_impl; + } + + template<typename... T> + struct RunTaskImpl; +}; + +template<typename H, typename... T> +struct TaskPool::RunTaskImpl<H, T...> +{ + static void + Run(H&& h, T&&... t) + { + auto f = AddTask(std::forward<H>(h)); + RunTaskImpl<T...>::Run(std::forward<T>(t)...); + f.wait(); + } +}; + +template<> +struct TaskPool::RunTaskImpl<> +{ + static void + Run() {} +}; + +int main() +{ + std::vector<std::future<uint32_t>> tasks; + for (int i = 0; i < 100000; ++i) + { + tasks.emplace_back(TaskPool::AddTask([](int i){ + uint32_t s = 0; + for (int j = 0; j <= i; ++j) + s += j; + return s; + }, + i)); + } + + for (auto& it : tasks) // Set breakpoint here + it.wait(); + + TaskPool::RunTasks( + []() { return 1; }, + []() { return "aaaa"; } + ); +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/backtrace_all/TestBacktraceAll.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/backtrace_all/TestBacktraceAll.py new file mode 100644 index 00000000000..870b6b223c8 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/backtrace_all/TestBacktraceAll.py @@ -0,0 +1,65 @@ +""" +Test regression for Bug 25251. +""" + +import unittest2 +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class BacktraceAllTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number for our breakpoint. + self.breakpoint = line_number( + 'ParallelTask.cpp', '// Set breakpoint here') + + # The android-arm compiler can't compile the inferior + @skipIfTargetAndroid(archs=["arm"]) + # because of an issue around std::future. + # TODO: Change the test to don't depend on std::future<T> + def test(self): + """Test breakpoint handling after a thread join.""" + self.build(dictionary=self.getBuildFlags()) + + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # This should create a breakpoint + lldbutil.run_break_set_by_file_and_line( + self, "ParallelTask.cpp", self.breakpoint, num_expected_locations=-1) + + # The breakpoint list should show 1 location. + self.expect( + "breakpoint list -f", + "Breakpoint location shown correctly", + substrs=[ + "1: file = 'ParallelTask.cpp', line = %d, exact_match = 0" % + self.breakpoint]) + + # Run the program. + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This should not result in a segmentation fault + self.expect("thread backtrace all", STOPPED_DUE_TO_BREAKPOINT, + substrs=["stop reason = breakpoint 1."]) + + # Run to completion + self.runCmd("continue") + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/Makefile new file mode 100644 index 00000000000..5fd720c6d06 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/Makefile @@ -0,0 +1,5 @@ +CXXFLAGS_EXTRAS := -std=c++11 +CXX_SOURCES := main.cpp +ENABLE_THREADS := YES + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/TestBacktraceLimit.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/TestBacktraceLimit.py new file mode 100644 index 00000000000..6dbb3e30ee7 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/TestBacktraceLimit.py @@ -0,0 +1,27 @@ +""" +Test that the target.process.thread.max-backtrace-depth setting works. +""" + +import unittest2 +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class BacktraceLimitSettingTest(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + def test_backtrace_depth(self): + """Test that the max-backtrace-depth setting limits backtraces.""" + self.build() + self.main_source_file = lldb.SBFileSpec("main.cpp") + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + "Set a breakpoint here", self.main_source_file) + interp = self.dbg.GetCommandInterpreter() + result = lldb.SBCommandReturnObject() + interp.HandleCommand("settings set target.process.thread.max-backtrace-depth 30", result) + self.assertEqual(True, result.Succeeded()) + self.assertEqual(30, thread.GetNumFrames()) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/main.cpp new file mode 100644 index 00000000000..eca1eadc8e4 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/main.cpp @@ -0,0 +1,13 @@ +int bottom () { + return 1; // Set a breakpoint here +} +int foo(int in) { + if (in > 0) + return foo(--in) + 5; + else + return bottom(); +} +int main() +{ + return foo(500); +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/break_after_join/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/break_after_join/Makefile new file mode 100644 index 00000000000..566938ca0cc --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/break_after_join/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp +ENABLE_THREADS := YES +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/break_after_join/TestBreakAfterJoin.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/break_after_join/TestBreakAfterJoin.py new file mode 100644 index 00000000000..391f9d96597 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/break_after_join/TestBreakAfterJoin.py @@ -0,0 +1,93 @@ +""" +Test number of threads. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class BreakpointAfterJoinTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number for our breakpoint. + self.breakpoint = line_number('main.cpp', '// Set breakpoint here') + + @expectedFailureAll( + oslist=["linux"], + bugnumber="llvm.org/pr15824 thread states not properly maintained") + @expectedFailureAll( + oslist=lldbplatformutil.getDarwinOSTriples(), + bugnumber="llvm.org/pr15824 thread states not properly maintained and <rdar://problem/28557237>") + @expectedFailureAll( + oslist=["freebsd"], + bugnumber="llvm.org/pr18190 thread states not properly maintained") + @expectedFailureNetBSD + def test(self): + """Test breakpoint handling after a thread join.""" + self.build(dictionary=self.getBuildFlags()) + + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # This should create a breakpoint in the main thread. + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.breakpoint, num_expected_locations=1) + + # The breakpoint list should show 1 location. + self.expect( + "breakpoint list -f", + "Breakpoint location shown correctly", + substrs=[ + "1: file = 'main.cpp', line = %d, exact_match = 0, locations = 1" % + self.breakpoint]) + + # Run the program. + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # Get the target process + target = self.dbg.GetSelectedTarget() + process = target.GetProcess() + + # The exit probably occurred during breakpoint handling, but it isn't + # guaranteed. The main thing we're testing here is that the debugger + # handles this cleanly is some way. + + # Get the number of threads + num_threads = process.GetNumThreads() + + # Make sure we see at least six threads + self.assertTrue( + num_threads >= 6, + 'Number of expected threads and actual threads do not match.') + + # Make sure all threads are stopped + for i in range(0, num_threads): + self.assertTrue( + process.GetThreadAtIndex(i).IsStopped(), + "Thread {0} didn't stop during breakpoint.".format(i)) + + # Run to completion + self.runCmd("continue") + + # If the process hasn't exited, collect some information + if process.GetState() != lldb.eStateExited: + self.runCmd("thread list") + self.runCmd("process status") + + # At this point, the inferior process should have exited. + self.assertTrue( + process.GetState() == lldb.eStateExited, + PROCESS_EXITED) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/break_after_join/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/break_after_join/main.cpp new file mode 100644 index 00000000000..a589d979003 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/break_after_join/main.cpp @@ -0,0 +1,105 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// This test is intended to create a situation in which one thread will exit +// while a breakpoint is being handled in another thread. This may not always +// happen because it's possible that the exiting thread will exit before the +// breakpoint is hit. The test case should be flexible enough to treat that +// as success. + +#include "pseudo_barrier.h" +#include <chrono> +#include <thread> + +volatile int g_test = 0; + +// A barrier to synchronize all the threads. +pseudo_barrier_t g_barrier1; + +// A barrier to keep the threads from exiting until after the breakpoint has +// been passed. +pseudo_barrier_t g_barrier2; + +void * +break_thread_func () +{ + // Wait until all the threads are running + pseudo_barrier_wait(g_barrier1); + + // Wait for the join thread to join + std::this_thread::sleep_for(std::chrono::microseconds(50)); + + // Do something + g_test++; // Set breakpoint here + + // Synchronize after the breakpoint + pseudo_barrier_wait(g_barrier2); + + // Return + return NULL; +} + +void * +wait_thread_func () +{ + // Wait until the entire first group of threads is running + pseudo_barrier_wait(g_barrier1); + + // Wait until the breakpoint has been passed + pseudo_barrier_wait(g_barrier2); + + // Return + return NULL; +} + +void * +join_thread_func (void *input) +{ + std::thread *thread_to_join = (std::thread *)input; + + // Sync up with the rest of the threads. + pseudo_barrier_wait(g_barrier1); + + // Join the other thread + thread_to_join->join(); + + // Return + return NULL; +} + +int main () +{ + // The first barrier waits for the non-joining threads to start. + // This thread will also participate in that barrier. + // The idea here is to guarantee that the joining thread will be + // last in the internal list maintained by the debugger. + pseudo_barrier_init(g_barrier1, 5); + + // The second barrier keeps the waiting threads around until the breakpoint + // has been passed. + pseudo_barrier_init(g_barrier2, 4); + + // Create a thread to hit the breakpoint + std::thread thread_1(break_thread_func); + + // Create more threads to slow the debugger down during processing. + std::thread thread_2(wait_thread_func); + std::thread thread_3(wait_thread_func); + std::thread thread_4(wait_thread_func); + + // Create a thread to join the breakpoint thread + std::thread thread_5(join_thread_func, &thread_1); + + // Wait for the threads to finish + thread_5.join(); // implies thread_1 is already finished + thread_4.join(); + thread_3.join(); + thread_2.join(); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/Makefile new file mode 100644 index 00000000000..c33ae5685ef --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/Makefile @@ -0,0 +1,5 @@ +CXX_SOURCES := main.cpp + +ENABLE_THREADS := YES + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentBreakpointDelayBreakpointOneSignal.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentBreakpointDelayBreakpointOneSignal.py new file mode 100644 index 00000000000..a0c1da8dad1 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentBreakpointDelayBreakpointOneSignal.py @@ -0,0 +1,23 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentBreakpointDelayBreakpointOneSignal(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + @skipIfFreeBSD # timing out on buildbot + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + @expectedFailureNetBSD + def test(self): + """Test two threads that trigger a breakpoint (one with a 1 second delay) and one signal thread. """ + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions(num_breakpoint_threads=1, + num_delay_breakpoint_threads=1, + num_signal_threads=1) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentBreakpointOneDelayBreakpointThreads.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentBreakpointOneDelayBreakpointThreads.py new file mode 100644 index 00000000000..bcee1c54e76 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentBreakpointOneDelayBreakpointThreads.py @@ -0,0 +1,21 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentBreakpointOneDelayBreakpointThreads(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + @skipIfFreeBSD # timing out on buildbot + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + def test(self): + """Test threads that trigger a breakpoint where one thread has a 1 second delay. """ + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions(num_breakpoint_threads=1, + num_delay_breakpoint_threads=1) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentBreakpointsDelayedBreakpointOneWatchpoint.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentBreakpointsDelayedBreakpointOneWatchpoint.py new file mode 100644 index 00000000000..dfe2cb7d23e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentBreakpointsDelayedBreakpointOneWatchpoint.py @@ -0,0 +1,24 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentBreakpointsDelayedBreakpointOneWatchpoint( + ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + @skipIfFreeBSD # timing out on buildbot + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + @add_test_categories(["watchpoint"]) + def test(self): + """Test a breakpoint, a delayed breakpoint, and one watchpoint thread. """ + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions(num_breakpoint_threads=1, + num_delay_breakpoint_threads=1, + num_watchpoint_threads=1) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithBreak.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithBreak.py new file mode 100644 index 00000000000..9083c3838bc --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithBreak.py @@ -0,0 +1,20 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentCrashWithBreak(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + @skipIfFreeBSD # timing out on buildbot + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + def test(self): + """ Test a thread that crashes while another thread hits a breakpoint.""" + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions(num_crash_threads=1, num_breakpoint_threads=1) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithSignal.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithSignal.py new file mode 100644 index 00000000000..37795be849d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithSignal.py @@ -0,0 +1,20 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentCrashWithSignal(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + @skipIfFreeBSD # timing out on buildbot + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + def test(self): + """ Test a thread that crashes while another thread generates a signal.""" + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions(num_crash_threads=1, num_signal_threads=1) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithWatchpoint.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithWatchpoint.py new file mode 100644 index 00000000000..13f5b4ad35e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithWatchpoint.py @@ -0,0 +1,21 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentCrashWithWatchpoint(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + @skipIfFreeBSD # timing out on buildbot + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + @add_test_categories(["watchpoint"]) + def test(self): + """ Test a thread that crashes while another thread hits a watchpoint.""" + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions(num_crash_threads=1, num_watchpoint_threads=1) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithWatchpointBreakpointSignal.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithWatchpointBreakpointSignal.py new file mode 100644 index 00000000000..3de0850abe2 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithWatchpointBreakpointSignal.py @@ -0,0 +1,24 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentCrashWithWatchpointBreakpointSignal(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + @skipIfFreeBSD # timing out on buildbot + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + @add_test_categories(["watchpoint"]) + def test(self): + """ Test a thread that crashes while other threads generate a signal and hit a watchpoint and breakpoint. """ + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions(num_crash_threads=1, + num_breakpoint_threads=1, + num_signal_threads=1, + num_watchpoint_threads=1) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelaySignalBreak.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelaySignalBreak.py new file mode 100644 index 00000000000..af9c6c994ab --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelaySignalBreak.py @@ -0,0 +1,22 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentDelaySignalBreak(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + @skipIfFreeBSD # timing out on buildbot + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + def test(self): + """Test (1-second delay) signal and a breakpoint in multiple threads.""" + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions( + num_breakpoint_threads=1, + num_delay_signal_threads=1) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelaySignalWatch.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelaySignalWatch.py new file mode 100644 index 00000000000..91358f34676 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelaySignalWatch.py @@ -0,0 +1,23 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentDelaySignalWatch(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + @skipIfFreeBSD # timing out on buildbot + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + @add_test_categories(["watchpoint"]) + def test(self): + """Test a watchpoint and a (1 second delay) signal in multiple threads.""" + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions( + num_delay_signal_threads=1, + num_watchpoint_threads=1) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelayWatchBreak.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelayWatchBreak.py new file mode 100644 index 00000000000..8f7a8ba6a08 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelayWatchBreak.py @@ -0,0 +1,23 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentDelayWatchBreak(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + @skipIfFreeBSD # timing out on buildbot + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + @add_test_categories(["watchpoint"]) + def test(self): + """Test (1-second delay) watchpoint and a breakpoint in multiple threads.""" + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions( + num_breakpoint_threads=1, + num_delay_watchpoint_threads=1) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelayedCrashWithBreakpointSignal.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelayedCrashWithBreakpointSignal.py new file mode 100644 index 00000000000..9c1ac90423c --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelayedCrashWithBreakpointSignal.py @@ -0,0 +1,22 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentDelayedCrashWithBreakpointSignal(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + @skipIfFreeBSD # timing out on buildbot + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + def test(self): + """ Test a thread with a delayed crash while other threads generate a signal and hit a breakpoint. """ + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions(num_delay_crash_threads=1, + num_breakpoint_threads=1, + num_signal_threads=1) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelayedCrashWithBreakpointWatchpoint.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelayedCrashWithBreakpointWatchpoint.py new file mode 100644 index 00000000000..12344ffb061 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelayedCrashWithBreakpointWatchpoint.py @@ -0,0 +1,23 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentDelayedCrashWithBreakpointWatchpoint(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + @skipIfFreeBSD # timing out on buildbot + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + @add_test_categories(["watchpoint"]) + def test(self): + """ Test a thread with a delayed crash while other threads hit a watchpoint and a breakpoint. """ + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions(num_delay_crash_threads=1, + num_breakpoint_threads=1, + num_watchpoint_threads=1) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentManyBreakpoints.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentManyBreakpoints.py new file mode 100644 index 00000000000..bbbfbdb0958 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentManyBreakpoints.py @@ -0,0 +1,20 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentManyBreakpoints(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + @skipIfOutOfTreeDebugserver + def test(self): + """Test 100 breakpoints from 100 threads.""" + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions(num_breakpoint_threads=100) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentManyCrash.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentManyCrash.py new file mode 100644 index 00000000000..0530728b6ac --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentManyCrash.py @@ -0,0 +1,20 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentManyCrash(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + @skipIfOutOfTreeDebugserver + def test(self): + """Test 100 threads that cause a segfault.""" + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions(num_crash_threads=100) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentManySignals.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentManySignals.py new file mode 100644 index 00000000000..ec06227ec54 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentManySignals.py @@ -0,0 +1,23 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentManySignals(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + # This test is flaky on Darwin. + @skipIfDarwin + @expectedFailureNetBSD + @skipIfOutOfTreeDebugserver + def test(self): + """Test 100 signals from 100 threads.""" + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions(num_signal_threads=100) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentManyWatchpoints.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentManyWatchpoints.py new file mode 100644 index 00000000000..2274fbb6d4a --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentManyWatchpoints.py @@ -0,0 +1,21 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentManyWatchpoints(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + @add_test_categories(["watchpoint"]) + @skipIfOutOfTreeDebugserver + def test(self): + """Test 100 watchpoints from 100 threads.""" + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions(num_watchpoint_threads=100) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentNWatchNBreak.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentNWatchNBreak.py new file mode 100644 index 00000000000..2c5205fc49f --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentNWatchNBreak.py @@ -0,0 +1,22 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentNWatchNBreak(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + @skipIfFreeBSD # timing out on buildbot + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + @add_test_categories(["watchpoint"]) + def test(self): + """Test with 5 watchpoint and breakpoint threads.""" + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions(num_watchpoint_threads=5, + num_breakpoint_threads=5) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentSignalBreak.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentSignalBreak.py new file mode 100644 index 00000000000..6c18cb2e965 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentSignalBreak.py @@ -0,0 +1,20 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentSignalBreak(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + @skipIfFreeBSD # timing out on buildbot + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + def test(self): + """Test signal and a breakpoint in multiple threads.""" + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions(num_breakpoint_threads=1, num_signal_threads=1) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentSignalDelayBreak.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentSignalDelayBreak.py new file mode 100644 index 00000000000..e1779b44f7c --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentSignalDelayBreak.py @@ -0,0 +1,23 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentSignalDelayBreak(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + @skipIfFreeBSD # timing out on buildbot + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + @expectedFailureNetBSD + def test(self): + """Test signal and a (1 second delay) breakpoint in multiple threads.""" + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions( + num_delay_breakpoint_threads=1, + num_signal_threads=1) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentSignalDelayWatch.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentSignalDelayWatch.py new file mode 100644 index 00000000000..d932d5f847b --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentSignalDelayWatch.py @@ -0,0 +1,24 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentSignalDelayWatch(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + @skipIfFreeBSD # timing out on buildbot + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + @expectedFailureNetBSD + @add_test_categories(["watchpoint"]) + def test(self): + """Test a (1 second delay) watchpoint and a signal in multiple threads.""" + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions( + num_signal_threads=1, + num_delay_watchpoint_threads=1) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentSignalNWatchNBreak.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentSignalNWatchNBreak.py new file mode 100644 index 00000000000..3b005e559a4 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentSignalNWatchNBreak.py @@ -0,0 +1,24 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentSignalNWatchNBreak(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + @skipIfFreeBSD # timing out on buildbot + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + @expectedFailureNetBSD + @add_test_categories(["watchpoint"]) + def test(self): + """Test one signal thread with 5 watchpoint and breakpoint threads.""" + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions(num_signal_threads=1, + num_watchpoint_threads=5, + num_breakpoint_threads=5) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentSignalWatch.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentSignalWatch.py new file mode 100644 index 00000000000..6cf26aea9e2 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentSignalWatch.py @@ -0,0 +1,21 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentSignalWatch(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + @skipIfFreeBSD # timing out on buildbot + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + @add_test_categories(["watchpoint"]) + def test(self): + """Test a watchpoint and a signal in multiple threads.""" + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions(num_signal_threads=1, num_watchpoint_threads=1) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentSignalWatchBreak.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentSignalWatchBreak.py new file mode 100644 index 00000000000..38a51258853 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentSignalWatchBreak.py @@ -0,0 +1,24 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentSignalWatchBreak(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + @skipIfFreeBSD # timing out on buildbot + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + @expectedFailureNetBSD + @add_test_categories(["watchpoint"]) + def test(self): + """Test a signal/watchpoint/breakpoint in multiple threads.""" + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions(num_signal_threads=1, + num_watchpoint_threads=1, + num_breakpoint_threads=1) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoBreakpointThreads.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoBreakpointThreads.py new file mode 100644 index 00000000000..5ddc15bd964 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoBreakpointThreads.py @@ -0,0 +1,20 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentTwoBreakpointThreads(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + @skipIfFreeBSD # timing out on buildbot + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + def test(self): + """Test two threads that trigger a breakpoint. """ + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions(num_breakpoint_threads=2) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoBreakpointsOneDelaySignal.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoBreakpointsOneDelaySignal.py new file mode 100644 index 00000000000..07f99b0f82e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoBreakpointsOneDelaySignal.py @@ -0,0 +1,23 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentTwoBreakpointsOneDelaySignal(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + @skipIfFreeBSD # timing out on buildbot + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + @expectedFailureNetBSD + def test(self): + """Test two threads that trigger a breakpoint and one (1 second delay) signal thread. """ + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions( + num_breakpoint_threads=2, + num_delay_signal_threads=1) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoBreakpointsOneSignal.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoBreakpointsOneSignal.py new file mode 100644 index 00000000000..1ad1c591c7e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoBreakpointsOneSignal.py @@ -0,0 +1,21 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentTwoBreakpointsOneSignal(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + @skipIfFreeBSD # timing out on buildbot + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + @expectedFailureNetBSD + def test(self): + """Test two threads that trigger a breakpoint and one signal thread. """ + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions(num_breakpoint_threads=2, num_signal_threads=1) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoBreakpointsOneWatchpoint.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoBreakpointsOneWatchpoint.py new file mode 100644 index 00000000000..47e973a4871 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoBreakpointsOneWatchpoint.py @@ -0,0 +1,23 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentTwoBreakpointsOneWatchpoint(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + @skipIfFreeBSD # timing out on buildbot + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + @add_test_categories(["watchpoint"]) + def test(self): + """Test two threads that trigger a breakpoint and one watchpoint thread. """ + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions( + num_breakpoint_threads=2, + num_watchpoint_threads=1) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoWatchpointThreads.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoWatchpointThreads.py new file mode 100644 index 00000000000..bdc6f8ef87e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoWatchpointThreads.py @@ -0,0 +1,21 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentTwoWatchpointThreads(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + @skipIfFreeBSD # timing out on buildbot + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + @add_test_categories(["watchpoint"]) + def test(self): + """Test two threads that trigger a watchpoint. """ + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions(num_watchpoint_threads=2) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoWatchpointsOneBreakpoint.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoWatchpointsOneBreakpoint.py new file mode 100644 index 00000000000..163f76d189b --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoWatchpointsOneBreakpoint.py @@ -0,0 +1,23 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentTwoWatchpointsOneBreakpoint(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + @skipIfFreeBSD # timing out on buildbot + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + @add_test_categories(["watchpoint"]) + def test(self): + """Test two threads that trigger a watchpoint and one breakpoint thread. """ + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions( + num_watchpoint_threads=2, + num_breakpoint_threads=1) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoWatchpointsOneDelayBreakpoint.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoWatchpointsOneDelayBreakpoint.py new file mode 100644 index 00000000000..1ec5e065dc4 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoWatchpointsOneDelayBreakpoint.py @@ -0,0 +1,23 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentTwoWatchpointsOneDelayBreakpoint(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + @skipIfFreeBSD # timing out on buildbot + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + @add_test_categories(["watchpoint"]) + def test(self): + """Test two threads that trigger a watchpoint and one (1 second delay) breakpoint thread. """ + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions( + num_watchpoint_threads=2, + num_delay_breakpoint_threads=1) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoWatchpointsOneSignal.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoWatchpointsOneSignal.py new file mode 100644 index 00000000000..8f044badf5e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoWatchpointsOneSignal.py @@ -0,0 +1,22 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentTwoWatchpointsOneSignal(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + @skipIfFreeBSD # timing out on buildbot + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + @expectedFailureNetBSD + @add_test_categories(["watchpoint"]) + def test(self): + """Test two threads that trigger a watchpoint and one signal thread. """ + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions(num_watchpoint_threads=2, num_signal_threads=1) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentWatchBreak.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentWatchBreak.py new file mode 100644 index 00000000000..4a418082ff0 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentWatchBreak.py @@ -0,0 +1,23 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentWatchBreak(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + @skipIfFreeBSD # timing out on buildbot + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + @add_test_categories(["watchpoint"]) + def test(self): + """Test watchpoint and a breakpoint in multiple threads.""" + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions( + num_breakpoint_threads=1, + num_watchpoint_threads=1) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentWatchBreakDelay.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentWatchBreakDelay.py new file mode 100644 index 00000000000..2bc08399322 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentWatchBreakDelay.py @@ -0,0 +1,23 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentWatchBreakDelay(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + @skipIfFreeBSD # timing out on buildbot + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + @add_test_categories(["watchpoint"]) + def test(self): + """Test watchpoint and a (1 second delay) breakpoint in multiple threads.""" + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions( + num_delay_breakpoint_threads=1, + num_watchpoint_threads=1) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentWatchpointDelayWatchpointOneBreakpoint.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentWatchpointDelayWatchpointOneBreakpoint.py new file mode 100644 index 00000000000..dce84fed775 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentWatchpointDelayWatchpointOneBreakpoint.py @@ -0,0 +1,23 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentWatchpointDelayWatchpointOneBreakpoint(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + @skipIfFreeBSD # timing out on buildbot + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + @add_test_categories(["watchpoint"]) + def test(self): + """Test two threads that trigger a watchpoint (one with a 1 second delay) and one breakpoint thread. """ + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions(num_watchpoint_threads=1, + num_delay_watchpoint_threads=1, + num_breakpoint_threads=1) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentWatchpointWithDelayWatchpointThreads.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentWatchpointWithDelayWatchpointThreads.py new file mode 100644 index 00000000000..87b8ea0d775 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentWatchpointWithDelayWatchpointThreads.py @@ -0,0 +1,22 @@ + +import unittest2 + +from lldbsuite.test.decorators import * +from lldbsuite.test.concurrent_base import ConcurrentEventsBase +from lldbsuite.test.lldbtest import TestBase + + +@skipIfWindows +class ConcurrentWatchpointWithDelayWatchpointThreads(ConcurrentEventsBase): + + mydir = ConcurrentEventsBase.compute_mydir(__file__) + + @skipIfFreeBSD # timing out on buildbot + # Atomic sequences are not supported yet for MIPS in LLDB. + @skipIf(triple='^mips') + @add_test_categories(["watchpoint"]) + def test(self): + """Test two threads that trigger a watchpoint where one thread has a 1 second delay. """ + self.build(dictionary=self.getBuildFlags()) + self.do_thread_actions(num_watchpoint_threads=1, + num_delay_watchpoint_threads=1) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/main.cpp new file mode 100644 index 00000000000..33ec8ad1f50 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/main.cpp @@ -0,0 +1,187 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// This test is intended to create a situation in which multiple events +// (breakpoints, watchpoints, crashes, and signal generation/delivery) happen +// from multiple threads. The test expects the debugger to set a breakpoint on +// the main thread (before any worker threads are spawned) and modify variables +// which control the number of threads that are spawned for each action. + +#include "pseudo_barrier.h" +#include <vector> +using namespace std; + +#include <pthread.h> + +#include <signal.h> +#include <sys/types.h> +#include <unistd.h> + +typedef std::vector<std::pair<unsigned, void*(*)(void*)> > action_counts; +typedef std::vector<pthread_t> thread_vector; + +pseudo_barrier_t g_barrier; +int g_breakpoint = 0; +int g_sigusr1_count = 0; +uint32_t g_watchme; + +struct action_args { + int delay; +}; + +// Perform any extra actions required by thread 'input' arg +void do_action_args(void *input) { + if (input) { + action_args *args = static_cast<action_args*>(input); + sleep(args->delay); + } +} + +void * +breakpoint_func (void *input) +{ + // Wait until all threads are running + pseudo_barrier_wait(g_barrier); + do_action_args(input); + + // Do something + g_breakpoint++; // Set breakpoint here + return 0; +} + +void * +signal_func (void *input) { + // Wait until all threads are running + pseudo_barrier_wait(g_barrier); + do_action_args(input); + + // Send a user-defined signal to the current process + //kill(getpid(), SIGUSR1); + // Send a user-defined signal to the current thread + pthread_kill(pthread_self(), SIGUSR1); + + return 0; +} + +void * +watchpoint_func (void *input) { + pseudo_barrier_wait(g_barrier); + do_action_args(input); + + g_watchme = 1; // watchpoint triggers here + return 0; +} + +void * +crash_func (void *input) { + pseudo_barrier_wait(g_barrier); + do_action_args(input); + + int *a = 0; + *a = 5; // crash happens here + return 0; +} + +void sigusr1_handler(int sig) { + if (sig == SIGUSR1) + g_sigusr1_count += 1; // Break here in signal handler +} + +/// Register a simple function for to handle signal +void register_signal_handler(int signal, void (*handler)(int)) +{ + sigset_t empty_sigset; + sigemptyset(&empty_sigset); + + struct sigaction action; + action.sa_sigaction = 0; + action.sa_mask = empty_sigset; + action.sa_flags = 0; + action.sa_handler = handler; + sigaction(SIGUSR1, &action, 0); +} + +void start_threads(thread_vector& threads, + action_counts& actions, + void* args = 0) { + action_counts::iterator b = actions.begin(), e = actions.end(); + for(action_counts::iterator i = b; i != e; ++i) { + for(unsigned count = 0; count < i->first; ++count) { + pthread_t t; + pthread_create(&t, 0, i->second, args); + threads.push_back(t); + } + } +} + +int dotest() +{ + g_watchme = 0; + + // Actions are triggered immediately after the thread is spawned + unsigned num_breakpoint_threads = 1; + unsigned num_watchpoint_threads = 0; + unsigned num_signal_threads = 1; + unsigned num_crash_threads = 0; + + // Actions below are triggered after a 1-second delay + unsigned num_delay_breakpoint_threads = 0; + unsigned num_delay_watchpoint_threads = 0; + unsigned num_delay_signal_threads = 0; + unsigned num_delay_crash_threads = 0; + + register_signal_handler(SIGUSR1, sigusr1_handler); // Break here and adjust num_[breakpoint|watchpoint|signal|crash]_threads + + unsigned total_threads = num_breakpoint_threads \ + + num_watchpoint_threads \ + + num_signal_threads \ + + num_crash_threads \ + + num_delay_breakpoint_threads \ + + num_delay_watchpoint_threads \ + + num_delay_signal_threads \ + + num_delay_crash_threads; + + // Don't let either thread do anything until they're both ready. + pseudo_barrier_init(g_barrier, total_threads); + + action_counts actions; + actions.push_back(std::make_pair(num_breakpoint_threads, breakpoint_func)); + actions.push_back(std::make_pair(num_watchpoint_threads, watchpoint_func)); + actions.push_back(std::make_pair(num_signal_threads, signal_func)); + actions.push_back(std::make_pair(num_crash_threads, crash_func)); + + action_counts delay_actions; + delay_actions.push_back(std::make_pair(num_delay_breakpoint_threads, breakpoint_func)); + delay_actions.push_back(std::make_pair(num_delay_watchpoint_threads, watchpoint_func)); + delay_actions.push_back(std::make_pair(num_delay_signal_threads, signal_func)); + delay_actions.push_back(std::make_pair(num_delay_crash_threads, crash_func)); + + // Create threads that handle instant actions + thread_vector threads; + start_threads(threads, actions); + + // Create threads that handle delayed actions + action_args delay_arg; + delay_arg.delay = 1; + start_threads(threads, delay_actions, &delay_arg); + + // Join all threads + typedef std::vector<pthread_t>::iterator thread_iterator; + for(thread_iterator t = threads.begin(); t != threads.end(); ++t) + pthread_join(*t, 0); + + return 0; +} + +int main () +{ + dotest(); + return 0; // Break here and verify one thread is active. +} + + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/crash_during_step/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/crash_during_step/Makefile new file mode 100644 index 00000000000..3d0b98f13f3 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/crash_during_step/Makefile @@ -0,0 +1,2 @@ +CXX_SOURCES := main.cpp +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/crash_during_step/TestCrashDuringStep.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/crash_during_step/TestCrashDuringStep.py new file mode 100644 index 00000000000..3394bb2d6aa --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/crash_during_step/TestCrashDuringStep.py @@ -0,0 +1,61 @@ +""" +Test that step-inst over a crash behaves correctly. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class CrashDuringStepTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + TestBase.setUp(self) + self.breakpoint = line_number('main.cpp', '// Set breakpoint here') + + # IO error due to breakpoint at invalid address + @expectedFailureAll(triple=re.compile('^mips')) + def test_step_inst_with(self): + """Test thread creation during step-inst handling.""" + self.build(dictionary=self.getBuildFlags()) + exe = self.getBuildArtifact("a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target and target.IsValid(), "Target is valid") + + self.bp_num = lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.breakpoint, num_expected_locations=1) + + # Run the program. + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process and process.IsValid(), PROCESS_IS_VALID) + + # The stop reason should be breakpoint. + self.assertEqual( + process.GetState(), + lldb.eStateStopped, + PROCESS_STOPPED) + thread = lldbutil.get_stopped_thread( + process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), STOPPED_DUE_TO_BREAKPOINT) + + # Keep stepping until the inferior crashes + while process.GetState() == lldb.eStateStopped and not lldbutil.is_thread_crashed(self, thread): + thread.StepInstruction(False) + + self.assertEqual( + process.GetState(), + lldb.eStateStopped, + PROCESS_STOPPED) + self.assertTrue( + lldbutil.is_thread_crashed( + self, + thread), + "Thread has crashed") + process.Kill() diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/crash_during_step/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/crash_during_step/main.cpp new file mode 100644 index 00000000000..34cccf4dc2a --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/crash_during_step/main.cpp @@ -0,0 +1,15 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +void (*crash)() = nullptr; + +int main() +{ + crash(); // Set breakpoint here + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/create_after_attach/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/create_after_attach/Makefile new file mode 100644 index 00000000000..566938ca0cc --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/create_after_attach/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp +ENABLE_THREADS := YES +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/create_after_attach/TestCreateAfterAttach.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/create_after_attach/TestCreateAfterAttach.py new file mode 100644 index 00000000000..59fb3b6fd39 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/create_after_attach/TestCreateAfterAttach.py @@ -0,0 +1,128 @@ +""" +Test thread creation after process attach. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class CreateAfterAttachTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipIfFreeBSD # Hangs. May be the same as Linux issue llvm.org/pr16229 but + # not yet investigated. Revisit once required functionality + # is implemented for FreeBSD. + # Occasionally hangs on Windows, may be same as other issues. + @skipIfWindows + @skipIfiOSSimulator + @expectedFailureNetBSD + def test_create_after_attach_with_popen(self): + """Test thread creation after process attach.""" + self.build(dictionary=self.getBuildFlags(use_cpp11=False)) + self.create_after_attach(use_fork=False) + + @skipIfFreeBSD # Hangs. Revisit once required functionality is implemented + # for FreeBSD. + @skipIfRemote + @skipIfWindows # Windows doesn't have fork. + @skipIfiOSSimulator + @expectedFailureNetBSD + def test_create_after_attach_with_fork(self): + """Test thread creation after process attach.""" + self.build(dictionary=self.getBuildFlags(use_cpp11=False)) + self.create_after_attach(use_fork=True) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line numbers for our breakpoints. + self.break_1 = line_number('main.cpp', '// Set first breakpoint here') + self.break_2 = line_number('main.cpp', '// Set second breakpoint here') + self.break_3 = line_number('main.cpp', '// Set third breakpoint here') + + def create_after_attach(self, use_fork): + """Test thread creation after process attach.""" + + exe = self.getBuildArtifact("a.out") + + # Spawn a new process + if use_fork: + pid = self.forkSubprocess(exe) + else: + popen = self.spawnSubprocess(exe) + pid = popen.pid + self.addTearDownHook(self.cleanupSubprocesses) + + # Attach to the spawned process + self.runCmd("process attach -p " + str(pid)) + + target = self.dbg.GetSelectedTarget() + + process = target.GetProcess() + self.assertTrue(process, PROCESS_IS_VALID) + + # This should create a breakpoint in the main thread. + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.break_1, num_expected_locations=1) + + # This should create a breakpoint in the second child thread. + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.break_2, num_expected_locations=1) + + # This should create a breakpoint in the first child thread. + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.break_3, num_expected_locations=1) + + # Note: With std::thread, we cannot rely on particular thread numbers. Using + # std::thread may cause the program to spin up a thread pool (and it does on + # Windows), so the thread numbers are non-deterministic. + + # Run to the first breakpoint + self.runCmd("continue") + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + '* thread #', + 'main', + 'stop reason = breakpoint']) + + # Change a variable to escape the loop + self.runCmd("expression main_thread_continue = 1") + + # Run to the second breakpoint + self.runCmd("continue") + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + '* thread #', + 'thread_2_func', + 'stop reason = breakpoint']) + + # Change a variable to escape the loop + self.runCmd("expression child_thread_continue = 1") + + # Run to the third breakpoint + self.runCmd("continue") + + # The stop reason of the thread should be breakpoint. + # Thread 3 may or may not have already exited. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + '* thread #', + 'thread_1_func', + 'stop reason = breakpoint']) + + # Run to completion + self.runCmd("continue") + + # At this point, the inferior process should have exited. + self.assertTrue( + process.GetState() == lldb.eStateExited, + PROCESS_EXITED) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/create_after_attach/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/create_after_attach/main.cpp new file mode 100644 index 00000000000..d8f06e55a2d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/create_after_attach/main.cpp @@ -0,0 +1,61 @@ +#include <stdio.h> +#include <chrono> +#include <thread> + +using std::chrono::microseconds; + +volatile int g_thread_2_continuing = 0; + +void * +thread_1_func (void *input) +{ + // Waiting to be released by the debugger. + while (!g_thread_2_continuing) // Another thread will change this value + { + std::this_thread::sleep_for(microseconds(1)); + } + + // Return + return NULL; // Set third breakpoint here +} + +void * +thread_2_func (void *input) +{ + // Waiting to be released by the debugger. + int child_thread_continue = 0; + while (!child_thread_continue) // The debugger will change this value + { + std::this_thread::sleep_for(microseconds(1)); // Set second breakpoint here + } + + // Release thread 1 + g_thread_2_continuing = 1; + + // Return + return NULL; +} + +int main(int argc, char const *argv[]) +{ + lldb_enable_attach(); + + // Create a new thread + std::thread thread_1(thread_1_func, nullptr); + + // Waiting to be attached by the debugger. + int main_thread_continue = 0; + while (!main_thread_continue) // The debugger will change this value + { + std::this_thread::sleep_for(microseconds(1)); // Set first breakpoint here + } + + // Create another new thread + std::thread thread_2(thread_2_func, nullptr); + + // Wait for the threads to finish. + thread_1.join(); + thread_2.join(); + + printf("Exiting now\n"); +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/create_during_step/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/create_during_step/Makefile new file mode 100644 index 00000000000..566938ca0cc --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/create_during_step/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp +ENABLE_THREADS := YES +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/create_during_step/TestCreateDuringStep.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/create_during_step/TestCreateDuringStep.py new file mode 100644 index 00000000000..fa8c943836f --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/create_during_step/TestCreateDuringStep.py @@ -0,0 +1,154 @@ +""" +Test number of threads. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class CreateDuringStepTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll( + oslist=["linux"], + bugnumber="llvm.org/pr15824 thread states not properly maintained") + @expectedFailureAll( + oslist=lldbplatformutil.getDarwinOSTriples(), + bugnumber="llvm.org/pr15824 thread states not properly maintained, <rdar://problem/28557237>") + @expectedFailureAll( + oslist=["freebsd"], + bugnumber="llvm.org/pr18190 thread states not properly maintained") + @expectedFailureAll( + oslist=["windows"], + bugnumber="llvm.org/pr24668: Breakpoints not resolved correctly") + @expectedFailureNetBSD + def test_step_inst(self): + """Test thread creation during step-inst handling.""" + self.build(dictionary=self.getBuildFlags()) + self.create_during_step_base( + "thread step-inst -m all-threads", + 'stop reason = instruction step') + + @expectedFailureAll( + oslist=["linux"], + bugnumber="llvm.org/pr15824 thread states not properly maintained") + @expectedFailureAll( + oslist=lldbplatformutil.getDarwinOSTriples(), + bugnumber="llvm.org/pr15824 thread states not properly maintained, <rdar://problem/28557237>") + @expectedFailureAll( + oslist=["freebsd"], + bugnumber="llvm.org/pr18190 thread states not properly maintained") + @expectedFailureAll( + oslist=["windows"], + bugnumber="llvm.org/pr24668: Breakpoints not resolved correctly") + @expectedFailureNetBSD + def test_step_over(self): + """Test thread creation during step-over handling.""" + self.build(dictionary=self.getBuildFlags()) + self.create_during_step_base( + "thread step-over -m all-threads", + 'stop reason = step over') + + @expectedFailureAll( + oslist=["linux"], + bugnumber="llvm.org/pr15824 thread states not properly maintained") + @expectedFailureAll( + oslist=lldbplatformutil.getDarwinOSTriples(), + bugnumber="<rdar://problem/28574077>") + @expectedFailureAll( + oslist=["freebsd"], + bugnumber="llvm.org/pr18190 thread states not properly maintained") + @expectedFailureAll( + oslist=["windows"], + bugnumber="llvm.org/pr24668: Breakpoints not resolved correctly") + @expectedFailureNetBSD + def test_step_in(self): + """Test thread creation during step-in handling.""" + self.build(dictionary=self.getBuildFlags()) + self.create_during_step_base( + "thread step-in -m all-threads", + 'stop reason = step in') + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line numbers to break and continue. + self.breakpoint = line_number('main.cpp', '// Set breakpoint here') + self.continuepoint = line_number('main.cpp', '// Continue from here') + + def create_during_step_base(self, step_cmd, step_stop_reason): + """Test thread creation while using step-in.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Get the target process + target = self.dbg.GetSelectedTarget() + + # This should create a breakpoint in the stepping thread. + self.bkpt = target.BreakpointCreateByLocation("main.cpp", self.breakpoint) + + # Run the program. + self.runCmd("run", RUN_SUCCEEDED) + + process = target.GetProcess() + + # The stop reason of the thread should be breakpoint. + stepping_thread = lldbutil.get_one_thread_stopped_at_breakpoint(process, self.bkpt) + self.assertTrue(stepping_thread.IsValid(), "We stopped at the right breakpoint") + + # Get the number of threads + num_threads = process.GetNumThreads() + + # Make sure we see only two threads + self.assertTrue( + num_threads == 2, + 'Number of expected threads and actual threads do not match.') + + # Get the thread objects + thread1 = process.GetThreadAtIndex(0) + thread2 = process.GetThreadAtIndex(1) + + current_line = self.breakpoint + # Keep stepping until we've reached our designated continue point + while current_line != self.continuepoint: + if stepping_thread != process.GetSelectedThread(): + process.SetSelectedThread(stepping_thread) + + self.runCmd(step_cmd) + + frame = stepping_thread.GetFrameAtIndex(0) + current_line = frame.GetLineEntry().GetLine() + + # Make sure we're still where we thought we were + self.assertTrue( + current_line >= self.breakpoint, + "Stepped to unexpected line, " + + str(current_line)) + self.assertTrue( + current_line <= self.continuepoint, + "Stepped to unexpected line, " + + str(current_line)) + + # Update the number of threads + num_threads = process.GetNumThreads() + + # Check to see that we increased the number of threads as expected + self.assertTrue( + num_threads == 3, + 'Number of expected threads and actual threads do not match after thread exit.') + + stop_reason = stepping_thread.GetStopReason() + self.assertEqual(stop_reason, lldb.eStopReasonPlanComplete, "Stopped for plan completion") + + # Run to completion + self.runCmd("process continue") + + # At this point, the inferior process should have exited. + self.assertTrue( + process.GetState() == lldb.eStateExited, + PROCESS_EXITED) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/create_during_step/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/create_during_step/main.cpp new file mode 100644 index 00000000000..d09bdb0ddfc --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/create_during_step/main.cpp @@ -0,0 +1,78 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// This test is intended to create a situation in which one thread will be +// created while the debugger is stepping in another thread. + +#include "pseudo_barrier.h" +#include <thread> + +#define do_nothing() + +pseudo_barrier_t g_barrier; + +volatile int g_thread_created = 0; +volatile int g_test = 0; + +void * +step_thread_func () +{ + g_test = 0; // Set breakpoint here + + while (!g_thread_created) + g_test++; + + // One more time to provide a continue point + g_test++; // Continue from here + + // Return + return NULL; +} + +void * +create_thread_func (void *input) +{ + std::thread *step_thread = (std::thread*)input; + + // Wait until the main thread knows this thread is started. + pseudo_barrier_wait(g_barrier); + + // Wait until the other thread is done. + step_thread->join(); + + // Return + return NULL; +} + +int main () +{ + // Use a simple count to simulate a barrier. + pseudo_barrier_init(g_barrier, 2); + + // Create a thread to hit the breakpoint. + std::thread thread_1(step_thread_func); + + // Wait until the step thread is stepping + while (g_test < 1) + do_nothing(); + + // Create a thread to exit while we're stepping. + std::thread thread_2(create_thread_func, &thread_1); + + // Wait until that thread is started + pseudo_barrier_wait(g_barrier); + + // Let the stepping thread know the other thread is there + g_thread_created = 1; + + // Wait for the threads to finish. + thread_2.join(); + thread_1.join(); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/Makefile new file mode 100644 index 00000000000..566938ca0cc --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp +ENABLE_THREADS := YES +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/TestExitDuringBreak.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/TestExitDuringBreak.py new file mode 100644 index 00000000000..130abfe8652 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/TestExitDuringBreak.py @@ -0,0 +1,63 @@ +""" +Test number of threads. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ExitDuringBreakpointTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number for our breakpoint. + self.breakpoint = line_number('main.cpp', '// Set breakpoint here') + + def test(self): + """Test thread exit during breakpoint handling.""" + self.build(dictionary=self.getBuildFlags()) + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # This should create a breakpoint in the main thread. + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.breakpoint, num_expected_locations=1) + + # Run the program. + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # Get the target process + target = self.dbg.GetSelectedTarget() + process = target.GetProcess() + + # The exit probably occurred during breakpoint handling, but it isn't + # guaranteed. The main thing we're testing here is that the debugger + # handles this cleanly is some way. + + # Get the number of threads + num_threads = process.GetNumThreads() + + # Make sure we see at least five threads + self.assertTrue( + num_threads >= 5, + 'Number of expected threads and actual threads do not match.') + + # Run to completion + self.runCmd("continue") + + # At this point, the inferior process should have exited. + self.assertTrue( + process.GetState() == lldb.eStateExited, + PROCESS_EXITED) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/main.cpp new file mode 100644 index 00000000000..ec28678c5d6 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/main.cpp @@ -0,0 +1,117 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// This test is intended to create a situation in which one thread will exit +// while a breakpoint is being handled in another thread. This may not always +// happen because it's possible that the exiting thread will exit before the +// breakpoint is hit. The test case should be flexible enough to treat that +// as success. + +#include "pseudo_barrier.h" +#include <chrono> +#include <thread> + +volatile int g_test = 0; + +// A barrier to synchronize all the threads except the one that will exit. +pseudo_barrier_t g_barrier1; + +// A barrier to synchronize all the threads including the one that will exit. +pseudo_barrier_t g_barrier2; + +// A barrier to keep the first group of threads from exiting until after the +// breakpoint has been passed. +pseudo_barrier_t g_barrier3; + +void * +break_thread_func () +{ + // Wait until the entire first group of threads is running + pseudo_barrier_wait(g_barrier1); + + // Wait for the exiting thread to start + pseudo_barrier_wait(g_barrier2); + + // Do something + g_test++; // Set breakpoint here + + // Synchronize after the breakpoint + pseudo_barrier_wait(g_barrier3); + + // Return + return NULL; +} + +void * +wait_thread_func () +{ + // Wait until the entire first group of threads is running + pseudo_barrier_wait(g_barrier1); + + // Wait for the exiting thread to start + pseudo_barrier_wait(g_barrier2); + + // Wait until the breakpoint has been passed + pseudo_barrier_wait(g_barrier3); + + // Return + return NULL; +} + +void * +exit_thread_func () +{ + // Sync up with the rest of the threads. + pseudo_barrier_wait(g_barrier2); + + // Try to make sure this thread doesn't exit until the breakpoint is hit. + std::this_thread::sleep_for(std::chrono::microseconds(1)); + + // Return + return NULL; +} + +int main () +{ + + // The first barrier waits for the non-exiting threads to start. + // This thread will also participate in that barrier. + // The idea here is to guarantee that the exiting thread will be + // last in the internal list maintained by the debugger. + pseudo_barrier_init(g_barrier1, 5); + + // The second break synchronizes thread execution with the breakpoint. + pseudo_barrier_init(g_barrier2, 5); + + // The third barrier keeps the waiting threads around until the breakpoint + // has been passed. + pseudo_barrier_init(g_barrier3, 4); + + // Create a thread to hit the breakpoint + std::thread thread_1(break_thread_func); + + // Create more threads to slow the debugger down during processing. + std::thread thread_2(wait_thread_func); + std::thread thread_3(wait_thread_func); + std::thread thread_4(wait_thread_func); + + // Wait for all these threads to get started. + pseudo_barrier_wait(g_barrier1); + + // Create a thread to exit during the breakpoint + std::thread thread_5(exit_thread_func); + + // Wait for the threads to finish + thread_5.join(); + thread_4.join(); + thread_3.join(); + thread_2.join(); + thread_1.join(); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/Makefile new file mode 100644 index 00000000000..ebecfbf9241 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/Makefile @@ -0,0 +1,3 @@ +ENABLE_THREADS := YES +CXX_SOURCES := main.cpp +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/TestExitDuringStep.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/TestExitDuringStep.py new file mode 100644 index 00000000000..d35bd45fe80 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/TestExitDuringStep.py @@ -0,0 +1,150 @@ +""" +Test number of threads. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ExitDuringStepTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipIfFreeBSD # llvm.org/pr21411: test is hanging + @skipIfWindows # This is flakey on Windows: llvm.org/pr38373 + def test(self): + """Test thread exit during step handling.""" + self.build(dictionary=self.getBuildFlags()) + self.exit_during_step_base( + "thread step-inst -m all-threads", + 'stop reason = instruction step', + True) + + @skipIfFreeBSD # llvm.org/pr21411: test is hanging + @skipIfWindows # This is flakey on Windows: llvm.org/pr38373 + def test_step_over(self): + """Test thread exit during step-over handling.""" + self.build(dictionary=self.getBuildFlags()) + self.exit_during_step_base( + "thread step-over -m all-threads", + 'stop reason = step over', + False) + + @skipIfFreeBSD # llvm.org/pr21411: test is hanging + @skipIfWindows # This is flakey on Windows: llvm.org/pr38373 + def test_step_in(self): + """Test thread exit during step-in handling.""" + self.build(dictionary=self.getBuildFlags()) + self.exit_during_step_base( + "thread step-in -m all-threads", + 'stop reason = step in', + False) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line numbers to break and continue. + self.breakpoint = line_number('main.cpp', '// Set breakpoint here') + self.continuepoint = line_number('main.cpp', '// Continue from here') + + def exit_during_step_base(self, step_cmd, step_stop_reason, by_instruction): + """Test thread exit during step handling.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # This should create a breakpoint in the main thread. + self.bp_num = lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.breakpoint, num_expected_locations=1) + + # The breakpoint list should show 1 location. + self.expect( + "breakpoint list -f", + "Breakpoint location shown correctly", + substrs=[ + "1: file = 'main.cpp', line = %d, exact_match = 0, locations = 1" % + self.breakpoint]) + + # Run the program. + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # Get the target process + target = self.dbg.GetSelectedTarget() + process = target.GetProcess() + + num_threads = process.GetNumThreads() + # Make sure we see all three threads + self.assertGreaterEqual( + num_threads, + 3, + 'Number of expected threads and actual threads do not match.') + + stepping_thread = lldbutil.get_one_thread_stopped_at_breakpoint_id( + process, self.bp_num) + self.assertIsNotNone( + stepping_thread, + "Could not find a thread stopped at the breakpoint") + + current_line = self.breakpoint + stepping_frame = stepping_thread.GetFrameAtIndex(0) + self.assertEqual( + current_line, + stepping_frame.GetLineEntry().GetLine(), + "Starting line for stepping doesn't match breakpoint line.") + + # Keep stepping until we've reached our designated continue point + while current_line != self.continuepoint: + # Since we're using the command interpreter to issue the thread command + # (on the selected thread) we need to ensure the selected thread is the + # stepping thread. + if stepping_thread != process.GetSelectedThread(): + process.SetSelectedThread(stepping_thread) + + self.runCmd(step_cmd) + + frame = stepping_thread.GetFrameAtIndex(0) + + current_line = frame.GetLineEntry().GetLine() + + if by_instruction and current_line == 0: + continue + + self.assertGreaterEqual( + current_line, + self.breakpoint, + "Stepped to unexpected line, " + + str(current_line)) + self.assertLessEqual( + current_line, + self.continuepoint, + "Stepped to unexpected line, " + + str(current_line)) + + self.runCmd("thread list") + + # Update the number of threads + new_num_threads = process.GetNumThreads() + + # Check to see that we reduced the number of threads as expected + self.assertEqual( + new_num_threads, + num_threads - 1, + 'Number of threads did not reduce by 1 after thread exit.') + + self.expect("thread list", 'Process state is stopped due to step', + substrs=['stopped', + step_stop_reason]) + + # Run to completion + self.runCmd("continue") + + # At this point, the inferior process should have exited. + self.assertEqual(process.GetState(), lldb.eStateExited, PROCESS_EXITED) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/main.cpp new file mode 100644 index 00000000000..0e2ae00576c --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/main.cpp @@ -0,0 +1,77 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// This test is intended to create a situation in which one thread will exit +// while the debugger is stepping in another thread. + +#include "pseudo_barrier.h" +#include <thread> + +#define do_nothing() + +// A barrier to synchronize thread start. +pseudo_barrier_t g_barrier; + +volatile int g_thread_exited = 0; + +volatile int g_test = 0; + +void * +step_thread_func () +{ + // Wait until both threads are started. + pseudo_barrier_wait(g_barrier); + + g_test = 0; // Set breakpoint here + + while (!g_thread_exited) + g_test++; + + // One more time to provide a continue point + g_test++; // Continue from here + + // Return + return NULL; +} + +void * +exit_thread_func () +{ + // Wait until both threads are started. + pseudo_barrier_wait(g_barrier); + + // Wait until the other thread is stepping. + while (g_test == 0) + do_nothing(); + + // Return + return NULL; +} + +int main () +{ + // Synchronize thread start so that doesn't happen during stepping. + pseudo_barrier_init(g_barrier, 2); + + // Create a thread to hit the breakpoint. + std::thread thread_1(step_thread_func); + + // Create a thread to exit while we're stepping. + std::thread thread_2(exit_thread_func); + + // Wait for the exit thread to finish. + thread_2.join(); + + // Let the stepping thread know the other thread is gone. + g_thread_exited = 1; + + // Wait for the stepping thread to finish. + thread_1.join(); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/jump/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/jump/Makefile new file mode 100644 index 00000000000..6e962b97209 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/jump/Makefile @@ -0,0 +1,3 @@ +ENABLE_THREADS := YES +CXX_SOURCES := main.cpp other.cpp +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/jump/TestThreadJump.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/jump/TestThreadJump.py new file mode 100644 index 00000000000..2035435442f --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/jump/TestThreadJump.py @@ -0,0 +1,78 @@ +""" +Test jumping to different places. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ThreadJumpTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test(self): + """Test thread jump handling.""" + self.build(dictionary=self.getBuildFlags()) + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Find the line numbers for our breakpoints. + self.mark1 = line_number('main.cpp', '// 1st marker') + self.mark2 = line_number('main.cpp', '// 2nd marker') + self.mark3 = line_number('main.cpp', '// 3rd marker') + self.mark4 = line_number('main.cpp', '// 4th marker') + self.mark5 = line_number('other.cpp', '// other marker') + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.mark3, num_expected_locations=1) + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint 1. + self.expect( + "thread list", + STOPPED_DUE_TO_BREAKPOINT + " 1", + substrs=[ + 'stopped', + 'main.cpp:{}'.format( + self.mark3), + 'stop reason = breakpoint 1']) + + # Try the int path, force it to return 'a' + self.do_min_test(self.mark3, self.mark1, "i", "4") + # Try the int path, force it to return 'b' + self.do_min_test(self.mark3, self.mark2, "i", "5") + # Try the double path, force it to return 'a' + self.do_min_test(self.mark4, self.mark1, "j", "7") + # Expected to fail on powerpc64le architecture + if not self.isPPC64le(): + # Try the double path, force it to return 'b' + self.do_min_test(self.mark4, self.mark2, "j", "8") + + # Try jumping to another function in a different file. + self.runCmd( + "thread jump --file other.cpp --line %i --force" % + self.mark5) + self.expect("process status", + substrs=["at other.cpp:%i" % self.mark5]) + + # Try jumping to another function (without forcing) + self.expect( + "j main.cpp:%i" % + self.mark1, + COMMAND_FAILED_AS_EXPECTED, + error=True, + substrs=["error"]) + + def do_min_test(self, start, jump, var, value): + # jump to the start marker + self.runCmd("j %i" % start) + self.runCmd("thread step-in") # step into the min fn + # jump to the branch we're interested in + self.runCmd("j %i" % jump) + self.runCmd("thread step-out") # return out + self.runCmd("thread step-over") # assign to the global + self.expect("expr %s" % var, substrs=[value]) # check it diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/jump/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/jump/main.cpp new file mode 100644 index 00000000000..e0580bd2542 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/jump/main.cpp @@ -0,0 +1,34 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// This test verifies the correct handling of program counter jumps. + +int otherfn(); + +template<typename T> +T min(T a, T b) +{ + if (a < b) + { + return a; // 1st marker + } else { + return b; // 2nd marker + } +} + +int main () +{ + int i; + double j; + int min_i_a = 4, min_i_b = 5; + double min_j_a = 7.0, min_j_b = 8.0; + i = min(min_i_a, min_i_b); // 3rd marker + j = min(min_j_a, min_j_b); // 4th marker + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/jump/other.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/jump/other.cpp new file mode 100644 index 00000000000..3ce9ad6548b --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/jump/other.cpp @@ -0,0 +1,12 @@ +//===-- other.cpp -----------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +int otherfn() +{ + return 4; // other marker +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/multi_break/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/multi_break/Makefile new file mode 100644 index 00000000000..566938ca0cc --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/multi_break/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp +ENABLE_THREADS := YES +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/multi_break/TestMultipleBreakpoints.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/multi_break/TestMultipleBreakpoints.py new file mode 100644 index 00000000000..20645fbc63e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/multi_break/TestMultipleBreakpoints.py @@ -0,0 +1,90 @@ +""" +Test number of threads. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class MultipleBreakpointTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number for our breakpoint. + self.breakpoint = line_number('main.cpp', '// Set breakpoint here') + + @expectedFailureAll( + oslist=["linux"], + bugnumber="llvm.org/pr15824 thread states not properly maintained") + @expectedFailureAll( + oslist=lldbplatformutil.getDarwinOSTriples(), + bugnumber="llvm.org/pr15824 thread states not properly maintained and <rdar://problem/28557237>") + @expectedFailureAll( + oslist=["freebsd"], + bugnumber="llvm.org/pr18190 thread states not properly maintained") + @skipIfWindows # This is flakey on Windows: llvm.org/pr24668, llvm.org/pr38373 + @expectedFailureNetBSD + def test(self): + """Test simultaneous breakpoints in multiple threads.""" + self.build(dictionary=self.getBuildFlags()) + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # This should create a breakpoint in the main thread. + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.breakpoint, num_expected_locations=1) + + # Run the program. + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + # The breakpoint may be hit in either thread 2 or thread 3. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # Get the target process + target = self.dbg.GetSelectedTarget() + process = target.GetProcess() + + # Get the number of threads + num_threads = process.GetNumThreads() + + # Make sure we see all three threads + self.assertTrue( + num_threads >= 3, + 'Number of expected threads and actual threads do not match.') + + # Get the thread objects + thread1 = process.GetThreadAtIndex(0) + thread2 = process.GetThreadAtIndex(1) + thread3 = process.GetThreadAtIndex(2) + + # Make sure both threads are stopped + self.assertTrue( + thread1.IsStopped(), + "Primary thread didn't stop during breakpoint") + self.assertTrue( + thread2.IsStopped(), + "Secondary thread didn't stop during breakpoint") + self.assertTrue( + thread3.IsStopped(), + "Tertiary thread didn't stop during breakpoint") + + # Delete the first breakpoint then continue + self.runCmd("breakpoint delete 1") + + # Run to completion + self.runCmd("continue") + + # At this point, the inferior process should have exited. + self.assertTrue( + process.GetState() == lldb.eStateExited, + PROCESS_EXITED) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/multi_break/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/multi_break/main.cpp new file mode 100644 index 00000000000..5f884d75866 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/multi_break/main.cpp @@ -0,0 +1,48 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// This test is intended to create a situation in which a breakpoint will be +// hit in two threads at nearly the same moment. The expected result is that +// the breakpoint in the second thread will be hit while the breakpoint handler +// in the first thread is trying to stop all threads. + +#include "pseudo_barrier.h" +#include <thread> + +pseudo_barrier_t g_barrier; + +volatile int g_test = 0; + +void * +thread_func () +{ + // Wait until both threads are running + pseudo_barrier_wait(g_barrier); + + // Do something + g_test++; // Set breakpoint here + + // Return + return NULL; +} + +int main () +{ + // Don't let either thread do anything until they're both ready. + pseudo_barrier_init(g_barrier, 2); + + // Create two threads + std::thread thread_1(thread_func); + std::thread thread_2(thread_func); + + // Wait for the threads to finish + thread_1.join(); + thread_2.join(); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/num_threads/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/num_threads/Makefile new file mode 100644 index 00000000000..566938ca0cc --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/num_threads/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp +ENABLE_THREADS := YES +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py new file mode 100644 index 00000000000..cfd2941ad19 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py @@ -0,0 +1,123 @@ +""" +Test number of threads. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class NumberOfThreadsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line numbers for our break points. + self.thread3_notify_all_line = line_number('main.cpp', '// Set thread3 break point on notify_all at this line.') + self.thread3_before_lock_line = line_number('main.cpp', '// thread3-before-lock') + + def test_number_of_threads(self): + """Test number of threads.""" + self.build() + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # This should create a breakpoint with 1 location. + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.thread3_notify_all_line, num_expected_locations=1) + + # The breakpoint list should show 1 location. + self.expect( + "breakpoint list -f", + "Breakpoint location shown correctly", + substrs=[ + "1: file = 'main.cpp', line = %d, exact_match = 0, locations = 1" % + self.thread3_notify_all_line]) + + # Run the program. + self.runCmd("run", RUN_SUCCEEDED) + + # Stopped once. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=["stop reason = breakpoint 1."]) + + # Get the target process + target = self.dbg.GetSelectedTarget() + process = target.GetProcess() + + # Get the number of threads + num_threads = process.GetNumThreads() + + # Using std::thread may involve extra threads, so we assert that there are + # at least 4 rather than exactly 4. + self.assertTrue( + num_threads >= 13, + 'Number of expected threads and actual threads do not match.') + + @skipIfDarwin # rdar://33462362 + @skipIfWindows # This is flakey on Windows: llvm.org/pr37658, llvm.org/pr38373 + @expectedFailureNetBSD + def test_unique_stacks(self): + """Test backtrace unique with multiple threads executing the same stack.""" + self.build() + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Set a break point on the thread3 notify all (should get hit on threads 4-13). + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.thread3_before_lock_line, num_expected_locations=1) + + # Run the program. + self.runCmd("run", RUN_SUCCEEDED) + + # Stopped once. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=["stop reason = breakpoint 1."]) + + process = self.process() + + # Get the number of threads + num_threads = process.GetNumThreads() + + # Using std::thread may involve extra threads, so we assert that there are + # at least 10 thread3's rather than exactly 10. + self.assertTrue( + num_threads >= 10, + 'Number of expected threads and actual threads do not match.') + + # Attempt to walk each of the thread's executing the thread3 function to + # the same breakpoint. + def is_thread3(thread): + for frame in thread: + if "thread3" in frame.GetFunctionName(): return True + return False + + expect_threads = "" + for i in range(num_threads): + thread = process.GetThreadAtIndex(i) + self.assertTrue(thread.IsValid()) + if not is_thread3(thread): + continue + + # If we aren't stopped out the thread breakpoint try to resume. + if thread.GetStopReason() != lldb.eStopReasonBreakpoint: + self.runCmd("thread continue %d"%(i+1)) + self.assertEqual(thread.GetStopReason(), lldb.eStopReasonBreakpoint) + + expect_threads += " #%d"%(i+1) + + # Construct our expected back trace string + expect_string = "10 thread(s)%s" % (expect_threads) + + # Now that we are stopped, we should have 10 threads waiting in the + # thread3 function. All of these threads should show as one stack. + self.expect("thread backtrace unique", + "Backtrace with unique stack shown correctly", + substrs=[expect_string, + "main.cpp:%d"%self.thread3_before_lock_line]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/num_threads/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/num_threads/main.cpp new file mode 100644 index 00000000000..fdc060d135d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/num_threads/main.cpp @@ -0,0 +1,65 @@ +#include "pseudo_barrier.h" +#include <condition_variable> +#include <mutex> +#include <thread> +#include <vector> + +std::mutex mutex; +std::condition_variable cond; +pseudo_barrier_t thread3_barrier; + +void * +thread3(void *input) +{ + pseudo_barrier_wait(thread3_barrier); + + int dummy = 47; // thread3-before-lock + + std::unique_lock<std::mutex> lock(mutex); + cond.notify_all(); // Set thread3 break point on notify_all at this line. + return NULL; +} + +void * +thread2(void *input) +{ + std::unique_lock<std::mutex> lock(mutex); + cond.notify_all(); // release main thread + cond.wait(lock); + return NULL; +} + +void * +thread1(void *input) +{ + std::thread thread_2(thread2, nullptr); + thread_2.join(); + + return NULL; +} + +int main() +{ + std::unique_lock<std::mutex> lock(mutex); + + std::thread thread_1(thread1, nullptr); + cond.wait(lock); // wait for thread2 + + pseudo_barrier_init(thread3_barrier, 10); + + std::vector<std::thread> thread_3s; + for (int i = 0; i < 10; i++) { + thread_3s.push_back(std::thread(thread3, nullptr)); + } + + cond.wait(lock); // wait for thread_3s + + lock.unlock(); + + thread_1.join(); + for (auto &t : thread_3s){ + t.join(); + } + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/state/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/state/Makefile new file mode 100644 index 00000000000..3d0b98f13f3 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/state/Makefile @@ -0,0 +1,2 @@ +CXX_SOURCES := main.cpp +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/state/TestThreadStates.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/state/TestThreadStates.py new file mode 100644 index 00000000000..60938088c9a --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/state/TestThreadStates.py @@ -0,0 +1,326 @@ +""" +Test thread states. +""" + + + +import unittest2 +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ThreadStateTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll( + oslist=["linux"], + bugnumber="llvm.org/pr15824 thread states not properly maintained") + @skipIfDarwin # llvm.org/pr15824 thread states not properly maintained and <rdar://problem/28557237> + @expectedFailureAll( + oslist=["freebsd"], + bugnumber="llvm.org/pr18190 thread states not properly maintained") + @expectedFailureNetBSD + def test_state_after_breakpoint(self): + """Test thread state after breakpoint.""" + self.build(dictionary=self.getBuildFlags(use_cpp11=False)) + self.thread_state_after_breakpoint_test() + + @skipIfDarwin # 'llvm.org/pr23669', cause Python crash randomly + @expectedFailureAll( + oslist=lldbplatformutil.getDarwinOSTriples(), + bugnumber="llvm.org/pr23669") + @expectedFailureAll(oslist=["freebsd"], bugnumber="llvm.org/pr15824") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24660") + def test_state_after_continue(self): + """Test thread state after continue.""" + self.build(dictionary=self.getBuildFlags(use_cpp11=False)) + self.thread_state_after_continue_test() + + @skipIfDarwin # 'llvm.org/pr23669', cause Python crash randomly + @expectedFailureDarwin('llvm.org/pr23669') + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24660") + @expectedFailureNetBSD + # thread states not properly maintained + @unittest2.expectedFailure("llvm.org/pr16712") + def test_state_after_expression(self): + """Test thread state after expression.""" + self.build(dictionary=self.getBuildFlags(use_cpp11=False)) + self.thread_state_after_expression_test() + + # thread states not properly maintained + @unittest2.expectedFailure("llvm.org/pr15824 and <rdar://problem/28557237>") + @expectedFailureAll( + oslist=["windows"], + bugnumber="llvm.org/pr24668: Breakpoints not resolved correctly") + @skipIfDarwin # llvm.org/pr15824 thread states not properly maintained and <rdar://problem/28557237> + @expectedFailureNetBSD + def test_process_state(self): + """Test thread states (comprehensive).""" + self.build(dictionary=self.getBuildFlags(use_cpp11=False)) + self.thread_states_test() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line numbers for our breakpoints. + self.break_1 = line_number('main.cpp', '// Set first breakpoint here') + self.break_2 = line_number('main.cpp', '// Set second breakpoint here') + + def thread_state_after_breakpoint_test(self): + """Test thread state after breakpoint.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # This should create a breakpoint in the main thread. + bp = lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.break_1, num_expected_locations=1) + + # Run the program. + self.runCmd("run", RUN_SUCCEEDED) + + # Get the target process + target = self.dbg.GetSelectedTarget() + process = target.GetProcess() + + thread = lldbutil.get_stopped_thread( + process, lldb.eStopReasonBreakpoint) + self.assertIsNotNone(thread) + + # Make sure the thread is in the stopped state. + self.assertTrue( + thread.IsStopped(), + "Thread state isn't \'stopped\' during breakpoint 1.") + self.assertFalse(thread.IsSuspended(), + "Thread state is \'suspended\' during breakpoint 1.") + + # Kill the process + self.runCmd("process kill") + + def wait_for_running_event(self, process): + listener = self.dbg.GetListener() + if lldb.remote_platform: + lldbutil.expect_state_changes( + self, listener, process, [ + lldb.eStateConnected]) + lldbutil.expect_state_changes( + self, listener, process, [ + lldb.eStateRunning]) + + def thread_state_after_continue_test(self): + """Test thread state after continue.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # This should create a breakpoint in the main thread. + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.break_1, num_expected_locations=1) + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.break_2, num_expected_locations=1) + + # Run the program. + self.runCmd("run", RUN_SUCCEEDED) + + # Get the target process + target = self.dbg.GetSelectedTarget() + process = target.GetProcess() + + thread = lldbutil.get_stopped_thread( + process, lldb.eStopReasonBreakpoint) + self.assertIsNotNone(thread) + + # Continue, the inferior will go into an infinite loop waiting for + # 'g_test' to change. + self.dbg.SetAsync(True) + self.runCmd("continue") + self.wait_for_running_event(process) + + # Check the thread state. It should be running. + self.assertFalse( + thread.IsStopped(), + "Thread state is \'stopped\' when it should be running.") + self.assertFalse( + thread.IsSuspended(), + "Thread state is \'suspended\' when it should be running.") + + # Go back to synchronous interactions + self.dbg.SetAsync(False) + + # Kill the process + self.runCmd("process kill") + + def thread_state_after_expression_test(self): + """Test thread state after expression.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # This should create a breakpoint in the main thread. + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.break_1, num_expected_locations=1) + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.break_2, num_expected_locations=1) + + # Run the program. + self.runCmd("run", RUN_SUCCEEDED) + + # Get the target process + target = self.dbg.GetSelectedTarget() + process = target.GetProcess() + + thread = lldbutil.get_stopped_thread( + process, lldb.eStopReasonBreakpoint) + self.assertIsNotNone(thread) + + # Get the inferior out of its loop + self.runCmd("expression g_test = 1") + + # Check the thread state + self.assertTrue( + thread.IsStopped(), + "Thread state isn't \'stopped\' after expression evaluation.") + self.assertFalse( + thread.IsSuspended(), + "Thread state is \'suspended\' after expression evaluation.") + + # Let the process run to completion + self.runCmd("process continue") + + @expectedFailureAll( + oslist=["windows"], + bugnumber="llvm.org/pr24668: Breakpoints not resolved correctly") + @skipIfDarwin # llvm.org/pr15824 thread states not properly maintained and <rdar://problem/28557237> + @no_debug_info_test + def test_process_interrupt(self): + """Test process interrupt and continue.""" + self.build(dictionary=self.getBuildFlags(use_cpp11=False)) + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # This should create a breakpoint in the main thread. + bpno = lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.break_1, num_expected_locations=1) + + # Run the program. + self.runCmd("run", RUN_SUCCEEDED) + + # Get the target process + target = self.dbg.GetSelectedTarget() + process = target.GetProcess() + + thread = lldbutil.get_stopped_thread( + process, lldb.eStopReasonBreakpoint) + self.assertIsNotNone(thread) + + # Remove the breakpoint to avoid the single-step-over-bkpt dance in the + # "continue" below + self.assertTrue(target.BreakpointDelete(bpno)) + + # Continue, the inferior will go into an infinite loop waiting for + # 'g_test' to change. + self.dbg.SetAsync(True) + self.runCmd("continue") + self.wait_for_running_event(process) + + # Go back to synchronous interactions + self.dbg.SetAsync(False) + + # Stop the process + self.runCmd("process interrupt") + + self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal) + + # Get the inferior out of its loop + self.runCmd("expression g_test = 1") + + # Run to completion + self.runCmd("continue") + + def thread_states_test(self): + """Test thread states (comprehensive).""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # This should create a breakpoint in the main thread. + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.break_1, num_expected_locations=1) + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.break_2, num_expected_locations=1) + + # Run the program. + self.runCmd("run", RUN_SUCCEEDED) + + # Get the target process + target = self.dbg.GetSelectedTarget() + process = target.GetProcess() + thread = lldbutil.get_stopped_thread( + process, lldb.eStopReasonBreakpoint) + self.assertIsNotNone(thread) + + # Make sure the thread is in the stopped state. + self.assertTrue( + thread.IsStopped(), + "Thread state isn't \'stopped\' during breakpoint 1.") + self.assertFalse(thread.IsSuspended(), + "Thread state is \'suspended\' during breakpoint 1.") + + # Continue, the inferior will go into an infinite loop waiting for + # 'g_test' to change. + self.dbg.SetAsync(True) + self.runCmd("continue") + self.wait_for_running_event(process) + + # Check the thread state. It should be running. + self.assertFalse( + thread.IsStopped(), + "Thread state is \'stopped\' when it should be running.") + self.assertFalse( + thread.IsSuspended(), + "Thread state is \'suspended\' when it should be running.") + + # Go back to synchronous interactions + self.dbg.SetAsync(False) + + # Stop the process + self.runCmd("process interrupt") + + self.assertEqual(thread.GetState(), lldb.eStopReasonSignal) + + # Check the thread state + self.assertTrue( + thread.IsStopped(), + "Thread state isn't \'stopped\' after process stop.") + self.assertFalse(thread.IsSuspended(), + "Thread state is \'suspended\' after process stop.") + + # Get the inferior out of its loop + self.runCmd("expression g_test = 1") + + # Check the thread state + self.assertTrue( + thread.IsStopped(), + "Thread state isn't \'stopped\' after expression evaluation.") + self.assertFalse( + thread.IsSuspended(), + "Thread state is \'suspended\' after expression evaluation.") + + self.assertEqual(thread.GetState(), lldb.eStopReasonSignal) + + # Run to breakpoint 2 + self.runCmd("continue") + + self.assertEqual(thread.GetState(), lldb.eStopReasonBreakpoint) + + # Make sure both threads are stopped + self.assertTrue( + thread.IsStopped(), + "Thread state isn't \'stopped\' during breakpoint 2.") + self.assertFalse(thread.IsSuspended(), + "Thread state is \'suspended\' during breakpoint 2.") + + # Run to completion + self.runCmd("continue") + + # At this point, the inferior process should have exited. + self.assertEqual(process.GetState(), lldb.eStateExited, PROCESS_EXITED) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/state/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/state/main.cpp new file mode 100644 index 00000000000..63b50494bd0 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/state/main.cpp @@ -0,0 +1,44 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// This test is intended to verify that thread states are properly maintained +// when transitional actions are performed in the debugger. Most of the logic +// is in the test script. This program merely provides places where the test +// can create the intended states. + +#include <chrono> +#include <thread> + +volatile int g_test = 0; + +int addSomething(int a) +{ + return a + g_test; +} + +int doNothing() +{ + int temp = 0; // Set first breakpoint here + + while (!g_test && temp < 5) + { + ++temp; + std::this_thread::sleep_for(std::chrono::seconds(2)); + } + + return temp; // Set second breakpoint here +} + +int main () +{ + int result = doNothing(); + + int i = addSomething(result); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_out/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_out/Makefile new file mode 100644 index 00000000000..c46619c6623 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_out/Makefile @@ -0,0 +1,4 @@ +CXX_SOURCES := main.cpp +ENABLE_THREADS := YES + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_out/TestThreadStepOut.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_out/TestThreadStepOut.py new file mode 100644 index 00000000000..2d9632eb2dd --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_out/TestThreadStepOut.py @@ -0,0 +1,156 @@ +""" +Test stepping out from a function in a multi-threaded program. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ThreadStepOutTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # Test occasionally times out on the Linux build bot + @skipIfLinux + @expectedFailureAll( + oslist=["linux"], + bugnumber="llvm.org/pr23477 Test occasionally times out on the Linux build bot") + @expectedFailureAll( + oslist=["freebsd"], + bugnumber="llvm.org/pr18066 inferior does not exit") + @skipIfWindows # This test will hang on windows llvm.org/pr21753 + @expectedFailureAll(oslist=["windows"]) + @expectedFailureNetBSD + def test_step_single_thread(self): + """Test thread step out on one thread via command interpreter. """ + self.build(dictionary=self.getBuildFlags()) + self.step_out_test(self.step_out_single_thread_with_cmd) + + # Test occasionally times out on the Linux build bot + @skipIfLinux + @expectedFailureAll( + oslist=["linux"], + bugnumber="llvm.org/pr23477 Test occasionally times out on the Linux build bot") + @expectedFailureAll( + oslist=["freebsd"], + bugnumber="llvm.org/pr19347 2nd thread stops at breakpoint") + @skipIfWindows # This test will hang on windows llvm.org/pr21753 + @expectedFailureAll(oslist=["windows"]) + @expectedFailureAll(oslist=["watchos"], archs=['armv7k'], bugnumber="rdar://problem/34674488") # stop reason is trace when it should be step-out + @expectedFailureNetBSD + def test_step_all_threads(self): + """Test thread step out on all threads via command interpreter. """ + self.build(dictionary=self.getBuildFlags()) + self.step_out_test(self.step_out_all_threads_with_cmd) + + # Test occasionally times out on the Linux build bot + @skipIfLinux + @expectedFailureAll( + oslist=["linux"], + bugnumber="llvm.org/pr23477 Test occasionally times out on the Linux build bot") + @expectedFailureAll( + oslist=["freebsd"], + bugnumber="llvm.org/pr19347 2nd thread stops at breakpoint") + @skipIfWindows # This test will hang on windows llvm.org/pr21753 + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24681") + @expectedFailureNetBSD + def test_python(self): + """Test thread step out on one thread via Python API (dwarf).""" + self.build(dictionary=self.getBuildFlags()) + self.step_out_test(self.step_out_with_python) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number for our breakpoint. + self.bkpt_string = '// Set breakpoint here' + self.breakpoint = line_number('main.cpp', self.bkpt_string) + + if "gcc" in self.getCompiler() or self.isIntelCompiler() or self.getArchitecture() in ['arm64', 'arm64e']: + self.step_out_destination = line_number( + 'main.cpp', '// Expect to stop here after step-out (icc and gcc; arm64)') + else: + self.step_out_destination = line_number( + 'main.cpp', '// Expect to stop here after step-out (clang)') + + def step_out_single_thread_with_cmd(self): + self.step_out_with_cmd("this-thread") + self.expect( + "thread backtrace all", + "Thread location after step out is correct", + substrs=[ + "main.cpp:%d" % + self.step_out_destination, + "main.cpp:%d" % + self.breakpoint]) + + def step_out_all_threads_with_cmd(self): + self.step_out_with_cmd("all-threads") + self.expect( + "thread backtrace all", + "Thread location after step out is correct", + substrs=[ + "main.cpp:%d" % + self.step_out_destination]) + + def step_out_with_cmd(self, run_mode): + self.runCmd("thread select %d" % self.step_out_thread.GetIndexID()) + self.runCmd("thread step-out -m %s" % run_mode) + self.expect("process status", "Expected stop reason to be step-out", + substrs=["stop reason = step out"]) + + self.expect( + "thread list", + "Selected thread did not change during step-out", + substrs=[ + "* thread #%d" % + self.step_out_thread.GetIndexID()]) + + def step_out_with_python(self): + self.step_out_thread.StepOut() + + reason = self.step_out_thread.GetStopReason() + self.assertEqual( + lldb.eStopReasonPlanComplete, + reason, + "Expected thread stop reason 'plancomplete', but got '%s'" % + lldbutil.stop_reason_to_str(reason)) + + # Verify location after stepping out + frame = self.step_out_thread.GetFrameAtIndex(0) + desc = lldbutil.get_description(frame.GetLineEntry()) + expect = "main.cpp:%d" % self.step_out_destination + self.assertTrue( + expect in desc, "Expected %s but thread stopped at %s" % + (expect, desc)) + + def step_out_test(self, step_out_func): + """Test single thread step out of a function.""" + (self.inferior_target, self.inferior_process, thread, bkpt) = lldbutil.run_to_source_breakpoint( + self, self.bkpt_string, lldb.SBFileSpec('main.cpp'), only_one_thread = False) + + # We hit the breakpoint on at least one thread. If we hit it on both threads + # simultaneously, we can try the step out. Otherwise, suspend the thread + # that hit the breakpoint, and continue till the second thread hits + # the breakpoint: + + (breakpoint_threads, other_threads) = ([], []) + lldbutil.sort_stopped_threads(self.inferior_process, + breakpoint_threads=breakpoint_threads, + other_threads=other_threads) + if len(breakpoint_threads) == 1: + success = thread.Suspend() + self.assertTrue(success, "Couldn't suspend a thread") + bkpt_threads = lldbutil.continue_to_breakpoint(bkpt) + self.assertEqual(len(bkpt_threads), 1, "Second thread stopped") + success = thread.Resume() + self.assertTrue(success, "Couldn't resume a thread") + + self.step_out_thread = breakpoint_threads[0] + + # Step out of thread stopped at breakpoint + step_out_func() diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_out/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_out/main.cpp new file mode 100644 index 00000000000..e7754d0ac74 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_out/main.cpp @@ -0,0 +1,50 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// This test is intended to create a situation in which two threads are stopped +// at a breakpoint and the debugger issues a step-out command. + +#include "pseudo_barrier.h" +#include <thread> + +pseudo_barrier_t g_barrier; + +volatile int g_test = 0; + +void step_out_of_here() { + g_test += 5; // Set breakpoint here +} + +void * +thread_func () +{ + // Wait until both threads are running + pseudo_barrier_wait(g_barrier); + + // Do something + step_out_of_here(); // Expect to stop here after step-out (clang) + + // Return + return NULL; // Expect to stop here after step-out (icc and gcc; arm64) +} + +int main () +{ + // Don't let either thread do anything until they're both ready. + pseudo_barrier_init(g_barrier, 2); + + // Create two threads + std::thread thread_1(thread_func); + std::thread thread_2(thread_func); + + // Wait for the threads to finish + thread_1.join(); + thread_2.join(); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_until/.categories b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_until/.categories new file mode 100644 index 00000000000..c00c25822e4 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_until/.categories @@ -0,0 +1 @@ +basic_process diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_until/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_until/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_until/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_until/TestStepUntil.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_until/TestStepUntil.py new file mode 100644 index 00000000000..dd48ebaf8e1 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_until/TestStepUntil.py @@ -0,0 +1,86 @@ +"""Test stepping over vrs. hitting breakpoints & subsequent stepping in various forms.""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class StepUntilTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line numbers that we will step to in main: + self.main_source = "main.c" + self.less_than_two = line_number('main.c', 'Less than 2') + self.greater_than_two = line_number('main.c', 'Greater than or equal to 2.') + self.back_out_in_main = line_number('main.c', 'Back out in main') + + def do_until (self, args, until_lines, expected_linenum): + self.build() + exe = self.getBuildArtifact("a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + main_source_spec = lldb.SBFileSpec(self.main_source) + break_before = target.BreakpointCreateBySourceRegex( + 'At the start', + main_source_spec) + self.assertTrue(break_before, VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple( + args, None, self.get_process_working_directory()) + + self.assertTrue(process, PROCESS_IS_VALID) + + # The stop reason of the thread should be breakpoint. + threads = lldbutil.get_threads_stopped_at_breakpoint( + process, break_before) + + if len(threads) != 1: + self.fail("Failed to stop at first breakpoint in main.") + + thread = threads[0] + return thread + + thread = self.common_setup(None) + + cmd_interp = self.dbg.GetCommandInterpreter() + ret_obj = lldb.SBCommandReturnObject() + + cmd_line = "thread until" + for line_num in until_lines: + cmd_line += " %d"%(line_num) + + cmd_interp.HandleCommand(cmd_line, ret_obj) + self.assertTrue(ret_obj.Succeeded(), "'%s' failed: %s."%(cmd_line, ret_obj.GetError())) + + frame = thread.frames[0] + line = frame.GetLineEntry().GetLine() + self.assertEqual(line, expected_linenum, 'Did not get the expected stop line number') + + def test_hitting_one (self): + """Test thread step until - targeting one line and hitting it.""" + self.do_until(None, [self.less_than_two], self.less_than_two) + + def test_targetting_two_hitting_first (self): + """Test thread step until - targeting two lines and hitting one.""" + self.do_until(["foo", "bar", "baz"], [self.less_than_two, self.greater_than_two], self.greater_than_two) + + def test_targetting_two_hitting_second (self): + """Test thread step until - targeting two lines and hitting the other one.""" + self.do_until(None, [self.less_than_two, self.greater_than_two], self.less_than_two) + + def test_missing_one (self): + """Test thread step until - targeting one line and missing it.""" + self.do_until(["foo", "bar", "baz"], [self.less_than_two], self.back_out_in_main) + + + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_until/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_until/main.c new file mode 100644 index 00000000000..e0b4d8ab951 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_until/main.c @@ -0,0 +1,20 @@ +#include <stdio.h> + +void call_me(int argc) +{ + printf ("At the start, argc: %d.\n", argc); + + if (argc < 2) + printf("Less than 2.\n"); + else + printf("Greater than or equal to 2.\n"); +} + +int +main(int argc, char **argv) +{ + call_me(argc); + printf("Back out in main.\n"); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/Makefile new file mode 100644 index 00000000000..ebecfbf9241 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/Makefile @@ -0,0 +1,3 @@ +ENABLE_THREADS := YES +CXX_SOURCES := main.cpp +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/TestThreadExit.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/TestThreadExit.py new file mode 100644 index 00000000000..6bd55e1753f --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/TestThreadExit.py @@ -0,0 +1,121 @@ +""" +Test number of threads. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class ThreadExitTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line numbers for our breakpoints. + self.break_1 = line_number('main.cpp', '// Set first breakpoint here') + self.break_2 = line_number('main.cpp', '// Set second breakpoint here') + self.break_3 = line_number('main.cpp', '// Set third breakpoint here') + self.break_4 = line_number('main.cpp', '// Set fourth breakpoint here') + + @skipIfWindows # This is flakey on Windows: llvm.org/pr38373 + def test(self): + """Test thread exit handling.""" + self.build(dictionary=self.getBuildFlags()) + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # This should create a breakpoint with 1 location. + bp1_id = lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.break_1, num_expected_locations=1) + bp2_id = lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.break_2, num_expected_locations=1) + bp3_id = lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.break_3, num_expected_locations=1) + bp4_id = lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.break_4, num_expected_locations=1) + + # The breakpoint list should show 1 locations. + self.expect( + "breakpoint list -f", + "Breakpoint location shown correctly", + substrs=[ + "1: file = 'main.cpp', line = %d, exact_match = 0, locations = 1" % + self.break_1, + "2: file = 'main.cpp', line = %d, exact_match = 0, locations = 1" % + self.break_2, + "3: file = 'main.cpp', line = %d, exact_match = 0, locations = 1" % + self.break_3, + "4: file = 'main.cpp', line = %d, exact_match = 0, locations = 1" % + self.break_4]) + + # Run the program. + self.runCmd("run", RUN_SUCCEEDED) + # Get the target process + target = self.dbg.GetSelectedTarget() + process = target.GetProcess() + + stopped_thread = lldbutil.get_one_thread_stopped_at_breakpoint_id( + process, bp1_id) + self.assertIsNotNone(stopped_thread, + "Process is not stopped at breakpoint 1") + + # Get the number of threads + num_threads = process.GetNumThreads() + self.assertGreaterEqual( + num_threads, + 2, + 'Number of expected threads and actual threads do not match at breakpoint 1.') + + # Run to the second breakpoint + self.runCmd("continue") + stopped_thread = lldbutil.get_one_thread_stopped_at_breakpoint_id( + process, bp2_id) + self.assertIsNotNone(stopped_thread, + "Process is not stopped at breakpoint 2") + + # Update the number of threads + new_num_threads = process.GetNumThreads() + self.assertEqual( + new_num_threads, + num_threads + 1, + 'Number of expected threads did not increase by 1 at bp 2.') + + # Run to the third breakpoint + self.runCmd("continue") + stopped_thread = lldbutil.get_one_thread_stopped_at_breakpoint_id( + process, bp3_id) + self.assertIsNotNone(stopped_thread, + "Process is not stopped at breakpoint 3") + + # Update the number of threads + new_num_threads = process.GetNumThreads() + self.assertEqual( + new_num_threads, + num_threads, + 'Number of expected threads is not equal to original number of threads at bp 3.') + + # Run to the fourth breakpoint + self.runCmd("continue") + stopped_thread = lldbutil.get_one_thread_stopped_at_breakpoint_id( + process, bp4_id) + self.assertIsNotNone(stopped_thread, + "Process is not stopped at breakpoint 4") + + # Update the number of threads + new_num_threads = process.GetNumThreads() + self.assertEqual( + new_num_threads, + num_threads - 1, + 'Number of expected threads did not decrease by 1 at bp 4.') + + # Run to completion + self.runCmd("continue") + + # At this point, the inferior process should have exited. + self.assertEqual(process.GetState(), lldb.eStateExited, PROCESS_EXITED) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/main.cpp new file mode 100644 index 00000000000..7510dd3a7ff --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/main.cpp @@ -0,0 +1,73 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// This test verifies the correct handling of child thread exits. + +#include "pseudo_barrier.h" +#include <thread> + +pseudo_barrier_t g_barrier1; +pseudo_barrier_t g_barrier2; +pseudo_barrier_t g_barrier3; + +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; // Set second breakpoint here +} + +void * +thread2 () +{ + // Synchronize with thread1 and the main thread. + pseudo_barrier_wait(g_barrier2); + + // Synchronize with the main thread. + pseudo_barrier_wait(g_barrier3); + + // Return + return NULL; +} + +int main () +{ + pseudo_barrier_init(g_barrier1, 2); + pseudo_barrier_init(g_barrier2, 3); + pseudo_barrier_init(g_barrier3, 2); + + // 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); // Set first breakpoint here + + // Wait for thread2 to start. + pseudo_barrier_wait(g_barrier2); + + // Wait for the first thread to finish + thread_1.join(); + + // Synchronize with the remaining thread + int dummy = 47; // Set third breakpoint here + pseudo_barrier_wait(g_barrier3); + + // Wait for the second thread to finish + thread_2.join(); + + return 0; // Set fourth breakpoint here +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break/Makefile new file mode 100644 index 00000000000..c46619c6623 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break/Makefile @@ -0,0 +1,4 @@ +CXX_SOURCES := main.cpp +ENABLE_THREADS := YES + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break/TestThreadSpecificBreakpoint.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break/TestThreadSpecificBreakpoint.py new file mode 100644 index 00000000000..e5505e1943c --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break/TestThreadSpecificBreakpoint.py @@ -0,0 +1,71 @@ +""" +Test that we obey thread conditioned breakpoints. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +def set_thread_id(thread, breakpoint): + id = thread.id + breakpoint.SetThreadID(id) + +def set_thread_name(thread, breakpoint): + breakpoint.SetThreadName("main-thread") + +class ThreadSpecificBreakTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + @add_test_categories(['pyapi']) + + @expectedFailureAll(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], archs=['armv7', 'armv7k'], bugnumber='rdar://problem/34563920') # armv7 ios problem - breakpoint with tid qualifier isn't working + def test_thread_id(self): + self.do_test(set_thread_id) + + @skipUnlessDarwin + @expectedFailureAll(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], archs=['armv7', 'armv7k'], bugnumber='rdar://problem/34563920') # armv7 ios problem - breakpoint with tid qualifier isn't working + def test_thread_name(self): + self.do_test(set_thread_name) + + def do_test(self, setter_method): + """Test that we obey thread conditioned breakpoints.""" + self.build() + main_source_spec = lldb.SBFileSpec("main.cpp") + (target, process, main_thread, main_breakpoint) = lldbutil.run_to_source_breakpoint(self, + "Set main breakpoint here", main_source_spec) + + thread_breakpoint = target.BreakpointCreateBySourceRegex( + "Set thread-specific breakpoint here", main_source_spec) + self.assertGreater( + thread_breakpoint.GetNumLocations(), + 0, + "thread breakpoint has no locations associated with it.") + + # Set the thread-specific breakpoint to stop only on the main thread + # before the secondary thread has a chance to execute it. The main + # thread joins the secondary thread, and then the main thread will + # execute the code at the breakpoint. If the thread-specific + # breakpoint works, the next stop will be on the main thread. + setter_method(main_thread, thread_breakpoint) + + process.Continue() + next_stop_state = process.GetState() + self.assertEqual( + next_stop_state, + lldb.eStateStopped, + "We should have stopped at the thread breakpoint.") + stopped_threads = lldbutil.get_threads_stopped_at_breakpoint( + process, thread_breakpoint) + self.assertEqual( + len(stopped_threads), + 1, + "thread breakpoint stopped at unexpected number of threads") + self.assertEqual( + stopped_threads[0].GetThreadID(), + main_thread.GetThreadID(), + "thread breakpoint stopped at the wrong thread") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break/main.cpp new file mode 100644 index 00000000000..03e93bd4125 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break/main.cpp @@ -0,0 +1,32 @@ +#include <chrono> +#include <thread> + +void +thread_function () +{ + // Set thread-specific breakpoint here. + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + // On Windows, a sleep_for of less than about 16 ms effectively calls + // Sleep(0). The MS standard thread implementation uses a system thread + // pool, which can deadlock on a Sleep(0), hanging not only the secondary + // thread but the entire test. I increased the delay to 20 ms to ensure + // Sleep is called with a delay greater than 0. The deadlock potential + // is described here: + // https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep#remarks +} + +int +main () +{ + // Set main breakpoint here. + + #ifdef __APPLE__ + pthread_setname_np("main-thread"); + #endif + + std::thread t(thread_function); + t.join(); + + thread_function(); + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break_plus_condition/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break_plus_condition/Makefile new file mode 100644 index 00000000000..c46619c6623 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break_plus_condition/Makefile @@ -0,0 +1,4 @@ +CXX_SOURCES := main.cpp +ENABLE_THREADS := YES + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break_plus_condition/TestThreadSpecificBpPlusCondition.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break_plus_condition/TestThreadSpecificBpPlusCondition.py new file mode 100644 index 00000000000..126ad9e97ee --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break_plus_condition/TestThreadSpecificBpPlusCondition.py @@ -0,0 +1,76 @@ +""" +Test that we obey thread conditioned breakpoints and expression +conditioned breakpoints simultaneously +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ThreadSpecificBreakPlusConditionTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # test frequently times out or hangs + @skipIf(oslist=['windows', 'freebsd']) + @skipIfDarwin + # hits break in another thread in testrun + @expectedFailureAll(oslist=['freebsd'], bugnumber='llvm.org/pr18522') + @add_test_categories(['pyapi']) + @expectedFailureAll(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], archs=['armv7', 'armv7k'], bugnumber='rdar://problem/34563348') # Two threads seem to end up with the same my_value when built for armv7. + @expectedFailureNetBSD + def test_python(self): + """Test that we obey thread conditioned breakpoints.""" + self.build() + exe = self.getBuildArtifact("a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + main_source_spec = lldb.SBFileSpec("main.cpp") + + # Set a breakpoint in the thread body, and make it active for only the + # first thread. + break_thread_body = target.BreakpointCreateBySourceRegex( + "Break here in thread body.", main_source_spec) + self.assertTrue( + break_thread_body.IsValid() and break_thread_body.GetNumLocations() > 0, + "Failed to set thread body breakpoint.") + + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + + self.assertTrue(process, PROCESS_IS_VALID) + + threads = lldbutil.get_threads_stopped_at_breakpoint( + process, break_thread_body) + + victim_thread = threads[0] + + # Pick one of the threads, and change the breakpoint so it ONLY stops for this thread, + # but add a condition that it won't stop for this thread's my_value. The other threads + # pass the condition, so they should stop, but if the thread-specification is working + # they should not stop. So nobody should hit the breakpoint anymore, and we should + # just exit cleanly. + + frame = victim_thread.GetFrameAtIndex(0) + value = frame.FindVariable("my_value").GetValueAsSigned(0) + self.assertTrue( + value > 0 and value < 11, + "Got a reasonable value for my_value.") + + cond_string = "my_value != %d" % (value) + + break_thread_body.SetThreadID(victim_thread.GetThreadID()) + break_thread_body.SetCondition(cond_string) + + process.Continue() + + next_stop_state = process.GetState() + self.assertTrue( + next_stop_state == lldb.eStateExited, + "We should have not hit the breakpoint again.") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break_plus_condition/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break_plus_condition/main.cpp new file mode 100644 index 00000000000..af8ab84157f --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break_plus_condition/main.cpp @@ -0,0 +1,39 @@ +#include <chrono> +#include <thread> +#include <vector> + +void * +thread_function (void *thread_marker) +{ + int keep_going = 1; + int my_value = *((int *)thread_marker); + int counter = 0; + + while (counter < 20) + { + counter++; // Break here in thread body. + std::this_thread::sleep_for(std::chrono::microseconds(10)); + } + return NULL; +} + + +int +main () +{ + std::vector<std::thread> threads; + + int thread_value = 0; + int i; + + for (i = 0; i < 10; i++) + { + thread_value += 1; + threads.push_back(std::thread(thread_function, &thread_value)); + } + + for (i = 0; i < 10; i++) + threads[i].join(); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/basic/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/basic/Makefile new file mode 100644 index 00000000000..07133cff358 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/basic/Makefile @@ -0,0 +1,4 @@ +C_SOURCES := main.c +CFLAGS_EXTRAS := -fsanitize=thread -g + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/basic/TestTsanBasic.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/basic/TestTsanBasic.py new file mode 100644 index 00000000000..1b71de5d273 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/basic/TestTsanBasic.py @@ -0,0 +1,135 @@ +""" +Tests basic ThreadSanitizer support (detecting a data race). +""" + +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +import lldbsuite.test.lldbutil as lldbutil +import json + + +class TsanBasicTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll( + oslist=["linux"], + bugnumber="non-core functionality, need to reenable and fix later (DES 2014.11.07)") + @expectedFailureNetBSD + @skipIfFreeBSD # llvm.org/pr21136 runtimes not yet available by default + @skipIfRemote + @skipUnlessThreadSanitizer + def test(self): + self.build() + self.tsan_tests() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + self.line_malloc = line_number('main.c', '// malloc line') + self.line_thread1 = line_number('main.c', '// thread1 line') + self.line_thread2 = line_number('main.c', '// thread2 line') + + def tsan_tests(self): + exe = self.getBuildArtifact("a.out") + self.expect( + "file " + exe, + patterns=["Current executable set to .*a.out"]) + + self.runCmd("run") + + stop_reason = self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason() + if stop_reason == lldb.eStopReasonExec: + # On OS X 10.10 and older, we need to re-exec to enable + # interceptors. + self.runCmd("continue") + + # the stop reason of the thread should be breakpoint. + self.expect("thread list", "A data race should be detected", + substrs=['stopped', 'stop reason = Data race detected']) + + self.assertEqual( + self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason(), + lldb.eStopReasonInstrumentation) + + # test that the TSan dylib is present + self.expect( + "image lookup -n __tsan_get_current_report", + "__tsan_get_current_report should be present", + substrs=['1 match found']) + + # We should be stopped in __tsan_on_report + process = self.dbg.GetSelectedTarget().process + thread = process.GetSelectedThread() + frame = thread.GetSelectedFrame() + self.assertTrue("__tsan_on_report" in frame.GetFunctionName()) + + # The stopped thread backtrace should contain either line1 or line2 + # from main.c. + found = False + for i in range(0, thread.GetNumFrames()): + frame = thread.GetFrameAtIndex(i) + if frame.GetLineEntry().GetFileSpec().GetFilename() == "main.c": + if frame.GetLineEntry().GetLine() == self.line_thread1: + found = True + if frame.GetLineEntry().GetLine() == self.line_thread2: + found = True + self.assertTrue(found) + + self.expect( + "thread info -s", + "The extended stop info should contain the TSan provided fields", + substrs=[ + "instrumentation_class", + "description", + "mops"]) + + output_lines = self.res.GetOutput().split('\n') + json_line = '\n'.join(output_lines[2:]) + data = json.loads(json_line) + self.assertEqual(data["instrumentation_class"], "ThreadSanitizer") + self.assertEqual(data["issue_type"], "data-race") + self.assertEqual(len(data["mops"]), 2) + + backtraces = thread.GetStopReasonExtendedBacktraces( + lldb.eInstrumentationRuntimeTypeAddressSanitizer) + self.assertEqual(backtraces.GetSize(), 0) + + backtraces = thread.GetStopReasonExtendedBacktraces( + lldb.eInstrumentationRuntimeTypeThreadSanitizer) + self.assertTrue(backtraces.GetSize() >= 2) + + # First backtrace is a memory operation + thread = backtraces.GetThreadAtIndex(0) + found = False + for i in range(0, thread.GetNumFrames()): + frame = thread.GetFrameAtIndex(i) + if frame.GetLineEntry().GetFileSpec().GetFilename() == "main.c": + if frame.GetLineEntry().GetLine() == self.line_thread1: + found = True + if frame.GetLineEntry().GetLine() == self.line_thread2: + found = True + self.assertTrue(found) + + # Second backtrace is a memory operation + thread = backtraces.GetThreadAtIndex(1) + found = False + for i in range(0, thread.GetNumFrames()): + frame = thread.GetFrameAtIndex(i) + if frame.GetLineEntry().GetFileSpec().GetFilename() == "main.c": + if frame.GetLineEntry().GetLine() == self.line_thread1: + found = True + if frame.GetLineEntry().GetLine() == self.line_thread2: + found = True + self.assertTrue(found) + + self.runCmd("continue") + + # the stop reason of the thread should be a SIGABRT. + self.expect("thread list", "We should be stopped due a SIGABRT", + substrs=['stopped', 'stop reason = signal SIGABRT']) + + # test that we're in pthread_kill now (TSan abort the process) + self.expect("thread list", "We should be stopped in pthread_kill", + substrs=['pthread_kill']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/basic/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/basic/main.c new file mode 100644 index 00000000000..108ae74d4aa --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/basic/main.c @@ -0,0 +1,36 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> + +char *pointer; + +void *f1(void *p) { + pointer[0] = 'x'; // thread1 line + return NULL; +} + +void *f2(void *p) { + pointer[0] = 'y'; // thread2 line + return NULL; +} + +int main (int argc, char const *argv[]) +{ + pointer = (char *)malloc(10); // malloc line + + pthread_t t1, t2; + pthread_create(&t1, NULL, f1, NULL); + pthread_create(&t2, NULL, f2, NULL); + + pthread_join(t1, NULL); + pthread_join(t2, NULL); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/cpp_global_location/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/cpp_global_location/Makefile new file mode 100644 index 00000000000..5f671971d59 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/cpp_global_location/Makefile @@ -0,0 +1,4 @@ +CXX_SOURCES := main.cpp +CFLAGS_EXTRAS := -fsanitize=thread -g + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/cpp_global_location/TestTsanCPPGlobalLocation.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/cpp_global_location/TestTsanCPPGlobalLocation.py new file mode 100644 index 00000000000..407126d01d3 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/cpp_global_location/TestTsanCPPGlobalLocation.py @@ -0,0 +1,64 @@ +""" +Tests that TSan correctly reports the filename and line number of a racy global C++ variable. +""" + +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +import lldbsuite.test.lldbutil as lldbutil +import json + + +class TsanCPPGlobalLocationTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll( + oslist=["linux"], + bugnumber="non-core functionality, need to reenable and fix later (DES 2014.11.07)") + @expectedFailureNetBSD + @skipIfFreeBSD # llvm.org/pr21136 runtimes not yet available by default + @skipIfRemote + @skipUnlessThreadSanitizer + def test(self): + self.build() + self.tsan_tests() + + def tsan_tests(self): + exe = self.getBuildArtifact("a.out") + self.expect( + "file " + exe, + patterns=["Current executable set to .*a.out"]) + + self.runCmd("run") + + stop_reason = self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason() + if stop_reason == lldb.eStopReasonExec: + # On OS X 10.10 and older, we need to re-exec to enable + # interceptors. + self.runCmd("continue") + + # the stop reason of the thread should be breakpoint. + self.expect("thread list", "A data race should be detected", + substrs=['stopped', 'stop reason = Data race detected']) + + self.expect( + "thread info -s", + "The extended stop info should contain the TSan provided fields", + substrs=[ + "instrumentation_class", + "description", + "mops"]) + + output_lines = self.res.GetOutput().split('\n') + json_line = '\n'.join(output_lines[2:]) + data = json.loads(json_line) + self.assertEqual(data["instrumentation_class"], "ThreadSanitizer") + self.assertEqual(data["issue_type"], "data-race") + + self.assertTrue(data["location_filename"].endswith("/main.cpp")) + self.assertEqual( + data["location_line"], + line_number( + 'main.cpp', + '// global variable')) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/cpp_global_location/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/cpp_global_location/main.cpp new file mode 100644 index 00000000000..04735ef86ff --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/cpp_global_location/main.cpp @@ -0,0 +1,37 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +long my_global_variable; // global variable + +void *f1(void *p) { + my_global_variable = 42; + return NULL; +} + +void *f2(void *p) { + my_global_variable = 43; + return NULL; +} + +int main (int argc, char const *argv[]) +{ + pthread_t t1; + pthread_create(&t1, NULL, f1, NULL); + + pthread_t t2; + pthread_create(&t2, NULL, f2, NULL); + + pthread_join(t1, NULL); + pthread_join(t2, NULL); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/global_location/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/global_location/Makefile new file mode 100644 index 00000000000..07133cff358 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/global_location/Makefile @@ -0,0 +1,4 @@ +C_SOURCES := main.c +CFLAGS_EXTRAS := -fsanitize=thread -g + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/global_location/TestTsanGlobalLocation.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/global_location/TestTsanGlobalLocation.py new file mode 100644 index 00000000000..7bfd90b0af3 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/global_location/TestTsanGlobalLocation.py @@ -0,0 +1,64 @@ +""" +Tests that TSan correctly reports the filename and line number of a racy global variable. +""" + +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +import lldbsuite.test.lldbutil as lldbutil +import json + + +class TsanGlobalLocationTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll( + oslist=["linux"], + bugnumber="non-core functionality, need to reenable and fix later (DES 2014.11.07)") + @expectedFailureNetBSD + @skipIfFreeBSD # llvm.org/pr21136 runtimes not yet available by default + @skipIfRemote + @skipUnlessThreadSanitizer + def test(self): + self.build() + self.tsan_tests() + + def tsan_tests(self): + exe = self.getBuildArtifact("a.out") + self.expect( + "file " + exe, + patterns=["Current executable set to .*a.out"]) + + self.runCmd("run") + + stop_reason = self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason() + if stop_reason == lldb.eStopReasonExec: + # On OS X 10.10 and older, we need to re-exec to enable + # interceptors. + self.runCmd("continue") + + # the stop reason of the thread should be breakpoint. + self.expect("thread list", "A data race should be detected", + substrs=['stopped', 'stop reason = Data race detected']) + + self.expect( + "thread info -s", + "The extended stop info should contain the TSan provided fields", + substrs=[ + "instrumentation_class", + "description", + "mops"]) + + output_lines = self.res.GetOutput().split('\n') + json_line = '\n'.join(output_lines[2:]) + data = json.loads(json_line) + self.assertEqual(data["instrumentation_class"], "ThreadSanitizer") + self.assertEqual(data["issue_type"], "data-race") + + self.assertTrue(data["location_filename"].endswith("/main.c")) + self.assertEqual( + data["location_line"], + line_number( + 'main.c', + '// global variable')) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/global_location/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/global_location/main.c new file mode 100644 index 00000000000..4c88d9f0cc0 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/global_location/main.c @@ -0,0 +1,37 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +long my_global_variable; // global variable + +void *f1(void *p) { + my_global_variable = 42; + return NULL; +} + +void *f2(void *p) { + my_global_variable = 43; + return NULL; +} + +int main (int argc, char const *argv[]) +{ + pthread_t t1; + pthread_create(&t1, NULL, f1, NULL); + + pthread_t t2; + pthread_create(&t2, NULL, f2, NULL); + + pthread_join(t1, NULL); + pthread_join(t2, NULL); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/multiple/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/multiple/Makefile new file mode 100644 index 00000000000..07133cff358 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/multiple/Makefile @@ -0,0 +1,4 @@ +C_SOURCES := main.c +CFLAGS_EXTRAS := -fsanitize=thread -g + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/multiple/TestTsanMultiple.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/multiple/TestTsanMultiple.py new file mode 100644 index 00000000000..b40f950eda5 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/multiple/TestTsanMultiple.py @@ -0,0 +1,81 @@ +""" +Test ThreadSanitizer when multiple different issues are found. +""" + +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +import lldbsuite.test.lldbutil as lldbutil +import json + + +class TsanMultipleTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll( + oslist=["linux"], + bugnumber="non-core functionality, need to reenable and fix later (DES 2014.11.07)") + @expectedFailureNetBSD + @skipIfFreeBSD # llvm.org/pr21136 runtimes not yet available by default + @skipIfRemote + @skipUnlessThreadSanitizer + def test(self): + self.build() + self.tsan_tests() + + def tsan_tests(self): + exe = self.getBuildArtifact("a.out") + self.expect( + "file " + exe, + patterns=["Current executable set to .*a.out"]) + + self.runCmd("env TSAN_OPTIONS=abort_on_error=0") + + self.runCmd("run") + + stop_reason = self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason() + if stop_reason == lldb.eStopReasonExec: + # On OS X 10.10 and older, we need to re-exec to enable + # interceptors. + self.runCmd("continue") + + report_count = 0 + while self.dbg.GetSelectedTarget().process.GetSelectedThread( + ).GetStopReason() == lldb.eStopReasonInstrumentation: + report_count += 1 + + stop_description = self.dbg.GetSelectedTarget( + ).process.GetSelectedThread().GetStopDescription(100) + + self.assertTrue( + (stop_description == "Data race detected") or + (stop_description == "Use of deallocated memory detected") or + (stop_description == "Thread leak detected") or + (stop_description == "Use of an uninitialized or destroyed mutex detected") or + (stop_description == "Unlock of an unlocked mutex (or by a wrong thread) detected") + ) + + self.expect( + "thread info -s", + "The extended stop info should contain the TSan provided fields", + substrs=[ + "instrumentation_class", + "description", + "mops"]) + + output_lines = self.res.GetOutput().split('\n') + json_line = '\n'.join(output_lines[2:]) + data = json.loads(json_line) + self.assertEqual(data["instrumentation_class"], "ThreadSanitizer") + + backtraces = self.dbg.GetSelectedTarget().process.GetSelectedThread( + ).GetStopReasonExtendedBacktraces(lldb.eInstrumentationRuntimeTypeThreadSanitizer) + self.assertTrue(backtraces.GetSize() >= 1) + + self.runCmd("continue") + + self.assertEqual( + self.dbg.GetSelectedTarget().process.GetState(), + lldb.eStateExited, + PROCESS_EXITED) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/multiple/main.m b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/multiple/main.m new file mode 100644 index 00000000000..d15bdaa3300 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/multiple/main.m @@ -0,0 +1,137 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#import <Foundation/Foundation.h> +#import <pthread.h> + +long my_global; + +void *Thread1(void *arg) { + my_global = 42; + return NULL; +} + +void *Thread2(void *arg) { + my_global = 144; + return NULL; +} + +void TestDataRace1() { + pthread_t t1, t2; + pthread_create(&t1, NULL, Thread1, NULL); + pthread_create(&t2, NULL, Thread2, NULL); + + pthread_join(t1, NULL); + pthread_join(t2, NULL); +} + +void TestInvalidMutex() { + pthread_mutex_t m = {0}; + pthread_mutex_lock(&m); + + pthread_mutex_init(&m, NULL); + pthread_mutex_lock(&m); + pthread_mutex_unlock(&m); + pthread_mutex_destroy(&m); + pthread_mutex_lock(&m); +} + +void TestMutexWrongLock() { + pthread_mutex_t m = {0}; + pthread_mutex_init(&m, NULL); + pthread_mutex_unlock(&m); +} + +long some_global; + +void TestDataRaceBlocks1() { + dispatch_queue_t q = dispatch_queue_create("my.queue", DISPATCH_QUEUE_CONCURRENT); + + for (int i = 0; i < 2; i++) { + dispatch_async(q, ^{ + some_global++; // race 1 + + usleep(100000); // force the blocks to be on different threads + }); + } + + usleep(100000); + dispatch_barrier_sync(q, ^{ }); +} + +void TestDataRaceBlocks2() { + dispatch_queue_t q = dispatch_queue_create("my.queue2", DISPATCH_QUEUE_CONCURRENT); + + char *c; + + c = malloc((rand() % 1000) + 10); + for (int i = 0; i < 2; i++) { + dispatch_async(q, ^{ + c[0] = 'x'; // race 2 + fprintf(stderr, "tid: %p\n", pthread_self()); + usleep(100000); // force the blocks to be on different threads + }); + } + dispatch_barrier_sync(q, ^{ }); + + free(c); +} + +void TestUseAfterFree() { + char *c; + + c = malloc((rand() % 1000) + 10); + free(c); + c[0] = 'x'; +} + +void TestRacePipe() { + dispatch_queue_t q = dispatch_queue_create("my.queue3", DISPATCH_QUEUE_CONCURRENT); + + int a[2]; + pipe(a); + int fd = a[0]; + + for (int i = 0; i < 2; i++) { + dispatch_async(q, ^{ + write(fd, "abc", 3); + usleep(100000); // force the blocks to be on different threads + }); + dispatch_async(q, ^{ + close(fd); + usleep(100000); + }); + } + + dispatch_barrier_sync(q, ^{ }); +} + +void TestThreadLeak() { + pthread_t t1; + pthread_create(&t1, NULL, Thread1, NULL); +} + +int main(int argc, const char * argv[]) { + TestDataRace1(); + + TestInvalidMutex(); + + TestMutexWrongLock(); + + TestDataRaceBlocks1(); + + TestDataRaceBlocks2(); + + TestUseAfterFree(); + + TestRacePipe(); + + TestThreadLeak(); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/thread_leak/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/thread_leak/Makefile new file mode 100644 index 00000000000..07133cff358 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/thread_leak/Makefile @@ -0,0 +1,4 @@ +C_SOURCES := main.c +CFLAGS_EXTRAS := -fsanitize=thread -g + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/thread_leak/TestTsanThreadLeak.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/thread_leak/TestTsanThreadLeak.py new file mode 100644 index 00000000000..09704e40cd3 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/thread_leak/TestTsanThreadLeak.py @@ -0,0 +1,46 @@ +""" +Tests ThreadSanitizer's support to detect a leaked thread. +""" + +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +import lldbsuite.test.lldbutil as lldbutil + + +class TsanThreadLeakTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll( + oslist=["linux"], + bugnumber="non-core functionality, need to reenable and fix later (DES 2014.11.07)") + @expectedFailureNetBSD + @skipIfFreeBSD # llvm.org/pr21136 runtimes not yet available by default + @skipIfRemote + @skipUnlessThreadSanitizer + def test(self): + self.build() + self.tsan_tests() + + def tsan_tests(self): + exe = self.getBuildArtifact("a.out") + self.expect( + "file " + exe, + patterns=["Current executable set to .*a.out"]) + + self.runCmd("run") + + stop_reason = self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason() + if stop_reason == lldb.eStopReasonExec: + # On OS X 10.10 and older, we need to re-exec to enable + # interceptors. + self.runCmd("continue") + + # the stop reason of the thread should be breakpoint. + self.expect("thread list", "A thread leak should be detected", + substrs=['stopped', 'stop reason = Thread leak detected']) + + self.assertEqual( + self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason(), + lldb.eStopReasonInstrumentation) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/thread_leak/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/thread_leak/main.c new file mode 100644 index 00000000000..0c3a2cf84f5 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/thread_leak/main.c @@ -0,0 +1,23 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> + +void *f1(void *p) { + printf("hello\n"); + return NULL; +} + +int main (int argc, char const *argv[]) +{ + pthread_t t1; + pthread_create(&t1, NULL, f1, NULL); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/thread_numbers/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/thread_numbers/Makefile new file mode 100644 index 00000000000..07133cff358 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/thread_numbers/Makefile @@ -0,0 +1,4 @@ +C_SOURCES := main.c +CFLAGS_EXTRAS := -fsanitize=thread -g + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/thread_numbers/TestTsanThreadNumbers.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/thread_numbers/TestTsanThreadNumbers.py new file mode 100644 index 00000000000..61870eac9c4 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/thread_numbers/TestTsanThreadNumbers.py @@ -0,0 +1,82 @@ +""" +Tests that TSan and LLDB have correct thread numbers. +""" + +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +import lldbsuite.test.lldbutil as lldbutil +import json + + +class TsanThreadNumbersTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll( + oslist=["linux"], + bugnumber="non-core functionality, need to reenable and fix later (DES 2014.11.07)") + @expectedFailureNetBSD + @skipIfFreeBSD # llvm.org/pr21136 runtimes not yet available by default + @skipIfRemote + @skipUnlessThreadSanitizer + def test(self): + self.build() + self.tsan_tests() + + def tsan_tests(self): + exe = self.getBuildArtifact("a.out") + self.expect( + "file " + exe, + patterns=["Current executable set to .*a.out"]) + + self.runCmd("run") + + stop_reason = self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason() + if stop_reason == lldb.eStopReasonExec: + # On OS X 10.10 and older, we need to re-exec to enable + # interceptors. + self.runCmd("continue") + + # the stop reason of the thread should be breakpoint. + self.expect("thread list", "A data race should be detected", + substrs=['stopped', 'stop reason = Data race detected']) + + self.assertEqual( + self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason(), + lldb.eStopReasonInstrumentation) + + report_thread_id = self.dbg.GetSelectedTarget( + ).process.GetSelectedThread().GetIndexID() + + self.expect( + "thread info -s", + "The extended stop info should contain the TSan provided fields", + substrs=[ + "instrumentation_class", + "description", + "mops"]) + + output_lines = self.res.GetOutput().split('\n') + json_line = '\n'.join(output_lines[2:]) + data = json.loads(json_line) + self.assertEqual(data["instrumentation_class"], "ThreadSanitizer") + self.assertEqual(data["issue_type"], "data-race") + self.assertEqual(len(data["mops"]), 2) + + self.assertEqual(data["mops"][0]["thread_id"], report_thread_id) + + other_thread_id = data["mops"][1]["thread_id"] + self.assertTrue(other_thread_id != report_thread_id) + other_thread = self.dbg.GetSelectedTarget( + ).process.GetThreadByIndexID(other_thread_id) + self.assertTrue(other_thread.IsValid()) + + self.runCmd("thread select %d" % other_thread_id) + + self.expect( + "thread backtrace", + "The other thread should be stopped in f1 or f2", + substrs=[ + "a.out", + "main.c"]) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/thread_numbers/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/thread_numbers/main.c new file mode 100644 index 00000000000..5bc82131402 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tsan/thread_numbers/main.c @@ -0,0 +1,57 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +char *pointer; + +void *nothing(void *p) { + return NULL; +} + +void *f1(void *p) { + pointer[0] = 'x'; + sleep(100); + return NULL; +} + +void *f2(void *p) { + pointer[0] = 'y'; + sleep(100); + return NULL; +} + +int main (int argc, char const *argv[]) +{ + pointer = (char *)malloc(10); + + for (int i = 0; i < 3; i++) { + pthread_t t; + pthread_create(&t, NULL, nothing, NULL); + pthread_join(t, NULL); + } + + pthread_t t1; + pthread_create(&t1, NULL, f1, NULL); + + for (int i = 0; i < 3; i++) { + pthread_t t; + pthread_create(&t, NULL, nothing, NULL); + pthread_join(t, NULL); + } + + pthread_t t2; + pthread_create(&t2, NULL, f2, NULL); + + pthread_join(t1, NULL); + pthread_join(t2, NULL); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tty/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tty/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tty/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tty/TestTerminal.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tty/TestTerminal.py new file mode 100644 index 00000000000..bf5f1200ace --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tty/TestTerminal.py @@ -0,0 +1,51 @@ +""" +Test lldb command aliases. +""" + +from __future__ import print_function + + +import unittest2 +import os +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class LaunchInTerminalTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # Darwin is the only platform that I know of that supports optionally launching + # a program in a separate terminal window. It would be great if other platforms + # added support for this. + @skipUnlessDarwin + # If the test is being run under sudo, the spawned terminal won't retain that elevated + # privilege so it can't open the socket to talk back to the test case + @unittest2.skipIf(hasattr(os, 'geteuid') and os.geteuid() + == 0, "test cannot be run as root") + # Do we need to disable this test if the testsuite is being run on a remote system? + # This env var is only defined when the shell is running in a local mac + # terminal window + @unittest2.skipUnless( + 'TERM_PROGRAM' in os.environ, + "test must be run on local system") + @no_debug_info_test + def test_launch_in_terminal(self): + self.build() + exe = self.getBuildArtifact("a.out") + + target = self.dbg.CreateTarget(exe) + launch_info = lldb.SBLaunchInfo(["-lAF", "/tmp/"]) + launch_info.SetLaunchFlags( + lldb.eLaunchFlagLaunchInTTY | lldb.eLaunchFlagCloseTTYOnExit) + error = lldb.SBError() + process = target.Launch(launch_info, error) + print("Error was: %s."%(error.GetCString())) + self.assertTrue( + error.Success(), + "Make sure launch happened successfully in a terminal window") + # Running in synchronous mode our process should have run and already + # exited by the time target.Launch() returns + self.assertTrue(process.GetState() == lldb.eStateExited) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tty/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tty/main.c new file mode 100644 index 00000000000..71c854b5bf4 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/tty/main.c @@ -0,0 +1,10 @@ +#include <stdio.h> + +int +main(int argc, char** argv) +{ + for (int i = 0; i < argc; i++) { + printf("%d: %s.\n", i, argv[i]); + } + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/type_completion/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/type_completion/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/type_completion/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/type_completion/TestTypeCompletion.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/type_completion/TestTypeCompletion.py new file mode 100644 index 00000000000..fb0b1096f4d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/type_completion/TestTypeCompletion.py @@ -0,0 +1,155 @@ +""" +Check that types only get completed when necessary. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TypeCompletionTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll( + compiler="icc", + bugnumber="often fails with 'NameAndAddress should be valid.") + # Fails with gcc 4.8.1 with llvm.org/pr15301 LLDB prints incorrect sizes + # of STL containers + def test_with_run_command(self): + """Check that types only get completed when necessary.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_source_regexp( + self, "// Set break point at this line.") + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type category enable -l c++', check=False) + + self.runCmd('type category disable -l c++', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + p_vector = self.dbg.GetSelectedTarget().GetProcess( + ).GetSelectedThread().GetSelectedFrame().FindVariable('p') + p_type = p_vector.GetType() + self.assertFalse( + p_type.IsTypeComplete(), + 'vector<T> complete but it should not be') + + self.runCmd("continue") + + p_vector = self.dbg.GetSelectedTarget().GetProcess( + ).GetSelectedThread().GetSelectedFrame().FindVariable('p') + p_type = p_vector.GetType() + self.assertFalse( + p_type.IsTypeComplete(), + 'vector<T> complete but it should not be') + + self.runCmd("continue") + + self.runCmd("frame variable p --show-types") + + p_vector = self.dbg.GetSelectedTarget().GetProcess( + ).GetSelectedThread().GetSelectedFrame().FindVariable('p') + p_type = p_vector.GetType() + self.assertTrue( + p_type.IsTypeComplete(), + 'vector<T> should now be complete') + name_address_type = p_type.GetTemplateArgumentType(0) + self.assertTrue( + name_address_type.IsValid(), + 'NameAndAddress should be valid') + self.assertFalse( + name_address_type.IsTypeComplete(), + 'NameAndAddress complete but it should not be') + + self.runCmd("continue") + + self.runCmd("frame variable guy --show-types") + + p_vector = self.dbg.GetSelectedTarget().GetProcess( + ).GetSelectedThread().GetSelectedFrame().FindVariable('p') + p_type = p_vector.GetType() + self.assertTrue( + p_type.IsTypeComplete(), + 'vector<T> should now be complete') + name_address_type = p_type.GetTemplateArgumentType(0) + self.assertTrue( + name_address_type.IsValid(), + 'NameAndAddress should be valid') + self.assertTrue( + name_address_type.IsTypeComplete(), + 'NameAndAddress should now be complete') + field0 = name_address_type.GetFieldAtIndex(0) + self.assertTrue( + field0.IsValid(), + 'NameAndAddress::m_name should be valid') + string = field0.GetType().GetPointeeType() + self.assertTrue(string.IsValid(), 'CustomString should be valid') + self.assertFalse(string.IsTypeComplete(), + 'CustomString complete but it should not be') + + self.runCmd("continue") + + p_vector = self.dbg.GetSelectedTarget().GetProcess( + ).GetSelectedThread().GetSelectedFrame().FindVariable('p') + p_type = p_vector.GetType() + self.assertTrue( + p_type.IsTypeComplete(), + 'vector<T> should now be complete') + name_address_type = p_type.GetTemplateArgumentType(0) + self.assertTrue( + name_address_type.IsValid(), + 'NameAndAddress should be valid') + self.assertTrue( + name_address_type.IsTypeComplete(), + 'NameAndAddress should now be complete') + field0 = name_address_type.GetFieldAtIndex(0) + self.assertTrue( + field0.IsValid(), + 'NameAndAddress::m_name should be valid') + string = field0.GetType().GetPointeeType() + self.assertTrue(string.IsValid(), 'CustomString should be valid') + self.assertFalse(string.IsTypeComplete(), + 'CustomString complete but it should not be') + + self.runCmd('type category enable -l c++', check=False) + self.runCmd('frame variable guy --show-types --ptr-depth=1') + + p_vector = self.dbg.GetSelectedTarget().GetProcess( + ).GetSelectedThread().GetSelectedFrame().FindVariable('p') + p_type = p_vector.GetType() + self.assertTrue( + p_type.IsTypeComplete(), + 'vector<T> should now be complete') + name_address_type = p_type.GetTemplateArgumentType(0) + self.assertTrue( + name_address_type.IsValid(), + 'NameAndAddress should be valid') + self.assertTrue( + name_address_type.IsTypeComplete(), + 'NameAndAddress should now be complete') + field0 = name_address_type.GetFieldAtIndex(0) + self.assertTrue( + field0.IsValid(), + 'NameAndAddress::m_name should be valid') + string = field0.GetType().GetPointeeType() + self.assertTrue(string.IsValid(), 'CustomString should be valid') + self.assertTrue( + string.IsTypeComplete(), + 'CustomString should now be complete') diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/type_completion/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/type_completion/main.cpp new file mode 100644 index 00000000000..a361df0849a --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/type_completion/main.cpp @@ -0,0 +1,80 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <string.h> +#include <vector> +#include <iostream> + +class CustomString +{ +public: + CustomString (const char* buffer) : + m_buffer(nullptr) + { + if (buffer) + { + auto l = strlen(buffer); + m_buffer = new char[1 + l]; + strcpy(m_buffer, buffer); + } + } + + ~CustomString () + { + delete[] m_buffer; + } + + const char* + GetBuffer () + { + return m_buffer; + } + +private: + char *m_buffer; +}; + +class NameAndAddress + { + public: + CustomString& GetName() { return *m_name; } + CustomString& GetAddress() { return *m_address; } + NameAndAddress(const char* N, const char* A) : m_name(new CustomString(N)), m_address(new CustomString(A)) + { + } + ~NameAndAddress() + { + } + + private: + CustomString* m_name; + CustomString* m_address; +}; + +typedef std::vector<NameAndAddress> People; + +int main (int argc, const char * argv[]) +{ + People p; + p.push_back(NameAndAddress("Enrico","123 Main Street")); + p.push_back(NameAndAddress("Foo","10710 Johnson Avenue")); // Set break point at this line. + p.push_back(NameAndAddress("Arpia","6956 Florey Street")); + p.push_back(NameAndAddress("Apple","1 Infinite Loop")); // Set break point at this line. + p.push_back(NameAndAddress("Richard","9500 Gilman Drive")); + p.push_back(NameAndAddress("Bar","3213 Windsor Rd")); + + for (int j = 0; j<p.size(); j++) + { + NameAndAddress guy = p[j]; + std::cout << "Person " << j << " is named " << guy.GetName().GetBuffer() << " and lives at " << guy.GetAddress().GetBuffer() << std::endl; // Set break point at this line. + } + + return 0; + +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/type_lookup/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/type_lookup/Makefile new file mode 100644 index 00000000000..876340159d9 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/type_lookup/Makefile @@ -0,0 +1,8 @@ +OBJCXX_SOURCES := main.mm + +CFLAGS_EXTRAS := -w + + + +LD_EXTRAS := -framework Foundation +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/type_lookup/TestTypeLookup.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/type_lookup/TestTypeLookup.py new file mode 100644 index 00000000000..2257fd63063 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/type_lookup/TestTypeLookup.py @@ -0,0 +1,51 @@ +""" +Test type lookup command. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TypeLookupTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.mm', '// break here') + + @skipUnlessDarwin + @skipIf(archs=['i386']) + def test_type_lookup(self): + """Test type lookup command.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.mm", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + self.expect( + 'type lookup NoSuchType', + substrs=['@interface'], + matching=False) + self.expect('type lookup NSURL', substrs=['NSURL']) + self.expect('type lookup NSArray', substrs=['NSArray']) + self.expect('type lookup NSObject', substrs=['NSObject', 'isa']) + self.expect('type lookup PleaseDontBeARealTypeThatExists', substrs=[ + "no type was found matching 'PleaseDontBeARealTypeThatExists'"]) + self.expect('type lookup MyCPPClass', substrs=['setF', 'float getF']) + self.expect('type lookup MyClass', substrs=['setF', 'float getF']) + self.expect('type lookup MyObjCClass', substrs=['@interface MyObjCClass', 'int x', 'int y']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/type_lookup/main.mm b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/type_lookup/main.mm new file mode 100644 index 00000000000..7b005a2086d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/type_lookup/main.mm @@ -0,0 +1,57 @@ +//===-- main.mm -----------------------------------------------*- ObjC -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#import <Foundation/Foundation.h> + +class MyCPPClass { +public: + MyCPPClass(float f) : f(f) {} + + float setF(float f) { + float oldf = this->f; + this->f = f; + return oldf; + } + + float getF() { + return f; + } +private: + float f; +}; + +typedef MyCPPClass MyClass; + +@interface MyObjCClass : NSObject { + int x; +} +- (id)init; +- (int)read; +@end + +@implementation MyObjCClass { + int y; +} +- (id)init { + if (self = [super init]) { + self->x = 12; + self->y = 24; + } + return self; +} +- (int)read { + return self->x + self->y; +} +@end + +int main (int argc, const char * argv[]) +{ + MyClass my_cpp(3.1415); + return 0; // break here +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/ubsan/basic/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/ubsan/basic/Makefile new file mode 100644 index 00000000000..b27db90a40d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/ubsan/basic/Makefile @@ -0,0 +1,4 @@ +C_SOURCES := main.c +CFLAGS_EXTRAS := -fsanitize=undefined -g + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/ubsan/basic/TestUbsanBasic.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/ubsan/basic/TestUbsanBasic.py new file mode 100644 index 00000000000..76fdb33fd32 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/ubsan/basic/TestUbsanBasic.py @@ -0,0 +1,89 @@ +""" +Tests basic UndefinedBehaviorSanitizer support (detecting an alignment error). +""" + +import os +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +import lldbsuite.test.lldbutil as lldbutil +import json + + +class UbsanBasicTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipUnlessUndefinedBehaviorSanitizer + def test(self): + self.build() + self.ubsan_tests() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + self.line_align = line_number('main.c', '// align line') + + def ubsan_tests(self): + # Load the test + exe = self.getBuildArtifact("a.out") + self.expect( + "file " + exe, + patterns=["Current executable set to .*a.out"]) + + self.runCmd("run") + + process = self.dbg.GetSelectedTarget().process + thread = process.GetSelectedThread() + frame = thread.GetSelectedFrame() + + # the stop reason of the thread should be breakpoint. + self.expect("thread list", "A ubsan issue should be detected", + substrs=['stopped', 'stop reason =']) + + stop_reason = thread.GetStopReason() + self.assertEqual(stop_reason, lldb.eStopReasonInstrumentation) + + # test that the UBSan dylib is present + self.expect( + "image lookup -n __ubsan_on_report", + "__ubsan_on_report should be present", + substrs=['1 match found']) + + # We should be stopped in __ubsan_on_report + self.assertTrue("__ubsan_on_report" in frame.GetFunctionName()) + + # The stopped thread backtrace should contain either 'align line' + found = False + for i in range(thread.GetNumFrames()): + frame = thread.GetFrameAtIndex(i) + if frame.GetLineEntry().GetFileSpec().GetFilename() == "main.c": + if frame.GetLineEntry().GetLine() == self.line_align: + found = True + self.assertTrue(found) + + backtraces = thread.GetStopReasonExtendedBacktraces( + lldb.eInstrumentationRuntimeTypeUndefinedBehaviorSanitizer) + self.assertTrue(backtraces.GetSize() == 1) + + self.expect( + "thread info -s", + "The extended stop info should contain the UBSan provided fields", + substrs=[ + "instrumentation_class", + "memory_address", + "description", + "filename", + "line", + "col"]) + + output_lines = self.res.GetOutput().split('\n') + json_line = '\n'.join(output_lines[2:]) + data = json.loads(json_line) + + self.assertEqual(data["instrumentation_class"], "UndefinedBehaviorSanitizer") + self.assertEqual(data["description"], "misaligned-pointer-use") + self.assertEqual(os.path.basename(data["filename"]), "main.c") + self.assertEqual(data["line"], self.line_align) + + self.runCmd("continue") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/ubsan/basic/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/ubsan/basic/main.c new file mode 100644 index 00000000000..4991fc074d0 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/ubsan/basic/main.c @@ -0,0 +1,4 @@ +int main() { + int data[4]; + return *(int *)(((char *)&data[0]) + 2); // align line +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/Makefile new file mode 100644 index 00000000000..b27db90a40d --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/Makefile @@ -0,0 +1,4 @@ +C_SOURCES := main.c +CFLAGS_EXTRAS := -fsanitize=undefined -g + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/TestUbsanUserExpression.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/TestUbsanUserExpression.py new file mode 100644 index 00000000000..68f8c0360ff --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/TestUbsanUserExpression.py @@ -0,0 +1,46 @@ +""" +Test that hitting a UBSan issue while running user expression doesn't break the evaluation. +""" + +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +import lldbsuite.test.lldbutil as lldbutil + + +class UbsanUserExpressionTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipUnlessUndefinedBehaviorSanitizer + def test(self): + self.build() + self.ubsan_tests() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + self.line_breakpoint = line_number('main.c', '// breakpoint line') + + def ubsan_tests(self): + # Load the test + exe = self.getBuildArtifact("a.out") + self.expect( + "file " + exe, + patterns=["Current executable set to .*a.out"]) + + self.runCmd("breakpoint set -f main.c -l %d" % self.line_breakpoint) + + self.runCmd("run") + + process = self.dbg.GetSelectedTarget().process + thread = process.GetSelectedThread() + frame = thread.GetSelectedFrame() + + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', 'stop reason = breakpoint']) + + self.expect("p foo()", substrs=["(int) $0 = 42"]) + + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', 'stop reason = breakpoint']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/main.c new file mode 100644 index 00000000000..4786aaa89b2 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/main.c @@ -0,0 +1,9 @@ +int foo() { + int data[4]; + int x = *(int *)(((char *)&data[0]) + 2); + return 42; +} + +int main() { + return 0; // breakpoint line +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/ehframe/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/ehframe/Makefile new file mode 100644 index 00000000000..493ea3f7f68 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/ehframe/Makefile @@ -0,0 +1,5 @@ +C_SOURCES := main.c + +CFLAGS ?= -g -fomit-frame-pointer + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/ehframe/TestEhFrameUnwind.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/ehframe/TestEhFrameUnwind.py new file mode 100644 index 00000000000..905543ff769 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/ehframe/TestEhFrameUnwind.py @@ -0,0 +1,49 @@ +""" +Test that we can backtrace correctly from Non ABI functions on the stack +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class EHFrameBasedUnwind(TestBase): + mydir = TestBase.compute_mydir(__file__) + + @skipUnlessPlatform(['linux']) + @skipIf(archs=["aarch64", "arm", "i386", "i686"]) + def test(self): + """Test that we can backtrace correctly from Non ABI functions on the stack""" + self.build() + self.setTearDownCleanup() + + exe = self.getBuildArtifact("a.out") + target = self.dbg.CreateTarget(exe) + + self.assertTrue(target, VALID_TARGET) + + lldbutil.run_break_set_by_symbol(self, "func") + + process = target.LaunchSimple( + ["abc", "xyz"], None, self.get_process_working_directory()) + + if not process: + self.fail("SBTarget.Launch() failed") + + if process.GetState() != lldb.eStateStopped: + self.fail("Process should be in the 'stopped' state, " + "instead the actual state is: '%s'" % + lldbutil.state_type_to_str(process.GetState())) + + stacktraces = lldbutil.print_stacktraces(process, string_buffer=True) + self.expect(stacktraces, exe=False, + substrs=['(int)argc=3']) + + self.runCmd("thread step-inst") + + stacktraces = lldbutil.print_stacktraces(process, string_buffer=True) + self.expect(stacktraces, exe=False, + substrs=['(int)argc=3']) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/ehframe/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/ehframe/main.c new file mode 100644 index 00000000000..46de1efe626 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/ehframe/main.c @@ -0,0 +1,58 @@ +void func() { + +#ifdef __powerpc64__ + __asm__ ( + "mflr 0;" + "std 0,16(1);" + "addi 1,1,-24;" + "mr 31,1;" + ".cfi_def_cfa_offset 24;" + "addi 0,0,0;" + "addi 1,1,24;" + "ld 0,16(1);" + ".cfi_def_cfa_offset 0;" + ); +#elif !defined __mips__ + __asm__ ( + "pushq $0x10;" + ".cfi_def_cfa_offset 16;" + "jmp label;" + "movq $0x48, %rax;" +"label: subq $0x38, %rax;" + "movq $0x48, %rcx;" + "movq $0x48, %rdx;" + "movq $0x48, %rax;" + "popq %rax;" + ); +#elif __mips64 + __asm__ ( + "daddiu $sp,$sp,-16;" + ".cfi_def_cfa_offset 16;" + "sd $ra,8($sp);" + ".cfi_offset 31, -8;" + "daddiu $ra,$zero,0;" + "ld $ra,8($sp);" + "daddiu $sp, $sp,16;" + ".cfi_restore 31;" + ".cfi_def_cfa_offset 0;" + ); +#else + // For MIPS32 + __asm__ ( + "addiu $sp,$sp,-8;" + ".cfi_def_cfa_offset 8;" + "sw $ra,4($sp);" + ".cfi_offset 31, -4;" + "addiu $ra,$zero,0;" + "lw $ra,4($sp);" + "addiu $sp,$sp,8;" + ".cfi_restore 31;" + ".cfi_def_cfa_offset 0;" + ); +#endif +} + +int main(int argc, char const *argv[]) +{ + func(); +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/Makefile new file mode 100644 index 00000000000..36cf5a296e5 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/Makefile @@ -0,0 +1,5 @@ +C_SOURCES := main.c + +CFLAGS ?= -g -Os + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/TestNoreturnUnwind.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/TestNoreturnUnwind.py new file mode 100644 index 00000000000..1086a34d3dd --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/TestNoreturnUnwind.py @@ -0,0 +1,85 @@ +""" +Test that we can backtrace correctly with 'noreturn' functions on the stack +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class NoreturnUnwind(TestBase): + mydir = TestBase.compute_mydir(__file__) + + @skipIfWindows # clang-cl does not support gcc style attributes. + # clang does not preserve LR in noreturn functions, making unwinding impossible + @skipIf(compiler="clang", archs=['arm'], oslist=['linux']) + @expectedFailureAll(bugnumber="llvm.org/pr33452", triple='^mips') + @expectedFailureNetBSD + def test(self): + """Test that we can backtrace correctly with 'noreturn' functions on the stack""" + self.build() + self.setTearDownCleanup() + + exe = self.getBuildArtifact("a.out") + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + + if not process: + self.fail("SBTarget.Launch() failed") + + if process.GetState() != lldb.eStateStopped: + self.fail("Process should be in the 'stopped' state, " + "instead the actual state is: '%s'" % + lldbutil.state_type_to_str(process.GetState())) + + thread = process.GetThreadAtIndex(0) + abort_frame_number = 0 + for f in thread.frames: + # Some C libraries mangle the abort symbol into __GI_abort. + if f.GetFunctionName() in ["abort", "__GI_abort"]: + break + abort_frame_number = abort_frame_number + 1 + + if self.TraceOn(): + print("Backtrace once we're stopped:") + for f in thread.frames: + print(" %d %s" % (f.GetFrameID(), f.GetFunctionName())) + + # I'm going to assume that abort() ends up calling/invoking another + # function before halting the process. In which case if abort_frame_number + # equals 0, we didn't find abort() in the backtrace. + if abort_frame_number == len(thread.frames): + self.fail("Unable to find abort() in backtrace.") + + func_c_frame_number = abort_frame_number + 1 + if thread.GetFrameAtIndex( + func_c_frame_number).GetFunctionName() != "func_c": + self.fail("Did not find func_c() above abort().") + + # This depends on whether we see the func_b inlined function in the backtrace + # or not. I'm not interested in testing that aspect of the backtrace here + # right now. + + if thread.GetFrameAtIndex( + func_c_frame_number + + 1).GetFunctionName() == "func_b": + func_a_frame_number = func_c_frame_number + 2 + else: + func_a_frame_number = func_c_frame_number + 1 + + if thread.GetFrameAtIndex( + func_a_frame_number).GetFunctionName() != "func_a": + self.fail("Did not find func_a() above func_c().") + + main_frame_number = func_a_frame_number + 1 + + if thread.GetFrameAtIndex( + main_frame_number).GetFunctionName() != "main": + self.fail("Did not find main() above func_a().") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/main.c new file mode 100644 index 00000000000..4f6525fbf52 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/main.c @@ -0,0 +1,35 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +static void func_a (void) __attribute__((noinline)); +static void func_b (void) __attribute__((noreturn)); +static void func_c (void) __attribute__((noinline)); + +static void +func_c (void) +{ + abort (); +} + +static void +func_b (void) +{ + func_c (); + while (1) + ; +} + +static void +func_a (void) +{ + func_b (); +} + +int +main (int argc, char *argv[]) +{ + func_a (); + + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/TestNoReturnModuleEnd.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/TestNoReturnModuleEnd.py new file mode 100644 index 00000000000..cce485bd5a5 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/TestNoReturnModuleEnd.py @@ -0,0 +1,50 @@ +""" +Test that we properly display the backtrace when a noreturn function happens to +be at the end of the stack. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestNoreturnModuleEnd(TestBase): + NO_DEBUG_INFO_TESTCASE = True + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + super(TestNoreturnModuleEnd, self).setUp() + self._initial_platform = lldb.DBG.GetSelectedPlatform() + + def tearDown(self): + lldb.DBG.SetSelectedPlatform(self._initial_platform) + super(TestNoreturnModuleEnd, self).tearDown() + + def test(self): + target = self.dbg.CreateTarget("test.out") + process = target.LoadCore("test.core") + self.assertTrue(process.IsValid(), PROCESS_IS_VALID) + self.assertEqual(process.GetNumThreads(), 1) + + thread = process.GetSelectedThread() + self.assertTrue(thread.IsValid()) + + backtrace = [ + ["func2", 3], + ["func1", 8], + ["_start", 8], + ] + self.assertEqual(thread.GetNumFrames(), len(backtrace)) + for i in range(len(backtrace)): + frame = thread.GetFrameAtIndex(i) + self.assertTrue(frame.IsValid()) + symbol = frame.GetSymbol() + self.assertTrue(symbol.IsValid()) + self.assertEqual(symbol.GetName(), backtrace[i][0]) + function_start = symbol.GetStartAddress().GetLoadAddress(target) + self.assertEquals(function_start + backtrace[i][1], frame.GetPC()) + + self.dbg.DeleteTarget(target) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/a.s b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/a.s new file mode 100644 index 00000000000..119465c132a --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/a.s @@ -0,0 +1,35 @@ +# compile this with: +# as a.s -o a.o --32 && ld a.o -m elf_i386 +# generate core file with: +# ulimit -s 12 && ./a.out + +.text + +.globl func2 +.type func2, @function +func2: + pushl %ebp + movl %esp, %ebp + movl 0, %eax + popl %ebp + ret +.size func2, .-func2 + +.globl _start +.type _start, @function +_start: + pushl %ebp + movl %esp, %ebp + call func1 + popl %ebp + ret +.size _start, .-_start + +.globl func1 +.type func1, @function +func1: + pushl %ebp + movl %esp, %ebp + call func2 +.size func1, .-func1 + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/test.out b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/test.out Binary files differnew file mode 100755 index 00000000000..141c61ecbea --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/test.out diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/sigtramp/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/sigtramp/Makefile new file mode 100644 index 00000000000..10495940055 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/sigtramp/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/sigtramp/TestSigtrampUnwind.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/sigtramp/TestSigtrampUnwind.py new file mode 100644 index 00000000000..bf19cacac06 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/sigtramp/TestSigtrampUnwind.py @@ -0,0 +1,93 @@ +""" +Test that we can backtrace correctly with 'sigtramp' functions on the stack +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class SigtrampUnwind(TestBase): + mydir = TestBase.compute_mydir(__file__) + + # On different platforms the "_sigtramp" and "__kill" frames are likely to be different. + # This test could probably be adapted to run on linux/*bsd easily enough. + @skipUnlessDarwin + @expectedFailureAll(oslist=["ios", "watchos", "tvos", "bridgeos"], bugnumber="<rdar://problem/34006863>") # lldb skips 1 frame on arm64 above _sigtramp + def test(self): + """Test that we can backtrace correctly with _sigtramp on the stack""" + self.build() + self.setTearDownCleanup() + + exe = self.getBuildArtifact("a.out") + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + lldbutil.run_break_set_by_file_and_line(self, "main.c", line_number( + 'main.c', '// Set breakpoint here'), num_expected_locations=1) + + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + + if not process: + self.fail("SBTarget.Launch() failed") + + if process.GetState() != lldb.eStateStopped: + self.fail("Process should be in the 'stopped' state, " + "instead the actual state is: '%s'" % + lldbutil.state_type_to_str(process.GetState())) + + self.expect( + "pro handle -n false -p true -s false SIGUSR1", + "Have lldb pass SIGUSR1 signals", + substrs=[ + "SIGUSR1", + "true", + "false", + "false"]) + + lldbutil.run_break_set_by_symbol( + self, + "handler", + num_expected_locations=1, + module_name="a.out") + + self.runCmd("continue") + + thread = process.GetThreadAtIndex(0) + + found_handler = False + found_sigtramp = False + found_kill = False + found_main = False + + for f in thread.frames: + if f.GetFunctionName() == "handler": + found_handler = True + if f.GetFunctionName() == "_sigtramp": + found_sigtramp = True + if f.GetFunctionName() == "__kill": + found_kill = True + if f.GetFunctionName() == "main": + found_main = True + + if self.TraceOn(): + print("Backtrace once we're stopped:") + for f in thread.frames: + print(" %d %s" % (f.GetFrameID(), f.GetFunctionName())) + + if not found_handler: + self.fail("Unable to find handler() in backtrace.") + + if not found_sigtramp: + self.fail("Unable to find _sigtramp() in backtrace.") + + if not found_kill: + self.fail("Unable to find kill() in backtrace.") + + if not found_main: + self.fail("Unable to find main() in backtrace.") diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/sigtramp/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/sigtramp/main.c new file mode 100644 index 00000000000..aaa03e7aa84 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/sigtramp/main.c @@ -0,0 +1,27 @@ +#include <stdlib.h> +#include <signal.h> +#include <stdio.h> +#include <unistd.h> + +void handler (int in) +{ + puts ("in handler routine"); + while (1) + ; +} + +void +foo () +{ + puts ("in foo ()"); + kill (getpid(), SIGUSR1); +} +int main () +{ + puts ("in main"); // Set breakpoint here + signal (SIGUSR1, handler); + puts ("signal handler set up"); + foo(); + puts ("exiting"); + return 0; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/standard/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/standard/Makefile new file mode 100644 index 00000000000..22f1051530f --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/standard/Makefile @@ -0,0 +1 @@ +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/standard/TestStandardUnwind.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/standard/TestStandardUnwind.py new file mode 100644 index 00000000000..032b9e1aa61 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/standard/TestStandardUnwind.py @@ -0,0 +1,175 @@ +""" +Test that we can backtrace correctly from standard functions. + +This test suit is a collection of automatically generated tests from the source files in the +directory. Please DON'T add individual test cases to this file. + +To add a new test case to this test suit please create a simple C/C++ application and put the +source file into the directory of the test cases. The test suit will automatically pick the +file up and generate a test case from it in run time (with name test_standard_unwind_<file_name> +after escaping some special characters). +""" + +from __future__ import print_function + + +import unittest2 +import os +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +test_source_dirs = ["."] + + +class StandardUnwindTest(TestBase): + mydir = TestBase.compute_mydir(__file__) + + def standard_unwind_tests(self): + # The following variables have to be defined for each architecture and OS we testing for: + # base_function_names: List of function names where we accept that the stack unwinding is + # correct if they are on the stack. It should include the bottom most + # function on the stack and a list of functions where we know we can't + # unwind for any reason (list of expected failure functions) + # no_step_function_names: The list of functions where we don't want to step through + # instruction by instruction for any reason. (A valid reason is if + # it is impossible to step through a function instruction by + # instruction because it is special for some reason.) For these + # functions we will immediately do a step-out when we hit them. + + triple = self.dbg.GetSelectedPlatform().GetTriple() + if re.match("arm-.*-.*-android", triple): + base_function_names = [ + "_start", # Base function on the stack + "__memcpy_base", # Function reached by a fall through from the previous function + "__memcpy_base_aligned", + # Function reached by a fall through from the previous function + ] + no_step_function_names = [ + "__sync_fetch_and_add_4", # Calls into a special SO where we can't set a breakpoint + "pthread_mutex_lock", + # Uses ldrex and strex what interferes with the software single + # stepping + "pthread_mutex_unlock", + # Uses ldrex and strex what interferes with the software single + # stepping + "pthread_once", + # Uses ldrex and strex what interferes with the software single + # stepping + ] + elif re.match("aarch64-.*-.*-android", triple): + base_function_names = [ + "do_arm64_start", # Base function on the stack + ] + no_step_function_names = [ + None, + "__cxa_guard_acquire", + # Uses ldxr and stxr what interferes with the software single + # stepping + "__cxa_guard_release", + # Uses ldxr and stxr what interferes with the software single + # stepping + "pthread_mutex_lock", + # Uses ldxr and stxr what interferes with the software single + # stepping + "pthread_mutex_unlock", + # Uses ldxr and stxr what interferes with the software single + # stepping + "pthread_once", + # Uses ldxr and stxr what interferes with the software single + # stepping + ] + else: + self.skipTest("No expectations for the current architecture") + + exe = self.getBuildArtifact("a.out") + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + target.BreakpointCreateByName("main") + + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process is not None, "SBTarget.Launch() failed") + self.assertEqual( + process.GetState(), + lldb.eStateStopped, + "The process didn't hit main") + + index = 0 + while process.GetState() == lldb.eStateStopped: + index += 1 + if process.GetNumThreads() > 1: + # In case of a multi threaded inferior if one of the thread is stopped in a blocking + # syscall and we try to step it then + # SBThread::StepInstruction() will block forever + self.skipTest( + "Multi threaded inferiors are not supported by this test") + + thread = process.GetThreadAtIndex(0) + + if self.TraceOn(): + print("INDEX: %u" % index) + for f in thread.frames: + print(f) + + if thread.GetFrameAtIndex(0).GetFunctionName() is not None: + found_main = False + for f in thread.frames: + if f.GetFunctionName() in base_function_names: + found_main = True + break + self.assertTrue(found_main, + "Main function isn't found on the backtrace") + + if thread.GetFrameAtIndex( + 0).GetFunctionName() in no_step_function_names: + thread.StepOut() + else: + thread.StepInstruction(False) + +# Collect source files in the specified directories +test_source_files = set([]) +for d in test_source_dirs: + if os.path.isabs(d): + dirname = d + else: + dirname = os.path.join(os.path.dirname(__file__), d) + + for root, _, files in os.walk(dirname): + test_source_files = test_source_files | set( + os.path.abspath(os.path.join(root, f)) for f in files) + +# Generate test cases based on the collected source files +for f in test_source_files: + if f.endswith(".cpp") or f.endswith(".c"): + @skipIfWindows + @add_test_categories(["dwarf"]) + def test_function_dwarf(self, f=f): + if f.endswith(".cpp"): + d = {'CXX_SOURCES': f} + elif f.endswith(".c"): + d = {'C_SOURCES': f} + + # If we can't compile the inferior just skip the test instead of failing it. + # It makes the test suit more robust when testing on several different architecture + # avoid the hassle of skipping tests manually. + try: + self.buildDwarf(dictionary=d) + self.setTearDownCleanup(d) + except: + if self.TraceOn(): + print(sys.exc_info()[0]) + self.skipTest("Inferior not supported") + self.standard_unwind_tests() + + test_name = "test_unwind_" + str(f) + for c in ".=()/\\": + test_name = test_name.replace(c, '_') + + test_function_dwarf.__name__ = test_name + setattr( + StandardUnwindTest, + test_function_dwarf.__name__, + test_function_dwarf) diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/standard/hand_written/divmod.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/standard/hand_written/divmod.cpp new file mode 100644 index 00000000000..b2da92e992e --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/standard/hand_written/divmod.cpp @@ -0,0 +1,14 @@ +//===-- divmod.cpp ----------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +int +main(int argc, char const *argv[]) +{ + signed long long a = 123456789, b = 12, c = a / b, d = a % b; + unsigned long long e = 123456789, f = 12, g = e / f, h = e % f; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/standard/hand_written/fprintf.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/standard/hand_written/fprintf.cpp new file mode 100644 index 00000000000..f8be1aa0d40 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/standard/hand_written/fprintf.cpp @@ -0,0 +1,15 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <cstdio> + +int +main(int argc, char const *argv[]) +{ + fprintf(stderr, "%d %p %s\n", argc, argv, argv[0]); +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/standard/hand_written/new_delete.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/standard/hand_written/new_delete.cpp new file mode 100644 index 00000000000..b609ea366de --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/unwind/standard/hand_written/new_delete.cpp @@ -0,0 +1,14 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +int +main(int argc, char const *argv[]) +{ + int* p = new int; + delete p; +} diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/value_md5_crash/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/value_md5_crash/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/value_md5_crash/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/value_md5_crash/TestValueMD5Crash.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/value_md5_crash/TestValueMD5Crash.py new file mode 100644 index 00000000000..04f25c586e6 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/value_md5_crash/TestValueMD5Crash.py @@ -0,0 +1,52 @@ +""" +Verify that the hash computing logic for ValueObject's values can't crash us. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ValueMD5CrashTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// break here') + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24663") + def test_with_run_command(self): + """Verify that the hash computing logic for ValueObject's values can't crash us.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + value = self.frame().FindVariable("a") + value.SetPreferDynamicValue(lldb.eDynamicCanRunTarget) + + v = value.GetValue() + type_name = value.GetTypeName() + self.assertTrue(type_name == "B *", "a is a B*") + + self.runCmd("next") + self.runCmd("process kill") + + # now the process is dead, and value needs updating + v = value.GetValue() + + # if we are here, instead of crashed, the test succeeded diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/value_md5_crash/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/value_md5_crash/main.cpp new file mode 100644 index 00000000000..b641049f272 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/value_md5_crash/main.cpp @@ -0,0 +1,28 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +class A { +public: + virtual int foo() { return 1; } + virtual ~A () = default; + A() = default; +}; + +class B : public A { +public: + virtual int foo() { return 2; } + virtual ~B () = default; + B() = default; +}; + +int main() { + A* a = new B(); + a->foo(); // break here + return 0; // break here +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/var_path/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/var_path/Makefile new file mode 100644 index 00000000000..99998b20bcb --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/var_path/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/var_path/TestVarPath.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/var_path/TestVarPath.py new file mode 100644 index 00000000000..faab8a7f612 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/var_path/TestVarPath.py @@ -0,0 +1,95 @@ +""" +Make sure the getting a variable path works and doesn't crash. +""" + + + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + + +class TestVarPath(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # If your test case doesn't stress debug info, the + # set this to true. That way it won't be run once for + # each debug info format. + NO_DEBUG_INFO_TESTCASE = True + + def test_frame_var(self): + self.build() + self.do_test() + + def verify_point(self, frame, var_name, var_typename, x_value, y_value): + v = frame.GetValueForVariablePath(var_name) + self.assertTrue(v.GetError().Success(), "Make sure we find '%s'" % (var_name)) + self.assertTrue(v.GetType().GetName() == var_typename, + "Make sure '%s' has type '%s'" % (var_name, var_typename)) + + if '*' in var_typename: + valid_prefix = var_name + '->' + invalid_prefix = var_name + '.' + else: + valid_prefix = var_name + '.' + invalid_prefix = var_name + '->' + + valid_x_path = valid_prefix + 'x' + valid_y_path = valid_prefix + 'y' + invalid_x_path = invalid_prefix + 'x' + invalid_y_path = invalid_prefix + 'y' + invalid_m_path = invalid_prefix + 'm' + + v = frame.GetValueForVariablePath(valid_x_path) + self.assertTrue(v.GetError().Success(), "Make sure we find '%s'" % (valid_x_path)) + self.assertTrue(v.GetValue() == str(x_value), "Make sure '%s' has a value of %i" % (valid_x_path, x_value)) + self.assertTrue(v.GetType().GetName() == "int", "Make sure '%s' has type 'int'" % (valid_x_path)) + v = frame.GetValueForVariablePath(invalid_x_path) + self.assertTrue(v.GetError().Fail(), "Make sure we don't find '%s'" % (invalid_x_path)) + + v = frame.GetValueForVariablePath(valid_y_path) + self.assertTrue(v.GetError().Success(), "Make sure we find '%s'" % (valid_y_path)) + self.assertTrue(v.GetValue() == str(y_value), "Make sure '%s' has a value of %i" % (valid_y_path, y_value)) + self.assertTrue(v.GetType().GetName() == "int", "Make sure '%s' has type 'int'" % (valid_y_path)) + v = frame.GetValueForVariablePath(invalid_y_path) + self.assertTrue(v.GetError().Fail(), "Make sure we don't find '%s'" % (invalid_y_path)) + + v = frame.GetValueForVariablePath(invalid_m_path) + self.assertTrue(v.GetError().Fail(), "Make sure we don't find '%s'" % (invalid_m_path)) + + def do_test(self): + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( + self, "// Set a breakpoint here", lldb.SBFileSpec("main.cpp")) + + frame = thread.GetFrameAtIndex(0) + v = frame.GetValueForVariablePath('no_such_variable') + self.assertTrue(v.GetError().Fail(), "Make sure we don't find 'no_such_variable'") + + # Test an instance + self.verify_point(frame, 'pt', 'Point', 1, 2) + # Test a pointer + self.verify_point(frame, 'pt_ptr', 'Point *', 3030, 4040) + # Test using a pointer as an array + self.verify_point(frame, 'pt_ptr[-1]', 'Point', 1010, 2020) + self.verify_point(frame, 'pt_ptr[0]', 'Point', 3030, 4040) + self.verify_point(frame, 'pt_ptr[1]', 'Point', 5050, 6060) + # Test arrays + v = frame.GetValueForVariablePath('points') + self.assertTrue(v.GetError().Success(), + "Make sure we find 'points'") + self.verify_point(frame, 'points[0]', 'Point', 1010, 2020) + self.verify_point(frame, 'points[1]', 'Point', 3030, 4040) + self.verify_point(frame, 'points[2]', 'Point', 5050, 6060) + # Test a reference + self.verify_point(frame, 'pt_ref', 'Point &', 1, 2) + v = frame.GetValueForVariablePath('pt_sp') + self.assertTrue(v.GetError().Success(), "Make sure we find 'pt_sp'") + # Make sure we don't crash when looking for non existant child + # in type with synthetic children. This used to cause a crash. + v = frame.GetValueForVariablePath('pt_sp->not_valid_child') + self.assertTrue(v.GetError().Fail(), + "Make sure we don't find 'pt_sp->not_valid_child'") + + + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/var_path/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/var_path/main.cpp new file mode 100644 index 00000000000..0ea19cfcfea --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/var_path/main.cpp @@ -0,0 +1,15 @@ +#include <memory> + +struct Point { + int x, y; +}; + +int main() { + Point pt = { 1, 2 }; + Point points[] = {{1010,2020}, {3030,4040}, {5050,6060}}; + Point *pt_ptr = &points[1]; + Point &pt_ref = pt; + std::shared_ptr<Point> pt_sp(new Point{111,222}); + return 0; // Set a breakpoint here +} + diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/wrong_commands/.categories b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/wrong_commands/.categories new file mode 100644 index 00000000000..3a3f4df6416 --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/wrong_commands/.categories @@ -0,0 +1 @@ +cmdline diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/wrong_commands/TestWrongCommands.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/wrong_commands/TestWrongCommands.py new file mode 100644 index 00000000000..c722840b28f --- /dev/null +++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/functionalities/wrong_commands/TestWrongCommands.py @@ -0,0 +1,36 @@ +""" +Test how lldb reacts to wrong commands +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class UnknownCommandTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @no_debug_info_test + def test_ambiguous_command(self): + command_interpreter = self.dbg.GetCommandInterpreter() + self.assertTrue(command_interpreter, VALID_COMMAND_INTERPRETER) + result = lldb.SBCommandReturnObject() + + command_interpreter.HandleCommand("g", result) + self.assertFalse(result.Succeeded()) + self.assertRegexpMatches(result.GetError(), "Ambiguous command 'g'. Possible matches:") + self.assertRegexpMatches(result.GetError(), "gui") + self.assertRegexpMatches(result.GetError(), "gdb-remote") + self.assertEquals(1, result.GetError().count("gdb-remote")) + + @no_debug_info_test + def test_unknown_command(self): + command_interpreter = self.dbg.GetCommandInterpreter() + self.assertTrue(command_interpreter, VALID_COMMAND_INTERPRETER) + result = lldb.SBCommandReturnObject() + + command_interpreter.HandleCommand("qbert", result) + self.assertFalse(result.Succeeded()) + self.assertEquals(result.GetError(), "error: 'qbert' is not a valid command.\n") |