summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/API/SBAddress.h1
-rw-r--r--lldb/include/lldb/API/SBDefines.h1
-rw-r--r--lldb/include/lldb/API/SBEvent.h6
-rw-r--r--lldb/include/lldb/API/SBStream.h1
-rw-r--r--lldb/include/lldb/API/SBThread.h12
-rw-r--r--lldb/include/lldb/API/SBThreadPlan.h129
-rw-r--r--lldb/include/lldb/Expression/ClangFunction.h4
-rw-r--r--lldb/include/lldb/Interpreter/ScriptInterpreter.h43
-rw-r--r--lldb/include/lldb/Interpreter/ScriptInterpreterPython.h20
-rw-r--r--lldb/include/lldb/Target/Thread.h24
-rw-r--r--lldb/include/lldb/Target/ThreadPlan.h5
-rw-r--r--lldb/include/lldb/Target/ThreadPlanPython.h80
-rw-r--r--lldb/include/lldb/Target/ThreadPlanStepRange.h4
-rw-r--r--lldb/include/lldb/lldb-private-enumerations.h3
-rw-r--r--lldb/lldb.xcodeproj/project.pbxproj18
-rwxr-xr-xlldb/scripts/Python/build-swig-Python.sh2
-rw-r--r--lldb/scripts/Python/interface/SBThread.i3
-rw-r--r--lldb/scripts/Python/interface/SBThreadPlan.i123
-rw-r--r--lldb/scripts/Python/python-swigsafecast.swig14
-rw-r--r--lldb/scripts/Python/python-wrapper.swig112
-rw-r--r--lldb/scripts/lldb.swig2
-rw-r--r--lldb/source/API/SBCommandInterpreter.cpp15
-rw-r--r--lldb/source/API/SBEvent.cpp6
-rw-r--r--lldb/source/API/SBThread.cpp69
-rw-r--r--lldb/source/API/SBThreadPlan.cpp285
-rw-r--r--lldb/source/Commands/CommandObjectThread.cpp597
-rw-r--r--lldb/source/Expression/ClangFunction.cpp20
-rw-r--r--lldb/source/Expression/ClangUserExpression.cpp14
-rw-r--r--lldb/source/Interpreter/ScriptInterpreter.cpp8
-rw-r--r--lldb/source/Interpreter/ScriptInterpreterPython.cpp90
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp8
-rw-r--r--lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp24
-rw-r--r--lldb/source/Target/Thread.cpp159
-rw-r--r--lldb/source/Target/ThreadPlanPython.cpp192
-rw-r--r--lldb/source/Target/ThreadPlanStepInRange.cpp29
-rw-r--r--lldb/source/Target/ThreadPlanStepOut.cpp51
-rw-r--r--lldb/source/Target/ThreadPlanStepOverRange.cpp26
-rw-r--r--lldb/source/Target/ThreadPlanStepRange.cpp8
38 files changed, 1891 insertions, 317 deletions
diff --git a/lldb/include/lldb/API/SBAddress.h b/lldb/include/lldb/API/SBAddress.h
index 58a7d2bfb1d..c2d07b6e9bc 100644
--- a/lldb/include/lldb/API/SBAddress.h
+++ b/lldb/include/lldb/API/SBAddress.h
@@ -117,6 +117,7 @@ protected:
friend class SBSymbolContext;
friend class SBTarget;
friend class SBThread;
+ friend class SBThreadPlan;
friend class SBValue;
friend class SBQueueItem;
diff --git a/lldb/include/lldb/API/SBDefines.h b/lldb/include/lldb/API/SBDefines.h
index eb1d0bf4f44..9ba5da34d54 100644
--- a/lldb/include/lldb/API/SBDefines.h
+++ b/lldb/include/lldb/API/SBDefines.h
@@ -71,6 +71,7 @@ class LLDB_API SBSymbolContextList;
class LLDB_API SBTarget;
class LLDB_API SBThread;
class LLDB_API SBThreadCollection;
+class LLDB_API SBThreadPlan;
class LLDB_API SBType;
class LLDB_API SBTypeCategory;
class LLDB_API SBTypeEnumMember;
diff --git a/lldb/include/lldb/API/SBEvent.h b/lldb/include/lldb/API/SBEvent.h
index 6cb975a1ff7..1706d0c009b 100644
--- a/lldb/include/lldb/API/SBEvent.h
+++ b/lldb/include/lldb/API/SBEvent.h
@@ -30,6 +30,10 @@ public:
// Make an event that contains a C string.
SBEvent (uint32_t event, const char *cstr, uint32_t cstr_len);
+ SBEvent (lldb::EventSP &event_sp);
+
+ SBEvent (lldb_private::Event *event_sp);
+
~SBEvent();
const SBEvent &
@@ -77,8 +81,6 @@ protected:
friend class SBThread;
friend class SBWatchpoint;
- SBEvent (lldb::EventSP &event_sp);
-
lldb::EventSP &
GetSP () const;
diff --git a/lldb/include/lldb/API/SBStream.h b/lldb/include/lldb/API/SBStream.h
index 07b23d166e3..cd33bfda32b 100644
--- a/lldb/include/lldb/API/SBStream.h
+++ b/lldb/include/lldb/API/SBStream.h
@@ -85,6 +85,7 @@ protected:
friend class SBSymbolContextList;
friend class SBTarget;
friend class SBThread;
+ friend class SBThreadPlan;
friend class SBType;
friend class SBTypeEnumMember;
friend class SBTypeMemberFunction;
diff --git a/lldb/include/lldb/API/SBThread.h b/lldb/include/lldb/API/SBThread.h
index 07a43ebee7c..ebf38fa9290 100644
--- a/lldb/include/lldb/API/SBThread.h
+++ b/lldb/include/lldb/API/SBThread.h
@@ -127,6 +127,9 @@ public:
uint32_t line);
SBError
+ StepUsingScriptedThreadPlan (const char *script_class_name);
+
+ SBError
JumpToLine (lldb::SBFileSpec &file_spec, uint32_t line);
void
@@ -216,6 +219,15 @@ public:
bool
SafeToCallFunctions ();
+#ifndef SWIG
+ lldb_private::Thread *
+ operator->();
+
+ lldb_private::Thread *
+ get();
+
+#endif
+
protected:
friend class SBBreakpoint;
friend class SBBreakpointLocation;
diff --git a/lldb/include/lldb/API/SBThreadPlan.h b/lldb/include/lldb/API/SBThreadPlan.h
new file mode 100644
index 00000000000..e53942d65fa
--- /dev/null
+++ b/lldb/include/lldb/API/SBThreadPlan.h
@@ -0,0 +1,129 @@
+//===-- SBThread.h ----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SBThreadPlan_h_
+#define LLDB_SBThreadPlan_h_
+
+#include "lldb/API/SBDefines.h"
+
+#include <stdio.h>
+
+namespace lldb {
+
+class SBThreadPlan
+{
+
+friend class lldb_private::ThreadPlan;
+
+public:
+ SBThreadPlan ();
+
+ SBThreadPlan (const lldb::SBThreadPlan &threadPlan);
+
+ SBThreadPlan (const lldb::ThreadPlanSP& lldb_object_sp);
+
+ SBThreadPlan (lldb::SBThread &thread, const char *class_name);
+
+ ~SBThreadPlan ();
+
+ bool
+ IsValid() const;
+
+ void
+ Clear ();
+
+ lldb::StopReason
+ GetStopReason();
+
+ /// Get the number of words associated with the stop reason.
+ /// See also GetStopReasonDataAtIndex().
+ size_t
+ GetStopReasonDataCount();
+
+ //--------------------------------------------------------------------------
+ /// Get information associated with a stop reason.
+ ///
+ /// Breakpoint stop reasons will have data that consists of pairs of
+ /// breakpoint IDs followed by the breakpoint location IDs (they always come
+ /// in pairs).
+ ///
+ /// Stop Reason Count Data Type
+ /// ======================== ===== =========================================
+ /// eStopReasonNone 0
+ /// eStopReasonTrace 0
+ /// eStopReasonBreakpoint N duple: {breakpoint id, location id}
+ /// eStopReasonWatchpoint 1 watchpoint id
+ /// eStopReasonSignal 1 unix signal number
+ /// eStopReasonException N exception data
+ /// eStopReasonExec 0
+ /// eStopReasonPlanComplete 0
+ //--------------------------------------------------------------------------
+ uint64_t
+ GetStopReasonDataAtIndex(uint32_t idx);
+
+ SBThread
+ GetThread () const;
+
+ const lldb::SBThreadPlan &
+ operator = (const lldb::SBThreadPlan &rhs);
+
+ bool
+ GetDescription (lldb::SBStream &description) const;
+
+ void
+ SetPlanComplete (bool success);
+
+ bool
+ IsPlanComplete();
+
+ bool
+ IsValid();
+
+ // This section allows an SBThreadPlan to push another of the common types of plans...
+ SBThreadPlan
+ QueueThreadPlanForStepOverRange (SBAddress &start_address,
+ lldb::addr_t range_size);
+
+ SBThreadPlan
+ QueueThreadPlanForStepInRange (SBAddress &start_address,
+ lldb::addr_t range_size);
+
+ SBThreadPlan
+ QueueThreadPlanForStepOut (uint32_t frame_idx_to_step_to, bool first_insn = false);
+
+ SBThreadPlan
+ QueueThreadPlanForRunToAddress (SBAddress address);
+
+#ifndef SWIG
+ lldb_private::ThreadPlan *
+ get();
+#endif
+
+protected:
+ friend class SBBreakpoint;
+ friend class SBBreakpointLocation;
+ friend class SBFrame;
+ friend class SBProcess;
+ friend class SBDebugger;
+ friend class SBValue;
+ friend class lldb_private::QueueImpl;
+ friend class SBQueueItem;
+
+#ifndef SWIG
+ void
+ SetThreadPlan (const lldb::ThreadPlanSP& lldb_object_sp);
+#endif
+
+private:
+ lldb::ThreadPlanSP m_opaque_sp;
+};
+
+} // namespace lldb
+
+#endif // LLDB_SBThreadPlan_h_
diff --git a/lldb/include/lldb/Expression/ClangFunction.h b/lldb/include/lldb/Expression/ClangFunction.h
index 61d56729f93..476bf7d92ed 100644
--- a/lldb/include/lldb/Expression/ClangFunction.h
+++ b/lldb/include/lldb/Expression/ClangFunction.h
@@ -285,9 +285,9 @@ public:
/// True if the thread plan may simply be discarded if an error occurs.
///
/// @return
- /// A ThreadPlan for executing the function.
+ /// A ThreadPlan shared pointer for executing the function.
//------------------------------------------------------------------
- ThreadPlan *
+ lldb::ThreadPlanSP
GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
lldb::addr_t args_addr,
const EvaluateExpressionOptions &options,
diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
index 5a8322f8eb4..bc7c7a0e57a 100644
--- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h
+++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
@@ -104,6 +104,12 @@ public:
const char *session_dictionary_name,
const lldb::ValueObjectSP& valobj_sp);
+ typedef void* (*SWIGPythonCreateScriptedThreadPlan) (const char *python_class_name,
+ const char *session_dictionary_name,
+ const lldb::ThreadPlanSP& thread_plan_sp);
+
+ typedef bool (*SWIGPythonCallThreadPlan) (void *implementor, const char *method_name, Event *event_sp, bool &got_error);
+
typedef void* (*SWIGPythonCreateOSPlugin) (const char *python_class_name,
const char *session_dictionary_name,
const lldb::ProcessSP& process_sp);
@@ -348,6 +354,39 @@ public:
}
virtual lldb::ScriptInterpreterObjectSP
+ CreateScriptedThreadPlan (const char *class_name,
+ lldb::ThreadPlanSP thread_plan_sp)
+ {
+ return lldb::ScriptInterpreterObjectSP();
+ }
+
+ virtual bool
+ ScriptedThreadPlanExplainsStop (lldb::ScriptInterpreterObjectSP implementor_sp,
+ Event *event,
+ bool &script_error)
+ {
+ script_error = true;
+ return true;
+ }
+
+ virtual bool
+ ScriptedThreadPlanShouldStop (lldb::ScriptInterpreterObjectSP implementor_sp,
+ Event *event,
+ bool &script_error)
+ {
+ script_error = true;
+ return true;
+ }
+
+ virtual lldb::StateType
+ ScriptedThreadPlanGetRunState (lldb::ScriptInterpreterObjectSP implementor_sp,
+ bool &script_error)
+ {
+ script_error = true;
+ return lldb::eStateStepping;
+ }
+
+ virtual lldb::ScriptInterpreterObjectSP
LoadPluginModule (const FileSpec& file_spec,
lldb_private::Error& error)
{
@@ -573,7 +612,9 @@ public:
SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread,
SWIGPythonScriptKeyword_Target swig_run_script_keyword_target,
SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame,
- SWIGPython_GetDynamicSetting swig_plugin_get);
+ SWIGPython_GetDynamicSetting swig_plugin_get,
+ SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script,
+ SWIGPythonCallThreadPlan swig_call_thread_plan);
virtual void
ResetOutputFileHandle (FILE *new_fh) { } //By default, do nothing.
diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h b/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h
index 14a62d67fde..483cb090cd5 100644
--- a/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h
+++ b/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h
@@ -80,6 +80,22 @@ public:
lldb::ScriptInterpreterObjectSP
CreateSyntheticScriptedProvider (const char *class_name,
lldb::ValueObjectSP valobj);
+
+ lldb::ScriptInterpreterObjectSP
+ virtual CreateScriptedThreadPlan (const char *class_name,
+ lldb::ThreadPlanSP thread_plan);
+
+ virtual bool
+ ScriptedThreadPlanExplainsStop (lldb::ScriptInterpreterObjectSP implementor_sp,
+ Event *event,
+ bool &script_error);
+ virtual bool
+ ScriptedThreadPlanShouldStop (lldb::ScriptInterpreterObjectSP implementor_sp,
+ Event *event,
+ bool &script_error);
+ virtual lldb::StateType
+ ScriptedThreadPlanGetRunState (lldb::ScriptInterpreterObjectSP implementor_sp,
+ bool &script_error);
virtual lldb::ScriptInterpreterObjectSP
OSPlugin_CreatePluginObject (const char *class_name,
@@ -275,7 +291,9 @@ public:
SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread,
SWIGPythonScriptKeyword_Target swig_run_script_keyword_target,
SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame,
- SWIGPython_GetDynamicSetting swig_plugin_get);
+ SWIGPython_GetDynamicSetting swig_plugin_get,
+ SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script,
+ SWIGPythonCallThreadPlan swig_call_thread_plan);
const char *
GetDictionaryName ()
diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h
index cba09e16410..87373fb8f19 100644
--- a/lldb/include/lldb/Target/Thread.h
+++ b/lldb/include/lldb/Target/Thread.h
@@ -912,6 +912,11 @@ public:
bool stop_others,
uint32_t frame_idx);
+ virtual lldb::ThreadPlanSP
+ QueueThreadPlanForStepScripted (bool abort_other_plans,
+ const char *class_name,
+ bool stop_other_threads);
+
//------------------------------------------------------------------
// Thread Plan accessors:
//------------------------------------------------------------------
@@ -1041,6 +1046,20 @@ public:
void
DiscardThreadPlansUpToPlan (ThreadPlan *up_to_plan_ptr);
+
+ //------------------------------------------------------------------
+ /// Discards the plans queued on the plan stack of the current thread up to and
+ /// including the plan in that matches \a thread_index counting only
+ /// the non-Private plans.
+ ///
+ /// @param[in] up_to_plan_sp
+ /// Discard all plans up to and including this user plan given by this index.
+ ///
+ /// @return
+ /// \b true if there was a thread plan with that user index, \b false otherwise.
+ //------------------------------------------------------------------
+ bool
+ DiscardUserThreadPlansUpToIndex (uint32_t thread_index);
//------------------------------------------------------------------
/// Prints the current plan stack.
@@ -1050,7 +1069,10 @@ public:
///
//------------------------------------------------------------------
void
- DumpThreadPlans (Stream *s) const;
+ DumpThreadPlans (Stream *s,
+ lldb::DescriptionLevel desc_level = lldb::eDescriptionLevelVerbose,
+ bool include_internal = true,
+ bool ignore_boring = false) const;
virtual bool
CheckpointThreadState (ThreadStateCheckpoint &saved_state);
diff --git a/lldb/include/lldb/Target/ThreadPlan.h b/lldb/include/lldb/Target/ThreadPlan.h
index 1f20841906d..db2e7989405 100644
--- a/lldb/include/lldb/Target/ThreadPlan.h
+++ b/lldb/include/lldb/Target/ThreadPlan.h
@@ -223,6 +223,7 @@ namespace lldb_private {
//------------------------------------------------------------------
class ThreadPlan :
+ public std::enable_shared_from_this<ThreadPlan>,
public UserID
{
public:
@@ -241,6 +242,7 @@ public:
eKindNull,
eKindBase,
eKindCallFunction,
+ eKindPython,
eKindStepInstruction,
eKindStepOut,
eKindStepOverBreakpoint,
@@ -687,7 +689,8 @@ protected:
virtual lldb::StateType
GetPlanRunState ();
-
+
+ DISALLOW_COPY_AND_ASSIGN(ThreadPlanNull);
};
diff --git a/lldb/include/lldb/Target/ThreadPlanPython.h b/lldb/include/lldb/Target/ThreadPlanPython.h
new file mode 100644
index 00000000000..fa41af1915c
--- /dev/null
+++ b/lldb/include/lldb/Target/ThreadPlanPython.h
@@ -0,0 +1,80 @@
+//===-- ThreadPlanPython.h --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ThreadPlan_Python_h_
+#define liblldb_ThreadPlan_Python_h_
+
+// C Includes
+// C++ Includes
+#include <string>
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Core/UserID.h"
+#include "lldb/Host/Mutex.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanTracer.h"
+#include "lldb/Target/StopInfo.h"
+
+namespace lldb_private {
+
+//------------------------------------------------------------------
+// ThreadPlanPython:
+//
+//------------------------------------------------------------------
+
+class ThreadPlanPython : public ThreadPlan
+{
+public:
+ ThreadPlanPython (Thread &thread, const char *class_name);
+ virtual ~ThreadPlanPython ();
+
+ virtual void
+ GetDescription (Stream *s,
+ lldb::DescriptionLevel level);
+
+ virtual bool
+ ValidatePlan (Stream *error);
+
+ virtual bool
+ ShouldStop (Event *event_ptr);
+
+ virtual bool
+ MischiefManaged ();
+
+ virtual bool
+ WillStop ();
+
+ virtual bool
+ StopOthers ();
+
+ virtual void
+ DidPush ();
+
+protected:
+ virtual bool
+ DoPlanExplainsStop (Event *event_ptr);
+
+ virtual lldb::StateType
+ GetPlanRunState ();
+
+private:
+ std::string m_class_name;
+ lldb::ScriptInterpreterObjectSP m_implementation_sp;
+
+ DISALLOW_COPY_AND_ASSIGN(ThreadPlanPython);
+};
+
+
+} // namespace lldb_private
+
+#endif // liblldb_ThreadPlan_Python_h_
diff --git a/lldb/include/lldb/Target/ThreadPlanStepRange.h b/lldb/include/lldb/Target/ThreadPlanStepRange.h
index 3487e9ad66c..43c55c2aa41 100644
--- a/lldb/include/lldb/Target/ThreadPlanStepRange.h
+++ b/lldb/include/lldb/Target/ThreadPlanStepRange.h
@@ -30,7 +30,8 @@ public:
Thread &thread,
const AddressRange &range,
const SymbolContext &addr_context,
- lldb::RunMode stop_others);
+ lldb::RunMode stop_others,
+ bool given_ranges_only = false);
virtual ~ThreadPlanStepRange ();
@@ -83,6 +84,7 @@ protected:
bool m_first_run_event; // We want to broadcast only one running event, our first.
lldb::BreakpointSP m_next_branch_bp_sp;
bool m_use_fast_step;
+ bool m_given_ranges_only;
private:
std::vector<lldb::DisassemblerSP> m_instruction_ranges;
diff --git a/lldb/include/lldb/lldb-private-enumerations.h b/lldb/include/lldb/lldb-private-enumerations.h
index 9aae2a6cb25..c62863d744c 100644
--- a/lldb/include/lldb/lldb-private-enumerations.h
+++ b/lldb/include/lldb/lldb-private-enumerations.h
@@ -22,7 +22,8 @@ typedef enum StepType
eStepTypeTraceOver, ///< Single step one instruction, stepping over.
eStepTypeInto, ///< Single step into a specified context.
eStepTypeOver, ///< Single step over a specified context.
- eStepTypeOut ///< Single step out a specified context.
+ eStepTypeOut, ///< Single step out a specified context.
+ eStepTypeScripted ///< A step type implemented by the script interpreter.
} StepType;
//----------------------------------------------------------------------
diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj
index 3a3934d51c0..c86afb02880 100644
--- a/lldb/lldb.xcodeproj/project.pbxproj
+++ b/lldb/lldb.xcodeproj/project.pbxproj
@@ -613,6 +613,10 @@
49DCF6FE170E6B4A0092F75E /* IRMemoryMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49DCF6FD170E6B4A0092F75E /* IRMemoryMap.cpp */; };
49DCF702170E70120092F75E /* Materializer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49DCF700170E70120092F75E /* Materializer.cpp */; };
4C3ADCD61810D88B00357218 /* BreakpointResolverFileRegex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CAA56141422D986001FFA01 /* BreakpointResolverFileRegex.cpp */; };
+ 4C56543119D1EFAA002E9C44 /* ThreadPlanPython.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C56543019D1EFAA002E9C44 /* ThreadPlanPython.cpp */; };
+ 4C56543319D1EFB6002E9C44 /* ThreadPlanPython.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C56543219D1EFB5002E9C44 /* ThreadPlanPython.h */; };
+ 4C56543519D2297A002E9C44 /* SBThreadPlan.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C56543419D2297A002E9C44 /* SBThreadPlan.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4C56543719D22B32002E9C44 /* SBThreadPlan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C56543619D22B32002E9C44 /* SBThreadPlan.cpp */; };
4C6649A014EEE7F100B0316F /* StreamCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C66499F14EEE7F100B0316F /* StreamCallback.h */; };
4C6649A314EEE81000B0316F /* StreamCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C6649A214EEE81000B0316F /* StreamCallback.cpp */; };
4C73152219B7D71700F865A4 /* Iterable.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C73152119B7D71700F865A4 /* Iterable.h */; };
@@ -1893,6 +1897,11 @@
4C43DF8611069BFD00E55CBF /* ThreadPlanStepOverRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanStepOverRange.h; path = include/lldb/Target/ThreadPlanStepOverRange.h; sourceTree = "<group>"; };
4C43DF8911069C3200E55CBF /* ThreadPlanStepInRange.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanStepInRange.cpp; path = source/Target/ThreadPlanStepInRange.cpp; sourceTree = "<group>"; };
4C43DF8A11069C3200E55CBF /* ThreadPlanStepOverRange.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanStepOverRange.cpp; path = source/Target/ThreadPlanStepOverRange.cpp; sourceTree = "<group>"; };
+ 4C56543019D1EFAA002E9C44 /* ThreadPlanPython.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanPython.cpp; path = source/Target/ThreadPlanPython.cpp; sourceTree = "<group>"; };
+ 4C56543219D1EFB5002E9C44 /* ThreadPlanPython.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanPython.h; path = include/lldb/Target/ThreadPlanPython.h; sourceTree = "<group>"; };
+ 4C56543419D2297A002E9C44 /* SBThreadPlan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBThreadPlan.h; path = include/lldb/API/SBThreadPlan.h; sourceTree = "<group>"; };
+ 4C56543619D22B32002E9C44 /* SBThreadPlan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBThreadPlan.cpp; path = source/API/SBThreadPlan.cpp; sourceTree = "<group>"; };
+ 4C56543819D22FD9002E9C44 /* SBThreadPlan.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBThreadPlan.i; sourceTree = "<group>"; };
4C5DBBC611E3FEC60035160F /* CommandObjectCommands.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectCommands.cpp; path = source/Commands/CommandObjectCommands.cpp; sourceTree = "<group>"; };
4C5DBBC711E3FEC60035160F /* CommandObjectCommands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectCommands.h; path = source/Commands/CommandObjectCommands.h; sourceTree = "<group>"; };
4C626533130F1B0A00C889F6 /* StreamTee.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StreamTee.h; path = include/lldb/Core/StreamTee.h; sourceTree = "<group>"; };
@@ -2669,6 +2678,7 @@
2611FF0E142D83060017FEA3 /* SBSymbolContextList.i */,
2611FF0F142D83060017FEA3 /* SBTarget.i */,
2611FF10142D83060017FEA3 /* SBThread.i */,
+ 4C56543819D22FD9002E9C44 /* SBThreadPlan.i */,
8CCB018419BA54930009FD44 /* SBThreadCollection.i */,
2611FF11142D83060017FEA3 /* SBType.i */,
9475C18A14E5EA1C001BFC6D /* SBTypeCategory.i */,
@@ -2786,6 +2796,8 @@
9A9831091125FC5800A56CB0 /* SBThread.cpp */,
8CCB018119BA4E210009FD44 /* SBThreadCollection.h */,
8CCB017F19BA4DD00009FD44 /* SBThreadCollection.cpp */,
+ 4C56543419D2297A002E9C44 /* SBThreadPlan.h */,
+ 4C56543619D22B32002E9C44 /* SBThreadPlan.cpp */,
2617447911685869005ADD65 /* SBType.h */,
261744771168585B005ADD65 /* SBType.cpp */,
9475C18514E5E9C5001BFC6D /* SBTypeCategory.h */,
@@ -3805,6 +3817,8 @@
49EC3E98118F90AC00B1265E /* ThreadPlanCallFunction.cpp */,
4C7CF7E31295E10E00B4FBB5 /* ThreadPlanCallUserExpression.h */,
4C7CF7E51295E12B00B4FBB5 /* ThreadPlanCallUserExpression.cpp */,
+ 4C56543219D1EFB5002E9C44 /* ThreadPlanPython.h */,
+ 4C56543019D1EFAA002E9C44 /* ThreadPlanPython.cpp */,
4C43DEF9110641F300E55CBF /* ThreadPlanShouldStopHere.h */,
4C43DEFA110641F300E55CBF /* ThreadPlanShouldStopHere.cpp */,
260C848010F50F0A00BB2B04 /* ThreadPlanStepInstruction.h */,
@@ -4403,6 +4417,7 @@
268F9D53123AA15200B91E9B /* SBSymbolContextList.h in Headers */,
2668022C115FD13D008E1FE4 /* SBTarget.h in Headers */,
2668022E115FD13D008E1FE4 /* SBThread.h in Headers */,
+ 4C56543519D2297A002E9C44 /* SBThreadPlan.h in Headers */,
263C493A178B50CF0070F12D /* SBModuleSpec.h in Headers */,
2617447A11685869005ADD65 /* SBType.h in Headers */,
9475C18914E5EA08001BFC6D /* SBTypeCategory.h in Headers */,
@@ -4495,6 +4510,7 @@
26DAED6015D327A200E15819 /* OptionValuePathMappings.h in Headers */,
26ACEC2815E077AE00E94760 /* Property.h in Headers */,
26491E3B15E1DB8600CBFFC2 /* OptionValueRegex.h in Headers */,
+ 4C56543319D1EFB6002E9C44 /* ThreadPlanPython.h in Headers */,
2697A39515E404BA003E682C /* OptionValueArch.h in Headers */,
26474CBF18D0CB2D0073DEBA /* RegisterContextMach_i386.h in Headers */,
26474CC118D0CB2D0073DEBA /* RegisterContextMach_x86_64.h in Headers */,
@@ -4899,6 +4915,7 @@
9443B122140C18C40013457C /* SBData.cpp in Sources */,
4CF52AF8142829390051E832 /* SBFileSpecList.cpp in Sources */,
23059A101958B319007B8189 /* SBUnixSignals.cpp in Sources */,
+ 4C56543719D22B32002E9C44 /* SBThreadPlan.cpp in Sources */,
8CCB018319BA51BF0009FD44 /* SBThreadCollection.cpp in Sources */,
26B82840142D020F002DBC64 /* SBSection.cpp in Sources */,
B2A58724143119D50092BFBA /* SBWatchpoint.cpp in Sources */,
@@ -5176,6 +5193,7 @@
268900E613353E6F00698AC0 /* Variable.cpp in Sources */,
268900E713353E6F00698AC0 /* VariableList.cpp in Sources */,
268900E813353E6F00698AC0 /* ABI.cpp in Sources */,
+ 4C56543119D1EFAA002E9C44 /* ThreadPlanPython.cpp in Sources */,
26AB92121819D74600E63F3E /* DWARFDataExtractor.cpp in Sources */,
268900E913353E6F00698AC0 /* CPPLanguageRuntime.cpp in Sources */,
268900EA13353E6F00698AC0 /* DynamicLoader.cpp in Sources */,
diff --git a/lldb/scripts/Python/build-swig-Python.sh b/lldb/scripts/Python/build-swig-Python.sh
index 88769c88856..3b610e139e2 100755
--- a/lldb/scripts/Python/build-swig-Python.sh
+++ b/lldb/scripts/Python/build-swig-Python.sh
@@ -114,6 +114,7 @@ HEADER_FILES="${SRC_ROOT}/include/lldb/lldb.h"\
" ${SRC_ROOT}/include/lldb/API/SBTarget.h"\
" ${SRC_ROOT}/include/lldb/API/SBThread.h"\
" ${SRC_ROOT}/include/lldb/API/SBThreadCollection.h"\
+" ${SRC_ROOT}/include/lldb/API/SBThreadPlan.h"\
" ${SRC_ROOT}/include/lldb/API/SBType.h"\
" ${SRC_ROOT}/include/lldb/API/SBTypeCategory.h"\
" ${SRC_ROOT}/include/lldb/API/SBTypeFilter.h"\
@@ -163,6 +164,7 @@ INTERFACE_FILES="${SRC_ROOT}/scripts/Python/interface/SBAddress.i"\
" ${SRC_ROOT}/scripts/Python/interface/SBTarget.i"\
" ${SRC_ROOT}/scripts/Python/interface/SBThread.i"\
" ${SRC_ROOT}/scripts/Python/interface/SBThreadCollection.i"\
+" ${SRC_ROOT}/scripts/Python/interface/SBThreadPlan.i"\
" ${SRC_ROOT}/scripts/Python/interface/SBType.i"\
" ${SRC_ROOT}/scripts/Python/interface/SBTypeCategory.i"\
" ${SRC_ROOT}/scripts/Python/interface/SBTypeFilter.i"\
diff --git a/lldb/scripts/Python/interface/SBThread.i b/lldb/scripts/Python/interface/SBThread.i
index 4d69ddaf229..dac0f9bc4a7 100644
--- a/lldb/scripts/Python/interface/SBThread.i
+++ b/lldb/scripts/Python/interface/SBThread.i
@@ -213,6 +213,9 @@ public:
uint32_t line);
SBError
+ StepUsingScriptedThreadPlan (const char *script_class_name);
+
+ SBError
JumpToLine (lldb::SBFileSpec &file_spec, uint32_t line);
void
diff --git a/lldb/scripts/Python/interface/SBThreadPlan.i b/lldb/scripts/Python/interface/SBThreadPlan.i
new file mode 100644
index 00000000000..785855ec5b9
--- /dev/null
+++ b/lldb/scripts/Python/interface/SBThreadPlan.i
@@ -0,0 +1,123 @@
+//===-- SBThread.h ----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SBThreadPlan_h_
+#define LLDB_SBThreadPlan_h_
+
+#include "lldb/API/SBDefines.h"
+
+#include <stdio.h>
+
+namespace lldb {
+
+%feature("docstring",
+"Represents a plan for the execution control of a given thread.
+
+See also SBThread and SBFrame."
+) SBThread;
+
+class SBThreadPlan
+{
+
+friend class lldb_private::ThreadPlan;
+
+public:
+ SBThreadPlan ();
+
+ SBThreadPlan (const lldb::SBThreadPlan &threadPlan);
+
+ SBThreadPlan (const lldb::ThreadPlanSP& lldb_object_sp);
+
+ SBThreadPlan (lldb::SBThread &thread, const char *class_name);
+
+ ~SBThreadPlan ();
+
+ bool
+ IsValid() const;
+
+ void
+ Clear ();
+
+ lldb::StopReason
+ GetStopReason();
+
+ /// Get the number of words associated with the stop reason.
+ /// See also GetStopReasonDataAtIndex().
+ size_t
+ GetStopReasonDataCount();
+
+ //--------------------------------------------------------------------------
+ /// Get information associated with a stop reason.
+ ///
+ /// Breakpoint stop reasons will have data that consists of pairs of
+ /// breakpoint IDs followed by the breakpoint location IDs (they always come
+ /// in pairs).
+ ///
+ /// Stop Reason Count Data Type
+ /// ======================== ===== =========================================
+ /// eStopReasonNone 0
+ /// eStopReasonTrace 0
+ /// eStopReasonBreakpoint N duple: {breakpoint id, location id}
+ /// eStopReasonWatchpoint 1 watchpoint id
+ /// eStopReasonSignal 1 unix signal number
+ /// eStopReasonException N exception data
+ /// eStopReasonExec 0
+ /// eStopReasonPlanComplete 0
+ //--------------------------------------------------------------------------
+ uint64_t
+ GetStopReasonDataAtIndex(uint32_t idx);
+
+ SBThread
+ GetThread () const;
+
+ bool
+ GetDescription (lldb::SBStream &description) const;
+
+ void
+ SetPlanComplete (bool success);
+
+ bool
+ IsPlanComplete();
+
+ bool
+ IsValid();
+
+ // This section allows an SBThreadPlan to push another of the common types of plans...
+ SBThreadPlan
+ QueueThreadPlanForStepOverRange (SBAddress &start_address,
+ lldb::addr_t range_size);
+
+ SBThreadPlan
+ QueueThreadPlanForStepInRange (SBAddress &start_address,
+ lldb::addr_t range_size);
+
+ SBThreadPlan
+ QueueThreadPlanForStepOut (uint32_t frame_idx_to_step_to, bool first_insn = false);
+
+ SBThreadPlan
+ QueueThreadPlanForRunToAddress (SBAddress address);
+
+
+protected:
+ friend class SBBreakpoint;
+ friend class SBBreakpointLocation;
+ friend class SBFrame;
+ friend class SBProcess;
+ friend class SBDebugger;
+ friend class SBValue;
+ friend class lldb_private::QueueImpl;
+ friend class SBQueueItem;
+
+private:
+ lldb::ThreadPlanSP m_opaque_sp;
+};
+
+} // namespace lldb
+
+#endif // LLDB_SBThreadPlan_h_
diff --git a/lldb/scripts/Python/python-swigsafecast.swig b/lldb/scripts/Python/python-swigsafecast.swig
index 0150854d2c6..4813c4f8c4d 100644
--- a/lldb/scripts/Python/python-swigsafecast.swig
+++ b/lldb/scripts/Python/python-swigsafecast.swig
@@ -45,6 +45,13 @@ SBTypeToSWIGWrapper (unsigned int* c_int)
template <>
PyObject*
+SBTypeToSWIGWrapper (lldb::SBEvent* event_sb)
+{
+ return SWIG_NewPointerObj((void *) event_sb, SWIGTYPE_p_lldb__SBEvent, 0);
+}
+
+template <>
+PyObject*
SBTypeToSWIGWrapper (lldb::SBProcess* process_sb)
{
return SWIG_NewPointerObj((void *) process_sb, SWIGTYPE_p_lldb__SBProcess, 0);
@@ -59,6 +66,13 @@ SBTypeToSWIGWrapper (lldb::SBThread* thread_sb)
template <>
PyObject*
+SBTypeToSWIGWrapper (lldb::SBThreadPlan* thread_plan_sb)
+{
+ return SWIG_NewPointerObj((void *) thread_plan_sb, SWIGTYPE_p_lldb__SBThreadPlan, 0);
+}
+
+template <>
+PyObject*
SBTypeToSWIGWrapper (lldb::SBTarget* target_sb)
{
return SWIG_NewPointerObj((void *) target_sb, SWIGTYPE_p_lldb__SBTarget, 0);
diff --git a/lldb/scripts/Python/python-wrapper.swig b/lldb/scripts/Python/python-wrapper.swig
index 646323a21cd..c3812df8110 100644
--- a/lldb/scripts/Python/python-wrapper.swig
+++ b/lldb/scripts/Python/python-wrapper.swig
@@ -419,6 +419,118 @@ LLDBSwigPythonCreateSyntheticProvider
Py_RETURN_NONE;
}
+SWIGEXPORT void*
+LLDBSwigPythonCreateScriptedThreadPlan
+(
+ const char *python_class_name,
+ const char *session_dictionary_name,
+ const lldb::ThreadPlanSP& thread_plan_sp
+)
+{
+ PyObject* retval = NULL;
+
+ if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
+ Py_RETURN_NONE;
+
+ // I do not want the SBThreadPlan to be deallocated when going out of scope because python
+ // has ownership of it and will manage memory for this object by itself
+ lldb::SBThreadPlan *tp_value = new lldb::SBThreadPlan(thread_plan_sp);
+
+ PyObject *ThreadPlan_PyObj = SBTypeToSWIGWrapper(tp_value);
+
+ if (ThreadPlan_PyObj == NULL)
+ Py_RETURN_NONE;
+
+ {
+ PyErr_Cleaner py_err_cleaner(true);
+
+ PyCallable pfunc = PyCallable::FindWithFunctionName(python_class_name, session_dictionary_name);
+
+ if (!pfunc)
+ return retval;
+
+ Py_INCREF(ThreadPlan_PyObj);
+
+ PyObject* session_dict = NULL;
+ session_dict = FindSessionDictionary(session_dictionary_name);
+ retval = pfunc(tp_value, session_dict);
+
+ // FIXME: At this point we should check that the class we found supports all the methods
+ // that we need.
+
+ Py_XINCREF (session_dict);
+
+ Py_XINCREF(retval);
+ }
+
+ if (retval)
+ return retval;
+ else
+ Py_RETURN_NONE;
+}
+
+SWIGEXPORT bool
+LLDBSWIGPythonCallThreadPlan
+(
+ void *implementor,
+ const char *method_name,
+ lldb_private::Event *event,
+ bool &got_error
+)
+{
+ bool ret_val = false;
+ got_error = false;
+
+
+ PyErr_Cleaner py_err_cleaner(false);
+
+ PyCallable pfunc = PyCallable::FindWithMemberFunction((PyObject *) implementor, method_name);
+
+ if (!pfunc)
+ {
+ return ret_val;
+ }
+
+ PyObject* py_return = Py_None;
+
+ if (event != NULL)
+ {
+ lldb::SBEvent sb_event(event);
+
+ PyObject *py_obj_event = SBTypeToSWIGWrapper(sb_event);
+
+ py_return = pfunc(py_obj_event);
+ }
+ else
+ {
+ py_return = pfunc();
+ }
+
+ if (PyErr_Occurred())
+ {
+ got_error = true;
+ printf ("Return value was neither false nor true for call to %s.\n", method_name);
+ PyErr_Print();
+ }
+ else
+ {
+ if (py_return == Py_True)
+ ret_val = true;
+ else if (py_return == Py_False)
+ ret_val = false;
+ else
+ {
+ // Somebody returned the wrong thing...
+ got_error = true;
+ printf ("Wrong return value type for call to %s.\n", method_name);
+ }
+ }
+
+ Py_XDECREF(py_return);
+
+ return ret_val;
+}
+
// wrapper that calls an optional instance member of an object taking no arguments
static PyObject*
LLDBSwigPython_CallOptionalMember
diff --git a/lldb/scripts/lldb.swig b/lldb/scripts/lldb.swig
index fc9c04249e4..fec05bb42b4 100644
--- a/lldb/scripts/lldb.swig
+++ b/lldb/scripts/lldb.swig
@@ -92,6 +92,7 @@ import os
#include "lldb/API/SBTarget.h"
#include "lldb/API/SBThread.h"
#include "lldb/API/SBThreadCollection.h"
+#include "lldb/API/SBThreadPlan.h"
#include "lldb/API/SBType.h"
#include "lldb/API/SBTypeCategory.h"
#include "lldb/API/SBTypeEnumMember.h"
@@ -164,6 +165,7 @@ import os
%include "./Python/interface/SBTarget.i"
%include "./Python/interface/SBThread.i"
%include "./Python/interface/SBThreadCollection.i"
+%include "./Python/interface/SBThreadPlan.i"
%include "./Python/interface/SBType.i"
%include "./Python/interface/SBTypeCategory.i"
%include "./Python/interface/SBTypeEnumMember.i"
diff --git a/lldb/source/API/SBCommandInterpreter.cpp b/lldb/source/API/SBCommandInterpreter.cpp
index e1adea795b0..397ee61839a 100644
--- a/lldb/source/API/SBCommandInterpreter.cpp
+++ b/lldb/source/API/SBCommandInterpreter.cpp
@@ -442,6 +442,17 @@ LLDBSwigPythonCreateSyntheticProvider (const char *python_class_name,
const lldb::ValueObjectSP& valobj_sp);
+extern "C" void*
+LLDBSwigPythonCreateScriptedThreadPlan (const char *python_class_name,
+ const char *session_dictionary_name,
+ const lldb::ThreadPlanSP& thread_plan_sp);
+
+extern "C" bool
+LLDBSWIGPythonCallThreadPlan (void *implementor,
+ const char *method_name,
+ Event *event_sp,
+ bool &got_error);
+
extern "C" uint32_t
LLDBSwigPython_CalculateNumChildren (void *implementor);
@@ -539,7 +550,9 @@ SBCommandInterpreter::InitializeSWIG ()
LLDBSWIGPythonRunScriptKeywordThread,
LLDBSWIGPythonRunScriptKeywordTarget,
LLDBSWIGPythonRunScriptKeywordFrame,
- LLDBSWIGPython_GetDynamicSetting);
+ LLDBSWIGPython_GetDynamicSetting,
+ LLDBSwigPythonCreateScriptedThreadPlan,
+ LLDBSWIGPythonCallThreadPlan);
#endif
}
}
diff --git a/lldb/source/API/SBEvent.cpp b/lldb/source/API/SBEvent.cpp
index 57a699fd739..c62c495b87c 100644
--- a/lldb/source/API/SBEvent.cpp
+++ b/lldb/source/API/SBEvent.cpp
@@ -43,6 +43,12 @@ SBEvent::SBEvent (EventSP &event_sp) :
{
}
+SBEvent::SBEvent (Event *event_ptr) :
+ m_event_sp (),
+ m_opaque_ptr (event_ptr)
+{
+}
+
SBEvent::SBEvent (const SBEvent &rhs) :
m_event_sp (rhs.m_event_sp),
m_opaque_ptr (rhs.m_opaque_ptr)
diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp
index a0bfa431353..390fa0d4b6e 100644
--- a/lldb/source/API/SBThread.cpp
+++ b/lldb/source/API/SBThread.cpp
@@ -41,6 +41,7 @@
#include "lldb/API/SBEvent.h"
#include "lldb/API/SBFrame.h"
#include "lldb/API/SBProcess.h"
+#include "lldb/API/SBThreadPlan.h"
#include "lldb/API/SBValue.h"
using namespace lldb;
@@ -918,7 +919,9 @@ SBThread::RunToAddress (lldb::addr_t addr)
Thread *thread = exe_ctx.GetThreadPtr();
- ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForRunToAddress (abort_other_plans, target_addr, stop_other_threads));
+ ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForRunToAddress (abort_other_plans,
+ target_addr,
+ stop_other_threads));
// This returns an error, we should use it!
ResumeNewPlan (exe_ctx, new_plan_sp.get());
@@ -1073,6 +1076,46 @@ SBThread::StepOverUntil (lldb::SBFrame &sb_frame,
}
SBError
+SBThread::StepUsingScriptedThreadPlan (const char *script_class_name)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+ SBError sb_error;
+
+ Mutex::Locker api_locker;
+ ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
+
+ if (log)
+ {
+ log->Printf ("SBThread(%p)::StepUsingScriptedThreadPlan: class name: %s",
+ static_cast<void*>(exe_ctx.GetThreadPtr()),
+ script_class_name);
+ }
+
+
+ if (!exe_ctx.HasThreadScope())
+ {
+ sb_error.SetErrorString("this SBThread object is invalid");
+ return sb_error;
+ }
+
+ Thread *thread = exe_ctx.GetThreadPtr();
+ ThreadPlanSP thread_plan_sp = thread->QueueThreadPlanForStepScripted(false, script_class_name, false);
+
+ if (thread_plan_sp)
+ sb_error = ResumeNewPlan(exe_ctx, thread_plan_sp.get());
+ else
+ {
+ sb_error.SetErrorStringWithFormat("Error queuing thread plan for class: %s.", script_class_name);
+ if (log)
+ log->Printf ("SBThread(%p)::StepUsingScriptedThreadPlan: Error queuing thread plan for class: %s",
+ static_cast<void*>(exe_ctx.GetThreadPtr()),
+ script_class_name);
+ }
+
+ return sb_error;
+}
+
+SBError
SBThread::JumpToLine (lldb::SBFileSpec &file_spec, uint32_t line)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
@@ -1473,7 +1516,8 @@ SBThread::GetExtendedBacktraceThread (const char *type)
const char *queue_name = new_thread_sp->GetQueueName();
if (queue_name == NULL)
queue_name = "";
- log->Printf ("SBThread(%p)::GetExtendedBacktraceThread() => new extended Thread created (%p) with queue_id 0x%" PRIx64 " queue name '%s'",
+ log->Printf ("SBThread(%p)::GetExtendedBacktraceThread() => new extended Thread "
+ "created (%p) with queue_id 0x%" PRIx64 " queue name '%s'",
static_cast<void*>(exe_ctx.GetThreadPtr()),
static_cast<void*>(new_thread_sp.get()),
new_thread_sp->GetQueueID(),
@@ -1515,3 +1559,24 @@ SBThread::SafeToCallFunctions ()
return thread_sp->SafeToCallFunctions();
return true;
}
+
+lldb_private::Thread *
+SBThread::operator->()
+{
+ ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
+ if (thread_sp)
+ return thread_sp.get();
+ else
+ return NULL;
+}
+
+lldb_private::Thread *
+SBThread::get()
+{
+ ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
+ if (thread_sp)
+ return thread_sp.get();
+ else
+ return NULL;
+}
+
diff --git a/lldb/source/API/SBThreadPlan.cpp b/lldb/source/API/SBThreadPlan.cpp
new file mode 100644
index 00000000000..02b1a8d893b
--- /dev/null
+++ b/lldb/source/API/SBThreadPlan.cpp
@@ -0,0 +1,285 @@
+//===-- SBThread.cpp --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+#include "lldb/API/SBThread.h"
+
+#include "lldb/API/SBSymbolContext.h"
+#include "lldb/API/SBFileSpec.h"
+#include "lldb/API/SBStream.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/State.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StructuredData.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Target/SystemRuntime.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Queue.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Target/StopInfo.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanPython.h"
+#include "lldb/Target/ThreadPlanStepInstruction.h"
+#include "lldb/Target/ThreadPlanStepOut.h"
+#include "lldb/Target/ThreadPlanStepRange.h"
+#include "lldb/Target/ThreadPlanStepInRange.h"
+
+
+#include "lldb/API/SBAddress.h"
+#include "lldb/API/SBDebugger.h"
+#include "lldb/API/SBEvent.h"
+#include "lldb/API/SBFrame.h"
+#include "lldb/API/SBProcess.h"
+#include "lldb/API/SBThreadPlan.h"
+#include "lldb/API/SBValue.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Constructors
+//----------------------------------------------------------------------
+SBThreadPlan::SBThreadPlan ()
+{
+}
+
+SBThreadPlan::SBThreadPlan (const ThreadPlanSP& lldb_object_sp) :
+ m_opaque_sp (lldb_object_sp)
+{
+}
+
+SBThreadPlan::SBThreadPlan (const SBThreadPlan &rhs) :
+ m_opaque_sp (rhs.m_opaque_sp)
+{
+
+}
+
+SBThreadPlan::SBThreadPlan (lldb::SBThread &sb_thread, const char *class_name)
+{
+ Thread *thread = sb_thread.get();
+ if (thread)
+ m_opaque_sp.reset(new ThreadPlanPython(*thread, class_name));
+}
+
+//----------------------------------------------------------------------
+// Assignment operator
+//----------------------------------------------------------------------
+
+const lldb::SBThreadPlan &
+SBThreadPlan::operator = (const SBThreadPlan &rhs)
+{
+ if (this != &rhs)
+ m_opaque_sp = rhs.m_opaque_sp;
+ return *this;
+}
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+SBThreadPlan::~SBThreadPlan()
+{
+}
+
+lldb_private::ThreadPlan *
+SBThreadPlan::get()
+{
+ return m_opaque_sp.get();
+}
+
+bool
+SBThreadPlan::IsValid() const
+{
+ return m_opaque_sp.get() != NULL;
+}
+
+void
+SBThreadPlan::Clear ()
+{
+ m_opaque_sp.reset();
+}
+
+lldb::StopReason
+SBThreadPlan::GetStopReason()
+{
+ return eStopReasonNone;
+}
+
+size_t
+SBThreadPlan::GetStopReasonDataCount()
+{
+ return 0;
+}
+
+uint64_t
+SBThreadPlan::GetStopReasonDataAtIndex(uint32_t idx)
+{
+ return 0;
+}
+
+SBThread
+SBThreadPlan::GetThread () const
+{
+ if (m_opaque_sp)
+ {
+ return SBThread(m_opaque_sp->GetThread().shared_from_this());
+ }
+ else
+ return SBThread();
+}
+
+bool
+SBThreadPlan::GetDescription (lldb::SBStream &description) const
+{
+ if (m_opaque_sp)
+ {
+ m_opaque_sp->GetDescription(description.get(), eDescriptionLevelFull);
+ }
+ else
+ {
+ description.Printf("Empty SBThreadPlan");
+ }
+ return true;
+}
+
+void
+SBThreadPlan::SetThreadPlan (const ThreadPlanSP& lldb_object_sp)
+{
+ m_opaque_sp = lldb_object_sp;
+}
+
+void
+SBThreadPlan::SetPlanComplete (bool success)
+{
+ if (m_opaque_sp)
+ m_opaque_sp->SetPlanComplete (success);
+}
+
+bool
+SBThreadPlan::IsPlanComplete()
+{
+ if (m_opaque_sp)
+ return m_opaque_sp->IsPlanComplete();
+ else
+ return true;
+}
+
+bool
+SBThreadPlan::IsValid()
+{
+ if (m_opaque_sp)
+ return m_opaque_sp->ValidatePlan(nullptr);
+ else
+ return false;
+}
+
+ // This section allows an SBThreadPlan to push another of the common types of plans...
+ //
+ // FIXME, you should only be able to queue thread plans from inside the methods of a
+ // Scripted Thread Plan. Need a way to enforce that.
+
+SBThreadPlan
+SBThreadPlan::QueueThreadPlanForStepOverRange (SBAddress &sb_start_address,
+ lldb::addr_t size)
+{
+ if (m_opaque_sp)
+ {
+ Address *start_address = sb_start_address.get();
+ if (!start_address)
+ {
+ return SBThreadPlan();
+ }
+
+ AddressRange range (*start_address, size);
+ SymbolContext sc;
+ start_address->CalculateSymbolContext(&sc);
+ return SBThreadPlan (m_opaque_sp->GetThread().QueueThreadPlanForStepOverRange (false,
+ range,
+ sc,
+ eAllThreads));
+ }
+ else
+ {
+ return SBThreadPlan();
+ }
+}
+
+SBThreadPlan
+SBThreadPlan::QueueThreadPlanForStepInRange (SBAddress &sb_start_address,
+ lldb::addr_t size)
+{
+ if (m_opaque_sp)
+ {
+ Address *start_address = sb_start_address.get();
+ if (!start_address)
+ {
+ return SBThreadPlan();
+ }
+
+ AddressRange range (*start_address, size);
+ SymbolContext sc;
+ start_address->CalculateSymbolContext(&sc);
+ return SBThreadPlan (m_opaque_sp->GetThread().QueueThreadPlanForStepInRange (false,
+ range,
+ sc,
+ NULL,
+ eAllThreads));
+ }
+ else
+ {
+ return SBThreadPlan();
+ }
+}
+
+SBThreadPlan
+SBThreadPlan::QueueThreadPlanForStepOut (uint32_t frame_idx_to_step_to, bool first_insn)
+{
+ if (m_opaque_sp)
+ {
+ SymbolContext sc;
+ sc = m_opaque_sp->GetThread().GetStackFrameAtIndex(0)->GetSymbolContext(lldb::eSymbolContextEverything);
+ return SBThreadPlan (m_opaque_sp->GetThread().QueueThreadPlanForStepOut (false,
+ &sc,
+ first_insn,
+ false,
+ eVoteYes,
+ eVoteNoOpinion,
+ frame_idx_to_step_to));
+ }
+ else
+ {
+ return SBThreadPlan();
+ }
+}
+
+SBThreadPlan
+SBThreadPlan::QueueThreadPlanForRunToAddress (SBAddress sb_address)
+{
+ if (m_opaque_sp)
+ {
+ Address *address = sb_address.get();
+ if (!address)
+ return SBThreadPlan();
+
+ return SBThreadPlan (m_opaque_sp->GetThread().QueueThreadPlanForRunToAddress (false,
+ *address,
+ false));
+ }
+ else
+ {
+ return SBThreadPlan();
+ }
+}
+
+
diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp
index e7a8652ac89..785e8f078ee 100644
--- a/lldb/source/Commands/CommandObjectThread.cpp
+++ b/lldb/source/Commands/CommandObjectThread.cpp
@@ -46,7 +46,108 @@ using namespace lldb_private;
// CommandObjectThreadBacktrace
//-------------------------------------------------------------------------
-class CommandObjectThreadBacktrace : public CommandObjectParsed
+class CommandObjectIterateOverThreads : public CommandObjectParsed
+{
+public:
+ CommandObjectIterateOverThreads (CommandInterpreter &interpreter,
+ const char *name,
+ const char *help,
+ const char *syntax,
+ uint32_t flags) :
+ CommandObjectParsed (interpreter, name, help, syntax, flags)
+ {
+ }
+
+ virtual ~CommandObjectIterateOverThreads() {}
+ virtual bool
+ DoExecute (Args& command, CommandReturnObject &result)
+ {
+ result.SetStatus (m_success_return);
+
+ if (command.GetArgumentCount() == 0)
+ {
+ Thread *thread = m_exe_ctx.GetThreadPtr();
+ if (!HandleOneThread (*thread, result))
+ return false;
+ }
+ else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0)
+ {
+ Process *process = m_exe_ctx.GetProcessPtr();
+ uint32_t idx = 0;
+ for (ThreadSP thread_sp : process->Threads())
+ {
+ if (idx != 0 && m_add_return)
+ result.AppendMessage("");
+
+ if (!HandleOneThread(*(thread_sp.get()), result))
+ return false;
+ ++idx;
+ }
+ }
+ else
+ {
+ const size_t num_args = command.GetArgumentCount();
+ Process *process = m_exe_ctx.GetProcessPtr();
+ Mutex::Locker locker (process->GetThreadList().GetMutex());
+ std::vector<ThreadSP> thread_sps;
+
+ for (size_t i = 0; i < num_args; i++)
+ {
+ bool success;
+
+ uint32_t thread_idx = Args::StringToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success);
+ if (!success)
+ {
+ result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i));
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx));
+
+ if (!thread_sps[i])
+ {
+ result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i));
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ }
+
+ for (uint32_t i = 0; i < num_args; i++)
+ {
+ if (!HandleOneThread (*(thread_sps[i].get()), result))
+ return false;
+
+ if (i < num_args - 1 && m_add_return)
+ result.AppendMessage("");
+ }
+ }
+ return result.Succeeded();
+ }
+
+protected:
+
+ // Override this to do whatever you need to do for one thread.
+ //
+ // If you return false, the iteration will stop, otherwise it will proceed.
+ // The result is set to m_success_return (defaults to eReturnStatusSuccessFinishResult) before the iteration,
+ // so you only need to set the return status in HandleOneThread if you want to indicate an error.
+ // If m_add_return is true, a blank line will be inserted between each of the listings (except the last one.)
+
+ virtual bool
+ HandleOneThread (Thread &thread, CommandReturnObject &result) = 0;
+
+ ReturnStatus m_success_return = eReturnStatusSuccessFinishResult;
+ bool m_add_return = true;
+
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectThreadBacktrace
+//-------------------------------------------------------------------------
+
+class CommandObjectThreadBacktrace : public CommandObjectIterateOverThreads
{
public:
@@ -134,7 +235,7 @@ public:
};
CommandObjectThreadBacktrace (CommandInterpreter &interpreter) :
- CommandObjectParsed (interpreter,
+ CommandObjectIterateOverThreads (interpreter,
"thread backtrace",
"Show the stack for one or more threads. If no threads are specified, show the currently selected thread. Use the thread-index \"all\" to see all threads.",
NULL,
@@ -145,18 +246,6 @@ public:
eFlagProcessMustBePaused ),
m_options(interpreter)
{
- CommandArgumentEntry arg;
- CommandArgumentData thread_idx_arg;
-
- // Define the first (and only) variant of this arg.
- thread_idx_arg.arg_type = eArgTypeThreadIndex;
- thread_idx_arg.arg_repetition = eArgRepeatStar;
-
- // There is only one variant this argument could be; put it into the argument entry.
- arg.push_back (thread_idx_arg);
-
- // Push the data for the first argument into the m_arguments vector.
- m_arguments.push_back (arg);
}
~CommandObjectThreadBacktrace()
@@ -197,106 +286,28 @@ protected:
}
virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
- {
- result.SetStatus (eReturnStatusSuccessFinishResult);
+ HandleOneThread (Thread &thread, CommandReturnObject &result)
+ {
Stream &strm = result.GetOutputStream();
// Don't show source context when doing backtraces.
const uint32_t num_frames_with_source = 0;
- if (command.GetArgumentCount() == 0)
- {
- Thread *thread = m_exe_ctx.GetThreadPtr();
- // Thread::GetStatus() returns the number of frames shown.
- if (thread->GetStatus (strm,
+
+ if (!thread.GetStatus (strm,
m_options.m_start,
m_options.m_count,
num_frames_with_source))
- {
- result.SetStatus (eReturnStatusSuccessFinishResult);
- if (m_options.m_extended_backtrace)
- {
- DoExtendedBacktrace (thread, result);
- }
- }
- }
- else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0)
{
- Process *process = m_exe_ctx.GetProcessPtr();
- uint32_t idx = 0;
- for (ThreadSP thread_sp : process->Threads())
- {
- if (idx != 0)
- result.AppendMessage("");
-
- if (!thread_sp->GetStatus (strm,
- m_options.m_start,
- m_options.m_count,
- num_frames_with_source))
- {
- result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", idx);
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
- if (m_options.m_extended_backtrace)
- {
- DoExtendedBacktrace (thread_sp.get(), result);
- }
-
- ++idx;
- }
+ result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", thread.GetIndexID());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
}
- else
+ if (m_options.m_extended_backtrace)
{
- const size_t num_args = command.GetArgumentCount();
- Process *process = m_exe_ctx.GetProcessPtr();
- Mutex::Locker locker (process->GetThreadList().GetMutex());
- std::vector<ThreadSP> thread_sps;
-
- for (size_t i = 0; i < num_args; i++)
- {
- bool success;
-
- uint32_t thread_idx = Args::StringToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success);
- if (!success)
- {
- result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i));
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
-
- thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx));
-
- if (!thread_sps[i])
- {
- result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i));
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
-
- }
-
- for (uint32_t i = 0; i < num_args; i++)
- {
- if (!thread_sps[i]->GetStatus (strm,
- m_options.m_start,
- m_options.m_count,
- num_frames_with_source))
- {
- result.AppendErrorWithFormat ("error displaying backtrace for thread: \"%s\"\n", command.GetArgumentAtIndex(i));
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
- if (m_options.m_extended_backtrace)
- {
- DoExtendedBacktrace (thread_sps[i].get(), result);
- }
-
- if (i < num_args - 1)
- result.AppendMessage("");
- }
+ DoExtendedBacktrace (&thread, result);
}
- return result.Succeeded();
+
+ return true;
}
CommandOptions m_options;
@@ -379,6 +390,12 @@ public:
break;
}
break;
+ case 'C':
+ {
+ m_class_name.clear();
+ m_class_name.assign(option_arg);
+ }
+ break;
case 'm':
{
OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
@@ -416,6 +433,7 @@ public:
m_run_mode = eOnlyDuringStepping;
m_avoid_regexp.clear();
m_step_in_target.clear();
+ m_class_name.clear();
m_step_count = 1;
}
@@ -435,6 +453,7 @@ public:
RunMode m_run_mode;
std::string m_avoid_regexp;
std::string m_step_in_target;
+ std::string m_class_name;
int32_t m_step_count;
};
@@ -520,6 +539,22 @@ protected:
}
}
+ if (m_step_type == eStepTypeScripted)
+ {
+ if (m_options.m_class_name.empty())
+ {
+ result.AppendErrorWithFormat ("empty class name for scripted step.");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ else if (!m_interpreter.GetScriptInterpreter()->CheckObjectExists(m_options.m_class_name.c_str()))
+ {
+ result.AppendErrorWithFormat ("class for scripted step: \"%s\" does not exist.", m_options.m_class_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ }
+
const bool abort_other_plans = false;
const lldb::RunMode stop_other_threads = m_options.m_run_mode;
@@ -530,7 +565,7 @@ protected:
bool_stop_other_threads = false;
else if (m_options.m_run_mode == eOnlyDuringStepping)
{
- if (m_step_type == eStepTypeOut)
+ if (m_step_type == eStepTypeOut || m_step_type == eStepTypeScripted)
bool_stop_other_threads = false;
else
bool_stop_other_threads = true;
@@ -599,6 +634,12 @@ protected:
thread->GetSelectedFrameIndex(),
m_options.m_step_out_avoid_no_debug);
}
+ else if (m_step_type == eStepTypeScripted)
+ {
+ new_plan_sp = thread->QueueThreadPlanForStepScripted (abort_other_plans,
+ m_options.m_class_name.c_str(),
+ bool_stop_other_threads);
+ }
else
{
result.AppendError ("step type is not supported");
@@ -686,10 +727,11 @@ CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] =
{
{ LLDB_OPT_SET_1, false, "step-in-avoids-no-debug", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "A boolean value that sets whether stepping into functions will step over functions with no debug information."},
{ LLDB_OPT_SET_1, false, "step-out-avoids-no-debug", 'A', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "A boolean value, if true stepping out of functions will continue to step out till it hits a function with debug information."},
-{ LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 1, eArgTypeCount, "How many times to perform the stepping operation - currently only supported for step-inst and next-inst."},
-{ LLDB_OPT_SET_1, false, "run-mode", 'm', OptionParser::eRequiredArgument, NULL, 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', OptionParser::eRequiredArgument, NULL, 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', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFunctionName, "The name of the directly called function step in should stop at when stepping into."},
+{ LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 1, eArgTypeCount, "How many times to perform the stepping operation - currently only supported for step-inst and next-inst."},
+{ LLDB_OPT_SET_1, false, "run-mode", 'm', OptionParser::eRequiredArgument, NULL, 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', OptionParser::eRequiredArgument, NULL, 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', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFunctionName, "The name of the directly called function step in should stop at when stepping into."},
+{ LLDB_OPT_SET_2, false, "python-class", 'C', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonClass, "The name of the class that will manage this step - only supported for Scripted Step."},
{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
@@ -1358,32 +1400,22 @@ protected:
// CommandObjectThreadInfo
//-------------------------------------------------------------------------
-class CommandObjectThreadInfo : public CommandObjectParsed
+class CommandObjectThreadInfo : public CommandObjectIterateOverThreads
{
public:
CommandObjectThreadInfo (CommandInterpreter &interpreter) :
- CommandObjectParsed (interpreter,
- "thread info",
- "Show an extended summary of information about thread(s) in a process.",
- "thread info",
- eFlagRequiresProcess |
- eFlagTryTargetAPILock |
- eFlagProcessMustBeLaunched |
- eFlagProcessMustBePaused),
+ CommandObjectIterateOverThreads (interpreter,
+ "thread info",
+ "Show an extended summary of information about thread(s) in a process.",
+ "thread info",
+ eFlagRequiresProcess |
+ eFlagTryTargetAPILock |
+ eFlagProcessMustBeLaunched |
+ eFlagProcessMustBePaused),
m_options (interpreter)
{
- CommandArgumentEntry arg;
- CommandArgumentData thread_idx_arg;
-
- thread_idx_arg.arg_type = eArgTypeThreadIndex;
- thread_idx_arg.arg_repetition = eArgRepeatStar;
-
- // There is only one variant this argument could be; put it into the argument entry.
- arg.push_back (thread_idx_arg);
-
- // Push the data for the first argument into the m_arguments vector.
- m_arguments.push_back (arg);
+ m_add_return = false;
}
class CommandOptions : public Options
@@ -1451,81 +1483,16 @@ public:
}
virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ HandleOneThread (Thread &thread, CommandReturnObject &result)
{
- result.SetStatus (eReturnStatusSuccessFinishResult);
Stream &strm = result.GetOutputStream();
-
- if (command.GetArgumentCount() == 0)
+ if (!thread.GetDescription (strm, eDescriptionLevelFull, m_options.m_json))
{
- Thread *thread = m_exe_ctx.GetThreadPtr();
- if (thread->GetDescription (strm, eDescriptionLevelFull, m_options.m_json))
- {
- result.SetStatus (eReturnStatusSuccessFinishResult);
- }
- }
- else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0)
- {
- Process *process = m_exe_ctx.GetProcessPtr();
- uint32_t idx = 0;
- for (ThreadSP thread_sp : process->Threads())
- {
- if (idx != 0)
- result.AppendMessage("");
- if (!thread_sp->GetDescription (strm, eDescriptionLevelFull, m_options.m_json))
- {
- result.AppendErrorWithFormat ("error displaying info for thread: \"0x%4.4x\"\n", idx);
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
- ++idx;
- }
- }
- else
- {
- const size_t num_args = command.GetArgumentCount();
- Process *process = m_exe_ctx.GetProcessPtr();
- Mutex::Locker locker (process->GetThreadList().GetMutex());
- std::vector<ThreadSP> thread_sps;
-
- for (size_t i = 0; i < num_args; i++)
- {
- bool success;
-
- uint32_t thread_idx = Args::StringToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success);
- if (!success)
- {
- result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i));
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
-
- thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx));
-
- if (!thread_sps[i])
- {
- result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i));
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
-
- }
-
- for (uint32_t i = 0; i < num_args; i++)
- {
- if (!thread_sps[i]->GetDescription (strm, eDescriptionLevelFull, m_options.m_json))
- {
- result.AppendErrorWithFormat ("error displaying info for thread: \"%s\"\n", command.GetArgumentAtIndex(i));
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
-
- if (i < num_args - 1)
- result.AppendMessage("");
- }
-
+ result.AppendErrorWithFormat ("error displaying info for thread: \"%d\"\n", thread.GetIndexID());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
}
- return result.Succeeded();
+ return true;
}
CommandOptions m_options;
@@ -1958,6 +1925,228 @@ CommandObjectThreadJump::CommandOptions::g_option_table[] =
};
//-------------------------------------------------------------------------
+// Next are the subcommands of CommandObjectMultiwordThreadPlan
+//-------------------------------------------------------------------------
+
+
+//-------------------------------------------------------------------------
+// CommandObjectThreadPlanList
+//-------------------------------------------------------------------------
+class CommandObjectThreadPlanList : public CommandObjectIterateOverThreads
+{
+public:
+
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions (CommandInterpreter &interpreter) :
+ Options(interpreter)
+ {
+ // Keep default values of all options in one place: OptionParsingStarting ()
+ OptionParsingStarting ();
+ }
+
+ virtual
+ ~CommandOptions ()
+ {
+ }
+
+ virtual Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg)
+ {
+ Error error;
+ const int short_option = m_getopt_table[option_idx].val;
+
+ switch (short_option)
+ {
+ case 'i':
+ {
+ m_internal = true;
+ }
+ break;
+ case 'v':
+ {
+ m_verbose = true;
+ }
+ break;
+ default:
+ error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
+ break;
+
+ }
+ return error;
+ }
+
+ void
+ OptionParsingStarting ()
+ {
+ m_verbose = false;
+ m_internal = false;
+ }
+
+ const OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_option_table;
+ }
+
+ // Options table: Required for subclasses of Options.
+
+ static OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+ bool m_verbose;
+ bool m_internal;
+ };
+
+ CommandObjectThreadPlanList (CommandInterpreter &interpreter) :
+ CommandObjectIterateOverThreads (interpreter,
+ "thread plan list",
+ "Show thread plans for one or more threads. If no threads are specified, show the "
+ "currently selected thread. Use the thread-index \"all\" to see all threads.",
+ NULL,
+ eFlagRequiresProcess |
+ eFlagRequiresThread |
+ eFlagTryTargetAPILock |
+ eFlagProcessMustBeLaunched |
+ eFlagProcessMustBePaused ),
+ m_options(interpreter)
+ {
+ }
+
+ ~CommandObjectThreadPlanList ()
+ {
+ }
+
+ virtual Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
+protected:
+ virtual bool
+ HandleOneThread (Thread &thread, CommandReturnObject &result)
+ {
+ Stream &strm = result.GetOutputStream();
+ DescriptionLevel desc_level = eDescriptionLevelFull;
+ if (m_options.m_verbose)
+ desc_level = eDescriptionLevelVerbose;
+
+ thread.DumpThreadPlans (&strm, desc_level, m_options.m_internal, true);
+ return true;
+ }
+ CommandOptions m_options;
+};
+
+OptionDefinition
+CommandObjectThreadPlanList::CommandOptions::g_option_table[] =
+{
+{ LLDB_OPT_SET_1, false, "verbose", 'v', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display more information about the thread plans"},
+{ LLDB_OPT_SET_1, false, "internal", 'i', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display internal as well as user thread plans"},
+{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
+};
+
+class CommandObjectThreadPlanDiscard : public CommandObjectParsed
+{
+public:
+ CommandObjectThreadPlanDiscard (CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter,
+ "thread plan discard",
+ "Discards thread plans up to and including the plan passed as the command argument."
+ "Only user visible plans can be discarded, use the index from \"thread plan list\""
+ " without the \"-i\" argument.",
+ NULL,
+ eFlagRequiresProcess |
+ eFlagRequiresThread |
+ eFlagTryTargetAPILock |
+ eFlagProcessMustBeLaunched |
+ eFlagProcessMustBePaused )
+ {
+ CommandArgumentEntry arg;
+ CommandArgumentData plan_index_arg;
+
+ // Define the first (and only) variant of this arg.
+ plan_index_arg.arg_type = eArgTypeUnsignedInteger;
+ plan_index_arg.arg_repetition = eArgRepeatPlain;
+
+ // There is only one variant this argument could be; put it into the argument entry.
+ arg.push_back (plan_index_arg);
+
+ // Push the data for the first argument into the m_arguments vector.
+ m_arguments.push_back (arg);
+ }
+
+ virtual ~CommandObjectThreadPlanDiscard () {}
+
+ bool
+ DoExecute (Args& args, CommandReturnObject &result)
+ {
+ Thread *thread = m_exe_ctx.GetThreadPtr();
+ if (args.GetArgumentCount() != 1)
+ {
+ result.AppendErrorWithFormat("Too many arguments, expected one - the thread plan index - but got %zu.",
+ args.GetArgumentCount());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ bool success;
+ uint32_t thread_plan_idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), 0, 0, &success);
+ if (!success)
+ {
+ result.AppendErrorWithFormat("Invalid thread index: \"%s\" - should be unsigned int.",
+ args.GetArgumentAtIndex(0));
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ if (thread_plan_idx == 0)
+ {
+ result.AppendErrorWithFormat("You wouldn't really want me to discard the base thread plan.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ if (thread->DiscardUserThreadPlansUpToIndex(thread_plan_idx))
+ {
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ return true;
+ }
+ else
+ {
+ result.AppendErrorWithFormat("Could not find User thread plan with index %s.",
+ args.GetArgumentAtIndex(0));
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectMultiwordThreadPlan
+//-------------------------------------------------------------------------
+
+class CommandObjectMultiwordThreadPlan : public CommandObjectMultiword
+{
+public:
+ CommandObjectMultiwordThreadPlan(CommandInterpreter &interpreter) :
+ CommandObjectMultiword (interpreter,
+ "plan",
+ "A set of subcommands for accessing the thread plans controlling execution control on one or more threads.",
+ "thread plan <subcommand> [<subcommand objects]")
+ {
+ LoadSubCommand ("list", CommandObjectSP (new CommandObjectThreadPlanList (interpreter)));
+ LoadSubCommand ("discard", CommandObjectSP (new CommandObjectThreadPlanDiscard (interpreter)));
+ }
+
+ virtual ~CommandObjectMultiwordThreadPlan () {}
+
+
+};
+
+//-------------------------------------------------------------------------
// CommandObjectMultiwordThread
//-------------------------------------------------------------------------
@@ -2014,6 +2203,16 @@ CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &
NULL,
eStepTypeTraceOver,
eStepScopeInstruction)));
+
+ LoadSubCommand ("step-scripted", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
+ interpreter,
+ "thread step-scripted",
+ "Step as instructed by the script class passed in the -C option.",
+ NULL,
+ eStepTypeScripted,
+ eStepScopeSource)));
+
+ LoadSubCommand ("plan", CommandObjectSP (new CommandObjectMultiwordThreadPlan(interpreter)));
}
CommandObjectMultiwordThread::~CommandObjectMultiwordThread ()
diff --git a/lldb/source/Expression/ClangFunction.cpp b/lldb/source/Expression/ClangFunction.cpp
index 27afba2898a..5654e654cdb 100644
--- a/lldb/source/Expression/ClangFunction.cpp
+++ b/lldb/source/Expression/ClangFunction.cpp
@@ -422,7 +422,7 @@ ClangFunction::InsertFunction (ExecutionContext &exe_ctx, lldb::addr_t &args_add
return true;
}
-ThreadPlan *
+lldb::ThreadPlanSP
ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
lldb::addr_t args_addr,
const EvaluateExpressionOptions &options,
@@ -447,14 +447,14 @@ ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
lldb::addr_t args = { args_addr };
- ThreadPlan *new_plan = new ThreadPlanCallFunction (*thread,
+ lldb::ThreadPlanSP new_plan_sp (new ThreadPlanCallFunction (*thread,
wrapper_address,
ClangASTType(),
args,
- options);
- new_plan->SetIsMasterPlan(true);
- new_plan->SetOkayToDiscard (false);
- return new_plan;
+ options));
+ new_plan_sp->SetIsMasterPlan(true);
+ new_plan_sp->SetOkayToDiscard (false);
+ return new_plan_sp;
}
bool
@@ -541,10 +541,10 @@ ClangFunction::ExecuteFunction(
if (log)
log->Printf("== [ClangFunction::ExecuteFunction] Executing function \"%s\" ==", m_name.c_str());
- lldb::ThreadPlanSP call_plan_sp (GetThreadPlanToCallFunction (exe_ctx,
- args_addr,
- real_options,
- errors));
+ lldb::ThreadPlanSP call_plan_sp = GetThreadPlanToCallFunction (exe_ctx,
+ args_addr,
+ real_options,
+ errors);
if (!call_plan_sp)
return lldb::eExpressionSetupError;
diff --git a/lldb/source/Expression/ClangUserExpression.cpp b/lldb/source/Expression/ClangUserExpression.cpp
index 52ef4d31035..dab7b556e39 100644
--- a/lldb/source/Expression/ClangUserExpression.cpp
+++ b/lldb/source/Expression/ClangUserExpression.cpp
@@ -885,17 +885,17 @@ ClangUserExpression::Execute (Stream &error_stream,
args.push_back(struct_address);
- ThreadPlanCallUserExpression *user_expression_plan =
- new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(),
- wrapper_address,
- args,
- options,
- shared_ptr_to_me);
- lldb::ThreadPlanSP call_plan_sp(user_expression_plan);
+ lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(),
+ wrapper_address,
+ args,
+ options,
+ shared_ptr_to_me));
if (!call_plan_sp || !call_plan_sp->ValidatePlan (&error_stream))
return lldb::eExpressionSetupError;
+ ThreadPlanCallUserExpression *user_expression_plan = static_cast<ThreadPlanCallUserExpression *>(call_plan_sp.get());
+
lldb::addr_t function_stack_pointer = user_expression_plan->GetFunctionStackPointer();
function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize();
diff --git a/lldb/source/Interpreter/ScriptInterpreter.cpp b/lldb/source/Interpreter/ScriptInterpreter.cpp
index b6c46f83bd9..721eedb59d7 100644
--- a/lldb/source/Interpreter/ScriptInterpreter.cpp
+++ b/lldb/source/Interpreter/ScriptInterpreter.cpp
@@ -131,7 +131,9 @@ ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_call
SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread,
SWIGPythonScriptKeyword_Target swig_run_script_keyword_target,
SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame,
- SWIGPython_GetDynamicSetting swig_plugin_get)
+ SWIGPython_GetDynamicSetting swig_plugin_get,
+ SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script,
+ SWIGPythonCallThreadPlan swig_call_thread_plan)
{
#ifndef LLDB_DISABLE_PYTHON
ScriptInterpreterPython::InitializeInterpreter (python_swig_init_callback,
@@ -153,6 +155,8 @@ ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_call
swig_run_script_keyword_thread,
swig_run_script_keyword_target,
swig_run_script_keyword_frame,
- swig_plugin_get);
+ swig_plugin_get,
+ swig_thread_plan_script,
+ swig_call_thread_plan);
#endif // #ifndef LLDB_DISABLE_PYTHON
}
diff --git a/lldb/source/Interpreter/ScriptInterpreterPython.cpp b/lldb/source/Interpreter/ScriptInterpreterPython.cpp
index 1b24fea7c21..945e869a794 100644
--- a/lldb/source/Interpreter/ScriptInterpreterPython.cpp
+++ b/lldb/source/Interpreter/ScriptInterpreterPython.cpp
@@ -37,6 +37,7 @@
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/PythonDataObjects.h"
#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
using namespace lldb;
using namespace lldb_private;
@@ -62,6 +63,8 @@ static ScriptInterpreter::SWIGPythonScriptKeyword_Thread g_swig_run_script_keywo
static ScriptInterpreter::SWIGPythonScriptKeyword_Target g_swig_run_script_keyword_target = nullptr;
static ScriptInterpreter::SWIGPythonScriptKeyword_Frame g_swig_run_script_keyword_frame = nullptr;
static ScriptInterpreter::SWIGPython_GetDynamicSetting g_swig_plugin_get = nullptr;
+static ScriptInterpreter::SWIGPythonCreateScriptedThreadPlan g_swig_thread_plan_script = nullptr;
+static ScriptInterpreter::SWIGPythonCallThreadPlan g_swig_call_thread_plan = nullptr;
static std::string
ReadPythonBacktrace (PyObject* py_backtrace);
@@ -1617,6 +1620,87 @@ ScriptInterpreterPython::OSPlugin_CreateThread (lldb::ScriptInterpreterObjectSP
}
lldb::ScriptInterpreterObjectSP
+ScriptInterpreterPython::CreateScriptedThreadPlan (const char *class_name,
+ lldb::ThreadPlanSP thread_plan_sp)
+{
+ if (class_name == nullptr || class_name[0] == '\0')
+ return lldb::ScriptInterpreterObjectSP();
+
+ if (!thread_plan_sp.get())
+ return lldb::ScriptInterpreterObjectSP();
+
+ Debugger &debugger = thread_plan_sp->GetTarget().GetDebugger();
+ ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter();
+ ScriptInterpreterPython *python_interpreter = static_cast<ScriptInterpreterPython *>(script_interpreter);
+
+ if (!script_interpreter)
+ return lldb::ScriptInterpreterObjectSP();
+
+ void* ret_val;
+
+ {
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+
+ ret_val = g_swig_thread_plan_script (class_name,
+ python_interpreter->m_dictionary_name.c_str(),
+ thread_plan_sp);
+ }
+
+ return MakeScriptObject(ret_val);
+}
+
+bool
+ScriptInterpreterPython::ScriptedThreadPlanExplainsStop (lldb::ScriptInterpreterObjectSP implementor_sp,
+ Event *event,
+ bool &script_error)
+{
+ bool explains_stop = true;
+ if (implementor_sp)
+ {
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ explains_stop = g_swig_call_thread_plan (implementor_sp->GetObject(), "explains_stop", event, script_error);
+ if (script_error)
+ return true;
+ }
+ return explains_stop;
+}
+
+bool
+ScriptInterpreterPython::ScriptedThreadPlanShouldStop (lldb::ScriptInterpreterObjectSP implementor_sp,
+ Event *event,
+ bool &script_error)
+{
+ bool should_stop = true;
+ if (implementor_sp)
+ {
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ should_stop = g_swig_call_thread_plan (implementor_sp->GetObject(), "should_stop", event, script_error);
+ if (script_error)
+ return true;
+ }
+ return should_stop;
+}
+
+lldb::StateType
+ScriptInterpreterPython::ScriptedThreadPlanGetRunState (lldb::ScriptInterpreterObjectSP implementor_sp,
+ bool &script_error)
+{
+ bool should_step = false;
+ if (implementor_sp)
+ {
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ should_step = g_swig_call_thread_plan (implementor_sp->GetObject(), "should_step", NULL, script_error);
+ if (script_error)
+ should_step = true;
+ }
+ if (should_step)
+ return lldb::eStateStepping;
+ else
+ return lldb::eStateRunning;
+}
+
+
+lldb::ScriptInterpreterObjectSP
ScriptInterpreterPython::LoadPluginModule (const FileSpec& file_spec,
lldb_private::Error& error)
{
@@ -2536,7 +2620,9 @@ ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback swig_init_callb
SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread,
SWIGPythonScriptKeyword_Target swig_run_script_keyword_target,
SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame,
- SWIGPython_GetDynamicSetting swig_plugin_get)
+ SWIGPython_GetDynamicSetting swig_plugin_get,
+ SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script,
+ SWIGPythonCallThreadPlan swig_call_thread_plan)
{
g_swig_init_callback = swig_init_callback;
g_swig_breakpoint_callback = swig_breakpoint_callback;
@@ -2558,6 +2644,8 @@ ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback swig_init_callb
g_swig_run_script_keyword_target = swig_run_script_keyword_target;
g_swig_run_script_keyword_frame = swig_run_script_keyword_frame;
g_swig_plugin_get = swig_plugin_get;
+ g_swig_thread_plan_script = swig_thread_plan_script;
+ g_swig_call_thread_plan = swig_call_thread_plan;
}
void
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
index cdd5b465479..fe364faefe3 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
@@ -89,10 +89,10 @@ AppleThreadPlanStepThroughObjCTrampoline::InitializeClangFunction ()
options.SetIgnoreBreakpoints(true);
options.SetStopOthers(m_stop_others);
m_thread.CalculateExecutionContext(exc_ctx);
- m_func_sp.reset(m_impl_function->GetThreadPlanToCallFunction (exc_ctx,
- m_args_addr,
- options,
- errors));
+ m_func_sp = m_impl_function->GetThreadPlanToCallFunction (exc_ctx,
+ m_args_addr,
+ options,
+ errors);
m_func_sp->SetOkayToDiscard(true);
m_thread.QueueThreadPlan (m_func_sp, false);
}
diff --git a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
index 4a94457466b..7db83ae5467 100644
--- a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
+++ b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
@@ -98,13 +98,11 @@ lldb_private::InferiorCallMmap (Process *process,
ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
lldb::addr_t args[] = { addr, length, prot_arg, flags_arg, fd, offset };
- ThreadPlanCallFunction *call_function_thread_plan
- = new ThreadPlanCallFunction (*thread,
- mmap_range.GetBaseAddress(),
- clang_void_ptr_type,
- args,
- options);
- lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan);
+ lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,
+ mmap_range.GetBaseAddress(),
+ clang_void_ptr_type,
+ args,
+ options));
if (call_plan_sp)
{
StreamFile error_strm;
@@ -241,13 +239,11 @@ lldb_private::InferiorCall (Process *process,
ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
- ThreadPlanCallFunction *call_function_thread_plan
- = new ThreadPlanCallFunction (*thread,
- *address,
- clang_void_ptr_type,
- llvm::ArrayRef<addr_t>(),
- options);
- lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan);
+ lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,
+ *address,
+ clang_void_ptr_type,
+ llvm::ArrayRef<addr_t>(),
+ options));
if (call_plan_sp)
{
StreamString error_strm;
diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp
index f8ea250639b..30e0ffb909b 100644
--- a/lldb/source/Target/Thread.cpp
+++ b/lldb/source/Target/Thread.cpp
@@ -32,6 +32,7 @@
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
#include "lldb/Target/ThreadPlanBase.h"
+#include "lldb/Target/ThreadPlanPython.h"
#include "lldb/Target/ThreadPlanStepInstruction.h"
#include "lldb/Target/ThreadPlanStepOut.h"
#include "lldb/Target/ThreadPlanStepOverBreakpoint.h"
@@ -652,17 +653,18 @@ Thread::SetupForResume ()
if (cur_plan->GetKind() != ThreadPlan::eKindStepOverBreakpoint)
{
- ThreadPlanStepOverBreakpoint *step_bp_plan = new ThreadPlanStepOverBreakpoint (*this);
- if (step_bp_plan)
+ ThreadPlanSP step_bp_plan_sp (new ThreadPlanStepOverBreakpoint (*this));
+ if (step_bp_plan_sp)
{
- ThreadPlanSP step_bp_plan_sp;
- step_bp_plan->SetPrivate (true);
+ ;
+ step_bp_plan_sp->SetPrivate (true);
if (GetCurrentPlan()->RunState() != eStateStepping)
{
+ ThreadPlanStepOverBreakpoint *step_bp_plan
+ = static_cast<ThreadPlanStepOverBreakpoint *>(step_bp_plan_sp.get());
step_bp_plan->SetAutoContinue(true);
}
- step_bp_plan_sp.reset (step_bp_plan);
QueueThreadPlan (step_bp_plan_sp, false);
}
}
@@ -1290,6 +1292,36 @@ Thread::SetTracer (lldb::ThreadPlanTracerSP &tracer_sp)
m_plan_stack[i]->SetThreadPlanTracer(tracer_sp);
}
+bool
+Thread::DiscardUserThreadPlansUpToIndex (uint32_t thread_index)
+{
+ // Count the user thread plans from the back end to get the number of the one we want
+ // to discard:
+
+ uint32_t idx = 0;
+ ThreadPlan *up_to_plan_ptr = nullptr;
+
+ for (ThreadPlanSP plan_sp : m_plan_stack)
+ {
+ if (plan_sp->GetPrivate())
+ continue;
+ if (idx == thread_index)
+ {
+ up_to_plan_ptr = plan_sp.get();
+ break;
+ }
+ else
+ idx++;
+ }
+
+ if (up_to_plan_ptr == nullptr)
+ return false;
+
+ DiscardThreadPlansUpToPlan(up_to_plan_ptr);
+ return true;
+}
+
+
void
Thread::DiscardThreadPlansUpToPlan (lldb::ThreadPlanSP &up_to_plan_sp)
{
@@ -1483,18 +1515,16 @@ Thread::QueueThreadPlanForStepInRange
LazyBool step_out_avoids_code_without_debug_info
)
{
- ThreadPlanSP thread_plan_sp;
- ThreadPlanStepInRange *plan = new ThreadPlanStepInRange (*this,
+ ThreadPlanSP thread_plan_sp (new ThreadPlanStepInRange (*this,
range,
addr_context,
stop_other_threads,
step_in_avoids_code_without_debug_info,
- step_out_avoids_code_without_debug_info);
+ step_out_avoids_code_without_debug_info));
+ ThreadPlanStepInRange *plan = static_cast<ThreadPlanStepInRange *>(thread_plan_sp.get());
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;
@@ -1546,17 +1576,18 @@ Thread::QueueThreadPlanForStepOutNoShouldStop
uint32_t frame_idx
)
{
- ThreadPlanStepOut *new_plan = new ThreadPlanStepOut (*this,
+ ThreadPlanSP thread_plan_sp(new ThreadPlanStepOut (*this,
addr_context,
first_insn,
stop_other_threads,
stop_vote,
run_vote,
frame_idx,
- eLazyBoolNo);
+ eLazyBoolNo));
+
+ ThreadPlanStepOut *new_plan = static_cast<ThreadPlanStepOut *>(thread_plan_sp.get());
new_plan->ClearShouldStopHereCallbacks();
- ThreadPlanSP thread_plan_sp(new_plan);
-
+
if (thread_plan_sp->ValidatePlan(NULL))
{
QueueThreadPlan (thread_plan_sp, abort_other_plans);
@@ -1602,61 +1633,105 @@ Thread::QueueThreadPlanForStepUntil (bool abort_other_plans,
}
+lldb::ThreadPlanSP
+Thread::QueueThreadPlanForStepScripted (bool abort_other_plans,
+ const char *class_name,
+ bool stop_other_threads)
+{
+ ThreadPlanSP thread_plan_sp (new ThreadPlanPython (*this, class_name));
+ QueueThreadPlan (thread_plan_sp, abort_other_plans);
+ // This seems a little funny, but I don't want to have to split up the constructor and the
+ // DidPush in the scripted plan, that seems annoying.
+ // That means the constructor has to be in DidPush.
+ // So I have to validate the plan AFTER pushing it, and then take it off again...
+ if (!thread_plan_sp->ValidatePlan(nullptr))
+ {
+ DiscardThreadPlansUpToPlan(thread_plan_sp);
+ return ThreadPlanSP();
+ }
+ else
+ return thread_plan_sp;
+
+}
+
uint32_t
Thread::GetIndexID () const
{
return m_index_id;
}
-void
-Thread::DumpThreadPlans (lldb_private::Stream *s) const
+static void
+PrintPlanElement (Stream *s, const ThreadPlanSP &plan, lldb::DescriptionLevel desc_level, int32_t elem_idx)
{
- uint32_t stack_size = m_plan_stack.size();
- int i;
- s->Indent();
- s->Printf ("Plan Stack for thread #%u: tid = 0x%4.4" PRIx64 ", stack_size = %d\n", GetIndexID(), GetID(), stack_size);
- for (i = stack_size - 1; i >= 0; i--)
- {
s->IndentMore();
s->Indent();
- s->Printf ("Element %d: ", i);
- m_plan_stack[i]->GetDescription (s, eDescriptionLevelFull);
+ s->Printf ("Element %d: ", elem_idx);
+ plan->GetDescription (s, desc_level);
s->EOL();
s->IndentLess();
+}
+
+static void
+PrintPlanStack (Stream *s, const std::vector<lldb::ThreadPlanSP> &plan_stack, lldb::DescriptionLevel desc_level, bool include_internal)
+{
+ int32_t print_idx = 0;
+ for (ThreadPlanSP plan_sp : plan_stack)
+ {
+ if (include_internal || !plan_sp->GetPrivate())
+ {
+ PrintPlanElement (s, plan_sp, desc_level, print_idx++);
+ }
}
+}
- stack_size = m_completed_plan_stack.size();
- if (stack_size > 0)
+void
+Thread::DumpThreadPlans (Stream *s,
+ lldb::DescriptionLevel desc_level,
+ bool include_internal,
+ bool ignore_boring_threads) const
+{
+ uint32_t stack_size = m_plan_stack.size();
+
+ if (ignore_boring_threads)
{
- s->Indent();
- s->Printf ("Completed Plan Stack: %d elements.\n", stack_size);
- for (i = stack_size - 1; i >= 0; i--)
+ uint32_t stack_size = m_plan_stack.size();
+ uint32_t completed_stack_size = m_completed_plan_stack.size();
+ uint32_t discarded_stack_size = m_discarded_plan_stack.size();
+ if (stack_size == 1 && completed_stack_size == 0 && discarded_stack_size == 0)
{
+ s->Printf ("thread #%u: tid = 0x%4.4" PRIx64 "\n", GetIndexID(), GetID());
s->IndentMore();
s->Indent();
- s->Printf ("Element %d: ", i);
- m_completed_plan_stack[i]->GetDescription (s, eDescriptionLevelFull);
- s->EOL();
+ s->Printf("No active thread plans\n");
s->IndentLess();
+ return;
}
}
+ s->Indent();
+ s->Printf ("thread #%u: tid = 0x%4.4" PRIx64 ":\n", GetIndexID(), GetID());
+ s->IndentMore();
+ s->Indent();
+ s->Printf ("Active plan stack:\n");
+ PrintPlanStack (s, m_plan_stack, desc_level, include_internal);
+
+ stack_size = m_completed_plan_stack.size();
+ if (stack_size > 0)
+ {
+ s->Indent();
+ s->Printf ("Completed Plan Stack:\n");
+ PrintPlanStack (s, m_completed_plan_stack, desc_level, include_internal);
+ }
+
stack_size = m_discarded_plan_stack.size();
if (stack_size > 0)
{
s->Indent();
- s->Printf ("Discarded Plan Stack: %d elements.\n", stack_size);
- for (i = stack_size - 1; i >= 0; i--)
- {
- s->IndentMore();
- s->Indent();
- s->Printf ("Element %d: ", i);
- m_discarded_plan_stack[i]->GetDescription (s, eDescriptionLevelFull);
- s->EOL();
- s->IndentLess();
- }
+ s->Printf ("Discarded Plan Stack:\n");
+ PrintPlanStack (s, m_discarded_plan_stack, desc_level, include_internal);
}
+ s->IndentLess();
}
TargetSP
diff --git a/lldb/source/Target/ThreadPlanPython.cpp b/lldb/source/Target/ThreadPlanPython.cpp
new file mode 100644
index 00000000000..e196d81c897
--- /dev/null
+++ b/lldb/source/Target/ThreadPlanPython.cpp
@@ -0,0 +1,192 @@
+//===-- ThreadPlan.cpp ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+#include "lldb/Target/ThreadPlan.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/State.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/ScriptInterpreter.h"
+#include "lldb/Interpreter/ScriptInterpreterPython.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanPython.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// ThreadPlanPython
+//----------------------------------------------------------------------
+
+ThreadPlanPython::ThreadPlanPython (Thread &thread, const char *class_name) :
+ ThreadPlan (ThreadPlan::eKindPython,
+ "Python based Thread Plan",
+ thread,
+ eVoteNoOpinion,
+ eVoteNoOpinion),
+ m_class_name (class_name)
+{
+ SetIsMasterPlan (true);
+ SetOkayToDiscard (true);
+ SetPrivate (false);
+}
+
+ThreadPlanPython::~ThreadPlanPython ()
+{
+ // FIXME, do I need to decrement the ref count on this implementation object to make it go away?
+}
+
+bool
+ThreadPlanPython::ValidatePlan (Stream *error)
+{
+ // I have to postpone setting up the implementation till after the constructor because I need to call
+ // shared_from_this, which you can't do in the constructor. So I'll do it here.
+ if (m_implementation_sp)
+ return true;
+ else
+ return false;
+}
+
+void
+ThreadPlanPython::DidPush()
+{
+ // We set up the script side in DidPush, so that it can push other plans in the constructor,
+ // and doesn't have to care about the details of DidPush.
+
+ if (!m_class_name.empty())
+ {
+ ScriptInterpreter *script_interp = m_thread.GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
+ if (script_interp)
+ {
+ m_implementation_sp = script_interp->CreateScriptedThreadPlan (m_class_name.c_str(), this->shared_from_this());
+ }
+ }
+}
+
+bool
+ThreadPlanPython::ShouldStop (Event *event_ptr)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
+ if (log)
+ log->Printf ("%s called on Python Thread Plan: %s )",
+ __PRETTY_FUNCTION__, m_class_name.c_str());
+
+ bool should_stop = true;
+ if (m_implementation_sp)
+ {
+ ScriptInterpreter *script_interp = m_thread.GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
+ if (script_interp)
+ {
+ bool script_error;
+ should_stop = script_interp->ScriptedThreadPlanShouldStop (m_implementation_sp, event_ptr, script_error);
+ if (script_error)
+ SetPlanComplete(false);
+ }
+ }
+ return should_stop;
+}
+
+bool
+ThreadPlanPython::DoPlanExplainsStop (Event *event_ptr)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
+ if (log)
+ log->Printf ("%s called on Python Thread Plan: %s )",
+ __PRETTY_FUNCTION__, m_class_name.c_str());
+
+ bool explains_stop = true;
+ if (m_implementation_sp)
+ {
+ ScriptInterpreter *script_interp = m_thread.GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
+ if (script_interp)
+ {
+ bool script_error;
+ explains_stop = script_interp->ScriptedThreadPlanExplainsStop (m_implementation_sp, event_ptr, script_error);
+ if (script_error)
+ SetPlanComplete(false);
+ }
+ }
+ return explains_stop;
+}
+
+bool
+ThreadPlanPython::MischiefManaged ()
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
+ if (log)
+ log->Printf ("%s called on Python Thread Plan: %s )",
+ __PRETTY_FUNCTION__, m_class_name.c_str());
+ bool mischief_managed = true;
+ if (m_implementation_sp)
+ {
+ // I don't really need mischief_managed, since it's simpler to just call SetPlanComplete in should_stop.
+ mischief_managed = IsPlanComplete();
+ if (mischief_managed)
+ m_implementation_sp.reset();
+ }
+ return mischief_managed;
+}
+
+lldb::StateType
+ThreadPlanPython::GetPlanRunState ()
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
+ if (log)
+ log->Printf ("%s called on Python Thread Plan: %s )",
+ __PRETTY_FUNCTION__,
+ m_class_name.c_str());
+ lldb::StateType run_state = eStateRunning;
+ if (m_implementation_sp)
+ {
+ ScriptInterpreter *script_interp = m_thread.GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
+ if (script_interp)
+ {
+ bool script_error;
+ run_state = script_interp->ScriptedThreadPlanGetRunState (m_implementation_sp, script_error);
+ }
+ }
+ return run_state;
+}
+
+// The ones below are not currently exported to Python.
+
+bool
+ThreadPlanPython::StopOthers ()
+{
+ // For now Python plans run all threads, but we should add some controls for this.
+ return false;
+}
+
+void
+ThreadPlanPython::GetDescription (Stream *s,
+ lldb::DescriptionLevel level)
+{
+ s->Printf ("Python thread plan implemented by class %s.", m_class_name.c_str());
+}
+
+bool
+ThreadPlanPython::WillStop ()
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
+ if (log)
+ log->Printf ("%s called on Python Thread Plan: %s )",
+ __PRETTY_FUNCTION__, m_class_name.c_str());
+ return true;
+}
diff --git a/lldb/source/Target/ThreadPlanStepInRange.cpp b/lldb/source/Target/ThreadPlanStepInRange.cpp
index 3e9abef6557..1e7b0458981 100644
--- a/lldb/source/Target/ThreadPlanStepInRange.cpp
+++ b/lldb/source/Target/ThreadPlanStepInRange.cpp
@@ -128,17 +128,31 @@ void
ThreadPlanStepInRange::GetDescription (Stream *s, lldb::DescriptionLevel level)
{
if (level == lldb::eDescriptionLevelBrief)
+ {
s->Printf("step in");
- else
+ return;
+ }
+
+ s->Printf ("Stepping in");
+ bool printed_line_info = false;
+ if (m_addr_context.line_entry.IsValid())
+ {
+ s->Printf (" through line ");
+ m_addr_context.line_entry.DumpStopContext (s, false);
+ printed_line_info = true;
+ }
+
+ const char *step_into_target = m_step_into_target.AsCString();
+ if (step_into_target && step_into_target[0] != '\0')
+ s->Printf (" targeting %s", m_step_into_target.AsCString());
+
+ if (!printed_line_info || level == eDescriptionLevelVerbose)
{
- s->Printf ("Stepping through range (stepping into functions): ");
+ s->Printf (" using ranges:");
DumpRanges(s);
- const char *step_into_target = m_step_into_target.AsCString();
- if (step_into_target && step_into_target[0] != '\0')
- s->Printf (" targeting %s.", m_step_into_target.AsCString());
- else
- s->PutChar('.');
}
+
+ s->PutChar('.');
}
bool
@@ -303,6 +317,7 @@ ThreadPlanStepInRange::ShouldStop (Event *event_ptr)
else
{
m_no_more_plans = false;
+ m_sub_plan_sp->SetPrivate(true);
return false;
}
}
diff --git a/lldb/source/Target/ThreadPlanStepOut.cpp b/lldb/source/Target/ThreadPlanStepOut.cpp
index b62f557319a..0ded99b3091 100644
--- a/lldb/source/Target/ThreadPlanStepOut.cpp
+++ b/lldb/source/Target/ThreadPlanStepOut.cpp
@@ -54,7 +54,6 @@ ThreadPlanStepOut::ThreadPlanStepOut
m_return_addr (LLDB_INVALID_ADDRESS),
m_stop_others (stop_others),
m_immediate_step_from_function(NULL)
-
{
SetFlagsToDefault();
SetupAvoidNoDebug(step_out_avoids_code_without_debug_info);
@@ -90,6 +89,7 @@ ThreadPlanStepOut::ThreadPlanStepOut
frame_idx - 1,
eLazyBoolNo));
static_cast<ThreadPlanStepOut *>(m_step_out_to_inline_plan_sp.get())->SetShouldStopHereCallbacks(nullptr, nullptr);
+ m_step_out_to_inline_plan_sp->SetPrivate(true);
}
else
{
@@ -177,10 +177,34 @@ ThreadPlanStepOut::GetDescription (Stream *s, lldb::DescriptionLevel level)
else if (m_step_through_inline_plan_sp)
s->Printf ("Stepping out by stepping through inlined function.");
else
- s->Printf ("Stepping out from address 0x%" PRIx64 " to return address 0x%" PRIx64 " using breakpoint site %d",
- (uint64_t)m_step_from_insn,
- (uint64_t)m_return_addr,
- m_return_bp_id);
+ {
+ s->Printf ("Stepping out from ");
+ Address tmp_address;
+ if (tmp_address.SetLoadAddress (m_step_from_insn, &GetTarget()))
+ {
+ tmp_address.Dump(s, &GetThread(), Address::DumpStyleResolvedDescription, Address::DumpStyleLoadAddress);
+ }
+ else
+ {
+ s->Printf ("address 0x%" PRIx64 "", (uint64_t)m_step_from_insn);
+ }
+
+ // FIXME: find some useful way to present the m_return_id, since there may be multiple copies of the
+ // same function on the stack.
+
+ s->Printf ("returning to frame at ");
+ if (tmp_address.SetLoadAddress (m_return_addr, &GetTarget()))
+ {
+ tmp_address.Dump(s, &GetThread(), Address::DumpStyleResolvedDescription, Address::DumpStyleLoadAddress);
+ }
+ else
+ {
+ s->Printf ("address 0x%" PRIx64 "", (uint64_t)m_return_addr);
+ }
+
+ if (level == eDescriptionLevelVerbose)
+ s->Printf(" using breakpoint site %d", m_return_bp_id);
+ }
}
}
@@ -474,11 +498,16 @@ ThreadPlanStepOut::QueueInlinedStepPlan (bool queue_now)
inlined_sc.target_sp = GetTarget().shared_from_this();
RunMode run_mode = m_stop_others ? lldb::eOnlyThisThread : lldb::eAllThreads;
const LazyBool avoid_no_debug = eLazyBoolNo;
- ThreadPlanStepOverRange *step_through_inline_plan_ptr = new ThreadPlanStepOverRange(m_thread,
- inline_range,
- inlined_sc,
- run_mode,
- avoid_no_debug);
+
+ m_step_through_inline_plan_sp.reset (new ThreadPlanStepOverRange(m_thread,
+ inline_range,
+ inlined_sc,
+ run_mode,
+ avoid_no_debug));
+ ThreadPlanStepOverRange *step_through_inline_plan_ptr
+ = static_cast<ThreadPlanStepOverRange *>(m_step_through_inline_plan_sp.get());
+ m_step_through_inline_plan_sp->SetPrivate(true);
+
step_through_inline_plan_ptr->SetOkayToDiscard(true);
StreamString errors;
if (!step_through_inline_plan_ptr->ValidatePlan(&errors))
@@ -493,7 +522,7 @@ ThreadPlanStepOut::QueueInlinedStepPlan (bool queue_now)
if (inlined_block->GetRangeAtIndex (i, inline_range))
step_through_inline_plan_ptr->AddRange (inline_range);
}
- m_step_through_inline_plan_sp.reset (step_through_inline_plan_ptr);
+
if (queue_now)
m_thread.QueueThreadPlan (m_step_through_inline_plan_sp, false);
return true;
diff --git a/lldb/source/Target/ThreadPlanStepOverRange.cpp b/lldb/source/Target/ThreadPlanStepOverRange.cpp
index a4f3743346e..a6d65e4d811 100644
--- a/lldb/source/Target/ThreadPlanStepOverRange.cpp
+++ b/lldb/source/Target/ThreadPlanStepOverRange.cpp
@@ -62,12 +62,26 @@ void
ThreadPlanStepOverRange::GetDescription (Stream *s, lldb::DescriptionLevel level)
{
if (level == lldb::eDescriptionLevelBrief)
+ {
s->Printf("step over");
- else
+ return;
+ }
+ s->Printf ("Stepping over");
+ bool printed_line_info = false;
+ if (m_addr_context.line_entry.IsValid())
+ {
+ s->Printf (" line ");
+ m_addr_context.line_entry.DumpStopContext (s, false);
+ printed_line_info = true;
+ }
+
+ if (!printed_line_info || level == eDescriptionLevelVerbose)
{
- s->Printf ("stepping through range (stepping over functions): ");
- DumpRanges(s);
+ s->Printf (" using ranges: ");
+ DumpRanges(s);
}
+
+ s->PutChar('.');
}
void
@@ -317,11 +331,15 @@ ThreadPlanStepOverRange::ShouldStop (Event *event_ptr)
{
new_plan_sp = CheckShouldStopHereAndQueueStepOut (frame_order);
}
-
+
if (!new_plan_sp)
m_no_more_plans = true;
else
+ {
+ // Any new plan will be an implementation plan, so mark it private:
+ new_plan_sp->SetPrivate(true);
m_no_more_plans = false;
+ }
if (!new_plan_sp)
{
diff --git a/lldb/source/Target/ThreadPlanStepRange.cpp b/lldb/source/Target/ThreadPlanStepRange.cpp
index 82ca59fbca3..adc515cebc0 100644
--- a/lldb/source/Target/ThreadPlanStepRange.cpp
+++ b/lldb/source/Target/ThreadPlanStepRange.cpp
@@ -44,7 +44,8 @@ ThreadPlanStepRange::ThreadPlanStepRange (ThreadPlanKind kind,
Thread &thread,
const AddressRange &range,
const SymbolContext &addr_context,
- lldb::RunMode stop_others) :
+ lldb::RunMode stop_others,
+ bool given_ranges_only) :
ThreadPlan (kind, name, thread, eVoteNoOpinion, eVoteNoOpinion),
m_addr_context (addr_context),
m_address_ranges (),
@@ -53,7 +54,8 @@ ThreadPlanStepRange::ThreadPlanStepRange (ThreadPlanKind kind,
m_parent_stack_id(),
m_no_more_plans (false),
m_first_run_event (true),
- m_use_fast_step(false)
+ m_use_fast_step(false),
+ m_given_ranges_only (given_ranges_only)
{
m_use_fast_step = GetTarget().GetUseFastStepping();
AddRange(range);
@@ -149,7 +151,7 @@ ThreadPlanStepRange::InRange ()
break;
}
- if (!ret_value)
+ if (!ret_value && !m_given_ranges_only)
{
// See if we've just stepped to another part of the same line number...
StackFrame *frame = m_thread.GetStackFrameAtIndex(0).get();
OpenPOWER on IntegriCloud