brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.1 KiB · 9852df8 Raw
139 lines · python
1"""2Test conditionally break on a function and inspect its variables.3"""4 5import lldb6from lldbsuite.test.decorators import *7from lldbsuite.test.lldbtest import *8from lldbsuite.test import lldbutil9 10# rdar://problem/853213111# lldb not able to digest the clang-generated debug info correctly with respect to function name12#13# This class currently fails for clang.14 15 16class ConditionalBreakTestCase(TestBase):17    @add_test_categories(["pyapi"])18    def test_with_python(self):19        """Exercise some thread and frame APIs to break if c() is called by a()."""20        self.build()21        self.do_conditional_break()22 23    def test_with_command(self):24        """Simulate a user using lldb commands to break on c() if called from a()."""25        self.build()26        self.simulate_conditional_break_by_user()27 28    def do_conditional_break(self):29        """Exercise some thread and frame APIs to break if c() is called by a()."""30        exe = self.getBuildArtifact("a.out")31 32        target = self.dbg.CreateTarget(exe)33        self.assertTrue(target, VALID_TARGET)34 35        breakpoint = target.BreakpointCreateByName("c", exe)36        self.assertTrue(breakpoint, VALID_BREAKPOINT)37 38        # Now launch the process, and do not stop at entry point.39        process = target.LaunchSimple(None, None, self.get_process_working_directory())40 41        self.assertTrue(process, PROCESS_IS_VALID)42 43        # The stop reason of the thread should be breakpoint.44        self.assertState(45            process.GetState(), lldb.eStateStopped, STOPPED_DUE_TO_BREAKPOINT46        )47 48        # Find the line number where a's parent frame function is c.49        line = line_number(50            "main.c", "// Find the line number where c's parent frame is a here."51        )52 53        # Suppose we are only interested in the call scenario where c()'s54        # immediate caller is a() and we want to find out the value passed from55        # a().56        #57        # The 10 in range(10) is just an arbitrary number, which means we would58        # like to try for at most 10 times.59        for j in range(10):60            if self.TraceOn():61                print("j is: ", j)62            thread = lldbutil.get_one_thread_stopped_at_breakpoint(process, breakpoint)63            self.assertIsNotNone(64                thread, "Expected one thread to be stopped at the breakpoint"65            )66 67            if thread.GetNumFrames() >= 2:68                frame0 = thread.GetFrameAtIndex(0)69                name0 = frame0.GetFunction().GetName()70                frame1 = thread.GetFrameAtIndex(1)71                name1 = frame1.GetFunction().GetName()72                # lldbutil.print_stacktrace(thread)73                self.assertEqual(name0, "c", "Break on function c()")74                if name1 == "a":75                    # By design, we know that a() calls c() only from main.c:27.76                    # In reality, similar logic can be used to find out the call77                    # site.78                    self.assertEqual(79                        frame1.GetLineEntry().GetLine(),80                        line,81                        "Immediate caller a() at main.c:%d" % line,82                    )83 84                    # And the local variable 'val' should have a value of (int)85                    # 3.86                    val = frame1.FindVariable("val")87                    self.assertEqual("int", val.GetTypeName())88                    self.assertEqual("3", val.GetValue())89                    break90 91            process.Continue()92 93    def simulate_conditional_break_by_user(self):94        """Simulate a user using lldb commands to break on c() if called from a()."""95 96        # Sourcing .lldb in the current working directory, which sets the main97        # executable, sets the breakpoint on c(), and adds the callback for the98        # breakpoint such that lldb only stops when the caller of c() is a().99        # the "my" package that defines the date() function.100        if self.TraceOn():101            print("About to source .lldb")102 103        if not self.TraceOn():104            self.HideStdout()105 106        # Separate out the "file " + self.getBuildArtifact("a.out") command from .lldb file, for the sake of107        # remote testsuite.108        self.runCmd("file " + self.getBuildArtifact("a.out"))109        self.runCmd("command source .lldb")110 111        self.runCmd("break list")112 113        if self.TraceOn():114            print("About to run.")115        self.runCmd("run", RUN_SUCCEEDED)116 117        self.runCmd("break list")118 119        if self.TraceOn():120            print("Done running")121 122        # The stop reason of the thread should be breakpoint.123        self.expect(124            "thread list",125            STOPPED_DUE_TO_BREAKPOINT,126            substrs=["stopped", "stop reason = breakpoint"],127        )128 129        # The frame info for frame #0 points to a.out`c and its immediate caller130        # (frame #1) points to a.out`a.131 132        self.expect("frame info", "We should stop at c()", substrs=["a.out`c"])133 134        # Select our parent frame as the current frame.135        self.runCmd("frame select 1")136        self.expect(137            "frame info", "The immediate caller should be a()", substrs=["a.out`a"]138        )139