2010-09-08 08:46:08 +08:00
|
|
|
"""
|
|
|
|
Test conditionally break on a function and inspect its variables.
|
|
|
|
"""
|
|
|
|
|
|
|
|
import os, time
|
|
|
|
import re
|
|
|
|
import unittest2
|
|
|
|
import lldb
|
|
|
|
from lldbtest import *
|
|
|
|
|
|
|
|
class ConditionalBreakTestCase(TestBase):
|
|
|
|
|
|
|
|
mydir = "conditional_break"
|
|
|
|
|
|
|
|
@unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
|
Added the capability to specify a one-liner Python script as the callback
command for a breakpoint, for example:
(lldb) breakpoint command add -p 1 "conditional_break.stop_if_called_from_a()"
The ScriptInterpreter interface has an extra method:
/// Set a one-liner as the callback for the breakpoint command.
virtual void
SetBreakpointCommandCallback (CommandInterpreter &interpreter,
BreakpointOptions *bp_options,
const char *oneliner);
to accomplish the above.
Also added a test case to demonstrate lldb's use of breakpoint callback command
to stop at function c() only when its immediate caller is function a(). The
following session shows the user entering the following commands:
1) command source .lldb (set up executable, breakpoint, and breakpoint command)
2) run (the callback mechanism will skip two breakpoints where c()'s immeidate caller is not a())
3) bt (to see that indeed c()'s immediate caller is a())
4) c (to continue and finish the program)
test/conditional_break $ ../../build/Debug/lldb
(lldb) command source .lldb
Executing commands in '.lldb'.
(lldb) file a.out
Current executable set to 'a.out' (x86_64).
(lldb) breakpoint set -n c
Breakpoint created: 1: name = 'c', locations = 1
(lldb) script import sys, os
(lldb) script sys.path.append(os.path.join(os.getcwd(), os.pardir))
(lldb) script import conditional_break
(lldb) breakpoint command add -p 1 "conditional_break.stop_if_called_from_a()"
(lldb) run
run
Launching '/Volumes/data/lldb/svn/trunk/test/conditional_break/a.out' (x86_64)
(lldb) Checking call frames...
Stack trace for thread id=0x2e03 name=None queue=com.apple.main-thread:
frame #0: a.out`c at main.c:39
frame #1: a.out`b at main.c:34
frame #2: a.out`a at main.c:25
frame #3: a.out`main at main.c:44
frame #4: a.out`start
c called from b
Continuing...
Checking call frames...
Stack trace for thread id=0x2e03 name=None queue=com.apple.main-thread:
frame #0: a.out`c at main.c:39
frame #1: a.out`b at main.c:34
frame #2: a.out`main at main.c:47
frame #3: a.out`start
c called from b
Continuing...
Checking call frames...
Stack trace for thread id=0x2e03 name=None queue=com.apple.main-thread:
frame #0: a.out`c at main.c:39
frame #1: a.out`a at main.c:27
frame #2: a.out`main at main.c:50
frame #3: a.out`start
c called from a
Stopped at c() with immediate caller as a().
a(1) returns 4
b(2) returns 5
Process 20420 Stopped
* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread
36
37 int c(int val)
38 {
39 -> return val + 3;
40 }
41
42 int main (int argc, char const *argv[])
(lldb) bt
bt
thread #1: tid = 0x2e03, stop reason = breakpoint 1.1, queue = com.apple.main-thread
frame #0: 0x0000000100000de8 a.out`c + 7 at main.c:39
frame #1: 0x0000000100000dbc a.out`a + 44 at main.c:27
frame #2: 0x0000000100000e4b a.out`main + 91 at main.c:50
frame #3: 0x0000000100000d88 a.out`start + 52
(lldb) c
c
Resuming process 20420
Process 20420 Exited
a(3) returns 6
(lldb)
llvm-svn: 113596
2010-09-11 02:21:10 +08:00
|
|
|
def test_with_dsym_python(self):
|
2010-09-08 08:46:08 +08:00
|
|
|
"""Exercise some thread and frame APIs to break if c() is called by a()."""
|
|
|
|
self.buildDsym()
|
|
|
|
self.do_conditional_break()
|
|
|
|
|
Added the capability to specify a one-liner Python script as the callback
command for a breakpoint, for example:
(lldb) breakpoint command add -p 1 "conditional_break.stop_if_called_from_a()"
The ScriptInterpreter interface has an extra method:
/// Set a one-liner as the callback for the breakpoint command.
virtual void
SetBreakpointCommandCallback (CommandInterpreter &interpreter,
BreakpointOptions *bp_options,
const char *oneliner);
to accomplish the above.
Also added a test case to demonstrate lldb's use of breakpoint callback command
to stop at function c() only when its immediate caller is function a(). The
following session shows the user entering the following commands:
1) command source .lldb (set up executable, breakpoint, and breakpoint command)
2) run (the callback mechanism will skip two breakpoints where c()'s immeidate caller is not a())
3) bt (to see that indeed c()'s immediate caller is a())
4) c (to continue and finish the program)
test/conditional_break $ ../../build/Debug/lldb
(lldb) command source .lldb
Executing commands in '.lldb'.
(lldb) file a.out
Current executable set to 'a.out' (x86_64).
(lldb) breakpoint set -n c
Breakpoint created: 1: name = 'c', locations = 1
(lldb) script import sys, os
(lldb) script sys.path.append(os.path.join(os.getcwd(), os.pardir))
(lldb) script import conditional_break
(lldb) breakpoint command add -p 1 "conditional_break.stop_if_called_from_a()"
(lldb) run
run
Launching '/Volumes/data/lldb/svn/trunk/test/conditional_break/a.out' (x86_64)
(lldb) Checking call frames...
Stack trace for thread id=0x2e03 name=None queue=com.apple.main-thread:
frame #0: a.out`c at main.c:39
frame #1: a.out`b at main.c:34
frame #2: a.out`a at main.c:25
frame #3: a.out`main at main.c:44
frame #4: a.out`start
c called from b
Continuing...
Checking call frames...
Stack trace for thread id=0x2e03 name=None queue=com.apple.main-thread:
frame #0: a.out`c at main.c:39
frame #1: a.out`b at main.c:34
frame #2: a.out`main at main.c:47
frame #3: a.out`start
c called from b
Continuing...
Checking call frames...
Stack trace for thread id=0x2e03 name=None queue=com.apple.main-thread:
frame #0: a.out`c at main.c:39
frame #1: a.out`a at main.c:27
frame #2: a.out`main at main.c:50
frame #3: a.out`start
c called from a
Stopped at c() with immediate caller as a().
a(1) returns 4
b(2) returns 5
Process 20420 Stopped
* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread
36
37 int c(int val)
38 {
39 -> return val + 3;
40 }
41
42 int main (int argc, char const *argv[])
(lldb) bt
bt
thread #1: tid = 0x2e03, stop reason = breakpoint 1.1, queue = com.apple.main-thread
frame #0: 0x0000000100000de8 a.out`c + 7 at main.c:39
frame #1: 0x0000000100000dbc a.out`a + 44 at main.c:27
frame #2: 0x0000000100000e4b a.out`main + 91 at main.c:50
frame #3: 0x0000000100000d88 a.out`start + 52
(lldb) c
c
Resuming process 20420
Process 20420 Exited
a(3) returns 6
(lldb)
llvm-svn: 113596
2010-09-11 02:21:10 +08:00
|
|
|
def test_with_dwarf_python(self):
|
2010-09-08 08:46:08 +08:00
|
|
|
"""Exercise some thread and frame APIs to break if c() is called by a()."""
|
|
|
|
self.buildDwarf()
|
|
|
|
self.do_conditional_break()
|
|
|
|
|
Added the capability to specify a one-liner Python script as the callback
command for a breakpoint, for example:
(lldb) breakpoint command add -p 1 "conditional_break.stop_if_called_from_a()"
The ScriptInterpreter interface has an extra method:
/// Set a one-liner as the callback for the breakpoint command.
virtual void
SetBreakpointCommandCallback (CommandInterpreter &interpreter,
BreakpointOptions *bp_options,
const char *oneliner);
to accomplish the above.
Also added a test case to demonstrate lldb's use of breakpoint callback command
to stop at function c() only when its immediate caller is function a(). The
following session shows the user entering the following commands:
1) command source .lldb (set up executable, breakpoint, and breakpoint command)
2) run (the callback mechanism will skip two breakpoints where c()'s immeidate caller is not a())
3) bt (to see that indeed c()'s immediate caller is a())
4) c (to continue and finish the program)
test/conditional_break $ ../../build/Debug/lldb
(lldb) command source .lldb
Executing commands in '.lldb'.
(lldb) file a.out
Current executable set to 'a.out' (x86_64).
(lldb) breakpoint set -n c
Breakpoint created: 1: name = 'c', locations = 1
(lldb) script import sys, os
(lldb) script sys.path.append(os.path.join(os.getcwd(), os.pardir))
(lldb) script import conditional_break
(lldb) breakpoint command add -p 1 "conditional_break.stop_if_called_from_a()"
(lldb) run
run
Launching '/Volumes/data/lldb/svn/trunk/test/conditional_break/a.out' (x86_64)
(lldb) Checking call frames...
Stack trace for thread id=0x2e03 name=None queue=com.apple.main-thread:
frame #0: a.out`c at main.c:39
frame #1: a.out`b at main.c:34
frame #2: a.out`a at main.c:25
frame #3: a.out`main at main.c:44
frame #4: a.out`start
c called from b
Continuing...
Checking call frames...
Stack trace for thread id=0x2e03 name=None queue=com.apple.main-thread:
frame #0: a.out`c at main.c:39
frame #1: a.out`b at main.c:34
frame #2: a.out`main at main.c:47
frame #3: a.out`start
c called from b
Continuing...
Checking call frames...
Stack trace for thread id=0x2e03 name=None queue=com.apple.main-thread:
frame #0: a.out`c at main.c:39
frame #1: a.out`a at main.c:27
frame #2: a.out`main at main.c:50
frame #3: a.out`start
c called from a
Stopped at c() with immediate caller as a().
a(1) returns 4
b(2) returns 5
Process 20420 Stopped
* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread
36
37 int c(int val)
38 {
39 -> return val + 3;
40 }
41
42 int main (int argc, char const *argv[])
(lldb) bt
bt
thread #1: tid = 0x2e03, stop reason = breakpoint 1.1, queue = com.apple.main-thread
frame #0: 0x0000000100000de8 a.out`c + 7 at main.c:39
frame #1: 0x0000000100000dbc a.out`a + 44 at main.c:27
frame #2: 0x0000000100000e4b a.out`main + 91 at main.c:50
frame #3: 0x0000000100000d88 a.out`start + 52
(lldb) c
c
Resuming process 20420
Process 20420 Exited
a(3) returns 6
(lldb)
llvm-svn: 113596
2010-09-11 02:21:10 +08:00
|
|
|
@unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
|
|
|
|
def test_with_dsym_command(self):
|
|
|
|
"""Simulate a user using lldb commands to break on c() if called from a()."""
|
|
|
|
self.buildDsym()
|
|
|
|
self.simulate_conditional_break_by_user()
|
|
|
|
|
|
|
|
def test_with_dwarf_command(self):
|
|
|
|
"""Simulate a user using lldb commands to break on c() if called from a()."""
|
|
|
|
self.buildDwarf()
|
|
|
|
self.simulate_conditional_break_by_user()
|
|
|
|
|
2010-09-08 08:46:08 +08:00
|
|
|
def do_conditional_break(self):
|
|
|
|
"""Exercise some thread and frame APIs to break if c() is called by a()."""
|
|
|
|
exe = os.path.join(os.getcwd(), "a.out")
|
|
|
|
self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
|
|
|
|
|
|
|
|
# Break on c().
|
|
|
|
self.expect("breakpoint set -n c", BREAKPOINT_CREATED,
|
|
|
|
startstr = "Breakpoint created: 1: name = 'c', locations = 1")
|
|
|
|
|
|
|
|
self.runCmd("run", RUN_SUCCEEDED)
|
|
|
|
|
|
|
|
# The stop reason of the thread should be breakpoint.
|
|
|
|
self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
|
|
|
|
substrs = ['state is Stopped', 'stop reason = breakpoint'])
|
|
|
|
|
|
|
|
# Suppose we are only interested in the call scenario where c()'s
|
|
|
|
# immediate caller is a() and we want to find out the value passed
|
|
|
|
# from a().
|
|
|
|
for j in range(3):
|
|
|
|
target = self.dbg.GetSelectedTarget()
|
|
|
|
process = target.GetProcess()
|
|
|
|
thread = process.GetThreadAtIndex(0)
|
2010-09-09 06:54:46 +08:00
|
|
|
import lldbutil
|
|
|
|
lldbutil.PrintStackTrace(thread)
|
2010-09-08 08:46:08 +08:00
|
|
|
|
|
|
|
if thread.GetNumFrames() >= 2:
|
|
|
|
frame0 = thread.GetFrameAtIndex(0)
|
|
|
|
name0 = frame0.GetFunction().GetName()
|
|
|
|
frame1 = thread.GetFrameAtIndex(1)
|
|
|
|
name1 = frame1.GetFunction().GetName()
|
|
|
|
self.assertTrue(name0 == "c", "Break on function c()")
|
|
|
|
if (name1 == "a"):
|
|
|
|
line = frame1.GetLineEntry().GetLine()
|
|
|
|
# By design, we know that a() calls c() only from main.c:27.
|
|
|
|
# In reality, similar logic can be used to find out the call
|
|
|
|
# site.
|
|
|
|
self.assertTrue(line == 27, "Immediate caller a() at main.c:27")
|
2010-09-08 08:55:12 +08:00
|
|
|
self.expect("thread backtrace", "Call site at a()",
|
|
|
|
substrs = ["main.c:27"])
|
|
|
|
self.expect("frame variable", "Passed in arg val of (int) 3",
|
|
|
|
startstr = "val = (int) 3")
|
2010-09-08 08:46:08 +08:00
|
|
|
break
|
|
|
|
|
|
|
|
# This doesn't work?
|
|
|
|
#process.Continue()
|
|
|
|
self.runCmd("process continue")
|
|
|
|
|
Added the capability to specify a one-liner Python script as the callback
command for a breakpoint, for example:
(lldb) breakpoint command add -p 1 "conditional_break.stop_if_called_from_a()"
The ScriptInterpreter interface has an extra method:
/// Set a one-liner as the callback for the breakpoint command.
virtual void
SetBreakpointCommandCallback (CommandInterpreter &interpreter,
BreakpointOptions *bp_options,
const char *oneliner);
to accomplish the above.
Also added a test case to demonstrate lldb's use of breakpoint callback command
to stop at function c() only when its immediate caller is function a(). The
following session shows the user entering the following commands:
1) command source .lldb (set up executable, breakpoint, and breakpoint command)
2) run (the callback mechanism will skip two breakpoints where c()'s immeidate caller is not a())
3) bt (to see that indeed c()'s immediate caller is a())
4) c (to continue and finish the program)
test/conditional_break $ ../../build/Debug/lldb
(lldb) command source .lldb
Executing commands in '.lldb'.
(lldb) file a.out
Current executable set to 'a.out' (x86_64).
(lldb) breakpoint set -n c
Breakpoint created: 1: name = 'c', locations = 1
(lldb) script import sys, os
(lldb) script sys.path.append(os.path.join(os.getcwd(), os.pardir))
(lldb) script import conditional_break
(lldb) breakpoint command add -p 1 "conditional_break.stop_if_called_from_a()"
(lldb) run
run
Launching '/Volumes/data/lldb/svn/trunk/test/conditional_break/a.out' (x86_64)
(lldb) Checking call frames...
Stack trace for thread id=0x2e03 name=None queue=com.apple.main-thread:
frame #0: a.out`c at main.c:39
frame #1: a.out`b at main.c:34
frame #2: a.out`a at main.c:25
frame #3: a.out`main at main.c:44
frame #4: a.out`start
c called from b
Continuing...
Checking call frames...
Stack trace for thread id=0x2e03 name=None queue=com.apple.main-thread:
frame #0: a.out`c at main.c:39
frame #1: a.out`b at main.c:34
frame #2: a.out`main at main.c:47
frame #3: a.out`start
c called from b
Continuing...
Checking call frames...
Stack trace for thread id=0x2e03 name=None queue=com.apple.main-thread:
frame #0: a.out`c at main.c:39
frame #1: a.out`a at main.c:27
frame #2: a.out`main at main.c:50
frame #3: a.out`start
c called from a
Stopped at c() with immediate caller as a().
a(1) returns 4
b(2) returns 5
Process 20420 Stopped
* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread
36
37 int c(int val)
38 {
39 -> return val + 3;
40 }
41
42 int main (int argc, char const *argv[])
(lldb) bt
bt
thread #1: tid = 0x2e03, stop reason = breakpoint 1.1, queue = com.apple.main-thread
frame #0: 0x0000000100000de8 a.out`c + 7 at main.c:39
frame #1: 0x0000000100000dbc a.out`a + 44 at main.c:27
frame #2: 0x0000000100000e4b a.out`main + 91 at main.c:50
frame #3: 0x0000000100000d88 a.out`start + 52
(lldb) c
c
Resuming process 20420
Process 20420 Exited
a(3) returns 6
(lldb)
llvm-svn: 113596
2010-09-11 02:21:10 +08:00
|
|
|
def simulate_conditional_break_by_user(self):
|
|
|
|
"""Simulate a user using lldb commands to break on c() if called from a()."""
|
|
|
|
|
|
|
|
# Sourcing .lldb in the current working directory, which sets the main
|
|
|
|
# executable, sets the breakpoint on c(), and adds the callback for the
|
|
|
|
# breakpoint such that lldb only stops when the caller of c() is a().
|
|
|
|
# the "my" package that defines the date() function.
|
|
|
|
self.runCmd("command source .lldb")
|
|
|
|
|
|
|
|
self.runCmd("run", RUN_SUCCEEDED)
|
|
|
|
|
|
|
|
# The stop reason of the thread should be breakpoint.
|
|
|
|
self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
|
|
|
|
substrs = ['state is Stopped', 'stop reason = breakpoint'])
|
|
|
|
|
|
|
|
# The frame info for frame #0 points to a.out`c and its immediate caller
|
|
|
|
# (frame #1) points to a.out`a.
|
|
|
|
|
|
|
|
self.expect("frame info", "We should stop at c()",
|
|
|
|
substrs = ["a.out`c"])
|
|
|
|
|
|
|
|
# Select our parent frame as the current frame.
|
|
|
|
self.runCmd("frame select 1")
|
|
|
|
self.expect("frame info", "The immediate caller should be a()",
|
|
|
|
substrs = ["a.out`a"])
|
|
|
|
|
|
|
|
|
2010-09-08 08:46:08 +08:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
import atexit
|
|
|
|
lldb.SBDebugger.Initialize()
|
|
|
|
atexit.register(lambda: lldb.SBDebugger.Terminate())
|
|
|
|
unittest2.main()
|