199451b44SJordan Rupprecht""" 299451b44SJordan RupprechtTest conditionally break on a function and inspect its variables. 399451b44SJordan Rupprecht""" 499451b44SJordan Rupprecht 599451b44SJordan Rupprechtfrom __future__ import print_function 699451b44SJordan Rupprecht 799451b44SJordan Rupprecht 899451b44SJordan Rupprechtimport lldb 999451b44SJordan Rupprechtfrom lldbsuite.test.decorators import * 1099451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import * 1199451b44SJordan Rupprechtfrom lldbsuite.test import lldbutil 1299451b44SJordan Rupprecht 1399451b44SJordan Rupprecht# rdar://problem/8532131 1499451b44SJordan Rupprecht# lldb not able to digest the clang-generated debug info correctly with respect to function name 1599451b44SJordan Rupprecht# 1699451b44SJordan Rupprecht# This class currently fails for clang as well as llvm-gcc. 1799451b44SJordan Rupprecht 1899451b44SJordan Rupprecht 1999451b44SJordan Rupprechtclass ConditionalBreakTestCase(TestBase): 2099451b44SJordan Rupprecht 2199451b44SJordan Rupprecht @add_test_categories(['pyapi']) 2299451b44SJordan Rupprecht def test_with_python(self): 2399451b44SJordan Rupprecht """Exercise some thread and frame APIs to break if c() is called by a().""" 2499451b44SJordan Rupprecht self.build() 2599451b44SJordan Rupprecht self.do_conditional_break() 2699451b44SJordan Rupprecht 2799451b44SJordan Rupprecht def test_with_command(self): 2899451b44SJordan Rupprecht """Simulate a user using lldb commands to break on c() if called from a().""" 2999451b44SJordan Rupprecht self.build() 3099451b44SJordan Rupprecht self.simulate_conditional_break_by_user() 3199451b44SJordan Rupprecht 3299451b44SJordan Rupprecht def do_conditional_break(self): 3399451b44SJordan Rupprecht """Exercise some thread and frame APIs to break if c() is called by a().""" 3499451b44SJordan Rupprecht exe = self.getBuildArtifact("a.out") 3599451b44SJordan Rupprecht 3699451b44SJordan Rupprecht target = self.dbg.CreateTarget(exe) 3799451b44SJordan Rupprecht self.assertTrue(target, VALID_TARGET) 3899451b44SJordan Rupprecht 3999451b44SJordan Rupprecht breakpoint = target.BreakpointCreateByName("c", exe) 4099451b44SJordan Rupprecht self.assertTrue(breakpoint, VALID_BREAKPOINT) 4199451b44SJordan Rupprecht 4299451b44SJordan Rupprecht # Now launch the process, and do not stop at entry point. 4399451b44SJordan Rupprecht process = target.LaunchSimple( 4499451b44SJordan Rupprecht None, None, self.get_process_working_directory()) 4599451b44SJordan Rupprecht 4699451b44SJordan Rupprecht self.assertTrue(process, PROCESS_IS_VALID) 4799451b44SJordan Rupprecht 4899451b44SJordan Rupprecht # The stop reason of the thread should be breakpoint. 49*47c4c6a7SDave Lee self.assertState(process.GetState(), lldb.eStateStopped, 5099451b44SJordan Rupprecht STOPPED_DUE_TO_BREAKPOINT) 5199451b44SJordan Rupprecht 5299451b44SJordan Rupprecht # Find the line number where a's parent frame function is c. 5399451b44SJordan Rupprecht line = line_number( 5499451b44SJordan Rupprecht 'main.c', 5599451b44SJordan Rupprecht "// Find the line number where c's parent frame is a here.") 5699451b44SJordan Rupprecht 5799451b44SJordan Rupprecht # Suppose we are only interested in the call scenario where c()'s 5899451b44SJordan Rupprecht # immediate caller is a() and we want to find out the value passed from 5999451b44SJordan Rupprecht # a(). 6099451b44SJordan Rupprecht # 6199451b44SJordan Rupprecht # The 10 in range(10) is just an arbitrary number, which means we would 6299451b44SJordan Rupprecht # like to try for at most 10 times. 6399451b44SJordan Rupprecht for j in range(10): 6499451b44SJordan Rupprecht if self.TraceOn(): 6599451b44SJordan Rupprecht print("j is: ", j) 6699451b44SJordan Rupprecht thread = lldbutil.get_one_thread_stopped_at_breakpoint( 6799451b44SJordan Rupprecht process, breakpoint) 6899451b44SJordan Rupprecht self.assertIsNotNone( 6999451b44SJordan Rupprecht thread, "Expected one thread to be stopped at the breakpoint") 7099451b44SJordan Rupprecht 7199451b44SJordan Rupprecht if thread.GetNumFrames() >= 2: 7299451b44SJordan Rupprecht frame0 = thread.GetFrameAtIndex(0) 7399451b44SJordan Rupprecht name0 = frame0.GetFunction().GetName() 7499451b44SJordan Rupprecht frame1 = thread.GetFrameAtIndex(1) 7599451b44SJordan Rupprecht name1 = frame1.GetFunction().GetName() 7699451b44SJordan Rupprecht # lldbutil.print_stacktrace(thread) 77619e2e09SDave Lee self.assertEqual(name0, "c", "Break on function c()") 7899451b44SJordan Rupprecht if (name1 == "a"): 7999451b44SJordan Rupprecht # By design, we know that a() calls c() only from main.c:27. 8099451b44SJordan Rupprecht # In reality, similar logic can be used to find out the call 8199451b44SJordan Rupprecht # site. 82619e2e09SDave Lee self.assertEqual(frame1.GetLineEntry().GetLine(), line, 8399451b44SJordan Rupprecht "Immediate caller a() at main.c:%d" % line) 8499451b44SJordan Rupprecht 8599451b44SJordan Rupprecht # And the local variable 'val' should have a value of (int) 8699451b44SJordan Rupprecht # 3. 8799451b44SJordan Rupprecht val = frame1.FindVariable("val") 8899451b44SJordan Rupprecht self.assertEqual("int", val.GetTypeName()) 8999451b44SJordan Rupprecht self.assertEqual("3", val.GetValue()) 9099451b44SJordan Rupprecht break 9199451b44SJordan Rupprecht 9299451b44SJordan Rupprecht process.Continue() 9399451b44SJordan Rupprecht 9499451b44SJordan Rupprecht def simulate_conditional_break_by_user(self): 9599451b44SJordan Rupprecht """Simulate a user using lldb commands to break on c() if called from a().""" 9699451b44SJordan Rupprecht 9799451b44SJordan Rupprecht # Sourcing .lldb in the current working directory, which sets the main 9899451b44SJordan Rupprecht # executable, sets the breakpoint on c(), and adds the callback for the 9999451b44SJordan Rupprecht # breakpoint such that lldb only stops when the caller of c() is a(). 10099451b44SJordan Rupprecht # the "my" package that defines the date() function. 10199451b44SJordan Rupprecht if self.TraceOn(): 10299451b44SJordan Rupprecht print("About to source .lldb") 10399451b44SJordan Rupprecht 10499451b44SJordan Rupprecht if not self.TraceOn(): 10599451b44SJordan Rupprecht self.HideStdout() 10699451b44SJordan Rupprecht 10799451b44SJordan Rupprecht # Separate out the "file " + self.getBuildArtifact("a.out") command from .lldb file, for the sake of 10899451b44SJordan Rupprecht # remote testsuite. 10999451b44SJordan Rupprecht self.runCmd("file " + self.getBuildArtifact("a.out")) 11099451b44SJordan Rupprecht self.runCmd("command source .lldb") 11199451b44SJordan Rupprecht 11299451b44SJordan Rupprecht self.runCmd("break list") 11399451b44SJordan Rupprecht 11499451b44SJordan Rupprecht if self.TraceOn(): 11599451b44SJordan Rupprecht print("About to run.") 11699451b44SJordan Rupprecht self.runCmd("run", RUN_SUCCEEDED) 11799451b44SJordan Rupprecht 11899451b44SJordan Rupprecht self.runCmd("break list") 11999451b44SJordan Rupprecht 12099451b44SJordan Rupprecht if self.TraceOn(): 12199451b44SJordan Rupprecht print("Done running") 12299451b44SJordan Rupprecht 12399451b44SJordan Rupprecht # The stop reason of the thread should be breakpoint. 12499451b44SJordan Rupprecht self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, 12599451b44SJordan Rupprecht substrs=['stopped', 'stop reason = breakpoint']) 12699451b44SJordan Rupprecht 12799451b44SJordan Rupprecht # The frame info for frame #0 points to a.out`c and its immediate caller 12899451b44SJordan Rupprecht # (frame #1) points to a.out`a. 12999451b44SJordan Rupprecht 13099451b44SJordan Rupprecht self.expect("frame info", "We should stop at c()", 13199451b44SJordan Rupprecht substrs=["a.out`c"]) 13299451b44SJordan Rupprecht 13399451b44SJordan Rupprecht # Select our parent frame as the current frame. 13499451b44SJordan Rupprecht self.runCmd("frame select 1") 13599451b44SJordan Rupprecht self.expect("frame info", "The immediate caller should be a()", 13699451b44SJordan Rupprecht substrs=["a.out`a"]) 137