[Lldb-commits] [lldb] r170008 - in /lldb/trunk: include/lldb/API/SBThread.h include/lldb/Target/Thread.h include/lldb/Target/ThreadPlanStepInRange.h include/lldb/Target/ThreadPlanStepOverRange.h scripts/Python/interface/SBThread.i source/API/SBThread.cpp source/Commands/CommandObjectThread.cpp source/Target/Thread.cpp source/Target/ThreadPlanStepInRange.cpp test/lang/c/stepping/TestStepAndBreakpoints.py test/lang/c/stepping/main.c
Jim Ingham
jingham at apple.com
Wed Dec 12 11:58:40 PST 2012
Author: jingham
Date: Wed Dec 12 13:58:40 2012
New Revision: 170008
URL: http://llvm.org/viewvc/llvm-project?rev=170008&view=rev
Log:
Fixed a few bugs in the "step in" thread plan logic.
Added a "step-in-target" flag to "thread step-in" so if you have something like:
Process 28464 stopped
* thread #1: tid = 0x1c03, function: main , stop reason = breakpoint 1.1
frame #0: 0x0000000100000e08 a.out`main at main.c:62
61
-> 62 int A6 = complex (a(4), b(5), c(6)); // Stop here to step targetting b and hitting breakpoint.
63
and you want to get into "complex" skipping a, b and c, you can do:
(lldb) step -t complex
Process 28464 stopped
* thread #1: tid = 0x1c03, function: complex , stop reason = step in
frame #0: 0x0000000100000d0d a.out`complex at main.c:44
41
42 int complex (int first, int second, int third)
43 {
-> 44 return first + second + third; // Step in targetting complex should stop here
45 }
46
47 int main (int argc, char const *argv[])
Modified:
lldb/trunk/include/lldb/API/SBThread.h
lldb/trunk/include/lldb/Target/Thread.h
lldb/trunk/include/lldb/Target/ThreadPlanStepInRange.h
lldb/trunk/include/lldb/Target/ThreadPlanStepOverRange.h
lldb/trunk/scripts/Python/interface/SBThread.i
lldb/trunk/source/API/SBThread.cpp
lldb/trunk/source/Commands/CommandObjectThread.cpp
lldb/trunk/source/Target/Thread.cpp
lldb/trunk/source/Target/ThreadPlanStepInRange.cpp
lldb/trunk/test/lang/c/stepping/TestStepAndBreakpoints.py
lldb/trunk/test/lang/c/stepping/main.c
Modified: lldb/trunk/include/lldb/API/SBThread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBThread.h?rev=170008&r1=170007&r2=170008&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBThread.h (original)
+++ lldb/trunk/include/lldb/API/SBThread.h Wed Dec 12 13:58:40 2012
@@ -99,6 +99,9 @@
StepInto (lldb::RunMode stop_other_threads = lldb::eOnlyDuringStepping);
void
+ StepInto (const char *target_name, lldb::RunMode stop_other_threads = lldb::eOnlyDuringStepping);
+
+ void
StepOut ();
void
Modified: lldb/trunk/include/lldb/Target/Thread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Thread.h?rev=170008&r1=170007&r2=170008&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Thread.h (original)
+++ lldb/trunk/include/lldb/Target/Thread.h Wed Dec 12 13:58:40 2012
@@ -480,8 +480,8 @@
bool stop_other_threads);
//------------------------------------------------------------------
- /// Queues the plan used to step through an address range, stepping into or over
- /// function calls depending on the value of StepType.
+ /// Queues the plan used to step through an address range, stepping over
+ /// function calls.
///
/// @param[in] abort_other_plans
/// \b true if we discard the currently queued plans and replace them with this one.
@@ -507,10 +507,48 @@
/// A pointer to the newly queued thread plan, or NULL if the plan could not be queued.
//------------------------------------------------------------------
virtual ThreadPlan *
- QueueThreadPlanForStepRange (bool abort_other_plans,
- StepType type,
+ QueueThreadPlanForStepOverRange (bool abort_other_plans,
const AddressRange &range,
const SymbolContext &addr_context,
+ lldb::RunMode stop_other_threads);
+
+ //------------------------------------------------------------------
+ /// Queues the plan used to step through an address range, stepping into functions.
+ ///
+ /// @param[in] abort_other_plans
+ /// \b true if we discard the currently queued plans and replace them with this one.
+ /// Otherwise this plan will go on the end of the plan stack.
+ ///
+ /// @param[in] type
+ /// Type of step to do, only eStepTypeInto and eStepTypeOver are supported by this plan.
+ ///
+ /// @param[in] range
+ /// The address range to step through.
+ ///
+ /// @param[in] addr_context
+ /// When dealing with stepping through inlined functions the current PC is not enough information to know
+ /// what "step" means. For instance a series of nested inline functions might start at the same address.
+ // The \a addr_context provides the current symbol context the step
+ /// is supposed to be out of.
+ // FIXME: Currently unused.
+ ///
+ /// @param[in] step_in_target
+ /// Name if function we are trying to step into. We will step out if we don't land in that function.
+ ///
+ /// @param[in] stop_other_threads
+ /// \b true if we will stop other threads while we single step this one.
+ ///
+ /// @param[in] avoid_code_without_debug_info
+ /// If \b true we will step out if we step into code with no debug info.
+ ///
+ /// @return
+ /// A pointer to the newly queued thread plan, or NULL if the plan could not be queued.
+ //------------------------------------------------------------------
+ virtual ThreadPlan *
+ QueueThreadPlanForStepInRange (bool abort_other_plans,
+ const AddressRange &range,
+ const SymbolContext &addr_context,
+ const char *step_in_target,
lldb::RunMode stop_other_threads,
bool avoid_code_without_debug_info);
Modified: lldb/trunk/include/lldb/Target/ThreadPlanStepInRange.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanStepInRange.h?rev=170008&r1=170007&r2=170008&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ThreadPlanStepInRange.h (original)
+++ lldb/trunk/include/lldb/Target/ThreadPlanStepInRange.h Wed Dec 12 13:58:40 2012
@@ -32,6 +32,12 @@
const SymbolContext &addr_context,
lldb::RunMode stop_others);
+ ThreadPlanStepInRange (Thread &thread,
+ const AddressRange &range,
+ const SymbolContext &addr_context,
+ const char *step_into_function_name,
+ lldb::RunMode stop_others);
+
virtual
~ThreadPlanStepInRange ();
@@ -43,6 +49,11 @@
void SetAvoidRegexp(const char *name);
+ void SetStepInTarget (const char *target)
+ {
+ m_step_into_target.SetCString(target);
+ }
+
static ThreadPlan *
DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, void *baton);
@@ -65,10 +76,15 @@
private:
friend ThreadPlan *
- Thread::QueueThreadPlanForStepRange (bool abort_other_plans,
- StepType type,
+ Thread::QueueThreadPlanForStepOverRange (bool abort_other_plans,
const AddressRange &range,
const SymbolContext &addr_context,
+ lldb::RunMode stop_others);
+ friend ThreadPlan *
+ Thread::QueueThreadPlanForStepInRange (bool abort_other_plans,
+ const AddressRange &range,
+ const SymbolContext &addr_context,
+ const char *step_in_target,
lldb::RunMode stop_others,
bool avoid_code_without_debug_info);
@@ -81,7 +97,7 @@
bool m_step_past_prologue; // FIXME: For now hard-coded to true, we could put a switch in for this if there's
// demand for that.
bool m_virtual_step; // true if we've just done a "virtual step", i.e. just moved the inline stack depth.
-
+ ConstString m_step_into_target;
DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepInRange);
};
Modified: lldb/trunk/include/lldb/Target/ThreadPlanStepOverRange.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanStepOverRange.h?rev=170008&r1=170007&r2=170008&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ThreadPlanStepOverRange.h (original)
+++ lldb/trunk/include/lldb/Target/ThreadPlanStepOverRange.h Wed Dec 12 13:58:40 2012
@@ -41,13 +41,6 @@
private:
- friend ThreadPlan *
- Thread::QueueThreadPlanForStepRange (bool abort_other_plans,
- StepType type,
- const AddressRange &range,
- const SymbolContext &addr_context,
- lldb::RunMode stop_others,
- bool avoid_code_without_debug_info);
bool m_first_resume;
DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepOverRange);
Modified: lldb/trunk/scripts/Python/interface/SBThread.i
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/interface/SBThread.i?rev=170008&r1=170007&r2=170008&view=diff
==============================================================================
--- lldb/trunk/scripts/Python/interface/SBThread.i (original)
+++ lldb/trunk/scripts/Python/interface/SBThread.i Wed Dec 12 13:58:40 2012
@@ -124,6 +124,9 @@
StepInto (lldb::RunMode stop_other_threads = lldb::eOnlyDuringStepping);
void
+ StepInto (const char *target_name, lldb::RunMode stop_other_threads = lldb::eOnlyDuringStepping);
+
+ void
StepOut ();
void
Modified: lldb/trunk/source/API/SBThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBThread.cpp?rev=170008&r1=170007&r2=170008&view=diff
==============================================================================
--- lldb/trunk/source/API/SBThread.cpp (original)
+++ lldb/trunk/source/API/SBThread.cpp Wed Dec 12 13:58:40 2012
@@ -564,13 +564,10 @@
if (frame_sp->HasDebugInformation ())
{
SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
- new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans,
- eStepTypeOver,
- sc.line_entry.range,
- sc,
- stop_other_threads,
- false);
-
+ new_plan = thread->QueueThreadPlanForStepOverRange (abort_other_plans,
+ sc.line_entry.range,
+ sc,
+ stop_other_threads);
}
else
{
@@ -588,14 +585,23 @@
void
SBThread::StepInto (lldb::RunMode stop_other_threads)
{
+ StepInto (NULL, stop_other_threads);
+}
+
+void
+SBThread::StepInto (const char *target_name, lldb::RunMode stop_other_threads)
+{
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
Mutex::Locker api_locker;
ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
if (log)
- log->Printf ("SBThread(%p)::StepInto (stop_other_threads='%s')", exe_ctx.GetThreadPtr(),
+ log->Printf ("SBThread(%p)::StepInto (target_name='%s', stop_other_threads='%s')",
+ exe_ctx.GetThreadPtr(),
+ target_name? target_name: "<NULL>",
Thread::RunModeAsCString (stop_other_threads));
+
if (exe_ctx.HasThreadScope())
{
bool abort_other_plans = false;
@@ -608,12 +614,12 @@
{
bool avoid_code_without_debug_info = true;
SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
- new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans,
- eStepTypeInto,
- sc.line_entry.range,
- sc,
- stop_other_threads,
- avoid_code_without_debug_info);
+ new_plan = thread->QueueThreadPlanForStepInRange (abort_other_plans,
+ sc.line_entry.range,
+ sc,
+ target_name,
+ stop_other_threads,
+ avoid_code_without_debug_info);
}
else
{
Modified: lldb/trunk/source/Commands/CommandObjectThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectThread.cpp?rev=170008&r1=170007&r2=170008&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectThread.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectThread.cpp Wed Dec 12 13:58:40 2012
@@ -325,6 +325,13 @@
}
break;
+ case 't':
+ {
+ m_step_in_target.clear();
+ m_step_in_target.assign(option_arg);
+
+ }
+ break;
default:
error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
break;
@@ -339,6 +346,7 @@
m_avoid_no_debug = true;
m_run_mode = eOnlyDuringStepping;
m_avoid_regexp.clear();
+ m_step_in_target.clear();
}
const OptionDefinition*
@@ -355,6 +363,7 @@
bool m_avoid_no_debug;
RunMode m_run_mode;
std::string m_avoid_regexp;
+ std::string m_step_in_target;
};
CommandObjectThreadStepWithTypeAndScope (CommandInterpreter &interpreter,
@@ -469,9 +478,10 @@
if (frame->HasDebugInformation ())
{
- new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans, m_step_type,
+ new_plan = thread->QueueThreadPlanForStepInRange (abort_other_plans,
frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
- frame->GetSymbolContext(eSymbolContextEverything),
+ frame->GetSymbolContext(eSymbolContextEverything),
+ m_options.m_step_in_target.c_str(),
stop_other_threads,
m_options.m_avoid_no_debug);
if (new_plan && !m_options.m_avoid_regexp.empty())
@@ -489,12 +499,10 @@
StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
if (frame->HasDebugInformation())
- new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans,
- m_step_type,
- frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
- frame->GetSymbolContext(eSymbolContextEverything),
- stop_other_threads,
- false);
+ new_plan = thread->QueueThreadPlanForStepOverRange (abort_other_plans,
+ frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
+ frame->GetSymbolContext(eSymbolContextEverything),
+ stop_other_threads);
else
new_plan = thread->QueueThreadPlanForStepSingleInstruction (true,
abort_other_plans,
@@ -595,7 +603,8 @@
{
{ LLDB_OPT_SET_1, false, "avoid-no-debug", 'a', required_argument, NULL, 0, eArgTypeBoolean, "A boolean value that sets whether step-in will step over functions with no debug information."},
{ LLDB_OPT_SET_1, false, "run-mode", 'm', required_argument, g_tri_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread."},
-{ LLDB_OPT_SET_1, false, "step-over-regexp",'r', required_argument, NULL, 0, eArgTypeRegularExpression, "A regular expression that defines function names to step over."},
+{ LLDB_OPT_SET_1, false, "step-over-regexp",'r', required_argument, NULL, 0, eArgTypeRegularExpression, "A regular expression that defines function names to not to stop at when stepping in."},
+{ LLDB_OPT_SET_1, false, "step-in-target", 't', required_argument, NULL, 0, eArgTypeFunctionName, "The name of the directly called function step in should stop at when stepping into."},
{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
};
Modified: lldb/trunk/source/Target/Thread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Thread.cpp?rev=170008&r1=170007&r2=170008&view=diff
==============================================================================
--- lldb/trunk/source/Target/Thread.cpp (original)
+++ lldb/trunk/source/Target/Thread.cpp Wed Dec 12 13:58:40 2012
@@ -1188,28 +1188,41 @@
}
ThreadPlan *
-Thread::QueueThreadPlanForStepRange
+Thread::QueueThreadPlanForStepOverRange
(
bool abort_other_plans,
- StepType type,
const AddressRange &range,
- const SymbolContext &addr_context,
+ const SymbolContext &addr_context,
+ lldb::RunMode stop_other_threads
+)
+{
+ ThreadPlanSP thread_plan_sp;
+ thread_plan_sp.reset (new ThreadPlanStepOverRange (*this, range, addr_context, stop_other_threads));
+
+ QueueThreadPlan (thread_plan_sp, abort_other_plans);
+ return thread_plan_sp.get();
+}
+
+ThreadPlan *
+Thread::QueueThreadPlanForStepInRange
+(
+ bool abort_other_plans,
+ const AddressRange &range,
+ const SymbolContext &addr_context,
+ const char *step_in_target,
lldb::RunMode stop_other_threads,
bool avoid_code_without_debug_info
)
{
ThreadPlanSP thread_plan_sp;
- if (type == eStepTypeInto)
- {
- ThreadPlanStepInRange *plan = new ThreadPlanStepInRange (*this, range, addr_context, stop_other_threads);
- if (avoid_code_without_debug_info)
- plan->GetFlags().Set (ThreadPlanShouldStopHere::eAvoidNoDebug);
- else
- plan->GetFlags().Clear (ThreadPlanShouldStopHere::eAvoidNoDebug);
- thread_plan_sp.reset (plan);
- }
+ ThreadPlanStepInRange *plan = new ThreadPlanStepInRange (*this, range, addr_context, stop_other_threads);
+ if (avoid_code_without_debug_info)
+ plan->GetFlags().Set (ThreadPlanShouldStopHere::eAvoidNoDebug);
else
- thread_plan_sp.reset (new ThreadPlanStepOverRange (*this, range, addr_context, stop_other_threads));
+ plan->GetFlags().Clear (ThreadPlanShouldStopHere::eAvoidNoDebug);
+ if (step_in_target)
+ plan->SetStepInTarget(step_in_target);
+ thread_plan_sp.reset (plan);
QueueThreadPlan (thread_plan_sp, abort_other_plans);
return thread_plan_sp.get();
Modified: lldb/trunk/source/Target/ThreadPlanStepInRange.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanStepInRange.cpp?rev=170008&r1=170007&r2=170008&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanStepInRange.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanStepInRange.cpp Wed Dec 12 13:58:40 2012
@@ -52,6 +52,23 @@
SetFlagsToDefault ();
}
+ThreadPlanStepInRange::ThreadPlanStepInRange
+(
+ Thread &thread,
+ const AddressRange &range,
+ const SymbolContext &addr_context,
+ const char *step_into_target,
+ lldb::RunMode stop_others
+) :
+ ThreadPlanStepRange (ThreadPlan::eKindStepInRange, "Step Range stepping in", thread, range, addr_context, stop_others),
+ ThreadPlanShouldStopHere (this, ThreadPlanStepInRange::DefaultShouldStopHereCallback, NULL),
+ m_step_past_prologue (true),
+ m_virtual_step (false),
+ m_step_into_target (step_into_target)
+{
+ SetFlagsToDefault ();
+}
+
ThreadPlanStepInRange::~ThreadPlanStepInRange ()
{
}
@@ -65,6 +82,7 @@
{
s->Printf ("Stepping through range (stepping into functions): ");
DumpRanges(s);
+ s->Printf ("targeting %s.", m_step_into_target.AsCString());
}
}
@@ -140,6 +158,7 @@
}
SetPlanComplete();
+ m_no_more_plans = true;
return true;
}
@@ -279,15 +298,40 @@
}
}
- if (!should_step_out)
+ if (current_plan->GetKind() == eKindStepInRange)
{
- if (current_plan->GetKind() == eKindStepInRange)
+ ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan);
+ if (step_in_range_plan->m_step_into_target)
+ {
+ SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol);
+ if (sc.symbol != NULL)
+ {
+ // First try an exact match, since that's cheap with ConstStrings. Then do a strstr compare.
+ if (step_in_range_plan->m_step_into_target == sc.GetFunctionName())
+ {
+ should_step_out = false;
+ }
+ else
+ {
+ const char *target_name = step_in_range_plan->m_step_into_target.AsCString();
+ const char *function_name = sc.GetFunctionName().AsCString();
+
+ if (function_name == NULL)
+ should_step_out = true;
+ else if (strstr (function_name, target_name) == NULL)
+ should_step_out = true;
+ }
+ }
+ }
+
+ if (!should_step_out)
{
- ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan);
- should_step_out = step_in_range_plan->FrameMatchesAvoidRegexp ();
+ ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan);
+ should_step_out = step_in_range_plan->FrameMatchesAvoidRegexp ();
}
}
+
if (should_step_out)
{
// FIXME: Make sure the ThreadPlanForStepOut does the right thing with inlined functions.
@@ -313,8 +357,12 @@
// case we'll do our ordinary processing, or we stopped for some
// reason that isn't handled by our sub-plans, in which case we want to just stop right
// away.
- // We also set ourselves complete when we stop for this sort of unintended reason, but mark
- // success as false so we don't end up being the reason for the stop.
+ // In general, we don't want to mark the plan as complete for unexplained stops.
+ // For instance, if you step in to some code with no debug info, so you step out
+ // and in the course of that hit a breakpoint, then you want to stop & show the user
+ // the breakpoint, but not unship the step in plan, since you still may want to complete that
+ // plan when you continue. This is particularly true when doing "step in to target function."
+ // stepping.
//
// The only variation is that if we are doing "step by running to next branch" in which case
// if we hit our branch breakpoint we don't set the plan to complete.
@@ -340,8 +388,8 @@
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
if (log)
log->PutCString ("ThreadPlanStepInRange got asked if it explains the stop for some reason other than step.");
- SetPlanComplete(false);
}
+ return false;
break;
default:
break;
Modified: lldb/trunk/test/lang/c/stepping/TestStepAndBreakpoints.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/c/stepping/TestStepAndBreakpoints.py?rev=170008&r1=170007&r2=170008&view=diff
==============================================================================
--- lldb/trunk/test/lang/c/stepping/TestStepAndBreakpoints.py (original)
+++ lldb/trunk/test/lang/c/stepping/TestStepAndBreakpoints.py Wed Dec 12 13:58:40 2012
@@ -161,6 +161,71 @@
self.assertTrue (thread.GetFrameAtIndex(0).GetLineEntry().GetLine() == current_line)
self.assertTrue (thread.GetFrameAtIndex(0).GetLineEntry().GetFileSpec() == current_file)
+ # Now we are going to test step in targetting a function:
+
+ break_in_b.SetEnabled (False)
+
+ break_before_complex_1 = target.BreakpointCreateBySourceRegex ('// Stop here to try step in targetting b.', self.main_source_spec)
+ self.assertTrue(break_before_complex_1, VALID_BREAKPOINT)
+
+ break_before_complex_2 = target.BreakpointCreateBySourceRegex ('// Stop here to try step in targetting complex.', self.main_source_spec)
+ self.assertTrue(break_before_complex_2, VALID_BREAKPOINT)
+
+ break_before_complex_3 = target.BreakpointCreateBySourceRegex ('// Stop here to step targetting b and hitting breakpoint.', self.main_source_spec)
+ self.assertTrue(break_before_complex_3, VALID_BREAKPOINT)
+
+ break_before_complex_4 = target.BreakpointCreateBySourceRegex ('// Stop here to make sure bogus target steps over.', self.main_source_spec)
+ self.assertTrue(break_before_complex_4, VALID_BREAKPOINT)
+
+ threads = lldbutil.continue_to_breakpoint(process, break_before_complex_1)
+ self.assertTrue (len(threads) == 1)
+ thread = threads[0]
+ break_before_complex_1.SetEnabled(False)
+
+ thread.StepInto ("b")
+ self.assertTrue (thread.GetFrameAtIndex(0).GetFunctionName() == "b")
+
+ # Now continue out and stop at the next call to complex. This time step all the way into complex:
+ threads = lldbutil.continue_to_breakpoint (process, break_before_complex_2)
+ self.assertTrue (len(threads) == 1)
+ thread = threads[0]
+ break_before_complex_2.SetEnabled(False)
+
+ thread.StepInto ("complex")
+ self.assertTrue (thread.GetFrameAtIndex(0).GetFunctionName() == "complex")
+
+ # Now continue out and stop at the next call to complex. This time enable breakpoints in a and c and then step targetting b:
+ threads = lldbutil.continue_to_breakpoint (process, break_before_complex_3)
+ self.assertTrue (len(threads) == 1)
+ thread = threads[0]
+ break_before_complex_3.SetEnabled(False)
+
+ break_at_start_of_a = target.BreakpointCreateByName ('a')
+ break_at_start_of_c = target.BreakpointCreateByName ('c')
+
+ thread.StepInto ("b")
+ threads = lldbutil.get_stopped_threads(process, lldb.eStopReasonBreakpoint);
+
+ self.assertTrue (len(threads) == 1)
+ thread = threads[0]
+ stop_break_id = thread.GetStopReasonDataAtIndex(0)
+ self.assertTrue(stop_break_id == break_at_start_of_a.GetID() or stop_break_id == break_at_start_of_c.GetID())
+
+ break_at_start_of_a.SetEnabled(False)
+ break_at_start_of_c.SetEnabled(False)
+
+ process.Continue()
+ self.assertTrue (thread.GetFrameAtIndex(0).GetFunctionName() == "b")
+
+ # Now continue out and stop at the next call to complex. This time enable breakpoints in a and c and then step targetting b:
+ threads = lldbutil.continue_to_breakpoint (process, break_before_complex_4)
+ self.assertTrue (len(threads) == 1)
+ thread = threads[0]
+ break_before_complex_4.SetEnabled(False)
+
+ thread.StepInto("NoSuchFunction")
+ self.assertTrue (thread.GetFrameAtIndex(0).GetFunctionName() == "main")
+
if __name__ == '__main__':
import atexit
lldb.SBDebugger.Initialize()
Modified: lldb/trunk/test/lang/c/stepping/main.c
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/c/stepping/main.c?rev=170008&r1=170007&r2=170008&view=diff
==============================================================================
--- lldb/trunk/test/lang/c/stepping/main.c (original)
+++ lldb/trunk/test/lang/c/stepping/main.c Wed Dec 12 13:58:40 2012
@@ -14,7 +14,7 @@
int a(int val)
{
- int return_value = val;
+ int return_value = val; // basic break at the start of b
if (val <= 1)
{
@@ -39,6 +39,11 @@
return val + 3; // Find the line number of function "c" here.
}
+int complex (int first, int second, int third)
+{
+ return first + second + third; // Step in targetting complex should stop here
+}
+
int main (int argc, char const *argv[])
{
int A1 = a(1); // frame select 2, thread step-out while stopped at "c(1)"
@@ -50,5 +55,13 @@
int A3 = a(3); // frame select 1, thread step-out while stopped at "c(3)"
printf("a(3) returns %d\n", A3);
+ int A4 = complex (a(1), b(2), c(3)); // Stop here to try step in targetting b.
+
+ int A5 = complex (a(2), b(3), c(4)); // Stop here to try step in targetting complex.
+
+ int A6 = complex (a(4), b(5), c(6)); // Stop here to step targetting b and hitting breakpoint.
+
+ int A7 = complex (a(5), b(6), c(7)); // Stop here to make sure bogus target steps over.
+
return 0;
}
More information about the lldb-commits
mailing list