diff options
Diffstat (limited to 'packages/Python')
306 files changed, 8122 insertions, 2433 deletions
diff --git a/packages/Python/lldbsuite/support/encoded_file.py b/packages/Python/lldbsuite/support/encoded_file.py index 2c2fef383f7f..5c04cce3b3f9 100644 --- a/packages/Python/lldbsuite/support/encoded_file.py +++ b/packages/Python/lldbsuite/support/encoded_file.py @@ -31,7 +31,7 @@ def _encoded_write(old_write, encoding):          # If we were asked to write a `str` (in Py2) or a `bytes` (in Py3) decode it          # as unicode before attempting to write.          if isinstance(s, six.binary_type): -            s = s.decode(encoding) +            s = s.decode(encoding, "replace")          return old_write(s)      return impl diff --git a/packages/Python/lldbsuite/test/README-TestSuite b/packages/Python/lldbsuite/test/README-TestSuite index 92649fc9963c..8ea64c0aa3d5 100644 --- a/packages/Python/lldbsuite/test/README-TestSuite +++ b/packages/Python/lldbsuite/test/README-TestSuite @@ -1,7 +1,7 @@ -This README file describes the files and directories related to the Python test -suite under the current 'test' directory. +This README file describes the files and directories related       -*- rst -*- +to the Python test suite under the current 'test' directory. -o dotest.py +- dotest.py    Provides the test driver for the test suite.  To invoke it, cd to the 'test'    directory and issue the './dotest.py' command or './dotest.py -v' for more @@ -20,7 +20,7 @@ o dotest.py       This runs the test suite, with logging turned on for the lldb as well as       the process.gdb-remote channels and directs the run log to a file. -o lldbtest.py +- lldbtest.py    Provides an abstract base class of lldb test case named 'TestBase', which in    turn inherits from Python's unittest.TestCase.  The concrete subclass can @@ -41,7 +41,7 @@ o lldbtest.py    test case on its own.  To run the whole test suite, 'dotest.py' is all you    need to do. -o subdirectories of 'test' +- subdirectories of 'test'    Most of them predate the introduction of the python test suite and contain    example C/C++/ObjC source files which get compiled into executables which are @@ -58,7 +58,7 @@ o subdirectories of 'test'    testcase that run a process to a breakpoint and check a local variable.  These    are convenient starting points for adding new tests. -o make directory +- make directory    Contains Makefile.rules, which can be utilized by test cases to write Makefile    based rules to build binaries for the inferiors. @@ -95,12 +95,12 @@ o make directory    The exe names for the two test methods are equal to the test method names and    are therefore guaranteed different. -o plugins directory +- plugins directory    Contains platform specific plugin to build binaries with dsym/dwarf debugging    info.  Other platform specific functionalities may be added in the future. -o unittest2 directory +- unittest2 directory    Many new features were added to unittest in Python 2.7, including test    discovery. unittest2 allows you to use these features with earlier versions of @@ -114,7 +114,7 @@ o unittest2 directory    Later versions of unittest2 include changes in unittest made in Python 3.2 and    onwards after the release of Python 2.7. -o dotest.pl +- dotest.pl    In case you wonder, there is also a 'dotest.pl' perl script file.  It was    created to visit each Python test case under the specified directory and @@ -127,47 +127,56 @@ o dotest.pl    Note: dotest.pl has been moved to the attic directory. -o Profiling dotest.py runs +- Profiling dotest.py runs    I used the following command line thingy to do the profiling on a SnowLeopard    machine: -$ DOTEST_PROFILE=YES DOTEST_SCRIPT_DIR=/Volumes/data/lldb/svn/trunk/test /System/Library/Frameworks/Python.framework/Versions/Current/lib/python2.6/cProfile.py -o my.profile ./dotest.py -v -w 2> ~/Developer/Log/lldbtest.log +    $ DOTEST_PROFILE=YES DOTEST_SCRIPT_DIR=/Volumes/data/lldb/svn/trunk/test /System/Library/Frameworks/Python.framework/Versions/Current/lib/python2.6/cProfile.py -o my.profile ./dotest.py -v -w 2> ~/Developer/Log/lldbtest.log    After that, I used the pstats.py module to browse the statistics: -$ python /System/Library/Frameworks/Python.framework/Versions/Current/lib/python2.6/pstats.py my.profile  - -o Writing test cases: - - We strongly prefer writing test cases using the SB API's rather than the runCmd & expect.   - Unless you are actually testing some feature of the command line, please don't write  - command based tests.  For historical reasons there are plenty of examples of tests in the  - test suite that use runCmd where they shouldn't, but don't copy them, copy the plenty that  - do use the SB API's instead.   - - The reason for this is that our policy is that we will maintain compatibility with the  - SB API's.  But we don't make any similar guarantee about the details of command result format.   - If your test is using the command line, it is going to have to check against the command result - text, and you either end up writing your check  pattern by checking as little as possible so  - you won't be exposed to random changes in the text; in which case you can end up missing some  - failure, or you test too much and it means irrelevant changes break your tests. - - However, if you use the Python API's it is possible to check all the results you want  - to check in a very explicit way, which makes the tests much more robust. - - Even if you are testing that a command-line command does some specific thing, it is still  - better in general to use the SB API's to drive to the point where you want to run the test,  - then use SBInterpreter::HandleCommand to run the command.  You get the full result text  - from the command in the command return object, and all the part where you are driving the  - debugger to the point you want to test will be more robust. - - The sample_test directory contains a standard and an "inline" test that are good starting - points for writing a new test. - -o Attaching in test cases: - - If you need to attach to inferiors in your tests, you must make sure the inferior calls - lldb_enable_attach(), before the debugger attempts to attach. This function performs any - platform-specific processing needed to enable attaching to this process (e.g., on Linux, we - execute prctl(PR_SET_TRACER) syscall to disable protections present in some Linux systems). +    $ python /System/Library/Frameworks/Python.framework/Versions/Current/lib/python2.6/pstats.py my.profile  + +- Writing test cases: + +  We strongly prefer writing test cases using the SB API's rather than +  the runCmd & expect.  Unless you are actually testing some feature +  of the command line, please don't write command based tests.  For +  historical reasons there are plenty of examples of tests in the test +  suite that use runCmd where they shouldn't, but don't copy them, +  copy the plenty that do use the SB API's instead. + +  The reason for this is that our policy is that we will maintain +  compatibility with the SB API's.  But we don't make any similar +  guarantee about the details of command result format.  If your test +  is using the command line, it is going to have to check against the +  command result text, and you either end up writing your check +  pattern by checking as little as possible so you won't be exposed to +  random changes in the text; in which case you can end up missing +  some failure, or you test too much and it means irrelevant changes +  break your tests. + +  However, if you use the Python API's it is possible to check all the +  results you want to check in a very explicit way, which makes the +  tests much more robust. + +  Even if you are testing that a command-line command does some +  specific thing, it is still better in general to use the SB API's to +  drive to the point where you want to run the test, then use +  SBInterpreter::HandleCommand to run the command.  You get the full +  result text from the command in the command return object, and all +  the part where you are driving the debugger to the point you want to +  test will be more robust. + +  The sample_test directory contains a standard and an "inline" test +  that are good starting points for writing a new test. + +- Attaching in test cases: + +  If you need to attach to inferiors in your tests, you must make sure +  the inferior calls lldb_enable_attach(), before the debugger +  attempts to attach. This function performs any platform-specific +  processing needed to enable attaching to this process (e.g., on +  Linux, we execute prctl(PR_SET_TRACER) syscall to disable +  protections present in some Linux systems). diff --git a/packages/Python/lldbsuite/test/api/multithreaded/TestMultithreaded.py b/packages/Python/lldbsuite/test/api/multithreaded/TestMultithreaded.py index dd03fcf31e87..d91eec1fd51b 100644 --- a/packages/Python/lldbsuite/test/api/multithreaded/TestMultithreaded.py +++ b/packages/Python/lldbsuite/test/api/multithreaded/TestMultithreaded.py @@ -68,7 +68,7 @@ class SBBreakpointCallbackCase(TestBase):      # clang-cl does not support throw or catch (llvm.org/pr24538)      @skipIfWindows      @expectedFlakeyFreeBSD -    @expectedFailureAll(oslist=["linux"]) +    @skipIf(oslist=["linux"]) # flakey      def test_sb_api_listener_resume(self):          """ Test that a process can be resumed from a non-main thread. """          self.build_and_test( diff --git a/packages/Python/lldbsuite/test/arm/breakpoint-it/TestBreakpointIt.py b/packages/Python/lldbsuite/test/arm/breakpoint-it/TestBreakpointIt.py index 30510638f096..e9dbe670dc0b 100644 --- a/packages/Python/lldbsuite/test/arm/breakpoint-it/TestBreakpointIt.py +++ b/packages/Python/lldbsuite/test/arm/breakpoint-it/TestBreakpointIt.py @@ -19,6 +19,7 @@ class TestBreakpointIt(TestBase):      NO_DEBUG_INFO_TESTCASE = True      @skipIf(archs=no_match(["arm"])) +    @skipIf(archs=["arm64", "arm64e"])      def test_false(self):          self.build()          exe = self.getBuildArtifact("a.out") @@ -32,6 +33,7 @@ class TestBreakpointIt(TestBase):                  "Breakpoint does not get hit")      @skipIf(archs=no_match(["arm"])) +    @skipIf(archs=["arm64", "arm64e"])      def test_true(self):          self.build()          exe = self.getBuildArtifact("a.out") diff --git a/packages/Python/lldbsuite/test/benchmarks/disassembly/TestDisassembly.py b/packages/Python/lldbsuite/test/benchmarks/disassembly/TestDisassembly.py deleted file mode 100644 index 8bce4815894d..000000000000 --- a/packages/Python/lldbsuite/test/benchmarks/disassembly/TestDisassembly.py +++ /dev/null @@ -1,165 +0,0 @@ -"""Disassemble lldb's Driver::MainLoop() functions comparing lldb against gdb.""" - -from __future__ import print_function - - -import os -import sys -import lldb -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbbench import * -from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil - - -def is_exe(fpath): -    """Returns true if fpath is an executable.""" -    return os.path.isfile(fpath) and os.access(fpath, os.X_OK) - - -class DisassembleDriverMainLoop(BenchBase): - -    mydir = TestBase.compute_mydir(__file__) - -    def setUp(self): -        """ -        Note that lldbtest_config.lldbExec can be specified with the LLDB_EXEC env variable (see -        dotest.py), and gdbExec can be specified with the GDB_EXEC env variable. -        This provides a flexibility in specifying different versions of gdb for -        comparison purposes. -        """ -        BenchBase.setUp(self) -        # If env var GDB_EXEC is specified, use it; otherwise, use gdb in your -        # PATH env var. -        if "GDB_EXEC" in os.environ and is_exe(os.environ["GDB_EXEC"]): -            self.gdbExec = os.environ["GDB_EXEC"] -        else: -            self.gdbExec = "gdb" - -        self.exe = lldbtest_config.lldbExec -        self.function = 'Driver::MainLoop()' -        self.lldb_avg = None -        self.gdb_avg = None -        self.count = 5 - -    @benchmarks_test -    @no_debug_info_test -    @expectedFailureAll( -        oslist=["windows"], -        bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") -    def test_run_lldb_then_gdb(self): -        """Test disassembly on a large function with lldb vs. gdb.""" -        print() -        print("lldb path: %s" % lldbtest_config.lldbExec) -        print("gdb path: %s" % self.gdbExec) - -        print() -        self.run_lldb_disassembly(self.exe, self.function, self.count) -        print("lldb benchmark:", self.stopwatch) -        self.run_gdb_disassembly(self.exe, self.function, self.count) -        print("gdb benchmark:", self.stopwatch) -        print("lldb_avg/gdb_avg: %f" % (self.lldb_avg / self.gdb_avg)) - -    @benchmarks_test -    @no_debug_info_test -    @expectedFailureAll( -        oslist=["windows"], -        bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") -    def test_run_gdb_then_lldb(self): -        """Test disassembly on a large function with lldb vs. gdb.""" -        print() -        print("lldb path: %s" % lldbtest_config.lldbExec) -        print("gdb path: %s" % self.gdbExec) - -        print() -        self.run_gdb_disassembly(self.exe, self.function, self.count) -        print("gdb benchmark:", self.stopwatch) -        self.run_lldb_disassembly(self.exe, self.function, self.count) -        print("lldb benchmark:", self.stopwatch) -        print("lldb_avg/gdb_avg: %f" % (self.lldb_avg / self.gdb_avg)) - -    def run_lldb_disassembly(self, exe, function, count): -        import pexpect -        # Set self.child_prompt, which is "(lldb) ". -        self.child_prompt = '(lldb) ' -        prompt = self.child_prompt - -        # So that the child gets torn down after the test. -        self.child = pexpect.spawn( -            '%s %s %s' % -            (lldbtest_config.lldbExec, self.lldbOption, exe)) -        child = self.child - -        # Turn on logging for what the child sends back. -        if self.TraceOn(): -            child.logfile_read = sys.stdout - -        child.expect_exact(prompt) -        child.sendline('breakpoint set -F %s' % function) -        child.expect_exact(prompt) -        child.sendline('run') -        child.expect_exact(prompt) - -        # Reset the stopwatch now. -        self.stopwatch.reset() -        for i in range(count): -            with self.stopwatch: -                # Disassemble the function. -                child.sendline('disassemble -f') -                child.expect_exact(prompt) -            child.sendline('next') -            child.expect_exact(prompt) - -        child.sendline('quit') -        try: -            self.child.expect(pexpect.EOF) -        except: -            pass - -        self.lldb_avg = self.stopwatch.avg() -        if self.TraceOn(): -            print("lldb disassembly benchmark:", str(self.stopwatch)) -        self.child = None - -    def run_gdb_disassembly(self, exe, function, count): -        import pexpect -        # Set self.child_prompt, which is "(gdb) ". -        self.child_prompt = '(gdb) ' -        prompt = self.child_prompt - -        # So that the child gets torn down after the test. -        self.child = pexpect.spawn('%s --nx %s' % (self.gdbExec, exe)) -        child = self.child - -        # Turn on logging for what the child sends back. -        if self.TraceOn(): -            child.logfile_read = sys.stdout - -        child.expect_exact(prompt) -        child.sendline('break %s' % function) -        child.expect_exact(prompt) -        child.sendline('run') -        child.expect_exact(prompt) - -        # Reset the stopwatch now. -        self.stopwatch.reset() -        for i in range(count): -            with self.stopwatch: -                # Disassemble the function. -                child.sendline('disassemble') -                child.expect_exact(prompt) -            child.sendline('next') -            child.expect_exact(prompt) - -        child.sendline('quit') -        child.expect_exact('The program is running.  Exit anyway?') -        child.sendline('y') -        try: -            self.child.expect(pexpect.EOF) -        except: -            pass - -        self.gdb_avg = self.stopwatch.avg() -        if self.TraceOn(): -            print("gdb disassembly benchmark:", str(self.stopwatch)) -        self.child = None diff --git a/packages/Python/lldbsuite/test/benchmarks/disassembly/TestDoAttachThenDisassembly.py b/packages/Python/lldbsuite/test/benchmarks/disassembly/TestDoAttachThenDisassembly.py deleted file mode 100644 index 36f23572648d..000000000000 --- a/packages/Python/lldbsuite/test/benchmarks/disassembly/TestDoAttachThenDisassembly.py +++ /dev/null @@ -1,70 +0,0 @@ -"""Test lldb's disassemblt speed.  This bench deliberately attaches to an lldb -inferior and traverses the stack for thread0 to arrive at frame with function -'MainLoop'.  It is important to specify an lldb executable as the inferior.""" - -from __future__ import print_function - - -import os -import sys -import lldb -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbbench import * -from lldbsuite.test.lldbtest import * - - -class AttachThenDisassemblyBench(BenchBase): - -    mydir = TestBase.compute_mydir(__file__) - -    def setUp(self): -        BenchBase.setUp(self) -        self.exe = lldbtest_config.lldbExec -        self.count = 10 - -    @benchmarks_test -    @no_debug_info_test -    def test_attach_then_disassembly(self): -        """Attach to a spawned lldb process then run disassembly benchmarks.""" -        print() -        self.run_lldb_attach_then_disassembly(self.exe, self.count) -        print("lldb disassembly benchmark:", self.stopwatch) - -    def run_lldb_attach_then_disassembly(self, exe, count): -        target = self.dbg.CreateTarget(exe) - -        # Spawn a new process and don't display the stdout if not in TraceOn() -        # mode. -        import subprocess -        popen = subprocess.Popen([exe, self.lldbOption], stdout=open( -            os.devnull, 'w') if not self.TraceOn() else None) -        if self.TraceOn(): -            print("pid of spawned process: %d" % popen.pid) - -        # Attach to the launched lldb process. -        listener = lldb.SBListener("my.attach.listener") -        error = lldb.SBError() -        process = target.AttachToProcessWithID(listener, popen.pid, error) - -        # Set thread0 as the selected thread, followed by the 'MainLoop' frame -        # as the selected frame.  Then do disassembly on the function. -        thread0 = process.GetThreadAtIndex(0) -        process.SetSelectedThread(thread0) -        i = 0 -        found = False -        for f in thread0: -            # print("frame#%d %s" % (i, f.GetFunctionName())) -            if "MainLoop" in f.GetFunctionName(): -                found = True -                thread0.SetSelectedFrame(i) -                if self.TraceOn(): -                    print("Found frame#%d for function 'MainLoop'" % i) -                break -            i += 1 - -        # Reset the stopwatch now. -        self.stopwatch.reset() -        for i in range(count): -            with self.stopwatch: -                # Disassemble the function. -                self.runCmd("disassemble -f") diff --git a/packages/Python/lldbsuite/test/benchmarks/disassembly/TestXcode41Vs42GDBDisassembly.py b/packages/Python/lldbsuite/test/benchmarks/disassembly/TestXcode41Vs42GDBDisassembly.py deleted file mode 100644 index fd91bb441d9f..000000000000 --- a/packages/Python/lldbsuite/test/benchmarks/disassembly/TestXcode41Vs42GDBDisassembly.py +++ /dev/null @@ -1,120 +0,0 @@ -"""Disassemble lldb's Driver::MainLoop() functions comparing Xcode 4.1 vs. 4.2's gdb.""" - -from __future__ import print_function - - -import os -import sys -import lldb -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbbench import * -from lldbsuite.test.lldbtest import * -from lldbsuite.test import configuration -from lldbsuite.test import lldbutil - - -class XCode41Vs42GDBDisassembly(BenchBase): - -    mydir = TestBase.compute_mydir(__file__) - -    def setUp(self): -        BenchBase.setUp(self) -        self.gdb_41_exe = '/Xcode41/usr/bin/gdb' -        self.gdb_42_exe = '/Developer/usr/bin/gdb' -        self.exe = lldbtest_config.lldbExec -        self.function = 'Driver::MainLoop()' -        self.gdb_41_avg = None -        self.gdb_42_avg = None -        self.count = 5 - -    @benchmarks_test -    @no_debug_info_test -    @expectedFailureAll( -        oslist=["windows"], -        bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") -    def test_run_41_then_42(self): -        """Test disassembly on a large function with 4.1 vs. 4.2's gdb.""" -        print() -        self.run_gdb_disassembly( -            self.gdb_41_exe, -            self.exe, -            self.function, -            self.count) -        print("4.1 gdb benchmark:", self.stopwatch) -        self.gdb_41_avg = self.stopwatch.avg() -        self.run_gdb_disassembly( -            self.gdb_42_exe, -            self.exe, -            self.function, -            self.count) -        print("4.2 gdb benchmark:", self.stopwatch) -        self.gdb_42_avg = self.stopwatch.avg() -        print("gdb_42_avg/gdb_41_avg: %f" % -              (self.gdb_42_avg / self.gdb_41_avg)) - -    @benchmarks_test -    @no_debug_info_test -    @expectedFailureAll( -        oslist=["windows"], -        bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") -    def test_run_42_then_41(self): -        """Test disassembly on a large function with 4.1 vs. 4.2's gdb.""" -        print() -        self.run_gdb_disassembly( -            self.gdb_42_exe, -            self.exe, -            self.function, -            self.count) -        print("4.2 gdb benchmark:", self.stopwatch) -        self.gdb_42_avg = self.stopwatch.avg() -        self.run_gdb_disassembly( -            self.gdb_41_exe, -            self.exe, -            self.function, -            self.count) -        print("4.1 gdb benchmark:", self.stopwatch) -        self.gdb_41_avg = self.stopwatch.avg() -        print("gdb_42_avg/gdb_41_avg: %f" % -              (self.gdb_42_avg / self.gdb_41_avg)) - -    def run_gdb_disassembly(self, gdb_exe_path, exe, function, count): -        import pexpect -        # Set self.child_prompt, which is "(gdb) ". -        self.child_prompt = '(gdb) ' -        prompt = self.child_prompt - -        # So that the child gets torn down after the test. -        self.child = pexpect.spawn('%s --nx %s' % (gdb_exe_path, exe)) -        child = self.child - -        # Turn on logging for what the child sends back. -        if self.TraceOn(): -            child.logfile_read = sys.stdout - -        child.expect_exact(prompt) -        child.sendline('break %s' % function) -        child.expect_exact(prompt) -        child.sendline('run') -        child.expect_exact(prompt) - -        # Reset the stopwatch now. -        self.stopwatch.reset() -        for i in range(count): -            with self.stopwatch: -                # Disassemble the function. -                child.sendline('disassemble') -                child.expect_exact(prompt) -            child.sendline('next') -            child.expect_exact(prompt) - -        child.sendline('quit') -        child.expect_exact('The program is running.  Exit anyway?') -        child.sendline('y') -        try: -            self.child.expect(pexpect.EOF) -        except: -            pass - -        if self.TraceOn(): -            print("gdb disassembly benchmark:", str(self.stopwatch)) -        self.child = None diff --git a/packages/Python/lldbsuite/test/configuration.py b/packages/Python/lldbsuite/test/configuration.py index 94781050dc4b..a7f4ac7efe2b 100644 --- a/packages/Python/lldbsuite/test/configuration.py +++ b/packages/Python/lldbsuite/test/configuration.py @@ -46,6 +46,9 @@ count = 1  arch = None        # Must be initialized after option parsing  compiler = None    # Must be initialized after option parsing +# Path to the FileCheck testing tool. Not optional. +filecheck = None +  # The arch might dictate some specific CFLAGS to be passed to the toolchain to build  # the inferior programs.  The global variable cflags_extras provides a hook to do  # just that. @@ -110,9 +113,13 @@ lldb_platform_working_dir = None  # The base directory in which the tests are being built.  test_build_dir = None +# The only directory to scan for tests. If multiple test directories are +# specified, and an exclusive test subdirectory is specified, the latter option +# takes precedence. +exclusive_test_subdir = None +  # Parallel execution settings  is_inferior_test_runner = False -multiprocess_test_subdir = None  num_threads = None  no_multiprocess_test_runner = False  test_runner_name = None @@ -144,3 +151,42 @@ def shouldSkipBecauseOfCategories(test_categories):              return True      return False + + +def get_absolute_path_to_exclusive_test_subdir(): +    """ +    If an exclusive test subdirectory is specified, return its absolute path. +    Otherwise return None. +    """ +    test_directory = os.path.dirname(os.path.realpath(__file__)) + +    if not exclusive_test_subdir: +        return + +    if len(exclusive_test_subdir) > 0: +        test_subdir = os.path.join(test_directory, exclusive_test_subdir) +        if os.path.isdir(test_subdir): +            return test_subdir + +        print('specified test subdirectory {} is not a valid directory\n' +                .format(test_subdir)) + + +def get_absolute_path_to_root_test_dir(): +    """ +    If an exclusive test subdirectory is specified, return its absolute path. +    Otherwise, return the absolute path of the root test directory. +    """ +    test_subdir = get_absolute_path_to_exclusive_test_subdir() +    if test_subdir: +        return test_subdir + +    return os.path.dirname(os.path.realpath(__file__)) + + +def get_filecheck_path(): +    """ +    Get the path to the FileCheck testing tool. +    """ +    if filecheck and os.path.lexists(filecheck): +        return filecheck diff --git a/packages/Python/lldbsuite/test/decorators.py b/packages/Python/lldbsuite/test/decorators.py index 8b33cad3d1ba..2458a6f8745e 100644 --- a/packages/Python/lldbsuite/test/decorators.py +++ b/packages/Python/lldbsuite/test/decorators.py @@ -74,13 +74,14 @@ def _check_expected_version(comparison, expected, actual):          LooseVersion(expected_str)) +_re_pattern_type = type(re.compile(''))  def _match_decorator_property(expected, actual):      if actual is None or expected is None:          return True      if isinstance(expected, no_match):          return not _match_decorator_property(expected.item, actual) -    elif isinstance(expected, (re._pattern_type,) + six.string_types): +    elif isinstance(expected, (_re_pattern_type,) + six.string_types):          return re.search(expected, actual) is not None      elif hasattr(expected, "__iter__"):          return any([x is not None and _match_decorator_property(x, actual) @@ -192,10 +193,10 @@ def _decorateTest(mode,              py_version is None) or _check_expected_version(              py_version[0], py_version[1], sys.version_info)          skip_for_macos_version = (macos_version is None) or ( -            _check_expected_version( +            (platform.mac_ver()[0] != "") and (_check_expected_version(                  macos_version[0],                  macos_version[1], -                platform.mac_ver()[0])) +                platform.mac_ver()[0])))          # For the test to be skipped, all specified (e.g. not None) parameters must be True.          # An unspecified parameter means "any", so those are marked skip by default.  And we skip @@ -457,12 +458,6 @@ def expectedFlakey(expected_fn, bugnumber=None):          return expectedFailure_impl -def expectedFlakeyDsym(bugnumber=None): -    def fn(self): -        return self.getDebugInfo() == "dwarf" -    return expectedFlakey(fn, bugnumber) - -  def expectedFlakeyOS(oslist, bugnumber=None, compilers=None):      def fn(self):          return (self.getPlatform() in oslist and @@ -600,28 +595,6 @@ def skipUnlessDarwin(func):      return skipUnlessPlatform(lldbplatformutil.getDarwinOSTriples())(func) -def skipUnlessGoInstalled(func): -    """Decorate the item to skip tests when no Go compiler is available.""" - -    def is_go_missing(self): -        compiler = self.getGoCompilerVersion() -        if not compiler: -            return "skipping because go compiler not found" -        match_version = re.search(r"(\d+\.\d+(\.\d+)?)", compiler) -        if not match_version: -            # Couldn't determine version. -            return "skipping because go version could not be parsed out of {}".format( -                compiler) -        else: -            min_strict_version = StrictVersion("1.4.0") -            compiler_strict_version = StrictVersion(match_version.group(1)) -            if compiler_strict_version < min_strict_version: -                return "skipping because available version ({}) does not meet minimum required version ({})".format( -                    compiler_strict_version, min_strict_version) -        return None -    return skipTestIfFn(is_go_missing)(func) - -  def skipIfHostIncompatibleWithRemote(func):      """Decorate the item to skip tests if binaries built on this host are incompatible.""" @@ -687,6 +660,30 @@ def skipUnlessSupportedTypeAttribute(attr):          return None      return skipTestIfFn(compiler_doesnt_support_struct_attribute) +def skipUnlessHasCallSiteInfo(func): +    """Decorate the function to skip testing unless call site info from clang is available.""" + +    def is_compiler_clang_with_call_site_info(self): +        compiler_path = self.getCompiler() +        compiler = os.path.basename(compiler_path) +        if not compiler.startswith("clang"): +            return "Test requires clang as compiler" + +        f = tempfile.NamedTemporaryFile() +        cmd = "echo 'int main() {}' | " \ +              "%s -g -glldb -O1 -S -emit-llvm -x c -o %s -" % (compiler_path, f.name) +        if os.popen(cmd).close() is not None: +            return "Compiler can't compile with call site info enabled" + +        with open(f.name, 'r') as ir_output_file: +            buf = ir_output_file.read() + +        if 'DIFlagAllCallsDescribed' not in buf: +            return "Compiler did not introduce DIFlagAllCallsDescribed IR flag" + +        return None +    return skipTestIfFn(is_compiler_clang_with_call_site_info)(func) +  def skipUnlessThreadSanitizer(func):      """Decorate the item to skip test unless Clang -fsanitize=thread is supported.""" @@ -810,3 +807,10 @@ def skipUnlessFeature(feature):              except subprocess.CalledProcessError:                  return "%s is not supported on this system." % feature      return skipTestIfFn(is_feature_enabled) + +def skipIfSanitized(func): +    """Skip this test if the environment is set up to run LLDB itself under ASAN.""" +    def is_sanitized(): +        return (('DYLD_INSERT_LIBRARIES' in os.environ) and +                'libclang_rt.asan' in os.environ['DYLD_INSERT_LIBRARIES']) +    return skipTestIfFn(is_sanitized)(func) diff --git a/packages/Python/lldbsuite/test/dosep.py b/packages/Python/lldbsuite/test/dosep.py index 616fbf381edf..21010c28a78c 100644 --- a/packages/Python/lldbsuite/test/dosep.py +++ b/packages/Python/lldbsuite/test/dosep.py @@ -1558,7 +1558,7 @@ def rerun_tests(test_subdir, tests_for_rerun, dotest_argv, session_dir,      print("\nTest rerun complete\n") -def main(num_threads, test_subdir, test_runner_name, results_formatter): +def main(num_threads, test_runner_name, results_formatter):      """Run dotest.py in inferior mode in parallel.      @param num_threads the parsed value of the num-threads command line @@ -1600,16 +1600,7 @@ def main(num_threads, test_subdir, test_runner_name, results_formatter):      session_dir = os.path.join(os.getcwd(), dotest_options.s) -    # The root directory was specified on the command line -    test_directory = os.path.dirname(os.path.realpath(__file__)) -    if test_subdir and len(test_subdir) > 0: -        test_subdir = os.path.join(test_directory, test_subdir) -        if not os.path.isdir(test_subdir): -            print( -                'specified test subdirectory {} is not a valid directory\n' -                .format(test_subdir)) -    else: -        test_subdir = test_directory +    test_subdir = configuration.get_absolute_path_to_root_test_dir()      # clean core files in test tree from previous runs (Linux)      cores = find('core.*', test_subdir) @@ -1698,7 +1689,7 @@ def main(num_threads, test_subdir, test_runner_name, results_formatter):      # move core files into session dir      cores = find('core.*', test_subdir)      for core in cores: -        dst = core.replace(test_directory, "")[1:] +        dst = core.replace(test_subdir, "")[1:]          dst = dst.replace(os.path.sep, "-")          os.rename(core, os.path.join(session_dir, dst)) diff --git a/packages/Python/lldbsuite/test/dotest.py b/packages/Python/lldbsuite/test/dotest.py index d28c5ef069b7..644f63576c06 100644 --- a/packages/Python/lldbsuite/test/dotest.py +++ b/packages/Python/lldbsuite/test/dotest.py @@ -307,6 +307,24 @@ def parseOptionsAndInitTestdirs():        os.environ['DSYMUTIL'] = seven.get_command_output(            'xcrun -find -toolchain default dsymutil') +    if args.filecheck: +        # The lldb-dotest script produced by the CMake build passes in a path +        # to a working FileCheck binary. So does one specific Xcode project +        # target. However, when invoking dotest.py directly, a valid --filecheck +        # option needs to be given. +        configuration.filecheck = os.path.abspath(args.filecheck) +    else: +        outputPaths = get_llvm_bin_dirs() +        for outputPath in outputPaths: +            candidatePath = os.path.join(outputPath, 'FileCheck') +            if is_exe(candidatePath): +                configuration.filecheck = candidatePath +                break + +    if not configuration.get_filecheck_path(): +        logging.warning('No valid FileCheck executable; some tests may fail...') +        logging.warning('(Double-check the --filecheck argument to dotest.py)') +      if args.channels:          lldbtest_config.channels = args.channels @@ -439,7 +457,7 @@ def parseOptionsAndInitTestdirs():          configuration.num_threads = args.num_threads      if args.test_subdir: -        configuration.multiprocess_test_subdir = args.test_subdir +        configuration.exclusive_test_subdir = args.test_subdir      if args.test_runner_name:          configuration.test_runner_name = args.test_runner_name @@ -616,6 +634,31 @@ def getOutputPaths(lldbRootDirectory):      return result +def get_llvm_bin_dirs(): +    """ +    Returns an array of paths that may have the llvm/clang/etc binaries +    in them, relative to this current file.   +    Returns an empty array if none are found. +    """ +    result = [] + +    lldb_root_path = os.path.join( +        os.path.dirname(__file__), "..", "..", "..", "..") +    paths_to_try = [ +        "llvm-build/Release+Asserts/x86_64/bin", +        "llvm-build/Debug+Asserts/x86_64/bin", +        "llvm-build/Release/x86_64/bin", +        "llvm-build/Debug/x86_64/bin", +        "llvm-build/Ninja-DebugAssert/llvm-macosx-x86_64/bin", +        "llvm-build/Ninja-ReleaseAssert/llvm-macosx-x86_64/bin", +        "llvm-build/Ninja-RelWithDebInfoAssert/llvm-macosx-x86_64/bin", +    ] +    for p in paths_to_try: +        path = os.path.join(lldb_root_path, p) +        if os.path.exists(path): +            result.append(path) + +    return result  def setupSysPath():      """ @@ -646,6 +689,7 @@ def setupSysPath():      pluginPath = os.path.join(scriptPath, 'plugins')      toolsLLDBMIPath = os.path.join(scriptPath, 'tools', 'lldb-mi') +    toolsLLDBVSCode = os.path.join(scriptPath, 'tools', 'lldb-vscode')      toolsLLDBServerPath = os.path.join(scriptPath, 'tools', 'lldb-server')      # Insert script dir, plugin dir, lldb-mi dir and lldb-server dir to the @@ -654,6 +698,9 @@ def setupSysPath():      # Adding test/tools/lldb-mi to the path makes it easy      sys.path.insert(0, toolsLLDBMIPath)      # to "import lldbmi_testcase" from the MI tests +    # Adding test/tools/lldb-vscode to the path makes it easy to +    # "import lldb_vscode_testcase" from the VSCode tests +    sys.path.insert(0, toolsLLDBVSCode)      # Adding test/tools/lldb-server to the path makes it easy      sys.path.insert(0, toolsLLDBServerPath)      # to "import lldbgdbserverutils" from the lldb-server tests @@ -723,6 +770,15 @@ def setupSysPath():                  "The 'lldb-mi' executable cannot be located.  The lldb-mi tests can not be run as a result.")              configuration.skipCategories.append("lldb-mi") +    lldbVSCodeExec = os.path.join(lldbDir, "lldb-vscode") +    if is_exe(lldbVSCodeExec): +        os.environ["LLDBVSCODE_EXEC"] = lldbVSCodeExec +    else: +        if not configuration.shouldSkipBecauseOfCategories(["lldb-vscode"]): +            print( +                "The 'lldb-vscode' executable cannot be located.  The lldb-vscode tests can not be run as a result.") +            configuration.skipCategories.append("lldb-vscode") +      lldbPythonDir = None  # The directory that contains 'lldb/__init__.py'      if not configuration.lldbFrameworkPath and os.path.exists(os.path.join(lldbLibDir, "LLDB.framework")):          configuration.lldbFrameworkPath = os.path.join(lldbLibDir, "LLDB.framework") @@ -882,6 +938,7 @@ def visit_file(dir, name):              unittest2.defaultTestLoader.loadTestsFromName(base)) +# TODO: This should be replaced with a call to find_test_files_in_dir_tree.  def visit(prefix, dir, names):      """Visitor function for os.path.walk(path, visit, arg).""" @@ -1004,14 +1061,15 @@ def getMyCommandLine():  def checkDsymForUUIDIsNotOn():      cmd = ["defaults", "read", "com.apple.DebugSymbols"] -    pipe = subprocess.Popen( +    process = subprocess.Popen(          cmd,          stdout=subprocess.PIPE,          stderr=subprocess.STDOUT) -    cmd_output = pipe.stdout.read() -    if cmd_output and "DBGFileMappedPaths = " in cmd_output: +    cmd_output = process.stdout.read() +    output_str = cmd_output.decode("utf-8") +    if "DBGFileMappedPaths = " in output_str:          print("%s =>" % ' '.join(cmd)) -        print(cmd_output) +        print(output_str)          print(              "Disable automatic lookup and caching of dSYMs before running the test suite!")          print("Exiting...") @@ -1159,7 +1217,6 @@ def run_suite():          from . import dosep          dosep.main(              configuration.num_threads, -            configuration.multiprocess_test_subdir,              configuration.test_runner_name,              configuration.results_formatter_object)          raise Exception("should never get here") @@ -1254,10 +1311,15 @@ def run_suite():      # Don't do lldb-server (llgs) tests on anything except Linux.      configuration.dont_do_llgs_test = not ("linux" in target_platform) -    # -    # Walk through the testdirs while collecting tests. -    # -    for testdir in configuration.testdirs: +    # Collect tests from the specified testing directories. If a test +    # subdirectory filter is explicitly specified, limit the search to that +    # subdirectory. +    exclusive_test_subdir = configuration.get_absolute_path_to_exclusive_test_subdir() +    if exclusive_test_subdir: +        dirs_to_search = [exclusive_test_subdir] +    else: +        dirs_to_search = configuration.testdirs +    for testdir in dirs_to_search:          for (dirpath, dirnames, filenames) in os.walk(testdir):              visit('Test', dirpath, filenames) diff --git a/packages/Python/lldbsuite/test/dotest_args.py b/packages/Python/lldbsuite/test/dotest_args.py index 58190d8c75ee..225ccf1181cc 100644 --- a/packages/Python/lldbsuite/test/dotest_args.py +++ b/packages/Python/lldbsuite/test/dotest_args.py @@ -85,6 +85,8 @@ def create_parser():      group.add_argument('--dsymutil', metavar='dsymutil', dest='dsymutil', help=textwrap.dedent('Specify which dsymutil to use.')) +    group.add_argument('--filecheck', metavar='filecheck', dest='filecheck', help=textwrap.dedent('Specify which FileCheck binary to use.')) +      # Test filtering options      group = parser.add_argument_group('Test filtering options')      group.add_argument( diff --git a/packages/Python/lldbsuite/test/expression_command/anonymous-struct/TestCallUserAnonTypedef.py b/packages/Python/lldbsuite/test/expression_command/anonymous-struct/TestCallUserAnonTypedef.py index 6a8fb5db5439..1108b1215329 100644 --- a/packages/Python/lldbsuite/test/expression_command/anonymous-struct/TestCallUserAnonTypedef.py +++ b/packages/Python/lldbsuite/test/expression_command/anonymous-struct/TestCallUserAnonTypedef.py @@ -23,7 +23,6 @@ class TestExprLookupAnonStructTypedef(TestBase):          # Find the breakpoint          self.line = line_number('main.cpp', '// lldb testsuite break') -    @expectedFailureAll(oslist=["windows"])      @expectedFailureAll(          oslist=['linux'],          archs=['arm'], diff --git a/packages/Python/lldbsuite/test/expression_command/call-function/TestCallBuiltinFunction.py b/packages/Python/lldbsuite/test/expression_command/call-function/TestCallBuiltinFunction.py new file mode 100644 index 000000000000..87787f3479a2 --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/call-function/TestCallBuiltinFunction.py @@ -0,0 +1,53 @@ +""" +Tests calling builtin functions using expression evaluation. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ExprCommandCallBuiltinFunction(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    # Builtins are expanded by Clang, so debug info shouldn't matter. +    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', +            '// Please test these expressions while stopped at this line:') + +    def test(self): +        self.build() + +        # Set breakpoint in main and run exe +        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 different builtin functions. + +        interp.HandleCommand("expr __builtin_isinf(0.0f)", result) +        self.assertEqual(result.GetOutput(), "(int) $0 = 0\n") + +        interp.HandleCommand("expr __builtin_isnormal(0.0f)", result) +        self.assertEqual(result.GetOutput(), "(int) $1 = 0\n") + +        interp.HandleCommand("expr __builtin_constant_p(1)", result) +        self.assertEqual(result.GetOutput(), "(int) $2 = 1\n") + +        interp.HandleCommand("expr __builtin_abs(-14)", result) +        self.assertEqual(result.GetOutput(), "(int) $3 = 14\n") diff --git a/packages/Python/lldbsuite/test/expression_command/call-function/TestCallStopAndContinue.py b/packages/Python/lldbsuite/test/expression_command/call-function/TestCallStopAndContinue.py index 63511779a927..d832983bdb64 100644 --- a/packages/Python/lldbsuite/test/expression_command/call-function/TestCallStopAndContinue.py +++ b/packages/Python/lldbsuite/test/expression_command/call-function/TestCallStopAndContinue.py @@ -6,7 +6,6 @@ from __future__ import print_function  import lldb -from lldbsuite.test.decorators import *  from lldbsuite.test.lldbtest import *  from lldbsuite.test import lldbutil @@ -24,10 +23,6 @@ class ExprCommandCallStopContinueTestCase(TestBase):              '// Please test these expressions while stopped at this line:')          self.func_line = line_number('main.cpp', '{5, "five"}') -    @expectedFlakeyDarwin("llvm.org/pr20274") -    @expectedFailureAll( -        oslist=["windows"], -        bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows")      def test(self):          """Test gathering result from interrupted function call."""          self.build() diff --git a/packages/Python/lldbsuite/test/expression_command/call-function/TestCallUserDefinedFunction.py b/packages/Python/lldbsuite/test/expression_command/call-function/TestCallUserDefinedFunction.py index ff3bd99ced99..0eb7086b6160 100644 --- a/packages/Python/lldbsuite/test/expression_command/call-function/TestCallUserDefinedFunction.py +++ b/packages/Python/lldbsuite/test/expression_command/call-function/TestCallUserDefinedFunction.py @@ -28,10 +28,6 @@ class ExprCommandCallUserDefinedFunction(TestBase):              'main.cpp',              '// Please test these expressions while stopped at this line:') -    @expectedFlakeyDsym("llvm.org/pr20274") -    @expectedFailureAll( -        oslist=["windows"], -        bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows")      def test(self):          """Test return values of user defined function calls."""          self.build() diff --git a/packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py b/packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py index b328ece6d39c..a9679b7dd368 100644 --- a/packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py +++ b/packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py @@ -41,7 +41,6 @@ class ExprCharTestCase(TestBase):          self.assertTrue(value.GetError().Success())          self.assertEqual(value.GetValueAsSigned(0), 3) -    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")      def test_default_char(self):          self.do_test() @@ -52,7 +51,6 @@ class ExprCharTestCase(TestBase):              "powerpc64le",              "s390x"],          bugnumber="llvm.org/pr23069") -    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")      def test_signed_char(self):          self.do_test(dictionary={'CFLAGS_EXTRAS': '-fsigned-char'}) @@ -64,7 +62,6 @@ class ExprCharTestCase(TestBase):              'armv7',              'armv7k'],          bugnumber="llvm.org/pr23069, <rdar://problem/28721938>") -    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")      @expectedFailureAll(triple='mips*', bugnumber="llvm.org/pr23069")      def test_unsigned_char(self):          self.do_test(dictionary={'CFLAGS_EXTRAS': '-funsigned-char'}) diff --git a/packages/Python/lldbsuite/test/expression_command/completion/.categories b/packages/Python/lldbsuite/test/expression_command/completion/.categories new file mode 100644 index 000000000000..3a3f4df6416b --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/completion/.categories @@ -0,0 +1 @@ +cmdline diff --git a/packages/Python/lldbsuite/test/expression_command/completion/Makefile b/packages/Python/lldbsuite/test/expression_command/completion/Makefile new file mode 100644 index 000000000000..6fc26a9193f0 --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/completion/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp other.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/expression_command/completion/TestExprCompletion.py b/packages/Python/lldbsuite/test/expression_command/completion/TestExprCompletion.py new file mode 100644 index 000000000000..536b9e0abcdd --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/completion/TestExprCompletion.py @@ -0,0 +1,257 @@ +""" +Test the lldb command line completion mechanism for the 'expr' command. +""" + +from __future__ import print_function + +import random +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 CommandLineExprCompletionTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    NO_DEBUG_INFO_TESTCASE = True + +    def test_expr_completion(self): +        self.build() +        self.main_source = "main.cpp" +        self.main_source_spec = lldb.SBFileSpec(self.main_source) +        self.dbg.CreateTarget(self.getBuildArtifact("a.out")) + +        # Try the completion before we have a context to complete on. +        self.assume_no_completions('expr some_expr') +        self.assume_no_completions('expr ') +        self.assume_no_completions('expr f') + + +        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, +                                          '// Break here', self.main_source_spec) + +        # Completing member functions +        self.complete_exactly('expr some_expr.FooNoArgs', +                              'expr some_expr.FooNoArgsBar()') +        self.complete_exactly('expr some_expr.FooWithArgs', +                              'expr some_expr.FooWithArgsBar(') +        self.complete_exactly('expr some_expr.FooWithMultipleArgs', +                              'expr some_expr.FooWithMultipleArgsBar(') +        self.complete_exactly('expr some_expr.FooUnderscore', +                              'expr some_expr.FooUnderscoreBar_()') +        self.complete_exactly('expr some_expr.FooNumbers', +                              'expr some_expr.FooNumbersBar1()') +        self.complete_exactly('expr some_expr.StaticMemberMethod', +                              'expr some_expr.StaticMemberMethodBar()') + +        # Completing static functions +        self.complete_exactly('expr Expr::StaticMemberMethod', +                              'expr Expr::StaticMemberMethodBar()') + +        # Completing member variables +        self.complete_exactly('expr some_expr.MemberVariab', +                              'expr some_expr.MemberVariableBar') + +        # Multiple completions +        self.completions_contain('expr some_expr.', +                                 ['some_expr.FooNumbersBar1()', +                                  'some_expr.FooUnderscoreBar_()', +                                  'some_expr.FooWithArgsBar(', +                                  'some_expr.MemberVariableBar']) + +        self.completions_contain('expr some_expr.Foo', +                                 ['some_expr.FooNumbersBar1()', +                                  'some_expr.FooUnderscoreBar_()', +                                  'some_expr.FooWithArgsBar(']) + +        self.completions_contain('expr ', +                                 ['static_cast', +                                  'reinterpret_cast', +                                  'dynamic_cast']) + +        self.completions_contain('expr 1 + ', +                                 ['static_cast', +                                  'reinterpret_cast', +                                  'dynamic_cast']) + +        # Completion expr without spaces +        # This is a bit awkward looking for the user, but that's how +        # the completion API works at the moment. +        self.completions_contain('expr 1+', +                                 ['1+some_expr', "1+static_cast"]) + +        # Test with spaces +        self.complete_exactly('expr   some_expr .FooNoArgs', +                              'expr   some_expr .FooNoArgsBar()') +        self.complete_exactly('expr  some_expr .FooNoArgs', +                              'expr  some_expr .FooNoArgsBar()') +        self.complete_exactly('expr some_expr .FooNoArgs', +                              'expr some_expr .FooNoArgsBar()') +        self.complete_exactly('expr some_expr. FooNoArgs', +                              'expr some_expr. FooNoArgsBar()') +        self.complete_exactly('expr some_expr . FooNoArgs', +                              'expr some_expr . FooNoArgsBar()') +        self.complete_exactly('expr Expr :: StaticMemberMethod', +                              'expr Expr :: StaticMemberMethodBar()') +        self.complete_exactly('expr Expr ::StaticMemberMethod', +                              'expr Expr ::StaticMemberMethodBar()') +        self.complete_exactly('expr Expr:: StaticMemberMethod', +                              'expr Expr:: StaticMemberMethodBar()') + +        # Test that string literals don't break our parsing logic. +        self.complete_exactly('expr const char *cstr = "some_e"; char c = *cst', +                              'expr const char *cstr = "some_e"; char c = *cstr') +        self.complete_exactly('expr const char *cstr = "some_e" ; char c = *cst', +                              'expr const char *cstr = "some_e" ; char c = *cstr') +        # Requesting completions inside an incomplete string doesn't provide any +        # completions. +        self.complete_exactly('expr const char *cstr = "some_e', +                              'expr const char *cstr = "some_e') + +        # Completing inside double dash should do nothing +        self.assume_no_completions('expr -i0 -- some_expr.', 10) +        self.assume_no_completions('expr -i0 -- some_expr.', 11) + +        # Test with expr arguments +        self.complete_exactly('expr -i0 -- some_expr .FooNoArgs', +                              'expr -i0 -- some_expr .FooNoArgsBar()') +        self.complete_exactly('expr  -i0 -- some_expr .FooNoArgs', +                              'expr  -i0 -- some_expr .FooNoArgsBar()') + +        # Addrof and deref +        self.complete_exactly('expr (*(&some_expr)).FooNoArgs', +                              'expr (*(&some_expr)).FooNoArgsBar()') +        self.complete_exactly('expr (*(&some_expr)) .FooNoArgs', +                              'expr (*(&some_expr)) .FooNoArgsBar()') +        self.complete_exactly('expr (* (&some_expr)) .FooNoArgs', +                              'expr (* (&some_expr)) .FooNoArgsBar()') +        self.complete_exactly('expr (* (& some_expr)) .FooNoArgs', +                              'expr (* (& some_expr)) .FooNoArgsBar()') + +        # Addrof and deref (part 2) +        self.complete_exactly('expr (&some_expr)->FooNoArgs', +                              'expr (&some_expr)->FooNoArgsBar()') +        self.complete_exactly('expr (&some_expr) ->FooNoArgs', +                              'expr (&some_expr) ->FooNoArgsBar()') +        self.complete_exactly('expr (&some_expr) -> FooNoArgs', +                              'expr (&some_expr) -> FooNoArgsBar()') +        self.complete_exactly('expr (&some_expr)-> FooNoArgs', +                              'expr (&some_expr)-> FooNoArgsBar()') + +        # Builtin arg +        self.complete_exactly('expr static_ca', +                              'expr static_cast') + +        # From other files +        self.complete_exactly('expr fwd_decl_ptr->Hidden', +                              'expr fwd_decl_ptr->HiddenMember') + + +        # Types +        self.complete_exactly('expr LongClassNa', +                              'expr LongClassName') +        self.complete_exactly('expr LongNamespaceName::NestedCla', +                              'expr LongNamespaceName::NestedClass') + +        # Namespaces +        self.complete_exactly('expr LongNamespaceNa', +                              'expr LongNamespaceName::') + +        # Multiple arguments +        self.complete_exactly('expr &some_expr + &some_e', +                              'expr &some_expr + &some_expr') +        self.complete_exactly('expr SomeLongVarNameWithCapitals + SomeLongVarName', +                              'expr SomeLongVarNameWithCapitals + SomeLongVarNameWithCapitals') +        self.complete_exactly('expr SomeIntVar + SomeIntV', +                              'expr SomeIntVar + SomeIntVar') + +        # Multiple statements +        self.complete_exactly('expr long LocalVariable = 0; LocalVaria', +                              'expr long LocalVariable = 0; LocalVariable') + +        # Custom Decls +        self.complete_exactly('expr auto l = [](int LeftHandSide, int bx){ return LeftHandS', +                              'expr auto l = [](int LeftHandSide, int bx){ return LeftHandSide') +        self.complete_exactly('expr struct LocalStruct { long MemberName; } ; LocalStruct S; S.Mem', +                              'expr struct LocalStruct { long MemberName; } ; LocalStruct S; S.MemberName') + +        # Completing function call arguments +        self.complete_exactly('expr some_expr.FooWithArgsBar(some_exp', +                              'expr some_expr.FooWithArgsBar(some_expr') +        self.complete_exactly('expr some_expr.FooWithArgsBar(SomeIntV', +                              'expr some_expr.FooWithArgsBar(SomeIntVar') +        self.complete_exactly('expr some_expr.FooWithMultipleArgsBar(SomeIntVar, SomeIntVa', +                              'expr some_expr.FooWithMultipleArgsBar(SomeIntVar, SomeIntVar') + +        # Function return values +        self.complete_exactly('expr some_expr.Self().FooNoArgs', +                              'expr some_expr.Self().FooNoArgsBar()') +        self.complete_exactly('expr some_expr.Self() .FooNoArgs', +                              'expr some_expr.Self() .FooNoArgsBar()') +        self.complete_exactly('expr some_expr.Self(). FooNoArgs', +                              'expr some_expr.Self(). FooNoArgsBar()') + +    def test_expr_completion_with_descriptions(self): +        self.build() +        self.main_source = "main.cpp" +        self.main_source_spec = lldb.SBFileSpec(self.main_source) +        self.dbg.CreateTarget(self.getBuildArtifact("a.out")) + +        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, +                                          '// Break here', self.main_source_spec) + +        self.check_completion_with_desc("expr ", [ +            # VarDecls have their type as description. +            ["some_expr", "Expr &"], +            # builtin types have no description. +            ["int", ""], +            ["float", ""] +        ]) +        self.check_completion_with_desc("expr some_expr.", [ +            # Functions have their signature as description. +            ["some_expr.Self()", "Expr &Self()"], +            ["some_expr.operator=(", "inline Expr &operator=(const Expr &)"], +            ["some_expr.FooNumbersBar1()", "int FooNumbersBar1()"], +            ["some_expr.StaticMemberMethodBar()", "static int StaticMemberMethodBar()"], +            ["some_expr.FooWithArgsBar(", "int FooWithArgsBar(int)"], +            ["some_expr.FooNoArgsBar()", "int FooNoArgsBar()"], +            ["some_expr.FooUnderscoreBar_()", "int FooUnderscoreBar_()"], +            ["some_expr.FooWithMultipleArgsBar(", "int FooWithMultipleArgsBar(int, int)"], +            ["some_expr.~Expr()", "inline ~Expr()"], +            # FieldDecls have their type as description. +            ["some_expr.MemberVariableBar", "int"], +        ]) + +    def assume_no_completions(self, str_input, cursor_pos = None): +        interp = self.dbg.GetCommandInterpreter() +        match_strings = lldb.SBStringList() +        if cursor_pos is None: +          cursor_pos = len(str_input) +        num_matches = interp.HandleCompletion(str_input, cursor_pos, 0, -1, match_strings) + +        available_completions = [] +        for m in match_strings: +            available_completions.append(m) + +        self.assertEquals(num_matches, 0, "Got matches, but didn't expect any: " + str(available_completions)) + +    def completions_contain(self, str_input, items): +        interp = self.dbg.GetCommandInterpreter() +        match_strings = lldb.SBStringList() +        num_matches = interp.HandleCompletion(str_input, len(str_input), 0, -1, match_strings) +        common_match = match_strings.GetStringAtIndex(0) + +        for item in items: +            found = False +            for m in match_strings: +                if m == item: +                    found = True +            if not found: +                # Transform match_strings to a python list with strings +                available_completions = [] +                for m in match_strings: +                     available_completions.append(m) +                self.assertTrue(found, "Couldn't find completion " + item + " in completions " + str(available_completions)) diff --git a/packages/Python/lldbsuite/test/expression_command/completion/main.cpp b/packages/Python/lldbsuite/test/expression_command/completion/main.cpp new file mode 100644 index 000000000000..908bebbebff5 --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/completion/main.cpp @@ -0,0 +1,35 @@ +namespace LongNamespaceName { class NestedClass { long m; }; } + +// Defined in other.cpp, we only have a forward declaration here. +struct ForwardDecl; +extern ForwardDecl fwd_decl; + +class LongClassName { long i ; }; + +class Expr { +public: +    int FooNoArgsBar() { return 1; } +    int FooWithArgsBar(int i) { return i; } +    int FooWithMultipleArgsBar(int i, int j) { return i + j; } +    int FooUnderscoreBar_() { return 4; } +    int FooNumbersBar1() { return 8; } +    int MemberVariableBar = 0; +    Expr &Self() { return *this; } +    static int StaticMemberMethodBar() { return 82; } +}; + +int main() +{ +    LongClassName a; +    LongNamespaceName::NestedClass NestedFoo; +    long SomeLongVarNameWithCapitals = 44; +    int SomeIntVar = 33; +    Expr some_expr; +    some_expr.FooNoArgsBar(); +    some_expr.FooWithArgsBar(1); +    some_expr.FooUnderscoreBar_(); +    some_expr.FooNumbersBar1(); +    Expr::StaticMemberMethodBar(); +    ForwardDecl *fwd_decl_ptr = &fwd_decl; +    return 0; // Break here +} diff --git a/packages/Python/lldbsuite/test/expression_command/completion/other.cpp b/packages/Python/lldbsuite/test/expression_command/completion/other.cpp new file mode 100644 index 000000000000..1f8a488639b9 --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/completion/other.cpp @@ -0,0 +1,4 @@ +struct ForwardDecl { +   long HiddenMemberName; +}; +ForwardDecl fwd_decl; diff --git a/packages/Python/lldbsuite/test/expression_command/dont_allow_jit/Makefile b/packages/Python/lldbsuite/test/expression_command/dont_allow_jit/Makefile new file mode 100644 index 000000000000..50d4ab65a6ec --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/dont_allow_jit/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../make + +C_SOURCES := main.c +CFLAGS_EXTRAS += -std=c99 + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/expression_command/dont_allow_jit/TestAllowJIT.py b/packages/Python/lldbsuite/test/expression_command/dont_allow_jit/TestAllowJIT.py new file mode 100644 index 000000000000..05c67902a3ab --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/dont_allow_jit/TestAllowJIT.py @@ -0,0 +1,90 @@ +""" +Test that --allow-jit=false does disallow JITting: +""" + +from __future__ import print_function + + +import os +import time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * + +class TestAllowJIT(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_allow_jit_expr_command(self): +        """Test the --allow-jit command line flag""" +        self.build() +        self.main_source_file = lldb.SBFileSpec("main.c") +        self.expr_cmd_test() + +    def test_allow_jit_options(self): +        """Test the SetAllowJIT SBExpressionOption setting""" +        self.build() +        self.main_source_file = lldb.SBFileSpec("main.c") +        self.expr_options_test() + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) + +    def expr_cmd_test(self): +        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, +                                   "Set a breakpoint here", self.main_source_file) + +        frame = thread.GetFrameAtIndex(0) +         +        # First make sure we can call the function with  +        interp = self.dbg.GetCommandInterpreter() +        self.expect("expr --allow-jit 1 -- call_me(10)", +                    substrs = ["(int) $", "= 18"]) +        # Now make sure it fails with the "can't IR interpret message" if allow-jit is false: +        self.expect("expr --allow-jit 0 -- call_me(10)", +                    error=True, +                    substrs = ["Can't run the expression locally"]) +         +    def expr_options_test(self): +        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, +                                   "Set a breakpoint here", self.main_source_file) + +        frame = thread.GetFrameAtIndex(0) + +        # First make sure we can call the function with the default option set.  +        options = lldb.SBExpressionOptions() +        # Check that the default is to allow JIT: +        self.assertEqual(options.GetAllowJIT(), True, "Default is true") + +        # Now use the options: +        result = frame.EvaluateExpression("call_me(10)", options) +        self.assertTrue(result.GetError().Success(), "expression succeeded") +        self.assertEqual(result.GetValueAsSigned(), 18, "got the right value.") + +        # Now disallow JIT and make sure it fails: +        options.SetAllowJIT(False) +        # Check that we got the right value: +        self.assertEqual(options.GetAllowJIT(), False, "Got False after setting to False") + +        # Again use it and ensure we fail: +        result = frame.EvaluateExpression("call_me(10)", options) +        self.assertTrue(result.GetError().Fail(), "expression failed with no JIT") +        self.assertTrue("Can't run the expression locally" in result.GetError().GetCString(), "Got right error") + +        # Finally set the allow JIT value back to true and make sure that works: +        options.SetAllowJIT(True) +        self.assertEqual(options.GetAllowJIT(), True, "Set back to True correctly") + +        # And again, make sure this works: +        result = frame.EvaluateExpression("call_me(10)", options) +        self.assertTrue(result.GetError().Success(), "expression succeeded") +        self.assertEqual(result.GetValueAsSigned(), 18, "got the right value.") + diff --git a/packages/Python/lldbsuite/test/expression_command/dont_allow_jit/main.c b/packages/Python/lldbsuite/test/expression_command/dont_allow_jit/main.c new file mode 100644 index 000000000000..ebd8ae11a73a --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/dont_allow_jit/main.c @@ -0,0 +1,15 @@ +#include <stdio.h> + +int +call_me(int input) +{ +  return printf("I was called: %d.\n", input); +} + +int +main() +{ +  int test_var = 10; +  printf ("Set a breakpoint here: %d.\n", test_var); +  return call_me(100); +} diff --git a/packages/Python/lldbsuite/test/expression_command/formatters/TestFormatters.py b/packages/Python/lldbsuite/test/expression_command/formatters/TestFormatters.py index f14b02bbd7c4..ee5c4a0ee1df 100644 --- a/packages/Python/lldbsuite/test/expression_command/formatters/TestFormatters.py +++ b/packages/Python/lldbsuite/test/expression_command/formatters/TestFormatters.py @@ -57,14 +57,21 @@ class ExprFormattersTestCase(TestBase):              self.runCmd("frame variable foo1.b --show-types")              self.runCmd("frame variable foo1.b.b_ref --show-types") -        self.expect( -            "expression --show-types -- *(new foo(47))", -            substrs=[ -                '(int) a = 47', -                '(bar) b = {', -                '(int) i = 94', -                '(baz) b = {', -                '(int) k = 99']) +        self.filecheck("expression --show-types -- *(new foo(47))", __file__, +                '-check-prefix=EXPR-TYPES-NEW-FOO') +        # EXPR-TYPES-NEW-FOO: (foo) ${{.*}} = { +        # EXPR-TYPES-NEW-FOO-NEXT:   (int) a = 47 +        # EXPR-TYPES-NEW-FOO-NEXT:   (int *) a_ptr = 0x +        # EXPR-TYPES-NEW-FOO-NEXT:   (bar) b = { +        # EXPR-TYPES-NEW-FOO-NEXT:     (int) i = 94 +        # EXPR-TYPES-NEW-FOO-NEXT:     (int *) i_ptr = 0x +        # EXPR-TYPES-NEW-FOO-NEXT:     (baz) b = { +        # EXPR-TYPES-NEW-FOO-NEXT:       (int) h = 97 +        # EXPR-TYPES-NEW-FOO-NEXT:       (int) k = 99 +        # EXPR-TYPES-NEW-FOO-NEXT:     } +        # EXPR-TYPES-NEW-FOO-NEXT:     (baz &) b_ref = 0x +        # EXPR-TYPES-NEW-FOO-NEXT:   } +        # EXPR-TYPES-NEW-FOO-NEXT: }          self.runCmd("type summary add -F formatters.foo_SummaryProvider foo") @@ -80,68 +87,49 @@ class ExprFormattersTestCase(TestBase):          self.expect("expression foo1.a_ptr",                      substrs=['(int *) $', '= 0x', ' -> 13']) -        self.expect( -            "expression foo1", -            substrs=[ -                '(foo) $', -                ' a = 12', -                'a_ptr = ', -                ' -> 13', -                'i = 24', -                'i_ptr = ', -                ' -> 25']) - -        self.expect( -            "expression --ptr-depth=1 -- new foo(47)", -            substrs=[ -                '(foo *) $', -                'a = 47', -                'a_ptr = ', -                ' -> 48', -                'i = 94', -                'i_ptr = ', -                ' -> 95']) - -        self.expect( -            "expression foo2", -            substrs=[ -                '(foo) $', -                'a = 121', -                'a_ptr = ', -                ' -> 122', -                'i = 242', -                'i_ptr = ', -                ' -> 243']) +        self.filecheck("expression foo1", __file__, '-check-prefix=EXPR-FOO1') +        # EXPR-FOO1: (foo) $ +        # EXPR-FOO1-SAME: a = 12 +        # EXPR-FOO1-SAME: a_ptr = {{[0-9]+}} -> 13 +        # EXPR-FOO1-SAME: i = 24 +        # EXPR-FOO1-SAME: i_ptr = {{[0-9]+}} -> 25 +        # EXPR-FOO1-SAME: b_ref = {{[0-9]+}} +        # EXPR-FOO1-SAME: h = 27 +        # EXPR-FOO1-SAME: k = 29 + +        self.filecheck("expression --ptr-depth=1 -- new foo(47)", __file__, +                '-check-prefix=EXPR-PTR-DEPTH1') +        # EXPR-PTR-DEPTH1: (foo *) $ +        # EXPR-PTR-DEPTH1-SAME: a = 47 +        # EXPR-PTR-DEPTH1-SAME: a_ptr = {{[0-9]+}} -> 48 +        # EXPR-PTR-DEPTH1-SAME: i = 94 +        # EXPR-PTR-DEPTH1-SAME: i_ptr = {{[0-9]+}} -> 95 + +        self.filecheck("expression foo2", __file__, '-check-prefix=EXPR-FOO2') +        # EXPR-FOO2: (foo) $ +        # EXPR-FOO2-SAME: a = 121 +        # EXPR-FOO2-SAME: a_ptr = {{[0-9]+}} -> 122 +        # EXPR-FOO2-SAME: i = 242 +        # EXPR-FOO2-SAME: i_ptr = {{[0-9]+}} -> 243 +        # EXPR-FOO2-SAME: h = 245 +        # EXPR-FOO2-SAME: k = 247          object_name = self.res.GetOutput()          object_name = object_name[7:]          object_name = object_name[0:object_name.find(' =')] -        self.expect( -            "frame variable foo2", -            substrs=[ -                '(foo)', -                'foo2', -                'a = 121', -                'a_ptr = ', -                ' -> 122', -                'i = 242', -                'i_ptr = ', -                ' -> 243']) - -        self.expect( -            "expression $" + -            object_name, -            substrs=[ -                '(foo) $', -                'a = 121', -                'a_ptr = ', -                ' -> 122', -                'i = 242', -                'i_ptr = ', -                ' -> 243', -                'h = 245', -                'k = 247']) +        self.filecheck("frame variable foo2", __file__, '-check-prefix=VAR-FOO2') +        # VAR-FOO2: (foo) foo2 +        # VAR-FOO2-SAME: a = 121 +        # VAR-FOO2-SAME: a_ptr = {{[0-9]+}} -> 122 +        # VAR-FOO2-SAME: i = 242 +        # VAR-FOO2-SAME: i_ptr = {{[0-9]+}} -> 243 +        # VAR-FOO2-SAME: h = 245 +        # VAR-FOO2-SAME: k = 247 + +        # The object is the same as foo2, so use the EXPR-FOO2 checks. +        self.filecheck("expression $" + object_name, __file__, +                '-check-prefix=EXPR-FOO2')          self.runCmd("type summary delete foo")          self.runCmd( diff --git a/packages/Python/lldbsuite/test/expression_command/formatters/main.cpp b/packages/Python/lldbsuite/test/expression_command/formatters/main.cpp index 4c3b180f3709..1b8ce48041f9 100644 --- a/packages/Python/lldbsuite/test/expression_command/formatters/main.cpp +++ b/packages/Python/lldbsuite/test/expression_command/formatters/main.cpp @@ -45,4 +45,4 @@ int main(int argc, char** argv)  	return 0; -}
\ No newline at end of file +} diff --git a/packages/Python/lldbsuite/test/expression_command/multiline/TestMultilineExpressions.py b/packages/Python/lldbsuite/test/expression_command/multiline/TestMultilineExpressions.py deleted file mode 100644 index 7f639a462201..000000000000 --- a/packages/Python/lldbsuite/test/expression_command/multiline/TestMultilineExpressions.py +++ /dev/null @@ -1,90 +0,0 @@ -"""Test multiline expressions.""" - -from __future__ import print_function - -import os -import lldb -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil - - -class MultilineExpressionsTestCase(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 on inside main.cpp. -        self.line = line_number('main.c', 'break') - -    @skipIfRemote -    @expectedFailureAll( -        oslist=["windows"], -        bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") -    def test_with_run_commands(self): -        """Test that multiline expressions work correctly""" -        self.build() -        import pexpect -        exe = self.getBuildArtifact("a.out") -        prompt = "(lldb) " - -        # So that the child gets torn down after the test. -        self.child = pexpect.spawn( -            '%s %s %s' % -            (lldbtest_config.lldbExec, self.lldbOption, exe)) -        child = self.child -        # Turn on logging for what the child sends back. -        if self.TraceOn(): -            child.logfile_read = sys.stdout - -        # Set the breakpoint, run the inferior, when it breaks, issue print on -        # the various convenience variables. -        child.expect_exact(prompt) -        child.sendline('breakpoint set -f main.c -l %d' % self.line) -        child.expect_exact(prompt) -        child.sendline('run') -        child.expect_exact("stop reason = breakpoint 1.1") -        child.expect_exact(prompt) -        child.sendline('expr') -        child.expect_exact('1:') - -        child.sendline('2+') -        child.expect_exact('2:') - -        child.sendline('3') -        child.expect_exact('3:') - -        child.sendline('') -        child.expect_exact(prompt) -        self.expect(child.before, exe=False, -                    patterns=['= 5']) - -    @skipIfRemote -    @expectedFailureAll( -        oslist=["windows"], -        bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") -    def test_empty_list(self): -        """Test printing an empty list of expressions""" -        import pexpect -        prompt = "(lldb) " - -        # So that the child gets torn down after the test -        self.child = pexpect.spawn( -                "%s %s" % -                (lldbtest_config.lldbExec, self.lldbOption)) -        child = self.child - -        # Turn on logging for what the child sends back. -        if self.TraceOn(): -            child.logfile_read = sys.stdout - -        # We expect a prompt, then send "print" to start a list of expressions, -        # then an empty line. We expect a prompt back. -        child.expect_exact(prompt) -        child.sendline("print") -        child.expect_exact('1:') -        child.sendline("") -        child.expect_exact(prompt) diff --git a/packages/Python/lldbsuite/test/expression_command/multiline/main.c b/packages/Python/lldbsuite/test/expression_command/multiline/main.c deleted file mode 100644 index da16b1e7846f..000000000000 --- a/packages/Python/lldbsuite/test/expression_command/multiline/main.c +++ /dev/null @@ -1,6 +0,0 @@ -#include <stdio.h> - -int main(int argc, char const *argv[]) { -    printf("Hello world.\n"); // break here -    return 0; -} diff --git a/packages/Python/lldbsuite/test/expression_command/options/TestExprOptions.py b/packages/Python/lldbsuite/test/expression_command/options/TestExprOptions.py index 1dbafc36a82a..13bc3b7ce2ac 100644 --- a/packages/Python/lldbsuite/test/expression_command/options/TestExprOptions.py +++ b/packages/Python/lldbsuite/test/expression_command/options/TestExprOptions.py @@ -14,6 +14,7 @@ import os  import time  import lldb  import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import *  from lldbsuite.test.lldbtest import * @@ -63,3 +64,30 @@ class ExprOptionsTestCase(TestBase):          val = frame.EvaluateExpression('foo != nullptr', options)          self.assertTrue(val.IsValid())          self.assertFalse(val.GetError().Success()) + +    @skipIfDarwin +    def test_expr_options_lang(self): +        """These expression language options should work as expected.""" +        self.build() + +        # Set debugger into synchronous mode +        self.dbg.SetAsync(False) + +        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( +            self, '// breakpoint_in_main', self.main_source_spec) + +        frame = thread.GetFrameAtIndex(0) +        options = lldb.SBExpressionOptions() + +        # Make sure we can retrieve `id` variable if language is set to C++11: +        options.SetLanguage(lldb.eLanguageTypeC_plus_plus_11) +        val = frame.EvaluateExpression('id == 0', options) +        self.assertTrue(val.IsValid()) +        self.assertTrue(val.GetError().Success()) +        self.DebugSBValue(val) + +        # Make sure we can't retrieve `id` variable if language is set to ObjC: +        options.SetLanguage(lldb.eLanguageTypeObjC) +        val = frame.EvaluateExpression('id == 0', options) +        self.assertTrue(val.IsValid()) +        self.assertFalse(val.GetError().Success()) diff --git a/packages/Python/lldbsuite/test/expression_command/options/main.cpp b/packages/Python/lldbsuite/test/expression_command/options/main.cpp index ecd9a90f6626..0d30c79bd229 100644 --- a/packages/Python/lldbsuite/test/expression_command/options/main.cpp +++ b/packages/Python/lldbsuite/test/expression_command/options/main.cpp @@ -1,11 +1,13 @@  extern "C" int foo(void);  static int static_value = 0; +static int id = 1234;  int  bar()  {      static_value++; -    return static_value; +    id++; +    return static_value + id;  }  int main (int argc, char const *argv[]) diff --git a/packages/Python/lldbsuite/test/expression_command/persistent_types/TestNestedPersistentTypes.py b/packages/Python/lldbsuite/test/expression_command/persistent_types/TestNestedPersistentTypes.py index f4ee1b0fb625..8630d6f41b34 100644 --- a/packages/Python/lldbsuite/test/expression_command/persistent_types/TestNestedPersistentTypes.py +++ b/packages/Python/lldbsuite/test/expression_command/persistent_types/TestNestedPersistentTypes.py @@ -17,7 +17,6 @@ class NestedPersistentTypesTestCase(TestBase):      mydir = TestBase.compute_mydir(__file__) -    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")      def test_persistent_types(self):          """Test that nested persistent types work."""          self.build() diff --git a/packages/Python/lldbsuite/test/expression_command/persistent_types/TestPersistentTypes.py b/packages/Python/lldbsuite/test/expression_command/persistent_types/TestPersistentTypes.py index f56cb11a80d8..403d24246a9d 100644 --- a/packages/Python/lldbsuite/test/expression_command/persistent_types/TestPersistentTypes.py +++ b/packages/Python/lldbsuite/test/expression_command/persistent_types/TestPersistentTypes.py @@ -17,7 +17,6 @@ class PersistenttypesTestCase(TestBase):      mydir = TestBase.compute_mydir(__file__) -    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")      def test_persistent_types(self):          """Test that lldb persistent types works correctly."""          self.build() diff --git a/packages/Python/lldbsuite/test/expression_command/pr35310/TestExprsBug35310.py b/packages/Python/lldbsuite/test/expression_command/pr35310/TestExprsBug35310.py index dd3d06fd672f..6d019c7415fc 100644 --- a/packages/Python/lldbsuite/test/expression_command/pr35310/TestExprsBug35310.py +++ b/packages/Python/lldbsuite/test/expression_command/pr35310/TestExprsBug35310.py @@ -16,7 +16,6 @@ class ExprBug35310(TestBase):          self.main_source = "main.cpp"          self.main_source_spec = lldb.SBFileSpec(self.main_source) -    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")      def test_issue35310(self):          """Test invoking functions with non-standard linkage names. diff --git a/packages/Python/lldbsuite/test/expression_command/radar_43822994/Makefile b/packages/Python/lldbsuite/test/expression_command/radar_43822994/Makefile new file mode 100644 index 000000000000..83b24da17b4d --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/radar_43822994/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp +CXXFLAGS += -std=c++11 + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/expression_command/radar_43822994/TestScopedEnumType.py b/packages/Python/lldbsuite/test/expression_command/radar_43822994/TestScopedEnumType.py new file mode 100644 index 000000000000..028047fc46bf --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/radar_43822994/TestScopedEnumType.py @@ -0,0 +1,44 @@ +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ScopedEnumType(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def test(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, +                                          '// Set break point at this line.', self.main_source_spec) +        frame = thread.GetFrameAtIndex(0) + +        self.expect("expr f == Foo::FooBar", +                substrs=['(bool) $0 = true']) + +        value = frame.EvaluateExpression("f == Foo::FooBar") +        self.assertTrue(value.IsValid()) +        self.assertTrue(value.GetError().Success()) +        self.assertEqual(value.GetValueAsUnsigned(), 1) + +        value = frame.EvaluateExpression("b == BarBar") +        self.assertTrue(value.IsValid()) +        self.assertTrue(value.GetError().Success()) +        self.assertEqual(value.GetValueAsUnsigned(), 1) + +        ## b is not a Foo +        value = frame.EvaluateExpression("b == Foo::FooBar") +        self.assertTrue(value.IsValid()) +        self.assertFalse(value.GetError().Success()) + +        ## integral is not implicitly convertible to a scoped enum +        value = frame.EvaluateExpression("1 == Foo::FooBar") +        self.assertTrue(value.IsValid()) +        self.assertFalse(value.GetError().Success()) diff --git a/packages/Python/lldbsuite/test/expression_command/radar_43822994/main.cpp b/packages/Python/lldbsuite/test/expression_command/radar_43822994/main.cpp new file mode 100644 index 000000000000..b0d67d23dc5e --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/radar_43822994/main.cpp @@ -0,0 +1,16 @@ +enum class Foo { +  FooBar = 42 +}; + +enum Bar { +    BarBar = 3, +    BarBarBar = 42 +}; + +int main(int argc, const char **argv) { +  Foo f = Foo::FooBar; +  Bar b = BarBar; +  bool b1 = f == Foo::FooBar; +  bool b2 = b == BarBar; +  return 0; // Set break point at this line. +} diff --git a/packages/Python/lldbsuite/test/expression_command/radar_9531204/TestPrintfAfterUp.py b/packages/Python/lldbsuite/test/expression_command/radar_9531204/TestPrintfAfterUp.py index c44cb6fc39da..dc8ee77fd6fb 100644 --- a/packages/Python/lldbsuite/test/expression_command/radar_9531204/TestPrintfAfterUp.py +++ b/packages/Python/lldbsuite/test/expression_command/radar_9531204/TestPrintfAfterUp.py @@ -18,7 +18,6 @@ class Radar9531204TestCase(TestBase):      mydir = TestBase.compute_mydir(__file__)      # rdar://problem/9531204 -    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")      def test_expr_commands(self):          """The evaluating printf(...) after break stop and then up a stack frame."""          self.build() diff --git a/packages/Python/lldbsuite/test/expression_command/radar_9673664/TestExprHelpExamples.py b/packages/Python/lldbsuite/test/expression_command/radar_9673664/TestExprHelpExamples.py index dfef8735071b..d18720ccf3f1 100644 --- a/packages/Python/lldbsuite/test/expression_command/radar_9673664/TestExprHelpExamples.py +++ b/packages/Python/lldbsuite/test/expression_command/radar_9673664/TestExprHelpExamples.py @@ -24,7 +24,6 @@ class Radar9673644TestCase(TestBase):          self.main_source = "main.c"          self.line = line_number(self.main_source, '// Set breakpoint here.') -    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")      def test_expr_commands(self):          """The following expression commands should just work."""          self.build() diff --git a/packages/Python/lldbsuite/test/expression_command/rdar44436068/Makefile b/packages/Python/lldbsuite/test/expression_command/rdar44436068/Makefile new file mode 100644 index 000000000000..f5a47fcc46cc --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/rdar44436068/Makefile @@ -0,0 +1,3 @@ +LEVEL = ../../make +C_SOURCES := main.c +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/expression_command/rdar44436068/Test128BitsInteger.py b/packages/Python/lldbsuite/test/expression_command/rdar44436068/Test128BitsInteger.py new file mode 100644 index 000000000000..c8308c16011e --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/rdar44436068/Test128BitsInteger.py @@ -0,0 +1,4 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals()) diff --git a/packages/Python/lldbsuite/test/expression_command/rdar44436068/main.c b/packages/Python/lldbsuite/test/expression_command/rdar44436068/main.c new file mode 100644 index 000000000000..156dbf04a1b7 --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/rdar44436068/main.c @@ -0,0 +1,8 @@ +int main(void) +{ +    __int128_t n = 1; +    n = n + n; +    return n; //%self.expect("p n", substrs=['(__int128_t) $0 = 2']) +              //%self.expect("p n + 6", substrs=['(__int128) $1 = 8']) +              //%self.expect("p n + n", substrs=['(__int128) $2 = 4']) +} diff --git a/packages/Python/lldbsuite/test/expression_command/test/TestExprs.py b/packages/Python/lldbsuite/test/expression_command/test/TestExprs.py index 3af7d808e128..deae7feb3ac1 100644 --- a/packages/Python/lldbsuite/test/expression_command/test/TestExprs.py +++ b/packages/Python/lldbsuite/test/expression_command/test/TestExprs.py @@ -102,7 +102,6 @@ class BasicExprCommandsTestCase(TestBase):          # (const char *) $8 = 0x... "/Volumes/data/lldb/svn/trunk/test/expression_command/test/a.out"      @add_test_categories(['pyapi']) -    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")      def test_evaluate_expression_python(self):          """Test SBFrame.EvaluateExpression() API for evaluating an expression."""          self.build() @@ -203,7 +202,6 @@ class BasicExprCommandsTestCase(TestBase):      # rdar://problem/8686536      # CommandInterpreter::HandleCommand is stripping \'s from input for      # WantsRawCommand commands -    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")      def test_expr_commands_can_handle_quotes(self):          """Throw some expression commands with quotes at lldb."""          self.build() diff --git a/packages/Python/lldbsuite/test/expression_command/test/TestExprs2.py b/packages/Python/lldbsuite/test/expression_command/test/TestExprs2.py index f5ec4f027866..88412e6b7c82 100644 --- a/packages/Python/lldbsuite/test/expression_command/test/TestExprs2.py +++ b/packages/Python/lldbsuite/test/expression_command/test/TestExprs2.py @@ -24,9 +24,6 @@ class ExprCommands2TestCase(TestBase):              'main.cpp',              '// Please test many expressions while stopped at this line:') -    @expectedFailureAll( -        oslist=["windows"], -        bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows")      def test_more_expr_commands(self):          """Test some more expression commands."""          self.build() @@ -60,9 +57,7 @@ class ExprCommands2TestCase(TestBase):          # (int) $5 = 6      @skipIfLinux -    @expectedFailureAll( -            oslist=["windows"], -            bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows") +    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24489")      def test_expr_symbols(self):          """Test symbols."""          self.build() diff --git a/packages/Python/lldbsuite/test/expression_command/unwind_expression/TestUnwindExpression.py b/packages/Python/lldbsuite/test/expression_command/unwind_expression/TestUnwindExpression.py index c942427a8e66..108de8867d50 100644 --- a/packages/Python/lldbsuite/test/expression_command/unwind_expression/TestUnwindExpression.py +++ b/packages/Python/lldbsuite/test/expression_command/unwind_expression/TestUnwindExpression.py @@ -55,7 +55,6 @@ class UnwindFromExpressionTest(TestBase):      @add_test_categories(['pyapi']) -    @expectedFailureAll(oslist=["windows"])      def test_unwind_expression(self):          """Test unwinding from an expression."""          self.build_and_run_to_bkpt() diff --git a/packages/Python/lldbsuite/test/functionalities/asan/Makefile b/packages/Python/lldbsuite/test/functionalities/asan/Makefile index 26654a023ed1..dc8d682f831a 100644 --- a/packages/Python/lldbsuite/test/functionalities/asan/Makefile +++ b/packages/Python/lldbsuite/test/functionalities/asan/Makefile @@ -1,6 +1,6 @@  LEVEL = ../../make  C_SOURCES := main.c -CFLAGS_EXTRAS := -fsanitize=address -g +CFLAGS_EXTRAS := -fsanitize=address -g -gcolumn-info  include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/asan/TestReportData.py b/packages/Python/lldbsuite/test/functionalities/asan/TestReportData.py index d7c511021863..ca070fa97dfa 100644 --- a/packages/Python/lldbsuite/test/functionalities/asan/TestReportData.py +++ b/packages/Python/lldbsuite/test/functionalities/asan/TestReportData.py @@ -37,6 +37,7 @@ class AsanTestReportDataCase(TestBase):          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") @@ -63,7 +64,7 @@ class AsanTestReportDataCase(TestBase):              lldb.eStopReasonInstrumentation)          self.expect("bt", "The backtrace should show the crashing line", -                    substrs=['main.c:%d' % self.line_crash]) +                    substrs=['main.c:%d:%d' % (self.line_crash, self.col_crash)])          self.expect(              "thread info -s", diff --git a/packages/Python/lldbsuite/test/functionalities/attach_resume/TestAttachResume.py b/packages/Python/lldbsuite/test/functionalities/attach_resume/TestAttachResume.py index ad87796766c3..754acade015a 100644 --- a/packages/Python/lldbsuite/test/functionalities/attach_resume/TestAttachResume.py +++ b/packages/Python/lldbsuite/test/functionalities/attach_resume/TestAttachResume.py @@ -21,7 +21,7 @@ class AttachResumeTestCase(TestBase):      @skipIfRemote      @expectedFailureAll(oslist=['freebsd'], bugnumber='llvm.org/pr19310') -    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") +    @skipIfWindows # llvm.org/pr24778, llvm.org/pr21753      def test_attach_continue_interrupt_detach(self):          """Test attach/continue/interrupt/detach"""          self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/Makefile b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/Makefile new file mode 100644 index 000000000000..6c22351dc3b5 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +C_SOURCES := main.c +CFLAGS_EXTRAS += -std=c99 -gcolumn-info + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py new file mode 100644 index 000000000000..07032cc0380c --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py @@ -0,0 +1,48 @@ +""" +Test setting a breakpoint by line and column. +""" + +from __future__ import print_function + + +import os +import time +import re +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, 20, 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(), 20) +            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, 20) +        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(), 20) +            in_condition |= b_loc.GetColumn() < 30 +        self.assertTrue(in_condition) diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/main.c b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/main.c new file mode 100644 index 000000000000..921bc382023f --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/main.c @@ -0,0 +1,23 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +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/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py index 7a2dc61b1b69..8143fa96433f 100644 --- a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py @@ -25,7 +25,6 @@ class BreakpointCommandTestCase(TestBase):          self.build()          self.breakpoint_command_sequence() -    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528")      def test_script_parameters(self):          """Test a sequence of breakpoint command add, list, and delete."""          self.build() @@ -45,7 +44,6 @@ class BreakpointCommandTestCase(TestBase):          self.addTearDownHook(              lambda: self.runCmd("settings clear auto-confirm")) -    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528")      def test_delete_all_breakpoints(self):          """Test that deleting all breakpoints works."""          self.build() @@ -133,9 +131,9 @@ class BreakpointCommandTestCase(TestBase):              patterns=[                  "1: file = '.*main.c', line = %d, exact_match = 0, locations = 1" %                  self.line, -                "1.1: .+at main.c:%d, .+unresolved, hit count = 0" % +                "1.1: .+at main.c:%d:?[0-9]*, .+unresolved, hit count = 0" %                  self.line, -                "2.1: .+at main.c:%d, .+unresolved, hit count = 0" % +                "2.1: .+at main.c:%d:?[0-9]*, .+unresolved, hit count = 0" %                  self.line])          self.expect("breakpoint command list 1", "Breakpoint 1 command ok", diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/TestBreakpointIgnoreCount.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/TestBreakpointIgnoreCount.py index eb4bac7e6e66..e3bf4c27f31e 100644 --- a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/TestBreakpointIgnoreCount.py +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/TestBreakpointIgnoreCount.py @@ -18,12 +18,14 @@ 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() diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/TestMoveNearest.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/TestMoveNearest.py index 16d5bc75473c..b8281e9c85bd 100644 --- a/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/TestMoveNearest.py +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/TestMoveNearest.py @@ -18,6 +18,8 @@ class TestMoveNearest(TestBase):          # 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): @@ -61,3 +63,7 @@ class TestMoveNearest(TestBase):          # "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/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/main.cpp b/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/main.cpp index c9295a5c7d3c..76a22a5420fe 100644 --- a/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/main.cpp @@ -1,7 +1,7 @@  #include "foo.h"  int call_foo2() { return foo2(); } - +// BR_Between  int  main() // !BR_main  { diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/Makefile b/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/Makefile new file mode 100644 index 000000000000..7934cd5db427 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/Makefile @@ -0,0 +1,9 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +ifneq (,$(findstring icc,$(CC))) +    CFLAGS += -debug inline-debug-info +endif + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/TestRequireHWBreakpoints.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/TestRequireHWBreakpoints.py new file mode 100644 index 000000000000..cda15fee84b8 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/TestRequireHWBreakpoints.py @@ -0,0 +1,106 @@ +""" +Test require hardware breakpoints. +""" + +from __future__ import print_function + +import os +import time +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 +    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 +    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 +    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") +        self.expect( +            "process status", +            substrs=[ +                'step over failed', +                'Could not create hardware breakpoint for thread plan' +            ]) + +    @skipIfWindows +    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/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/main.c b/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/main.c new file mode 100644 index 000000000000..7d49a57d4c7b --- /dev/null +++ b/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/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/Makefile b/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/Makefile new file mode 100644 index 000000000000..6067ee45e984 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +C_SOURCES := main.c +CFLAGS_EXTRAS += -std=c99 + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py new file mode 100644 index 000000000000..0eb9033e754b --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py @@ -0,0 +1,199 @@ +""" +Test setting breakpoints using a scripted resolver +""" + +from __future__ import print_function + + +import os +import time +import re +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): +        """ Make sure we are called at the right depths depending on what we return +            from __get_depth__""" +        self.build() +        self.do_test_cli() + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) + +    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") diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/main.c b/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/main.c new file mode 100644 index 000000000000..b91ccfc1b43e --- /dev/null +++ b/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/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/resolver.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/resolver.py new file mode 100644 index 000000000000..61f5f2df20ac --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/resolver.py @@ -0,0 +1,54 @@ +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) + +      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/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/TestBreakpointSerialization.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/TestBreakpointSerialization.py index c615278e8d48..943998a421be 100644 --- a/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/TestBreakpointSerialization.py +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/TestBreakpointSerialization.py @@ -180,7 +180,8 @@ class BreakpointSerialization(TestBase):          # actually have locations.          source_bps = lldb.SBBreakpointList(self.orig_target) -        bkpt = self.orig_target.BreakpointCreateByLocation("blubby.c", 666) +        bkpt = self.orig_target.BreakpointCreateByLocation( +            lldb.SBFileSpec("blubby.c"), 666, 333, 0, lldb.SBFileSpecList())          bkpt.SetEnabled(False)          bkpt.SetOneShot(True)          bkpt.SetThreadID(10) @@ -226,7 +227,8 @@ class BreakpointSerialization(TestBase):          all_bps = lldb.SBBreakpointList(self.orig_target)          source_bps = lldb.SBBreakpointList(self.orig_target) -        bkpt = self.orig_target.BreakpointCreateByLocation("blubby.c", 666) +        bkpt = self.orig_target.BreakpointCreateByLocation( +            lldb.SBFileSpec("blubby.c"), 666, 333, 0, lldb.SBFileSpecList())          bkpt.SetEnabled(False)          bkpt.SetOneShot(True)          bkpt.SetThreadID(10) @@ -260,7 +262,8 @@ class BreakpointSerialization(TestBase):          self.check_equivalence(all_bps)      def do_check_names(self): -        bkpt = self.orig_target.BreakpointCreateByLocation("blubby.c", 666) +        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) diff --git a/packages/Python/lldbsuite/test/functionalities/command_script_immediate_output/TestCommandScriptImmediateOutput.py b/packages/Python/lldbsuite/test/functionalities/command_script_immediate_output/TestCommandScriptImmediateOutput.py index c6ad75f014ee..c1595cf25515 100644 --- a/packages/Python/lldbsuite/test/functionalities/command_script_immediate_output/TestCommandScriptImmediateOutput.py +++ b/packages/Python/lldbsuite/test/functionalities/command_script_immediate_output/TestCommandScriptImmediateOutput.py @@ -28,6 +28,7 @@ class CommandScriptImmediateOutputTestCase (PExpectTest):          oslist=["windows"],          bugnumber="llvm.org/pr22274: need a pexpect replacement for windows")      @expectedFailureAll(oslist=["freebsd"], bugnumber="llvm.org/pr26139") +    @skipIfDarwin      def test_command_script_immediate_output_console(self):          """Test that LLDB correctly allows scripted commands to set immediate output to the console."""          self.launch(timeout=10) @@ -50,6 +51,7 @@ class CommandScriptImmediateOutputTestCase (PExpectTest):          oslist=["windows"],          bugnumber="llvm.org/pr22274: need a pexpect replacement for windows")      @expectedFailureAll(oslist=["freebsd"], bugnumber="llvm.org/pr26139") +    @skipIfDarwin      def test_command_script_immediate_output_file(self):          """Test that LLDB correctly allows scripted commands to set immediate output to a file."""          self.launch(timeout=10) diff --git a/packages/Python/lldbsuite/test/functionalities/completion/TestCompletion.py b/packages/Python/lldbsuite/test/functionalities/completion/TestCompletion.py index 5d4fcf64511b..c073425a93fb 100644 --- a/packages/Python/lldbsuite/test/functionalities/completion/TestCompletion.py +++ b/packages/Python/lldbsuite/test/functionalities/completion/TestCompletion.py @@ -43,7 +43,6 @@ class CommandLineCompletionTestCase(TestBase):          self.build()          self.main_source = "main.cpp"          self.main_source_spec = lldb.SBFileSpec(self.main_source) -        self.dbg.CreateTarget(self.getBuildArtifact("a.out"))          (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self,                                            '// Break here', self.main_source_spec) @@ -177,8 +176,8 @@ class CommandLineCompletionTestCase(TestBase):      @skipIfFreeBSD  # timing out on the FreeBSD buildbot      def test_settings_s_dash(self): -        """Test that 'settings set -' completes to 'settings set -g'.""" -        self.complete_from_to('settings set -', 'settings set -g') +        """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): @@ -275,6 +274,22 @@ class CommandLineCompletionTestCase(TestBase):          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."], +            ["bugreport", "Commands for creating domain-specific bug reports."] +        ]) + +        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", []) +      @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24489")      def test_symbol_name(self):          self.build() @@ -282,39 +297,3 @@ class CommandLineCompletionTestCase(TestBase):          self.complete_from_to('breakpoint set -n Fo',                                'breakpoint set -n Foo::Bar(int,\\ int)',                                turn_off_re_match=True) - -    def complete_from_to(self, str_input, patterns, turn_off_re_match=False): -        """Test that the completion mechanism completes str_input to patterns, -        where patterns could be a pattern-string or a list of pattern-strings""" -        # Patterns should not be None in order to proceed. -        self.assertFalse(patterns is None) -        # And should be either a string or list of strings.  Check for list type -        # below, if not, make a list out of the singleton string.  If patterns -        # is not a string or not a list of strings, there'll be runtime errors -        # later on. -        if not isinstance(patterns, list): -            patterns = [patterns] - -        interp = self.dbg.GetCommandInterpreter() -        match_strings = lldb.SBStringList() -        num_matches = interp.HandleCompletion(str_input, len(str_input), 0, -1, match_strings) -        common_match = match_strings.GetStringAtIndex(0) -        if num_matches == 0: -            compare_string = str_input -        else: -            if common_match != None and len(common_match) > 0: -                compare_string = str_input + common_match -            else: -                compare_string = "" -                for idx in range(1, num_matches+1): -                    compare_string += match_strings.GetStringAtIndex(idx) + "\n" - -        for p in patterns: -            if turn_off_re_match: -                self.expect( -                    compare_string, msg=COMPLETION_MSG( -                        str_input, p, match_strings), exe=False, substrs=[p]) -            else: -                self.expect( -                    compare_string, msg=COMPLETION_MSG( -                        str_input, p, match_strings), exe=False, patterns=[p]) diff --git a/packages/Python/lldbsuite/test/functionalities/conditional_break/TestConditionalBreak.py b/packages/Python/lldbsuite/test/functionalities/conditional_break/TestConditionalBreak.py index 904fb4c90372..7b123950c23d 100644 --- a/packages/Python/lldbsuite/test/functionalities/conditional_break/TestConditionalBreak.py +++ b/packages/Python/lldbsuite/test/functionalities/conditional_break/TestConditionalBreak.py @@ -34,9 +34,6 @@ class ConditionalBreakTestCase(TestBase):          self.build()          self.simulate_conditional_break_by_user() -    @expectedFailureAll( -        oslist=["windows"], -        bugnumber="llvm.org/pr26265: args in frames other than #0 are not evaluated correctly")      def do_conditional_break(self):          """Exercise some thread and frame APIs to break if c() is called by a()."""          exe = self.getBuildArtifact("a.out") diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py index 9749061f42d5..4b9de961724b 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py @@ -23,9 +23,6 @@ class CppDataFormatterTestCase(TestBase):          # 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")      @skipIf(debug_info="gmodules",              bugnumber="https://bugs.llvm.org/show_bug.cgi?id=36048")      def test_with_run_command(self): diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-script/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-script/main.cpp index aaccb6329acf..1c98f3db24c8 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-script/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-script/main.cpp @@ -50,4 +50,4 @@ int main (int argc, const char * argv[])      int dummy = 1;      return 0; -}
\ No newline at end of file +} diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-skip-summary/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-skip-summary/main.cpp index 82ffb2c20d47..665c9fe75d1c 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-skip-summary/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-skip-summary/main.cpp @@ -54,4 +54,4 @@ int main()      DeepData_2 data2;      return 0; // Set break point at this line. -}
\ No newline at end of file +} diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py index 13b38cbfa702..54e9c346df31 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py @@ -17,9 +17,6 @@ class SmartArrayDataFormatterTestCase(TestBase):      mydir = TestBase.compute_mydir(__file__) -    @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() diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/TestLibCxxFunction.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/TestLibCxxFunction.py index 81a76cc65d63..e44ea61d120f 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/TestLibCxxFunction.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/TestLibCxxFunction.py @@ -40,13 +40,17 @@ class LibCxxFunctionTestCase(TestBase):                      substrs=['stopped',                               'stop reason = breakpoint']) -        f1 = self.get_variable('f1') -        f2 = self.get_variable('f2') +        self.expect("frame variable f1", +                    substrs=['f1 =  Function = foo(int, int)']) -        if self.TraceOn(): -            print(f1) -        if self.TraceOn(): -            print(f2) +        self.expect("frame variable f2", +                    substrs=['f2 =  Lambda in File main.cpp at Line 27']) -        self.assertTrue(f1.GetValueAsUnsigned(0) != 0, 'f1 has a valid value') -        self.assertTrue(f2.GetValueAsUnsigned(0) != 0, 'f2 has a valid value') +        self.expect("frame variable f3", +                    substrs=['f3 =  Lambda in File main.cpp at Line 31']) + +        self.expect("frame variable f4", +                    substrs=['f4 =  Function in File main.cpp at Line 17']) + +        self.expect("frame variable f5", +                    substrs=['f5 =  Function = Bar::add_num(int) const']) diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/main.cpp index cfe689b29b01..541fdaca2afa 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/main.cpp @@ -13,13 +13,28 @@ int foo(int x, int y) {    return x + y - 1;  } -int main () +struct Bar { +   int operator()() { +       return 66 ; +   } +   int add_num(int i) const { return i + 3 ; } +} ; + +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);    }; -    return f1(acc,acc) + f2(acc); // Set break point at this line. -} +  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; + +  return f1(acc,acc) + f2(acc) + f3(acc+1,acc+2) + f4() + f5(bar1, 10); // Set break point at this line. +} diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/TestDataFormatterLibcxxList.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/TestDataFormatterLibcxxList.py index 90a7e119fb84..86248d1cac24 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/TestDataFormatterLibcxxList.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/TestDataFormatterLibcxxList.py @@ -190,6 +190,7 @@ class LibcxxListDataFormatterTestCase(TestBase):          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]", diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/main.cpp index 6247ca8b2412..da6eca985d20 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/main.cpp @@ -74,4 +74,4 @@ int main()      ss.clear();      thefoo_rw(1);  // Set break point at this line.          return 0; -}
\ No newline at end of file +} diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/main.cpp index e8385994125d..27bdc0a57729 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/main.cpp @@ -74,4 +74,4 @@ int main()      ss.clear();      thefoo_rw(1);  // Set break point at this line.          return 0; -}
\ No newline at end of file +} diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/Makefile b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/Makefile new file mode 100644 index 000000000000..19d6fc3e3c25 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../../../../make + +CXX_SOURCES := main.cpp + +USE_LIBCPP := 1 +include $(LEVEL)/Makefile.rules +CXXFLAGS += -std=c++17 -fno-exceptions diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/TestDataFormatterLibcxxOptional.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/TestDataFormatterLibcxxOptional.py new file mode 100644 index 000000000000..7826305931da --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/TestDataFormatterLibcxxOptional.py @@ -0,0 +1,75 @@ +""" +Test lldb data formatter subsystem. +""" + +from __future__ import print_function + + +import os +import time +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/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/main.cpp new file mode 100644 index 000000000000..16bb98c61056 --- /dev/null +++ b/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/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/Makefile b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/Makefile index 1f609a41d908..937b47ea06b0 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/Makefile +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/Makefile @@ -4,4 +4,4 @@ CXX_SOURCES := main.cpp  USE_LIBCPP := 1  include $(LEVEL)/Makefile.rules -CXXFLAGS += -O0 +CXXFLAGS += -std=c++11 -O0 diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py index 4574a044488c..63164f78e00e 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py @@ -68,7 +68,9 @@ class LibcxxStringDataFormatterTestCase(TestBase):                  '(%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::wstring) IHaveEmbeddedZerosToo = L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"'%ns, +                '(%s::u16string) u16_string = u"ß水氶"'%ns, +                '(%s::u32string) u32_string = U"🍄🍅🍆🍌"'%ns])          self.runCmd("n") @@ -98,4 +100,6 @@ class LibcxxStringDataFormatterTestCase(TestBase):                  '(%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::wstring) IHaveEmbeddedZerosToo = L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"'%ns, +                '(%s::u16string) u16_string = u"ß水氶"'%ns, +                '(%s::u32string) u32_string = U"🍄🍅🍆🍌"'%ns]) diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/main.cpp index 9ca0da39cfc8..838a4c71be1a 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/main.cpp @@ -10,6 +10,8 @@ int main()      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::u32string u32_string(U"🍄🍅🍆🍌");      S.assign(L"!!!!!"); // Set break point at this line.      return 0;  } diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/Makefile b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/Makefile new file mode 100644 index 000000000000..a6ea665ef63c --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../../../../make + +CXX_SOURCES := main.cpp + +USE_LIBCPP := 1 +include $(LEVEL)/Makefile.rules +CXXFLAGS += -std=c++17 diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/TestDataFormatterLibcxxVariant.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/TestDataFormatterLibcxxVariant.py new file mode 100644 index 000000000000..e1f6961b465d --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/TestDataFormatterLibcxxVariant.py @@ -0,0 +1,83 @@ +""" +Test lldb data formatter subsystem. +""" + +from __future__ import print_function + + +import os +import time +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/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/main.cpp new file mode 100644 index 000000000000..c0bc4ae12c1a --- /dev/null +++ b/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/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/TestDataFormatterLibcxxVector.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/TestDataFormatterLibcxxVector.py index 237e27fe1f31..06d3cda61be2 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/TestDataFormatterLibcxxVector.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/TestDataFormatterLibcxxVector.py @@ -51,8 +51,6 @@ class LibcxxVectorDataFormatterTestCase(TestBase):                      substrs=['1234'])      @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() @@ -180,8 +178,6 @@ class LibcxxVectorDataFormatterTestCase(TestBase):                      substrs=['vector has 0 items'])      @add_test_categories(["libc++"]) -    @skipIf(debug_info="gmodules", -            bugnumber="https://bugs.llvm.org/show_bug.cgi?id=36048")      def test_ref_and_ptr(self):          """Test that that file and class static variables display correctly."""          self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/main.cpp index d7b046c5bff8..7ddffd19012e 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/main.cpp @@ -35,4 +35,4 @@ int main()  	svter svI = sv.begin();      return 0; // Set break point at this line. -}
\ No newline at end of file +} diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/main.cpp index 568c35efe072..d5e5b212782d 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/main.cpp @@ -52,4 +52,4 @@ int main()      ss.clear();// Set break point at this line.      return 0;// Set break point at this line. -}
\ No newline at end of file +} diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/main.cpp index 4a9b4fc7d0db..f6e56cf12456 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/main.cpp @@ -9,4 +9,4 @@ int main()      std::string Q("quite a long std::strin with lots of info inside it");      S.assign(L"!!!!!"); // Set break point at this line.      return 0; -}
\ No newline at end of file +} diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/TestDataFormatterStdUniquePtr.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/TestDataFormatterStdUniquePtr.py index 5d05418a8b49..f782a2a8baea 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/TestDataFormatterStdUniquePtr.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/TestDataFormatterStdUniquePtr.py @@ -66,6 +66,7 @@ class StdUniquePtrDataFormatterTestCase(TestBase):      @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 diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py index 08768a61bd9d..138b32802951 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py @@ -24,9 +24,6 @@ class DataFormatterSynthValueTestCase(TestBase):          self.line = line_number('main.cpp', 'break here')      @skipIfFreeBSD  # llvm.org/pr20545 bogus output confuses buildbot parser -    @expectedFailureAll( -        oslist=["windows"], -        bugnumber="llvm.org/pr24462, Data formatters have problems on Windows")      def test_with_run_command(self):          """Test using Python synthetic children provider to provide a value."""          self.build() @@ -107,7 +104,7 @@ class DataFormatterSynthValueTestCase(TestBase):          # check that an aptly defined synthetic provider does not affect          # one-lining          self.expect( -            "expression struct S { myInt theInt{12}; }; S()", +            "expression struct Struct { myInt theInt{12}; }; Struct()",              substrs=['(theInt = 12)'])          # check that we can use a synthetic value in a summary diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/main.cpp index fec7907e0031..90571b59f81e 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/main.cpp @@ -59,4 +59,4 @@ int main()                 256*256*256*'D');      return 0; -}
\ No newline at end of file +} diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/typedef_array/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/typedef_array/main.cpp index 649c1e09a6a5..5b43102c268c 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/typedef_array/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/typedef_array/main.cpp @@ -9,6 +9,11 @@  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.expect("frame variable array --show-types --", substrs = ['(Foo [3]) array = {','(Foo) [0] = 1','(Foo) [1] = 2','(Foo) [2] = 3']) +    return 0; //% self.filecheck("frame variable array --show-types --", 'main.cpp')  } diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/TestDataFormatterVarScriptFormatting.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/TestDataFormatterVarScriptFormatting.py index d3c04afe91eb..670edad37f9e 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/TestDataFormatterVarScriptFormatting.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/TestDataFormatterVarScriptFormatting.py @@ -14,7 +14,7 @@ from lldbsuite.test.lldbtest import *  from lldbsuite.test import lldbutil -class PythonSynthDataFormatterTestCase(TestBase): +class DataFormatterVarScriptFormatting(TestBase):      mydir = TestBase.compute_mydir(__file__) diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/main.cpp index 4dc94af3566c..e9a36f911964 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/main.cpp @@ -5,4 +5,4 @@ int main() {      something<int> x;      something<void*> y;      return 0; // Set breakpoint here. -}
\ No newline at end of file +} diff --git a/packages/Python/lldbsuite/test/functionalities/stop-hook/Makefile b/packages/Python/lldbsuite/test/functionalities/deleted-executable/Makefile index 8a7102e347af..8a7102e347af 100644 --- a/packages/Python/lldbsuite/test/functionalities/stop-hook/Makefile +++ b/packages/Python/lldbsuite/test/functionalities/deleted-executable/Makefile diff --git a/packages/Python/lldbsuite/test/functionalities/deleted-executable/TestDeletedExecutable.py b/packages/Python/lldbsuite/test/functionalities/deleted-executable/TestDeletedExecutable.py new file mode 100644 index 000000000000..1eeaeeffa87b --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/deleted-executable/TestDeletedExecutable.py @@ -0,0 +1,31 @@ +""" +Test process attach/resume. +""" + +from __future__ import print_function + + +import os +import time +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"]) # determining the architecture of the process fails +    def test(self): +        self.build() +        exe = self.getBuildArtifact("a.out") + +        popen = self.spawnSubprocess(exe) +        self.addTearDownHook(self.cleanupSubprocesses) +        os.remove(exe) + +        self.runCmd("process attach -p " + str(popen.pid)) +        self.runCmd("kill") diff --git a/packages/Python/lldbsuite/test/functionalities/deleted-executable/main.cpp b/packages/Python/lldbsuite/test/functionalities/deleted-executable/main.cpp new file mode 100644 index 000000000000..ad5d18732eac --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/deleted-executable/main.cpp @@ -0,0 +1,9 @@ +#include <chrono> +#include <thread> + +int main(int argc, char const *argv[]) +{ +    lldb_enable_attach(); + +    std::this_thread::sleep_for(std::chrono::seconds(30)); +} diff --git a/packages/Python/lldbsuite/test/functionalities/disassembly/TestDisassembleBreakpoint.py b/packages/Python/lldbsuite/test/functionalities/disassembly/TestDisassembleBreakpoint.py index 52f9daf6bd45..91b858b4665a 100644 --- a/packages/Python/lldbsuite/test/functionalities/disassembly/TestDisassembleBreakpoint.py +++ b/packages/Python/lldbsuite/test/functionalities/disassembly/TestDisassembleBreakpoint.py @@ -18,9 +18,6 @@ class DisassemblyTestCase(TestBase):      mydir = TestBase.compute_mydir(__file__)      NO_DEBUG_INFO_TESTCASE = True -    @expectedFailureAll( -        oslist=["windows"], -        bugnumber="function names print fully demangled instead of name-only")      def test(self):          self.build()          target, _, _, bkpt = lldbutil.run_to_source_breakpoint(self, diff --git a/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/TestConvenienceVariables.py b/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/TestConvenienceVariables.py deleted file mode 100644 index 0f130b3ecbab..000000000000 --- a/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/TestConvenienceVariables.py +++ /dev/null @@ -1,108 +0,0 @@ -"""Test convenience variables when you drop in from lldb prompt into an embedded interpreter.""" - -from __future__ import print_function - - -import os -import lldb -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil - - -class ConvenienceVariablesCase(TestBase): - -    mydir = TestBase.compute_mydir(__file__) - -    def setUp(self): -        # Call super's setUp(). -        TestBase.setUp(self) -        # Find the line number to break on inside main.cpp. -        self.line = line_number('main.c', 'Hello world.') - -    @skipIfFreeBSD  # llvm.org/pr17228 -    @skipIfRemote -    @expectedFailureAll( -        oslist=["windows"], -        bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") -    def test_with_run_commands(self): -        """Test convenience variables lldb.debugger, lldb.target, lldb.process, lldb.thread, and lldb.frame.""" -        self.build() -        import pexpect -        exe = self.getBuildArtifact("a.out") -        prompt = "(lldb) " -        python_prompt = ">>> " - -        # So that the child gets torn down after the test. -        self.child = pexpect.spawn( -            '%s %s %s' % -            (lldbtest_config.lldbExec, self.lldbOption, exe)) -        child = self.child -        # Turn on logging for what the child sends back. -        if self.TraceOn(): -            child.logfile_read = sys.stdout - -        # Set the breakpoint, run the inferior, when it breaks, issue print on -        # the various convenience variables. -        child.expect_exact(prompt) -        child.sendline('breakpoint set -f main.c -l %d' % self.line) -        child.expect_exact(prompt) -        child.sendline('run') -        child.expect_exact("stop reason = breakpoint 1.1") -        child.expect_exact(prompt) -        child.sendline('script') -        child.expect_exact(python_prompt) - -        # Set a flag so that we know during teardown time, we need to exit the -        # Python interpreter, then the lldb interpreter. -        self.child_in_script_interpreter = True - -        child.sendline('print(lldb.debugger)') -        child.expect_exact(python_prompt) -        self.expect(child.before, exe=False, -                    patterns=['Debugger \(instance: .*, id: \d\)']) - -        child.sendline('print(lldb.target)') -        child.expect_exact(python_prompt) -        self.expect(child.before, exe=False, -                    substrs=['a.out']) - -        child.sendline('print(lldb.process)') -        child.expect_exact(python_prompt) -        self.expect(child.before, exe=False, patterns=[ -                    'SBProcess: pid = \d+, state = stopped, threads = \d, executable = a.out']) - -        child.sendline('print(lldb.thread.GetStopDescription(100))') -        child.expect_exact(python_prompt) -        self.expect( -            child.before, -            exe=False, -            patterns=[ -                'breakpoint 1\.1']) - -        child.sendline('lldb.frame.GetLineEntry().GetLine()') -        child.expect_exact(python_prompt) -        line_number = "%d"%(self.line) -        self.expect( -            child.before, -            exe=False, -            substrs=[ -                line_number]) - -        child.sendline('lldb.frame.GetLineEntry().GetFileSpec().GetFilename()') -        child.expect_exact(python_prompt) -        line_number = "%d"%(self.line) -        self.expect( -            child.before, -            exe=False, -            substrs=[ -                "main.c"]) - -        child.sendline('lldb.frame.GetFunctionName()') -        child.expect_exact(python_prompt) -        line_number = "%d"%(self.line) -        self.expect( -            child.before, -            exe=False, -            substrs=[ -                "main"]) diff --git a/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/main.c b/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/main.c deleted file mode 100644 index 277aa54a4eea..000000000000 --- a/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/main.c +++ /dev/null @@ -1,6 +0,0 @@ -#include <stdio.h> - -int main(int argc, char const *argv[]) { -    printf("Hello world.\n"); -    return 0; -} diff --git a/packages/Python/lldbsuite/test/functionalities/exec/TestExec.py b/packages/Python/lldbsuite/test/functionalities/exec/TestExec.py index 8126a7ec750c..2cec254acc0c 100644 --- a/packages/Python/lldbsuite/test/functionalities/exec/TestExec.py +++ b/packages/Python/lldbsuite/test/functionalities/exec/TestExec.py @@ -31,12 +31,14 @@ class ExecTestCase(TestBase):      @skipUnlessDarwin      @expectedFailureAll(archs=['i386'], bugnumber="rdar://28656532")      @expectedFailureAll(oslist=["ios", "tvos", "watchos", "bridgeos"], bugnumber="rdar://problem/34559552") # this exec test has problems on ios systems +    @skipIfSanitized # rdar://problem/43756823      def test_hitting_exec (self):          self.do_test(False)      @skipUnlessDarwin      @expectedFailureAll(archs=['i386'], bugnumber="rdar://28656532")      @expectedFailureAll(oslist=["ios", "tvos", "watchos", "bridgeos"], bugnumber="rdar://problem/34559552") # this exec test has problems on ios systems +    @skipIfSanitized # rdar://problem/43756823      def test_skipping_exec (self):          self.do_test(True) @@ -61,6 +63,8 @@ class ExecTestCase(TestBase):              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(): @@ -94,6 +98,8 @@ class ExecTestCase(TestBase):          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") diff --git a/packages/Python/lldbsuite/test/expression_command/multiline/Makefile b/packages/Python/lldbsuite/test/functionalities/expr-entry-bp/Makefile index 0d70f2595019..0d70f2595019 100644 --- a/packages/Python/lldbsuite/test/expression_command/multiline/Makefile +++ b/packages/Python/lldbsuite/test/functionalities/expr-entry-bp/Makefile diff --git a/packages/Python/lldbsuite/test/functionalities/expr-entry-bp/TestExprEntryBP.py b/packages/Python/lldbsuite/test/functionalities/expr-entry-bp/TestExprEntryBP.py new file mode 100644 index 000000000000..56abc19f4f30 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/expr-entry-bp/TestExprEntryBP.py @@ -0,0 +1,34 @@ +""" +Tests expressions evaluation when the breakpoint on module's entry is set. +""" + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class ExprEntryBPTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    NO_DEBUG_INFO_TESTCASE = True + +    def test_expr_entry_bp(self): +        """Tests expressions evaluation when the breakpoint on module's entry is set.""" +        self.build() +        self.main_source_file = lldb.SBFileSpec("main.c") + +        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, "Set a breakpoint here", self.main_source_file) + +        self.assertEqual(1, bkpt.GetNumLocations()) +        entry = bkpt.GetLocationAtIndex(0).GetAddress().GetModule().GetObjectFileEntryPointAddress() +        self.assertTrue(entry.IsValid(), "Can't get a module entry point") + +        entry_bp = target.BreakpointCreateBySBAddress(entry) +        self.assertTrue(entry_bp.IsValid(), "Can't set a breakpoint on the module entry point") + +        result = target.EvaluateExpression("sum(7, 1)") +        self.assertTrue(result.IsValid(), "Can't evaluate expression") +        self.assertEqual(8, result.GetValueAsSigned()) + +    def setUp(self): +        TestBase.setUp(self) diff --git a/packages/Python/lldbsuite/test/functionalities/expr-entry-bp/main.c b/packages/Python/lldbsuite/test/functionalities/expr-entry-bp/main.c new file mode 100644 index 000000000000..168fc9c8ccbf --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/expr-entry-bp/main.c @@ -0,0 +1,10 @@ +#include <stdio.h> + +int sum(int x, int y) { +  return x + y; +} + +int main() { +  printf("Set a breakpoint here.\n"); +  return sum(-1, 1); +} diff --git a/packages/Python/lldbsuite/test/functionalities/frame-recognizer/Makefile b/packages/Python/lldbsuite/test/functionalities/frame-recognizer/Makefile new file mode 100644 index 000000000000..45f00b3e9861 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/frame-recognizer/Makefile @@ -0,0 +1,10 @@ +LEVEL = ../../make + +OBJC_SOURCES := main.m + +CFLAGS_EXTRAS += -g0 # No debug info. +MAKE_DSYM := NO + +include $(LEVEL)/Makefile.rules + +LDFLAGS += -framework Foundation diff --git a/packages/Python/lldbsuite/test/functionalities/frame-recognizer/TestFrameRecognizer.py b/packages/Python/lldbsuite/test/functionalities/frame-recognizer/TestFrameRecognizer.py new file mode 100644 index 000000000000..1162157bad57 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/frame-recognizer/TestFrameRecognizer.py @@ -0,0 +1,117 @@ +# encoding: utf-8 +""" +Test lldb's frame recognizers. +""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +import recognizer + +class FrameRecognizerTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) +    NO_DEBUG_INFO_TESTCASE = True + +    @skipUnlessDarwin +    def test_frame_recognizer_1(self): +        self.build() + +        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) +        self.assertTrue(target, VALID_TARGET) + +        self.runCmd("command script import " + os.path.join(self.getSourceDir(), "recognizer.py")) + +        self.expect("frame recognizer list", +                    substrs=['no matching results found.']) + +        self.runCmd("frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo") + +        self.expect("frame recognizer list", +                    substrs=['0: recognizer.MyFrameRecognizer, module a.out, function foo']) + +        self.runCmd("frame recognizer add -l recognizer.MyOtherFrameRecognizer -s a.out -n bar -x") + +        self.expect("frame recognizer list", +                    substrs=['0: recognizer.MyFrameRecognizer, module a.out, function foo', +                             '1: recognizer.MyOtherFrameRecognizer, module a.out, function bar (regexp)' +                    ]) + +        self.runCmd("frame recognizer delete 0") + +        self.expect("frame recognizer list", +                    substrs=['1: recognizer.MyOtherFrameRecognizer, module a.out, function bar (regexp)']) + +        self.runCmd("frame recognizer clear") + +        self.expect("frame recognizer list", +                    substrs=['no matching results found.']) + +        self.runCmd("frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo") + +        lldbutil.run_break_set_by_symbol(self, "foo") +        self.runCmd("r") + +        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, +                    substrs=['stopped', 'stop reason = breakpoint']) + +        process = target.GetProcess() +        thread = process.GetSelectedThread() +        frame = thread.GetSelectedFrame() + +        self.assertEqual(frame.GetSymbol().GetName(), "foo") +        self.assertFalse(frame.GetLineEntry().IsValid()) + +        self.expect("frame variable", +                    substrs=['(int) a = 42', '(int) b = 56']) + +        # Recognized arguments don't show up by default... +        variables = frame.GetVariables(lldb.SBVariablesOptions()) +        self.assertEqual(variables.GetSize(), 0) + +        # ...unless you set target.display-recognized-arguments to 1... +        self.runCmd("settings set target.display-recognized-arguments 1") +        variables = frame.GetVariables(lldb.SBVariablesOptions()) +        self.assertEqual(variables.GetSize(), 2) + +        # ...and you can reset it back to 0 to hide them again... +        self.runCmd("settings set target.display-recognized-arguments 0") +        variables = frame.GetVariables(lldb.SBVariablesOptions()) +        self.assertEqual(variables.GetSize(), 0) + +        # ... or explicitly ask for them with SetIncludeRecognizedArguments(True). +        opts = lldb.SBVariablesOptions() +        opts.SetIncludeRecognizedArguments(True) +        variables = frame.GetVariables(opts) + +        self.assertEqual(variables.GetSize(), 2) +        self.assertEqual(variables.GetValueAtIndex(0).name, "a") +        self.assertEqual(variables.GetValueAtIndex(0).signed, 42) +        self.assertEqual(variables.GetValueAtIndex(1).name, "b") +        self.assertEqual(variables.GetValueAtIndex(1).signed, 56) + +        self.expect("frame recognizer info 0", +                    substrs=['frame 0 is recognized by recognizer.MyFrameRecognizer']) + +        self.expect("frame recognizer info 999", error=True, +                    substrs=['no frame with index 999']) + +        self.expect("frame recognizer info 1", +                    substrs=['frame 1 not recognized by any recognizer']) + +        # FIXME: The following doesn't work yet, but should be fixed. +        """ +        lldbutil.run_break_set_by_symbol(self, "bar") +        self.runCmd("c") + +        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, +                    substrs=['stopped', 'stop reason = breakpoint']) + +        self.expect("frame variable -t", +                    substrs=['(int *) a = ']) + +        self.expect("frame variable -t *a", +                    substrs=['*a = 78']) +        """ diff --git a/packages/Python/lldbsuite/test/functionalities/frame-recognizer/main.m b/packages/Python/lldbsuite/test/functionalities/frame-recognizer/main.m new file mode 100644 index 000000000000..51103ae038ac --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/frame-recognizer/main.m @@ -0,0 +1,28 @@ +//===-- main.m ------------------------------------------------*- ObjC -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#import <Foundation/Foundation.h> + +void foo(int a, int b) +{ +    printf("%d %d\n", a, b); +} + +void bar(int *ptr) +{ +	printf("%d\n", *ptr); +} + +int main (int argc, const char * argv[]) +{ +    foo(42, 56); +    int i = 78; +    bar(&i); +    return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/frame-recognizer/recognizer.py b/packages/Python/lldbsuite/test/functionalities/frame-recognizer/recognizer.py new file mode 100644 index 000000000000..a8a506745118 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/frame-recognizer/recognizer.py @@ -0,0 +1,21 @@ +# encoding: utf-8 + +import lldb + +class MyFrameRecognizer(object): +    def get_recognized_arguments(self, frame): +        if frame.name == "foo": +            arg1 = frame.EvaluateExpression("$arg1").signed +            arg2 = frame.EvaluateExpression("$arg2").signed +            val1 = lldb.target.CreateValueFromExpression("a", "%d" % arg1) +            val2 = lldb.target.CreateValueFromExpression("b", "%d" % arg2) +            return [val1, val2] +        elif frame.name == "bar": +            arg1 = frame.EvaluateExpression("$arg1").signed +            val1 = lldb.target.CreateValueFromExpression("a", "(int *)%d" % arg1) +            return [val1] +        return [] + +class MyOtherFrameRecognizer(object): +    def get_recognized_arguments(self, frame): +        return [] diff --git a/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestArmRegisterDefinition.py b/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestArmRegisterDefinition.py new file mode 100644 index 000000000000..6e28d5b54052 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestArmRegisterDefinition.py @@ -0,0 +1,130 @@ +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(): +            interp = self.dbg.GetCommandInterpreter() +            result = lldb.SBCommandReturnObject() +            interp.HandleCommand("log enable gdb-remote packets", result) +        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/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestNoWatchpointSupportInfo.py b/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestNoWatchpointSupportInfo.py new file mode 100644 index 000000000000..66a271e126dc --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestNoWatchpointSupportInfo.py @@ -0,0 +1,64 @@ +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;" + +            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(): +            interp = self.dbg.GetCommandInterpreter() +            result = lldb.SBCommandReturnObject() +            interp.HandleCommand("log enable gdb-remote packets", result) +        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/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestStopPCs.py b/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestStopPCs.py new file mode 100644 index 000000000000..7b733e77e679 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestStopPCs.py @@ -0,0 +1,46 @@ +from __future__ import print_function +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") +        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/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestTargetXMLArch.py b/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestTargetXMLArch.py index 184867e480b4..57c5ff0aac25 100644 --- a/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestTargetXMLArch.py +++ b/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestTargetXMLArch.py @@ -121,4 +121,4 @@ class TestTargetXMLArch(GDBRemoteTestBase):          if self.TraceOn():              interp.HandleCommand("target list", result)              print(result.GetOutput()) -        self.assertTrue(target.GetTriple().startswith('x86_64--')) +        self.assertTrue(target.GetTriple().startswith('x86_64-unknown-unknown')) diff --git a/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/gdbclientutils.py b/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/gdbclientutils.py index d8d759a5dd58..a9e553cbb7d5 100644 --- a/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/gdbclientutils.py +++ b/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/gdbclientutils.py @@ -102,12 +102,13 @@ class MockGDBServerResponder:              return self.interrupt()          if packet == "c":              return self.cont() -        if packet == "g": +        if packet[0] == "g":              return self.readRegisters()          if packet[0] == "G":              return self.writeRegisters(packet[1:])          if packet[0] == "p": -            return self.readRegister(int(packet[1:], 16)) +            regnum = packet[1:].split(';')[0] +            return self.readRegister(int(regnum, 16))          if packet[0] == "P":              register, value = packet[1:].split("=")              return self.readRegister(int(register, 16), value) @@ -124,12 +125,16 @@ class MockGDBServerResponder:              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:": @@ -144,6 +149,16 @@ class MockGDBServerResponder:              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() +          return self.other(packet)      def interrupt(self): @@ -179,6 +194,9 @@ class MockGDBServerResponder:      def qfThreadInfo(self):          return "l" +    def qsThreadInfo(self): +        return "l" +      def qC(self):          return "QC0" @@ -204,10 +222,22 @@ class MockGDBServerResponder:      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 @@ -246,7 +276,7 @@ class MockGDBServer:          addr = ("127.0.0.1", self.port)          self._socket.bind(addr)          self.port = self._socket.getsockname()[1] -        self._socket.listen(0) +        self._socket.listen(1)          self._thread = threading.Thread(target=self._run)          self._thread.start() diff --git a/packages/Python/lldbsuite/test/functionalities/inferior-crashing/TestInferiorCrashing.py b/packages/Python/lldbsuite/test/functionalities/inferior-crashing/TestInferiorCrashing.py index 4f54f5d4103b..528192519513 100644 --- a/packages/Python/lldbsuite/test/functionalities/inferior-crashing/TestInferiorCrashing.py +++ b/packages/Python/lldbsuite/test/functionalities/inferior-crashing/TestInferiorCrashing.py @@ -16,59 +16,42 @@ class CrashingInferiorTestCase(TestBase):      mydir = TestBase.compute_mydir(__file__) -    @expectedFailureAll( -        oslist=["windows"], -        bugnumber="llvm.org/pr24778, This actually works, but the test relies on the output format instead of the API") +    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")      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, This actually works, but the test relies on the output format instead of the API") +    @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']) -    @expectedFailureAll( -        oslist=["windows"], -        bugnumber="llvm.org/pr24778, This actually works, but the test relies on the output format instead of the API")      def test_inferior_crashing_python(self):          """Test that lldb reliably catches the inferior crashing (Python API)."""          self.build()          self.inferior_crashing_python() -    @expectedFailureAll( -        oslist=["windows"], -        bugnumber="llvm.org/pr24778, This actually works, but the test relies on the output format instead of the API")      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, This actually works, but the test relies on the output format instead of the API") +    @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() -    @expectedFailureAll( -        oslist=["windows"], -        bugnumber="llvm.org/pr24778, This actually works, but the test relies on the output format instead of the API")      @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() -    @expectedFailureAll( -        oslist=["windows"], -        bugnumber="llvm.org/pr24778, This actually works, but the test relies on the output format instead of the API")      # Inferior exits after stepping after a segfault. This is working as      # intended IMHO.      @skipIfLinux diff --git a/packages/Python/lldbsuite/test/functionalities/inferior-crashing/recursive-inferior/TestRecursiveInferior.py b/packages/Python/lldbsuite/test/functionalities/inferior-crashing/recursive-inferior/TestRecursiveInferior.py index d8efe65dc7f6..2cd4d46a7ca8 100644 --- a/packages/Python/lldbsuite/test/functionalities/inferior-crashing/recursive-inferior/TestRecursiveInferior.py +++ b/packages/Python/lldbsuite/test/functionalities/inferior-crashing/recursive-inferior/TestRecursiveInferior.py @@ -29,13 +29,11 @@ class CrashingRecursiveInferiorTestCase(TestBase):          self.recursive_inferior_crashing_registers()      @add_test_categories(['pyapi']) -    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")      def test_recursive_inferior_crashing_python(self):          """Test that lldb reliably catches the inferior crashing (Python API)."""          self.build()          self.recursive_inferior_crashing_python() -    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")      def test_recursive_inferior_crashing_expr(self):          """Test that the lldb expression interpreter can read from the inferior after crashing (command)."""          self.build() @@ -47,8 +45,8 @@ class CrashingRecursiveInferiorTestCase(TestBase):          self.build()          self.recursive_inferior_crashing_step() -    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")      @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() @@ -58,7 +56,6 @@ class CrashingRecursiveInferiorTestCase(TestBase):      # intended IMHO.      @skipIfLinux      @skipIfFreeBSD -    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")      def test_recursive_inferior_crashing_expr_step_and_expr(self):          """Test that lldb expressions work before and after stepping after a crash."""          self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/load_unload/TestLoadUnload.py b/packages/Python/lldbsuite/test/functionalities/load_unload/TestLoadUnload.py index ab5791c614af..7bc5d205a94f 100644 --- a/packages/Python/lldbsuite/test/functionalities/load_unload/TestLoadUnload.py +++ b/packages/Python/lldbsuite/test/functionalities/load_unload/TestLoadUnload.py @@ -158,6 +158,7 @@ class LoadUnloadTestCase(TestBase):      @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      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) diff --git a/packages/Python/lldbsuite/test/functionalities/memory-region/Makefile b/packages/Python/lldbsuite/test/functionalities/memory-region/Makefile new file mode 100644 index 000000000000..9d4f3b7f1412 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/memory-region/Makefile @@ -0,0 +1,8 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules + +clean:: +	rm -rf $(wildcard *.o *.d *.dSYM) diff --git a/packages/Python/lldbsuite/test/functionalities/memory-region/TestMemoryRegion.py b/packages/Python/lldbsuite/test/functionalities/memory-region/TestMemoryRegion.py new file mode 100644 index 000000000000..4d10e68672e0 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/memory-region/TestMemoryRegion.py @@ -0,0 +1,59 @@ +""" +Test the 'memory region' command. +""" + +from __future__ import print_function + + +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/packages/Python/lldbsuite/test/functionalities/memory-region/main.cpp b/packages/Python/lldbsuite/test/functionalities/memory-region/main.cpp new file mode 100644 index 000000000000..116c10a6c3ea --- /dev/null +++ b/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/packages/Python/lldbsuite/test/functionalities/memory/cache/TestMemoryCache.py b/packages/Python/lldbsuite/test/functionalities/memory/cache/TestMemoryCache.py index f45479bee0bf..56984885104e 100644 --- a/packages/Python/lldbsuite/test/functionalities/memory/cache/TestMemoryCache.py +++ b/packages/Python/lldbsuite/test/functionalities/memory/cache/TestMemoryCache.py @@ -24,7 +24,7 @@ class MemoryCacheTestCase(TestBase):          # Find the line number to break inside main().          self.line = line_number('main.cpp', '// Set break point at this line.') -    @expectedFlakeyOS(oslist=["windows"]) +    @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() diff --git a/packages/Python/lldbsuite/test/functionalities/memory/find/TestMemoryFind.py b/packages/Python/lldbsuite/test/functionalities/memory/find/TestMemoryFind.py index 8e0fbaa32018..245aaa819c7f 100644 --- a/packages/Python/lldbsuite/test/functionalities/memory/find/TestMemoryFind.py +++ b/packages/Python/lldbsuite/test/functionalities/memory/find/TestMemoryFind.py @@ -24,7 +24,6 @@ class MemoryFindTestCase(TestBase):          # Find the line number to break inside main().          self.line = line_number('main.cpp', '// break here') -    @expectedFailureAll(oslist=["windows"])      def test_memory_find(self):          """Test the 'memory find' command."""          self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py index 879f1adebc6a..2c25ccc253fd 100644 --- a/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py +++ b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py @@ -6,6 +6,7 @@ from __future__ import print_function  import shutil  import struct +import os  import lldb  from lldbsuite.test.decorators import * @@ -203,6 +204,30 @@ class LinuxCoreTestCase(TestBase):          for regname, value in values.iteritems():              self.expect("register read {}".format(regname), substrs=["{} = {}".format(regname, value)]) +    @expectedFailureAll(bugnumber="llvm.org/pr37371", hostoslist=["windows"]) +    @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) +      def check_memory_regions(self, process, region_count):          region_list = process.GetMemoryRegions()          self.assertEqual(region_list.GetSize(), region_count) @@ -299,15 +324,7 @@ class LinuxCoreTestCase(TestBase):              self.dbg.SetOutputFileHandle(None, False)              self.dbg.SetErrorFileHandle(None, False) -    def do_test(self, filename, pid, region_count, thread_name): -        target = self.dbg.CreateTarget(filename + ".out") -        process = target.LoadCore(filename + ".core") -        self.assertTrue(process, PROCESS_IS_VALID) -        self.assertEqual(process.GetNumThreads(), 1) -        self.assertEqual(process.GetProcessID(), pid) - -        self.check_state(process) - +    def check_stack(self, process, pid, thread_name):          thread = process.GetSelectedThread()          self.assertTrue(thread)          self.assertEqual(thread.GetThreadID(), pid) @@ -324,6 +341,21 @@ class LinuxCoreTestCase(TestBase):                  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/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpNew.py b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpNew.py index 5960215f8047..46398e39a0e0 100644 --- a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpNew.py +++ b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpNew.py @@ -88,6 +88,36 @@ class MiniDumpNewTestCase(TestBase):          self.assertEqual(self.process.GetProcessID(), self._linux_x86_64_pid)          self.check_state() +    def test_memory_region_name(self): +        self.dbg.CreateTarget(None) +        self.target = self.dbg.GetSelectedTarget() +        self.process = self.target.LoadCore("regions-linux-map.dmp") +        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_modules_in_mini_dump(self):          """Test that lldb can read the list of modules from the minidump."""          # target create -c linux-x86_64.dmp @@ -97,14 +127,18 @@ class MiniDumpNewTestCase(TestBase):          self.assertTrue(self.process, PROCESS_IS_VALID)          expected_modules = [              { -                'filename' : 'linux-gate.so', -                'uuid' : '4EAD28F8-88EF-3520-872B-73C6F2FE7306-C41AF22F', +                'filename' : 'linux-x86_64', +                'uuid' : 'E35C283B-C327-C287-62DB-788BF5A4078B-E2351448',              },              {                  'filename' : 'libm-2.19.so',                  'uuid' : 'D144258E-6149-00B2-55A3-1F3FD2283A87-8670D5BC',              },              { +                'filename' : 'libgcc_s.so.1', +                'uuid' : '36311B44-5771-0AE5-578C-4BF00791DED7-359DBB92', +            }, +            {                  'filename' : 'libstdc++.so.6.0.19',                  'uuid' : '76190E92-2AF7-457D-078F-75C9B15FA184-E83EB506',              }, @@ -113,24 +147,20 @@ class MiniDumpNewTestCase(TestBase):                  'uuid' : 'CF699A15-CAAE-64F5-0311-FC4655B86DC3-9A479789',              },              { -                'filename' : 'linux-x86_64', -                'uuid' : 'E35C283B-C327-C287-62DB-788BF5A4078B-E2351448', -            }, -            { -                'filename' : 'libgcc_s.so.1', -                'uuid' : '36311B44-5771-0AE5-578C-4BF00791DED7-359DBB92', -            }, -            {                  'filename' : 'libpthread-2.19.so',                  'uuid' : '31E9F21A-E8C1-0396-171F-1E13DA157809-86FA696C',              },              { +                'filename' : 'libbreakpad.so', +                'uuid' : '784FD549-332D-826E-D23F-18C17C6F320A', +            }, +            {                  'filename' : 'ld-2.19.so',                  'uuid' : 'D0F53790-4076-D73F-29E4-A37341F8A449-E2EF6CD0',              },              { -                'filename' : 'libbreakpad.so', -                'uuid' : '784FD549-332D-826E-D23F-18C17C6F320A', +                'filename' : 'linux-gate.so', +                'uuid' : '4EAD28F8-88EF-3520-872B-73C6F2FE7306-C41AF22F',              },          ]          self.assertEqual(self.target.GetNumModules(), len(expected_modules)) @@ -189,6 +219,161 @@ class MiniDumpNewTestCase(TestBase):          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.""" +        # target create -c arm64-macos.dmp +        self.dbg.CreateTarget(None) +        self.target = self.dbg.GetSelectedTarget() +        self.process = self.target.LoadCore("arm64-macos.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, "") +        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. +        """ +        self.dbg.CreateTarget(None) +        self.target = self.dbg.GetSelectedTarget() +        if apple: +            self.process = self.target.LoadCore("arm-macos.dmp") +        else: +            self.process = self.target.LoadCore("arm-linux.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, "") +        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) @@ -263,3 +448,65 @@ class MiniDumpNewTestCase(TestBase):          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""" +        # target create -c regions-linux-map.dmp +        self.dbg.CreateTarget(None) +        self.target = self.dbg.GetSelectedTarget() +        self.process = self.target.LoadCore("regions-linux-map.dmp") +        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/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm-linux.dmp b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm-linux.dmp Binary files differnew file mode 100644 index 000000000000..3b0cb8268def --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm-linux.dmp diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm-macos.dmp b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm-macos.dmp Binary files differnew file mode 100644 index 000000000000..9ff6a8396ec5 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm-macos.dmp diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm64-macos.dmp b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm64-macos.dmp Binary files differnew file mode 100644 index 000000000000..ba658dd48feb --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm64-macos.dmp diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/regions-linux-map.dmp b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/regions-linux-map.dmp Binary files differnew file mode 100644 index 000000000000..3f1dd53d98fa --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/regions-linux-map.dmp diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py index 61e2adee41d5..fe13871ddac9 100644 --- a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py +++ b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py @@ -50,28 +50,28 @@ class MiniDumpTestCase(TestBase):          self.assertTrue(self.process, PROCESS_IS_VALID)          expected_modules = [              { -                'filename' : r"C:\Windows\System32/MSVCP120D.dll", -                'uuid' : '6E51053C-E757-EB40-8D3F-9722C5BD80DD-01000000', -            }, -            { -                'filename' : r"C:\Windows\SysWOW64/kernel32.dll", -                'uuid' : '1B7ECBE5-5E00-1341-AB98-98D6913B52D8-02000000', -            }, -            {                  'filename' : r"C:\Users\amccarth\Documents\Visual Studio 2013\Projects\fizzbuzz\Debug/fizzbuzz.exe",                  'uuid' : '91B7450F-969A-F946-BF8F-2D6076EA421A-11000000',              },              { -                'filename' : r"C:\Windows\System32/MSVCR120D.dll", -                'uuid' : '86FB8263-C446-4640-AE42-8D97B3F91FF2-01000000', +                'filename' : r"C:\Windows\SysWOW64/ntdll.dll", +                'uuid' : '6A84B0BB-2C40-5240-A16B-67650BBFE6B0-02000000', +            }, +            { +                'filename' : r"C:\Windows\SysWOW64/kernel32.dll", +                'uuid' : '1B7ECBE5-5E00-1341-AB98-98D6913B52D8-02000000',              },              {                  'filename' : r"C:\Windows\SysWOW64/KERNELBASE.dll",                  'uuid' : '4152F90B-0DCB-D44B-AC5D-186A6452E522-01000000',              },              { -                'filename' : r"C:\Windows\SysWOW64/ntdll.dll", -                'uuid' : '6A84B0BB-2C40-5240-A16B-67650BBFE6B0-02000000', +                'filename' : r"C:\Windows\System32/MSVCP120D.dll", +                'uuid' : '6E51053C-E757-EB40-8D3F-9722C5BD80DD-01000000', +            }, +            { +                'filename' : r"C:\Windows\System32/MSVCR120D.dll", +                'uuid' : '86FB8263-C446-4640-AE42-8D97B3F91FF2-01000000',              },          ]          self.assertEqual(self.target.GetNumModules(), len(expected_modules)) @@ -80,7 +80,6 @@ class MiniDumpTestCase(TestBase):              self.assertEqual(module.file.fullpath, expected['filename'])              self.assertEqual(module.GetUUIDString(), expected['uuid']) -    @expectedFailureAll(bugnumber="llvm.org/pr35193", hostoslist=["windows"])      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 diff --git a/packages/Python/lldbsuite/test/functionalities/process_attach/TestProcessAttach.py b/packages/Python/lldbsuite/test/functionalities/process_attach/TestProcessAttach.py index 617b4bcfaec3..f485c13fa9f1 100644 --- a/packages/Python/lldbsuite/test/functionalities/process_attach/TestProcessAttach.py +++ b/packages/Python/lldbsuite/test/functionalities/process_attach/TestProcessAttach.py @@ -23,7 +23,6 @@ class ProcessAttachTestCase(TestBase):      NO_DEBUG_INFO_TESTCASE = True      @skipIfiOSSimulator -    @expectedFailureAll(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], bugnumber="<rdar://problem/34538611>") # old lldb-server has race condition, launching an inferior and then launching debugserver in quick succession sometimes fails      def test_attach_to_process_by_id(self):          """Test attach by process id"""          self.build() @@ -40,7 +39,6 @@ class ProcessAttachTestCase(TestBase):          process = target.GetProcess()          self.assertTrue(process, PROCESS_IS_VALID) -    @expectedFailureAll(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], bugnumber="<rdar://problem/34538611>") # old lldb-server has race condition, launching an inferior and then launching debugserver in quick succession sometimes fails      def test_attach_to_process_from_different_dir_by_id(self):          """Test attach by process id"""          newdir = self.getBuildArtifact("newdir") @@ -67,7 +65,6 @@ class ProcessAttachTestCase(TestBase):          process = target.GetProcess()          self.assertTrue(process, PROCESS_IS_VALID) -    @expectedFailureAll(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], bugnumber="<rdar://problem/34538611>") # old lldb-server has race condition, launching an inferior and then launching debugserver in quick succession sometimes fails      def test_attach_to_process_by_name(self):          """Test attach by process name"""          self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/process_group/TestChangeProcessGroup.py b/packages/Python/lldbsuite/test/functionalities/process_group/TestChangeProcessGroup.py index 8496ce6c04d7..d3b153270119 100644 --- a/packages/Python/lldbsuite/test/functionalities/process_group/TestChangeProcessGroup.py +++ b/packages/Python/lldbsuite/test/functionalities/process_group/TestChangeProcessGroup.py @@ -24,7 +24,6 @@ class ChangeProcessGroupTestCase(TestBase):      @skipIfFreeBSD  # Times out on FreeBSD llvm.org/pr23731      @skipIfWindows  # setpgid call does not exist on Windows      @expectedFailureAndroid("http://llvm.org/pr23762", api_levels=[16]) -    @expectedFailureAll(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], bugnumber="<rdar://problem/34538611>") # old lldb-server has race condition, launching an inferior and then launching debugserver in quick succession sometimes fails      def test_setpgid(self):          self.build()          exe = self.getBuildArtifact("a.out") diff --git a/packages/Python/lldbsuite/test/functionalities/register/intel_avx/TestYMMRegister.py b/packages/Python/lldbsuite/test/functionalities/register/intel_avx/TestYMMRegister.py index d362e6a8ae3d..1919d4b1ac6d 100644 --- a/packages/Python/lldbsuite/test/functionalities/register/intel_avx/TestYMMRegister.py +++ b/packages/Python/lldbsuite/test/functionalities/register/intel_avx/TestYMMRegister.py @@ -21,7 +21,6 @@ class TestYMMRegister(TestBase):      @skipIfiOSSimulator      @skipIfTargetAndroid()      @skipIf(archs=no_match(['i386', 'x86_64'])) -    @expectedFailureAll(oslist=["linux"], bugnumber="rdar://30523153")      @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr37995")      def test(self):          self.build(dictionary={"CFLAGS_EXTRAS": "-march=haswell"}) diff --git a/packages/Python/lldbsuite/test/functionalities/show_location/TestShowLocationDwarf5.py b/packages/Python/lldbsuite/test/functionalities/show_location/TestShowLocationDwarf5.py new file mode 100644 index 000000000000..a56282efd77d --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/show_location/TestShowLocationDwarf5.py @@ -0,0 +1,34 @@ +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__) + +    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/packages/Python/lldbsuite/test/functionalities/show_location/a.yaml b/packages/Python/lldbsuite/test/functionalities/show_location/a.yaml new file mode 100644 index 000000000000..27b119d3df63 --- /dev/null +++ b/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/packages/Python/lldbsuite/test/functionalities/stats_api/TestStatisticsAPI.py b/packages/Python/lldbsuite/test/functionalities/stats_api/TestStatisticsAPI.py index a6c38ca1d091..f2027eb131c5 100644 --- a/packages/Python/lldbsuite/test/functionalities/stats_api/TestStatisticsAPI.py +++ b/packages/Python/lldbsuite/test/functionalities/stats_api/TestStatisticsAPI.py @@ -17,6 +17,15 @@ class TestStatsAPI(TestBase):          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) diff --git a/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/Makefile b/packages/Python/lldbsuite/test/functionalities/step_scripted/Makefile index 0d70f2595019..0d70f2595019 100644 --- a/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/Makefile +++ b/packages/Python/lldbsuite/test/functionalities/step_scripted/Makefile diff --git a/packages/Python/lldbsuite/test/functionalities/step_scripted/Steps.py b/packages/Python/lldbsuite/test/functionalities/step_scripted/Steps.py new file mode 100644 index 000000000000..1383a03f4647 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/step_scripted/Steps.py @@ -0,0 +1,37 @@ +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") diff --git a/packages/Python/lldbsuite/test/functionalities/step_scripted/TestStepScripted.py b/packages/Python/lldbsuite/test/functionalities/step_scripted/TestStepScripted.py new file mode 100644 index 000000000000..a111ede6739c --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/step_scripted/TestStepScripted.py @@ -0,0 +1,41 @@ +""" +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 test_standard_step_out(self): +        """Tests stepping with the scripted thread plan laying over a standard thread plan for stepping out.""" +        self.build() +        self.main_source_file = lldb.SBFileSpec("main.c") +        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.main_source_file = lldb.SBFileSpec("main.c") +        self.step_out_with_scripted_plan("Steps.StepScripted") + +    def setUp(self): +        TestBase.setUp(self) +        self.runCmd("command script import Steps.py") + +    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()) diff --git a/packages/Python/lldbsuite/test/functionalities/step_scripted/main.c b/packages/Python/lldbsuite/test/functionalities/step_scripted/main.c new file mode 100644 index 000000000000..88b3c17125db --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/step_scripted/main.c @@ -0,0 +1,10 @@ +#include <stdio.h> + +void foo() { +  printf("Set a breakpoint here.\n"); +} + +int main() { +  foo(); +  return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/stop-hook/TestStopHookCmd.py b/packages/Python/lldbsuite/test/functionalities/stop-hook/TestStopHookCmd.py deleted file mode 100644 index 767b368cc7dc..000000000000 --- a/packages/Python/lldbsuite/test/functionalities/stop-hook/TestStopHookCmd.py +++ /dev/null @@ -1,77 +0,0 @@ -""" -Test lldb target stop-hook command. -""" - -from __future__ import print_function - - -import os -import lldb -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil - - -class StopHookCmdTestCase(TestBase): - -    mydir = TestBase.compute_mydir(__file__) - -    def setUp(self): -        # Call super's setUp(). -        TestBase.setUp(self) -        # Find the line numbers inside main.cpp. -        self.begl = line_number( -            'main.cpp', -            '// Set breakpoint here to test target stop-hook.') -        self.endl = line_number( -            'main.cpp', -            '// End of the line range for which stop-hook is to be run.') -        self.line = line_number( -            'main.cpp', -            '// Another breakpoint which is outside of the stop-hook range.') - -    @no_debug_info_test -    def test_not_crashing_if_no_target(self): -        """target stop-hook list should not crash if no target has been set.""" -        self.runCmd("target stop-hook list", check=False) - -    def test(self): -        """Test a sequence of target stop-hook commands.""" -        self.build() -        exe = self.getBuildArtifact("a.out") -        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) - -        lldbutil.run_break_set_by_file_and_line( -            self, "main.cpp", self.begl, num_expected_locations=1, loc_exact=True) - -        lldbutil.run_break_set_by_file_and_line( -            self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) - -        self.runCmd( -            "target stop-hook add -f main.cpp -l %d -e %d -o 'expr ptr'" % -            (self.begl, self.endl)) - -        self.expect('target stop-hook list', 'Stop Hook added successfully', -                    substrs=['State: enabled', -                             'expr ptr']) - -        self.runCmd('target stop-hook disable') - -        self.expect('target stop-hook list', 'Stop Hook disabled successfully', -                    substrs=['State: disabled', -                             'expr ptr']) - -        self.runCmd('target stop-hook enable') - -        self.expect('target stop-hook list', 'Stop Hook enabled successfully', -                    substrs=['State: enabled', -                             'expr ptr']) - -        self.runCmd("settings set auto-confirm true") -        self.addTearDownHook( -            lambda: self.runCmd("settings clear auto-confirm")) - -        self.runCmd('target stop-hook delete') - -        self.expect('target stop-hook list', 'Stop Hook deleted successfully', -                    substrs=['No stop hooks.']) diff --git a/packages/Python/lldbsuite/test/functionalities/stop-hook/TestStopHookMechanism.py b/packages/Python/lldbsuite/test/functionalities/stop-hook/TestStopHookMechanism.py deleted file mode 100644 index b76d98a333c2..000000000000 --- a/packages/Python/lldbsuite/test/functionalities/stop-hook/TestStopHookMechanism.py +++ /dev/null @@ -1,128 +0,0 @@ -""" -Test lldb target stop-hook mechanism to see whether it fires off correctly . -""" - -from __future__ import print_function - - -import os -import lldb -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbtest import * -from lldbsuite.test import configuration -from lldbsuite.test import lldbutil - - -class StopHookMechanismTestCase(TestBase): - -    mydir = TestBase.compute_mydir(__file__) - -    def setUp(self): -        # Call super's setUp(). -        TestBase.setUp(self) -        # Find the line numbers inside main.cpp. -        self.begl = line_number( -            'main.cpp', -            '// Set breakpoint here to test target stop-hook.') -        self.endl = line_number( -            'main.cpp', -            '// End of the line range for which stop-hook is to be run.') -        self.correct_step_line = line_number( -            'main.cpp', '// We should stop here after stepping.') -        self.line = line_number( -            'main.cpp', -            '// Another breakpoint which is outside of the stop-hook range.') - -    @skipIfFreeBSD  # llvm.org/pr15037 -    # stop-hooks sometimes fail to fire on Linux -    @expectedFlakeyLinux('llvm.org/pr15037') -    @expectedFailureAll( -        hostoslist=["windows"], -        bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") -    @skipIf(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], archs=['armv7', 'armv7k'])  # <rdar://problem/34582291> problem with armv7 and step-over and stop-hook firing on ios etc systems -    def test(self): -        """Test the stop-hook mechanism.""" -        self.build() - -        import pexpect -        exe = self.getBuildArtifact("a.out") -        prompt = "(lldb) " -        add_prompt = "Enter your stop hook command(s).  Type 'DONE' to end." -        add_prompt1 = "> " - -        # So that the child gets torn down after the test. -        self.child = pexpect.spawn('%s %s' % -                                   (lldbtest_config.lldbExec, self.lldbOption)) -        child = self.child -        # Turn on logging for what the child sends back. -        if self.TraceOn(): -            child.logfile_read = sys.stdout - -        if lldb.remote_platform: -            child.expect_exact(prompt) -            child.sendline( -                'platform select %s' % -                lldb.remote_platform.GetName()) -            child.expect_exact(prompt) -            child.sendline( -                'platform connect %s' % -                configuration.lldb_platform_url) -            child.expect_exact(prompt) -            child.sendline( -                'platform settings -w %s' % -                configuration.lldb_platform_working_dir) - -        child.expect_exact(prompt) -        child.sendline('target create %s' % exe) - -        # Set the breakpoint, followed by the target stop-hook commands. -        child.expect_exact(prompt) -        child.sendline('breakpoint set -f main.cpp -l %d' % self.begl) -        child.expect_exact(prompt) -        child.sendline('breakpoint set -f main.cpp -l %d' % self.line) -        child.expect_exact(prompt) -        child.sendline( -            'target stop-hook add -f main.cpp -l %d -e %d' % -            (self.begl, self.endl)) -        child.expect_exact(add_prompt) -        child.expect_exact(add_prompt1) -        child.sendline('expr ptr') -        child.expect_exact(add_prompt1) -        child.sendline('DONE') -        child.expect_exact(prompt) -        child.sendline('target stop-hook list') - -        # Now run the program, expect to stop at the first breakpoint which is -        # within the stop-hook range. -        child.expect_exact(prompt) -        child.sendline('run') -        # Make sure we see the stop hook text from the stop of the process from -        # the run hitting the first breakpoint -        child.expect_exact('(void *) $') -        child.expect_exact(prompt) -        child.sendline('thread step-over') -        # Expecting to find the output emitted by the firing of our stop hook. -        child.expect_exact('(void *) $') -        # This is orthogonal to the main stop hook test, but this example shows a bug in -        # CLANG where the line table entry for the "return -1" actually includes some code -        # from the other branch of the if/else, so we incorrectly stop at the "return -1" line. -        # I fixed that in lldb and I'm sticking in a test here because I don't want to have to -        # make up a whole nother test case for it. -        child.sendline('frame info') -        at_line = 'at main.cpp:%d' % (self.correct_step_line) -        print('expecting "%s"' % at_line) -        child.expect_exact(at_line) - -        # Now continue the inferior, we'll stop at another breakpoint which is -        # outside the stop-hook range. -        child.sendline('process continue') -        child.expect_exact( -            '// Another breakpoint which is outside of the stop-hook range.') -        # self.DebugPExpect(child) -        child.sendline('thread step-over') -        child.expect_exact( -            '// Another breakpoint which is outside of the stop-hook range.') -        # self.DebugPExpect(child) -        # Verify that the 'Stop Hooks' mechanism is NOT BEING fired off. -        self.expect(child.before, exe=False, matching=False, -                    substrs=['(void *) $']) diff --git a/packages/Python/lldbsuite/test/functionalities/stop-hook/main.cpp b/packages/Python/lldbsuite/test/functionalities/stop-hook/main.cpp deleted file mode 100644 index c10c1e5ef0d2..000000000000 --- a/packages/Python/lldbsuite/test/functionalities/stop-hook/main.cpp +++ /dev/null @@ -1,54 +0,0 @@ -//===-- main.c --------------------------------------------------*- C++ -*-===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -#include <stdio.h> -#include <stdlib.h> - -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); - -    return val; -} - -int b(int val) -{ -    int rc = c(val); -    void *ptr = malloc(1024); -    if (!ptr)  // Set breakpoint here to test target stop-hook. -        return -1; -    else -        printf("ptr=%p\n", ptr); // We should stop here after stepping. -    return rc; // End of the line range for which stop-hook is to be run. -} - -int c(int val) -{ -    return val + 3; -} - -int main (int argc, char const *argv[]) -{ -    int A1 = a(1); -    printf("a(1) returns %d\n", A1); -     -    int C2 = c(2); // Another breakpoint which is outside of the stop-hook range. -    printf("c(2) returns %d\n", C2); -     -    int A3 = a(3); -    printf("a(3) returns %d\n", A3); -     -    return 0; -} diff --git a/packages/Python/lldbsuite/test/functionalities/stop-hook/multiple_threads/TestStopHookMultipleThreads.py b/packages/Python/lldbsuite/test/functionalities/stop-hook/multiple_threads/TestStopHookMultipleThreads.py deleted file mode 100644 index 88267b60b978..000000000000 --- a/packages/Python/lldbsuite/test/functionalities/stop-hook/multiple_threads/TestStopHookMultipleThreads.py +++ /dev/null @@ -1,100 +0,0 @@ -""" -Test that lldb stop-hook works for multiple threads. -""" - -from __future__ import print_function - - -import os -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 StopHookForMultipleThreadsTestCase(TestBase): - -    mydir = TestBase.compute_mydir(__file__) - -    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, '// Set break point at this line, and add a stop-hook.') -        self.thread_function = line_number( -            self.source, -            '// Break here to test that the stop-hook mechanism works for multiple threads.') -        # Build dictionary to have unique executable names for each test -        # method. -        self.exe_name = self.testMethodName -        self.d = {'CXX_SOURCES': self.source, 'EXE': self.exe_name} - -    @expectedFlakeyFreeBSD("llvm.org/pr15037") -    # stop hooks sometimes fail to fire on Linux -    @expectedFlakeyLinux("llvm.org/pr15037") -    @expectedFailureAll( -        hostoslist=["windows"], -        bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") -    def test_stop_hook_multiple_threads(self): -        """Test that lldb stop-hook works for multiple threads.""" -        self.build(dictionary=self.d) -        self.setTearDownCleanup(dictionary=self.d) - -        import pexpect -        exe = self.getBuildArtifact(self.exe_name) -        prompt = "(lldb) " - -        # So that the child gets torn down after the test. -        self.child = pexpect.spawn('%s %s' % -                                   (lldbtest_config.lldbExec, self.lldbOption)) -        child = self.child -        # Turn on logging for what the child sends back. -        if self.TraceOn(): -            child.logfile_read = sys.stdout - -        if lldb.remote_platform: -            child.expect_exact(prompt) -            child.sendline( -                'platform select %s' % -                lldb.remote_platform.GetName()) -            child.expect_exact(prompt) -            child.sendline( -                'platform connect %s' % -                configuration.lldb_platform_url) -            child.expect_exact(prompt) -            child.sendline( -                'platform settings -w %s' % -                configuration.lldb_platform_working_dir) - -        child.expect_exact(prompt) -        child.sendline('target create %s' % exe) - -        # Set the breakpoint, followed by the target stop-hook commands. -        child.expect_exact(prompt) -        child.sendline('breakpoint set -f main.cpp -l %d' % self.first_stop) -        child.expect_exact(prompt) -        child.sendline( -            'breakpoint set -f main.cpp -l %d' % -            self.thread_function) -        child.expect_exact(prompt) - -        # Now run the program, expect to stop at the first breakpoint which is -        # within the stop-hook range. -        child.sendline('run') -        # 'Process 2415 launched', 'Process 2415 stopped' -        child.expect_exact("Process") -        child.expect_exact(prompt) -        child.sendline( -            'target stop-hook add -o "frame variable --show-globals g_val"') -        child.expect_exact("Stop hook")  # 'Stop hook #1 added.' -        child.expect_exact(prompt) - -        # Continue and expect to find the output emitted by the firing of our -        # stop hook. -        child.sendline('continue') -        child.expect_exact('(uint32_t) ::g_val = ') diff --git a/packages/Python/lldbsuite/test/functionalities/stop-hook/multiple_threads/main.cpp b/packages/Python/lldbsuite/test/functionalities/stop-hook/multiple_threads/main.cpp deleted file mode 100644 index e193ae18e2c1..000000000000 --- a/packages/Python/lldbsuite/test/functionalities/stop-hook/multiple_threads/main.cpp +++ /dev/null @@ -1,77 +0,0 @@ -//===-- main.cpp ------------------------------------------------*- C++ -*-===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include <chrono> -#include <cstdio> -#include <mutex> -#include <random> -#include <thread> - -std::default_random_engine g_random_engine{std::random_device{}()}; -std::uniform_int_distribution<> g_distribution{0, 3000000}; - -uint32_t g_val = 0; - -uint32_t -access_pool (bool flag = false) -{ -    static std::mutex g_access_mutex; -    if (!flag) -        g_access_mutex.lock(); - -    uint32_t old_val = g_val; -    if (flag) -        g_val = old_val + 1; - -    if (!flag) -        g_access_mutex.unlock(); -    return g_val; -} - -void -thread_func (uint32_t thread_index) -{ -    // Break here to test that the stop-hook mechanism works for multiple threads. -    printf ("%s (thread index = %u) startng...\n", __FUNCTION__, thread_index); - -    uint32_t count = 0; -    uint32_t val; -    while (count++ < 15) -    { -        // random micro second sleep from zero to 3 seconds -        int usec = g_distribution(g_random_engine); -        printf ("%s (thread = %u) doing a usleep (%d)...\n", __FUNCTION__, thread_index, usec); -        std::this_thread::sleep_for(std::chrono::microseconds{usec}); - -        if (count < 7) -            val = access_pool (); -        else -            val = access_pool (true); - -        printf ("%s (thread = %u) after usleep access_pool returns %d (count=%d)...\n", __FUNCTION__, thread_index, val, count); -    } -    printf ("%s (thread index = %u) exiting...\n", __FUNCTION__, thread_index); -} - - -int main (int argc, char const *argv[]) -{ -    std::thread threads[3]; - -    printf ("Before turning all three threads loose...\n"); // Set break point at this line, and add a stop-hook. -    // Create 3 threads -    for (auto &thread : threads) -        thread = std::thread{thread_func, std::distance(threads, &thread)}; - -    // Join all of our threads -    for (auto &thread : threads) -        thread.join(); - -    return 0; -} diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/Makefile b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/Makefile new file mode 100644 index 000000000000..15bc2e7f415b --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/Makefile @@ -0,0 +1,4 @@ +LEVEL = ../../../make +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules +CXXFLAGS += -g -O1 -glldb diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/TestAmbiguousTailCallSeq1.py b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/TestAmbiguousTailCallSeq1.py new file mode 100644 index 000000000000..aec4d503fd73 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/TestAmbiguousTailCallSeq1.py @@ -0,0 +1,5 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), +        [decorators.skipUnlessHasCallSiteInfo]) diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/main.cpp b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/main.cpp new file mode 100644 index 000000000000..48190184be10 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/main.cpp @@ -0,0 +1,33 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +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/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/Makefile b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/Makefile new file mode 100644 index 000000000000..15bc2e7f415b --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/Makefile @@ -0,0 +1,4 @@ +LEVEL = ../../../make +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules +CXXFLAGS += -g -O1 -glldb diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/TestAmbiguousTailCallSeq2.py b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/TestAmbiguousTailCallSeq2.py new file mode 100644 index 000000000000..aec4d503fd73 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/TestAmbiguousTailCallSeq2.py @@ -0,0 +1,5 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), +        [decorators.skipUnlessHasCallSiteInfo]) diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/main.cpp b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/main.cpp new file mode 100644 index 000000000000..1651db2ea4a1 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/main.cpp @@ -0,0 +1,38 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +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/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/Makefile b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/Makefile new file mode 100644 index 000000000000..15bc2e7f415b --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/Makefile @@ -0,0 +1,4 @@ +LEVEL = ../../../make +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules +CXXFLAGS += -g -O1 -glldb diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/TestDisambiguateCallSite.py b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/TestDisambiguateCallSite.py new file mode 100644 index 000000000000..aec4d503fd73 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/TestDisambiguateCallSite.py @@ -0,0 +1,5 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), +        [decorators.skipUnlessHasCallSiteInfo]) diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/main.cpp b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/main.cpp new file mode 100644 index 000000000000..d3aef19f7a4f --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/main.cpp @@ -0,0 +1,32 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +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/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/Makefile b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/Makefile new file mode 100644 index 000000000000..15bc2e7f415b --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/Makefile @@ -0,0 +1,4 @@ +LEVEL = ../../../make +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules +CXXFLAGS += -g -O1 -glldb diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/TestDisambiguatePathsToCommonSink.py b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/TestDisambiguatePathsToCommonSink.py new file mode 100644 index 000000000000..aec4d503fd73 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/TestDisambiguatePathsToCommonSink.py @@ -0,0 +1,5 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), +        [decorators.skipUnlessHasCallSiteInfo]) diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/main.cpp b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/main.cpp new file mode 100644 index 000000000000..5189218c4ef4 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/main.cpp @@ -0,0 +1,38 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +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/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/Makefile b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/Makefile new file mode 100644 index 000000000000..15bc2e7f415b --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/Makefile @@ -0,0 +1,4 @@ +LEVEL = ../../../make +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules +CXXFLAGS += -g -O1 -glldb diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/TestDisambiguateTailCallSeq.py b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/TestDisambiguateTailCallSeq.py new file mode 100644 index 000000000000..aec4d503fd73 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/TestDisambiguateTailCallSeq.py @@ -0,0 +1,5 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), +        [decorators.skipUnlessHasCallSiteInfo]) diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/main.cpp b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/main.cpp new file mode 100644 index 000000000000..3c723b8a3ee3 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/main.cpp @@ -0,0 +1,31 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +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/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/Makefile b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/Makefile new file mode 100644 index 000000000000..15bc2e7f415b --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/Makefile @@ -0,0 +1,4 @@ +LEVEL = ../../../make +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules +CXXFLAGS += -g -O1 -glldb diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/TestInliningAndTailCalls.py b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/TestInliningAndTailCalls.py new file mode 100644 index 000000000000..aec4d503fd73 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/TestInliningAndTailCalls.py @@ -0,0 +1,5 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), +        [decorators.skipUnlessHasCallSiteInfo]) diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/main.cpp b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/main.cpp new file mode 100644 index 000000000000..e4504ad151fa --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/main.cpp @@ -0,0 +1,50 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +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/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/Makefile b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/Makefile new file mode 100644 index 000000000000..15bc2e7f415b --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/Makefile @@ -0,0 +1,4 @@ +LEVEL = ../../../make +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules +CXXFLAGS += -g -O1 -glldb diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/TestTailCallFrameSBAPI.py b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/TestTailCallFrameSBAPI.py new file mode 100644 index 000000000000..038a0c45bf42 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/TestTailCallFrameSBAPI.py @@ -0,0 +1,73 @@ +""" +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__) + +    # 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 + +    @skipIf(compiler="clang", compiler_version=['<', '7.0']) +    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr26265") +    def test_tail_call_frame_sbapi(self): +        self.build() +        self.do_test() + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) + +    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/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/main.cpp b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/main.cpp new file mode 100644 index 000000000000..f9e84da51739 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/main.cpp @@ -0,0 +1,25 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +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/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/Makefile b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/Makefile new file mode 100644 index 000000000000..15bc2e7f415b --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/Makefile @@ -0,0 +1,4 @@ +LEVEL = ../../../make +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules +CXXFLAGS += -g -O1 -glldb diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/TestArtificialFrameStepOutMessage.py b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/TestArtificialFrameStepOutMessage.py new file mode 100644 index 000000000000..aec4d503fd73 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/TestArtificialFrameStepOutMessage.py @@ -0,0 +1,5 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), +        [decorators.skipUnlessHasCallSiteInfo]) diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/main.cpp b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/main.cpp new file mode 100644 index 000000000000..f2f11365df7a --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/main.cpp @@ -0,0 +1,28 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +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/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/Makefile b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/Makefile new file mode 100644 index 000000000000..15bc2e7f415b --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/Makefile @@ -0,0 +1,4 @@ +LEVEL = ../../../make +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules +CXXFLAGS += -g -O1 -glldb diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/TestSteppingOutWithArtificialFrames.py b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/TestSteppingOutWithArtificialFrames.py new file mode 100644 index 000000000000..2b432e56a740 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/TestSteppingOutWithArtificialFrames.py @@ -0,0 +1,95 @@ +""" +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()) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/main.cpp b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/main.cpp new file mode 100644 index 000000000000..f7a81873906e --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/main.cpp @@ -0,0 +1,25 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +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/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/Makefile b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/Makefile new file mode 100644 index 000000000000..15bc2e7f415b --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/Makefile @@ -0,0 +1,4 @@ +LEVEL = ../../../make +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules +CXXFLAGS += -g -O1 -glldb diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/TestUnambiguousTailCalls.py b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/TestUnambiguousTailCalls.py new file mode 100644 index 000000000000..aec4d503fd73 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/TestUnambiguousTailCalls.py @@ -0,0 +1,5 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), +        [decorators.skipUnlessHasCallSiteInfo]) diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/main.cpp b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/main.cpp new file mode 100644 index 000000000000..c180d45b9de6 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/main.cpp @@ -0,0 +1,30 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +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/packages/Python/lldbsuite/test/functionalities/target_create_deps/Makefile b/packages/Python/lldbsuite/test/functionalities/target_create_deps/Makefile new file mode 100644 index 000000000000..15cb0b64f218 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/target_create_deps/Makefile @@ -0,0 +1,16 @@ +LEVEL := ../../make + +LIB_PREFIX := load_ + +LD_EXTRAS := -L. -l$(LIB_PREFIX)a +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules + +a.out: lib_a + +lib_%: +	$(MAKE) VPATH=$(SRCDIR) -I $(SRCDIR) -f $(SRCDIR)/$*.mk + +clean:: +	$(MAKE) -f $(SRCDIR)/a.mk clean diff --git a/packages/Python/lldbsuite/test/functionalities/target_create_deps/TestTargetCreateDeps.py b/packages/Python/lldbsuite/test/functionalities/target_create_deps/TestTargetCreateDeps.py new file mode 100644 index 000000000000..a6c383ce3c80 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/target_create_deps/TestTargetCreateDeps.py @@ -0,0 +1,100 @@ +""" +Test that loading of dependents works correctly for all the potential +combinations. +""" + +from __future__ import print_function + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +@skipIfWindows # Windows deals differently with shared libs. +class TargetDependentsTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    NO_DEBUG_INFO_TESTCASE = True + +    def setUp(self): +        TestBase.setUp(self) +        self.build() + +    def has_exactly_one_image(self, matching, msg=""): +        self.expect( +            "image list", +            "image list should contain at least one image", +            substrs=['[  0]']) +        should_match = not matching +        self.expect( +            "image list", msg, matching=should_match, substrs=['[  1]']) + +    @expectedFailureAll(oslist=["linux"]) #linux does not support loading dependent files +    def test_dependents_implicit_default_exe(self): +        """Test default behavior""" +        exe = self.getBuildArtifact("a.out") +        self.runCmd("target create  " + exe, CURRENT_EXECUTABLE_SET) +        self.has_exactly_one_image(False) + +    @expectedFailureAll(oslist=["linux"]) #linux does not support loading dependent files +    def test_dependents_explicit_default_exe(self): +        """Test default behavior""" +        exe = self.getBuildArtifact("a.out") +        self.runCmd("target create -ddefault " + exe, CURRENT_EXECUTABLE_SET) +        self.has_exactly_one_image(False) + +    def test_dependents_explicit_true_exe(self): +        """Test default behavior""" +        exe = self.getBuildArtifact("a.out") +        self.runCmd("target create -dtrue " + exe, CURRENT_EXECUTABLE_SET) +        self.has_exactly_one_image(True) + +    @expectedFailureAll(oslist=["linux"]) #linux does not support loading dependent files +    def test_dependents_explicit_false_exe(self): +        """Test default behavior""" +        exe = self.getBuildArtifact("a.out") +        self.runCmd("target create -dfalse " + exe, CURRENT_EXECUTABLE_SET) +        self.has_exactly_one_image(False) + +    def test_dependents_implicit_false_exe(self): +        """Test default behavior""" +        exe = self.getBuildArtifact("a.out") +        self.runCmd("target create  -d " + exe, CURRENT_EXECUTABLE_SET) +        self.has_exactly_one_image(True) + +    def test_dependents_implicit_default_lib(self): +        ctx = self.platformContext +        dylibName = ctx.shlib_prefix + 'load_a.' + ctx.shlib_extension +        lib = self.getBuildArtifact(dylibName) +        self.runCmd("target create " + lib, CURRENT_EXECUTABLE_SET) +        self.has_exactly_one_image(True) + +    def test_dependents_explicit_default_lib(self): +        ctx = self.platformContext +        dylibName = ctx.shlib_prefix + 'load_a.' + ctx.shlib_extension +        lib = self.getBuildArtifact(dylibName) +        self.runCmd("target create -ddefault " + lib, CURRENT_EXECUTABLE_SET) +        self.has_exactly_one_image(True) + +    def test_dependents_explicit_true_lib(self): +        ctx = self.platformContext +        dylibName = ctx.shlib_prefix + 'load_a.' + ctx.shlib_extension +        lib = self.getBuildArtifact(dylibName) +        self.runCmd("target create -dtrue " + lib, CURRENT_EXECUTABLE_SET) +        self.has_exactly_one_image(True) + +    @expectedFailureAll(oslist=["linux"]) #linux does not support loading dependent files +    def test_dependents_explicit_false_lib(self): +        ctx = self.platformContext +        dylibName = ctx.shlib_prefix + 'load_a.' + ctx.shlib_extension +        lib = self.getBuildArtifact(dylibName) +        self.runCmd("target create -dfalse " + lib, CURRENT_EXECUTABLE_SET) +        self.has_exactly_one_image(False) + +    def test_dependents_implicit_false_lib(self): +        ctx = self.platformContext +        dylibName = ctx.shlib_prefix + 'load_a.' + ctx.shlib_extension +        lib = self.getBuildArtifact(dylibName) +        self.runCmd("target create -d " + lib, CURRENT_EXECUTABLE_SET) +        self.has_exactly_one_image(True) diff --git a/packages/Python/lldbsuite/test/functionalities/target_create_deps/a.cpp b/packages/Python/lldbsuite/test/functionalities/target_create_deps/a.cpp new file mode 100644 index 000000000000..c0dac40d0eed --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/target_create_deps/a.cpp @@ -0,0 +1,13 @@ +//===-- b.c -----------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +int a_function () +{ +    return 500; +} diff --git a/packages/Python/lldbsuite/test/functionalities/target_create_deps/a.mk b/packages/Python/lldbsuite/test/functionalities/target_create_deps/a.mk new file mode 100644 index 000000000000..f199bfed5b0d --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/target_create_deps/a.mk @@ -0,0 +1,9 @@ +LEVEL := ../../make + +LIB_PREFIX := load_ + +DYLIB_NAME := $(LIB_PREFIX)a +DYLIB_CXX_SOURCES := a.cpp +DYLIB_ONLY := YES + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/target_create_deps/main.cpp b/packages/Python/lldbsuite/test/functionalities/target_create_deps/main.cpp new file mode 100644 index 000000000000..08fbb59d8a58 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/target_create_deps/main.cpp @@ -0,0 +1,17 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +extern int a_function (); +extern int b_function (); + +int +main (int argc, char const *argv[]) +{ +    return a_function(); +} diff --git a/packages/Python/lldbsuite/test/functionalities/target_var/Makefile b/packages/Python/lldbsuite/test/functionalities/target_var/Makefile new file mode 100644 index 000000000000..bb9cc4f2f66d --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/target_var/Makefile @@ -0,0 +1,10 @@ +LEVEL = ../../make + +include $(LEVEL)/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/packages/Python/lldbsuite/test/functionalities/target_var/TestTargetVar.py b/packages/Python/lldbsuite/test/functionalities/target_var/TestTargetVar.py new file mode 100644 index 000000000000..d3afacca72f5 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/target_var/TestTargetVar.py @@ -0,0 +1,23 @@ +""" +Test that target var can resolve complex DWARF expressions. +""" + +import lldb +import sys +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/packages/Python/lldbsuite/test/functionalities/target_var/globals.c b/packages/Python/lldbsuite/test/functionalities/target_var/globals.c new file mode 100644 index 000000000000..266192849641 --- /dev/null +++ b/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/packages/Python/lldbsuite/test/functionalities/target_var/globals.ll b/packages/Python/lldbsuite/test/functionalities/target_var/globals.ll new file mode 100644 index 000000000000..192d4e126981 --- /dev/null +++ b/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/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/Makefile b/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/Makefile new file mode 100644 index 000000000000..f0bcf9752de2 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +CXXFLAGS += -std=c++11 +CXX_SOURCES := main.cpp +ENABLE_THREADS := YES +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/TestBacktraceLimit.py b/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/TestBacktraceLimit.py new file mode 100644 index 000000000000..4e595ea4c5f6 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/TestBacktraceLimit.py @@ -0,0 +1,31 @@ +""" +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 setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) + +    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/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/main.cpp b/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/main.cpp new file mode 100644 index 000000000000..eca1eadc8e45 --- /dev/null +++ b/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/packages/Python/lldbsuite/test/functionalities/thread/crash_during_step/TestCrashDuringStep.py b/packages/Python/lldbsuite/test/functionalities/thread/crash_during_step/TestCrashDuringStep.py index b20b738825a2..fa96db06a59d 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/crash_during_step/TestCrashDuringStep.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/crash_during_step/TestCrashDuringStep.py @@ -20,7 +20,6 @@ class CrashDuringStepTestCase(TestBase):          TestBase.setUp(self)          self.breakpoint = line_number('main.cpp', '// Set breakpoint here') -    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")      # IO error due to breakpoint at invalid address      @expectedFailureAll(triple=re.compile('^mips'))      def test_step_inst_with(self): diff --git a/packages/Python/lldbsuite/test/functionalities/thread/create_after_attach/TestCreateAfterAttach.py b/packages/Python/lldbsuite/test/functionalities/thread/create_after_attach/TestCreateAfterAttach.py index 3f26d8c76579..2afa77d34b5e 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/create_after_attach/TestCreateAfterAttach.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/create_after_attach/TestCreateAfterAttach.py @@ -23,7 +23,6 @@ class CreateAfterAttachTestCase(TestBase):      # Occasionally hangs on Windows, may be same as other issues.      @skipIfWindows      @skipIfiOSSimulator -    @expectedFailureAll(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], bugnumber="<rdar://problem/34538611>") # old lldb-server has race condition, launching an inferior and then launching debugserver in quick succession sometimes fails      def test_create_after_attach_with_popen(self):          """Test thread creation after process attach."""          self.build(dictionary=self.getBuildFlags(use_cpp11=False)) @@ -34,7 +33,6 @@ class CreateAfterAttachTestCase(TestBase):      @skipIfRemote      @skipIfWindows  # Windows doesn't have fork.      @skipIfiOSSimulator -    @expectedFailureAll(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], bugnumber="<rdar://problem/34538611>") # old lldb-server has race condition, launching an inferior and then launching debugserver in quick succession sometimes fails      def test_create_after_attach_with_fork(self):          """Test thread creation after process attach."""          self.build(dictionary=self.getBuildFlags(use_cpp11=False)) diff --git a/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/TestExitDuringBreak.py b/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/TestExitDuringBreak.py index c62990ccc93a..76c2c47da2cf 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/TestExitDuringBreak.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/TestExitDuringBreak.py @@ -23,9 +23,6 @@ class ExitDuringBreakpointTestCase(TestBase):          # 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")      def test(self):          """Test thread exit during breakpoint handling."""          self.build(dictionary=self.getBuildFlags()) diff --git a/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/TestExitDuringStep.py b/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/TestExitDuringStep.py index 0343a888a0f1..76488a7185de 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/TestExitDuringStep.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/TestExitDuringStep.py @@ -18,6 +18,7 @@ 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()) @@ -27,6 +28,7 @@ class ExitDuringStepTestCase(TestBase):              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()) @@ -36,6 +38,7 @@ class ExitDuringStepTestCase(TestBase):              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()) diff --git a/packages/Python/lldbsuite/test/functionalities/thread/jump/TestThreadJump.py b/packages/Python/lldbsuite/test/functionalities/thread/jump/TestThreadJump.py index 3300078e8c60..7194dafe0ac1 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/jump/TestThreadJump.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/jump/TestThreadJump.py @@ -17,7 +17,6 @@ class ThreadJumpTestCase(TestBase):      mydir = TestBase.compute_mydir(__file__) -    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr32343")      def test(self):          """Test thread jump handling."""          self.build(dictionary=self.getBuildFlags()) diff --git a/packages/Python/lldbsuite/test/functionalities/thread/multi_break/TestMultipleBreakpoints.py b/packages/Python/lldbsuite/test/functionalities/thread/multi_break/TestMultipleBreakpoints.py index cff9b5a8d5e5..3d7e26816f84 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/multi_break/TestMultipleBreakpoints.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/multi_break/TestMultipleBreakpoints.py @@ -32,9 +32,7 @@ class MultipleBreakpointTestCase(TestBase):      @expectedFailureAll(          oslist=["freebsd"],          bugnumber="llvm.org/pr18190 thread states not properly maintained") -    @expectedFailureAll( -        oslist=["windows"], -        bugnumber="llvm.org/pr24668: Breakpoints not resolved correctly") +    @skipIfWindows # This is flakey on Windows: llvm.org/pr24668, llvm.org/pr38373      def test(self):          """Test simultaneous breakpoints in multiple threads."""          self.build(dictionary=self.getBuildFlags()) diff --git a/packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py b/packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py index 724b9d8be907..9aa4a831a745 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py @@ -64,7 +64,7 @@ class NumberOfThreadsTestCase(TestBase):              'Number of expected threads and actual threads do not match.')      @skipIfDarwin # rdar://33462362 -    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr37658") +    @skipIfWindows # This is flakey on Windows: llvm.org/pr37658, llvm.org/pr38373      def test_unique_stacks(self):          """Test backtrace unique with multiple threads executing the same stack."""          self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/thread/state/TestThreadStates.py b/packages/Python/lldbsuite/test/functionalities/thread/state/TestThreadStates.py index 0cbd94e199dc..4b1247316e18 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/state/TestThreadStates.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/state/TestThreadStates.py @@ -52,17 +52,6 @@ class ThreadStateTestCase(TestBase):          self.thread_state_after_expression_test()      # thread states not properly maintained -    @unittest2.expectedFailure("llvm.org/pr16712") -    @expectedFailureAll( -        oslist=["windows"], -        bugnumber="llvm.org/pr24668: Breakpoints not resolved correctly") -    @skipIfDarwin # llvm.org/pr15824 thread states not properly maintained and <rdar://problem/28557237> -    def test_process_interrupt(self): -        """Test process interrupt.""" -        self.build(dictionary=self.getBuildFlags(use_cpp11=False)) -        self.process_interrupt_test() - -    # thread states not properly maintained      @unittest2.expectedFailure("llvm.org/pr15824 and <rdar://problem/28557237>")      @expectedFailureAll(          oslist=["windows"], @@ -198,13 +187,19 @@ class ThreadStateTestCase(TestBase):          # Let the process run to completion          self.runCmd("process continue") -    def process_interrupt_test(self): +    @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. -        lldbutil.run_break_set_by_file_and_line( +        bpno = lldbutil.run_break_set_by_file_and_line(              self, "main.cpp", self.break_1, num_expected_locations=1)          # Run the program. @@ -218,6 +213,10 @@ class ThreadStateTestCase(TestBase):              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) diff --git a/packages/Python/lldbsuite/test/functionalities/thread/step_out/TestThreadStepOut.py b/packages/Python/lldbsuite/test/functionalities/thread/step_out/TestThreadStepOut.py index 238b18837884..e786e8d7ff1e 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/step_out/TestThreadStepOut.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/step_out/TestThreadStepOut.py @@ -25,6 +25,7 @@ class ThreadStepOutTestCase(TestBase):      @expectedFailureAll(          oslist=["freebsd"],          bugnumber="llvm.org/pr18066 inferior does not exit") +    @skipIfWindows # This test will hang on windows llvm.org/pr21753      @expectedFailureAll(oslist=["windows"])      def test_step_single_thread(self):          """Test thread step out on one thread via command interpreter. """ @@ -39,6 +40,7 @@ class ThreadStepOutTestCase(TestBase):      @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      def test_step_all_threads(self): @@ -54,6 +56,7 @@ class ThreadStepOutTestCase(TestBase):      @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")      def test_python(self):          """Test thread step out on one thread via Python API (dwarf).""" diff --git a/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/TestThreadExit.py b/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/TestThreadExit.py index 07ceb3f5f6b7..c8b6e675b8a9 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/TestThreadExit.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/TestThreadExit.py @@ -8,6 +8,7 @@ from __future__ import print_function  import os  import time  import lldb +from lldbsuite.test.decorators import *  from lldbsuite.test.lldbtest import *  import lldbsuite.test.lldbutil as lldbutil @@ -25,6 +26,7 @@ class ThreadExitTestCase(TestBase):          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()) diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_hits/TestMultipleHits.py b/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_hits/TestMultipleHits.py index 7302f76c1fbc..a6d77924892b 100644 --- a/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_hits/TestMultipleHits.py +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_hits/TestMultipleHits.py @@ -22,6 +22,7 @@ class MultipleHitsTestCase(TestBase):          oslist=["windows"],          bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")      @skipIf(bugnumber="llvm.org/pr30758", oslist=["linux"], archs=["arm", "aarch64", "powerpc64le"]) +    @skipIfwatchOS      def test(self):          self.build()          exe = self.getBuildArtifact("a.out") diff --git a/packages/Python/lldbsuite/test/help/TestHelp.py b/packages/Python/lldbsuite/test/help/TestHelp.py index 2b89b49a6229..7d66b08b86a2 100644 --- a/packages/Python/lldbsuite/test/help/TestHelp.py +++ b/packages/Python/lldbsuite/test/help/TestHelp.py @@ -231,6 +231,17 @@ class HelpCommandTestCase(TestBase):          self.expect("help averyfriendlyalias", matching=True,                      substrs=['I am a very friendly alias'])      @no_debug_info_test +    def test_alias_prints_origin(self): +        """Test that 'help <unique_match_to_alias>' prints the alias origin.""" +        def cleanup(): +            self.runCmd('command unalias alongaliasname', check=False) + +        self.addTearDownHook(cleanup) +        self.runCmd('command alias alongaliasname help') +        self.expect("help alongaliasna", matching=True, +                    substrs=["'alongaliasna' is an abbreviation for 'help'"]) + +    @no_debug_info_test      def test_help_format_output(self):          """Test that help output reaches TerminalWidth."""          self.runCmd( diff --git a/packages/Python/lldbsuite/test/lang/c/anonymous/TestAnonymous.py b/packages/Python/lldbsuite/test/lang/c/anonymous/TestAnonymous.py index 930a09412eab..e3ae93d3a5ba 100644 --- a/packages/Python/lldbsuite/test/lang/c/anonymous/TestAnonymous.py +++ b/packages/Python/lldbsuite/test/lang/c/anonymous/TestAnonymous.py @@ -70,7 +70,6 @@ class AnonymousTestCase(TestBase):          self.expect("expression z.y", VARIABLES_DISPLAYED_CORRECTLY,                      substrs=["(type_y) $", "dummy = 2"]) -    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21550")      def test_expr_null(self):          self.build()          self.common_setup(self.line2) diff --git a/packages/Python/lldbsuite/test/lang/c/bitfields/TestBitfields.py b/packages/Python/lldbsuite/test/lang/c/bitfields/TestBitfields.py index 22b8a2991001..ba924683ad75 100644 --- a/packages/Python/lldbsuite/test/lang/c/bitfields/TestBitfields.py +++ b/packages/Python/lldbsuite/test/lang/c/bitfields/TestBitfields.py @@ -116,6 +116,38 @@ class BitfieldsTestCase(TestBase):          self.expect("expr/x (packed.c)", VARIABLES_DISPLAYED_CORRECTLY,                      substrs=['uint32_t', "7112233"]) +        for bit in range(1,18): +            expected = "1" if bit in [1, 5, 7, 13] else "0" +            self.expect("expr even_more_bits.b" + str(bit), VARIABLES_DISPLAYED_CORRECTLY, +                    substrs=['uint8_t', expected]) + +        for bit in [3, 10, 14]: +            self.expect("expr even_more_bits.b" + str(bit) + " = 1", VARIABLES_DISPLAYED_CORRECTLY, +                    substrs=['uint8_t', "1"]) + +        self.expect( +            "frame variable --show-types even_more_bits", +            VARIABLES_DISPLAYED_CORRECTLY, +            substrs=[ +                '(uint8_t:1) b1 = \'\\x01\'', +                '(uint8_t:1) b2 = \'\\0\'', +                '(uint8_t:1) b3 = \'\\x01\'', +                '(uint8_t:1) b4 = \'\\0\'', +                '(uint8_t:1) b5 = \'\\x01\'', +                '(uint8_t:1) b6 = \'\\0\'', +                '(uint8_t:1) b7 = \'\\x01\'', +                '(uint8_t:1) b8 = \'\\0\'', +                '(uint8_t:1) b9 = \'\\0\'', +                '(uint8_t:1) b10 = \'\\x01\'', +                '(uint8_t:1) b12 = \'\\0\'', +                '(uint8_t:1) b13 = \'\\x01\'', +                '(uint8_t:1) b14 = \'\\x01\'', +                '(uint8_t:1) b15 = \'\\0\'', +                '(uint8_t:1) b16 = \'\\0\'', +                '(uint8_t:1) b17 = \'\\0\'', +                ]) + +      @add_test_categories(['pyapi'])      # BitFields exhibit crashes in record layout on Windows      # (http://llvm.org/pr21800) diff --git a/packages/Python/lldbsuite/test/lang/c/bitfields/main.c b/packages/Python/lldbsuite/test/lang/c/bitfields/main.c index 236c926d81bd..fe972dbbe856 100644 --- a/packages/Python/lldbsuite/test/lang/c/bitfields/main.c +++ b/packages/Python/lldbsuite/test/lang/c/bitfields/main.c @@ -8,6 +8,7 @@  //===----------------------------------------------------------------------===//  #include <stdint.h>  #include <stdio.h> +#include <string.h>  int main (int argc, char const *argv[])  { @@ -63,6 +64,20 @@ int main (int argc, char const *argv[])      more_bits.c = 1;      more_bits.d = 0; +    struct EvenMoreBits +    { +        uint8_t b1  : 1, b2  : 1, b3  : 1, b4  : 1, b5  : 1, b6  : 1, +                b7  : 1, b8  : 1, b9  : 1, b10 : 1, b11 : 1, b12 : 1, +                b13 : 1, b14 : 1, b15 : 1, b16 : 1, b17 : 1; +    }; + +    struct EvenMoreBits even_more_bits; +    memset(&even_more_bits, 0, sizeof(even_more_bits)); +    even_more_bits.b1 = 1; +    even_more_bits.b5 = 1; +    even_more_bits.b7 = 1; +    even_more_bits.b13 = 1; +  #pragma pack(1)      struct PackedBits      { diff --git a/packages/Python/lldbsuite/test/lang/c/conflicting-symbol/TestConflictingSymbol.py b/packages/Python/lldbsuite/test/lang/c/conflicting-symbol/TestConflictingSymbol.py index fa14e5ef62e6..b0fde47a2c0b 100644 --- a/packages/Python/lldbsuite/test/lang/c/conflicting-symbol/TestConflictingSymbol.py +++ b/packages/Python/lldbsuite/test/lang/c/conflicting-symbol/TestConflictingSymbol.py @@ -93,6 +93,7 @@ class TestConflictingSymbols(TestBase):                  "Multiple internal symbols"])      @expectedFailureAll(bugnumber="llvm.org/pr35043") +    @skipIfWindows # This test is "passing" on Windows, but it is a false positive.      def test_shadowed(self):          self.build()          exe = self.getBuildArtifact("a.out") diff --git a/packages/Python/lldbsuite/test/lang/c/inlines/TestRedefinitionsInInlines.py b/packages/Python/lldbsuite/test/lang/c/inlines/TestRedefinitionsInInlines.py index 576e9ecd52ad..311c5ec8e120 100644 --- a/packages/Python/lldbsuite/test/lang/c/inlines/TestRedefinitionsInInlines.py +++ b/packages/Python/lldbsuite/test/lang/c/inlines/TestRedefinitionsInInlines.py @@ -3,9 +3,7 @@ from lldbsuite.test import decorators  lldbinline.MakeInlineTest(__file__,                            globals(), -                          [decorators.expectedFailureAll(oslist=["windows"], -                                                         bugnumber="llvm.org/pr27845"), -                              decorators.expectedFailureAll(compiler="clang", -                                                            compiler_version=["<", -                                                                              "3.5"], -                                                            bugnumber="llvm.org/pr27845")]) +                          [decorators.expectedFailureAll(compiler="clang", +                                                         compiler_version=["<", +                                                                           "3.5"], +                                                         bugnumber="llvm.org/pr27845")]) diff --git a/packages/Python/lldbsuite/test/lang/c/local_variables/Makefile b/packages/Python/lldbsuite/test/lang/c/local_variables/Makefile new file mode 100644 index 000000000000..fd7201886586 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/c/local_variables/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +CFLAGS_EXTRAS += -O1 + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/c/local_variables/TestLocalVariables.py b/packages/Python/lldbsuite/test/lang/c/local_variables/TestLocalVariables.py new file mode 100644 index 000000000000..7071b675f3bc --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/c/local_variables/TestLocalVariables.py @@ -0,0 +1,55 @@ +"""Show local variables and check that they can be inspected. + +This test was added after we made a change in clang to normalize +DW_OP_constu(X < 32) to DW_OP_litX which broke the debugger because +it didn't read the value as an unsigned. +""" + +from __future__ import print_function + + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class LocalVariablesTestCase(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.source = 'main.c' +        self.line = line_number( +            self.source, '// Set break point at this line.') + +    def test_c_local_variables(self): +        """Test local variable value.""" +        self.build() + +        # Create a target by the debugger. +        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) +        self.assertTrue(target, VALID_TARGET) + +        # Break inside the main. +        lldbutil.run_break_set_by_file_and_line( +            self, self.source, self.line, num_expected_locations=1, loc_exact=True) + +        # 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.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']) + +        self.expect("frame variable i", VARIABLES_DISPLAYED_CORRECTLY, +                    substrs=['(unsigned int) i = 10']) diff --git a/packages/Python/lldbsuite/test/lang/c/local_variables/main.c b/packages/Python/lldbsuite/test/lang/c/local_variables/main.c new file mode 100644 index 000000000000..2ab579a71a75 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/c/local_variables/main.c @@ -0,0 +1,19 @@ +#include <stdio.h> + +void bar(unsigned i) +{ +  printf("%d\n", i); +} + +void foo(unsigned j) +{ +  unsigned i = j; +  bar(i); +  i = 10; +  bar(i); // Set break point at this line. +} + +int main(int argc, char** argv) +{ +  foo(argc); +} diff --git a/packages/Python/lldbsuite/test/lang/c/shared_lib/TestSharedLib.py b/packages/Python/lldbsuite/test/lang/c/shared_lib/TestSharedLib.py index f53a19138356..d1595163f6e3 100644 --- a/packages/Python/lldbsuite/test/lang/c/shared_lib/TestSharedLib.py +++ b/packages/Python/lldbsuite/test/lang/c/shared_lib/TestSharedLib.py @@ -35,12 +35,10 @@ class SharedLibTestCase(TestBase):              "expression GetMeASubFoo(my_foo_ptr)",              startstr="(sub_foo *) $") -    @expectedFailureAll(oslist=["windows"])      def test_expr(self):          """Test that types work when defined in a shared library and forward-declared in the main executable"""          self.common_test_expr(True) -    @expectedFailureAll(oslist=["windows"])      def test_expr_no_preload(self):          """Test that types work when defined in a shared library and forward-declared in the main executable, but with preloading disabled"""          self.common_test_expr(False) diff --git a/packages/Python/lldbsuite/test/lang/c/strings/TestCStrings.py b/packages/Python/lldbsuite/test/lang/c/strings/TestCStrings.py index b1c8a5ecf4bf..597a247178e4 100644 --- a/packages/Python/lldbsuite/test/lang/c/strings/TestCStrings.py +++ b/packages/Python/lldbsuite/test/lang/c/strings/TestCStrings.py @@ -11,7 +11,6 @@ class CStringsTestCase(TestBase):      mydir = TestBase.compute_mydir(__file__) -    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")      def test_with_run_command(self):          """Tests that C strings work as expected in expressions"""          self.build() diff --git a/packages/Python/lldbsuite/test/lang/c/struct_types/TestStructTypes.py b/packages/Python/lldbsuite/test/lang/c/struct_types/TestStructTypes.py index af362f5be5d7..c8308c16011e 100644 --- a/packages/Python/lldbsuite/test/lang/c/struct_types/TestStructTypes.py +++ b/packages/Python/lldbsuite/test/lang/c/struct_types/TestStructTypes.py @@ -1,7 +1,4 @@  from lldbsuite.test import lldbinline  from lldbsuite.test import decorators -lldbinline.MakeInlineTest( -    __file__, globals(), [ -        decorators.expectedFailureAll( -            oslist=["windows"], bugnumber="llvm.org/pr24764")]) +lldbinline.MakeInlineTest(__file__, globals()) diff --git a/packages/Python/lldbsuite/test/lang/c/unicode/TestUnicodeSymbols.py b/packages/Python/lldbsuite/test/lang/c/unicode/TestUnicodeSymbols.py index b2c9bbb83c0f..9eb25e4d1050 100644 --- a/packages/Python/lldbsuite/test/lang/c/unicode/TestUnicodeSymbols.py +++ b/packages/Python/lldbsuite/test/lang/c/unicode/TestUnicodeSymbols.py @@ -9,6 +9,7 @@ class TestUnicodeSymbols(TestBase):      mydir = TestBase.compute_mydir(__file__) +    @skipIf(compiler="clang", compiler_version=['<', '7.0'])      def test_union_members(self):          self.build()          spec = lldb.SBModuleSpec() diff --git a/packages/Python/lldbsuite/test/lang/c/vla/Makefile b/packages/Python/lldbsuite/test/lang/c/vla/Makefile new file mode 100644 index 000000000000..b09a579159d4 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/c/vla/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/c/vla/TestVLA.py b/packages/Python/lldbsuite/test/lang/c/vla/TestVLA.py new file mode 100644 index 000000000000..f6341ec24fa6 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/c/vla/TestVLA.py @@ -0,0 +1,27 @@ +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test import decorators +import lldbsuite.test.lldbutil as lldbutil + + +class TestVLA(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    @decorators.skipIf(compiler="clang", compiler_version=['<', '8.0']) +    def test_vla(self): +        self.build() +        _, process, _, _ = lldbutil.run_to_source_breakpoint( +            self, "break here", lldb.SBFileSpec('main.c')) + +        def test(a, array): +            for i in range(a): +                self.expect("fr v vla[%d]"%i, substrs=["int", "%d"%(a-i)]) +                self.expect("expr vla[%d]"%i, substrs=["int", "%d"%(a-i)]) +            self.expect("frame var vla", substrs=array) +            self.expect("expr      vla", error=True, substrs=["incomplete"]) + +        test(2, ["int []", "[0] = 2, [1] = 1"]) +        process.Continue() +        test(4, ["int []", "[0] = 4, [1] = 3, [2] = 2, [3] = 1"]) + diff --git a/packages/Python/lldbsuite/test/lang/c/vla/main.c b/packages/Python/lldbsuite/test/lang/c/vla/main.c new file mode 100644 index 000000000000..ba9cc1855607 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/c/vla/main.c @@ -0,0 +1,15 @@ +void pause() {} + +int foo(int a) { +  int vla[a]; + +  for (int i = 0; i < a; ++i) +    vla[i] = a-i; + +  pause(); // break here +  return vla[a-1]; +} + +int main (void) { +  return foo(2) + foo(4); +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/call-function/TestCallCPPFunction.py b/packages/Python/lldbsuite/test/lang/cpp/call-function/TestCallCPPFunction.py index 9b227bc8d3c8..b6274b3d2669 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/call-function/TestCallCPPFunction.py +++ b/packages/Python/lldbsuite/test/lang/cpp/call-function/TestCallCPPFunction.py @@ -16,9 +16,6 @@ class CallCPPFunctionTestCase(TestBase):          TestBase.setUp(self)          self.line = line_number('main.cpp', '// breakpoint') -    @expectedFailureAll( -        oslist=["windows"], -        bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows")      def test_with_run_command(self):          """Test calling a function by basename"""          self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/chained-calls/TestCppChainedCalls.py b/packages/Python/lldbsuite/test/lang/cpp/chained-calls/TestCppChainedCalls.py index a344c4f7d18a..080c051de98f 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/chained-calls/TestCppChainedCalls.py +++ b/packages/Python/lldbsuite/test/lang/cpp/chained-calls/TestCppChainedCalls.py @@ -8,7 +8,6 @@ class TestCppChainedCalls(TestBase):      mydir = TestBase.compute_mydir(__file__) -    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")      def test_with_run_command(self):          self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/TestClassTemplateParameterPack.py b/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/TestClassTemplateParameterPack.py index aad2ea20c133..7e67f73b7092 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/TestClassTemplateParameterPack.py +++ b/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/TestClassTemplateParameterPack.py @@ -4,6 +4,4 @@ from lldbsuite.test import decorators  lldbinline.MakeInlineTest(      __file__, globals(), [          decorators.expectedFailureAll( -            oslist=["windows"], bugnumber="llvm.org/pr24764"), -        decorators.expectedFailureAll(              compiler="gcc")]) diff --git a/packages/Python/lldbsuite/test/lang/cpp/class_static/TestStaticVariables.py b/packages/Python/lldbsuite/test/lang/cpp/class_static/TestStaticVariables.py index 97b0bfd8aee0..eead3c509ff0 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/class_static/TestStaticVariables.py +++ b/packages/Python/lldbsuite/test/lang/cpp/class_static/TestStaticVariables.py @@ -23,7 +23,6 @@ class StaticVariableTestCase(TestBase):          # 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/pr24764")      def test_with_run_command(self):          """Test that file and class static variables display correctly."""          self.build() @@ -63,7 +62,6 @@ class StaticVariableTestCase(TestBase):          compiler=["clang"],          compiler_version=["<", "3.9"],          bugnumber='llvm.org/pr20550') -    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764")      def test_with_run_command_complete(self):          """          Test that file and class static variables display correctly with @@ -108,8 +106,8 @@ class StaticVariableTestCase(TestBase):          compiler=["clang"],          compiler_version=["<", "3.9"],          bugnumber='llvm.org/pr20550') -    @add_test_categories(['pyapi'])      @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764") +    @add_test_categories(['pyapi'])      def test_with_python_api(self):          """Test Python APIs on file and class static variables."""          self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/global_operators/TestCppGlobalOperators.py b/packages/Python/lldbsuite/test/lang/cpp/global_operators/TestCppGlobalOperators.py index fa68d0a15021..4ead709cf565 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/global_operators/TestCppGlobalOperators.py +++ b/packages/Python/lldbsuite/test/lang/cpp/global_operators/TestCppGlobalOperators.py @@ -49,7 +49,6 @@ class TestCppGlobalOperators(TestBase):          return thread.GetSelectedFrame() -    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")      def test_equals_operator(self):          frame = self.prepare_executable_and_get_frame() @@ -87,7 +86,6 @@ class TestCppGlobalOperators(TestBase):          self.assertTrue(got_type.IsPointerType())          self.assertEqual(got_type.GetPointeeType().GetName(), "Struct") -    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")      def test_operator_new(self):          frame = self.prepare_executable_and_get_frame() diff --git a/packages/Python/lldbsuite/test/lang/cpp/lambdas/TestLambdas.py b/packages/Python/lldbsuite/test/lang/cpp/lambdas/TestLambdas.py index 284caabbc17b..c8308c16011e 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/lambdas/TestLambdas.py +++ b/packages/Python/lldbsuite/test/lang/cpp/lambdas/TestLambdas.py @@ -1,7 +1,4 @@  from lldbsuite.test import lldbinline  from lldbsuite.test import decorators -lldbinline.MakeInlineTest( -    __file__, globals(), [ -        lldbinline.expectedFailureAll( -            oslist=["windows"])]) +lldbinline.MakeInlineTest(__file__, globals()) diff --git a/packages/Python/lldbsuite/test/lang/cpp/llvm-style/TestLLVMStyle.py b/packages/Python/lldbsuite/test/lang/cpp/llvm-style/TestLLVMStyle.py index af362f5be5d7..c8308c16011e 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/llvm-style/TestLLVMStyle.py +++ b/packages/Python/lldbsuite/test/lang/cpp/llvm-style/TestLLVMStyle.py @@ -1,7 +1,4 @@  from lldbsuite.test import lldbinline  from lldbsuite.test import decorators -lldbinline.MakeInlineTest( -    __file__, globals(), [ -        decorators.expectedFailureAll( -            oslist=["windows"], bugnumber="llvm.org/pr24764")]) +lldbinline.MakeInlineTest(__file__, globals()) diff --git a/packages/Python/lldbsuite/test/lang/cpp/namespace/TestNamespaceLookup.py b/packages/Python/lldbsuite/test/lang/cpp/namespace/TestNamespaceLookup.py index 2837cfd9244e..9c65966b348a 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/namespace/TestNamespaceLookup.py +++ b/packages/Python/lldbsuite/test/lang/cpp/namespace/TestNamespaceLookup.py @@ -42,11 +42,9 @@ class NamespaceLookupTestCase(TestBase):                               'stop reason = breakpoint'])      @expectedFailureAll( -        oslist=[ -            "windows", -            "linux", -            "freebsd"], +        oslist=["freebsd"],          bugnumber="llvm.org/pr25819") +    @skipIfWindows # This is flakey on Windows: llvm.org/pr38373      def test_scope_lookup_with_run_command(self):          """Test scope lookup of functions in lldb."""          self.build() @@ -185,6 +183,7 @@ class NamespaceLookupTestCase(TestBase):          self.expect("expr -- foo()", startstr="(int) $2 = 42")      @unittest2.expectedFailure("lldb file scope lookup bugs") +    @skipIfWindows # This is flakey on Windows: llvm.org/pr38373      def test_file_scope_lookup_with_run_command(self):          """Test file scope lookup in lldb."""          self.build() @@ -204,7 +203,7 @@ class NamespaceLookupTestCase(TestBase):          # finds the global ::func().          self.expect("expr -- func()", startstr="(int) $0 = 2") -    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr25819") +    @skipIfWindows # This is flakey on Windows: llvm.org/pr38373      def test_scope_lookup_before_using_with_run_command(self):          """Test scope lookup before using in lldb."""          self.build() @@ -230,10 +229,7 @@ class NamespaceLookupTestCase(TestBase):          oslist=["linux"],          debug_info=["dwo"])  # Skip to avoid crash      @expectedFailureAll( -        oslist=[ -            "windows", -            "linux", -            "freebsd"], +        oslist=["freebsd"],          bugnumber="llvm.org/pr25819")      def test_scope_after_using_directive_lookup_with_run_command(self):          """Test scope lookup after using directive in lldb.""" @@ -297,10 +293,7 @@ class NamespaceLookupTestCase(TestBase):          self.expect("expr -- func()", startstr="error")      @expectedFailureAll( -        oslist=[ -            "windows", -            "linux", -            "freebsd"], +        oslist=["freebsd"],          bugnumber="llvm.org/pr25819")      def test_scope_lookup_shadowed_by_using_with_run_command(self):          """Test scope lookup shadowed by using in lldb.""" diff --git a/packages/Python/lldbsuite/test/lang/cpp/namespace_conflicts/TestNamespaceConflicts.py b/packages/Python/lldbsuite/test/lang/cpp/namespace_conflicts/TestNamespaceConflicts.py index af362f5be5d7..c8308c16011e 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/namespace_conflicts/TestNamespaceConflicts.py +++ b/packages/Python/lldbsuite/test/lang/cpp/namespace_conflicts/TestNamespaceConflicts.py @@ -1,7 +1,4 @@  from lldbsuite.test import lldbinline  from lldbsuite.test import decorators -lldbinline.MakeInlineTest( -    __file__, globals(), [ -        decorators.expectedFailureAll( -            oslist=["windows"], bugnumber="llvm.org/pr24764")]) +lldbinline.MakeInlineTest(__file__, globals()) diff --git a/packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/TestOverloadedFunctions.py b/packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/TestOverloadedFunctions.py index 7f68eb8923eb..ad969ef3d088 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/TestOverloadedFunctions.py +++ b/packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/TestOverloadedFunctions.py @@ -16,9 +16,6 @@ class OverloadedFunctionsTestCase(TestBase):          TestBase.setUp(self)          self.line = line_number('main.cpp', '// breakpoint') -    @expectedFailureAll( -        oslist=["windows"], -        bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows")      def test_with_run_command(self):          """Test that functions with the same name are resolved correctly"""          self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/rvalue-references/TestRvalueReferences.py b/packages/Python/lldbsuite/test/lang/cpp/rvalue-references/TestRvalueReferences.py index cc79366c7149..5e31d93eb163 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/rvalue-references/TestRvalueReferences.py +++ b/packages/Python/lldbsuite/test/lang/cpp/rvalue-references/TestRvalueReferences.py @@ -16,9 +16,6 @@ class RvalueReferencesTestCase(TestBase):      @expectedFailureAll(          compiler="icc",          bugnumber="ICC (13.1, 14-beta) do not emit DW_TAG_rvalue_reference_type.") -    @expectedFailureAll( -        oslist=["windows"], -        bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows")      def test_with_run_command(self):          """Test that rvalues are supported in the C++ expression parser"""          self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/scope/TestCppScope.py b/packages/Python/lldbsuite/test/lang/cpp/scope/TestCppScope.py index c7afeb2dbb6f..213e7fbe9022 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/scope/TestCppScope.py +++ b/packages/Python/lldbsuite/test/lang/cpp/scope/TestCppScope.py @@ -15,7 +15,7 @@ class TestCppScopes(TestBase):      def test_all_but_c(self):          self.do_test(False) -    @expectedFailureAll(oslist=["windows"]) +    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764")      def test_c(self):          self.do_test(True) diff --git a/packages/Python/lldbsuite/test/lang/cpp/static_methods/TestCPPStaticMethods.py b/packages/Python/lldbsuite/test/lang/cpp/static_methods/TestCPPStaticMethods.py index 404ef22a0b8c..4b422674134c 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/static_methods/TestCPPStaticMethods.py +++ b/packages/Python/lldbsuite/test/lang/cpp/static_methods/TestCPPStaticMethods.py @@ -16,7 +16,6 @@ class CPPStaticMethodsTestCase(TestBase):          TestBase.setUp(self)          self.line = line_number('main.cpp', '// Break at this line') -    @expectedFailureAll(oslist=["windows"])      def test_with_run_command(self):          """Test that static methods are properly distinguished from regular methods"""          self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/std-function-step-into-callable/Makefile b/packages/Python/lldbsuite/test/lang/cpp/std-function-step-into-callable/Makefile new file mode 100644 index 000000000000..a42bb089d15a --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/std-function-step-into-callable/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp +CXXFLAGS += -std=c++11 +USE_LIBCPP := 1 + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/std-function-step-into-callable/TestStdFunctionStepIntoCallable.py b/packages/Python/lldbsuite/test/lang/cpp/std-function-step-into-callable/TestStdFunctionStepIntoCallable.py new file mode 100644 index 000000000000..abd35acd15bb --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/std-function-step-into-callable/TestStdFunctionStepIntoCallable.py @@ -0,0 +1,71 @@ +""" +Test stepping into std::function +""" + +from __future__ import print_function + + +import lldb +import sys +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class LibCxxFunctionSteppingIntoCallableTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    NO_DEBUG_INFO_TESTCASE = True + +    @add_test_categories(["libc++"]) +    def test(self): +        """Test that std::function as defined by libc++ is correctly printed by LLDB""" +        self.build() + +        self.main_source = "main.cpp" +        self.main_source_spec = lldb.SBFileSpec(self.main_source) +        self.source_foo_line = line_number( +            self.main_source, '// Source foo start line') +        self.source_lambda_f2_line = line_number( +            self.main_source, '// Source lambda used by f2 start line') +        self.source_lambda_f3_line = line_number( +            self.main_source, '// Source lambda used by f3 start line') +        self.source_bar_operator_line = line_number( +            self.main_source, '// Source Bar::operator()() start line') +        self.source_bar_add_num_line = line_number( +            self.main_source, '// Source Bar::add_num start line') +        self.source_main_invoking_f1 = line_number( +            self.main_source, '// Source main invoking f1') + +        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( +            self, "// Set break point at this line.", self.main_source_spec) + +        thread.StepInto() +        self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetLine(), self.source_main_invoking_f1 ) ; +        self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetFileSpec().GetFilename(), self.main_source) ; + +        thread.StepInto() +        self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetLine(), self.source_foo_line ) ; +        self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetFileSpec().GetFilename(), self.main_source) ; +        process.Continue() + +        thread.StepInto() +        self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetLine(), self.source_lambda_f2_line ) ; +        self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetFileSpec().GetFilename(), self.main_source) ; +        process.Continue() + +        thread.StepInto() +        self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetLine(), self.source_lambda_f3_line ) ; +        self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetFileSpec().GetFilename(), self.main_source) ; +        process.Continue() + +        thread.StepInto() +        self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetLine(), self.source_bar_operator_line ) ; +        self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetFileSpec().GetFilename(), self.main_source) ; +        process.Continue() + +        thread.StepInto() +        self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetLine(), self.source_bar_add_num_line ) ; +        self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetFileSpec().GetFilename(), self.main_source) ; +        process.Continue() diff --git a/packages/Python/lldbsuite/test/lang/cpp/std-function-step-into-callable/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/std-function-step-into-callable/main.cpp new file mode 100644 index 000000000000..a85e77db040e --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/std-function-step-into-callable/main.cpp @@ -0,0 +1,38 @@ +#include <functional> + +int foo(int x, int y) { +  return x + y - 1; // Source foo start line +} + +struct Bar { +   int operator()() { +       return 66 ; // Source Bar::operator()() start line +   } +   int add_num(int i) const { return i + 3 ; } // Source Bar::add_num start line +   int num_ = 0 ; +} ; + +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); // Source lambda used by f2 start line +  }; + +  auto f = [](int x, int y) { return x + y; }; // Source lambda used by f3 start line +  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; +  std::function<int(Bar const&)> f_mem = &Bar::num_; + +  return f_mem(bar1) +     // Set break point at this line. +         f1(acc,acc) +     // Source main invoking f1 +         f2(acc) +         // Set break point at this line. +         f3(acc+1,acc+2) + // Set break point at this line.  +         f4() +            // Set break point at this line.  +         f5(bar1, 10);     // Set break point at this line. +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/stl/TestSTL.py b/packages/Python/lldbsuite/test/lang/cpp/stl/TestSTL.py index 42c372489c63..d11004e66d0a 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/stl/TestSTL.py +++ b/packages/Python/lldbsuite/test/lang/cpp/stl/TestSTL.py @@ -26,6 +26,7 @@ class STLTestCase(TestBase):          self.line = line_number(              self.source, '// Set break point at this line.') +    @skipIf      @expectedFailureAll(bugnumber="llvm.org/PR36713")      def test(self):          """Test some expressions involving STL data types.""" diff --git a/packages/Python/lldbsuite/test/lang/cpp/template/TestTemplateArgs.py b/packages/Python/lldbsuite/test/lang/cpp/template/TestTemplateArgs.py index 054bc93c3189..8f2ab56488f7 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/template/TestTemplateArgs.py +++ b/packages/Python/lldbsuite/test/lang/cpp/template/TestTemplateArgs.py @@ -47,7 +47,6 @@ class TemplateArgsTestCase(TestBase):          # Get frame for current thread          return thread.GetSelectedFrame() -    @expectedFailureAll(oslist=["windows"])      def test_integer_args(self):          frame = self.prepareProcess() @@ -111,11 +110,9 @@ class TemplateArgsTestCase(TestBase):          self.assertTrue(f4.GetType().GetName() == 'int')          self.assertTrue(f4.GetValue() == '42') -      # Gcc does not generate the necessary DWARF attribute for enum template      # parameters.      @expectedFailureAll(bugnumber="llvm.org/pr28354", compiler="gcc") -    @expectedFailureAll(oslist=["windows"])      def test_enum_args(self):          frame = self.prepareProcess() diff --git a/packages/Python/lldbsuite/test/lang/cpp/type_lookup/TestCppTypeLookup.py b/packages/Python/lldbsuite/test/lang/cpp/type_lookup/TestCppTypeLookup.py index 94d52e368e8c..7fa3f95ae9a7 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/type_lookup/TestCppTypeLookup.py +++ b/packages/Python/lldbsuite/test/lang/cpp/type_lookup/TestCppTypeLookup.py @@ -52,23 +52,23 @@ class TestCppTypeLookup(TestBase):          self.assertTrue(expr_result.GetError().Fail(),                          "'namespace_only' exists in namespace only") -        # Make sure we can find the correct type in a namespace "a" -        expr_result = frame.EvaluateExpression("*((a::namespace_only *)&i)") +        # Make sure we can find the correct type in a namespace "nsp_a" +        expr_result = frame.EvaluateExpression("*((nsp_a::namespace_only *)&i)")          self.check_value(expr_result, "a", 123) -        # Make sure we can find the correct type in a namespace "b" -        expr_result = frame.EvaluateExpression("*((b::namespace_only *)&i)") +        # Make sure we can find the correct type in a namespace "nsp_b" +        expr_result = frame.EvaluateExpression("*((nsp_b::namespace_only *)&i)")          self.check_value(expr_result, "b", 123)          # Make sure we can find the correct type in the root namespace          expr_result = frame.EvaluateExpression("*((namespace_and_file *)&i)")          self.check_value(expr_result, "ff", 123) -        # Make sure we can find the correct type in a namespace "a" +        # Make sure we can find the correct type in a namespace "nsp_a"          expr_result = frame.EvaluateExpression( -                "*((a::namespace_and_file *)&i)") +                "*((nsp_a::namespace_and_file *)&i)")          self.check_value(expr_result, "aa", 123) -        # Make sure we can find the correct type in a namespace "b" +        # Make sure we can find the correct type in a namespace "nsp_b"          expr_result = frame.EvaluateExpression( -                "*((b::namespace_and_file *)&i)") +                "*((nsp_b::namespace_and_file *)&i)")          self.check_value(expr_result, "bb", 123)          # Make sure we don't accidentally accept structures that exist only @@ -84,11 +84,11 @@ class TestCppTypeLookup(TestBase):          expr_result = frame.EvaluateExpression(                  "*((contains_type::in_contains_type *)&i)")          self.check_value(expr_result, "fff", 123) -        # Make sure we can find the correct type in a namespace "a" +        # Make sure we can find the correct type in a namespace "nsp_a"          expr_result = frame.EvaluateExpression( -                "*((a::contains_type::in_contains_type *)&i)") +                "*((nsp_a::contains_type::in_contains_type *)&i)")          self.check_value(expr_result, "aaa", 123) -        # Make sure we can find the correct type in a namespace "b" +        # Make sure we can find the correct type in a namespace "nsp_b"          expr_result = frame.EvaluateExpression( -                "*((b::contains_type::in_contains_type *)&i)") +                "*((nsp_b::contains_type::in_contains_type *)&i)")          self.check_value(expr_result, "bbb", 123) diff --git a/packages/Python/lldbsuite/test/lang/cpp/type_lookup/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/type_lookup/main.cpp index b244e80962c8..ae44bfa7c7d5 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/type_lookup/main.cpp +++ b/packages/Python/lldbsuite/test/lang/cpp/type_lookup/main.cpp @@ -11,7 +11,7 @@  // levels in the code and test that we can properly locate these types with  // a varienty of different expressions. -namespace a { +namespace nsp_a {    struct namespace_only {      int a;    }; @@ -24,7 +24,7 @@ namespace a {      };    };  }; -namespace b { +namespace nsp_b {    struct namespace_only {      int b;    }; @@ -50,12 +50,12 @@ struct contains_type {  int main (int argc, char const *argv[]) { -  a::namespace_only a_namespace_only = { 1 }; -  a::namespace_and_file a_namespace_and_file = { 2 }; -  a::contains_type::in_contains_type a_in_contains_type = { 3 }; -  b::namespace_only b_namespace_only = { 11 }; -  b::namespace_and_file b_namespace_and_file = { 22 }; -  b::contains_type::in_contains_type b_in_contains_type = { 33 }; +  nsp_a::namespace_only a_namespace_only = { 1 }; +  nsp_a::namespace_and_file a_namespace_and_file = { 2 }; +  nsp_a::contains_type::in_contains_type a_in_contains_type = { 3 }; +  nsp_b::namespace_only b_namespace_only = { 11 }; +  nsp_b::namespace_and_file b_namespace_and_file = { 22 }; +  nsp_b::contains_type::in_contains_type b_in_contains_type = { 33 };    namespace_and_file file_namespace_and_file = { 44 };    contains_type::in_contains_type file_in_contains_type = { 55 };    int i = 123; // Provide an integer that can be used for casting diff --git a/packages/Python/lldbsuite/test/lang/cpp/unicode-literals/TestUnicodeLiterals.py b/packages/Python/lldbsuite/test/lang/cpp/unicode-literals/TestUnicodeLiterals.py index 216f86064dca..1a50c9dfc69f 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/unicode-literals/TestUnicodeLiterals.py +++ b/packages/Python/lldbsuite/test/lang/cpp/unicode-literals/TestUnicodeLiterals.py @@ -31,25 +31,16 @@ class UnicodeLiteralsTestCase(TestBase):      mydir = TestBase.compute_mydir(__file__) -    @expectedFailureAll( -        oslist=["windows"], -        bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows")      def test_expr1(self):          """Test that the expression parser returns proper Unicode strings."""          self.build()          self.rdar12991846(expr=1) -    @expectedFailureAll( -        oslist=["windows"], -        bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows")      def test_expr2(self):          """Test that the expression parser returns proper Unicode strings."""          self.build()          self.rdar12991846(expr=2) -    @expectedFailureAll( -        oslist=["windows"], -        bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows")      def test_expr3(self):          """Test that the expression parser returns proper Unicode strings."""          self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/virtual/TestVirtual.py b/packages/Python/lldbsuite/test/lang/cpp/virtual/TestVirtual.py index b3fe9c40c198..365eb829ba64 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/virtual/TestVirtual.py +++ b/packages/Python/lldbsuite/test/lang/cpp/virtual/TestVirtual.py @@ -36,6 +36,7 @@ class CppVirtualMadness(TestBase):      @expectedFailureAll(          compiler="icc",          bugnumber="llvm.org/pr16808 lldb does not call the correct virtual function with icc.") +    @skipIfWindows # This test will hang on windows llvm.org/pr21753      def test_virtual_madness(self):          """Test that expression works correctly with virtual inheritance as well as virtual function."""          self.build() diff --git a/packages/Python/lldbsuite/test/lang/go/expressions/TestExpressions.py b/packages/Python/lldbsuite/test/lang/go/expressions/TestExpressions.py deleted file mode 100644 index 963e0676100d..000000000000 --- a/packages/Python/lldbsuite/test/lang/go/expressions/TestExpressions.py +++ /dev/null @@ -1,123 +0,0 @@ -"""Test the go expression parser/interpreter.""" - -import os -import time -import unittest2 -import lldb -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil - - -class TestGoUserExpression(TestBase): - -    mydir = TestBase.compute_mydir(__file__) - -    @add_test_categories(['pyapi']) -    @skipIfRemote  # Not remote test suit ready -    @skipIfFreeBSD  # Test hanging on FreeBSD - llvm.org/pr37194 -    @skipUnlessGoInstalled -    def test_with_dsym_and_python_api(self): -        """Test GoASTUserExpress.""" -        self.buildGo() -        self.launchProcess() -        self.go_expressions() - -    def setUp(self): -        # Call super's setUp(). -        TestBase.setUp(self) -        # Find the line numbers to break inside main(). -        self.main_source = "main.go" -        self.break_line = line_number( -            self.main_source, '// Set breakpoint here.') - -    def check_builtin(self, name, size=0, typeclass=lldb.eTypeClassBuiltin): -        tl = self.target().FindTypes(name) -        self.assertEqual(1, len(tl)) -        t = list(tl)[0] -        self.assertEqual(name, t.name) -        self.assertEqual(typeclass, t.type) -        if size > 0: -            self.assertEqual(size, t.size) - -    def launchProcess(self): -        exe = self.getBuildArtifact("a.out") - -        target = self.dbg.CreateTarget(exe) -        self.assertTrue(target, VALID_TARGET) - -        bpt = target.BreakpointCreateByLocation( -            self.main_source, self.break_line) -        self.assertTrue(bpt, 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. -        thread_list = lldbutil.get_threads_stopped_at_breakpoint(process, bpt) - -        # Make sure we stopped at the first breakpoint. -        self.assertTrue( -            len(thread_list) != 0, -            "No thread stopped at our breakpoint.") -        self.assertTrue(len(thread_list) == 1, -                        "More than one thread stopped at our breakpoint.") - -        frame = thread_list[0].GetFrameAtIndex(0) -        self.assertTrue(frame, "Got a valid frame 0 frame.") - -    def go_expressions(self): -        frame = self.frame() -        v = frame.EvaluateExpression("1") -        self.assertEqual(1, v.GetValueAsSigned()) -        x = frame.EvaluateExpression("x") -        self.assertEqual(22, x.GetValueAsSigned()) - -        a = frame.EvaluateExpression("a") -        self.assertEqual(3, a.GetNumChildren()) -        a0 = a.GetChildAtIndex(0) -        self.assertEqual(8, a0.GetValueAsSigned()) - -        # Array indexing -        a0 = frame.EvaluateExpression("a[0]") -        self.assertEqual(8, a0.GetValueAsSigned()) - -        # Slice indexing -        b1 = frame.EvaluateExpression("b[1]") -        self.assertEqual(9, b1.GetValueAsSigned()) - -        # Test global in this package -        g = frame.EvaluateExpression("myGlobal") -        self.assertEqual(17, g.GetValueAsSigned(), str(g)) - -        # Global with package name -        g = frame.EvaluateExpression("main.myGlobal") -        self.assertEqual(17, g.GetValueAsSigned(), str(g)) - -        # Global with quoted package name -        g = frame.EvaluateExpression('"main".myGlobal') -        self.assertEqual(17, g.GetValueAsSigned(), str(g)) - -        # Casting with package local type -        s = frame.EvaluateExpression("*(*myStruct)(i.data)") -        sb = s.GetChildMemberWithName("a") -        self.assertEqual(2, sb.GetValueAsSigned()) - -        # casting with explicit package -        s = frame.EvaluateExpression("*(*main.myStruct)(i.data)") -        sb = s.GetChildMemberWithName("a") -        self.assertEqual(2, sb.GetValueAsSigned()) - -        # Casting quoted package -        s = frame.EvaluateExpression('*(*"main".myStruct)(i.data)') -        sb = s.GetChildMemberWithName("b") -        self.assertEqual(-1, sb.GetValueAsSigned()) - -if __name__ == '__main__': -    import atexit -    lldb.SBDebugger.Initialize() -    atexit.register(lambda: lldb.SBDebugger.Terminate()) -    unittest2.main() diff --git a/packages/Python/lldbsuite/test/lang/go/expressions/main.go b/packages/Python/lldbsuite/test/lang/go/expressions/main.go deleted file mode 100644 index c8b97fe07d7d..000000000000 --- a/packages/Python/lldbsuite/test/lang/go/expressions/main.go +++ /dev/null @@ -1,21 +0,0 @@ -package main - -import "fmt" - -type myStruct struct { -    a, b int -} - -var myGlobal = 17 - -func myFunc(i interface{}) { -    a := [...]int{8, 9, 10} -    b := a[:] -    x := 22 -    fmt.Println(a, b, x, i, myGlobal)  // Set breakpoint here. -} - -func main() { -    s := myStruct {2, -1} -    myFunc(s) -}
\ No newline at end of file diff --git a/packages/Python/lldbsuite/test/lang/go/formatters/TestGoFormatters.py b/packages/Python/lldbsuite/test/lang/go/formatters/TestGoFormatters.py deleted file mode 100644 index b31ac35be46c..000000000000 --- a/packages/Python/lldbsuite/test/lang/go/formatters/TestGoFormatters.py +++ /dev/null @@ -1,76 +0,0 @@ -"""Test the Go Data Formatter Plugin.""" - -import os -import time -import unittest2 -import lldb -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil - - -class TestGoLanguage(TestBase): - -    mydir = TestBase.compute_mydir(__file__) - -    @skipIfFreeBSD  # llvm.org/pr24895 triggers assertion failure -    @skipIfRemote  # Not remote test suite ready -    @no_debug_info_test -    @skipUnlessGoInstalled -    def test_go_formatter_plugin(self): -        """Test go data formatters.""" -        self.buildGo() -        self.launchProcess() -        self.check_formatters() - -    def setUp(self): -        # Call super's setUp(). -        TestBase.setUp(self) -        # Find the line numbers to break inside main(). -        self.main_source = "main.go" -        self.break_line = line_number(self.main_source, '// stop here') - -    def launchProcess(self): -        exe = self.getBuildArtifact("a.out") - -        target = self.dbg.CreateTarget(exe) -        self.assertTrue(target, VALID_TARGET) - -        self.bpt = target.BreakpointCreateByLocation( -            self.main_source, self.break_line) -        self.assertTrue(self.bpt, 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. -        thread_list = lldbutil.get_threads_stopped_at_breakpoint( -            process, self.bpt) - -        # Make sure we stopped at the first breakpoint. -        self.assertTrue( -            len(thread_list) != 0, -            "No thread stopped at our breakpoint.") -        self.assertTrue(len(thread_list) == 1, -                        "More than one thread stopped at our breakpoint.") - -        frame = thread_list[0].GetFrameAtIndex(0) -        self.assertTrue(frame, "Got a valid frame 0 frame.") - -    def check_formatters(self): -        a = self.frame().FindVariable('a') -        self.assertEqual('(string) a = "my string"', str(a)) -        b = self.frame().FindVariable('b') -        self.assertEqual( -            "([]int) b = (len 2, cap 7) {\n  [0] = 0\n  [1] = 0\n}", -            str(b)) - - -if __name__ == '__main__': -    import atexit -    lldb.SBDebugger.Initialize() -    atexit.register(lambda: lldb.SBDebugger.Terminate()) -    unittest2.main() diff --git a/packages/Python/lldbsuite/test/lang/go/formatters/main.go b/packages/Python/lldbsuite/test/lang/go/formatters/main.go deleted file mode 100644 index 7956ad66bcb4..000000000000 --- a/packages/Python/lldbsuite/test/lang/go/formatters/main.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import "fmt" - -func main() { -    a := "my string" -    b := make([]int, 2, 7) -    fmt.Println(a, b)  // stop here -}
\ No newline at end of file diff --git a/packages/Python/lldbsuite/test/lang/go/goroutines/TestGoroutines.py b/packages/Python/lldbsuite/test/lang/go/goroutines/TestGoroutines.py deleted file mode 100644 index 027fb3adc0cf..000000000000 --- a/packages/Python/lldbsuite/test/lang/go/goroutines/TestGoroutines.py +++ /dev/null @@ -1,104 +0,0 @@ -"""Test the Go OS Plugin.""" - -from __future__ import print_function - - -import os -import time -import lldb -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil - - -class TestGoASTContext(TestBase): - -    mydir = TestBase.compute_mydir(__file__) - -    @add_test_categories(['pyapi']) -    @skipIfFreeBSD  # llvm.org/pr24895 triggers assertion failure -    @skipIfRemote  # Not remote test suite ready -    @no_debug_info_test -    @skipUnlessGoInstalled -    def test_goroutine_plugin(self): -        """Test goroutine as threads support.""" -        self.buildGo() -        self.launchProcess() -        self.check_goroutines() - -    def setUp(self): -        # Call super's setUp(). -        TestBase.setUp(self) -        # Find the line numbers to break inside main(). -        self.main_source = "main.go" -        self.break_line1 = line_number(self.main_source, '// stop1') -        self.break_line2 = line_number(self.main_source, '// stop2') -        self.break_line3 = line_number(self.main_source, '// stop3') - -    def launchProcess(self): -        exe = self.getBuildArtifact("a.out") - -        target = self.dbg.CreateTarget(exe) -        self.assertTrue(target, VALID_TARGET) - -        self.bpt1 = target.BreakpointCreateByLocation( -            self.main_source, self.break_line1) -        self.assertTrue(self.bpt1, VALID_BREAKPOINT) -        self.bpt2 = target.BreakpointCreateByLocation( -            self.main_source, self.break_line2) -        self.assertTrue(self.bpt2, VALID_BREAKPOINT) -        self.bpt3 = target.BreakpointCreateByLocation( -            self.main_source, self.break_line3) -        self.assertTrue(self.bpt3, 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. -        thread_list = lldbutil.get_threads_stopped_at_breakpoint( -            process, self.bpt1) - -        # Make sure we stopped at the first breakpoint. -        self.assertTrue( -            len(thread_list) != 0, -            "No thread stopped at our breakpoint.") -        self.assertTrue(len(thread_list) == 1, -                        "More than one thread stopped at our breakpoint.") - -        frame = thread_list[0].GetFrameAtIndex(0) -        self.assertTrue(frame, "Got a valid frame 0 frame.") - -    def check_goroutines(self): -        self.assertLess(len(self.process().threads), 20) -        self.process().Continue() - -        # Make sure we stopped at the 2nd breakpoint -        thread_list = lldbutil.get_threads_stopped_at_breakpoint( -            self.process(), self.bpt2) -        self.assertTrue( -            len(thread_list) != 0, -            "No thread stopped at our breakpoint.") -        self.assertTrue(len(thread_list) == 1, -                        "More than one thread stopped at our breakpoint.") - -        # There's (at least) 21 goroutines. -        self.assertGreater(len(self.process().threads), 20) -        # self.dbg.HandleCommand("log enable lldb os") - -        # Now test that stepping works if the memory thread moves to a -        # different backing thread. -        for i in list(range(11)): -            self.thread().StepOver() -            self.assertEqual( -                lldb.eStopReasonPlanComplete, -                self.thread().GetStopReason(), -                self.thread().GetStopDescription(100)) - -        # Disable the plugin and make sure the goroutines disappear -        self.dbg.HandleCommand( -            "settings set plugin.os.goroutines.enable false") -        self.thread().StepInstruction(False) -        self.assertLess(len(self.process().threads), 20) diff --git a/packages/Python/lldbsuite/test/lang/go/goroutines/main.go b/packages/Python/lldbsuite/test/lang/go/goroutines/main.go deleted file mode 100644 index bb44f7b8b716..000000000000 --- a/packages/Python/lldbsuite/test/lang/go/goroutines/main.go +++ /dev/null @@ -1,89 +0,0 @@ -package main - -import ( -	"fmt" -	"runtime" -) - -type philosopher struct { -	i int -	forks [2]chan bool -	eating chan int -	done  chan struct{} -} - -func (p philosopher) run() { -	for { -		select { -		case <-p.done: -			return -		case <-p.forks[0]: -			p.eat() -		} -	} -} - -func (p philosopher) eat() { -	select { -	case <-p.done: -		return -	case <-p.forks[1]: -		p.eating <- p.i -		p.forks[0] <- true -		p.forks[1] <- true -		runtime.Gosched() -	} -} - -func startPhilosophers(n int) (chan struct{}, chan int) { -	philosophers := make([]*philosopher, n) -	chans := make([]chan bool, n) -	for i := range chans { -		chans[i] = make(chan bool, 1) -		chans[i] <- true -	} -	eating := make(chan int, n) -	done := make(chan struct{}) -	for i := range philosophers { -		var min, max int -		if i == n - 1 { -			min = 0 -			max = i -		} else { -			min = i -			max = i + 1 -		} -		philosophers[i] = &philosopher{i: i, forks: [2]chan bool{chans[min], chans[max]}, eating: eating, done: done} -		go philosophers[i].run() -	} -	return done, eating -} - -func wait(c chan int) { -	fmt.Println(<- c) -	runtime.Gosched() -} - -func main() { -	// Restrict go to 1 real thread so we can be sure we're seeing goroutines -	// and not threads. -	runtime.GOMAXPROCS(1) -	// Create a bunch of goroutines -	done, eating := startPhilosophers(20) // stop1 -	// Now turn up the number of threads so this goroutine is likely to get -	// scheduled on a different thread. -	runtime.GOMAXPROCS(runtime.NumCPU()) // stop2 -	// Now let things run. Hopefully we'll bounce around -	wait(eating) -	wait(eating) -	wait(eating) -	wait(eating) -	wait(eating) -	wait(eating) -	wait(eating) -	wait(eating) -	wait(eating) -	wait(eating) -	close(done) -	fmt.Println("done") // stop3 -} diff --git a/packages/Python/lldbsuite/test/lang/go/runtime/TestGoLanguageRuntime b/packages/Python/lldbsuite/test/lang/go/runtime/TestGoLanguageRuntime deleted file mode 100644 index b06aa656aaa3..000000000000 --- a/packages/Python/lldbsuite/test/lang/go/runtime/TestGoLanguageRuntime +++ /dev/null @@ -1,80 +0,0 @@ -"""Test the go dynamic type handling.""" - -import os, time -import unittest2 -import lldb -import lldbutil -from lldbtest import * - -class TestGoLanguageRuntime(TestBase): - -    mydir = TestBase.compute_mydir(__file__) - -    @python_api_test -    @expectedFailureAll(oslist=['freebsd'], bugnumber='llvm.org/pr24895') -    @skipIfRemote # Not remote test suite ready -    @skipUnlessGoInstalled -    def test_with_dsym_and_python_api(self): -        """Test GoASTContext dwarf parsing.""" -        self.buildGo() -        self.launchProcess() -        self.go_interface_types() - -    def setUp(self): -        # Call super's setUp(). -        TestBase.setUp(self) -        # Find the line numbers to break inside main(). -        self.main_source = "main.go" -        self.break_line1 = line_number(self.main_source, '// Set breakpoint 1') -        self.break_line2 = line_number(self.main_source, '// Set breakpoint 2') - - -    def launchProcess(self): -        exe = self.getBuildArtifact("a.out") - -        target = self.dbg.CreateTarget(exe) -        self.assertTrue(target, VALID_TARGET) - -        bpt1 = target.BreakpointCreateByLocation(self.main_source, self.break_line1) -        self.assertTrue(bpt1, VALID_BREAKPOINT) -        bpt2 = target.BreakpointCreateByLocation(self.main_source, self.break_line2) -        self.assertTrue(bpt2, 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. -        thread_list = lldbutil.get_threads_stopped_at_breakpoint (process, bpt1) - -        # Make sure we stopped at the first breakpoint. -        self.assertTrue (len(thread_list) != 0, "No thread stopped at our breakpoint.") -        self.assertTrue (len(thread_list) == 1, "More than one thread stopped at our breakpoint.") - -        frame = thread_list[0].GetFrameAtIndex(0) -        self.assertTrue (frame, "Got a valid frame 0 frame.") - -    def go_interface_types(self): -        f = self.frame() -        v = f.FindVariable("a", lldb.eDynamicCanRunTarget) -        self.assertEqual("*int", v.GetType().name) -        self.assertEqual(1, v.Dereference().GetValueAsSigned()) -        v = f.FindVariable("b", lldb.eDynamicCanRunTarget) -        self.assertEqual("*float64", v.GetType().name) -        err = lldb.SBError() -        self.assertEqual(2.0, v.Dereference().GetData().GetDouble(err, 0)) -        v = f.FindVariable("c", lldb.eDynamicCanRunTarget) -        self.assertEqual("*main.SomeFooer", v.GetType().name) -        self.assertEqual(9, v.Dereference().GetChildAtIndex(0).GetValueAsSigned()) -        v = f.FindVariable("d", lldb.eDynamicCanRunTarget) -        self.assertEqual("*main.AnotherFooer", v.GetType().name) -        self.assertEqual(-1, v.Dereference().GetChildAtIndex(0).GetValueAsSigned()) -        self.assertEqual(-2, v.Dereference().GetChildAtIndex(1).GetValueAsSigned()) -        self.assertEqual(-3, v.Dereference().GetChildAtIndex(2).GetValueAsSigned()) - -if __name__ == '__main__': -    import atexit -    lldb.SBDebugger.Initialize() -    atexit.register(lambda: lldb.SBDebugger.Terminate()) -    unittest2.main() diff --git a/packages/Python/lldbsuite/test/lang/go/runtime/main.go b/packages/Python/lldbsuite/test/lang/go/runtime/main.go deleted file mode 100644 index 227c8c377ed7..000000000000 --- a/packages/Python/lldbsuite/test/lang/go/runtime/main.go +++ /dev/null @@ -1,38 +0,0 @@ -package main - -import "fmt" - -type Fooer interface { -	Foo() int -} - -type SomeFooer struct { -	val int -} - -func (s SomeFooer) Foo() int { -	return s.val -} - -type AnotherFooer struct { -    a, b, c int -} - -func (s AnotherFooer) Foo() int { -	return s.a -} - - -func printEface(a, b, c, d interface{}) { -    fmt.Println(a, b, c, d)  // Set breakpoint 1 -} - -func printIface(a, b Fooer) { -    fmt.Println(a, b)  // Set breakpoint 2 -} -func main() { -    sf := SomeFooer{9} -    af := AnotherFooer{-1, -2, -3} -    printEface(1,2.0, sf, af) -    printIface(sf, af) -}
\ No newline at end of file diff --git a/packages/Python/lldbsuite/test/lang/go/types/TestGoASTContext.py b/packages/Python/lldbsuite/test/lang/go/types/TestGoASTContext.py deleted file mode 100644 index 8fb56b9577af..000000000000 --- a/packages/Python/lldbsuite/test/lang/go/types/TestGoASTContext.py +++ /dev/null @@ -1,145 +0,0 @@ -"""Test the go DWARF type parsing.""" - -from __future__ import print_function - - -import os -import time -import lldb -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil - - -class TestGoASTContext(TestBase): - -    mydir = TestBase.compute_mydir(__file__) - -    @add_test_categories(['pyapi']) -    @skipIfFreeBSD  # llvm.org/pr24895 triggers assertion failure -    @skipIfRemote  # Not remote test suit ready -    @no_debug_info_test -    @skipUnlessGoInstalled -    @expectedFailureAll(bugnumber="llvm.org/pr33643") -    def test_with_dsym_and_python_api(self): -        """Test GoASTContext dwarf parsing.""" -        self.buildGo() -        self.launchProcess() -        self.go_builtin_types() -        self.check_main_vars() - -    def setUp(self): -        # Call super's setUp(). -        TestBase.setUp(self) -        # Find the line numbers to break inside main(). -        self.main_source = "main.go" -        self.break_line = line_number( -            self.main_source, '// Set breakpoint here.') - -    def check_builtin(self, name, size=0, typeclass=lldb.eTypeClassBuiltin): -        tl = self.target().FindTypes(name) -        self.assertEqual(1, len(tl)) -        t = list(tl)[0] -        self.assertEqual(name, t.name) -        self.assertEqual(typeclass, t.type) -        if size > 0: -            self.assertEqual(size, t.size) - -    def launchProcess(self): -        exe = self.getBuildArtifact("a.out") - -        target = self.dbg.CreateTarget(exe) -        self.assertTrue(target, VALID_TARGET) - -        bpt = target.BreakpointCreateByLocation( -            self.main_source, self.break_line) -        self.assertTrue(bpt, 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. -        thread_list = lldbutil.get_threads_stopped_at_breakpoint(process, bpt) - -        # Make sure we stopped at the first breakpoint. -        self.assertTrue( -            len(thread_list) != 0, -            "No thread stopped at our breakpoint.") -        self.assertTrue(len(thread_list) == 1, -                        "More than one thread stopped at our breakpoint.") - -        frame = thread_list[0].GetFrameAtIndex(0) -        self.assertTrue(frame, "Got a valid frame 0 frame.") - -    def go_builtin_types(self): -        address_size = self.target().GetAddressByteSize() -        self.check_builtin('bool') -        self.check_builtin('uint8', 1) -        self.check_builtin('int8', 1) -        self.check_builtin('uint16', 2) -        self.check_builtin('int16', 2) -        self.check_builtin('uint32', 4) -        self.check_builtin('int32', 4) -        self.check_builtin('uint64', 8) -        self.check_builtin('int64', 8) -        self.check_builtin('uintptr', address_size) -        self.check_builtin('int', address_size) -        self.check_builtin('uint', address_size) -        self.check_builtin('float32', 4) -        self.check_builtin('float64', 8) -        self.check_builtin('complex64', 8, lldb.eTypeClassComplexFloat) -        self.check_builtin('complex128', 16, lldb.eTypeClassComplexFloat) - -    def var(self, name): -        var = self.frame().FindVariable(name) -        self.assertTrue(var.IsValid(), "%s %s" % (VALID_VARIABLE, name)) -        return var - -    def check_main_vars(self): -        v = self.var('theBool') -        self.assertEqual('true', v.value) - -        v = self.var('theInt') -        self.assertEqual('-7', v.value) - -        v = self.var('theComplex') -        self.assertEqual('1 + 2i', v.value) - -        v = self.var('thePointer') -        self.assertTrue(v.TypeIsPointerType()) -        self.assertEqual('-10', v.Dereference().value) -        self.assertEqual(1, v.GetNumChildren()) -        self.assertEqual('-10', v.GetChildAtIndex(0).value) - -        # print() -        # print(os.getpid()) -        # time.sleep(60) -        v = self.var('theStruct') -        if v.TypeIsPointerType(): -            v = v.Dereference() -        self.assertEqual(2, v.GetNumChildren()) -        self.assertEqual('7', v.GetChildAtIndex(0).value) -        self.assertEqual('7', v.GetChildMemberWithName('myInt').value) -        self.assertEqual( -            v.load_addr, -            v.GetChildAtIndex(1).GetValueAsUnsigned()) -        self.assertEqual(v.load_addr, v.GetChildMemberWithName( -            'myPointer').GetValueAsUnsigned()) - -        # Test accessing struct fields through pointers. -        v = v.GetChildMemberWithName('myPointer') -        self.assertTrue(v.TypeIsPointerType()) -        self.assertEqual(2, v.GetNumChildren()) -        self.assertEqual('7', v.GetChildAtIndex(0).value) -        c = v.GetChildMemberWithName('myPointer') -        self.assertTrue(c.TypeIsPointerType()) -        self.assertEqual(2, c.GetNumChildren()) -        self.assertEqual('7', c.GetChildAtIndex(0).value) - -        v = self.var('theArray') -        self.assertEqual(5, v.GetNumChildren()) -        for i in list(range(5)): -            self.assertEqual(str(i + 1), v.GetChildAtIndex(i).value) diff --git a/packages/Python/lldbsuite/test/lang/go/types/main.go b/packages/Python/lldbsuite/test/lang/go/types/main.go deleted file mode 100644 index c74650721d7d..000000000000 --- a/packages/Python/lldbsuite/test/lang/go/types/main.go +++ /dev/null @@ -1,47 +0,0 @@ -package main - -import "fmt" - -type Fooer interface { -	Foo() int -} - -type SomeFooer struct { -	val int -} - -func (s SomeFooer) Foo() int { -	return s.val -} - -type mystruct struct { -	myInt int -	myPointer *mystruct -} - -func main() { -	theBool := true -	theInt := -7 -	theComplex := 1 + 2i -	pointee := -10 -	thePointer := &pointee -	theStruct := &mystruct { myInt: 7} -	theStruct.myPointer = theStruct -	theArray := [5]byte{1, 2, 3, 4, 5} -	theSlice := theArray[1:2] -	theString := "abc" -	 -	f := SomeFooer {9} -	var theEface interface{} = f -	var theFooer Fooer = f -	 -	theChan := make(chan int) -	theMap := make(map[int]string) -	theMap[1] = "1" - -	fmt.Println(theBool)  // Set breakpoint here. -	// Reference all the variables so the compiler is happy. -	fmt.Println(theInt, theComplex, thePointer, theStruct.myInt) -	fmt.Println(theArray[0], theSlice[0], theString) -	fmt.Println(theEface, theFooer, theChan, theMap) -}
\ No newline at end of file diff --git a/packages/Python/lldbsuite/test/lang/mixed/TestMixedLanguages.py b/packages/Python/lldbsuite/test/lang/mixed/TestMixedLanguages.py index 2ba57e61349f..a69e8a7aa1f9 100644 --- a/packages/Python/lldbsuite/test/lang/mixed/TestMixedLanguages.py +++ b/packages/Python/lldbsuite/test/lang/mixed/TestMixedLanguages.py @@ -35,7 +35,7 @@ class MixedLanguagesTestCase(TestBase):          self.format_string = m.group(1)          # Change the default format to print the language. -        format_string = "frame #${frame.index}: ${frame.pc}{ ${module.file.basename}`${function.name}{${function.pc-offset}}}{, lang=${language}}\n" +        format_string = "frame #${frame.index}: ${frame.pc}{ ${module.file.basename}\`${function.name}{${function.pc-offset}}}{, lang=${language}}\n"          self.runCmd("settings set frame-format %s" % format_string)          self.expect("settings show frame-format", SETTING_MSG("frame-format"),                      substrs=[format_string]) diff --git a/packages/Python/lldbsuite/test/lang/objc/exceptions/Makefile b/packages/Python/lldbsuite/test/lang/objc/exceptions/Makefile new file mode 100644 index 000000000000..261658b10ae8 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/exceptions/Makefile @@ -0,0 +1,9 @@ +LEVEL = ../../../make + +OBJCXX_SOURCES := main.mm + +CFLAGS_EXTRAS += -w + +include $(LEVEL)/Makefile.rules + +LDFLAGS += -framework Foundation diff --git a/packages/Python/lldbsuite/test/lang/objc/exceptions/TestObjCExceptions.py b/packages/Python/lldbsuite/test/lang/objc/exceptions/TestObjCExceptions.py new file mode 100644 index 000000000000..92b32504cf20 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/exceptions/TestObjCExceptions.py @@ -0,0 +1,205 @@ +# encoding: utf-8 +""" +Test lldb Obj-C exception support. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ObjCExceptionsTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    @skipUnlessDarwin +    def test_objc_exceptions_at_throw(self): +        self.build() + +        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) +        self.assertTrue(target, VALID_TARGET) + +        launch_info = lldb.SBLaunchInfo(["a.out", "0"]) +        lldbutil.run_to_name_breakpoint(self, "objc_exception_throw", launch_info=launch_info) + +        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, +                    substrs=['stopped', 'stop reason = breakpoint']) + +        self.expect('thread exception', substrs=[ +                '(NSException *) exception = ', +                'name: "ThrownException" - reason: "SomeReason"', +            ]) + +        target = self.dbg.GetSelectedTarget() +        thread = target.GetProcess().GetSelectedThread() +        frame = thread.GetSelectedFrame() +         +        opts = lldb.SBVariablesOptions() +        opts.SetIncludeRecognizedArguments(True) +        variables = frame.GetVariables(opts) + +        self.assertEqual(variables.GetSize(), 1) +        self.assertEqual(variables.GetValueAtIndex(0).name, "exception") + +        lldbutil.run_to_source_breakpoint(self, "// Set break point at this line.", lldb.SBFileSpec("main.mm"), launch_info=launch_info) + +        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, +                    substrs=['stopped', 'stop reason = breakpoint']) + +        target = self.dbg.GetSelectedTarget() +        thread = target.GetProcess().GetSelectedThread() +        frame = thread.GetSelectedFrame() + +        # No exception being currently thrown/caught at this point +        self.assertFalse(thread.GetCurrentException().IsValid()) +        self.assertFalse(thread.GetCurrentExceptionBacktrace().IsValid()) + +        self.expect( +            'frame variable e1', +            substrs=[ +                '(NSException *) e1 = ', +                'name: "ExceptionName" - reason: "SomeReason"' +            ]) + +        self.expect( +            'frame variable --dynamic-type no-run-target *e1', +            substrs=[ +                '(NSException) *e1 = ', +                'name = ', '"ExceptionName"', +                'reason = ', '"SomeReason"', +                'userInfo = ', '1 key/value pair', +                'reserved = ', 'nil', +            ]) + +        e1 = frame.FindVariable("e1") +        self.assertTrue(e1) +        self.assertEqual(e1.type.name, "NSException *") +        self.assertEqual(e1.GetSummary(), 'name: "ExceptionName" - reason: "SomeReason"') +        self.assertEqual(e1.GetChildMemberWithName("name").description, "ExceptionName") +        self.assertEqual(e1.GetChildMemberWithName("reason").description, "SomeReason") +        userInfo = e1.GetChildMemberWithName("userInfo").dynamic +        self.assertEqual(userInfo.summary, "1 key/value pair") +        self.assertEqual(userInfo.GetChildAtIndex(0).GetChildAtIndex(0).description, "some_key") +        self.assertEqual(userInfo.GetChildAtIndex(0).GetChildAtIndex(1).description, "some_value") +        self.assertEqual(e1.GetChildMemberWithName("reserved").description, "<nil>") + +        self.expect( +            'frame variable e2', +            substrs=[ +                '(NSException *) e2 = ', +                'name: "ThrownException" - reason: "SomeReason"' +            ]) + +        self.expect( +            'frame variable --dynamic-type no-run-target *e2', +            substrs=[ +                '(NSException) *e2 = ', +                'name = ', '"ThrownException"', +                'reason = ', '"SomeReason"', +                'userInfo = ', '1 key/value pair', +                'reserved = ', +            ]) + +        e2 = frame.FindVariable("e2") +        self.assertTrue(e2) +        self.assertEqual(e2.type.name, "NSException *") +        self.assertEqual(e2.GetSummary(), 'name: "ThrownException" - reason: "SomeReason"') +        self.assertEqual(e2.GetChildMemberWithName("name").description, "ThrownException") +        self.assertEqual(e2.GetChildMemberWithName("reason").description, "SomeReason") +        userInfo = e2.GetChildMemberWithName("userInfo").dynamic +        self.assertEqual(userInfo.summary, "1 key/value pair") +        self.assertEqual(userInfo.GetChildAtIndex(0).GetChildAtIndex(0).description, "some_key") +        self.assertEqual(userInfo.GetChildAtIndex(0).GetChildAtIndex(1).description, "some_value") +        reserved = e2.GetChildMemberWithName("reserved").dynamic +        self.assertGreater(reserved.num_children, 0) +        callStackReturnAddresses = [reserved.GetChildAtIndex(i).GetChildAtIndex(1) for i in range(0, reserved.GetNumChildren()) +                if reserved.GetChildAtIndex(i).GetChildAtIndex(0).description == "callStackReturnAddresses"][0].dynamic +        children = [callStackReturnAddresses.GetChildAtIndex(i) for i in range(0, callStackReturnAddresses.num_children)] + +        pcs = [i.unsigned for i in children] +        names = [target.ResolveSymbolContextForAddress(lldb.SBAddress(pc, target), lldb.eSymbolContextSymbol).GetSymbol().name for pc in pcs] +        for n in ["objc_exception_throw", "foo(int)", "main"]: +            self.assertTrue(n in names, "%s is in the exception backtrace (%s)" % (n, names)) + +    @skipUnlessDarwin +    def test_objc_exceptions_at_abort(self): +        self.build() + +        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) +        self.assertTrue(target, VALID_TARGET) + +        self.runCmd("run 0") + +        # We should be stopped at pthread_kill because of an unhandled exception +        self.expect("thread list", +            substrs=['stopped', 'stop reason = signal SIGABRT']) + +        self.expect('thread exception', substrs=[ +                '(NSException *) exception = ', +                'name: "ThrownException" - reason: "SomeReason"', +                'libobjc.A.dylib`objc_exception_throw', +                'a.out`foo', 'at main.mm:25', +                'a.out`rethrow', 'at main.mm:36', +                'a.out`main', +            ]) + +        process = self.dbg.GetSelectedTarget().process +        thread = process.GetSelectedThread() + +        # There is an exception being currently processed at this point +        self.assertTrue(thread.GetCurrentException().IsValid()) +        self.assertTrue(thread.GetCurrentExceptionBacktrace().IsValid()) + +        history_thread = thread.GetCurrentExceptionBacktrace() +        self.assertGreaterEqual(history_thread.num_frames, 4) +        for n in ["objc_exception_throw", "foo(int)", "rethrow(int)", "main"]: +            self.assertEqual(len([f for f in history_thread.frames if f.GetFunctionName() == n]), 1) + +        self.runCmd("kill") + +        self.runCmd("run 1") +        # We should be stopped at pthread_kill because of an unhandled exception +        self.expect("thread list", +            substrs=['stopped', 'stop reason = signal SIGABRT']) + +        self.expect('thread exception', substrs=[ +                '(MyCustomException *) exception = ', +                'libobjc.A.dylib`objc_exception_throw', +                'a.out`foo', 'at main.mm:27', +                'a.out`rethrow', 'at main.mm:36', +                'a.out`main', +            ]) + +        process = self.dbg.GetSelectedTarget().process +        thread = process.GetSelectedThread() + +        history_thread = thread.GetCurrentExceptionBacktrace() +        self.assertGreaterEqual(history_thread.num_frames, 4) +        for n in ["objc_exception_throw", "foo(int)", "rethrow(int)", "main"]: +            self.assertEqual(len([f for f in history_thread.frames if f.GetFunctionName() == n]), 1) + +    @skipUnlessDarwin +    def test_cxx_exceptions_at_abort(self): +        self.build() + +        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) +        self.assertTrue(target, VALID_TARGET) + +        self.runCmd("run 2") + +        # We should be stopped at pthread_kill because of an unhandled exception +        self.expect("thread list", +            substrs=['stopped', 'stop reason = signal SIGABRT']) + +        self.expect('thread exception', substrs=[]) + +        process = self.dbg.GetSelectedTarget().process +        thread = process.GetSelectedThread() + +        # C++ exceptions are not exposed in the API (yet). +        self.assertFalse(thread.GetCurrentException().IsValid()) +        self.assertFalse(thread.GetCurrentExceptionBacktrace().IsValid()) diff --git a/packages/Python/lldbsuite/test/lang/objc/exceptions/main.mm b/packages/Python/lldbsuite/test/lang/objc/exceptions/main.mm new file mode 100644 index 000000000000..5683882486d8 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/exceptions/main.mm @@ -0,0 +1,63 @@ +//===-- main.m ------------------------------------------------*- ObjC -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#import <Foundation/Foundation.h> + +#import <exception> +#import <stdexcept> + +@interface MyCustomException: NSException +@end +@implementation MyCustomException +@end + +void foo(int n) +{ +    NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:@"some_value", @"some_key", nil]; +    switch (n) { +        case 0: +            @throw [[NSException alloc] initWithName:@"ThrownException" reason:@"SomeReason" userInfo:info]; +        case 1: +            @throw [[MyCustomException alloc] initWithName:@"ThrownException" reason:@"SomeReason" userInfo:info]; +        case 2: +            throw std::runtime_error("C++ exception"); +    } +} + +void rethrow(int n) +{ +    @try { +        foo(n); +    } @catch(NSException *e) { +        @throw; +    } +} + +int main(int argc, const char * argv[]) +{ +    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + +    NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:@"some_value", @"some_key", nil]; +    NSException *e1 = [[NSException alloc] initWithName:@"ExceptionName" reason:@"SomeReason" userInfo:info]; +    NSException *e2; + +    @try { +        foo(atoi(argv[1])); +    } @catch(NSException *e) { +        e2 = e; +    } + +    NSLog(@"1"); // Set break point at this line. + +    rethrow(atoi(argv[1])); + +    [pool drain]; +    return 0; +} + diff --git a/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/TestModulesInlineFunctions.py b/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/TestModulesInlineFunctions.py index 29d386253fb4..e9dbe6af864f 100644 --- a/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/TestModulesInlineFunctions.py +++ b/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/TestModulesInlineFunctions.py @@ -23,8 +23,6 @@ class ModulesInlineFunctionsTestCase(TestBase):      def setUp(self):          # Call super's setUp().          TestBase.setUp(self) -        # Find the line number to break inside main(). -        self.line = line_number('main.m', '// Set breakpoint here.')      @skipUnlessDarwin      @skipIf(macos_version=["<", "10.12"], debug_info=no_match(["gmodules"])) @@ -34,19 +32,8 @@ class ModulesInlineFunctionsTestCase(TestBase):          self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)          # Break inside the foo function which takes a bar_ptr argument. -        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']) - -        # The breakpoint should have a hit count of 1. -        self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, -                    substrs=[' resolved, hit count = 1']) +        lldbutil.run_to_source_breakpoint( +            self, '// Set breakpoint here.', lldb.SBFileSpec('main.m'))          self.runCmd(              "settings set target.clang-module-search-paths \"" + diff --git a/packages/Python/lldbsuite/test/lang/objc/real-definition/Bar.h b/packages/Python/lldbsuite/test/lang/objc/real-definition/Bar.h index 20a81faa1017..5ee6acb2425e 100644 --- a/packages/Python/lldbsuite/test/lang/objc/real-definition/Bar.h +++ b/packages/Python/lldbsuite/test/lang/objc/real-definition/Bar.h @@ -9,4 +9,4 @@  - (NSString *)description; -@end
\ No newline at end of file +@end diff --git a/packages/Python/lldbsuite/test/lang/objc/real-definition/Foo.h b/packages/Python/lldbsuite/test/lang/objc/real-definition/Foo.h index 14ff9eed50fd..d58da600765a 100644 --- a/packages/Python/lldbsuite/test/lang/objc/real-definition/Foo.h +++ b/packages/Python/lldbsuite/test/lang/objc/real-definition/Foo.h @@ -8,4 +8,4 @@  - (NSString *)description; -@end
\ No newline at end of file +@end diff --git a/packages/Python/lldbsuite/test/lldbinline.py b/packages/Python/lldbsuite/test/lldbinline.py index bb925ef908f5..c01fef00fe44 100644 --- a/packages/Python/lldbsuite/test/lldbinline.py +++ b/packages/Python/lldbsuite/test/lldbinline.py @@ -195,7 +195,6 @@ def MakeInlineTest(__file, __globals, decorators=None):      # Derive the test name from the current file name      file_basename = os.path.basename(__file) -    InlineTest.mydir = TestBase.compute_mydir(__file)      test_name, _ = os.path.splitext(file_basename) @@ -209,4 +208,5 @@ def MakeInlineTest(__file, __globals, decorators=None):      # Keep track of the original test filename so we report it      # correctly in test results.      test_class.test_filename = __file +    test_class.mydir = TestBase.compute_mydir(__file)      return test_class diff --git a/packages/Python/lldbsuite/test/lldbtest.py b/packages/Python/lldbsuite/test/lldbtest.py index 1b6302ae96a6..161e8c61349d 100644 --- a/packages/Python/lldbsuite/test/lldbtest.py +++ b/packages/Python/lldbsuite/test/lldbtest.py @@ -72,8 +72,7 @@ from lldbsuite.support import encoded_file  from lldbsuite.support import funcutils  # See also dotest.parseOptionsAndInitTestdirs(), where the environment variables -# LLDB_COMMAND_TRACE and LLDB_DO_CLEANUP are set from '-t' and '-r dir' -# options. +# LLDB_COMMAND_TRACE is set from '-t' option.  # By default, traceAlways is False.  if "LLDB_COMMAND_TRACE" in os.environ and os.environ[ @@ -740,6 +739,11 @@ class Base(unittest2.TestCase):          else:              self.lldbMiExec = None +        if "LLDBVSCODE_EXEC" in os.environ: +            self.lldbVSCodeExec = os.environ["LLDBVSCODE_EXEC"] +        else: +            self.lldbVSCodeExec = None +          # If we spawn an lldb process for test (via pexpect), do not load the          # init file unless told otherwise.          if "NO_LLDBINIT" in os.environ and "NO" == os.environ["NO_LLDBINIT"]: @@ -1215,12 +1219,15 @@ class Base(unittest2.TestCase):                  if os.path.isfile(src):                      dst = src.replace(self.log_basename, dst_log_basename)                      if os.name == "nt" and os.path.isfile(dst): -                        # On Windows, renaming a -> b will throw an exception if b exists.  On non-Windows platforms -                        # it silently replaces the destination.  Ultimately this means that atomic renames are not -                        # guaranteed to be possible on Windows, but we need this to work anyway, so just remove the -                        # destination first if it already exists. +                        # On Windows, renaming a -> b will throw an exception if +                        # b exists.  On non-Windows platforms it silently +                        # replaces the destination.  Ultimately this means that +                        # atomic renames are not guaranteed to be possible on +                        # Windows, but we need this to work anyway, so just +                        # remove the destination first if it already exists.                          remove_file(dst) +                    lldbutil.mkdir_p(os.path.dirname(dst))                      os.rename(src, dst)          else:              # success!  (and we don't want log files) delete log files @@ -1302,18 +1309,6 @@ class Base(unittest2.TestCase):                  version = m.group(1)          return version -    def getGoCompilerVersion(self): -        """ Returns a string that represents the go compiler version, or None if go is not found. -        """ -        compiler = which("go") -        if compiler: -            version_output = system([[compiler, "version"]])[0] -            for line in version_output.split(os.linesep): -                m = re.search('go version (devel|go\\S+)', line) -                if m: -                    return m.group(1) -        return None -      def platformIsDarwin(self):          """Returns true if the OS triple for the selected platform is any valid apple OS"""          return lldbplatformutil.platformIsDarwin() @@ -1582,12 +1577,6 @@ class Base(unittest2.TestCase):                                      dictionary, testdir, testname):              raise Exception("Don't know how to build binary with gmodules") -    def buildGo(self): -        """Build the default go binary. -        """ -        exe = self.getBuildArtifact("a.out") -        system([[which('go'), 'build -gcflags "-N -l" -o %s main.go' % exe]]) -      def signBinary(self, binary_path):          if sys.platform.startswith("darwin"):              codesign_cmd = "codesign --force --sign \"%s\" %s" % ( @@ -1875,18 +1864,16 @@ class TestBase(Base):          # decorators.          Base.setUp(self) -        if self.child: -            # Set the clang modules cache path. -            assert(self.getDebugInfo() == 'default') -            mod_cache = os.path.join(self.getBuildDir(), "module-cache") -            self.runCmd('settings set symbols.clang-modules-cache-path "%s"' -                        % mod_cache) - -            # Disable Spotlight lookup. The testsuite creates -            # different binaries with the same UUID, because they only -            # differ in the debug info, which is not being hashed. -            self.runCmd('settings set symbols.enable-external-lookup false') +        # Set the clang modules cache path used by LLDB. +        mod_cache = os.path.join(os.path.join(os.environ["LLDB_BUILD"], +                                              "module-cache-lldb")) +        self.runCmd('settings set symbols.clang-modules-cache-path "%s"' +                    % mod_cache) +        # Disable Spotlight lookup. The testsuite creates +        # different binaries with the same UUID, because they only +        # differ in the debug info, which is not being hashed. +        self.runCmd('settings set symbols.enable-external-lookup false')          if "LLDB_MAX_LAUNCH_COUNT" in os.environ:              self.maxLaunchCount = int(os.environ["LLDB_MAX_LAUNCH_COUNT"]) @@ -2074,8 +2061,17 @@ class TestBase(Base):                      print("Command '" + cmd + "' failed!", file=sbuf)          if check: +            output = "" +            if self.res.GetOutput(): +              output += "\nCommand output:\n" + self.res.GetOutput() +            if self.res.GetError(): +              output += "\nError output:\n" + self.res.GetError() +            if msg: +              msg += output +            if cmd: +              cmd += output              self.assertTrue(self.res.Succeeded(), -                            msg if msg else CMD_MSG(cmd)) +                            msg if (msg) else CMD_MSG(cmd))      def match(              self, @@ -2134,6 +2130,126 @@ class TestBase(Base):          return match_object +    def check_completion_with_desc(self, str_input, match_desc_pairs): +        interp = self.dbg.GetCommandInterpreter() +        match_strings = lldb.SBStringList() +        description_strings = lldb.SBStringList() +        num_matches = interp.HandleCompletionWithDescriptions(str_input, len(str_input), 0, -1, match_strings, description_strings) +        self.assertEqual(len(description_strings), len(match_strings)) + +        missing_pairs = [] +        for pair in match_desc_pairs: +            found_pair = False +            for i in range(num_matches + 1): +                match_candidate = match_strings.GetStringAtIndex(i) +                description_candidate = description_strings.GetStringAtIndex(i) +                if match_candidate == pair[0] and description_candidate == pair[1]: +                    found_pair = True +                    break +            if not found_pair: +                missing_pairs.append(pair) + +        if len(missing_pairs): +            error_msg = "Missing pairs:\n" +            for pair in missing_pairs: +                error_msg += " [" + pair[0] + ":" + pair[1] + "]\n" +            error_msg += "Got the following " + str(num_matches) + " completions back:\n" +            for i in range(num_matches + 1): +                match_candidate = match_strings.GetStringAtIndex(i) +                description_candidate = description_strings.GetStringAtIndex(i) +                error_msg += "[" + match_candidate + ":" + description_candidate + "]\n" +            self.assertEqual(0, len(missing_pairs), error_msg) + +    def complete_exactly(self, str_input, patterns): +        self.complete_from_to(str_input, patterns, True) + +    def complete_from_to(self, str_input, patterns, turn_off_re_match=False): +        """Test that the completion mechanism completes str_input to patterns, +        where patterns could be a pattern-string or a list of pattern-strings""" +        # Patterns should not be None in order to proceed. +        self.assertFalse(patterns is None) +        # And should be either a string or list of strings.  Check for list type +        # below, if not, make a list out of the singleton string.  If patterns +        # is not a string or not a list of strings, there'll be runtime errors +        # later on. +        if not isinstance(patterns, list): +            patterns = [patterns] + +        interp = self.dbg.GetCommandInterpreter() +        match_strings = lldb.SBStringList() +        num_matches = interp.HandleCompletion(str_input, len(str_input), 0, -1, match_strings) +        common_match = match_strings.GetStringAtIndex(0) +        if num_matches == 0: +            compare_string = str_input +        else: +            if common_match != None and len(common_match) > 0: +                compare_string = str_input + common_match +            else: +                compare_string = "" +                for idx in range(1, num_matches+1): +                    compare_string += match_strings.GetStringAtIndex(idx) + "\n" + +        for p in patterns: +            if turn_off_re_match: +                self.expect( +                    compare_string, msg=COMPLETION_MSG( +                        str_input, p, match_strings), exe=False, substrs=[p]) +            else: +                self.expect( +                    compare_string, msg=COMPLETION_MSG( +                        str_input, p, match_strings), exe=False, patterns=[p]) + +    def filecheck( +            self, +            command, +            check_file, +            filecheck_options = ''): +        # Run the command. +        self.runCmd( +                command, +                msg="FileCheck'ing result of `{0}`".format(command)) + +        # Get the error text if there was an error, and the regular text if not. +        output = self.res.GetOutput() if self.res.Succeeded() \ +                else self.res.GetError() + +        # Assemble the absolute path to the check file. As a convenience for +        # LLDB inline tests, assume that the check file is a relative path to +        # a file within the inline test directory. +        if check_file.endswith('.pyc'): +            check_file = check_file[:-1] +        check_file_abs = os.path.abspath(check_file) + +        # Run FileCheck. +        filecheck_bin = configuration.get_filecheck_path() +        if not filecheck_bin: +            self.assertTrue(False, "No valid FileCheck executable specified") +        filecheck_args = [filecheck_bin, check_file_abs] +        if filecheck_options: +            filecheck_args.append(filecheck_options) +        subproc = Popen(filecheck_args, stdin=PIPE, stdout=PIPE, stderr=PIPE, universal_newlines = True) +        cmd_stdout, cmd_stderr = subproc.communicate(input=output) +        cmd_status = subproc.returncode + +        filecheck_cmd = " ".join(filecheck_args) +        filecheck_trace = """ +--- FileCheck trace (code={0}) --- +{1} + +FileCheck input: +{2} + +FileCheck output: +{3} +{4} +""".format(cmd_status, filecheck_cmd, output, cmd_stdout, cmd_stderr) + +        trace = cmd_status != 0 or traceAlways +        with recording(self, trace) as sbuf: +            print(filecheck_trace, file=sbuf) + +        self.assertTrue(cmd_status == 0) +      def expect(              self,              str, diff --git a/packages/Python/lldbsuite/test/lldbutil.py b/packages/Python/lldbsuite/test/lldbutil.py index dc84383333ee..16950d7b5cdb 100644 --- a/packages/Python/lldbsuite/test/lldbutil.py +++ b/packages/Python/lldbsuite/test/lldbutil.py @@ -330,6 +330,20 @@ def sort_stopped_threads(process,  # Utility functions for setting breakpoints  # ================================================== +def run_break_set_by_script( +        test, +        class_name, +        extra_options=None, +        num_expected_locations=1): +    """Set a scripted breakpoint.  Check that it got the right number of locations.""" +    test.assertTrue(class_name is not None, "Must pass in a class name.") +    command = "breakpoint set -P " + class_name +    if extra_options is not None: +        command += " " + extra_options + +    break_results = run_break_set_command(test, command) +    check_breakpoint_result(test, break_results, num_locations=num_expected_locations) +    return get_bpno_from_match(break_results)  def run_break_set_by_file_and_line(          test, @@ -511,7 +525,7 @@ def run_break_set_command(test, command):      patterns = [          r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>[0-9]+) locations\.$",          r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>no) locations \(pending\)\.", -        r"^Breakpoint (?P<bpno>[0-9]+): where = (?P<module>.*)`(?P<symbol>[+\-]{0,1}[^+]+)( \+ (?P<offset>[0-9]+)){0,1}( \[inlined\] (?P<inline_symbol>.*)){0,1} at (?P<file>[^:]+):(?P<line_no>[0-9]+), address = (?P<address>0x[0-9a-fA-F]+)$", +        r"^Breakpoint (?P<bpno>[0-9]+): where = (?P<module>.*)`(?P<symbol>[+\-]{0,1}[^+]+)( \+ (?P<offset>[0-9]+)){0,1}( \[inlined\] (?P<inline_symbol>.*)){0,1} at (?P<file>[^:]+):(?P<line_no>[0-9]+)(?P<column>(:[0-9]+)?), address = (?P<address>0x[0-9a-fA-F]+)$",          r"^Breakpoint (?P<bpno>[0-9]+): where = (?P<module>.*)`(?P<symbol>.*)( \+ (?P<offset>[0-9]+)){0,1}, address = (?P<address>0x[0-9a-fA-F]+)$"]      match_object = test.match(command, patterns)      break_results = match_object.groupdict() @@ -722,6 +736,8 @@ def is_thread_crashed(test, thread):      elif test.getPlatform() == "linux":          return thread.GetStopReason() == lldb.eStopReasonSignal and thread.GetStopReasonDataAtIndex(              0) == thread.GetProcess().GetUnixSignals().GetSignalNumberFromName("SIGSEGV") +    elif test.getPlatform() == "windows": +        return "Exception 0xc0000005" in thread.GetStopDescription(100)      else:          return "invalid address" in thread.GetStopDescription(100) @@ -737,7 +753,7 @@ def get_crashed_threads(test, process):  # Helper functions for run_to_{source,name}_breakpoint: -def run_to_breakpoint_make_target(test, exe_name, in_cwd): +def run_to_breakpoint_make_target(test, exe_name = "a.out", in_cwd = True):      if in_cwd:          exe = test.getBuildArtifact(exe_name) @@ -746,7 +762,7 @@ def run_to_breakpoint_make_target(test, exe_name, in_cwd):      test.assertTrue(target, "Target: %s is not valid."%(exe_name))      return target -def run_to_breakpoint_do_run(test, target, bkpt, launch_info): +def run_to_breakpoint_do_run(test, target, bkpt, launch_info = None):      # Launch the process, and do not stop at the entry point.      if not launch_info: @@ -819,9 +835,31 @@ def run_to_source_breakpoint(test, bkpt_pattern, source_spec,      breakpoint = target.BreakpointCreateBySourceRegex(              bkpt_pattern, source_spec, bkpt_module)      test.assertTrue(breakpoint.GetNumLocations() > 0, -                    'No locations found for source breakpoint: "%s", file: "%s", dir: "%s"'%(bkpt_pattern, source_spec.GetFilename(), source_spec.GetDirectory())) +        'No locations found for source breakpoint: "%s", file: "%s", dir: "%s"' +        %(bkpt_pattern, source_spec.GetFilename(), source_spec.GetDirectory()))      return run_to_breakpoint_do_run(test, target, breakpoint, launch_info) +def run_to_line_breakpoint(test, source_spec, line_number, column = 0, +                           launch_info = None, exe_name = "a.out", +                           bkpt_module = None, +                           in_cwd = True): +    """Start up a target, using exe_name as the executable, and run it to +       a breakpoint set by (source_spec, line_number(, column)). + +       The rest of the behavior is the same as run_to_name_breakpoint. +    """ + +    target = run_to_breakpoint_make_target(test, exe_name, in_cwd) +    # Set the breakpoints +    breakpoint = target.BreakpointCreateByLocation( +        source_spec, line_number, column, 0, lldb.SBFileSpecList()) +    test.assertTrue(breakpoint.GetNumLocations() > 0, +        'No locations found for line breakpoint: "%s:%d(:%d)", dir: "%s"' +        %(source_spec.GetFilename(), line_number, column, +          source_spec.GetDirectory())) +    return run_to_breakpoint_do_run(test, target, breakpoint, launch_info) + +  def continue_to_breakpoint(process, bkpt):      """ Continues the process, if it stops, returns the threads stopped at bkpt; otherwise, returns None"""      process.Continue() diff --git a/packages/Python/lldbsuite/test/macosx/function-starts/Makefile b/packages/Python/lldbsuite/test/macosx/function-starts/Makefile new file mode 100644 index 000000000000..091876d51c35 --- /dev/null +++ b/packages/Python/lldbsuite/test/macosx/function-starts/Makefile @@ -0,0 +1,10 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp +EXE := StripMe +MAKE_DSYM := NO + +include $(LEVEL)/Makefile.rules + +main.o: main.cpp +	$(CC) $(CFLAGS_NO_DEBUG) -c $< -o $@ diff --git a/packages/Python/lldbsuite/test/macosx/function-starts/TestFunctionStarts.py b/packages/Python/lldbsuite/test/macosx/function-starts/TestFunctionStarts.py new file mode 100644 index 000000000000..ae3b825f95cb --- /dev/null +++ b/packages/Python/lldbsuite/test/macosx/function-starts/TestFunctionStarts.py @@ -0,0 +1,76 @@ +""" +Test that we read the function starts section. +""" + +from __future__ import print_function + + +import os +import time +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +exe_name = "StripMe"  # Must match Makefile + +class FunctionStartsTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    NO_DEBUG_INFO_TESTCASE = True + +    @skipIfRemote +    @skipUnlessDarwin +    def test_function_starts_binary(self): +        """Test that we make synthetic symbols when we have the binary.""" +        self.build() +        self.do_function_starts(False) + +    @skipIfRemote +    @skipUnlessDarwin +    def test_function_starts_no_binary(self): +        """Test that we make synthetic symbols when we don't have the binary""" +        self.build() +        self.do_function_starts(True) + +    def do_function_starts(self, in_memory): +        """Run the binary, stop at our unstripped function,  +           make sure the caller has synthetic symbols""" + +        exe = self.getBuildArtifact(exe_name) +        # Now strip the binary, but leave externals so we can break on dont_strip_me. +        try: +            fail_str = system([["strip", "-u", "-x", "-S", exe]]) +        except CalledProcessError as cmd_error: +            self.fail("Strip failed: %d"%(cmd_error.returncode)) + +        popen = self.spawnSubprocess(exe) +        self.addTearDownHook(self.cleanupSubprocesses) +        if in_memory: +          remove_file(exe)             + +        target = self.dbg.CreateTarget(None) +        self.assertTrue(target.IsValid(), "Got a vaid empty target.") +        error = lldb.SBError() +        attach_info = lldb.SBAttachInfo() +        attach_info.SetProcessID(popen.pid) +        attach_info.SetIgnoreExisting(False) +        process = target.Attach(attach_info, error) +        self.assertTrue(error.Success(), "Didn't attach successfully to %d: %s"%(popen.pid, error.GetCString())) +         +        bkpt = target.BreakpointCreateByName("dont_strip_me", exe) +        self.assertTrue(bkpt.GetNumLocations() > 0, "Didn't set the dont_strip_me bkpt.") +         +        threads = lldbutil.continue_to_breakpoint(process, bkpt) +        self.assertEqual(len(threads), 1, "Didn't hit my breakpoint.") + +        # Our caller frame should have been stripped.  Make sure we made a synthetic symbol +        # for it: +        thread = threads[0] +        self.assertTrue(thread.num_frames > 1, "Couldn't backtrace.") +        name = thread.frame[1].GetFunctionName() +        self.assertEqual("___lldb_unnamed_symbol1$$StripMe", name, "Frame name not synthetic") +         + +         diff --git a/packages/Python/lldbsuite/test/macosx/function-starts/main.cpp b/packages/Python/lldbsuite/test/macosx/function-starts/main.cpp new file mode 100644 index 000000000000..5a14506d6913 --- /dev/null +++ b/packages/Python/lldbsuite/test/macosx/function-starts/main.cpp @@ -0,0 +1,26 @@ +#include <stdio.h> +#include <fcntl.h> + +#include <chrono> +#include <thread> + +extern void dont_strip_me() +{ +  printf("I wasn't stripped\n"); +} + +static void *a_function() +{ +    while (1) +    { +        std::this_thread::sleep_for(std::chrono::microseconds(100));  +        dont_strip_me(); +    } +    return 0; +} + +int main(int argc, char const *argv[]) +{ +    a_function(); +    return 0; +} diff --git a/packages/Python/lldbsuite/test/macosx/load-kext/TestLoadKext.py b/packages/Python/lldbsuite/test/macosx/load-kext/TestLoadKext.py new file mode 100644 index 000000000000..1bd5ec020dbe --- /dev/null +++ b/packages/Python/lldbsuite/test/macosx/load-kext/TestLoadKext.py @@ -0,0 +1,38 @@ +""" +Test loading of a kext binary. +""" + +from __future__ import print_function + +import shutil +import struct + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class LoadKextTestCase(TestBase): +    NO_DEBUG_INFO_TESTCASE = True + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        TestBase.setUp(self) +        #super(LoadKextTestCase, self).setUp() +        #self._initial_platform = lldb.DBG.GetSelectedPlatform() + +    def test_load_kext(self): +        """Test that lldb can load a kext binary.""" + +        # Create kext from YAML. +        self.yaml2obj("mykext.yaml", self.getBuildArtifact("mykext")) + +        target = self.dbg.CreateTarget(self.getBuildArtifact("mykext")) + +        self.assertTrue(target.IsValid()) + +        self.assertEqual(target.GetNumModules(), 1) +        mod = target.GetModuleAtIndex(0) +        self.assertEqual(mod.GetFileSpec().GetFilename(), "mykext") diff --git a/packages/Python/lldbsuite/test/macosx/load-kext/mykext.yaml b/packages/Python/lldbsuite/test/macosx/load-kext/mykext.yaml new file mode 100644 index 000000000000..ccf016304c84 --- /dev/null +++ b/packages/Python/lldbsuite/test/macosx/load-kext/mykext.yaml @@ -0,0 +1,222 @@ +--- !mach-o +FileHeader:       +  magic:           0xFEEDFACF +  cputype:         0x01000007 +  cpusubtype:      0x00000003 +  filetype:        0x0000000B +  ncmds:           7 +  sizeofcmds:      520 +  flags:           0x00000085 +  reserved:        0x00000000 +LoadCommands:     +  - cmd:             LC_SEGMENT_64 +    cmdsize:         152 +    segname:         __TEXT +    vmaddr:          0 +    vmsize:          4096 +    fileoff:         0 +    filesize:        4096 +    maxprot:         7 +    initprot:        5 +    nsects:          1 +    flags:           0 +    Sections:         +      - sectname:        __text +        segname:         __TEXT +        addr:            0x0000000000000F60 +        size:            158 +        offset:          0x00000F60 +        align:           4 +        reloff:          0x00000000 +        nreloc:          0 +        flags:           0x80000400 +        reserved1:       0x00000000 +        reserved2:       0x00000000 +        reserved3:       0x00000000 +  - cmd:             LC_SEGMENT_64 +    cmdsize:         152 +    segname:         __DATA +    vmaddr:          4096 +    vmsize:          4096 +    fileoff:         4096 +    filesize:        4096 +    maxprot:         7 +    initprot:        3 +    nsects:          1 +    flags:           0 +    Sections:         +      - sectname:        __data +        segname:         __DATA +        addr:            0x0000000000001000 +        size:            220 +        offset:          0x00001000 +        align:           3 +        reloff:          0x00000000 +        nreloc:          0 +        flags:           0x00000000 +        reserved1:       0x00000000 +        reserved2:       0x00000000 +        reserved3:       0x00000000 +  - cmd:             LC_SEGMENT_64 +    cmdsize:         72 +    segname:         __LINKEDIT +    vmaddr:          8192 +    vmsize:          4096 +    fileoff:         8192 +    filesize:        800 +    maxprot:         7 +    initprot:        1 +    nsects:          0 +    flags:           0 +  - cmd:             LC_SYMTAB +    cmdsize:         24 +    symoff:          8224 +    nsyms:           19 +    stroff:          8528 +    strsize:         464 +  - cmd:             LC_DYSYMTAB +    cmdsize:         80 +    ilocalsym:       0 +    nlocalsym:       16 +    iextdefsym:      16 +    nextdefsym:      3 +    iundefsym:       19 +    nundefsym:       0 +    tocoff:          0 +    ntoc:            0 +    modtaboff:       0 +    nmodtab:         0 +    extrefsymoff:    0 +    nextrefsyms:     0 +    indirectsymoff:  0 +    nindirectsyms:   0 +    extreloff:       0 +    nextrel:         0 +    locreloff:       8192 +    nlocrel:         4 +  - cmd:             LC_UUID +    cmdsize:         24 +    uuid:            17A97B33-09B7-3195-9408-DBD965D578A5 +  - cmd:             LC_SOURCE_VERSION +    cmdsize:         16 +    version:         0 +LinkEditData:     +  NameList:         +    - n_strx:          40 +      n_type:          0x64 +      n_sect:          0 +      n_desc:          0 +      n_value:         0 +    - n_strx:          141 +      n_type:          0x64 +      n_sect:          0 +      n_desc:          0 +      n_value:         0 +    - n_strx:          155 +      n_type:          0x66 +      n_sect:          3 +      n_desc:          1 +      n_value:         1543540349 +    - n_strx:          276 +      n_type:          0x20 +      n_sect:          0 +      n_desc:          0 +      n_value:         0 +    - n_strx:          287 +      n_type:          0x20 +      n_sect:          0 +      n_desc:          0 +      n_value:         0 +    - n_strx:          298 +      n_type:          0x20 +      n_sect:          0 +      n_desc:          0 +      n_value:         0 +    - n_strx:          309 +      n_type:          0x20 +      n_sect:          0 +      n_desc:          0 +      n_value:         0 +    - n_strx:          1 +      n_type:          0x64 +      n_sect:          1 +      n_desc:          0 +      n_value:         0 +    - n_strx:          325 +      n_type:          0x1E +      n_sect:          1 +      n_desc:          0 +      n_value:         3992 +    - n_strx:          333 +      n_type:          0x1E +      n_sect:          1 +      n_desc:          0 +      n_value:         4018 +    - n_strx:          361 +      n_type:          0x1E +      n_sect:          1 +      n_desc:          0 +      n_value:         4035 +    - n_strx:          392 +      n_type:          0x1E +      n_sect:          1 +      n_desc:          0 +      n_value:         4052 +    - n_strx:          417 +      n_type:          0x1E +      n_sect:          1 +      n_desc:          0 +      n_value:         4068 +    - n_strx:          424 +      n_type:          0x1E +      n_sect:          2 +      n_desc:          0 +      n_value:         4296 +    - n_strx:          435 +      n_type:          0x1E +      n_sect:          2 +      n_desc:          0 +      n_value:         4304 +    - n_strx:          446 +      n_type:          0x1E +      n_sect:          2 +      n_desc:          0 +      n_value:         4312 +    - n_strx:          2 +      n_type:          0x0F +      n_sect:          2 +      n_desc:          0 +      n_value:         4096 +    - n_strx:          13 +      n_type:          0x0F +      n_sect:          1 +      n_desc:          0 +      n_value:         3936 +    - n_strx:          27 +      n_type:          0x0F +      n_sect:          1 +      n_desc:          0 +      n_value:         3968 +  StringTable:      +    - ' ' +    - _kmod_info +    - _mykext_start +    - _mykext_stop +    - /tmp/mykext/build/mykext/Build/Intermediates.noindex/mykext.build/Debug/mykext.build/DerivedSources/ +    - mykext_info.c +    - /tmp/mykext/build/mykext/Build/Intermediates.noindex/mykext.build/Debug/mykext.build/Objects-normal/x86_64/mykext_info.o +    - _kmod_info +    - __realmain +    - __antimain +    - __kext_apple_cc +    - __start +    - _OSKextGetCurrentIdentifier +    - _OSKextGetCurrentVersionString +    - _OSKextGetCurrentLoadTag +    - __stop +    - __realmain +    - __antimain +    - __kext_apple_cc +    - '' +    - '' +... diff --git a/packages/Python/lldbsuite/test/macosx/nslog/TestDarwinNSLogOutput.py b/packages/Python/lldbsuite/test/macosx/nslog/TestDarwinNSLogOutput.py index 59b325f57984..287c1c1b87b3 100644 --- a/packages/Python/lldbsuite/test/macosx/nslog/TestDarwinNSLogOutput.py +++ b/packages/Python/lldbsuite/test/macosx/nslog/TestDarwinNSLogOutput.py @@ -95,7 +95,8 @@ class DarwinNSLogOutputTestCase(TestBase):          self.expect(re.compile(r"stop reason = breakpoint"))      def runCmd(self, cmd): -        self.child.sendline(cmd) +        if self.child: +            self.child.sendline(cmd)      def expect_prompt(self, exactly=True):          self.expect(self.child_prompt, exactly=exactly) diff --git a/packages/Python/lldbsuite/test/macosx/queues/TestQueues.py b/packages/Python/lldbsuite/test/macosx/queues/TestQueues.py index ba58372ce5b7..cdc9606c377a 100644 --- a/packages/Python/lldbsuite/test/macosx/queues/TestQueues.py +++ b/packages/Python/lldbsuite/test/macosx/queues/TestQueues.py @@ -18,10 +18,16 @@ class TestQueues(TestBase):      @skipUnlessDarwin      @add_test_categories(['pyapi']) -    def test_with_python_api(self): +    def test_with_python_api_queues(self):          """Test queues inspection SB APIs."""          self.build()          self.queues() + +    @skipUnlessDarwin +    @add_test_categories(['pyapi']) +    def test_with_python_api_queues_with_backtrace(self): +        """Test queues inspection SB APIs.""" +        self.build()          self.queues_with_libBacktraceRecording()      def setUp(self): @@ -113,7 +119,7 @@ class TestQueues(TestBase):          break1 = target.BreakpointCreateByName("stopper", 'a.out')          self.assertTrue(break1, VALID_BREAKPOINT)          process = target.LaunchSimple( -            None, None, self.get_process_working_directory()) +            [], None, self.get_process_working_directory())          self.assertTrue(process, PROCESS_IS_VALID)          threads = lldbutil.get_threads_stopped_at_breakpoint(process, break1)          if len(threads) != 1: @@ -267,10 +273,14 @@ class TestQueues(TestBase):          self.assertTrue(break1, VALID_BREAKPOINT)          # Now launch the process, and do not stop at entry point. +        libbtr_path = "/Applications/Xcode.app/Contents/Developer/usr/lib/libBacktraceRecording.dylib" +        if self.getArchitecture() in ['arm', 'arm64', 'arm64e', 'arm64_32', 'armv7', 'armv7k']: +            libbtr_path = "/Developer/usr/lib/libBacktraceRecording.dylib" +          process = target.LaunchSimple( -            None, +            [],              [ -                'DYLD_INSERT_LIBRARIES=/Applications/Xcode.app/Contents/Developer/usr/lib/libBacktraceRecording.dylib', +                'DYLD_INSERT_LIBRARIES=%s' % (libbtr_path),                  'DYLD_LIBRARY_PATH=/usr/lib/system/introspection'],              self.get_process_working_directory()) diff --git a/packages/Python/lldbsuite/test/macosx/queues/main.c b/packages/Python/lldbsuite/test/macosx/queues/main.c index 715a3f3af52c..3978b92bff1a 100644 --- a/packages/Python/lldbsuite/test/macosx/queues/main.c +++ b/packages/Python/lldbsuite/test/macosx/queues/main.c @@ -1,13 +1,18 @@ -#include <stdio.h> +#include <stdatomic.h> +#include <string.h>  #include <unistd.h>  #include <dispatch/dispatch.h>  #include <pthread.h> -int finished_enqueueing_work = 0; +atomic_int finished_enqueueing_work = 0; +atomic_int thread_count = 0;  void  doing_the_work_1(void *in)  { +    // This is only counted once because the first job in the queue +    // starves all the others. +    atomic_fetch_add(&thread_count, 1);      while (1)          sleep (1);  } @@ -26,13 +31,15 @@ submit_work_1b(void *in)      dispatch_queue_t *work_performer_1 = (dispatch_queue_t*) in;      dispatch_async_f (*work_performer_1, NULL, doing_the_work_1);      dispatch_async_f (*work_performer_1, NULL, doing_the_work_1); +    atomic_fetch_add(&thread_count, 1);      while (1) -      sleep (1); +        sleep (1);  }  void  doing_the_work_2(void *in)  { +    atomic_fetch_add(&thread_count, 1);      while (1)          sleep (1);  } @@ -42,20 +49,22 @@ submit_work_2(void *in)  {      dispatch_queue_t *work_performer_2 = (dispatch_queue_t*) in;      int i = 0; -    while (i++ <  5000) +    while (i++ < 5000)      {          dispatch_async_f (*work_performer_2, NULL, doing_the_work_2);          dispatch_async_f (*work_performer_2, NULL, doing_the_work_2);      } -    finished_enqueueing_work = 1; +    atomic_fetch_add(&finished_enqueueing_work, 1);  }  void  doing_the_work_3(void *in)  { +    // This counts four times, since the queue is marked as CONCURRENT. +    atomic_fetch_add(&thread_count, 1);      while (1) -        sleep(1); +        sleep (1);  }  void @@ -77,7 +86,7 @@ stopper ()  } -int main () +int main (int argc, const char **argv)  {      dispatch_queue_t work_submittor_1 = dispatch_queue_create ("com.apple.work_submittor_1", DISPATCH_QUEUE_SERIAL);      dispatch_queue_t work_submittor_2 = dispatch_queue_create ("com.apple.work_submittor_and_quit_2", DISPATCH_QUEUE_SERIAL); @@ -97,41 +106,46 @@ int main ()      // Spin up threads with each of the different libdispatch QoS values. -      dispatch_async (dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{              pthread_setname_np ("user initiated QoS"); +            atomic_fetch_add(&thread_count, 1);              while (1)                  sleep (10); -                }); +      });      dispatch_async (dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{              pthread_setname_np ("user interactive QoS"); +            atomic_fetch_add(&thread_count, 1);              while (1)                  sleep (10); -                }); +      });      dispatch_async (dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), ^{              pthread_setname_np ("default QoS"); +            atomic_fetch_add(&thread_count, 1);              while (1)                  sleep (10); -                }); +      });      dispatch_async (dispatch_get_global_queue(QOS_CLASS_UTILITY, 0), ^{              pthread_setname_np ("utility QoS"); +            atomic_fetch_add(&thread_count, 1);              while (1)                  sleep (10); -                }); +      });      dispatch_async (dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), ^{              pthread_setname_np ("background QoS"); +            atomic_fetch_add(&thread_count, 1);              while (1)                  sleep (10); -                }); +      });      dispatch_async (dispatch_get_global_queue(QOS_CLASS_UNSPECIFIED, 0), ^{              pthread_setname_np ("unspecified QoS"); +            atomic_fetch_add(&thread_count, 1);              while (1)                  sleep (10); -                }); +      }); - -    while (finished_enqueueing_work == 0) +    // Unfortunately there is no pthread_barrier on darwin. +    while ((atomic_load(&thread_count) < 13) || (finished_enqueueing_work == 0))          sleep (1); -    stopper (); +    stopper ();  } diff --git a/packages/Python/lldbsuite/test/macosx/safe-to-func-call/main.c b/packages/Python/lldbsuite/test/macosx/safe-to-func-call/main.c index 613384ff73b3..586500876288 100644 --- a/packages/Python/lldbsuite/test/macosx/safe-to-func-call/main.c +++ b/packages/Python/lldbsuite/test/macosx/safe-to-func-call/main.c @@ -1,3 +1,4 @@ +#include <sys/time.h>  // work around module map issue with iOS sdk, <rdar://problem/35159346>   #include <sys/select.h>  #include <stdio.h>  #include <pthread.h> diff --git a/packages/Python/lldbsuite/test/macosx/universal/Makefile b/packages/Python/lldbsuite/test/macosx/universal/Makefile index d74ed26f50ab..a83de2a6c7e6 100644 --- a/packages/Python/lldbsuite/test/macosx/universal/Makefile +++ b/packages/Python/lldbsuite/test/macosx/universal/Makefile @@ -1,21 +1,25 @@ -CC ?= clang +LEVEL := ../../make + +EXE := testit + +include $(LEVEL)/Makefile.rules  all: testit -testit: testit.i386 testit.x86_64 +testit: testit.x86_64h testit.x86_64  	lipo -create -o testit $^ -testit.i386: testit.i386.o -	$(CC) -arch i386 -o testit.i386 $< +testit.x86_64h: testit.x86_64h.o +	$(CC) -arch x86_64h -o testit.x86_64h $<  testit.x86_64: testit.x86_64.o  	$(CC) -arch x86_64 -o testit.x86_64 $< -testit.i386.o: main.c -	$(CC) -g -O0 -arch i386 -c -o testit.i386.o $< +testit.x86_64h.o: main.c +	$(CC) -g -O0 -arch x86_64h -c -o testit.x86_64h.o $<  testit.x86_64.o: main.c  	$(CC) -g -O0 -arch x86_64 -c -o testit.x86_64.o $< -clean: +clean::  	rm -rf $(wildcard testit* *~) diff --git a/packages/Python/lldbsuite/test/macosx/universal/TestUniversal.py b/packages/Python/lldbsuite/test/macosx/universal/TestUniversal.py index ca4f3ce9b137..93fb358f4c84 100644 --- a/packages/Python/lldbsuite/test/macosx/universal/TestUniversal.py +++ b/packages/Python/lldbsuite/test/macosx/universal/TestUniversal.py @@ -11,9 +11,13 @@ from lldbsuite.test.decorators import *  from lldbsuite.test.lldbtest import *  from lldbsuite.test import lldbutil +def haswellOrLater(): +    features = subprocess.check_output(["sysctl", "machdep.cpu"]) +    return "AVX2" in features.split()  class UniversalTestCase(TestBase): +    NO_DEBUG_INFO_TESTCASE = True      mydir = TestBase.compute_mydir(__file__)      def setUp(self): @@ -24,8 +28,8 @@ class UniversalTestCase(TestBase):      @add_test_categories(['pyapi'])      @skipUnlessDarwin -    @unittest2.skipUnless(hasattr(os, "uname") and os.uname()[4] in [ -                          'i386', 'x86_64'], "requires i386 or x86_64") +    @unittest2.skipUnless(hasattr(os, "uname") and os.uname()[4] in +                          ['x86_64'], "requires x86_64")      @skipIfDarwinEmbedded # this test file assumes we're targetting an x86 system      def test_sbdebugger_create_target_with_file_and_target_triple(self):          """Test the SBDebugger.CreateTargetWithFileAndTargetTriple() API.""" @@ -37,8 +41,9 @@ class UniversalTestCase(TestBase):          # Create a target by the debugger.          target = self.dbg.CreateTargetWithFileAndTargetTriple( -            exe, "i386-apple-macosx") +            exe, "x86_64-apple-macosx")          self.assertTrue(target, VALID_TARGET) +        self.expect("image list -A -b", substrs=["x86_64 testit"])          # Now launch the process, and do not stop at entry point.          process = target.LaunchSimple( @@ -46,13 +51,16 @@ class UniversalTestCase(TestBase):          self.assertTrue(process, PROCESS_IS_VALID)      @skipUnlessDarwin -    @unittest2.skipUnless(hasattr(os, "uname") and os.uname()[4] in [ -                          'i386', 'x86_64'], "requires i386 or x86_64") +    @unittest2.skipUnless(hasattr(os, "uname") and os.uname()[4] in +                          ['x86_64'], "requires x86_64")      @skipIfDarwinEmbedded # this test file assumes we're targetting an x86 system      def test_process_launch_for_universal(self):          """Test process launch of a universal binary."""          from lldbsuite.test.lldbutil import print_registers +        if not haswellOrLater(): +            return +                  # Invoke the default build rule.          self.build() @@ -62,69 +70,54 @@ class UniversalTestCase(TestBase):          # By default, x86_64 is assumed if no architecture is specified.          self.expect("file " + exe, CURRENT_EXECUTABLE_SET,                      startstr="Current executable set to ", -                    substrs=["testit' (x86_64)."]) +                    substrs=["testit' (x86_64h)."])          # Break inside the main.          lldbutil.run_break_set_by_file_and_line(              self, "main.c", self.line, num_expected_locations=1, loc_exact=True) -        # We should be able to launch the x86_64 executable. +        # We should be able to launch the x86_64h executable.          self.runCmd("run", RUN_SUCCEEDED) -        # Check whether we have a 64-bit process launched. +        # Check whether we have a x86_64h process launched.          target = self.dbg.GetSelectedTarget()          process = target.GetProcess() -        self.assertTrue(target and process and -                        self.invoke(process, 'GetAddressByteSize') == 8, -                        "64-bit process launched") - -        frame = process.GetThreadAtIndex(0).GetFrameAtIndex(0) -        registers = print_registers(frame, string_buffer=True) -        self.expect(registers, exe=False, -                    substrs=['Name: rax']) - +        self.expect("image list -A -b", substrs=["x86_64h testit"])          self.runCmd("continue") -        # Now specify i386 as the architecture for "testit". -        self.expect("file -a i386 " + exe, CURRENT_EXECUTABLE_SET, +        # Now specify x86_64 as the architecture for "testit". +        self.expect("file -a x86_64 " + exe, CURRENT_EXECUTABLE_SET,                      startstr="Current executable set to ", -                    substrs=["testit' (i386)."]) +                    substrs=["testit' (x86_64)."])          # Break inside the main.          lldbutil.run_break_set_by_file_and_line(              self, "main.c", self.line, num_expected_locations=1, loc_exact=True) -        # We should be able to launch the i386 executable as well. +        # We should be able to launch the x86_64 executable as well.          self.runCmd("run", RUN_SUCCEEDED) -        # Check whether we have a 32-bit process launched. -        target = self.dbg.GetSelectedTarget() -        process = target.GetProcess() -        self.assertTrue(target and process, -                        "32-bit process launched") - -        pointerSize = self.invoke(process, 'GetAddressByteSize') -        self.assertTrue( -            pointerSize == 4, -            "AddressByteSize of 32-bit process should be 4, got %d instead." % -            pointerSize) - -        frame = process.GetThreadAtIndex(0).GetFrameAtIndex(0) -        registers = print_registers(frame, string_buffer=True) -        self.expect(registers, exe=False, -                    substrs=['Name: eax']) - +        # Check whether we have a x86_64 process launched. +         +        # FIXME: This wrong. We are expecting x86_64, but spawning a +        # new process currently doesn't allow specifying a *sub*-architecture. +        # <rdar://problem/46101466> +        self.expect("image list -A -b", substrs=["x86_64h testit"])          self.runCmd("continue")      @skipUnlessDarwin -    @unittest2.skipUnless(hasattr(os, "uname") and os.uname()[4] in [ -                          'i386', 'x86_64'], "requires i386 or x86_64") +    @unittest2.skipUnless(hasattr(os, "uname") and os.uname()[4] in +                          ['x86_64'], "requires x86_64")      @skipIfDarwinEmbedded # this test file assumes we're targetting an x86 system      def test_process_attach_with_wrong_arch(self): -        """Test that when we attach to a binary from the wrong fork of a universal binary, we fix up the ABI correctly.""" -        # Now keep the architecture at 32 bit, but switch the binary we launch to -        # 64 bit, and make sure on attach we switch to the correct -        # architecture. +        """Test that when we attach to a binary from the wrong fork of +            a universal binary, we fix up the ABI correctly.""" +        if not haswellOrLater(): +            return + +        # Now keep the architecture at x86_64, but switch the binary +        # we launch to x86_64h, and make sure on attach we switch to +        # the correct architecture.          # Invoke the default build rule.          self.build() @@ -134,10 +127,9 @@ class UniversalTestCase(TestBase):          # Create a target by the debugger.          target = self.dbg.CreateTargetWithFileAndTargetTriple( -            exe, "i386-apple-macosx") +            exe, "x86_64-apple-macosx")          self.assertTrue(target, VALID_TARGET) -        pointer_size = target.GetAddressByteSize() -        self.assertTrue(pointer_size == 4, "Initially we were 32 bit.") +        self.expect("image list -A -b", substrs=["x86_64 testit"])          bkpt = target.BreakpointCreateBySourceRegex(              "sleep", lldb.SBFileSpec("main.c")) @@ -155,14 +147,14 @@ class UniversalTestCase(TestBase):              empty_listener, popen.pid, error)          self.assertTrue(error.Success(), "Attached to process.") -        pointer_size = target.GetAddressByteSize() -        self.assertTrue(pointer_size == 8, "We switched to 64 bit.") +        self.expect("image list -A -b", substrs=["x86_64h testit"]) -        # It may seem odd that I am checking the number of frames, but the bug that -        # motivated this test was that we eventually fixed the architecture, but we -        # left the ABI set to the original value.  In that case, if you asked the -        # process for its architecture, it would look right, but since the ABI was -        # wrong, backtracing failed. +        # It may seem odd to check the number of frames, but the bug +        # that motivated this test was that we eventually fixed the +        # architecture, but we left the ABI set to the original value. +        # In that case, if you asked the process for its architecture, +        # it would look right, but since the ABI was wrong, +        # backtracing failed.          threads = lldbutil.continue_to_breakpoint(process, bkpt)          self.assertTrue(len(threads) == 1) diff --git a/packages/Python/lldbsuite/test/make/Makefile.rules b/packages/Python/lldbsuite/test/make/Makefile.rules index 32f41b24d5dc..a2dc6cc66595 100644 --- a/packages/Python/lldbsuite/test/make/Makefile.rules +++ b/packages/Python/lldbsuite/test/make/Makefile.rules @@ -29,10 +29,10 @@  # SHELL = /bin/sh -x  SRCDIR := $(shell dirname $(firstword $(MAKEFILE_LIST)))/ +BUILDDIR := $(shell pwd)  THIS_FILE_DIR := $(shell dirname $(lastword $(MAKEFILE_LIST)))/  LLDB_BASE_DIR := $(THIS_FILE_DIR)../../../../../ -  #----------------------------------------------------------------------  # If OS is not defined, use 'uname -s' to determine the OS name.  # @@ -50,6 +50,33 @@ ifeq "$(OS)" ""  endif  #---------------------------------------------------------------------- +# If OS is Windows, force SHELL to be cmd +# +# Some versions of make on Windows will search for other shells such as +# C:\cygwin\bin\sh.exe. This shell fails for numerous different reasons +# so default to using cmd.exe. +#---------------------------------------------------------------------- +ifeq "$(OS)" "Windows_NT" +	SHELL = $(WINDIR)\system32\cmd.exe +endif + +#---------------------------------------------------------------------- +# If the OS is Windows use double-quotes in commands +# +# For other operating systems, single-quotes work fine, but on Windows +# we strictly required double-quotes +#---------------------------------------------------------------------- +ifeq "$(HOST_OS)" "Windows_NT" +	JOIN_CMD = & +	QUOTE = " +	FIXUP_SYNTAX_HIGHLIGHTING_IN_MY_EDITOR = " +else +	JOIN_CMD = ; +	QUOTE = ' +	FIXUP_SYNTAX_HIGHLIGHTING_IN_MY_EDITOR = ' +endif + +#----------------------------------------------------------------------  # If TRIPLE is not defined try to set the ARCH, CC, CFLAGS, and more  # from the triple alone  #---------------------------------------------------------------------- @@ -63,7 +90,8 @@ ifneq "$(TRIPLE)" ""  	TRIPLE_VERSION =$(word 2, $(triple_os_and_version))  	ifeq "$(TRIPLE_VENDOR)" "apple"  		ifeq "$(TRIPLE_OS)" "ios" -		    ifeq "$(SDKROOT)" "" +			CODESIGN := codesign +			ifeq "$(SDKROOT)" ""  				# Set SDKROOT if it wasn't set  				ifneq (,$(findstring arm,$(ARCH)))  					SDKROOT = $(shell xcrun --sdk iphoneos --show-sdk-path) @@ -81,7 +109,8 @@ ifneq "$(TRIPLE)" ""  			endif  		endif  		ifeq "$(TRIPLE_OS)" "watchos" -		    ifeq "$(SDKROOT)" "" +			CODESIGN := codesign +			ifeq "$(SDKROOT)" ""  				# Set SDKROOT if it wasn't set  				ifneq (,$(findstring arm,$(ARCH)))  					SDKROOT = $(shell xcrun --sdk watchos --show-sdk-path) @@ -228,6 +257,12 @@ endif  CFLAGS += -I$(SRCDIR) -include $(THIS_FILE_DIR)test_common.h -I$(THIS_FILE_DIR)  CFLAGS += $(NO_LIMIT_DEBUG_INFO_FLAGS) $(ARCH_CFLAGS) $(CFLAGS_EXTRAS) +# If the OS is Windows, we need to pass -gdwarf to clang, otherwise it will build +# with codeview by default but all the tests rely on dwarf. +ifeq "$(OS)" "Windows_NT" +	CFLAGS += -gdwarf +endif +  # Use this one if you want to build one part of the result without debug information:  ifeq "$(OS)" "Darwin"  	CFLAGS_NO_DEBUG = -O0 $(ARCHFLAG) $(ARCH) $(FRAMEWORK_INCLUDES) $(ARCH_CFLAGS) $(CFLAGS_EXTRAS) @@ -239,12 +274,22 @@ ifeq "$(MAKE_DWO)" "YES"  	CFLAGS += -gsplit-dwarf  endif -CLANG_MODULE_CACHE_DIR := module-cache +# Use a shared module cache when building in the default test build directory. +CLANG_MODULE_CACHE_DIR := $(shell echo "$(BUILDDIR)" | sed $(QUOTE)s/lldb-test-build.noindex.*/lldb-test-build.noindex\/module-cache-clang/$(QUOTE)) + +ifeq "$(findstring lldb-test-build.noindex, $(BUILDDIR))" "" +CLANG_MODULE_CACHE_DIR := $(BUILDDIR)/module-cache +$(warning failed to set the shared clang module cache dir) +endif  MANDATORY_MODULE_BUILD_CFLAGS := -fmodules -gmodules -fmodules-cache-path=$(CLANG_MODULE_CACHE_DIR)  ifeq "$(MAKE_GMODULES)" "YES"  	CFLAGS += $(MANDATORY_MODULE_BUILD_CFLAGS) +	CXXFLAGS += $(MANDATORY_MODULE_BUILD_CFLAGS) +	ifeq "$(OS)" "Darwin" +		CXXFLAGS += -fcxx-modules +	endif  endif  CXXFLAGS += -std=c++11 $(CFLAGS) $(ARCH_CXXFLAGS) @@ -315,7 +360,7 @@ ifneq "$(OS)" "Darwin"  endif  ifdef PIE -    LDFLAGS += -pie +	LDFLAGS += -pie  endif  #---------------------------------------------------------------------- @@ -380,17 +425,17 @@ ifneq "$(strip $(DYLIB_OBJC_SOURCES))" ""  endif  ifneq "$(strip $(DYLIB_CXX_SOURCES))" "" -    DYLIB_OBJECTS +=$(strip $(DYLIB_CXX_SOURCES:.cpp=.o)) -    CXX = $(call cxx_compiler,$(CC)) -    LD = $(call cxx_linker,$(CC)) +	DYLIB_OBJECTS +=$(strip $(DYLIB_CXX_SOURCES:.cpp=.o)) +	CXX = $(call cxx_compiler,$(CC)) +	LD = $(call cxx_linker,$(CC))  endif  #----------------------------------------------------------------------  # Check if we have a precompiled header  #----------------------------------------------------------------------  ifneq "$(strip $(PCH_CXX_SOURCE))" "" -    PCH_OUTPUT = $(PCH_CXX_SOURCE:.h=.h.pch) -    PCHFLAGS = -include $(PCH_CXX_SOURCE) +	PCH_OUTPUT = $(PCH_CXX_SOURCE:.h=.h.pch) +	PCHFLAGS = -include $(PCH_CXX_SOURCE)  endif  #---------------------------------------------------------------------- @@ -472,21 +517,21 @@ ifneq "$(strip $(CXX_SOURCES) $(OBJCXX_SOURCES))" ""  ifneq "$(filter g++,$(CXX))" ""  	CXXVERSION = $(shell $(CXX) -dumpversion | cut -b 1-3)  	ifeq "$(CXXVERSION)" "4.6" -                # GCC 4.6 cannot handle -std=c++11, so replace it with -std=c++0x -                # instead. FIXME: remove once GCC version is upgraded. +		# GCC 4.6 cannot handle -std=c++11, so replace it with -std=c++0x +		# instead. FIXME: remove once GCC version is upgraded.  		override CXXFLAGS := $(subst -std=c++11,-std=c++0x,$(CXXFLAGS))  	endif  endif  endif  ifeq ($(findstring clang, $(CXX)), clang) -  CXXFLAGS += --driver-mode=g++ +	CXXFLAGS += --driver-mode=g++  endif  ifneq "$(CXX)" "" -  ifeq ($(findstring clang, $(LD)), clang) -    LDFLAGS += --driver-mode=g++ -  endif +	ifeq ($(findstring clang, $(LD)), clang) +		LDFLAGS += --driver-mode=g++ +	endif  endif  #---------------------------------------------------------------------- @@ -508,6 +553,9 @@ endif  else  $(EXE) : $(OBJECTS) $(ARCHIVE_NAME)  	$(LD) $(OBJECTS) $(LDFLAGS) $(ARCHIVE_NAME) -o "$(EXE)" +ifneq "$(CODESIGN)" "" +	$(CODESIGN) -s - "$(EXE)" +endif  endif  #---------------------------------------------------------------------- @@ -552,6 +600,9 @@ endif  $(DYLIB_FILENAME) : $(DYLIB_OBJECTS)  ifeq "$(OS)" "Darwin"  	$(LD) $(DYLIB_OBJECTS) $(LDFLAGS) -install_name "$(DYLIB_EXECUTABLE_PATH)/$(DYLIB_FILENAME)" -dynamiclib -o "$(DYLIB_FILENAME)" +ifneq "$(CODESIGN)" "" +	$(CODESIGN) -s - "$(DYLIB_FILENAME)" +endif  ifneq "$(MAKE_DSYM)" "NO"  ifneq "$(DS)" ""  	"$(DS)" $(DSFLAGS) "$(DYLIB_FILENAME)" @@ -594,14 +645,6 @@ endif  # the compiler -MM option. The -M option will list all system headers,  # and the -MM option will list all non-system dependencies.  #---------------------------------------------------------------------- -ifeq "$(HOST_OS)" "Windows_NT" -	JOIN_CMD = & -	QUOTE = " -else -	JOIN_CMD = ; -	QUOTE = ' -endif -  %.d: %.c  	@rm -f $@ $(JOIN_CMD) \  	$(CC) -M $(CFLAGS) $< > $@.tmp && \ diff --git a/packages/Python/lldbsuite/test/python_api/event/TestEvents.py b/packages/Python/lldbsuite/test/python_api/event/TestEvents.py index 8a9e456f3458..f5d143fbd40b 100644 --- a/packages/Python/lldbsuite/test/python_api/event/TestEvents.py +++ b/packages/Python/lldbsuite/test/python_api/event/TestEvents.py @@ -119,7 +119,6 @@ class EventAPITestCase(TestBase):      @add_test_categories(['pyapi'])      @expectedFlakeyLinux("llvm.org/pr23730")  # Flaky, fails ~1/100 cases -    @expectedFlakeyOS(oslist=["windows"])      def test_wait_for_event(self):          """Exercise SBListener.WaitForEvent() API."""          self.build() @@ -198,7 +197,6 @@ class EventAPITestCase(TestBase):      @expectedFailureAll(          oslist=["linux"],          bugnumber="llvm.org/pr23617 Flaky, fails ~1/10 cases") -    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")      def test_add_listener_to_broadcaster(self):          """Exercise some SBBroadcaster APIs."""          self.build() diff --git a/packages/Python/lldbsuite/test/python_api/frame/TestFrames.py b/packages/Python/lldbsuite/test/python_api/frame/TestFrames.py index 85e915ad3a48..fc2f03f9e617 100644 --- a/packages/Python/lldbsuite/test/python_api/frame/TestFrames.py +++ b/packages/Python/lldbsuite/test/python_api/frame/TestFrames.py @@ -20,7 +20,6 @@ class FrameAPITestCase(TestBase):      mydir = TestBase.compute_mydir(__file__)      @add_test_categories(['pyapi']) -    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")      def test_get_arg_vals_for_call_stack(self):          """Exercise SBFrame.GetVariables() API to get argument vals."""          self.build() diff --git a/packages/Python/lldbsuite/test/python_api/hello_world/TestHelloWorld.py b/packages/Python/lldbsuite/test/python_api/hello_world/TestHelloWorld.py index b0f09d2fa7b5..33f4a790aacf 100644 --- a/packages/Python/lldbsuite/test/python_api/hello_world/TestHelloWorld.py +++ b/packages/Python/lldbsuite/test/python_api/hello_world/TestHelloWorld.py @@ -10,8 +10,7 @@ import time  import lldb  from lldbsuite.test.decorators import *  from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil - +import lldbsuite.test.lldbutil as lldbutil  class HelloWorldTestCase(TestBase):      NO_DEBUG_INFO_TESTCASE = True @@ -35,7 +34,7 @@ class HelloWorldTestCase(TestBase):      def test_with_process_launch_api(self):          """Create target, breakpoint, launch a process, and then kill it."""          # Get the full path to our executable to be attached/debugged. -        exe = self.getBuildArtifact(self.testMethodName) +        exe = '%s_%d'%(self.getBuildArtifact(self.testMethodName), os.getpid())          d = {'EXE': exe}          self.build(dictionary=d)          self.setTearDownCleanup(dictionary=d) @@ -77,23 +76,22 @@ class HelloWorldTestCase(TestBase):          self.assertEqual(breakpoint.GetHitCount(), 1, BREAKPOINT_HIT_ONCE)      @add_test_categories(['pyapi']) -    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24600")      @skipIfiOSSimulator -    @expectedFailureAll(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], bugnumber="<rdar://problem/34538611>") # old lldb-server has race condition, launching an inferior and then launching debugserver in quick succession sometimes fails      def test_with_attach_to_process_with_id_api(self):          """Create target, spawn a process, and attach to it with process id.""" -        exe = self.getBuildArtifact(self.testMethodName) +        exe = '%s_%d'%(self.getBuildArtifact(self.testMethodName), os.getpid())          d = {'EXE': exe}          self.build(dictionary=d)          self.setTearDownCleanup(dictionary=d)          target = self.dbg.CreateTarget(exe)          # Spawn a new process -        popen = self.spawnSubprocess(exe, ["abc", "xyz"]) +        token = exe+'.token' +        if os.path.exists(token): +            os.remove(token) +        popen = self.spawnSubprocess(exe, [token])          self.addTearDownHook(self.cleanupSubprocesses) - -        # Give the subprocess time to start and wait for user input -        time.sleep(0.25) +        lldbutil.wait_for_file_on_target(self, token)          listener = lldb.SBListener("my.attach.listener")          error = lldb.SBError() @@ -102,30 +100,29 @@ class HelloWorldTestCase(TestBase):          self.assertTrue(error.Success() and process, PROCESS_IS_VALID)          # Let's check the stack traces of the attached process. -        import lldbsuite.test.lldbutil as lldbutil          stacktraces = lldbutil.print_stacktraces(process, string_buffer=True)          self.expect(stacktraces, exe=False,                      substrs=['main.c:%d' % self.line2, -                             '(int)argc=3']) +                             '(int)argc=2'])      @add_test_categories(['pyapi']) -    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24600")      @skipIfiOSSimulator -    @expectedFailureAll(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], bugnumber="<rdar://problem/34538611>") # old lldb-server has race condition, launching an inferior and then launching debugserver in quick succession sometimes fails +    @skipIfSanitized # FIXME: Hangs indefinitely.      def test_with_attach_to_process_with_name_api(self):          """Create target, spawn a process, and attach to it with process name.""" -        exe = self.getBuildArtifact(self.testMethodName) +        exe = '%s_%d'%(self.getBuildArtifact(self.testMethodName), os.getpid())          d = {'EXE': exe}          self.build(dictionary=d)          self.setTearDownCleanup(dictionary=d)          target = self.dbg.CreateTarget(exe) -        # Spawn a new process -        popen = self.spawnSubprocess(exe, ["abc", "xyz"]) +        # Spawn a new process. +        token = exe+'.token' +        if os.path.exists(token): +            os.remove(token) +        popen = self.spawnSubprocess(exe, [token])          self.addTearDownHook(self.cleanupSubprocesses) - -        # Give the subprocess time to start and wait for user input -        time.sleep(0.25) +        lldbutil.wait_for_file_on_target(self, token)          listener = lldb.SBListener("my.attach.listener")          error = lldb.SBError() @@ -140,7 +137,6 @@ class HelloWorldTestCase(TestBase):          target.ConnectRemote(listener, None, None, error)          process = target.AttachToProcessWithName(listener, name, False, error) -          self.assertTrue(error.Success() and process, PROCESS_IS_VALID)          # Verify that after attach, our selected target indeed matches name. @@ -150,8 +146,7 @@ class HelloWorldTestCase(TestBase):              startstr=name)          # Let's check the stack traces of the attached process. -        import lldbsuite.test.lldbutil as lldbutil          stacktraces = lldbutil.print_stacktraces(process, string_buffer=True)          self.expect(stacktraces, exe=False,                      substrs=['main.c:%d' % self.line2, -                             '(int)argc=3']) +                             '(int)argc=2']) diff --git a/packages/Python/lldbsuite/test/python_api/hello_world/main.c b/packages/Python/lldbsuite/test/python_api/hello_world/main.c index 32b0446517c5..c516f923614f 100644 --- a/packages/Python/lldbsuite/test/python_api/hello_world/main.c +++ b/packages/Python/lldbsuite/test/python_api/hello_world/main.c @@ -8,16 +8,22 @@  int main(int argc, char const *argv[])  { -    lldb_enable_attach(); +  lldb_enable_attach(); -    printf("Hello world.\n"); // Set break point at this line. -    if (argc == 1) -        return 0; +  printf("Hello world.\n"); // Set break point at this line. +  if (argc == 1) +    return 1; -    // Waiting to be attached by the debugger, otherwise. -    char line[100]; -    while (1)  -        sleep (1); // Waiting to be attached... +  // Create the synchronization token. +  FILE *f; +  if (f = fopen(argv[1], "wx")) { +    fputs("\n", f); +    fflush(f); +    fclose(f); +  } else +    return 1; -    printf("Exiting now\n"); +  // Waiting to be attached by the debugger, otherwise. +  while (1) +    sleep(1); // Waiting to be attached...  } diff --git a/packages/Python/lldbsuite/test/python_api/name_lookup/main.cpp b/packages/Python/lldbsuite/test/python_api/name_lookup/main.cpp index 79aa2d0452f4..b38208ce2a35 100644 --- a/packages/Python/lldbsuite/test/python_api/name_lookup/main.cpp +++ b/packages/Python/lldbsuite/test/python_api/name_lookup/main.cpp @@ -51,4 +51,4 @@ int main (int argc, char const *argv[])    g.unique_function_name();    g.unique_function_name(argc);    return 0; -}
\ No newline at end of file +} diff --git a/packages/Python/lldbsuite/test/python_api/sbvalue_persist/main.cpp b/packages/Python/lldbsuite/test/python_api/sbvalue_persist/main.cpp index 650d87acd6e6..c54339f3bba6 100644 --- a/packages/Python/lldbsuite/test/python_api/sbvalue_persist/main.cpp +++ b/packages/Python/lldbsuite/test/python_api/sbvalue_persist/main.cpp @@ -11,4 +11,4 @@ int main() {      f(); // break here      f(); // break here      return 0; -}
\ No newline at end of file +} diff --git a/packages/Python/lldbsuite/test/python_api/value/TestValueAPI.py b/packages/Python/lldbsuite/test/python_api/value/TestValueAPI.py index 8a4af0cc2b94..2299f1f1432d 100644 --- a/packages/Python/lldbsuite/test/python_api/value/TestValueAPI.py +++ b/packages/Python/lldbsuite/test/python_api/value/TestValueAPI.py @@ -153,6 +153,9 @@ class ValueAPITestCase(TestBase):          val_s = target.EvaluateExpression('s')          val_a = target.EvaluateExpression('a')          self.assertTrue( +            val_s.GetChildMemberWithName('a').GetAddress().IsValid(), +            VALID_VARIABLE) +        self.assertTrue(              val_s.GetChildMemberWithName('a').AddressOf(),              VALID_VARIABLE)          self.assertTrue( diff --git a/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py b/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py index d5862d274ceb..3c19c589b7a7 100644 --- a/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py +++ b/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py @@ -108,7 +108,6 @@ class TargetWatchAddressAPITestCase(TestBase):      # No size constraint on MIPS for watches      @skipIf(archs=['mips', 'mipsel', 'mips64', 'mips64el'])      @skipIf(archs=['s390x'])  # Likewise on SystemZ -    @expectedFailureAll(oslist=["windows"])      def test_watch_address_with_invalid_watch_size(self):          """Exercise SBTarget.WatchAddress() API but pass an invalid watch_size."""          self.build() diff --git a/packages/Python/lldbsuite/test/settings/TestSettings.py b/packages/Python/lldbsuite/test/settings/TestSettings.py index d6fa5a93b72c..b46e3b4103c6 100644 --- a/packages/Python/lldbsuite/test/settings/TestSettings.py +++ b/packages/Python/lldbsuite/test/settings/TestSettings.py @@ -132,7 +132,7 @@ class SettingsCommandTestCase(TestBase):          # Change the default format to print function.name rather than          # function.name-with-args -        format_string = "frame #${frame.index}: ${frame.pc}{ ${module.file.basename}`${function.name}{${function.pc-offset}}}{ at ${line.file.fullpath}:${line.number}}{, lang=${language}}\n" +        format_string = "frame #${frame.index}: ${frame.pc}{ ${module.file.basename}\`${function.name}{${function.pc-offset}}}{ at ${line.file.fullpath}:${line.number}}{, lang=${language}}\n"          self.runCmd("settings set frame-format %s" % format_string)          # Immediately test the setting. @@ -418,11 +418,11 @@ class SettingsCommandTestCase(TestBase):          # Set to known value          self.runCmd("settings set target.language c89")          # Set to new value with trailing whitespace -        self.runCmd("settings set target.language go ") +        self.runCmd("settings set target.language c11 ")          self.expect(              "settings show target.language",              SETTING_MSG("target.language"), -            startstr="target.language (language) = go") +            startstr="target.language (language) = c11")          self.runCmd("settings clear target.language", check=False)          # arguments          self.runCmd("settings set target.run-args 1 2 3")  # Set to known value diff --git a/packages/Python/lldbsuite/test/source-manager/TestSourceManager.py b/packages/Python/lldbsuite/test/source-manager/TestSourceManager.py index 0df4f8b2d2a8..ea822decdb6f 100644 --- a/packages/Python/lldbsuite/test/source-manager/TestSourceManager.py +++ b/packages/Python/lldbsuite/test/source-manager/TestSourceManager.py @@ -22,6 +22,8 @@ def ansi_underline_surround_regex(inner_regex_text):      # return re.compile(r"\[4m%s\[0m" % inner_regex_text)      return "4.+\033\\[4m%s\033\\[0m" % inner_regex_text +def ansi_color_surround_regex(inner_regex_text): +    return "\033\\[3[0-7]m%s\033\\[0m" % inner_regex_text  class SourceManagerTestCase(TestBase): @@ -47,7 +49,7 @@ class SourceManagerTestCase(TestBase):          # the character column after the initial whitespace.          return len(stop_line) - len(stop_line.lstrip()) + 1 -    def do_display_source_python_api(self, use_color, column_marker_regex): +    def do_display_source_python_api(self, use_color, needle_regex, highlight_source=False):          self.build()          exe = self.getBuildArtifact("a.out")          self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) @@ -69,6 +71,9 @@ class SourceManagerTestCase(TestBase):          # Setup whether we should use ansi escape sequences, including color          # and styles such as underline.          self.dbg.SetUseColor(use_color) +        # Disable syntax highlighting if needed. + +        self.runCmd("settings set highlight-source " + str(highlight_source).lower())          filespec = lldb.SBFileSpec(self.file, False)          source_mgr = self.dbg.GetSourceManager() @@ -87,10 +92,10 @@ class SourceManagerTestCase(TestBase):          # => 4        printf("Hello world.\n"); // Set break point at this line.          #    5        return 0;          #    6    } -        self.expect(stream.GetData(), "Source code displayed correctly", +        self.expect(stream.GetData(), "Source code displayed correctly:\n" + stream.GetData(),                      exe=False,                      patterns=['=> %d.*Hello world' % self.line, -                              column_marker_regex]) +                              needle_regex])          # Boundary condition testings for SBStream().  LLDB should not crash!          stream.Print(None) @@ -108,9 +113,28 @@ class SourceManagerTestCase(TestBase):          """Test display of source using the SBSourceManager API, using a          dumb terminal and thus no color support (the default)."""          use_color = True -        underline_regex = ansi_underline_surround_regex(r".") +        underline_regex = ansi_underline_surround_regex(r"printf")          self.do_display_source_python_api(use_color, underline_regex) +    @add_test_categories(['pyapi']) +    def test_display_source_python_ansi_terminal_syntax_highlighting(self): +        """Test display of source using the SBSourceManager API and check for +        the syntax highlighted output""" +        use_color = True +        syntax_highlighting = True; + +        # Just pick 'int' as something that should be colored. +        color_regex = ansi_color_surround_regex("int") +        self.do_display_source_python_api(use_color, color_regex, syntax_highlighting) + +        # Same for 'char'. +        color_regex = ansi_color_surround_regex("char") +        self.do_display_source_python_api(use_color, color_regex, syntax_highlighting) + +        # Test that we didn't color unrelated identifiers. +        self.do_display_source_python_api(use_color, r" main\(", syntax_highlighting) +        self.do_display_source_python_api(use_color, r"\);", syntax_highlighting) +      def test_move_and_then_display_source(self):          """Test that target.source-map settings work by moving main.c to hidden/main.c."""          self.build() diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/interpreter/TestMiInterpreterExec.py b/packages/Python/lldbsuite/test/tools/lldb-mi/interpreter/TestMiInterpreterExec.py index ccd7eba8bfe3..848bd3852393 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-mi/interpreter/TestMiInterpreterExec.py +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/interpreter/TestMiInterpreterExec.py @@ -18,6 +18,7 @@ class MiInterpreterExecTestCase(lldbmi_testcase.MiTestCaseBase):      @skipIfWindows  # llvm.org/pr24452: Get lldb-mi tests working on Windows      @skipIfFreeBSD  # llvm.org/pr22411: Failure presumably due to known thread races      @skipIfRemote   # We do not currently support remote debugging via the MI. +    @skipIfDarwin      def test_lldbmi_target_create(self):          """Test that 'lldb-mi --interpreter' can create target by 'target create' command.""" @@ -39,6 +40,7 @@ class MiInterpreterExecTestCase(lldbmi_testcase.MiTestCaseBase):      @skipIfRemote   # We do not currently support remote debugging via the MI.      @skipIfWindows  # llvm.org/pr24452: Get lldb-mi tests working on Windows.      @skipIfFreeBSD  # llvm.org/pr22411: Failure presumably due to known thread races. +    @skipIfDarwin      def test_lldbmi_target_list(self):          """Test that 'lldb-mi --interpreter' can list targets by 'target list' command.""" @@ -58,6 +60,7 @@ class MiInterpreterExecTestCase(lldbmi_testcase.MiTestCaseBase):      @skipIfWindows  # llvm.org/pr24452: Get lldb-mi tests working on Windows      @skipIfFreeBSD  # llvm.org/pr22411: Failure presumably due to known thread races      @skipIfRemote   # We do not currently support remote debugging via the MI. +    @skipIfDarwin      def test_lldbmi_breakpoint_set(self):          """Test that 'lldb-mi --interpreter' can set breakpoint by 'breakpoint set' command.""" @@ -82,6 +85,7 @@ class MiInterpreterExecTestCase(lldbmi_testcase.MiTestCaseBase):      @skipIfFreeBSD  # llvm.org/pr22411: Failure presumably due to known thread races      @expectedFlakeyLinux(bugnumber="llvm.org/pr25470")      @skipIfRemote   # We do not currently support remote debugging via the MI. +    @skipIfDarwin      def test_lldbmi_settings_set_target_run_args_before(self):          """Test that 'lldb-mi --interpreter' can set target arguments by 'setting set target.run-args' command before than target was created.""" @@ -115,6 +119,7 @@ class MiInterpreterExecTestCase(lldbmi_testcase.MiTestCaseBase):      @skipIfWindows  # llvm.org/pr24452: Get lldb-mi tests working on Windows      @skipIfFreeBSD  # llvm.org/pr22411: Failure presumably due to known thread races      @skipIfRemote   # We do not currently support remote debugging via the MI. +    @skipIfDarwin      def test_lldbmi_process_launch(self):          """Test that 'lldb-mi --interpreter' can launch process by "process launch" command.""" @@ -138,6 +143,7 @@ class MiInterpreterExecTestCase(lldbmi_testcase.MiTestCaseBase):      @skipIfWindows  # llvm.org/pr24452: Get lldb-mi tests working on Windows      @skipIfFreeBSD  # llvm.org/pr22411: Failure presumably due to known thread races      @skipIfRemote   # We do not currently support remote debugging via the MI. +    @skipIfDarwin      def test_lldbmi_thread_step_in(self):          """Test that 'lldb-mi --interpreter' can step in by "thread step-in" command.""" @@ -170,6 +176,7 @@ class MiInterpreterExecTestCase(lldbmi_testcase.MiTestCaseBase):      @skipIfWindows  # llvm.org/pr24452: Get lldb-mi tests working on Windows      @skipIfFreeBSD  # llvm.org/pr22411: Failure presumably due to known thread races      @skipIfRemote   # We do not currently support remote debugging via the MI. +    @skipIfDarwin      def test_lldbmi_thread_step_over(self):          """Test that 'lldb-mi --interpreter' can step over by "thread step-over" command.""" @@ -196,6 +203,7 @@ class MiInterpreterExecTestCase(lldbmi_testcase.MiTestCaseBase):      @skipIfFreeBSD  # llvm.org/pr22411: Failure presumably due to known thread races      @expectedFlakeyLinux("llvm.org/pr25470")      @skipIfRemote   # We do not currently support remote debugging via the MI. +    @skipIfDarwin      def test_lldbmi_thread_continue(self):          """Test that 'lldb-mi --interpreter' can continue execution by "thread continue" command.""" diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/lldbmi_testcase.py b/packages/Python/lldbsuite/test/tools/lldb-mi/lldbmi_testcase.py index 7b6ee55b250e..59a5b324465f 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-mi/lldbmi_testcase.py +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/lldbmi_testcase.py @@ -40,7 +40,7 @@ class MiTestCaseBase(Base):                  pass          Base.tearDown(self) -    def spawnLldbMi(self, args=None): +    def spawnLldbMi(self, exe=None, args=None, preconfig=True):          import pexpect          self.child = pexpect.spawn("%s --interpreter %s" % (              self.lldbMiExec, args if args else ""), cwd=self.getBuildDir()) @@ -49,6 +49,14 @@ class MiTestCaseBase(Base):          self.child.logfile_read = open(self.mylog, "w")          # wait until lldb-mi has started up and is ready to go          self.expect(self.child_prompt, exactly=True) +        if preconfig: +            self.runCmd("settings set symbols.enable-external-lookup false") +            self.expect("\^done") +            self.expect(self.child_prompt, exactly=True) +        if exe: +            self.runCmd("-file-exec-and-symbols \"%s\"" % exe) +            # Testcases expect to be able to match output of this command, +            # see test_lldbmi_specialchars.      def runCmd(self, cmd):          self.child.sendline(cmd) diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/startup_options/TestMiStartupOptions.py b/packages/Python/lldbsuite/test/tools/lldb-mi/startup_options/TestMiStartupOptions.py index 467952db7eba..b78f4762ddf9 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-mi/startup_options/TestMiStartupOptions.py +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/startup_options/TestMiStartupOptions.py @@ -22,7 +22,7 @@ class MiStartupOptionsTestCase(lldbmi_testcase.MiTestCaseBase):      def test_lldbmi_executable_option_file(self):          """Test that 'lldb-mi --interpreter %s' loads executable file.""" -        self.spawnLldbMi(args="%s" % self.myexe) +        self.spawnLldbMi(exe=self.myexe)          # Test that the executable is loaded when file was specified          self.expect("-file-exec-and-symbols \"%s\"" % self.myexe) @@ -52,7 +52,7 @@ class MiStartupOptionsTestCase(lldbmi_testcase.MiTestCaseBase):          # Prepare path to executable          path = "unknown_file" -        self.spawnLldbMi(args="%s" % path) +        self.spawnLldbMi(exe=path)          # Test that the executable isn't loaded when unknown file was specified          self.expect("-file-exec-and-symbols \"%s\"" % path) @@ -71,7 +71,7 @@ class MiStartupOptionsTestCase(lldbmi_testcase.MiTestCaseBase):          """Test that 'lldb-mi --interpreter %s' loads executable which is specified via absolute path."""          # Prepare path to executable -        self.spawnLldbMi(args="%s" % self.myexe) +        self.spawnLldbMi(exe=self.myexe)          # Test that the executable is loaded when file was specified using          # absolute path @@ -95,7 +95,7 @@ class MiStartupOptionsTestCase(lldbmi_testcase.MiTestCaseBase):          # Prepare path to executable          path = os.path.relpath(self.myexe, self.getBuildDir()) -        self.spawnLldbMi(args="%s" % path) +        self.spawnLldbMi(exe=path)          # Test that the executable is loaded when file was specified using          # relative path @@ -119,7 +119,7 @@ class MiStartupOptionsTestCase(lldbmi_testcase.MiTestCaseBase):          # Prepare path to executable          path = "unknown_dir" + self.myexe -        self.spawnLldbMi(args="%s" % path) +        self.spawnLldbMi(exe=path)          # Test that the executable isn't loaded when file was specified using          # unknown path @@ -237,7 +237,11 @@ class MiStartupOptionsTestCase(lldbmi_testcase.MiTestCaseBase):          # Prepared source file          sourceFile = self.copyScript("start_script_error") -        self.spawnLldbMi(args="--source %s" % sourceFile) +        self.spawnLldbMi(args="--source %s" % sourceFile, preconfig=False) + +        # After 'settings set symbols.enable-external-lookup false' +        self.expect("settings set symbols.enable-external-lookup false") +        self.expect("\^done")          # After '-file-exec-and-symbols a.out'          self.expect("-file-exec-and-symbols %s" % self.myexe) @@ -259,7 +263,7 @@ class MiStartupOptionsTestCase(lldbmi_testcase.MiTestCaseBase):          """Test that 'lldb-mi --log' creates a log file in the current directory."""          logDirectory = self.getBuildDir() -        self.spawnLldbMi(args="%s --log" % self.myexe) +        self.spawnLldbMi(exe=self.myexe, args="--log")          # Test that the executable is loaded when file was specified          self.expect("-file-exec-and-symbols \"%s\"" % self.myexe) @@ -296,9 +300,8 @@ class MiStartupOptionsTestCase(lldbmi_testcase.MiTestCaseBase):          import tempfile          logDirectory = tempfile.gettempdir() -        self.spawnLldbMi( -            args="%s --log --log-dir=%s" % -            (self.myexe, logDirectory)) +        self.spawnLldbMi(exe=self.myexe, +            args="--log --log-dir=%s" % logDirectory)          # Test that the executable is loaded when file was specified          self.expect("-file-exec-and-symbols \"%s\"" % self.myexe) diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/startup_options/start_script_error b/packages/Python/lldbsuite/test/tools/lldb-mi/startup_options/start_script_error index d834e7407c57..a1c581b08e0e 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-mi/startup_options/start_script_error +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/startup_options/start_script_error @@ -1,2 +1,3 @@ +settings set symbols.enable-external-lookup false  -file-exec-and-symbols a.out  -break-ins -f main diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/syntax/TestMiSyntax.py b/packages/Python/lldbsuite/test/tools/lldb-mi/syntax/TestMiSyntax.py index 50a94b53a18b..74d194e6dee2 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-mi/syntax/TestMiSyntax.py +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/syntax/TestMiSyntax.py @@ -53,7 +53,7 @@ class MiSyntaxTestCase(lldbmi_testcase.MiTestCaseBase):          os.symlink(self.myexe, complicated_myexe)          self.addTearDownHook(lambda: os.unlink(complicated_myexe)) -        self.spawnLldbMi(args="\"%s\"" % complicated_myexe) +        self.spawnLldbMi(exe=complicated_myexe)          # Test that the executable was loaded          self.expect( diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/TestAppleSimulatorOSType.py b/packages/Python/lldbsuite/test/tools/lldb-server/TestAppleSimulatorOSType.py index 8c8fed8e44e0..62c948c36cf7 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-server/TestAppleSimulatorOSType.py +++ b/packages/Python/lldbsuite/test/tools/lldb-server/TestAppleSimulatorOSType.py @@ -19,7 +19,13 @@ class TestAppleSimulatorOSType(gdbremote_testcase.GdbRemoteTestCaseBase):          sim_devices = json.loads(sim_devices_str)['devices']          # Find an available simulator for the requested platform          deviceUDID = None -        for (runtime,devices) in sim_devices.items(): +        for simulator in sim_devices: +            if isinstance(simulator,dict): +                runtime = simulator['name'] +                devices = simulator['devices'] +            else: +                runtime = simulator +                devices = sim_devices[simulator]              if not platform in runtime.lower():                  continue              for device in devices: @@ -95,18 +101,21 @@ class TestAppleSimulatorOSType(gdbremote_testcase.GdbRemoteTestCaseBase):      @apple_simulator_test('iphone')      @debugserver_test +    @skipIfDarwinEmbedded      def test_simulator_ostype_ios(self):          self.check_simulator_ostype(sdk='iphonesimulator',                                      platform='ios')      @apple_simulator_test('appletv')      @debugserver_test +    @skipIfDarwinEmbedded      def test_simulator_ostype_tvos(self):          self.check_simulator_ostype(sdk='appletvsimulator',                                      platform='tvos')      @apple_simulator_test('watch')      @debugserver_test +    @skipIfDarwinEmbedded      def test_simulator_ostype_watchos(self):          self.check_simulator_ostype(sdk='watchsimulator',                                      platform='watchos', arch='i386') diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteGPacket.py b/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteGPacket.py index 76910758fa91..cfadbc8f7d0f 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteGPacket.py +++ b/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteGPacket.py @@ -35,6 +35,7 @@ class TestGdbRemoteGPacket(gdbremote_testcase.GdbRemoteTestCaseBase):      @skipIfOutOfTreeDebugserver      @debugserver_test +    @skipIfDarwinEmbedded      def test_g_packet_debugserver(self):          self.init_debugserver_test()          self.run_test_g_packet() diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/.categories b/packages/Python/lldbsuite/test/tools/lldb-vscode/.categories new file mode 100644 index 000000000000..ce2cfd048e38 --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/.categories @@ -0,0 +1 @@ +lldb-vscode diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/attach/Makefile b/packages/Python/lldbsuite/test/tools/lldb-vscode/attach/Makefile new file mode 100644 index 000000000000..b09a579159d4 --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/attach/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/attach/TestVSCode_attach.py b/packages/Python/lldbsuite/test/tools/lldb-vscode/attach/TestVSCode_attach.py new file mode 100644 index 000000000000..67cd05b83c3b --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/attach/TestVSCode_attach.py @@ -0,0 +1,192 @@ +""" +Test lldb-vscode setBreakpoints request +""" + +from __future__ import print_function + +import unittest2 +import vscode +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import lldbvscode_testcase +import os +import shutil +import subprocess +import tempfile +import threading +import time + + +def spawn_and_wait(program, delay): +    if delay: +        time.sleep(delay) +    process = subprocess.Popen([program], +                               stdin=subprocess.PIPE, +                               stdout=subprocess.PIPE, +                               stderr=subprocess.PIPE) +    process.wait() + + +class TestVSCode_attach(lldbvscode_testcase.VSCodeTestCaseBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def set_and_hit_breakpoint(self, continueToExit=True): +        source = 'main.c' +        breakpoint1_line = line_number(source, '// breakpoint 1') +        lines = [breakpoint1_line] +        # Set breakoint in the thread function so we can step the threads +        breakpoint_ids = self.set_source_breakpoints(source, lines) +        self.assertEqual(len(breakpoint_ids), len(lines), +                         "expect correct number of breakpoints") +        self.continue_to_breakpoints(breakpoint_ids) +        if continueToExit: +            self.continue_to_exit() + + +    @skipIfWindows +    @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots +    @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin +    @no_debug_info_test +    def test_by_pid(self): +        ''' +            Tests attaching to a process by process ID. +        ''' +        self.build_and_create_debug_adaptor() +        program = self.getBuildArtifact("a.out") +        self.process = subprocess.Popen([program], +                                        stdin=subprocess.PIPE, +                                        stdout=subprocess.PIPE, +                                        stderr=subprocess.PIPE) +        self.attach(pid=self.process.pid) +        self.set_and_hit_breakpoint(continueToExit=True) + +    @skipIfWindows +    @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots +    @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin +    @no_debug_info_test +    def test_by_name(self): +        ''' +            Tests attaching to a process by process name. +        ''' +        self.build_and_create_debug_adaptor() +        orig_program = self.getBuildArtifact("a.out") +        # Since we are going to attach by process name, we need a unique +        # process name that has minimal chance to match a process that is +        # already running. To do this we use tempfile.mktemp() to give us a +        # full path to a location where we can copy our executable. We then +        # run this copy to ensure we don't get the error "more that one +        # process matches 'a.out'". +        program = tempfile.mktemp() +        shutil.copyfile(orig_program, program) +        shutil.copymode(orig_program, program) + +        def cleanup(): +            if os.path.exists(program): +                os.unlink(program) +        # Execute the cleanup function during test case tear down. +        self.addTearDownHook(cleanup) + +        self.process = subprocess.Popen([program], +                                        stdin=subprocess.PIPE, +                                        stdout=subprocess.PIPE, +                                        stderr=subprocess.PIPE) +        # Wait for a bit to ensure the process is launched +        time.sleep(5) +        self.attach(program=program) +        self.set_and_hit_breakpoint(continueToExit=True) + +    @skipUnlessDarwin +    @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots +    @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin +    @no_debug_info_test +    def test_by_name_waitFor(self): +        ''' +            Tests attaching to a process by process name and waiting for the +            next instance of a process to be launched, ingoring all current +            ones. +        ''' +        self.build_and_create_debug_adaptor() +        program = self.getBuildArtifact("a.out") +        self.spawn_thread = threading.Thread(target=spawn_and_wait, +                                             args=(program, 1.0,)) +        self.spawn_thread.start() +        self.attach(program=program, waitFor=True) +        self.set_and_hit_breakpoint(continueToExit=True) + +    @skipIfWindows +    @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots +    @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin +    @no_debug_info_test +    def test_commands(self): +        ''' +            Tests the "initCommands", "preRunCommands", "stopCommands", +            "exitCommands", and "attachCommands" that can be passed during +            attach. + +            "initCommands" are a list of LLDB commands that get executed +            before the targt is created. +            "preRunCommands" are a list of LLDB commands that get executed +            after the target has been created and before the launch. +            "stopCommands" are a list of LLDB commands that get executed each +            time the program stops. +            "exitCommands" are a list of LLDB commands that get executed when +            the process exits +            "attachCommands" are a list of LLDB commands that get executed and +            must have a valid process in the selected target in LLDB after +            they are done executing. This allows custom commands to create any +            kind of debug session. +        ''' +        self.build_and_create_debug_adaptor() +        program = self.getBuildArtifact("a.out") +        # Here we just create a target and launch the process as a way to test +        # if we are able to use attach commands to create any kind of a target +        # and use it for debugging +        attachCommands = [ +            'target create -d "%s"' % (program), +            'process launch -- arg1' +        ] +        initCommands = ['target list', 'platform list'] +        preRunCommands = ['image list a.out', 'image dump sections a.out'] +        stopCommands = ['frame variable', 'bt'] +        exitCommands = ['expr 2+3', 'expr 3+4'] +        self.attach(program=program, +                    attachCommands=attachCommands, +                    initCommands=initCommands, +                    preRunCommands=preRunCommands, +                    stopCommands=stopCommands, +                    exitCommands=exitCommands) + +        # Get output from the console. This should contain both the +        # "initCommands" and the "preRunCommands". +        output = self.get_console() +        # Verify all "initCommands" were found in console output +        self.verify_commands('initCommands', output, initCommands) +        # Verify all "preRunCommands" were found in console output +        self.verify_commands('preRunCommands', output, preRunCommands) + +        functions = ['main'] +        breakpoint_ids = self.set_function_breakpoints(functions) +        self.assertTrue(len(breakpoint_ids) == len(functions), +                        "expect one breakpoint") +        self.continue_to_breakpoints(breakpoint_ids) +        output = self.get_console(timeout=1.0) +        self.verify_commands('stopCommands', output, stopCommands) + +        # Continue after launch and hit the "pause()" call and stop the target. +        # Get output from the console. This should contain both the +        # "stopCommands" that were run after we stop. +        self.vscode.request_continue() +        time.sleep(0.5) +        self.vscode.request_pause() +        self.vscode.wait_for_stopped() +        output = self.get_console(timeout=1.0) +        self.verify_commands('stopCommands', output, stopCommands) + +        # Continue until the program exits +        self.continue_to_exit() +        # Get output from the console. This should contain both the +        # "exitCommands" that were run after the second breakpoint was hit +        output = self.get_console(timeout=1.0) +        self.verify_commands('exitCommands', output, exitCommands) diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/attach/main.c b/packages/Python/lldbsuite/test/tools/lldb-vscode/attach/main.c new file mode 100644 index 000000000000..a078d42203eb --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/attach/main.c @@ -0,0 +1,8 @@ +#include <stdio.h> +#include <unistd.h> + +int main(int argc, char const *argv[]) { +  printf("pid = %i\n", getpid()); +  sleep(5); +  return 0; // breakpoint 1 +} diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/Makefile b/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/Makefile new file mode 100644 index 000000000000..314f1cb2f077 --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setBreakpoints.py b/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setBreakpoints.py new file mode 100644 index 000000000000..1ebf2b8981ab --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setBreakpoints.py @@ -0,0 +1,211 @@ +""" +Test lldb-vscode setBreakpoints request +""" + +from __future__ import print_function + +import pprint +import unittest2 +import vscode +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import lldbvscode_testcase +import os + + +class TestVSCode_setBreakpoints(lldbvscode_testcase.VSCodeTestCaseBase): + +    mydir = TestBase.compute_mydir(__file__) + +    @skipIfWindows +    @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots +    @no_debug_info_test +    def test_set_and_clear(self): +        '''Tests setting and clearing source file and line breakpoints. +           This packet is a bit tricky on the debug adaptor side since there +           is no "clearBreakpoints" packet. Source file and line breakpoints +           are set by sending a "setBreakpoints" packet with a source file +           specified and zero or more source lines. If breakpoints have been +           set in the source file before, any exising breakpoints must remain +           set, and any new breakpoints must be created, and any breakpoints +           that were in previous requests and are not in the current request +           must be removed. This function tests this setting and clearing +           and makes sure things happen correctly. It doesn't test hitting +           breakpoints and the functionality of each breakpoint, like +           'conditions' and 'hitCondition' settings.''' +        source_basename = 'main.cpp' +        source_path = os.path.join(os.getcwd(), source_basename) +        first_line = line_number('main.cpp', 'break 12') +        second_line = line_number('main.cpp', 'break 13') +        third_line = line_number('main.cpp', 'break 14') +        lines = [first_line, second_line, third_line] + +        # Visual Studio Code Debug Adaptors have no way to specify the file +        # without launching or attaching to a process, so we must start a +        # process in order to be able to set breakpoints. +        program = self.getBuildArtifact("a.out") +        self.build_and_launch(program) + +        # Set 3 breakoints and verify that they got set correctly +        response = self.vscode.request_setBreakpoints(source_path, lines) +        line_to_id = {} +        if response: +            breakpoints = response['body']['breakpoints'] +            self.assertTrue(len(breakpoints) == len(lines), +                            "expect %u source breakpoints" % (len(lines))) +            for breakpoint in breakpoints: +                line = breakpoint['line'] +                # Store the "id" of the breakpoint that was set for later +                line_to_id[line] = breakpoint['id'] +                self.assertTrue(line in lines, "line expected in lines array") +                self.assertTrue(breakpoint['verified'], +                                "expect breakpoint verified") + +        # There is no breakpoint delete packet, clients just send another +        # setBreakpoints packet with the same source file with fewer lines. +        # Below we remove the second line entry and call the setBreakpoints +        # function again. We want to verify that any breakpoints that were set +        # before still have the same "id". This means we didn't clear the +        # breakpoint and set it again at the same location. We also need to +        # verify that the second line location was actually removed. +        lines.remove(second_line) +        # Set 2 breakoints and verify that the previous breakoints that were +        # set above are still set. +        response = self.vscode.request_setBreakpoints(source_path, lines) +        if response: +            breakpoints = response['body']['breakpoints'] +            self.assertTrue(len(breakpoints) == len(lines), +                            "expect %u source breakpoints" % (len(lines))) +            for breakpoint in breakpoints: +                line = breakpoint['line'] +                # Verify the same breakpoints are still set within LLDB by +                # making sure the breakpoint ID didn't change +                self.assertTrue(line_to_id[line] == breakpoint['id'], +                                "verify previous breakpoints stayed the same") +                self.assertTrue(line in lines, "line expected in lines array") +                self.assertTrue(breakpoint['verified'], +                                "expect breakpoint still verified") + +        # Now get the full list of breakpoints set in the target and verify +        # we have only 2 breakpoints set. The response above could have told +        # us about 2 breakpoints, but we want to make sure we don't have the +        # third one still set in the target +        response = self.vscode.request_testGetTargetBreakpoints() +        if response: +            breakpoints = response['body']['breakpoints'] +            self.assertTrue(len(breakpoints) == len(lines), +                            "expect %u source breakpoints" % (len(lines))) +            for breakpoint in breakpoints: +                line = breakpoint['line'] +                # Verify the same breakpoints are still set within LLDB by +                # making sure the breakpoint ID didn't change +                self.assertTrue(line_to_id[line] == breakpoint['id'], +                                "verify previous breakpoints stayed the same") +                self.assertTrue(line in lines, "line expected in lines array") +                self.assertTrue(breakpoint['verified'], +                                "expect breakpoint still verified") + +        # Now clear all breakpoints for the source file by passing down an +        # empty lines array +        lines = [] +        response = self.vscode.request_setBreakpoints(source_path, lines) +        if response: +            breakpoints = response['body']['breakpoints'] +            self.assertTrue(len(breakpoints) == len(lines), +                            "expect %u source breakpoints" % (len(lines))) + +        # Verify with the target that all breakpoints have been cleared +        response = self.vscode.request_testGetTargetBreakpoints() +        if response: +            breakpoints = response['body']['breakpoints'] +            self.assertTrue(len(breakpoints) == len(lines), +                            "expect %u source breakpoints" % (len(lines))) + +        # Now set a breakpoint again in the same source file and verify it +        # was added. +        lines = [second_line] +        response = self.vscode.request_setBreakpoints(source_path, lines) +        if response: +            breakpoints = response['body']['breakpoints'] +            self.assertTrue(len(breakpoints) == len(lines), +                            "expect %u source breakpoints" % (len(lines))) +            for breakpoint in breakpoints: +                line = breakpoint['line'] +                self.assertTrue(line in lines, "line expected in lines array") +                self.assertTrue(breakpoint['verified'], +                                "expect breakpoint still verified") + +        # Now get the full list of breakpoints set in the target and verify +        # we have only 2 breakpoints set. The response above could have told +        # us about 2 breakpoints, but we want to make sure we don't have the +        # third one still set in the target +        response = self.vscode.request_testGetTargetBreakpoints() +        if response: +            breakpoints = response['body']['breakpoints'] +            self.assertTrue(len(breakpoints) == len(lines), +                            "expect %u source breakpoints" % (len(lines))) +            for breakpoint in breakpoints: +                line = breakpoint['line'] +                self.assertTrue(line in lines, "line expected in lines array") +                self.assertTrue(breakpoint['verified'], +                                "expect breakpoint still verified") + +    @skipIfWindows +    @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots +    @no_debug_info_test +    def test_functionality(self): +        '''Tests hitting breakpoints and the functionality of a single +           breakpoint, like 'conditions' and 'hitCondition' settings.''' +        source_basename = 'main.cpp' +        source_path = os.path.join(os.getcwd(), source_basename) +        loop_line = line_number('main.cpp', '// break loop') + +        program = self.getBuildArtifact("a.out") +        self.build_and_launch(program) +        # Set a breakpoint at the loop line with no condition and no +        # hitCondition +        breakpoint_ids = self.set_source_breakpoints(source_path, [loop_line]) +        self.assertTrue(len(breakpoint_ids) == 1, "expect one breakpoint") +        self.vscode.request_continue() + +        # Verify we hit the breakpoint we just set +        self.verify_breakpoint_hit(breakpoint_ids) + +        # Make sure i is zero at first breakpoint +        i = int(self.vscode.get_local_variable_value('i')) +        self.assertTrue(i == 0, 'i != 0 after hitting breakpoint') + +        # Update the condition on our breakpoint +        new_breakpoint_ids = self.set_source_breakpoints(source_path, +                                                         [loop_line], +                                                         condition="i==4") +        self.assertTrue(breakpoint_ids == new_breakpoint_ids, +                        "existing breakpoint should have its condition " +                        "updated") + +        self.continue_to_breakpoints(breakpoint_ids) +        i = int(self.vscode.get_local_variable_value('i')) +        self.assertTrue(i == 4, +                        'i != 4 showing conditional works') + +        new_breakpoint_ids = self.set_source_breakpoints(source_path, +                                                         [loop_line], +                                                         hitCondition="2") + +        self.assertTrue(breakpoint_ids == new_breakpoint_ids, +                        "existing breakpoint should have its condition " +                        "updated") + +        # Continue with a hitContidtion of 2 and expect it to skip 1 value +        self.continue_to_breakpoints(breakpoint_ids) +        i = int(self.vscode.get_local_variable_value('i')) +        self.assertTrue(i == 6, +                        'i != 6 showing hitCondition works') + +        # continue after hitting our hitCondition and make sure it only goes +        # up by 1 +        self.continue_to_breakpoints(breakpoint_ids) +        i = int(self.vscode.get_local_variable_value('i')) +        self.assertTrue(i == 7, +                        'i != 7 showing post hitCondition hits every time') diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setExceptionBreakpoints.py b/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setExceptionBreakpoints.py new file mode 100644 index 000000000000..fdba683760e0 --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setExceptionBreakpoints.py @@ -0,0 +1,51 @@ +""" +Test lldb-vscode setBreakpoints request +""" + +from __future__ import print_function + +import pprint +import unittest2 +import vscode +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import lldbvscode_testcase +import os + + +class TestVSCode_setExceptionBreakpoints( +        lldbvscode_testcase.VSCodeTestCaseBase): + +    mydir = TestBase.compute_mydir(__file__) + +    @skipIfWindows +    @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots +    @no_debug_info_test +    def test_functionality(self): +        '''Tests setting and clearing exception breakpoints. +           This packet is a bit tricky on the debug adaptor side since there +           is no "clear exception breakpoints" packet. Exception breakpoints +           are set by sending a "setExceptionBreakpoints" packet with zero or +           more exception filters. If exception breakpoints have been set +           before, any exising breakpoints must remain set, and any new +           breakpoints must be created, and any breakpoints that were in +           previous requests and are not in the current request must be +           removed. This exception tests this setting and clearing and makes +           sure things happen correctly. It doesn't test hitting breakpoints +           and the functionality of each breakpoint, like 'conditions' and +           x'hitCondition' settings. +        ''' +        # Visual Studio Code Debug Adaptors have no way to specify the file +        # without launching or attaching to a process, so we must start a +        # process in order to be able to set breakpoints. +        program = self.getBuildArtifact("a.out") +        self.build_and_launch(program) + +        filters = ['cpp_throw', 'cpp_catch'] +        response = self.vscode.request_setExceptionBreakpoints(filters) +        if response: +            self.assertTrue(response['success']) + +        self.continue_to_exception_breakpoint('C++ Throw') +        self.continue_to_exception_breakpoint('C++ Catch') diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setFunctionBreakpoints.py b/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setFunctionBreakpoints.py new file mode 100644 index 000000000000..c7c67597c86b --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setFunctionBreakpoints.py @@ -0,0 +1,167 @@ +""" +Test lldb-vscode setBreakpoints request +""" + +from __future__ import print_function + +import pprint +import unittest2 +import vscode +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import lldbvscode_testcase +import os + + +class TestVSCode_setFunctionBreakpoints( +        lldbvscode_testcase.VSCodeTestCaseBase): + +    mydir = TestBase.compute_mydir(__file__) + +    @skipIfWindows +    @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots +    @skipIfLinux # test hangs on linux under heavy load +    @no_debug_info_test +    def test_set_and_clear(self): +        '''Tests setting and clearing function breakpoints. +           This packet is a bit tricky on the debug adaptor side since there +           is no "clearFunction Breakpoints" packet. Function breakpoints +           are set by sending a "setFunctionBreakpoints" packet with zero or +           more function names. If function breakpoints have been set before, +           any exising breakpoints must remain set, and any new breakpoints +           must be created, and any breakpoints that were in previous requests +           and are not in the current request must be removed. This function +           tests this setting and clearing and makes sure things happen +           correctly. It doesn't test hitting breakpoints and the functionality +           of each breakpoint, like 'conditions' and 'hitCondition' settings. +        ''' +        # Visual Studio Code Debug Adaptors have no way to specify the file +        # without launching or attaching to a process, so we must start a +        # process in order to be able to set breakpoints. +        program = self.getBuildArtifact("a.out") +        self.build_and_launch(program) +        bp_id_12 = None +        functions = ['twelve'] +        # Set a function breakpoint at 'twelve' +        response = self.vscode.request_setFunctionBreakpoints(functions) +        if response: +            breakpoints = response['body']['breakpoints'] +            self.assertTrue(len(breakpoints) == len(functions), +                            "expect %u source breakpoints" % (len(functions))) +            for breakpoint in breakpoints: +                bp_id_12 = breakpoint['id'] +                self.assertTrue(breakpoint['verified'], +                                "expect breakpoint verified") + +        # Add an extra name and make sure we have two breakpoints after this +        functions.append('thirteen') +        response = self.vscode.request_setFunctionBreakpoints(functions) +        if response: +            breakpoints = response['body']['breakpoints'] +            self.assertTrue(len(breakpoints) == len(functions), +                            "expect %u source breakpoints" % (len(functions))) +            for breakpoint in breakpoints: +                self.assertTrue(breakpoint['verified'], +                                "expect breakpoint verified") + +        # There is no breakpoint delete packet, clients just send another +        # setFunctionBreakpoints packet with the different function names. +        functions.remove('thirteen') +        response = self.vscode.request_setFunctionBreakpoints(functions) +        if response: +            breakpoints = response['body']['breakpoints'] +            self.assertTrue(len(breakpoints) == len(functions), +                            "expect %u source breakpoints" % (len(functions))) +            for breakpoint in breakpoints: +                bp_id = breakpoint['id'] +                self.assertTrue(bp_id == bp_id_12, +                                'verify "twelve" breakpoint ID is same') +                self.assertTrue(breakpoint['verified'], +                                "expect breakpoint still verified") + +        # Now get the full list of breakpoints set in the target and verify +        # we have only 1 breakpoints set. The response above could have told +        # us about 1 breakpoints, but we want to make sure we don't have the +        # second one still set in the target +        response = self.vscode.request_testGetTargetBreakpoints() +        if response: +            breakpoints = response['body']['breakpoints'] +            self.assertTrue(len(breakpoints) == len(functions), +                            "expect %u source breakpoints" % (len(functions))) +            for breakpoint in breakpoints: +                bp_id = breakpoint['id'] +                self.assertTrue(bp_id == bp_id_12, +                                'verify "twelve" breakpoint ID is same') +                self.assertTrue(breakpoint['verified'], +                                "expect breakpoint still verified") + +        # Now clear all breakpoints for the source file by passing down an +        # empty lines array +        functions = [] +        response = self.vscode.request_setFunctionBreakpoints(functions) +        if response: +            breakpoints = response['body']['breakpoints'] +            self.assertTrue(len(breakpoints) == len(functions), +                            "expect %u source breakpoints" % (len(functions))) + +        # Verify with the target that all breakpoints have been cleared +        response = self.vscode.request_testGetTargetBreakpoints() +        if response: +            breakpoints = response['body']['breakpoints'] +            self.assertTrue(len(breakpoints) == len(functions), +                            "expect %u source breakpoints" % (len(functions))) + +    @skipIfWindows +    @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots +    @no_debug_info_test +    def test_functionality(self): +        '''Tests hitting breakpoints and the functionality of a single +           breakpoint, like 'conditions' and 'hitCondition' settings.''' + +        program = self.getBuildArtifact("a.out") +        self.build_and_launch(program) +        # Set a breakpoint on "twelve" with no condition and no hitCondition +        functions = ['twelve'] +        breakpoint_ids = self.set_function_breakpoints(functions) + +        self.assertTrue(len(breakpoint_ids) == len(functions), +                        "expect one breakpoint") + +        # Verify we hit the breakpoint we just set +        self.continue_to_breakpoints(breakpoint_ids) + +        # Make sure i is zero at first breakpoint +        i = int(self.vscode.get_local_variable_value('i')) +        self.assertTrue(i == 0, 'i != 0 after hitting breakpoint') + +        # Update the condition on our breakpoint +        new_breakpoint_ids = self.set_function_breakpoints(functions, +                                                           condition="i==4") +        self.assertTrue(breakpoint_ids == new_breakpoint_ids, +                        "existing breakpoint should have its condition " +                        "updated") + +        self.continue_to_breakpoints(breakpoint_ids) +        i = int(self.vscode.get_local_variable_value('i')) +        self.assertTrue(i == 4, +                        'i != 4 showing conditional works') +        new_breakpoint_ids = self.set_function_breakpoints(functions, +                                                           hitCondition="2") + +        self.assertTrue(breakpoint_ids == new_breakpoint_ids, +                        "existing breakpoint should have its condition " +                        "updated") + +        # Continue with a hitContidtion of 2 and expect it to skip 1 value +        self.continue_to_breakpoints(breakpoint_ids) +        i = int(self.vscode.get_local_variable_value('i')) +        self.assertTrue(i == 6, +                        'i != 6 showing hitCondition works') + +        # continue after hitting our hitCondition and make sure it only goes +        # up by 1 +        self.continue_to_breakpoints(breakpoint_ids) +        i = int(self.vscode.get_local_variable_value('i')) +        self.assertTrue(i == 7, +                        'i != 7 showing post hitCondition hits every time') diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/main.cpp b/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/main.cpp new file mode 100644 index 000000000000..e859b04e3a99 --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/main.cpp @@ -0,0 +1,27 @@ +#include <stdio.h> +#include <stdexcept> + +int twelve(int i) { +  return 12 + i; // break 12 +} + +int thirteen(int i) { +  return 13 + i; // break 13 +} + +namespace a { +  int fourteen(int i) { +    return 14 + i; // break 14 +  } +} +int main(int argc, char const *argv[]) { +  for (int i=0; i<10; ++i) { +    int x = twelve(i) + thirteen(i) + a::fourteen(i); // break loop +  } +  try { +    throw std::invalid_argument( "throwing exception for testing" ); +  } catch (...) { +    puts("caught exception..."); +  } +  return 0; +} diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/launch/Makefile b/packages/Python/lldbsuite/test/tools/lldb-vscode/launch/Makefile new file mode 100644 index 000000000000..b09a579159d4 --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/launch/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/launch/TestVSCode_launch.py b/packages/Python/lldbsuite/test/tools/lldb-vscode/launch/TestVSCode_launch.py new file mode 100644 index 000000000000..064cf9a6783e --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/launch/TestVSCode_launch.py @@ -0,0 +1,352 @@ +""" +Test lldb-vscode setBreakpoints request +""" + +from __future__ import print_function + +import pprint +import unittest2 +import vscode +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import lldbvscode_testcase +import os +import time + + +class TestVSCode_launch(lldbvscode_testcase.VSCodeTestCaseBase): + +    mydir = TestBase.compute_mydir(__file__) + +    @skipIfWindows +    @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots +    @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin +    @no_debug_info_test +    def test_default(self): +        ''' +            Tests the default launch of a simple program. No arguments, +            environment, or anything else is specified. +        ''' +        program = self.getBuildArtifact("a.out") +        self.build_and_launch(program) +        self.continue_to_exit() +        # Now get the STDOUT and verify our program argument is correct +        output = self.get_stdout() +        self.assertTrue(output and len(output) > 0, +                        "expect program output") +        lines = output.splitlines() +        self.assertTrue(program in lines[0], +                        "make sure program path is in first argument") + +    @skipIfWindows +    @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots +    @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin +    @no_debug_info_test +    def test_stopOnEntry(self): +        ''' +            Tests the default launch of a simple program that stops at the +            entry point instead of continuing. +        ''' +        program = self.getBuildArtifact("a.out") +        self.build_and_launch(program, stopOnEntry=True) +        self.set_function_breakpoints(['main']) +        stopped_events = self.continue_to_next_stop() +        for stopped_event in stopped_events: +            if 'body' in stopped_event: +                body = stopped_event['body'] +                if 'reason' in body: +                    reason = body['reason'] +                    self.assertTrue( +                        reason != 'breakpoint', +                        'verify stop isn\'t "main" breakpoint') + +    @skipIfWindows +    @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots +    @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin +    @no_debug_info_test +    def test_cwd(self): +        ''' +            Tests the default launch of a simple program with a current working +            directory. +        ''' +        program = self.getBuildArtifact("a.out") +        program_parent_dir = os.path.split(os.path.split(program)[0])[0] +        self.build_and_launch(program, +                              cwd=program_parent_dir) +        self.continue_to_exit() +        # Now get the STDOUT and verify our program argument is correct +        output = self.get_stdout() +        self.assertTrue(output and len(output) > 0, +                        "expect program output") +        lines = output.splitlines() +        found = False +        for line in lines: +            if line.startswith('cwd = \"'): +                quote_path = '"%s"' % (program_parent_dir) +                found = True +                self.assertTrue(quote_path in line, +                                "working directory '%s' not in '%s'" % ( +                                    program_parent_dir, line)) +        self.assertTrue(found, "verified program working directory") + +    @skipIfWindows +    @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots +    @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin +    @no_debug_info_test +    def test_debuggerRoot(self): +        ''' +            Tests the "debuggerRoot" will change the working directory of +            the lldb-vscode debug adaptor. +        ''' +        program = self.getBuildArtifact("a.out") +        program_parent_dir = os.path.split(os.path.split(program)[0])[0] +        commands = ['platform shell echo cwd = $PWD'] +        self.build_and_launch(program, +                              debuggerRoot=program_parent_dir, +                              initCommands=commands) +        output = self.get_console() +        self.assertTrue(output and len(output) > 0, +                        "expect console output") +        lines = output.splitlines() +        prefix = 'cwd = ' +        found = False +        for line in lines: +            if line.startswith(prefix): +                found = True +                self.assertTrue(program_parent_dir == line[len(prefix):], +                                "lldb-vscode working dir '%s' == '%s'" % ( +                                    program_parent_dir, line[6:])) +        self.assertTrue(found, "verified lldb-vscode working directory") +        self.continue_to_exit() + +    @skipIfWindows +    @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots +    @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin +    @no_debug_info_test +    def test_sourcePath(self): +        ''' +            Tests the "sourcePath" will set the target.source-map. +        ''' +        program = self.getBuildArtifact("a.out") +        program_dir = os.path.split(program)[0] +        self.build_and_launch(program, +                              sourcePath=program_dir) +        output = self.get_console() +        self.assertTrue(output and len(output) > 0, +                        "expect console output") +        lines = output.splitlines() +        prefix = '(lldb) settings set target.source-map "." ' +        found = False +        for line in lines: +            if line.startswith(prefix): +                found = True +                quoted_path = '"%s"' % (program_dir) +                self.assertTrue(quoted_path == line[len(prefix):], +                                "lldb-vscode working dir %s == %s" % ( +                                    quoted_path, line[6:])) +        self.assertTrue(found, 'found "sourcePath" in console output') +        self.continue_to_exit() + +    @skipIfWindows +    @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots +    @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin +    @no_debug_info_test +    def test_disableSTDIO(self): +        ''' +            Tests the default launch of a simple program with STDIO disabled. +        ''' +        program = self.getBuildArtifact("a.out") +        self.build_and_launch(program, +                              disableSTDIO=True) +        self.continue_to_exit() +        # Now get the STDOUT and verify our program argument is correct +        output = self.get_stdout() +        self.assertTrue(output is None or len(output) == 0, +                        "expect no program output") + +    @skipIfWindows +    @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots +    @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin +    @no_debug_info_test +    def test_shellExpandArguments_enabled(self): +        ''' +            Tests the default launch of a simple program with shell expansion +            enabled. +        ''' +        program = self.getBuildArtifact("a.out") +        program_dir = os.path.split(program)[0] +        glob = os.path.join(program_dir, '*.out') +        self.build_and_launch(program, args=[glob], shellExpandArguments=True) +        self.continue_to_exit() +        # Now get the STDOUT and verify our program argument is correct +        output = self.get_stdout() +        self.assertTrue(output and len(output) > 0, +                        "expect no program output") +        lines = output.splitlines() +        for line in lines: +            quote_path = '"%s"' % (program) +            if line.startswith("arg[1] ="): +                self.assertTrue(quote_path in line, +                                'verify "%s" expanded to "%s"' % ( +                                    glob, program)) + +    @skipIfWindows +    @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots +    @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin +    @no_debug_info_test +    def test_shellExpandArguments_disabled(self): +        ''' +            Tests the default launch of a simple program with shell expansion +            disabled. +        ''' +        program = self.getBuildArtifact("a.out") +        program_dir = os.path.split(program)[0] +        glob = os.path.join(program_dir, '*.out') +        self.build_and_launch(program, +                              args=[glob], +                              shellExpandArguments=False) +        self.continue_to_exit() +        # Now get the STDOUT and verify our program argument is correct +        output = self.get_stdout() +        self.assertTrue(output and len(output) > 0, +                        "expect no program output") +        lines = output.splitlines() +        for line in lines: +            quote_path = '"%s"' % (glob) +            if line.startswith("arg[1] ="): +                self.assertTrue(quote_path in line, +                                'verify "%s" stayed to "%s"' % ( +                                    glob, glob)) + +    @skipIfWindows +    @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots +    @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin +    @no_debug_info_test +    def test_args(self): +        ''' +            Tests launch of a simple program with arguments +        ''' +        program = self.getBuildArtifact("a.out") +        args = ["one", "with space", "'with single quotes'", +                '"with double quotes"'] +        self.build_and_launch(program, +                              args=args) +        self.continue_to_exit() + +        # Now get the STDOUT and verify our arguments got passed correctly +        output = self.get_stdout() +        self.assertTrue(output and len(output) > 0, +                        "expect program output") +        lines = output.splitlines() +        # Skip the first argument that contains the program name +        lines.pop(0) +        # Make sure arguments we specified are correct +        for (i, arg) in enumerate(args): +            quoted_arg = '"%s"' % (arg) +            self.assertTrue(quoted_arg in lines[i], +                            'arg[%i] "%s" not in "%s"' % (i+1, quoted_arg, lines[i])) + +    @skipIfWindows +    @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots +    @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin +    @no_debug_info_test +    def test_environment(self): +        ''' +            Tests launch of a simple program with environment variables +        ''' +        program = self.getBuildArtifact("a.out") +        env = ["NO_VALUE", "WITH_VALUE=BAR", "EMPTY_VALUE=", +               "SPACE=Hello World"] +        self.build_and_launch(program, +                              env=env) +        self.continue_to_exit() + +        # Now get the STDOUT and verify our arguments got passed correctly +        output = self.get_stdout() +        self.assertTrue(output and len(output) > 0, +                        "expect program output") +        lines = output.splitlines() +        # Skip the all arguments so we have only environment vars left +        while len(lines) and lines[0].startswith("arg["): +            lines.pop(0) +        # Make sure each environment variable in "env" is actually set in the +        # program environment that was printed to STDOUT +        for var in env: +            found = False +            for program_var in lines: +                if var in program_var: +                    found = True +                    break +            self.assertTrue(found, +                            '"%s" must exist in program environment (%s)' % ( +                                var, lines)) + +    @skipIfWindows +    @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots +    @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin +    @no_debug_info_test +    def test_commands(self): +        ''' +            Tests the "initCommands", "preRunCommands", "stopCommands" and +            "exitCommands" that can be passed during launch. + +            "initCommands" are a list of LLDB commands that get executed +            before the targt is created. +            "preRunCommands" are a list of LLDB commands that get executed +            after the target has been created and before the launch. +            "stopCommands" are a list of LLDB commands that get executed each +            time the program stops. +            "exitCommands" are a list of LLDB commands that get executed when +            the process exits +        ''' +        program = self.getBuildArtifact("a.out") +        initCommands = ['target list', 'platform list'] +        preRunCommands = ['image list a.out', 'image dump sections a.out'] +        stopCommands = ['frame variable', 'bt'] +        exitCommands = ['expr 2+3', 'expr 3+4'] +        self.build_and_launch(program, +                              initCommands=initCommands, +                              preRunCommands=preRunCommands, +                              stopCommands=stopCommands, +                              exitCommands=exitCommands) + +        # Get output from the console. This should contain both the +        # "initCommands" and the "preRunCommands". +        output = self.get_console() +        # Verify all "initCommands" were found in console output +        self.verify_commands('initCommands', output, initCommands) +        # Verify all "preRunCommands" were found in console output +        self.verify_commands('preRunCommands', output, preRunCommands) + +        source = 'main.c' +        first_line = line_number(source, '// breakpoint 1') +        second_line = line_number(source, '// breakpoint 2') +        lines = [first_line, second_line] + +        # Set 2 breakoints so we can verify that "stopCommands" get run as the +        # breakpoints get hit +        breakpoint_ids = self.set_source_breakpoints(source, lines) +        self.assertTrue(len(breakpoint_ids) == len(lines), +                        "expect correct number of breakpoints") + +        # Continue after launch and hit the first breakpoint. +        # Get output from the console. This should contain both the +        # "stopCommands" that were run after the first breakpoint was hit +        self.continue_to_breakpoints(breakpoint_ids) +        output = self.get_console(timeout=1.0) +        self.verify_commands('stopCommands', output, stopCommands) + +        # Continue again and hit the second breakpoint. +        # Get output from the console. This should contain both the +        # "stopCommands" that were run after the second breakpoint was hit +        self.continue_to_breakpoints(breakpoint_ids) +        output = self.get_console(timeout=1.0) +        self.verify_commands('stopCommands', output, stopCommands) + +        # Continue until the program exits +        self.continue_to_exit() +        # Get output from the console. This should contain both the +        # "exitCommands" that were run after the second breakpoint was hit +        output = self.get_console(timeout=1.0) +        self.verify_commands('exitCommands', output, exitCommands) diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/launch/main.c b/packages/Python/lldbsuite/test/tools/lldb-vscode/launch/main.c new file mode 100644 index 000000000000..aed2af9828f3 --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/launch/main.c @@ -0,0 +1,15 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +int main(int argc, char const *argv[], char const *envp[]) { +  for (int i=0; i<argc; ++i) +    printf("arg[%i] = \"%s\"\n", i, argv[i]); +  for (int i=0; envp[i]; ++i) +    printf("env[%i] = \"%s\"\n", i, envp[i]); +  char *cwd = getcwd(NULL, 0); +  printf("cwd = \"%s\"\n", cwd); // breakpoint 1 +  free(cwd); +  cwd = NULL; +  return 0;  // breakpoint 2 +} diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py b/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py new file mode 100644 index 000000000000..c66c6bb7af6b --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py @@ -0,0 +1,288 @@ +from __future__ import print_function + +from lldbsuite.test.lldbtest import * +import os +import vscode + + +class VSCodeTestCaseBase(TestBase): + +    def create_debug_adaptor(self): +        '''Create the Visual Studio Code debug adaptor''' +        self.assertTrue(os.path.exists(self.lldbVSCodeExec), +                        'lldb-vscode must exist') +        self.vscode = vscode.DebugAdaptor(executable=self.lldbVSCodeExec) + +    def build_and_create_debug_adaptor(self): +        self.build() +        self.create_debug_adaptor() + +    def set_source_breakpoints(self, source_path, lines, condition=None, +                               hitCondition=None): +        '''Sets source breakpoints and returns an array of strings containing +           the breakpoint location IDs ("1.1", "1.2") for each breakpoint +           that was set. +        ''' +        response = self.vscode.request_setBreakpoints( +            source_path, lines, condition=condition, hitCondition=hitCondition) +        if response is None: +            return [] +        breakpoints = response['body']['breakpoints'] +        breakpoint_ids = [] +        for breakpoint in breakpoints: +            response_id = breakpoint['id'] +            bp_id = response_id >> 32 +            bp_loc_id = response_id & 0xffffffff +            breakpoint_ids.append('%i.%i' % (bp_id, bp_loc_id)) +        return breakpoint_ids + +    def set_function_breakpoints(self, functions, condition=None, +                                 hitCondition=None): +        '''Sets breakpoints by function name given an array of function names +           and returns an array of strings containing the breakpoint location +           IDs ("1.1", "1.2") for each breakpoint that was set. +        ''' +        response = self.vscode.request_setFunctionBreakpoints( +            functions, condition=condition, hitCondition=hitCondition) +        if response is None: +            return [] +        breakpoints = response['body']['breakpoints'] +        breakpoint_ids = [] +        for breakpoint in breakpoints: +            response_id = breakpoint['id'] +            bp_id = response_id >> 32 +            bp_loc_id = response_id & 0xffffffff +            breakpoint_ids.append('%i.%i' % (bp_id, bp_loc_id)) +        return breakpoint_ids + +    def verify_breakpoint_hit(self, breakpoint_ids): +        '''Wait for the process we are debugging to stop, and verify we hit +           any breakpoint location in the "breakpoint_ids" array. +           "breakpoint_ids" should be a list of breakpoint location ID strings +           (["1.1", "2.1"]). The return value from +           self.set_source_breakpoints() can be passed to this function''' +        stopped_events = self.vscode.wait_for_stopped() +        for stopped_event in stopped_events: +            if 'body' in stopped_event: +                body = stopped_event['body'] +                if 'reason' not in body: +                    continue +                if body['reason'] != 'breakpoint': +                    continue +                if 'description' not in body: +                    continue +                # Description is "breakpoint 1.1", so look for any location id +                # ("1.1") in the description field as verification that one of +                # the breakpoint locations was hit +                description = body['description'] +                for breakpoint_id in breakpoint_ids: +                    if breakpoint_id in description: +                        return True +        return False + +    def verify_exception_breakpoint_hit(self, filter_label): +        '''Wait for the process we are debugging to stop, and verify the stop +           reason is 'exception' and that the description matches +           'filter_label' +        ''' +        stopped_events = self.vscode.wait_for_stopped() +        for stopped_event in stopped_events: +            if 'body' in stopped_event: +                body = stopped_event['body'] +                if 'reason' not in body: +                    continue +                if body['reason'] != 'exception': +                    continue +                if 'description' not in body: +                    continue +                description = body['description'] +                if filter_label == description: +                    return True +        return False + +    def verify_commands(self, flavor, output, commands): +        self.assertTrue(output and len(output) > 0, "expect console output") +        lines = output.splitlines() +        prefix = '(lldb) ' +        for cmd in commands: +            found = False +            for line in lines: +                if line.startswith(prefix) and cmd in line: +                    found = True +                    break +            self.assertTrue(found, +                            "verify '%s' found in console output for '%s'" % ( +                                cmd, flavor)) + +    def get_dict_value(self, d, key_path): +        '''Verify each key in the key_path array is in contained in each +           dictionary within "d". Assert if any key isn't in the +           corresponding dictionary. This is handy for grabbing values from VS +           Code response dictionary like getting +           response['body']['stackFrames'] +        ''' +        value = d +        for key in key_path: +            if key in value: +                value = value[key] +            else: +                self.assertTrue(key in value, +                                'key "%s" from key_path "%s" not in "%s"' % ( +                                    key, key_path, d)) +        return value + +    def get_stackFrames(self, threadId=None, startFrame=None, levels=None, +                        dump=False): +        response = self.vscode.request_stackTrace(threadId=threadId, +                                                  startFrame=startFrame, +                                                  levels=levels, +                                                  dump=dump) +        if response: +            return self.get_dict_value(response, ['body', 'stackFrames']) +        return None + +    def get_source_and_line(self, threadId=None, frameIndex=0): +        stackFrames = self.get_stackFrames(threadId=threadId, +                                           startFrame=frameIndex, +                                           levels=1) +        if stackFrames is not None: +            stackFrame = stackFrames[0] +            ['source', 'path'] +            if 'source' in stackFrame: +                source = stackFrame['source'] +                if 'path' in source: +                    if 'line' in stackFrame: +                        return (source['path'], stackFrame['line']) +        return ('', 0) + +    def get_stdout(self, timeout=0.0): +        return self.vscode.get_output('stdout', timeout=timeout) + +    def get_console(self, timeout=0.0): +        return self.vscode.get_output('console', timeout=timeout) + +    def get_local_as_int(self, name, threadId=None): +        value = self.vscode.get_local_variable_value(name, threadId=threadId) +        if value.startswith('0x'): +            return int(value, 16) +        elif value.startswith('0'): +            return int(value, 8) +        else: +            return int(value) + +    def set_local(self, name, value, id=None): +        '''Set a top level local variable only.''' +        return self.vscode.request_setVariable(1, name, str(value), id=id) + +    def set_global(self, name, value, id=None): +        '''Set a top level global variable only.''' +        return self.vscode.request_setVariable(2, name, str(value), id=id) + +    def stepIn(self, threadId=None, waitForStop=True): +        self.vscode.request_stepIn(threadId=threadId) +        if waitForStop: +            return self.vscode.wait_for_stopped() +        return None + +    def stepOver(self, threadId=None, waitForStop=True): +        self.vscode.request_next(threadId=threadId) +        if waitForStop: +            return self.vscode.wait_for_stopped() +        return None + +    def stepOut(self, threadId=None, waitForStop=True): +        self.vscode.request_stepOut(threadId=threadId) +        if waitForStop: +            return self.vscode.wait_for_stopped() +        return None + +    def continue_to_next_stop(self): +        self.vscode.request_continue() +        return self.vscode.wait_for_stopped() + +    def continue_to_breakpoints(self, breakpoint_ids): +        self.vscode.request_continue() +        self.verify_breakpoint_hit(breakpoint_ids) + +    def continue_to_exception_breakpoint(self, filter_label): +        self.vscode.request_continue() +        self.assertTrue(self.verify_exception_breakpoint_hit(filter_label), +                        'verify we got "%s"' % (filter_label)) + +    def continue_to_exit(self, exitCode=0): +        self.vscode.request_continue() +        stopped_events = self.vscode.wait_for_stopped() +        self.assertTrue(len(stopped_events) == 1, +                        "expecting single 'exited' event") +        self.assertTrue(stopped_events[0]['event'] == 'exited', +                        'make sure program ran to completion') +        self.assertTrue(stopped_events[0]['body']['exitCode'] == exitCode, +                        'exitCode == %i' % (exitCode)) + +    def attach(self, program=None, pid=None, waitFor=None, trace=None, +               initCommands=None, preRunCommands=None, stopCommands=None, +               exitCommands=None, attachCommands=None): +        '''Build the default Makefile target, create the VSCode debug adaptor, +           and attach to the process. +        ''' +        # Make sure we disconnect and terminate the VSCode debug adaptor even +        # if we throw an exception during the test case. +        def cleanup(): +            self.vscode.request_disconnect(terminateDebuggee=True) +            self.vscode.terminate() + +        # Execute the cleanup function during test case tear down. +        self.addTearDownHook(cleanup) +        # Initialize and launch the program +        self.vscode.request_initialize() +        response = self.vscode.request_attach( +            program=program, pid=pid, waitFor=waitFor, trace=trace, +            initCommands=initCommands, preRunCommands=preRunCommands, +            stopCommands=stopCommands, exitCommands=exitCommands, +            attachCommands=attachCommands) +        if not (response and response['success']): +            self.assertTrue(response['success'], +                            'attach failed (%s)' % (response['message'])) + +    def build_and_launch(self, program, args=None, cwd=None, env=None, +                         stopOnEntry=False, disableASLR=True, +                         disableSTDIO=False, shellExpandArguments=False, +                         trace=False, initCommands=None, preRunCommands=None, +                         stopCommands=None, exitCommands=None, +                         sourcePath=None, debuggerRoot=None): +        '''Build the default Makefile target, create the VSCode debug adaptor, +           and launch the process. +        ''' +        self.build_and_create_debug_adaptor() +        self.assertTrue(os.path.exists(program), 'executable must exist') + +        # Make sure we disconnect and terminate the VSCode debug adaptor even +        # if we throw an exception during the test case. +        def cleanup(): +            self.vscode.request_disconnect(terminateDebuggee=True) +            self.vscode.terminate() + +        # Execute the cleanup function during test case tear down. +        self.addTearDownHook(cleanup) + +        # Initialize and launch the program +        self.vscode.request_initialize() +        response = self.vscode.request_launch( +            program, +            args=args, +            cwd=cwd, +            env=env, +            stopOnEntry=stopOnEntry, +            disableASLR=disableASLR, +            disableSTDIO=disableSTDIO, +            shellExpandArguments=shellExpandArguments, +            trace=trace, +            initCommands=initCommands, +            preRunCommands=preRunCommands, +            stopCommands=stopCommands, +            exitCommands=exitCommands, +            sourcePath=sourcePath, +            debuggerRoot=debuggerRoot) +        if not (response and response['success']): +            self.assertTrue(response['success'], +                            'launch failed (%s)' % (response['message'])) diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/stackTrace/Makefile b/packages/Python/lldbsuite/test/tools/lldb-vscode/stackTrace/Makefile new file mode 100644 index 000000000000..b09a579159d4 --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/stackTrace/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/stackTrace/TestVSCode_stackTrace.py b/packages/Python/lldbsuite/test/tools/lldb-vscode/stackTrace/TestVSCode_stackTrace.py new file mode 100644 index 000000000000..4bb061881c47 --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/stackTrace/TestVSCode_stackTrace.py @@ -0,0 +1,160 @@ +""" +Test lldb-vscode setBreakpoints request +""" + +from __future__ import print_function + +import unittest2 +import vscode +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import lldbvscode_testcase +import os + + +class TestVSCode_stackTrace(lldbvscode_testcase.VSCodeTestCaseBase): + +    mydir = TestBase.compute_mydir(__file__) +    name_key_path = ['name'] +    source_key_path = ['source', 'path'] +    line_key_path = ['line'] + +    def verify_stackFrames(self, start_idx, stackFrames): +        frame_idx = start_idx +        for stackFrame in stackFrames: +            # Don't care about frame above main +            if frame_idx > 20: +                return +            self.verify_stackFrame(frame_idx, stackFrame) +            frame_idx += 1 + +    def verify_stackFrame(self, frame_idx, stackFrame): +        frame_name = self.get_dict_value(stackFrame, self.name_key_path) +        frame_source = self.get_dict_value(stackFrame, self.source_key_path) +        frame_line = self.get_dict_value(stackFrame, self.line_key_path) +        if frame_idx == 0: +            expected_line = self.recurse_end +            expected_name = 'recurse' +        elif frame_idx < 20: +            expected_line = self.recurse_call +            expected_name = 'recurse' +        else: +            expected_line = self.recurse_invocation +            expected_name = 'main' +        self.assertTrue(frame_name == expected_name, +                        'frame #%i name "%s" == "%s"' % ( +                            frame_idx, frame_name, expected_name)) +        self.assertTrue(frame_source == self.source_path, +                        'frame #%i source "%s" == "%s"' % ( +                            frame_idx, frame_source, self.source_path)) +        self.assertTrue(frame_line == expected_line, +                        'frame #%i line %i == %i' % (frame_idx, frame_line, +                                                     expected_line)) + +    @skipIfWindows +    @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots +    @no_debug_info_test +    def test_stackTrace(self): +        ''' +            Tests the 'stackTrace' packet and all its variants. +        ''' +        program = self.getBuildArtifact("a.out") +        self.build_and_launch(program) +        source = 'main.c' +        self.source_path = os.path.join(os.getcwd(), source) +        self.recurse_end = line_number(source, 'recurse end') +        self.recurse_call = line_number(source, 'recurse call') +        self.recurse_invocation = line_number(source, 'recurse invocation') + +        lines = [self.recurse_end] + +        # Set breakoint at a point of deepest recuusion +        breakpoint_ids = self.set_source_breakpoints(source, lines) +        self.assertTrue(len(breakpoint_ids) == len(lines), +                        "expect correct number of breakpoints") + +        self.continue_to_breakpoints(breakpoint_ids) +        startFrame = 0 +        # Verify we get all stack frames with no arguments +        stackFrames = self.get_stackFrames() +        frameCount = len(stackFrames) +        self.assertTrue(frameCount >= 20, +                        'verify we get at least 20 frames for all frames') +        self.verify_stackFrames(startFrame, stackFrames) + +        # Verify all stack frames by specifying startFrame = 0 and levels not +        # specified +        stackFrames = self.get_stackFrames(startFrame=startFrame) +        self.assertTrue(frameCount == len(stackFrames), +                        ('verify same number of frames with startFrame=%i') % ( +                            startFrame)) +        self.verify_stackFrames(startFrame, stackFrames) + +        # Verify all stack frames by specifying startFrame = 0 and levels = 0 +        levels = 0 +        stackFrames = self.get_stackFrames(startFrame=startFrame, +                                           levels=levels) +        self.assertTrue(frameCount == len(stackFrames), +                        ('verify same number of frames with startFrame=%i and' +                         ' levels=%i') % (startFrame, levels)) +        self.verify_stackFrames(startFrame, stackFrames) + +        # Get only the first stack frame by sepcifying startFrame = 0 and +        # levels = 1 +        levels = 1 +        stackFrames = self.get_stackFrames(startFrame=startFrame, +                                           levels=levels) +        self.assertTrue(levels == len(stackFrames), +                        ('verify one frame with startFrame=%i and' +                         ' levels=%i') % (startFrame, levels)) +        self.verify_stackFrames(startFrame, stackFrames) + +        # Get only the first 3 stack frames by sepcifying startFrame = 0 and +        # levels = 3 +        levels = 3 +        stackFrames = self.get_stackFrames(startFrame=startFrame, +                                           levels=levels) +        self.assertTrue(levels == len(stackFrames), +                        ('verify %i frames with startFrame=%i and' +                         ' levels=%i') % (levels, startFrame, levels)) +        self.verify_stackFrames(startFrame, stackFrames) + +        # Get only the first 15 stack frames by sepcifying startFrame = 5 and +        # levels = 16 +        startFrame = 5 +        levels = 16 +        stackFrames = self.get_stackFrames(startFrame=startFrame, +                                           levels=levels) +        self.assertTrue(levels == len(stackFrames), +                        ('verify %i frames with startFrame=%i and' +                         ' levels=%i') % (levels, startFrame, levels)) +        self.verify_stackFrames(startFrame, stackFrames) + +        # Verify we cap things correctly when we ask for too many frames +        startFrame = 5 +        levels = 1000 +        stackFrames = self.get_stackFrames(startFrame=startFrame, +                                           levels=levels) +        self.assertTrue(len(stackFrames) == frameCount - startFrame, +                        ('verify less than 1000 frames with startFrame=%i and' +                         ' levels=%i') % (startFrame, levels)) +        self.verify_stackFrames(startFrame, stackFrames) + +        # Verify level=0 works with non-zerp start frame +        startFrame = 5 +        levels = 0 +        stackFrames = self.get_stackFrames(startFrame=startFrame, +                                           levels=levels) +        self.assertTrue(len(stackFrames) == frameCount - startFrame, +                        ('verify less than 1000 frames with startFrame=%i and' +                         ' levels=%i') % (startFrame, levels)) +        self.verify_stackFrames(startFrame, stackFrames) + +        # Verify we get not frames when startFrame is too high +        startFrame = 1000 +        levels = 1 +        stackFrames = self.get_stackFrames(startFrame=startFrame, +                                           levels=levels) +        self.assertTrue(0 == len(stackFrames), +                        'verify zero frames with startFrame out of bounds') diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/stackTrace/main.c b/packages/Python/lldbsuite/test/tools/lldb-vscode/stackTrace/main.c new file mode 100644 index 000000000000..85b41c492817 --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/stackTrace/main.c @@ -0,0 +1,13 @@ +#include <stdio.h> +#include <unistd.h> + +int recurse(int x) { +  if (x <= 1) +    return 1; // recurse end +  return recurse(x-1) + x; // recurse call +} + +int main(int argc, char const *argv[]) { +  recurse(20); // recurse invocation +  return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/stop-hook/multiple_threads/Makefile b/packages/Python/lldbsuite/test/tools/lldb-vscode/step/Makefile index 035413ff763d..f24bb9f4d267 100644 --- a/packages/Python/lldbsuite/test/functionalities/stop-hook/multiple_threads/Makefile +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/step/Makefile @@ -1,6 +1,7 @@  LEVEL = ../../../make -CXX_SOURCES := main.cpp  ENABLE_THREADS := YES +CXX_SOURCES := main.cpp +  include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/step/TestVSCode_step.py b/packages/Python/lldbsuite/test/tools/lldb-vscode/step/TestVSCode_step.py new file mode 100644 index 000000000000..87ec71a513f6 --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/step/TestVSCode_step.py @@ -0,0 +1,79 @@ +""" +Test lldb-vscode setBreakpoints request +""" + +from __future__ import print_function + +import unittest2 +import vscode +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import lldbvscode_testcase +import os + + +class TestVSCode_step(lldbvscode_testcase.VSCodeTestCaseBase): + +    mydir = TestBase.compute_mydir(__file__) + +    @skipIfWindows +    @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots +    @no_debug_info_test +    def test_step(self): +        ''' +            Tests the stepping in/out/over in threads. +        ''' +        program = self.getBuildArtifact("a.out") +        self.build_and_launch(program) +        source = 'main.cpp' +        # source_path = os.path.join(os.getcwd(), source) +        breakpoint1_line = line_number(source, '// breakpoint 1') +        lines = [breakpoint1_line] +        # Set breakoint in the thread function so we can step the threads +        breakpoint_ids = self.set_source_breakpoints(source, lines) +        self.assertTrue(len(breakpoint_ids) == len(lines), +                        "expect correct number of breakpoints") +        self.continue_to_breakpoints(breakpoint_ids) +        threads = self.vscode.get_threads() +        for thread in threads: +            if 'reason' in thread: +                reason = thread['reason'] +                if reason == 'breakpoint': +                    # We have a thread that is stopped at our breakpoint. +                    # Get the value of "x" and get the source file and line. +                    # These will help us determine if we are stepping +                    # correctly. If we step a thread correctly we will verify +                    # the correct falue for x as it progresses through the +                    # program. +                    tid = thread['id'] +                    x1 = self.get_local_as_int('x', threadId=tid) +                    (src1, line1) = self.get_source_and_line(threadId=tid) + +                    # Now step into the "recurse()" function call again and +                    # verify, using the new value of "x" and the source file +                    # and line if we stepped correctly +                    self.stepIn(threadId=tid, waitForStop=True) +                    x2 = self.get_local_as_int('x', threadId=tid) +                    (src2, line2) = self.get_source_and_line(threadId=tid) +                    self.assertTrue(x1 == x2 + 1, 'verify step in variable') +                    self.assertTrue(line2 < line1, 'verify step in line') +                    self.assertTrue(src1 == src2, 'verify step in source') + +                    # Now step out and verify +                    self.stepOut(threadId=tid, waitForStop=True) +                    x3 = self.get_local_as_int('x', threadId=tid) +                    (src3, line3) = self.get_source_and_line(threadId=tid) +                    self.assertTrue(x1 == x3, 'verify step out variable') +                    self.assertTrue(line3 >= line1, 'verify step out line') +                    self.assertTrue(src1 == src3, 'verify step in source') + +                    # Step over and verify +                    self.stepOver(threadId=tid, waitForStop=True) +                    x4 = self.get_local_as_int('x', threadId=tid) +                    (src4, line4) = self.get_source_and_line(threadId=tid) +                    self.assertTrue(x4 == x3, 'verify step over variable') +                    self.assertTrue(line4 > line3, 'verify step over line') +                    self.assertTrue(src1 == src4, 'verify step over source') +                    # only step one thread that is at the breakpoint and stop +                    break diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/step/main.cpp b/packages/Python/lldbsuite/test/tools/lldb-vscode/step/main.cpp new file mode 100644 index 000000000000..2fd063113875 --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/step/main.cpp @@ -0,0 +1,16 @@ +#include <thread> + +int function(int x) { +  if ((x % 2) == 0) +    return function(x-1) + x; // breakpoint 1 +  else +    return x; +} + +int main(int argc, char const *argv[]) { +  std::thread thread1(function, 2); +  std::thread thread2(function, 4); +  thread1.join(); +  thread2.join(); +  return 0; +} diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/variables/Makefile b/packages/Python/lldbsuite/test/tools/lldb-vscode/variables/Makefile new file mode 100644 index 000000000000..314f1cb2f077 --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/variables/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/variables/TestVSCode_variables.py b/packages/Python/lldbsuite/test/tools/lldb-vscode/variables/TestVSCode_variables.py new file mode 100644 index 000000000000..0a8906f1c6c8 --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/variables/TestVSCode_variables.py @@ -0,0 +1,225 @@ +""" +Test lldb-vscode setBreakpoints request +""" + +from __future__ import print_function + +import unittest2 +import vscode +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import lldbvscode_testcase +import os + + +def make_buffer_verify_dict(start_idx, count, offset=0): +    verify_dict = {} +    for i in range(start_idx, start_idx + count): +        verify_dict['[%i]' % (i)] = {'type': 'int', 'value': str(i+offset)} +    return verify_dict + + +class TestVSCode_variables(lldbvscode_testcase.VSCodeTestCaseBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def verify_values(self, verify_dict, actual, varref_dict=None): +        if 'equals' in verify_dict: +            verify = verify_dict['equals'] +            for key in verify: +                verify_value = verify[key] +                actual_value = actual[key] +                self.assertTrue(verify_value == actual_value, +                                '"%s" keys don\'t match (%s != %s)' % ( +                                    key, actual_value, verify_value)) +        if 'startswith' in verify_dict: +            verify = verify_dict['startswith'] +            for key in verify: +                verify_value = verify[key] +                actual_value = actual[key] +                startswith = actual_value.startswith(verify_value) +                self.assertTrue(startswith, +                                ('"%s" value "%s" doesn\'t start with' +                                 ' "%s")') % ( +                                    key, actual_value, +                                    verify_value)) +        hasVariablesReference = 'variablesReference' in actual +        varRef = None +        if hasVariablesReference: +            # Remember variable references in case we want to test further +            # by using the evaluate name. +            varRef = actual['variablesReference'] +            if varRef != 0 and varref_dict is not None: +                varref_dict[actual['evaluateName']] = varRef +        if ('hasVariablesReference' in verify_dict and +                verify_dict['hasVariablesReference']): +            self.assertTrue(hasVariablesReference, +                            "verify variable reference") +        if 'children' in verify_dict: +            self.assertTrue(hasVariablesReference and varRef is not None and +                            varRef != 0, +                            ("children verify values specified for " +                             "variable without children")) + +            response = self.vscode.request_variables(varRef) +            self.verify_variables(verify_dict['children'], +                                  response['body']['variables'], +                                  varref_dict) + +    def verify_variables(self, verify_dict, variables, varref_dict=None): +        for variable in variables: +            name = variable['name'] +            self.assertTrue(name in verify_dict, +                            'variable "%s" in verify dictionary' % (name)) +            self.verify_values(verify_dict[name], variable, varref_dict) + +    @skipIfWindows +    @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots +    @no_debug_info_test +    def test_scopes_variables_setVariable_evaluate(self): +        ''' +            Tests the "scopes", "variables", "setVariable", and "evaluate" +            packets. +        ''' +        program = self.getBuildArtifact("a.out") +        self.build_and_launch(program) +        source = 'main.cpp' +        breakpoint1_line = line_number(source, '// breakpoint 1') +        lines = [breakpoint1_line] +        # Set breakoint in the thread function so we can step the threads +        breakpoint_ids = self.set_source_breakpoints(source, lines) +        self.assertTrue(len(breakpoint_ids) == len(lines), +                        "expect correct number of breakpoints") +        self.continue_to_breakpoints(breakpoint_ids) +        locals = self.vscode.get_local_variables() +        globals = self.vscode.get_global_variables() +        buffer_children = make_buffer_verify_dict(0, 32) +        verify_locals = { +            'argc': { +                'equals': {'type': 'int', 'value': '1'} +            }, +            'argv': { +                'equals': {'type': 'const char **'}, +                'startswith': {'value': '0x'}, +                'hasVariablesReference': True +            }, +            'pt': { +                'equals': {'type': 'PointType'}, +                'hasVariablesReference': True, +                'children': { +                    'x': {'equals': {'type': 'int', 'value': '11'}}, +                    'y': {'equals': {'type': 'int', 'value': '22'}}, +                    'buffer': {'children': buffer_children} +                } +            } +        } +        verify_globals = { +            's_local': { +                'equals': {'type': 'float', 'value': '2.25'} +            }, +            '::g_global': { +                'equals': {'type': 'int', 'value': '123'} +            }, +            's_global': { +                'equals': {'type': 'int', 'value': '234'} +            }, +        } +        varref_dict = {} +        self.verify_variables(verify_locals, locals, varref_dict) +        self.verify_variables(verify_globals, globals, varref_dict) +        # pprint.PrettyPrinter(indent=4).pprint(varref_dict) +        # We need to test the functionality of the "variables" request as it +        # has optional parameters like "start" and "count" to limit the number +        # of variables that are fetched +        varRef = varref_dict['pt.buffer'] +        response = self.vscode.request_variables(varRef) +        self.verify_variables(buffer_children, response['body']['variables']) +        # Verify setting start=0 in the arguments still gets all children +        response = self.vscode.request_variables(varRef, start=0) +        self.verify_variables(buffer_children, response['body']['variables']) +        # Verify setting count=0 in the arguments still gets all children. +        # If count is zero, it means to get all children. +        response = self.vscode.request_variables(varRef, count=0) +        self.verify_variables(buffer_children, response['body']['variables']) +        # Verify setting count to a value that is too large in the arguments +        # still gets all children, and no more +        response = self.vscode.request_variables(varRef, count=1000) +        self.verify_variables(buffer_children, response['body']['variables']) +        # Verify setting the start index and count gets only the children we +        # want +        response = self.vscode.request_variables(varRef, start=5, count=5) +        self.verify_variables(make_buffer_verify_dict(5, 5), +                              response['body']['variables']) +        # Verify setting the start index to a value that is out of range +        # results in an empty list +        response = self.vscode.request_variables(varRef, start=32, count=1) +        self.assertTrue(len(response['body']['variables']) == 0, +                        'verify we get no variable back for invalid start') + +        # Test evaluate +        expressions = { +            'pt.x': { +                'equals': {'result': '11', 'type': 'int'}, +                'hasVariablesReference': False +            }, +            'pt.buffer[2]': { +                'equals': {'result': '2', 'type': 'int'}, +                'hasVariablesReference': False +            }, +            'pt': { +                'equals': {'type': 'PointType'}, +                'startswith': {'result': 'PointType @ 0x'}, +                'hasVariablesReference': True +            }, +            'pt.buffer': { +                'equals': {'type': 'int [32]'}, +                'startswith': {'result': 'int [32] @ 0x'}, +                'hasVariablesReference': True +            }, +            'argv': { +                'equals': {'type': 'const char **'}, +                'startswith': {'result': '0x'}, +                'hasVariablesReference': True +            }, +            'argv[0]': { +                'equals': {'type': 'const char *'}, +                'startswith': {'result': '0x'}, +                'hasVariablesReference': True +            }, +            '2+3': { +                'equals': {'result': '5', 'type': 'int'}, +                'hasVariablesReference': False +            }, +        } +        for expression in expressions: +            response = self.vscode.request_evaluate(expression) +            self.verify_values(expressions[expression], response['body']) + +        # Test setting variables +        self.set_local('argc', 123) +        argc = self.get_local_as_int('argc') +        self.assertTrue(argc == 123, +                        'verify argc was set to 123 (123 != %i)' % (argc)) + +        self.set_local('argv', 0x1234) +        argv = self.get_local_as_int('argv') +        self.assertTrue(argv == 0x1234, +                        'verify argv was set to 0x1234 (0x1234 != %#x)' % ( +                            argv)) + +        # Set a variable value whose name is synthetic, like a variable index +        # and verify the value by reading it +        self.vscode.request_setVariable(varRef, "[0]", 100) +        response = self.vscode.request_variables(varRef, start=0, count=1) +        self.verify_variables(make_buffer_verify_dict(0, 1, 100), +                              response['body']['variables']) + +        # Set a variable value whose name is a real child value, like "pt.x" +        # and verify the value by reading it +        varRef = varref_dict['pt'] +        self.vscode.request_setVariable(varRef, "x", 111) +        response = self.vscode.request_variables(varRef, start=0, count=1) +        value = response['body']['variables'][0]['value'] +        self.assertTrue(value == '111', +                        'verify pt.x got set to 111 (111 != %s)' % (value)) diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/variables/main.cpp b/packages/Python/lldbsuite/test/tools/lldb-vscode/variables/main.cpp new file mode 100644 index 000000000000..0223bd0a75ea --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/variables/main.cpp @@ -0,0 +1,18 @@ + +#define BUFFER_SIZE 32 +struct PointType { +  int x; +  int y; +  int buffer[BUFFER_SIZE]; +}; + +int g_global = 123; +static int s_global = 234; + +int main(int argc, char const *argv[]) { +  static float s_local = 2.25; +  PointType pt = { 11,22, {0}}; +  for (int i=0; i<BUFFER_SIZE; ++i) +    pt.buffer[i] = i; +  return s_global - g_global - pt.y; // breakpoint 1 +} diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py b/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py new file mode 100644 index 000000000000..066158d0877f --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py @@ -0,0 +1,1084 @@ +#!/usr/bin/env python + +import binascii +import json +import optparse +import os +import pprint +import socket +import string +import subprocess +import sys +import threading + + +def dump_memory(base_addr, data, num_per_line, outfile): + +    data_len = len(data) +    hex_string = binascii.hexlify(data) +    addr = base_addr +    ascii_str = '' +    i = 0 +    while i < data_len: +        outfile.write('0x%8.8x: ' % (addr + i)) +        bytes_left = data_len - i +        if bytes_left >= num_per_line: +            curr_data_len = num_per_line +        else: +            curr_data_len = bytes_left +        hex_start_idx = i * 2 +        hex_end_idx = hex_start_idx + curr_data_len * 2 +        curr_hex_str = hex_string[hex_start_idx:hex_end_idx] +        # 'curr_hex_str' now contains the hex byte string for the +        # current line with no spaces between bytes +        t = iter(curr_hex_str) +        # Print hex bytes separated by space +        outfile.write(' '.join(a + b for a, b in zip(t, t))) +        # Print two spaces +        outfile.write('  ') +        # Calculate ASCII string for bytes into 'ascii_str' +        ascii_str = '' +        for j in range(i, i + curr_data_len): +            ch = data[j] +            if ch in string.printable and ch not in string.whitespace: +                ascii_str += '%c' % (ch) +            else: +                ascii_str += '.' +        # Print ASCII representation and newline +        outfile.write(ascii_str) +        i = i + curr_data_len +        outfile.write('\n') + + +def read_packet(f, verbose=False, trace_file=None): +    '''Decode a JSON packet that starts with the content length and is +       followed by the JSON bytes from a file 'f' +    ''' +    line = f.readline() +    if len(line) == 0: +        return None + +    # Watch for line that starts with the prefix +    prefix = 'Content-Length: ' +    if line.startswith(prefix): +        # Decode length of JSON bytes +        if verbose: +            print('content: "%s"' % (line)) +        length = int(line[len(prefix):]) +        if verbose: +            print('length: "%u"' % (length)) +        # Skip empty line +        line = f.readline() +        if verbose: +            print('empty: "%s"' % (line)) +        # Read JSON bytes +        json_str = f.read(length) +        if verbose: +            print('json: "%s"' % (json_str)) +        if trace_file: +            trace_file.write('from adaptor:\n%s\n' % (json_str)) +        # Decode the JSON bytes into a python dictionary +        return json.loads(json_str) + +    return None + + +def packet_type_is(packet, packet_type): +    return 'type' in packet and packet['type'] == packet_type + + +def read_packet_thread(vs_comm): +    done = False +    while not done: +        packet = read_packet(vs_comm.recv, trace_file=vs_comm.trace_file) +        if packet: +            done = not vs_comm.handle_recv_packet(packet) +        else: +            done = True + + +class DebugCommunication(object): + +    def __init__(self, recv, send): +        self.trace_file = None +        self.send = send +        self.recv = recv +        self.recv_packets = [] +        self.recv_condition = threading.Condition() +        self.recv_thread = threading.Thread(target=read_packet_thread, +                                            args=(self,)) +        self.process_event_body = None +        self.exit_status = None +        self.initialize_body = None +        self.thread_stop_reasons = {} +        self.sequence = 1 +        self.threads = None +        self.recv_thread.start() +        self.output_condition = threading.Condition() +        self.output = {} +        self.configuration_done_sent = False +        self.frame_scopes = {} + +    @classmethod +    def encode_content(cls, s): +        return "Content-Length: %u\r\n\r\n%s" % (len(s), s) + +    @classmethod +    def validate_response(cls, command, response): +        if command['command'] != response['command']: +            raise ValueError('command mismatch in response') +        if command['seq'] != response['request_seq']: +            raise ValueError('seq mismatch in response') + +    def get_output(self, category, timeout=0.0, clear=True): +        self.output_condition.acquire() +        output = None +        if category in self.output: +            output = self.output[category] +            if clear: +                del self.output[category] +        elif timeout != 0.0: +            self.output_condition.wait(timeout) +            if category in self.output: +                output = self.output[category] +                if clear: +                    del self.output[category] +        self.output_condition.release() +        return output + +    def handle_recv_packet(self, packet): +        '''Called by the read thread that is waiting for all incoming packets +           to store the incoming packet in "self.recv_packets" in a thread safe +           way. This function will then signal the "self.recv_condition" to +           indicate a new packet is available. Returns True if the caller +           should keep calling this function for more packets. +        ''' +        # Check the packet to see if is an event packet +        keepGoing = True +        packet_type = packet['type'] +        if packet_type == 'event': +            event = packet['event'] +            body = None +            if 'body' in packet: +                body = packet['body'] +            # Handle the event packet and cache information from these packets +            # as they come in +            if event == 'output': +                # Store any output we receive so clients can retrieve it later. +                category = body['category'] +                output = body['output'] +                self.output_condition.acquire() +                if category in self.output: +                    self.output[category] += output +                else: +                    self.output[category] = output +                self.output_condition.notify() +                self.output_condition.release() +                # no need to add 'output' packets to our packets list +                return keepGoing +            elif event == 'process': +                # When a new process is attached or launched, remember the +                # details that are available in the body of the event +                self.process_event_body = body +            elif event == 'stopped': +                # Each thread that stops with a reason will send a +                # 'stopped' event. We need to remember the thread stop +                # reasons since the 'threads' command doesn't return +                # that information. +                self._process_stopped() +                tid = body['threadId'] +                self.thread_stop_reasons[tid] = body +        elif packet_type == 'response': +            if packet['command'] == 'disconnect': +                keepGoing = False +        self.recv_condition.acquire() +        self.recv_packets.append(packet) +        self.recv_condition.notify() +        self.recv_condition.release() +        return keepGoing + +    def send_packet(self, command_dict, set_sequence=True): +        '''Take the "command_dict" python dictionary and encode it as a JSON +           string and send the contents as a packet to the VSCode debug +           adaptor''' +        # Set the sequence ID for this command automatically +        if set_sequence: +            command_dict['seq'] = self.sequence +            self.sequence += 1 +        # Encode our command dictionary as a JSON string +        json_str = json.dumps(command_dict, separators=(',', ':')) +        if self.trace_file: +            self.trace_file.write('to adaptor:\n%s\n' % (json_str)) +        length = len(json_str) +        if length > 0: +            # Send the encoded JSON packet and flush the 'send' file +            self.send.write(self.encode_content(json_str)) +            self.send.flush() + +    def recv_packet(self, filter_type=None, filter_event=None, timeout=None): +        '''Get a JSON packet from the VSCode debug adaptor. This function +           assumes a thread that reads packets is running and will deliver +           any received packets by calling handle_recv_packet(...). This +           function will wait for the packet to arrive and return it when +           it does.''' +        while True: +            self.recv_condition.acquire() +            packet = None +            while True: +                for (i, curr_packet) in enumerate(self.recv_packets): +                    packet_type = curr_packet['type'] +                    if filter_type is None or packet_type in filter_type: +                        if (filter_event is None or +                            (packet_type == 'event' and +                             curr_packet['event'] in filter_event)): +                            packet = self.recv_packets.pop(i) +                            break +                if packet: +                    break +                # Sleep until packet is received +                len_before = len(self.recv_packets) +                self.recv_condition.wait(timeout) +                len_after = len(self.recv_packets) +                if len_before == len_after: +                    return None  # Timed out +            self.recv_condition.release() +            return packet + +        return None + +    def send_recv(self, command): +        '''Send a command python dictionary as JSON and receive the JSON +           response. Validates that the response is the correct sequence and +           command in the reply. Any events that are received are added to the +           events list in this object''' +        self.send_packet(command) +        done = False +        while not done: +            response = self.recv_packet(filter_type='response') +            if response is None: +                desc = 'no response for "%s"' % (command['command']) +                raise ValueError(desc) +            self.validate_response(command, response) +            return response +        return None + +    def wait_for_event(self, filter=None, timeout=None): +        while True: +            return self.recv_packet(filter_type='event', filter_event=filter, +                                    timeout=timeout) +        return None + +    def wait_for_stopped(self, timeout=None): +        stopped_events = [] +        stopped_event = self.wait_for_event(filter=['stopped', 'exited'], +                                            timeout=timeout) +        exited = False +        while stopped_event: +            stopped_events.append(stopped_event) +            # If we exited, then we are done +            if stopped_event['event'] == 'exited': +                self.exit_status = stopped_event['body']['exitCode'] +                exited = True +                break +            # Otherwise we stopped and there might be one or more 'stopped' +            # events for each thread that stopped with a reason, so keep +            # checking for more 'stopped' events and return all of them +            stopped_event = self.wait_for_event(filter='stopped', timeout=0.25) +        if exited: +            self.threads = [] +        return stopped_events + +    def wait_for_exited(self): +        event_dict = self.wait_for_event('exited') +        if event_dict is None: +            raise ValueError("didn't get stopped event") +        return event_dict + +    def get_initialize_value(self, key): +        '''Get a value for the given key if it there is a key/value pair in +           the "initialize" request response body. +        ''' +        if self.initialize_body and key in self.initialize_body: +            return self.initialize_body[key] +        return None + +    def get_threads(self): +        if self.threads is None: +            self.request_threads() +        return self.threads + +    def get_thread_id(self, threadIndex=0): +        '''Utility function to get the first thread ID in the thread list. +           If the thread list is empty, then fetch the threads. +        ''' +        if self.threads is None: +            self.request_threads() +        if self.threads and threadIndex < len(self.threads): +            return self.threads[threadIndex]['id'] +        return None + +    def get_stackFrame(self, frameIndex=0, threadId=None): +        '''Get a single "StackFrame" object from a "stackTrace" request and +           return the "StackFrame as a python dictionary, or None on failure +        ''' +        if threadId is None: +            threadId = self.get_thread_id() +        if threadId is None: +            print('invalid threadId') +            return None +        response = self.request_stackTrace(threadId, startFrame=frameIndex, +                                           levels=1) +        if response: +            return response['body']['stackFrames'][0] +        print('invalid response') +        return None + +    def get_scope_variables(self, scope_name, frameIndex=0, threadId=None): +        stackFrame = self.get_stackFrame(frameIndex=frameIndex, +                                         threadId=threadId) +        if stackFrame is None: +            return [] +        frameId = stackFrame['id'] +        if frameId in self.frame_scopes: +            frame_scopes = self.frame_scopes[frameId] +        else: +            scopes_response = self.request_scopes(frameId) +            frame_scopes = scopes_response['body']['scopes'] +            self.frame_scopes[frameId] = frame_scopes +        for scope in frame_scopes: +            if scope['name'] == scope_name: +                varRef = scope['variablesReference'] +                variables_response = self.request_variables(varRef) +                if variables_response: +                    if 'body' in variables_response: +                        body = variables_response['body'] +                        if 'variables' in body: +                            vars = body['variables'] +                            return vars +        return [] + +    def get_global_variables(self, frameIndex=0, threadId=None): +        return self.get_scope_variables('Globals', frameIndex=frameIndex, +                                        threadId=threadId) + +    def get_local_variables(self, frameIndex=0, threadId=None): +        return self.get_scope_variables('Locals', frameIndex=frameIndex, +                                        threadId=threadId) + +    def get_local_variable(self, name, frameIndex=0, threadId=None): +        locals = self.get_local_variables(frameIndex=frameIndex, +                                          threadId=threadId) +        for local in locals: +            if 'name' in local and local['name'] == name: +                return local +        return None + +    def get_local_variable_value(self, name, frameIndex=0, threadId=None): +        variable = self.get_local_variable(name, frameIndex=frameIndex, +                                           threadId=threadId) +        if variable and 'value' in variable: +            return variable['value'] +        return None + +    def replay_packets(self, replay_file_path): +        f = open(replay_file_path, 'r') +        mode = 'invalid' +        set_sequence = False +        command_dict = None +        while mode != 'eof': +            if mode == 'invalid': +                line = f.readline() +                if line.startswith('to adapter:'): +                    mode = 'send' +                elif line.startswith('from adapter:'): +                    mode = 'recv' +            elif mode == 'send': +                command_dict = read_packet(f) +                # Skip the end of line that follows the JSON +                f.readline() +                if command_dict is None: +                    raise ValueError('decode packet failed from replay file') +                print('Sending:') +                pprint.PrettyPrinter(indent=2).pprint(command_dict) +                # raw_input('Press ENTER to send:') +                self.send_packet(command_dict, set_sequence) +                mode = 'invalid' +            elif mode == 'recv': +                print('Replay response:') +                replay_response = read_packet(f) +                # Skip the end of line that follows the JSON +                f.readline() +                pprint.PrettyPrinter(indent=2).pprint(replay_response) +                actual_response = self.recv_packet() +                if actual_response: +                    type = actual_response['type'] +                    print('Actual response:') +                    if type == 'response': +                        self.validate_response(command_dict, actual_response) +                    pprint.PrettyPrinter(indent=2).pprint(actual_response) +                else: +                    print("error: didn't get a valid response") +                mode = 'invalid' + +    def request_attach(self, program=None, pid=None, waitFor=None, trace=None, +                       initCommands=None, preRunCommands=None, +                       stopCommands=None, exitCommands=None, +                       attachCommands=None): +        args_dict = {} +        if pid is not None: +            args_dict['pid'] = pid +        if program is not None: +            args_dict['program'] = program +        if waitFor is not None: +            args_dict['waitFor'] = waitFor +        if trace: +            args_dict['trace'] = trace +        if initCommands: +            args_dict['initCommands'] = initCommands +        if preRunCommands: +            args_dict['preRunCommands'] = preRunCommands +        if stopCommands: +            args_dict['stopCommands'] = stopCommands +        if exitCommands: +            args_dict['exitCommands'] = exitCommands +        if attachCommands: +            args_dict['attachCommands'] = attachCommands +        command_dict = { +            'command': 'attach', +            'type': 'request', +            'arguments': args_dict +        } +        return self.send_recv(command_dict) + +    def request_configurationDone(self): +        command_dict = { +            'command': 'configurationDone', +            'type': 'request', +            'arguments': {} +        } +        response = self.send_recv(command_dict) +        if response: +            self.configuration_done_sent = True +        return response + +    def _process_stopped(self): +        self.threads = None +        self.frame_scopes = {} + +    def request_continue(self, threadId=None): +        if self.exit_status is not None: +            raise ValueError('request_continue called after process exited') +        # If we have launched or attached, then the first continue is done by +        # sending the 'configurationDone' request +        if not self.configuration_done_sent: +            return self.request_configurationDone() +        args_dict = {} +        if threadId is None: +            threadId = self.get_thread_id() +        args_dict['threadId'] = threadId +        command_dict = { +            'command': 'continue', +            'type': 'request', +            'arguments': args_dict +        } +        response = self.send_recv(command_dict) +        recv_packets = [] +        self.recv_condition.acquire() +        for event in self.recv_packets: +            if event['event'] != 'stopped': +                recv_packets.append(event) +        self.recv_packets = recv_packets +        self.recv_condition.release() +        return response + +    def request_disconnect(self, terminateDebuggee=None): +        args_dict = {} +        if terminateDebuggee is not None: +            if terminateDebuggee: +                args_dict['terminateDebuggee'] = True +            else: +                args_dict['terminateDebuggee'] = False +        command_dict = { +            'command': 'disconnect', +            'type': 'request', +            'arguments': args_dict +        } +        return self.send_recv(command_dict) + +    def request_evaluate(self, expression, frameIndex=0, threadId=None): +        stackFrame = self.get_stackFrame(frameIndex=frameIndex, +                                         threadId=threadId) +        if stackFrame is None: +            return [] +        args_dict = { +            'expression': expression, +            'frameId': stackFrame['id'], +        } +        command_dict = { +            'command': 'evaluate', +            'type': 'request', +            'arguments': args_dict +        } +        return self.send_recv(command_dict) + +    def request_initialize(self): +        command_dict = { +            'command': 'initialize', +            'type': 'request', +            'arguments': { +                'adapterID': 'lldb-native', +                'clientID': 'vscode', +                'columnsStartAt1': True, +                'linesStartAt1': True, +                'locale': 'en-us', +                'pathFormat': 'path', +                'supportsRunInTerminalRequest': True, +                'supportsVariablePaging': True, +                'supportsVariableType': True +            } +        } +        response = self.send_recv(command_dict) +        if response: +            if 'body' in response: +                self.initialize_body = response['body'] +        return response + +    def request_launch(self, program, args=None, cwd=None, env=None, +                       stopOnEntry=False, disableASLR=True, +                       disableSTDIO=False, shellExpandArguments=False, +                       trace=False, initCommands=None, preRunCommands=None, +                       stopCommands=None, exitCommands=None, sourcePath=None, +                       debuggerRoot=None): +        args_dict = { +            'program': program +        } +        if args: +            args_dict['args'] = args +        if cwd: +            args_dict['cwd'] = cwd +        if env: +            args_dict['env'] = env +        if stopOnEntry: +            args_dict['stopOnEntry'] = stopOnEntry +        if disableASLR: +            args_dict['disableASLR'] = disableASLR +        if disableSTDIO: +            args_dict['disableSTDIO'] = disableSTDIO +        if shellExpandArguments: +            args_dict['shellExpandArguments'] = shellExpandArguments +        if trace: +            args_dict['trace'] = trace +        if initCommands: +            args_dict['initCommands'] = initCommands +        if preRunCommands: +            args_dict['preRunCommands'] = preRunCommands +        if stopCommands: +            args_dict['stopCommands'] = stopCommands +        if exitCommands: +            args_dict['exitCommands'] = exitCommands +        if sourcePath: +            args_dict['sourcePath'] = sourcePath +        if debuggerRoot: +            args_dict['debuggerRoot'] = debuggerRoot +        command_dict = { +            'command': 'launch', +            'type': 'request', +            'arguments': args_dict +        } +        response = self.send_recv(command_dict) + +        # Wait for a 'process' and 'initialized' event in any order +        self.wait_for_event(filter=['process', 'initialized']) +        self.wait_for_event(filter=['process', 'initialized']) +        return response + +    def request_next(self, threadId): +        if self.exit_status is not None: +            raise ValueError('request_continue called after process exited') +        args_dict = {'threadId': threadId} +        command_dict = { +            'command': 'next', +            'type': 'request', +            'arguments': args_dict +        } +        return self.send_recv(command_dict) + +    def request_stepIn(self, threadId): +        if self.exit_status is not None: +            raise ValueError('request_continue called after process exited') +        args_dict = {'threadId': threadId} +        command_dict = { +            'command': 'stepIn', +            'type': 'request', +            'arguments': args_dict +        } +        return self.send_recv(command_dict) + +    def request_stepOut(self, threadId): +        if self.exit_status is not None: +            raise ValueError('request_continue called after process exited') +        args_dict = {'threadId': threadId} +        command_dict = { +            'command': 'stepOut', +            'type': 'request', +            'arguments': args_dict +        } +        return self.send_recv(command_dict) + +    def request_pause(self, threadId=None): +        if self.exit_status is not None: +            raise ValueError('request_continue called after process exited') +        if threadId is None: +            threadId = self.get_thread_id() +        args_dict = {'threadId': threadId} +        command_dict = { +            'command': 'pause', +            'type': 'request', +            'arguments': args_dict +        } +        return self.send_recv(command_dict) + +    def request_scopes(self, frameId): +        args_dict = {'frameId': frameId} +        command_dict = { +            'command': 'scopes', +            'type': 'request', +            'arguments': args_dict +        } +        return self.send_recv(command_dict) + +    def request_setBreakpoints(self, file_path, line_array, condition=None, +                               hitCondition=None): +        (dir, base) = os.path.split(file_path) +        breakpoints = [] +        for line in line_array: +            bp = {'line': line} +            if condition is not None: +                bp['condition'] = condition +            if hitCondition is not None: +                bp['hitCondition'] = hitCondition +            breakpoints.append(bp) +        source_dict = { +            'name': base, +            'path': file_path +        } +        args_dict = { +            'source': source_dict, +            'breakpoints': breakpoints, +            'lines': '%s' % (line_array), +            'sourceModified': False, +        } +        command_dict = { +            'command': 'setBreakpoints', +            'type': 'request', +            'arguments': args_dict +        } +        return self.send_recv(command_dict) + +    def request_setExceptionBreakpoints(self, filters): +        args_dict = {'filters': filters} +        command_dict = { +            'command': 'setExceptionBreakpoints', +            'type': 'request', +            'arguments': args_dict +        } +        return self.send_recv(command_dict) + +    def request_setFunctionBreakpoints(self, names, condition=None, +                                       hitCondition=None): +        breakpoints = [] +        for name in names: +            bp = {'name': name} +            if condition is not None: +                bp['condition'] = condition +            if hitCondition is not None: +                bp['hitCondition'] = hitCondition +            breakpoints.append(bp) +        args_dict = {'breakpoints': breakpoints} +        command_dict = { +            'command': 'setFunctionBreakpoints', +            'type': 'request', +            'arguments': args_dict +        } +        return self.send_recv(command_dict) + +    def request_stackTrace(self, threadId=None, startFrame=None, levels=None, +                           dump=False): +        if threadId is None: +            threadId = self.get_thread_id() +        args_dict = {'threadId': threadId} +        if startFrame is not None: +            args_dict['startFrame'] = startFrame +        if levels is not None: +            args_dict['levels'] = levels +        command_dict = { +            'command': 'stackTrace', +            'type': 'request', +            'arguments': args_dict +        } +        response = self.send_recv(command_dict) +        if dump: +            for (idx, frame) in enumerate(response['body']['stackFrames']): +                name = frame['name'] +                if 'line' in frame and 'source' in frame: +                    source = frame['source'] +                    if 'sourceReference' not in source: +                        if 'name' in source: +                            source_name = source['name'] +                            line = frame['line'] +                            print("[%3u] %s @ %s:%u" % (idx, name, source_name, +                                                        line)) +                            continue +                print("[%3u] %s" % (idx, name)) +        return response + +    def request_threads(self): +        '''Request a list of all threads and combine any information from any +           "stopped" events since those contain more information about why a +           thread actually stopped. Returns an array of thread dictionaries +           with information about all threads''' +        command_dict = { +            'command': 'threads', +            'type': 'request', +            'arguments': {} +        } +        response = self.send_recv(command_dict) +        body = response['body'] +        # Fill in "self.threads" correctly so that clients that call +        # self.get_threads() or self.get_thread_id(...) can get information +        # on threads when the process is stopped. +        if 'threads' in body: +            self.threads = body['threads'] +            for thread in self.threads: +                # Copy the thread dictionary so we can add key/value pairs to +                # it without affecfting the original info from the "threads" +                # command. +                tid = thread['id'] +                if tid in self.thread_stop_reasons: +                    thread_stop_info = self.thread_stop_reasons[tid] +                    copy_keys = ['reason', 'description', 'text'] +                    for key in copy_keys: +                        if key in thread_stop_info: +                            thread[key] = thread_stop_info[key] +        else: +            self.threads = None +        return response + +    def request_variables(self, variablesReference, start=None, count=None): +        args_dict = {'variablesReference': variablesReference} +        if start is not None: +            args_dict['start'] = start +        if count is not None: +            args_dict['count'] = count +        command_dict = { +            'command': 'variables', +            'type': 'request', +            'arguments': args_dict +        } +        return self.send_recv(command_dict) + +    def request_setVariable(self, containingVarRef, name, value, id=None): +        args_dict = { +            'variablesReference': containingVarRef, +            'name': name, +            'value': str(value) +        } +        if id is not None: +            args_dict['id'] = id +        command_dict = { +            'command': 'setVariable', +            'type': 'request', +            'arguments': args_dict +        } +        return self.send_recv(command_dict) + +    def request_testGetTargetBreakpoints(self): +        '''A request packet used in the LLDB test suite to get all currently +           set breakpoint infos for all breakpoints currently set in the +           target. +        ''' +        command_dict = { +            'command': '_testGetTargetBreakpoints', +            'type': 'request', +            'arguments': {} +        } +        return self.send_recv(command_dict) + +    def terminate(self): +        self.send.close() +        # self.recv.close() + + +class DebugAdaptor(DebugCommunication): +    def __init__(self, executable=None, port=None): +        self.process = None +        if executable is not None: +            self.process = subprocess.Popen([executable], +                                            stdin=subprocess.PIPE, +                                            stdout=subprocess.PIPE, +                                            stderr=subprocess.PIPE) +            DebugCommunication.__init__(self, self.process.stdout, +                                        self.process.stdin) +        elif port is not None: +            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +            s.connect(('127.0.0.1', port)) +            DebugCommunication.__init__(self, s.makefile('r'), s.makefile('w')) + +    def get_pid(self): +        if self.process: +            return self.process.pid +        return -1 + +    def terminate(self): +        super(DebugAdaptor, self).terminate() +        if self.process is not None: +            self.process.terminate() +            self.process.wait() +            self.process = None + + +def attach_options_specified(options): +    if options.pid is not None: +        return True +    if options.waitFor: +        return True +    if options.attach: +        return True +    if options.attachCmds: +        return True +    return False + + +def run_vscode(dbg, args, options): +    dbg.request_initialize() +    if attach_options_specified(options): +        response = dbg.request_attach(program=options.program, +                                      pid=options.pid, +                                      waitFor=options.waitFor, +                                      attachCommands=options.attachCmds, +                                      initCommands=options.initCmds, +                                      preRunCommands=options.preRunCmds, +                                      stopCommands=options.stopCmds, +                                      exitCommands=options.exitCmds) +    else: +        response = dbg.request_launch(options.program, +                                      args=args, +                                      env=options.envs, +                                      cwd=options.workingDir, +                                      debuggerRoot=options.debuggerRoot, +                                      sourcePath=options.sourcePath, +                                      initCommands=options.initCmds, +                                      preRunCommands=options.preRunCmds, +                                      stopCommands=options.stopCmds, +                                      exitCommands=options.exitCmds) + +    if response['success']: +        if options.sourceBreakpoints: +            source_to_lines = {} +            for file_line in options.sourceBreakpoints: +                (path, line) = file_line.split(':') +                if len(path) == 0 or len(line) == 0: +                    print('error: invalid source with line "%s"' % +                          (file_line)) + +                else: +                    if path in source_to_lines: +                        source_to_lines[path].append(int(line)) +                    else: +                        source_to_lines[path] = [int(line)] +            for source in source_to_lines: +                dbg.request_setBreakpoints(source, source_to_lines[source]) +        if options.funcBreakpoints: +            dbg.request_setFunctionBreakpoints(options.funcBreakpoints) +        dbg.request_configurationDone() +        dbg.wait_for_stopped() +    else: +        if 'message' in response: +            print(response['message']) +    dbg.request_disconnect(terminateDebuggee=True) + + +def main(): +    parser = optparse.OptionParser( +        description=('A testing framework for the Visual Studio Code Debug ' +                     'Adaptor protocol')) + +    parser.add_option( +        '--vscode', +        type='string', +        dest='vscode_path', +        help=('The path to the command line program that implements the ' +              'Visual Studio Code Debug Adaptor protocol.'), +        default=None) + +    parser.add_option( +        '--program', +        type='string', +        dest='program', +        help='The path to the program to debug.', +        default=None) + +    parser.add_option( +        '--workingDir', +        type='string', +        dest='workingDir', +        default=None, +        help='Set the working directory for the process we launch.') + +    parser.add_option( +        '--sourcePath', +        type='string', +        dest='sourcePath', +        default=None, +        help=('Set the relative source root for any debug info that has ' +              'relative paths in it.')) + +    parser.add_option( +        '--debuggerRoot', +        type='string', +        dest='debuggerRoot', +        default=None, +        help=('Set the working directory for lldb-vscode for any object files ' +              'with relative paths in the Mach-o debug map.')) + +    parser.add_option( +        '-r', '--replay', +        type='string', +        dest='replay', +        help=('Specify a file containing a packet log to replay with the ' +              'current Visual Studio Code Debug Adaptor executable.'), +        default=None) + +    parser.add_option( +        '-g', '--debug', +        action='store_true', +        dest='debug', +        default=False, +        help='Pause waiting for a debugger to attach to the debug adaptor') + +    parser.add_option( +        '--port', +        type='int', +        dest='port', +        help="Attach a socket to a port instead of using STDIN for VSCode", +        default=None) + +    parser.add_option( +        '--pid', +        type='int', +        dest='pid', +        help="The process ID to attach to", +        default=None) + +    parser.add_option( +        '--attach', +        action='store_true', +        dest='attach', +        default=False, +        help=('Specify this option to attach to a process by name. The ' +              'process name is the basanme of the executable specified with ' +              'the --program option.')) + +    parser.add_option( +        '-f', '--function-bp', +        type='string', +        action='append', +        dest='funcBreakpoints', +        help=('Specify the name of a function to break at. ' +              'Can be specified more than once.'), +        default=[]) + +    parser.add_option( +        '-s', '--source-bp', +        type='string', +        action='append', +        dest='sourceBreakpoints', +        default=[], +        help=('Specify source breakpoints to set in the format of ' +              '<source>:<line>. ' +              'Can be specified more than once.')) + +    parser.add_option( +        '--attachCommand', +        type='string', +        action='append', +        dest='attachCmds', +        default=[], +        help=('Specify a LLDB command that will attach to a process. ' +              'Can be specified more than once.')) + +    parser.add_option( +        '--initCommand', +        type='string', +        action='append', +        dest='initCmds', +        default=[], +        help=('Specify a LLDB command that will be executed before the target ' +              'is created. Can be specified more than once.')) + +    parser.add_option( +        '--preRunCommand', +        type='string', +        action='append', +        dest='preRunCmds', +        default=[], +        help=('Specify a LLDB command that will be executed after the target ' +              'has been created. Can be specified more than once.')) + +    parser.add_option( +        '--stopCommand', +        type='string', +        action='append', +        dest='stopCmds', +        default=[], +        help=('Specify a LLDB command that will be executed each time the' +              'process stops. Can be specified more than once.')) + +    parser.add_option( +        '--exitCommand', +        type='string', +        action='append', +        dest='exitCmds', +        default=[], +        help=('Specify a LLDB command that will be executed when the process ' +              'exits. Can be specified more than once.')) + +    parser.add_option( +        '--env', +        type='string', +        action='append', +        dest='envs', +        default=[], +        help=('Specify environment variables to pass to the launched ' +              'process.')) + +    parser.add_option( +        '--waitFor', +        action='store_true', +        dest='waitFor', +        default=False, +        help=('Wait for the next process to be launched whose name matches ' +              'the basename of the program specified with the --program ' +              'option')) + +    (options, args) = parser.parse_args(sys.argv[1:]) + +    if options.vscode_path is None and options.port is None: +        print('error: must either specify a path to a Visual Studio Code ' +              'Debug Adaptor vscode executable path using the --vscode ' +              'option, or a port to attach to for an existing lldb-vscode ' +              'using the --port option') +        return +    dbg = DebugAdaptor(executable=options.vscode_path, port=options.port) +    if options.debug: +        raw_input('Waiting for debugger to attach pid "%i"' % ( +                  dbg.get_pid())) +    if options.replay: +        dbg.replay_packets(options.replay) +    else: +        run_vscode(dbg, args, options) +    dbg.terminate() + + +if __name__ == '__main__': +    main()  | 
