aboutsummaryrefslogtreecommitdiffstats
path: root/include/lldb/Target
diff options
context:
space:
mode:
authorEd Maste <emaste@FreeBSD.org>2013-08-23 17:46:38 +0000
committerEd Maste <emaste@FreeBSD.org>2013-08-23 17:46:38 +0000
commitf034231a6a1fd5d6395206c1651de8cd9402cca3 (patch)
treef561dabc721ad515599172c16da3a4400b7f4aec /include/lldb/Target
downloadsrc-f034231a6a1fd5d6395206c1651de8cd9402cca3.tar.gz
src-f034231a6a1fd5d6395206c1651de8cd9402cca3.zip
Import lldb as of SVN r188801
(A number of files not required for the FreeBSD build have been removed.) Sponsored by: DARPA, AFRL
Notes
Notes: svn path=/vendor/lldb/dist/; revision=254721
Diffstat (limited to 'include/lldb/Target')
-rw-r--r--include/lldb/Target/ABI.h137
-rw-r--r--include/lldb/Target/CPPLanguageRuntime.h158
-rw-r--r--include/lldb/Target/DynamicLoader.h239
-rw-r--r--include/lldb/Target/ExecutionContext.h778
-rw-r--r--include/lldb/Target/ExecutionContextScope.h74
-rw-r--r--include/lldb/Target/LanguageRuntime.h113
-rw-r--r--include/lldb/Target/Memory.h196
-rw-r--r--include/lldb/Target/ObjCLanguageRuntime.h604
-rw-r--r--include/lldb/Target/OperatingSystem.h101
-rw-r--r--include/lldb/Target/PathMappingList.h171
-rw-r--r--include/lldb/Target/Platform.h755
-rw-r--r--include/lldb/Target/Process.h3786
-rw-r--r--include/lldb/Target/RegisterContext.h213
-rw-r--r--include/lldb/Target/SectionLoadList.h89
-rw-r--r--include/lldb/Target/StackFrame.h207
-rw-r--r--include/lldb/Target/StackFrameList.h157
-rw-r--r--include/lldb/Target/StackID.h149
-rw-r--r--include/lldb/Target/StopInfo.h227
-rw-r--r--include/lldb/Target/Target.h1223
-rw-r--r--include/lldb/Target/TargetList.h239
-rw-r--r--include/lldb/Target/Thread.h1067
-rw-r--r--include/lldb/Target/ThreadList.h163
-rw-r--r--include/lldb/Target/ThreadPlan.h658
-rw-r--r--include/lldb/Target/ThreadPlanBase.h71
-rw-r--r--include/lldb/Target/ThreadPlanCallFunction.h193
-rw-r--r--include/lldb/Target/ThreadPlanCallUserExpression.h65
-rw-r--r--include/lldb/Target/ThreadPlanRunToAddress.h85
-rw-r--r--include/lldb/Target/ThreadPlanShouldStopHere.h94
-rw-r--r--include/lldb/Target/ThreadPlanStepInRange.h110
-rw-r--r--include/lldb/Target/ThreadPlanStepInstruction.h64
-rw-r--r--include/lldb/Target/ThreadPlanStepOut.h90
-rw-r--r--include/lldb/Target/ThreadPlanStepOverBreakpoint.h57
-rw-r--r--include/lldb/Target/ThreadPlanStepOverRange.h52
-rw-r--r--include/lldb/Target/ThreadPlanStepRange.h94
-rw-r--r--include/lldb/Target/ThreadPlanStepThrough.h71
-rw-r--r--include/lldb/Target/ThreadPlanStepUntil.h80
-rw-r--r--include/lldb/Target/ThreadPlanTracer.h131
-rw-r--r--include/lldb/Target/ThreadSpec.h155
-rw-r--r--include/lldb/Target/UnixSignals.h144
-rw-r--r--include/lldb/Target/Unwind.h120
-rw-r--r--include/lldb/Target/UnwindAssembly.h58
41 files changed, 13238 insertions, 0 deletions
diff --git a/include/lldb/Target/ABI.h b/include/lldb/Target/ABI.h
new file mode 100644
index 000000000000..16f8ee7fc7d7
--- /dev/null
+++ b/include/lldb/Target/ABI.h
@@ -0,0 +1,137 @@
+//===-- ABI.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_ABI_h_
+#define liblldb_ABI_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Error.h"
+#include "lldb/Core/PluginInterface.h"
+#include "lldb/lldb-private.h"
+
+namespace lldb_private {
+
+class ABI :
+ public PluginInterface
+{
+public:
+ virtual
+ ~ABI();
+
+ virtual size_t
+ GetRedZoneSize () const = 0;
+
+ virtual bool
+ PrepareTrivialCall (Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t functionAddress,
+ lldb::addr_t returnAddress,
+ lldb::addr_t *arg1_ptr = NULL,
+ lldb::addr_t *arg2_ptr = NULL,
+ lldb::addr_t *arg3_ptr = NULL,
+ lldb::addr_t *arg4_ptr = NULL,
+ lldb::addr_t *arg5_ptr = NULL,
+ lldb::addr_t *arg6_ptr = NULL) const = 0;
+
+ virtual bool
+ GetArgumentValues (Thread &thread,
+ ValueList &values) const = 0;
+
+ lldb::ValueObjectSP
+ GetReturnValueObject (Thread &thread,
+ ClangASTType &type,
+ bool persistent = true) const;
+
+ // Set the Return value object in the current frame as though a function with
+ virtual Error
+ SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) = 0;
+
+protected:
+ // This is the method the ABI will call to actually calculate the return value.
+ // Don't put it in a persistant value object, that will be done by the ABI::GetReturnValueObject.
+ virtual lldb::ValueObjectSP
+ GetReturnValueObjectImpl (Thread &thread,
+ ClangASTType &type) const = 0;
+public:
+ virtual bool
+ CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) = 0;
+
+ virtual bool
+ CreateDefaultUnwindPlan (UnwindPlan &unwind_plan) = 0;
+
+ virtual bool
+ RegisterIsVolatile (const RegisterInfo *reg_info) = 0;
+
+ // Should return true if your ABI uses frames when doing stack backtraces. This
+ // means a frame pointer is used that points to the previous stack frame in some
+ // way or another.
+ virtual bool
+ StackUsesFrames () = 0;
+
+ // Should take a look at a call frame address (CFA) which is just the stack
+ // pointer value upon entry to a function. ABIs usually impose alignment
+ // restrictions (4, 8 or 16 byte aligned), and zero is usually not allowed.
+ // This function should return true if "cfa" is valid call frame address for
+ // the ABI, and false otherwise. This is used by the generic stack frame unwinding
+ // code to help determine when a stack ends.
+ virtual bool
+ CallFrameAddressIsValid (lldb::addr_t cfa) = 0;
+
+ // Validates a possible PC value and returns true if an opcode can be at "pc".
+ virtual bool
+ CodeAddressIsValid (lldb::addr_t pc) = 0;
+
+ virtual lldb::addr_t
+ FixCodeAddress (lldb::addr_t pc)
+ {
+ // Some targets might use bits in a code address to indicate
+ // a mode switch. ARM uses bit zero to signify a code address is
+ // thumb, so any ARM ABI plug-ins would strip those bits.
+ return pc;
+ }
+
+ virtual const RegisterInfo *
+ GetRegisterInfoArray (uint32_t &count) = 0;
+
+ // Some architectures (e.g. x86) will push the return address on the stack and decrement
+ // the stack pointer when making a function call. This means that every stack frame will
+ // have a unique CFA.
+ // Other architectures (e.g. arm) pass the return address in a register so it is possible
+ // to have a frame on a backtrace that does not push anything on the stack or change the
+ // CFA.
+ virtual bool
+ FunctionCallsChangeCFA () = 0;
+
+
+ bool
+ GetRegisterInfoByName (const ConstString &name, RegisterInfo &info);
+
+ bool
+ GetRegisterInfoByKind (lldb::RegisterKind reg_kind,
+ uint32_t reg_num,
+ RegisterInfo &info);
+
+ static lldb::ABISP
+ FindPlugin (const ArchSpec &arch);
+
+protected:
+ //------------------------------------------------------------------
+ // Classes that inherit from ABI can see and modify these
+ //------------------------------------------------------------------
+ ABI();
+private:
+ DISALLOW_COPY_AND_ASSIGN (ABI);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ABI_h_
diff --git a/include/lldb/Target/CPPLanguageRuntime.h b/include/lldb/Target/CPPLanguageRuntime.h
new file mode 100644
index 000000000000..98a4ab88cb25
--- /dev/null
+++ b/include/lldb/Target/CPPLanguageRuntime.h
@@ -0,0 +1,158 @@
+//===-- CPPLanguageRuntime.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_CPPLanguageRuntime_h_
+#define liblldb_CPPLanguageRuntime_h_
+
+// C Includes
+// C++ Includes
+#include <vector>
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/PluginInterface.h"
+#include "lldb/lldb-private.h"
+#include "lldb/Target/LanguageRuntime.h"
+
+namespace lldb_private {
+
+class CPPLanguageRuntime :
+ public LanguageRuntime
+{
+public:
+
+ class MethodName
+ {
+ public:
+ enum Type
+ {
+ eTypeInvalid,
+ eTypeUnknownMethod,
+ eTypeClassMethod,
+ eTypeInstanceMethod
+ };
+
+ MethodName () :
+ m_full(),
+ m_basename(),
+ m_context(),
+ m_arguments(),
+ m_qualifiers(),
+ m_type (eTypeInvalid),
+ m_parsed (false),
+ m_parse_error (false)
+ {
+ }
+
+ MethodName (const ConstString &s) :
+ m_full(s),
+ m_basename(),
+ m_context(),
+ m_arguments(),
+ m_qualifiers(),
+ m_type (eTypeInvalid),
+ m_parsed (false),
+ m_parse_error (false)
+ {
+ }
+
+ void
+ Clear();
+
+ bool
+ IsValid () const
+ {
+ if (m_parse_error)
+ return false;
+ if (m_type == eTypeInvalid)
+ return false;
+ return (bool)m_full;
+ }
+
+ Type
+ GetType () const
+ {
+ return m_type;
+ }
+
+ const ConstString &
+ GetFullName () const
+ {
+ return m_full;
+ }
+
+ llvm::StringRef
+ GetBasename ();
+
+ llvm::StringRef
+ GetContext ();
+
+ llvm::StringRef
+ GetArguments ();
+
+ llvm::StringRef
+ GetQualifiers ();
+
+ protected:
+ void
+ Parse();
+
+ ConstString m_full; // Full name: "lldb::SBTarget::GetBreakpointAtIndex(unsigned int) const"
+ llvm::StringRef m_basename; // Basename: "GetBreakpointAtIndex"
+ llvm::StringRef m_context; // Decl context: "lldb::SBTarget"
+ llvm::StringRef m_arguments; // Arguments: "(unsigned int)"
+ llvm::StringRef m_qualifiers; // Qualifiers: "const"
+ Type m_type;
+ bool m_parsed;
+ bool m_parse_error;
+ };
+
+ virtual
+ ~CPPLanguageRuntime();
+
+ virtual lldb::LanguageType
+ GetLanguageType () const
+ {
+ return lldb::eLanguageTypeC_plus_plus;
+ }
+
+ virtual bool
+ IsVTableName (const char *name) = 0;
+
+ virtual bool
+ GetObjectDescription (Stream &str, ValueObject &object);
+
+ virtual bool
+ GetObjectDescription (Stream &str, Value &value, ExecutionContextScope *exe_scope);
+
+ static bool
+ IsCPPMangledName(const char *name);
+
+ static bool
+ StripNamespacesFromVariableName (const char *name, const char *&base_name_start, const char *&base_name_end);
+
+ // in some cases, compilers will output different names for one same type. when tht happens, it might be impossible
+ // to construct SBType objects for a valid type, because the name that is available is not the same as the name that
+ // can be used as a search key in FindTypes(). the equivalents map here is meant to return possible alternative names
+ // for a type through which a search can be conducted. Currently, this is only enabled for C++ but can be extended
+ // to ObjC or other languages if necessary
+ static uint32_t
+ FindEquivalentNames(ConstString type_name, std::vector<ConstString>& equivalents);
+
+protected:
+ //------------------------------------------------------------------
+ // Classes that inherit from CPPLanguageRuntime can see and modify these
+ //------------------------------------------------------------------
+ CPPLanguageRuntime(Process *process);
+private:
+ DISALLOW_COPY_AND_ASSIGN (CPPLanguageRuntime);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CPPLanguageRuntime_h_
diff --git a/include/lldb/Target/DynamicLoader.h b/include/lldb/Target/DynamicLoader.h
new file mode 100644
index 000000000000..6b76e5891ae8
--- /dev/null
+++ b/include/lldb/Target/DynamicLoader.h
@@ -0,0 +1,239 @@
+//===-- DynamicLoader.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_DynamicLoader_h_
+#define liblldb_DynamicLoader_h_
+
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/PluginInterface.h"
+
+namespace lldb_private {
+
+//----------------------------------------------------------------------
+/// @class DynamicLoader DynamicLoader.h "lldb/Target/DynamicLoader.h"
+/// @brief A plug-in interface definition class for dynamic loaders.
+///
+/// Dynamic loader plug-ins track image (shared library) loading and
+/// unloading. The class is initialized given a live process that is
+/// halted at its entry point or just after attaching.
+///
+/// Dynamic loader plug-ins can track the process by registering
+/// callbacks using the:
+/// Process::RegisterNotificationCallbacks (const Notifications&)
+/// function.
+///
+/// Breakpoints can also be set in the process which can register
+/// functions that get called using:
+/// Process::BreakpointSetCallback (lldb::user_id_t, BreakpointHitCallback, void *).
+/// These breakpoint callbacks return a boolean value that indicates if
+/// the process should continue or halt and should return the global
+/// setting for this using:
+/// DynamicLoader::StopWhenImagesChange() const.
+//----------------------------------------------------------------------
+class DynamicLoader :
+ public PluginInterface
+{
+public:
+ //------------------------------------------------------------------
+ /// Find a dynamic loader plugin for a given process.
+ ///
+ /// Scans the installed DynamicLoader plug-ins and tries to find
+ /// an instance that can be used to track image changes in \a
+ /// process.
+ ///
+ /// @param[in] process
+ /// The process for which to try and locate a dynamic loader
+ /// plug-in instance.
+ ///
+ /// @param[in] plugin_name
+ /// An optional name of a specific dynamic loader plug-in that
+ /// should be used. If NULL, pick the best plug-in.
+ //------------------------------------------------------------------
+ static DynamicLoader*
+ FindPlugin (Process *process, const char *plugin_name);
+
+ //------------------------------------------------------------------
+ /// Construct with a process.
+ //------------------------------------------------------------------
+ DynamicLoader (Process *process);
+
+ //------------------------------------------------------------------
+ /// Destructor.
+ ///
+ /// The destructor is virtual since this class is designed to be
+ /// inherited from by the plug-in instance.
+ //------------------------------------------------------------------
+ virtual
+ ~DynamicLoader ();
+
+ //------------------------------------------------------------------
+ /// Called after attaching a process.
+ ///
+ /// Allow DynamicLoader plug-ins to execute some code after
+ /// attaching to a process.
+ //------------------------------------------------------------------
+ virtual void
+ DidAttach () = 0;
+
+ //------------------------------------------------------------------
+ /// Called after launching a process.
+ ///
+ /// Allow DynamicLoader plug-ins to execute some code after
+ /// the process has stopped for the first time on launch.
+ //------------------------------------------------------------------
+ virtual void
+ DidLaunch () = 0;
+
+
+ //------------------------------------------------------------------
+ /// Helper function that can be used to detect when a process has
+ /// called exec and is now a new and different process. This can
+ /// be called when necessary to try and detect the exec. The process
+ /// might be able to answer this question, but sometimes it might
+ /// not be able and the dynamic loader often knows what the program
+ /// entry point is. So the process and the dynamic loader can work
+ /// together to detect this.
+ //------------------------------------------------------------------
+ virtual bool
+ ProcessDidExec ()
+ {
+ return false;
+ }
+ //------------------------------------------------------------------
+ /// Get whether the process should stop when images change.
+ ///
+ /// When images (executables and shared libraries) get loaded or
+ /// unloaded, often debug sessions will want to try and resolve or
+ /// unresolve breakpoints that are set in these images. Any
+ /// breakpoints set by DynamicLoader plug-in instances should
+ /// return this value to ensure consistent debug session behaviour.
+ ///
+ /// @return
+ /// Returns \b true if the process should stop when images
+ /// change, \b false if the process should resume.
+ //------------------------------------------------------------------
+ bool
+ GetStopWhenImagesChange () const;
+
+ //------------------------------------------------------------------
+ /// Set whether the process should stop when images change.
+ ///
+ /// When images (executables and shared libraries) get loaded or
+ /// unloaded, often debug sessions will want to try and resolve or
+ /// unresolve breakpoints that are set in these images. The default
+ /// is set so that the process stops when images change, but this
+ /// can be overridden using this function callback.
+ ///
+ /// @param[in] stop
+ /// Boolean value that indicates whether the process should stop
+ /// when images change.
+ //------------------------------------------------------------------
+ void
+ SetStopWhenImagesChange (bool stop);
+
+ //------------------------------------------------------------------
+ /// Provides a plan to step through the dynamic loader trampoline
+ /// for the current state of \a thread.
+ ///
+ ///
+ /// @param[in] stop_others
+ /// Whether the plan should be set to stop other threads.
+ ///
+ /// @return
+ /// A pointer to the plan (caller owned) or NULL if we are not at such
+ /// a trampoline.
+ //------------------------------------------------------------------
+ virtual lldb::ThreadPlanSP
+ GetStepThroughTrampolinePlan (Thread &thread, bool stop_others) = 0;
+
+
+ //------------------------------------------------------------------
+ /// Some dynamic loaders provide features where there are a group of symbols "equivalent to"
+ /// a given symbol one of which will be chosen when the symbol is bound. If you want to
+ /// set a breakpoint on one of these symbols, you really need to set it on all the
+ /// equivalent symbols.
+ ///
+ ///
+ /// @param[in] original_symbol
+ /// The symbol for which we are finding equivalences.
+ ///
+ /// @param[in] module_list
+ /// The set of modules in which to search.
+ ///
+ /// @param[out] equivalent_symbols
+ /// The equivalent symbol list - any equivalent symbols found are appended to this list.
+ ///
+ /// @return
+ /// Number of equivalent symbols found.
+ //------------------------------------------------------------------
+ virtual size_t
+ FindEquivalentSymbols (Symbol *original_symbol, ModuleList &module_list, SymbolContextList &equivalent_symbols)
+ {
+ return 0;
+ }
+
+ //------------------------------------------------------------------
+ /// Ask if it is ok to try and load or unload an shared library
+ /// (image).
+ ///
+ /// The dynamic loader often knows when it would be ok to try and
+ /// load or unload a shared library. This function call allows the
+ /// dynamic loader plug-ins to check any current dyld state to make
+ /// sure it is an ok time to load a shared library.
+ ///
+ /// @return
+ /// \b true if it is currently ok to try and load a shared
+ /// library into the process, \b false otherwise.
+ //------------------------------------------------------------------
+ virtual Error
+ CanLoadImage () = 0;
+
+ //------------------------------------------------------------------
+ /// Ask if the eh_frame information for the given SymbolContext should
+ /// be relied on even when it's the first frame in a stack unwind.
+ ///
+ /// The CFI instructions from the eh_frame section are normally only
+ /// valid at call sites -- places where a program could throw an
+ /// exception and need to unwind out. But some Modules may be known
+ /// to the system as having reliable eh_frame information at all call
+ /// sites. This would be the case if the Module's contents are largely
+ /// hand-written assembly with hand-written eh_frame information.
+ /// Normally when unwinding from a function at the beginning of a stack
+ /// unwind lldb will examine the assembly instructions to understand
+ /// how the stack frame is set up and where saved registers are stored.
+ /// But with hand-written assembly this is not reliable enough -- we need
+ /// to consult those function's hand-written eh_frame information.
+ ///
+ /// @return
+ /// \b True if the symbol context should use eh_frame instructions
+ /// unconditionally when unwinding from this frame. Else \b false,
+ /// the normal lldb unwind behavior of only using eh_frame when the
+ /// function appears in the middle of the stack.
+ //------------------------------------------------------------------
+ virtual bool
+ AlwaysRelyOnEHUnwindInfo (SymbolContext &sym_ctx)
+ {
+ return false;
+ }
+
+protected:
+ //------------------------------------------------------------------
+ // Member variables.
+ //------------------------------------------------------------------
+ Process* m_process; ///< The process that this dynamic loader plug-in is tracking.
+private:
+ DISALLOW_COPY_AND_ASSIGN (DynamicLoader);
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_DynamicLoader_h_
diff --git a/include/lldb/Target/ExecutionContext.h b/include/lldb/Target/ExecutionContext.h
new file mode 100644
index 000000000000..de5fe14934a7
--- /dev/null
+++ b/include/lldb/Target/ExecutionContext.h
@@ -0,0 +1,778 @@
+//===-- ExecutionContext.h --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// Execution context objects refer to objects in the execution of the
+/// program that is being debugged. The consist of one or more of the
+/// following objects: target, process, thread, and frame. Many objects
+/// in the debugger need to track different executions contexts. For
+/// example, a local function variable might have an execution context
+/// that refers to a stack frame. A global or static variable might
+/// refer to a target since a stack frame isn't required in order to
+/// evaluate a global or static variable (a process isn't necessarily
+/// needed for a global variable since we might be able to read the
+/// variable value from a data section in one of the object files in
+/// a target). There are two types of objects that hold onto execution
+/// contexts: ExecutionContextRef and ExecutionContext. Both of these
+/// objects are deascribed below.
+///
+/// Not all objects in an ExectionContext objects will be valid. If you want
+/// to refer stronly (ExectionContext) or weakly (ExectionContextRef) to
+/// a process, then only the process and target references will be valid.
+/// For threads, only the thread, process and target references will be
+/// filled in. For frames, all of the objects will be filled in.
+///
+/// These classes are designed to be used as baton objects that get passed
+/// to a wide variety of functions that require execution contexts.
+//===----------------------------------------------------------------------===//
+
+
+
+#ifndef liblldb_ExecutionContext_h_
+#define liblldb_ExecutionContext_h_
+
+#include "lldb/lldb-private.h"
+#include "lldb/Target/StackID.h"
+#include "lldb/Host/Mutex.h"
+
+namespace lldb_private {
+
+//----------------------------------------------------------------------
+/// @class ExecutionContextRef ExecutionContext.h "lldb/Target/ExecutionContext.h"
+/// @brief A class that holds a weak reference to an execution context.
+///
+/// ExecutionContextRef objects are designed to hold onto an execution
+/// context that might change over time. For example, if an object wants
+/// to refer to a stack frame, it should hold onto an ExecutionContextRef
+/// to a frame object. The backing object that represents the stack frame
+/// might change over time and instaces of this object can track the logical
+/// object that refers to a frame even if it does change.
+///
+/// These objects also don't keep execution objects around longer than they
+/// should since they use weak pointers. For example if an object refers
+/// to a stack frame and a stack frame is no longer in a thread, then a
+/// ExecutionContextRef object that refers to that frame will not be able
+/// to get a shared pointer to those objects since they are no longer around.
+///
+/// ExecutionContextRef objects can also be used as objects in classes
+/// that want to track a "previous execution context". Since the weak
+/// references to the execution objects (target, process, thread and frame)
+/// don't keep these objects around, they are safe to keep around.
+///
+/// The general rule of thumb is all long lived objects that want to
+/// refer to execution contexts should use ExecutionContextRef objcts.
+/// The ExecutionContext class is used to temporarily get shared
+/// pointers to any execution context objects that are still around
+/// so they are guaranteed to exist during a function that requires the
+/// objects. ExecutionContext objects should NOT be used for long term
+/// storage since they will keep objects alive with extra shared pointer
+/// references to these objects.
+//----------------------------------------------------------------------
+class ExecutionContextRef
+{
+public:
+ //------------------------------------------------------------------
+ /// Default Constructor.
+ //------------------------------------------------------------------
+ ExecutionContextRef();
+
+ //------------------------------------------------------------------
+ /// Copy Constructor.
+ //------------------------------------------------------------------
+ ExecutionContextRef (const ExecutionContextRef &rhs);
+
+ //------------------------------------------------------------------
+ /// Construct using an ExecutionContext object that might be NULL.
+ ///
+ /// If \a exe_ctx_ptr is valid, then make weak references to any
+ /// valid objects in the ExecutionContext, othewise no weak
+ /// references to any execution context objects will be made.
+ //------------------------------------------------------------------
+ ExecutionContextRef (const ExecutionContext *exe_ctx_ptr);
+
+ //------------------------------------------------------------------
+ /// Construct using an ExecutionContext object.
+ ///
+ /// Make weak references to any valid objects in the ExecutionContext.
+ //------------------------------------------------------------------
+ ExecutionContextRef (const ExecutionContext &exe_ctx);
+
+ //------------------------------------------------------------------
+ /// Assignment operator
+ ///
+ /// Copy all weak refernces in \a rhs.
+ //------------------------------------------------------------------
+ ExecutionContextRef &
+ operator =(const ExecutionContextRef &rhs);
+
+ //------------------------------------------------------------------
+ /// Assignment operator from a ExecutionContext
+ ///
+ /// Make weak refernces to any stringly referenced objects in \a exe_ctx.
+ //------------------------------------------------------------------
+ ExecutionContextRef &
+ operator =(const ExecutionContext &exe_ctx);
+
+ //------------------------------------------------------------------
+ /// Construct using the target and all the selected items inside of it
+ /// (the process and its selected thread, and the thread's selected
+ /// frame). If there is no selected thread, default to the first thread
+ /// If there is no selected frame, default to the first frame.
+ //------------------------------------------------------------------
+ ExecutionContextRef (Target *target, bool adopt_selected);
+
+ //------------------------------------------------------------------
+ /// Construct using an execution context scope.
+ ///
+ /// If the ExecutionContextScope object is valid and refers to a frame,
+ /// make weak refernces too the frame, thread, process and target.
+ /// If the ExecutionContextScope object is valid and refers to a thread,
+ /// make weak refernces too the thread, process and target.
+ /// If the ExecutionContextScope object is valid and refers to a process,
+ /// make weak refernces too the process and target.
+ /// If the ExecutionContextScope object is valid and refers to a target,
+ /// make weak refernces too the target.
+ //------------------------------------------------------------------
+ ExecutionContextRef (ExecutionContextScope *exe_scope);
+
+ //------------------------------------------------------------------
+ /// Construct using an execution context scope.
+ ///
+ /// If the ExecutionContextScope object refers to a frame,
+ /// make weak refernces too the frame, thread, process and target.
+ /// If the ExecutionContextScope object refers to a thread,
+ /// make weak refernces too the thread, process and target.
+ /// If the ExecutionContextScope object refers to a process,
+ /// make weak refernces too the process and target.
+ /// If the ExecutionContextScope object refers to a target,
+ /// make weak refernces too the target.
+ //------------------------------------------------------------------
+ ExecutionContextRef (ExecutionContextScope &exe_scope);
+
+ ~ExecutionContextRef();
+ //------------------------------------------------------------------
+ /// Clear the object's state.
+ ///
+ /// Sets the process and thread to NULL, and the frame index to an
+ /// invalid value.
+ //------------------------------------------------------------------
+ void
+ Clear ();
+
+ //------------------------------------------------------------------
+ /// Set accessor that creates a weak reference to the target
+ /// referenced in \a target_sp.
+ ///
+ /// If \a target_sp is valid this object will create a weak
+ /// reference to that object, otherwise any previous target weak
+ /// reference contained in this object will be reset.
+ ///
+ /// Only the weak reference to the target will be updated, no other
+ /// weak references will be modified. If you want this execution
+ /// context to make a weak reference to the target's process, use
+ /// the ExecutionContextRef::SetContext() functions.
+ ///
+ /// @see ExecutionContextRef::SetContext(const lldb::TargetSP &, bool)
+ //------------------------------------------------------------------
+ void
+ SetTargetSP (const lldb::TargetSP &target_sp);
+
+ //------------------------------------------------------------------
+ /// Set accessor that creates a weak reference to the process
+ /// referenced in \a process_sp.
+ ///
+ /// If \a process_sp is valid this object will create a weak
+ /// reference to that object, otherwise any previous process weak
+ /// reference contained in this object will be reset.
+ ///
+ /// Only the weak reference to the process will be updated, no other
+ /// weak references will be modified. If you want this execution
+ /// context to make a weak reference to the target, use the
+ /// ExecutionContextRef::SetContext() functions.
+ ///
+ /// @see ExecutionContextRef::SetContext(const lldb::ProcessSP &)
+ //------------------------------------------------------------------
+ void
+ SetProcessSP (const lldb::ProcessSP &process_sp);
+
+ //------------------------------------------------------------------
+ /// Set accessor that creates a weak reference to the thread
+ /// referenced in \a thread_sp.
+ ///
+ /// If \a thread_sp is valid this object will create a weak
+ /// reference to that object, otherwise any previous thread weak
+ /// reference contained in this object will be reset.
+ ///
+ /// Only the weak reference to the thread will be updated, no other
+ /// weak references will be modified. If you want this execution
+ /// context to make a weak reference to the thread's process and
+ /// target, use the ExecutionContextRef::SetContext() functions.
+ ///
+ /// @see ExecutionContextRef::SetContext(const lldb::ThreadSP &)
+ //------------------------------------------------------------------
+ void
+ SetThreadSP (const lldb::ThreadSP &thread_sp);
+
+ //------------------------------------------------------------------
+ /// Set accessor that creates a weak reference to the frame
+ /// referenced in \a frame_sp.
+ ///
+ /// If \a frame_sp is valid this object will create a weak
+ /// reference to that object, otherwise any previous frame weak
+ /// reference contained in this object will be reset.
+ ///
+ /// Only the weak reference to the frame will be updated, no other
+ /// weak references will be modified. If you want this execution
+ /// context to make a weak reference to the frame's thread, process
+ /// and target, use the ExecutionContextRef::SetContext() functions.
+ ///
+ /// @see ExecutionContextRef::SetContext(const lldb::StackFrameSP &)
+ //------------------------------------------------------------------
+ void
+ SetFrameSP (const lldb::StackFrameSP &frame_sp);
+
+ void
+ SetTargetPtr (Target* target, bool adopt_selected);
+
+ void
+ SetProcessPtr (Process *process);
+
+ void
+ SetThreadPtr (Thread *thread);
+
+ void
+ SetFramePtr (StackFrame *frame);
+
+ //------------------------------------------------------------------
+ /// Get accessor that creates a strong reference from the weak target
+ /// reference contained in this object.
+ ///
+ /// @returns
+ /// A shared pointer to a target that is not guaranteed to be valid.
+ //------------------------------------------------------------------
+ lldb::TargetSP
+ GetTargetSP () const;
+
+ //------------------------------------------------------------------
+ /// Get accessor that creates a strong reference from the weak process
+ /// reference contained in this object.
+ ///
+ /// @returns
+ /// A shared pointer to a process that is not guaranteed to be valid.
+ //------------------------------------------------------------------
+ lldb::ProcessSP
+ GetProcessSP () const;
+
+ //------------------------------------------------------------------
+ /// Get accessor that creates a strong reference from the weak thread
+ /// reference contained in this object.
+ ///
+ /// @returns
+ /// A shared pointer to a thread that is not guaranteed to be valid.
+ //------------------------------------------------------------------
+ lldb::ThreadSP
+ GetThreadSP () const;
+
+ //------------------------------------------------------------------
+ /// Get accessor that creates a strong reference from the weak frame
+ /// reference contained in this object.
+ ///
+ /// @returns
+ /// A shared pointer to a frame that is not guaranteed to be valid.
+ //------------------------------------------------------------------
+ lldb::StackFrameSP
+ GetFrameSP () const;
+
+ //------------------------------------------------------------------
+ /// Create an ExecutionContext object from this object.
+ ///
+ /// Create strong references to any execution context objects that
+ /// are still valid. Any of the returned shared pointers in the
+ /// ExecutionContext objects is not guaranteed to be valid.
+ /// @returns
+ /// An execution context object that has strong references to
+ /// any valid weak references in this object.
+ //------------------------------------------------------------------
+ ExecutionContext
+ Lock () const;
+
+ //------------------------------------------------------------------
+ /// Returns true if this object has a weak reference to a thread.
+ /// The return value is only an indication of wether this object has
+ /// a weak reference and does not indicate wether the weak rerference
+ /// is valid or not.
+ //------------------------------------------------------------------
+ bool
+ HasThreadRef () const
+ {
+ return m_tid != LLDB_INVALID_THREAD_ID;
+ }
+
+ //------------------------------------------------------------------
+ /// Returns true if this object has a weak reference to a frame.
+ /// The return value is only an indication of wether this object has
+ /// a weak reference and does not indicate wether the weak rerference
+ /// is valid or not.
+ //------------------------------------------------------------------
+ bool
+ HasFrameRef () const
+ {
+ return m_stack_id.IsValid();
+ }
+
+ void
+ ClearThread ()
+ {
+ m_thread_wp.reset();
+ m_tid = LLDB_INVALID_THREAD_ID;
+ }
+
+ void
+ ClearFrame ()
+ {
+ m_stack_id.Clear();
+ }
+
+protected:
+ //------------------------------------------------------------------
+ // Member variables
+ //------------------------------------------------------------------
+ lldb::TargetWP m_target_wp; ///< A weak reference to a target
+ lldb::ProcessWP m_process_wp; ///< A weak reference to a process
+ mutable lldb::ThreadWP m_thread_wp; ///< A weak reference to a thread
+ lldb::tid_t m_tid; ///< The thread ID that this object refers to in case the backing object changes
+ StackID m_stack_id; ///< The stack ID that this object refers to in case the backing object changes
+};
+
+//----------------------------------------------------------------------
+/// @class ExecutionContext ExecutionContext.h "lldb/Target/ExecutionContext.h"
+/// @brief A class that contains an execution context.
+///
+/// This baton object can be passed into any function that requires
+/// a context that specifies a target, process, thread and frame.
+/// These objects are designed to be used for short term execution
+/// context object storage while a function might be trying to evaluate
+/// something that requires a thread or frame. ExecutionContextRef
+/// objects can be used to initialize one of these objects to turn
+/// the weak execution context object references to the target, process,
+/// thread and frame into strong references (shared pointers) so that
+/// functions can guarantee that these objects won't go away in the
+/// middle of a function.
+///
+/// ExecutionContext objects should be used as short lived objects
+/// (typically on the stack) in order to lock down an execution context
+/// for local use and for passing down to other functions that also
+/// require specific contexts. They should NOT be used for long term
+/// storage, for long term storage use ExecutionContextRef objects.
+//----------------------------------------------------------------------
+class ExecutionContext
+{
+public:
+ //------------------------------------------------------------------
+ /// Default Constructor.
+ //------------------------------------------------------------------
+ ExecutionContext();
+
+ //------------------------------------------------------------------
+ // Copy constructor
+ //------------------------------------------------------------------
+ ExecutionContext (const ExecutionContext &rhs);
+
+ //------------------------------------------------------------------
+ // Adopt the target and optionally its current context.
+ //------------------------------------------------------------------
+ ExecutionContext (Target* t, bool fill_current_process_thread_frame = true);
+
+ //------------------------------------------------------------------
+ // Create execution contexts from shared pointers
+ //------------------------------------------------------------------
+ ExecutionContext (const lldb::TargetSP &target_sp, bool get_process);
+ ExecutionContext (const lldb::ProcessSP &process_sp);
+ ExecutionContext (const lldb::ThreadSP &thread_sp);
+ ExecutionContext (const lldb::StackFrameSP &frame_sp);
+ //------------------------------------------------------------------
+ // Create execution contexts from weak pointers
+ //------------------------------------------------------------------
+ ExecutionContext (const lldb::TargetWP &target_wp, bool get_process);
+ ExecutionContext (const lldb::ProcessWP &process_wp);
+ ExecutionContext (const lldb::ThreadWP &thread_wp);
+ ExecutionContext (const lldb::StackFrameWP &frame_wp);
+ ExecutionContext (const ExecutionContextRef &exe_ctx_ref);
+ ExecutionContext (const ExecutionContextRef *exe_ctx_ref);
+
+ // These two variants take in a locker, and grab the target, lock the API mutex into locker, then
+ // fill in the rest of the shared pointers.
+ ExecutionContext (const ExecutionContextRef &exe_ctx_ref, Mutex::Locker &locker);
+ ExecutionContext (const ExecutionContextRef *exe_ctx_ref, Mutex::Locker &locker);
+ //------------------------------------------------------------------
+ // Create execution contexts from execution context scopes
+ //------------------------------------------------------------------
+ ExecutionContext (ExecutionContextScope *exe_scope);
+ ExecutionContext (ExecutionContextScope &exe_scope);
+
+
+ ExecutionContext &
+ operator =(const ExecutionContext &rhs);
+
+ bool
+ operator ==(const ExecutionContext &rhs) const;
+
+ bool
+ operator !=(const ExecutionContext &rhs) const;
+
+ //------------------------------------------------------------------
+ /// Construct with process, thread, and frame index.
+ ///
+ /// Initialize with process \a p, thread \a t, and frame index \a f.
+ ///
+ /// @param[in] process
+ /// The process for this execution context.
+ ///
+ /// @param[in] thread
+ /// The thread for this execution context.
+ ///
+ /// @param[in] frame
+ /// The frame index for this execution context.
+ //------------------------------------------------------------------
+ ExecutionContext (Process* process,
+ Thread *thread = NULL,
+ StackFrame * frame = NULL);
+
+
+ ~ExecutionContext();
+ //------------------------------------------------------------------
+ /// Clear the object's state.
+ ///
+ /// Sets the process and thread to NULL, and the frame index to an
+ /// invalid value.
+ //------------------------------------------------------------------
+ void
+ Clear ();
+
+ RegisterContext *
+ GetRegisterContext () const;
+
+ ExecutionContextScope *
+ GetBestExecutionContextScope () const;
+
+ uint32_t
+ GetAddressByteSize() const;
+
+ //------------------------------------------------------------------
+ /// Returns a pointer to the target object.
+ ///
+ /// The returned pointer might be NULL. Calling HasTargetScope(),
+ /// HasProcessScope(), HasThreadScope(), or HasFrameScope()
+ /// can help to pre-validate this pointer so that this accessor can
+ /// freely be used without having to check for NULL each time.
+ ///
+ /// @see ExecutionContext::HasTargetScope() const
+ /// @see ExecutionContext::HasProcessScope() const
+ /// @see ExecutionContext::HasThreadScope() const
+ /// @see ExecutionContext::HasFrameScope() const
+ //------------------------------------------------------------------
+ Target *
+ GetTargetPtr () const;
+
+ //------------------------------------------------------------------
+ /// Returns a pointer to the process object.
+ ///
+ /// The returned pointer might be NULL. Calling HasProcessScope(),
+ /// HasThreadScope(), or HasFrameScope() can help to pre-validate
+ /// this pointer so that this accessor can freely be used without
+ /// having to check for NULL each time.
+ ///
+ /// @see ExecutionContext::HasProcessScope() const
+ /// @see ExecutionContext::HasThreadScope() const
+ /// @see ExecutionContext::HasFrameScope() const
+ //------------------------------------------------------------------
+ Process *
+ GetProcessPtr () const;
+
+ //------------------------------------------------------------------
+ /// Returns a pointer to the thread object.
+ ///
+ /// The returned pointer might be NULL. Calling HasThreadScope() or
+ /// HasFrameScope() can help to pre-validate this pointer so that
+ /// this accessor can freely be used without having to check for
+ /// NULL each time.
+ ///
+ /// @see ExecutionContext::HasThreadScope() const
+ /// @see ExecutionContext::HasFrameScope() const
+ //------------------------------------------------------------------
+ Thread *
+ GetThreadPtr () const
+ {
+ return m_thread_sp.get();
+ }
+
+ //------------------------------------------------------------------
+ /// Returns a pointer to the frame object.
+ ///
+ /// The returned pointer might be NULL. Calling HasFrameScope(),
+ /// can help to pre-validate this pointer so that this accessor can
+ /// freely be used without having to check for NULL each time.
+ ///
+ /// @see ExecutionContext::HasFrameScope() const
+ //------------------------------------------------------------------
+ StackFrame *
+ GetFramePtr () const
+ {
+ return m_frame_sp.get();
+ }
+
+ //------------------------------------------------------------------
+ /// Returns a reference to the target object.
+ ///
+ /// Clients should call HasTargetScope(), HasProcessScope(),
+ /// HasThreadScope(), or HasFrameScope() prior to calling this
+ /// function to ensure that this ExecutionContext object contains
+ /// a valid target.
+ ///
+ /// @see ExecutionContext::HasTargetScope() const
+ /// @see ExecutionContext::HasProcessScope() const
+ /// @see ExecutionContext::HasThreadScope() const
+ /// @see ExecutionContext::HasFrameScope() const
+ //------------------------------------------------------------------
+ Target &
+ GetTargetRef () const;
+
+ //------------------------------------------------------------------
+ /// Returns a reference to the process object.
+ ///
+ /// Clients should call HasProcessScope(), HasThreadScope(), or
+ /// HasFrameScope() prior to calling this function to ensure that
+ /// this ExecutionContext object contains a valid target.
+ ///
+ /// @see ExecutionContext::HasProcessScope() const
+ /// @see ExecutionContext::HasThreadScope() const
+ /// @see ExecutionContext::HasFrameScope() const
+ //------------------------------------------------------------------
+ Process &
+ GetProcessRef () const;
+
+ //------------------------------------------------------------------
+ /// Returns a reference to the thread object.
+ ///
+ /// Clients should call HasThreadScope(), or HasFrameScope() prior
+ /// to calling this function to ensure that this ExecutionContext
+ /// object contains a valid target.
+ ///
+ /// @see ExecutionContext::HasThreadScope() const
+ /// @see ExecutionContext::HasFrameScope() const
+ //------------------------------------------------------------------
+ Thread &
+ GetThreadRef () const;
+
+ //------------------------------------------------------------------
+ /// Returns a reference to the thread object.
+ ///
+ /// Clients should call HasFrameScope() prior to calling this
+ /// function to ensure that this ExecutionContext object contains
+ /// a valid target.
+ ///
+ /// @see ExecutionContext::HasFrameScope() const
+ //------------------------------------------------------------------
+ StackFrame &
+ GetFrameRef () const;
+
+ //------------------------------------------------------------------
+ /// Get accessor to get the target shared pointer.
+ ///
+ /// The returned shared pointer is not guaranteed to be valid.
+ //------------------------------------------------------------------
+ const lldb::TargetSP &
+ GetTargetSP () const
+ {
+ return m_target_sp;
+ }
+
+ //------------------------------------------------------------------
+ /// Get accessor to get the process shared pointer.
+ ///
+ /// The returned shared pointer is not guaranteed to be valid.
+ //------------------------------------------------------------------
+ const lldb::ProcessSP &
+ GetProcessSP () const
+ {
+ return m_process_sp;
+ }
+
+ //------------------------------------------------------------------
+ /// Get accessor to get the thread shared pointer.
+ ///
+ /// The returned shared pointer is not guaranteed to be valid.
+ //------------------------------------------------------------------
+ const lldb::ThreadSP &
+ GetThreadSP () const
+ {
+ return m_thread_sp;
+ }
+
+ //------------------------------------------------------------------
+ /// Get accessor to get the frame shared pointer.
+ ///
+ /// The returned shared pointer is not guaranteed to be valid.
+ //------------------------------------------------------------------
+ const lldb::StackFrameSP &
+ GetFrameSP () const
+ {
+ return m_frame_sp;
+ }
+
+ //------------------------------------------------------------------
+ /// Set accessor to set only the target shared pointer.
+ //------------------------------------------------------------------
+ void
+ SetTargetSP (const lldb::TargetSP &target_sp);
+
+ //------------------------------------------------------------------
+ /// Set accessor to set only the process shared pointer.
+ //------------------------------------------------------------------
+ void
+ SetProcessSP (const lldb::ProcessSP &process_sp);
+
+ //------------------------------------------------------------------
+ /// Set accessor to set only the thread shared pointer.
+ //------------------------------------------------------------------
+ void
+ SetThreadSP (const lldb::ThreadSP &thread_sp);
+
+ //------------------------------------------------------------------
+ /// Set accessor to set only the frame shared pointer.
+ //------------------------------------------------------------------
+ void
+ SetFrameSP (const lldb::StackFrameSP &frame_sp);
+
+ //------------------------------------------------------------------
+ /// Set accessor to set only the target shared pointer from a target
+ /// pointer.
+ //------------------------------------------------------------------
+ void
+ SetTargetPtr (Target* target);
+
+ //------------------------------------------------------------------
+ /// Set accessor to set only the process shared pointer from a
+ /// process pointer.
+ //------------------------------------------------------------------
+ void
+ SetProcessPtr (Process *process);
+
+ //------------------------------------------------------------------
+ /// Set accessor to set only the thread shared pointer from a thread
+ /// pointer.
+ //------------------------------------------------------------------
+ void
+ SetThreadPtr (Thread *thread);
+
+ //------------------------------------------------------------------
+ /// Set accessor to set only the frame shared pointer from a frame
+ /// pointer.
+ //------------------------------------------------------------------
+ void
+ SetFramePtr (StackFrame *frame);
+
+ //------------------------------------------------------------------
+ // Set the execution context using a target shared pointer.
+ //
+ // If "target_sp" is valid, sets the target context to match and
+ // if "get_process" is true, sets the process shared pointer if
+ // the target currently has a process.
+ //------------------------------------------------------------------
+ void
+ SetContext (const lldb::TargetSP &target_sp, bool get_process);
+
+ //------------------------------------------------------------------
+ // Set the execution context using a process shared pointer.
+ //
+ // If "process_sp" is valid, then set the process and target in this
+ // context. Thread and frame contexts will be cleared.
+ // If "process_sp" is not valid, all shared pointers are reset.
+ //------------------------------------------------------------------
+ void
+ SetContext (const lldb::ProcessSP &process_sp);
+
+ //------------------------------------------------------------------
+ // Set the execution context using a thread shared pointer.
+ //
+ // If "thread_sp" is valid, then set the thread, process and target
+ // in this context. The frame context will be cleared.
+ // If "thread_sp" is not valid, all shared pointers are reset.
+ //------------------------------------------------------------------
+ void
+ SetContext (const lldb::ThreadSP &thread_sp);
+
+ //------------------------------------------------------------------
+ // Set the execution context using a frame shared pointer.
+ //
+ // If "frame_sp" is valid, then set the frame, thread, process and
+ // target in this context
+ // If "frame_sp" is not valid, all shared pointers are reset.
+ //------------------------------------------------------------------
+ void
+ SetContext (const lldb::StackFrameSP &frame_sp);
+
+ //------------------------------------------------------------------
+ /// Returns true the ExecutionContext object contains a valid
+ /// target.
+ ///
+ /// This function can be called after initializing an ExecutionContext
+ /// object, and if it returns true, calls to GetTargetPtr() and
+ /// GetTargetRef() do not need to be checked for validity.
+ //------------------------------------------------------------------
+ bool
+ HasTargetScope () const;
+
+ //------------------------------------------------------------------
+ /// Returns true the ExecutionContext object contains a valid
+ /// target and process.
+ ///
+ /// This function can be called after initializing an ExecutionContext
+ /// object, and if it returns true, calls to GetTargetPtr() and
+ /// GetTargetRef(), GetProcessPtr(), and GetProcessRef(), do not
+ /// need to be checked for validity.
+ //------------------------------------------------------------------
+ bool
+ HasProcessScope () const;
+
+ //------------------------------------------------------------------
+ /// Returns true the ExecutionContext object contains a valid
+ /// target, process, and thread.
+ ///
+ /// This function can be called after initializing an ExecutionContext
+ /// object, and if it returns true, calls to GetTargetPtr(),
+ /// GetTargetRef(), GetProcessPtr(), GetProcessRef(), GetThreadPtr(),
+ /// and GetThreadRef() do not need to be checked for validity.
+ //------------------------------------------------------------------
+ bool
+ HasThreadScope () const;
+
+ //------------------------------------------------------------------
+ /// Returns true the ExecutionContext object contains a valid
+ /// target, process, thread and frame.
+ ///
+ /// This function can be called after initializing an ExecutionContext
+ /// object, and if it returns true, calls to GetTargetPtr(),
+ /// GetTargetRef(), GetProcessPtr(), GetProcessRef(), GetThreadPtr(),
+ /// GetThreadRef(), GetFramePtr(), and GetFrameRef() do not need
+ /// to be checked for validity.
+ //------------------------------------------------------------------
+ bool
+ HasFrameScope () const;
+
+protected:
+ //------------------------------------------------------------------
+ // Member variables
+ //------------------------------------------------------------------
+ lldb::TargetSP m_target_sp; ///< The target that owns the process/thread/frame
+ lldb::ProcessSP m_process_sp; ///< The process that owns the thread/frame
+ lldb::ThreadSP m_thread_sp; ///< The thread that owns the frame
+ lldb::StackFrameSP m_frame_sp; ///< The stack frame in thread.
+};
+} // namespace lldb_private
+
+#endif // liblldb_ExecutionContext_h_
diff --git a/include/lldb/Target/ExecutionContextScope.h b/include/lldb/Target/ExecutionContextScope.h
new file mode 100644
index 000000000000..7ba40971af2c
--- /dev/null
+++ b/include/lldb/Target/ExecutionContextScope.h
@@ -0,0 +1,74 @@
+//===-- ExecutionContextScope.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_ExecutionContextScope_h_
+#define liblldb_ExecutionContextScope_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+
+namespace lldb_private {
+
+//----------------------------------------------------------------------
+/// @class ExecutionContextScope ExecutionContextScope.h "lldb/Symbol/ExecutionContextScope.h"
+/// @brief Inherit from this if your object can reconstruct its
+/// execution context.
+///
+/// Many objects that have pointers back to parent execution context
+/// objects can inherit from this pure virtual class can reconstruct
+/// their execution context without having to keep a complete
+/// ExecutionContext object in the object state. Examples of these
+/// objects include: Process, Thread, RegisterContext and StackFrame.
+///
+/// Bbjects can contain a valid pointer to an instance of this so they
+/// can reconstruct the execution context.
+///
+/// Objects that adhere to this protocol can reconstruct enough of a
+/// execution context to allow functions that take a execution contexts
+/// to be called.
+//----------------------------------------------------------------------
+class ExecutionContextScope
+{
+public:
+ virtual
+ ~ExecutionContextScope () {}
+
+ virtual lldb::TargetSP
+ CalculateTarget () = 0;
+
+ virtual lldb::ProcessSP
+ CalculateProcess () = 0;
+
+ virtual lldb::ThreadSP
+ CalculateThread () = 0;
+
+ virtual lldb::StackFrameSP
+ CalculateStackFrame () = 0;
+
+ //------------------------------------------------------------------
+ /// Reconstruct the object's execution context into \a sc.
+ ///
+ /// The object should fill in as much of the ExecutionContextScope as it
+ /// can so function calls that require a execution context can be made
+ /// for the given object.
+ ///
+ /// @param[out] exe_ctx
+ /// A reference to an execution context object that gets filled
+ /// in.
+ //------------------------------------------------------------------
+ virtual void
+ CalculateExecutionContext (ExecutionContext &exe_ctx) = 0;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ExecutionContextScope_h_
diff --git a/include/lldb/Target/LanguageRuntime.h b/include/lldb/Target/LanguageRuntime.h
new file mode 100644
index 000000000000..93c0437da75d
--- /dev/null
+++ b/include/lldb/Target/LanguageRuntime.h
@@ -0,0 +1,113 @@
+//===-- LanguageRuntime.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_LanguageRuntime_h_
+#define liblldb_LanguageRuntime_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-public.h"
+#include "lldb/Breakpoint/BreakpointResolver.h"
+#include "lldb/Breakpoint/BreakpointResolverName.h"
+#include "lldb/Core/PluginInterface.h"
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Target/ExecutionContextScope.h"
+
+namespace lldb_private {
+
+class LanguageRuntime :
+ public PluginInterface
+{
+public:
+ virtual
+ ~LanguageRuntime();
+
+ static LanguageRuntime*
+ FindPlugin (Process *process, lldb::LanguageType language);
+
+ virtual lldb::LanguageType
+ GetLanguageType () const = 0;
+
+ virtual bool
+ GetObjectDescription (Stream &str, ValueObject &object) = 0;
+
+ virtual bool
+ GetObjectDescription (Stream &str, Value &value, ExecutionContextScope *exe_scope) = 0;
+
+ // this call should return true if it could set the name and/or the type
+ virtual bool
+ GetDynamicTypeAndAddress (ValueObject &in_value,
+ lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name,
+ Address &address) = 0;
+
+ // This should be a fast test to determine whether it is likely that this value would
+ // have a dynamic type.
+ virtual bool
+ CouldHaveDynamicValue (ValueObject &in_value) = 0;
+
+ virtual void
+ SetExceptionBreakpoints ()
+ {
+ }
+
+ virtual void
+ ClearExceptionBreakpoints ()
+ {
+ }
+
+ virtual bool
+ ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason)
+ {
+ return false;
+ }
+
+ static lldb::BreakpointSP
+ CreateExceptionBreakpoint (Target &target,
+ lldb::LanguageType language,
+ bool catch_bp,
+ bool throw_bp,
+ bool is_internal = false);
+
+ static lldb::LanguageType
+ GetLanguageTypeFromString (const char *string);
+
+ static const char *
+ GetNameForLanguageType (lldb::LanguageType language);
+
+ Process *
+ GetProcess()
+ {
+ return m_process;
+ }
+
+ virtual lldb::BreakpointResolverSP
+ CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp) = 0;
+
+ virtual lldb::SearchFilterSP
+ CreateExceptionSearchFilter ();
+
+protected:
+ //------------------------------------------------------------------
+ // Classes that inherit from LanguageRuntime can see and modify these
+ //------------------------------------------------------------------
+
+ LanguageRuntime(Process *process);
+ Process *m_process;
+private:
+ DISALLOW_COPY_AND_ASSIGN (LanguageRuntime);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_LanguageRuntime_h_
diff --git a/include/lldb/Target/Memory.h b/include/lldb/Target/Memory.h
new file mode 100644
index 000000000000..568bbcdf2f7c
--- /dev/null
+++ b/include/lldb/Target/Memory.h
@@ -0,0 +1,196 @@
+//===-- Memory.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_Memory_h_
+#define liblldb_Memory_h_
+
+// C Includes
+// C++ Includes
+#include <map>
+#include <vector>
+
+// Other libraries and framework includes
+
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Core/RangeMap.h"
+#include "lldb/Host/Mutex.h"
+
+namespace lldb_private {
+ //----------------------------------------------------------------------
+ // A class to track memory that was read from a live process between
+ // runs.
+ //----------------------------------------------------------------------
+ class MemoryCache
+ {
+ public:
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ MemoryCache (Process &process);
+
+ ~MemoryCache ();
+
+ void
+ Clear(bool clear_invalid_ranges = false);
+
+ void
+ Flush (lldb::addr_t addr, size_t size);
+
+ size_t
+ Read (lldb::addr_t addr,
+ void *dst,
+ size_t dst_len,
+ Error &error);
+
+ uint32_t
+ GetMemoryCacheLineSize() const
+ {
+ return m_cache_line_byte_size ;
+ }
+
+ void
+ AddInvalidRange (lldb::addr_t base_addr, lldb::addr_t byte_size);
+
+ bool
+ RemoveInvalidRange (lldb::addr_t base_addr, lldb::addr_t byte_size);
+
+ protected:
+ typedef std::map<lldb::addr_t, lldb::DataBufferSP> BlockMap;
+ typedef RangeArray<lldb::addr_t, lldb::addr_t, 4> InvalidRanges;
+ //------------------------------------------------------------------
+ // Classes that inherit from MemoryCache can see and modify these
+ //------------------------------------------------------------------
+ Process &m_process;
+ uint32_t m_cache_line_byte_size;
+ Mutex m_mutex;
+ BlockMap m_cache;
+ InvalidRanges m_invalid_ranges;
+ private:
+ DISALLOW_COPY_AND_ASSIGN (MemoryCache);
+ };
+
+
+ class AllocatedBlock
+ {
+ public:
+ AllocatedBlock (lldb::addr_t addr,
+ uint32_t byte_size,
+ uint32_t permissions,
+ uint32_t chunk_size);
+
+ ~AllocatedBlock ();
+
+ lldb::addr_t
+ ReserveBlock (uint32_t size);
+
+ bool
+ FreeBlock (lldb::addr_t addr);
+
+ lldb::addr_t
+ GetBaseAddress () const
+ {
+ return m_addr;
+ }
+
+ uint32_t
+ GetByteSize () const
+ {
+ return m_byte_size;
+ }
+
+ uint32_t
+ GetPermissions () const
+ {
+ return m_permissions;
+ }
+
+ uint32_t
+ GetChunkSize () const
+ {
+ return m_chunk_size;
+ }
+
+ bool
+ Contains (lldb::addr_t addr) const
+ {
+ return ((addr >= m_addr) && addr < (m_addr + m_byte_size));
+ }
+ protected:
+ uint32_t
+ TotalChunks () const
+ {
+ return m_byte_size / m_chunk_size;
+ }
+
+ uint32_t
+ CalculateChunksNeededForSize (uint32_t size) const
+ {
+ return (size + m_chunk_size - 1) / m_chunk_size;
+ }
+ const lldb::addr_t m_addr; // Base address of this block of memory
+ const uint32_t m_byte_size; // 4GB of chunk should be enough...
+ const uint32_t m_permissions; // Permissions for this memory (logical OR of lldb::Permissions bits)
+ const uint32_t m_chunk_size; // The size of chunks that the memory at m_addr is divied up into
+ typedef std::map<uint32_t, uint32_t> OffsetToChunkSize;
+ OffsetToChunkSize m_offset_to_chunk_size;
+ };
+
+
+ //----------------------------------------------------------------------
+ // A class that can track allocated memory and give out allocated memory
+ // without us having to make an allocate/deallocate call every time we
+ // need some memory in a process that is being debugged.
+ //----------------------------------------------------------------------
+ class AllocatedMemoryCache
+ {
+ public:
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ AllocatedMemoryCache (Process &process);
+
+ ~AllocatedMemoryCache ();
+
+ void
+ Clear();
+
+ lldb::addr_t
+ AllocateMemory (size_t byte_size,
+ uint32_t permissions,
+ Error &error);
+
+ bool
+ DeallocateMemory (lldb::addr_t ptr);
+
+ protected:
+ typedef std::shared_ptr<AllocatedBlock> AllocatedBlockSP;
+
+ AllocatedBlockSP
+ AllocatePage (uint32_t byte_size,
+ uint32_t permissions,
+ uint32_t chunk_size,
+ Error &error);
+
+
+ //------------------------------------------------------------------
+ // Classes that inherit from MemoryCache can see and modify these
+ //------------------------------------------------------------------
+ Process &m_process;
+ Mutex m_mutex;
+ typedef std::multimap<uint32_t, AllocatedBlockSP> PermissionsToBlockMap;
+ PermissionsToBlockMap m_memory_map;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN (AllocatedMemoryCache);
+ };
+
+} // namespace lldb_private
+
+#endif // liblldb_Memory_h_
diff --git a/include/lldb/Target/ObjCLanguageRuntime.h b/include/lldb/Target/ObjCLanguageRuntime.h
new file mode 100644
index 000000000000..7bac57256444
--- /dev/null
+++ b/include/lldb/Target/ObjCLanguageRuntime.h
@@ -0,0 +1,604 @@
+//===-- ObjCLanguageRuntime.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_ObjCLanguageRuntime_h_
+#define liblldb_ObjCLanguageRuntime_h_
+
+// C Includes
+// C++ Includes
+#include <functional>
+#include <map>
+#include <unordered_set>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Core/PluginInterface.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Symbol/TypeVendor.h"
+#include "lldb/Target/LanguageRuntime.h"
+
+namespace lldb_private {
+
+class ClangUtilityFunction;
+
+class ObjCLanguageRuntime :
+ public LanguageRuntime
+{
+public:
+ class MethodName
+ {
+ public:
+ enum Type
+ {
+ eTypeUnspecified,
+ eTypeClassMethod,
+ eTypeInstanceMethod
+ };
+
+ MethodName () :
+ m_full(),
+ m_class(),
+ m_category(),
+ m_selector(),
+ m_type (eTypeUnspecified),
+ m_category_is_valid (false)
+ {
+ }
+
+ MethodName (const char *name, bool strict) :
+ m_full(),
+ m_class(),
+ m_category(),
+ m_selector(),
+ m_type (eTypeUnspecified),
+ m_category_is_valid (false)
+ {
+ SetName (name, strict);
+ }
+
+ void
+ Clear();
+
+ bool
+ IsValid (bool strict) const
+ {
+ // If "strict" is true, the name must have everything specified including
+ // the leading "+" or "-" on the method name
+ if (strict && m_type == eTypeUnspecified)
+ return false;
+ // Other than that, m_full will only be filled in if the objective C
+ // name is valid.
+ return (bool)m_full;
+ }
+
+ bool
+ HasCategory()
+ {
+ return (bool)GetCategory();
+ }
+
+ Type
+ GetType () const
+ {
+ return m_type;
+ }
+
+ const ConstString &
+ GetFullName () const
+ {
+ return m_full;
+ }
+
+ ConstString
+ GetFullNameWithoutCategory (bool empty_if_no_category);
+
+ bool
+ SetName (const char *name, bool strict);
+
+ const ConstString &
+ GetClassName ();
+
+ const ConstString &
+ GetClassNameWithCategory ();
+
+ const ConstString &
+ GetCategory ();
+
+ const ConstString &
+ GetSelector ();
+
+ // Get all possible names for a method. Examples:
+ // If name is "+[NSString(my_additions) myStringWithCString:]"
+ // names[0] => "+[NSString(my_additions) myStringWithCString:]"
+ // names[1] => "+[NSString myStringWithCString:]"
+ // If name is specified without the leading '+' or '-' like "[NSString(my_additions) myStringWithCString:]"
+ // names[0] => "+[NSString(my_additions) myStringWithCString:]"
+ // names[1] => "-[NSString(my_additions) myStringWithCString:]"
+ // names[2] => "+[NSString myStringWithCString:]"
+ // names[3] => "-[NSString myStringWithCString:]"
+ size_t
+ GetFullNames (std::vector<ConstString> &names, bool append);
+ protected:
+ ConstString m_full; // Full name: "+[NSString(my_additions) myStringWithCString:]"
+ ConstString m_class; // Class name: "NSString"
+ ConstString m_class_category; // Class with category: "NSString(my_additions)"
+ ConstString m_category; // Category: "my_additions"
+ ConstString m_selector; // Selector: "myStringWithCString:"
+ Type m_type;
+ bool m_category_is_valid;
+
+ };
+ typedef lldb::addr_t ObjCISA;
+
+ class ClassDescriptor;
+ typedef std::shared_ptr<ClassDescriptor> ClassDescriptorSP;
+
+ // the information that we want to support retrieving from an ObjC class
+ // this needs to be pure virtual since there are at least 2 different implementations
+ // of the runtime, and more might come
+ class ClassDescriptor
+ {
+ public:
+
+ ClassDescriptor() :
+ m_is_kvo (eLazyBoolCalculate),
+ m_is_cf (eLazyBoolCalculate),
+ m_type_wp ()
+ {
+ }
+
+ virtual
+ ~ClassDescriptor ()
+ {
+ }
+
+ virtual ConstString
+ GetClassName () = 0;
+
+ virtual ClassDescriptorSP
+ GetSuperclass () = 0;
+
+ // virtual if any implementation has some other version-specific rules
+ // but for the known v1/v2 this is all that needs to be done
+ virtual bool
+ IsKVO ()
+ {
+ if (m_is_kvo == eLazyBoolCalculate)
+ {
+ const char* class_name = GetClassName().AsCString();
+ if (class_name && *class_name)
+ m_is_kvo = (LazyBool)(strstr(class_name,"NSKVONotifying_") == class_name);
+ }
+ return (m_is_kvo == eLazyBoolYes);
+ }
+
+ // virtual if any implementation has some other version-specific rules
+ // but for the known v1/v2 this is all that needs to be done
+ virtual bool
+ IsCFType ()
+ {
+ if (m_is_cf == eLazyBoolCalculate)
+ {
+ const char* class_name = GetClassName().AsCString();
+ if (class_name && *class_name)
+ m_is_cf = (LazyBool)(strcmp(class_name,"__NSCFType") == 0 ||
+ strcmp(class_name,"NSCFType") == 0);
+ }
+ return (m_is_cf == eLazyBoolYes);
+ }
+
+ virtual bool
+ IsValid () = 0;
+
+ virtual bool
+ GetTaggedPointerInfo (uint64_t* info_bits = NULL,
+ uint64_t* value_bits = NULL,
+ uint64_t* payload = NULL) = 0;
+
+ virtual uint64_t
+ GetInstanceSize () = 0;
+
+ // use to implement version-specific additional constraints on pointers
+ virtual bool
+ CheckPointer (lldb::addr_t value,
+ uint32_t ptr_size) const
+ {
+ return true;
+ }
+
+ virtual ObjCISA
+ GetISA () = 0;
+
+ // This should return true iff the interface could be completed
+ virtual bool
+ Describe (std::function <void (ObjCISA)> const &superclass_func,
+ std::function <bool (const char*, const char*)> const &instance_method_func,
+ std::function <bool (const char*, const char*)> const &class_method_func,
+ std::function <bool (const char *, const char *, lldb::addr_t, uint64_t)> const &ivar_func)
+ {
+ return false;
+ }
+
+ lldb::TypeSP
+ GetType ()
+ {
+ return m_type_wp.lock();
+ }
+
+ void
+ SetType (const lldb::TypeSP &type_sp)
+ {
+ m_type_wp = type_sp;
+ }
+
+ protected:
+ bool
+ IsPointerValid (lldb::addr_t value,
+ uint32_t ptr_size,
+ bool allow_NULLs = false,
+ bool allow_tagged = false,
+ bool check_version_specific = false) const;
+
+ private:
+ LazyBool m_is_kvo;
+ LazyBool m_is_cf;
+ lldb::TypeWP m_type_wp;
+ };
+
+ virtual ClassDescriptorSP
+ GetClassDescriptor (ValueObject& in_value);
+
+ ClassDescriptorSP
+ GetNonKVOClassDescriptor (ValueObject& in_value);
+
+ virtual ClassDescriptorSP
+ GetClassDescriptorFromClassName (const ConstString &class_name);
+
+ virtual ClassDescriptorSP
+ GetClassDescriptorFromISA (ObjCISA isa);
+
+ ClassDescriptorSP
+ GetNonKVOClassDescriptor (ObjCISA isa);
+
+ virtual
+ ~ObjCLanguageRuntime();
+
+ virtual lldb::LanguageType
+ GetLanguageType () const
+ {
+ return lldb::eLanguageTypeObjC;
+ }
+
+ virtual bool
+ IsModuleObjCLibrary (const lldb::ModuleSP &module_sp) = 0;
+
+ virtual bool
+ ReadObjCLibrary (const lldb::ModuleSP &module_sp) = 0;
+
+ virtual bool
+ HasReadObjCLibrary () = 0;
+
+ virtual lldb::ThreadPlanSP
+ GetStepThroughTrampolinePlan (Thread &thread, bool stop_others) = 0;
+
+ lldb::addr_t
+ LookupInMethodCache (lldb::addr_t class_addr, lldb::addr_t sel);
+
+ void
+ AddToMethodCache (lldb::addr_t class_addr, lldb::addr_t sel, lldb::addr_t impl_addr);
+
+ TypeAndOrName
+ LookupInClassNameCache (lldb::addr_t class_addr);
+
+ void
+ AddToClassNameCache (lldb::addr_t class_addr, const char *name, lldb::TypeSP type_sp);
+
+ void
+ AddToClassNameCache (lldb::addr_t class_addr, const TypeAndOrName &class_or_type_name);
+
+ lldb::TypeSP
+ LookupInCompleteClassCache (ConstString &name);
+
+ virtual ClangUtilityFunction *
+ CreateObjectChecker (const char *) = 0;
+
+ virtual ObjCRuntimeVersions
+ GetRuntimeVersion ()
+ {
+ return eObjC_VersionUnknown;
+ }
+
+ bool
+ IsValidISA(ObjCISA isa)
+ {
+ UpdateISAToDescriptorMap();
+ return m_isa_to_descriptor.count(isa) > 0;
+ }
+
+ virtual void
+ UpdateISAToDescriptorMapIfNeeded() = 0;
+
+ void
+ UpdateISAToDescriptorMap()
+ {
+ if (m_process && m_process->GetStopID() != m_isa_to_descriptor_stop_id)
+ {
+ UpdateISAToDescriptorMapIfNeeded ();
+ }
+ }
+
+ virtual ObjCISA
+ GetISA(const ConstString &name);
+
+ virtual ConstString
+ GetActualTypeName(ObjCISA isa);
+
+ virtual ObjCISA
+ GetParentClass(ObjCISA isa);
+
+ virtual TypeVendor *
+ GetTypeVendor()
+ {
+ return NULL;
+ }
+
+ // Finds the byte offset of the child_type ivar in parent_type. If it can't find the
+ // offset, returns LLDB_INVALID_IVAR_OFFSET.
+
+ virtual size_t
+ GetByteOffsetForIvar (ClangASTType &parent_qual_type, const char *ivar_name);
+
+ // Given the name of an Objective-C runtime symbol (e.g., ivar offset symbol),
+ // try to determine from the runtime what the value of that symbol would be.
+ // Useful when the underlying binary is stripped.
+ virtual lldb::addr_t
+ LookupRuntimeSymbol (const ConstString &name)
+ {
+ return LLDB_INVALID_ADDRESS;
+ }
+
+ //------------------------------------------------------------------
+ /// Chop up an objective C function prototype.
+ ///
+ /// Chop up an objective C function fullname and optionally fill in
+ /// any non-NULL ConstString objects. If a ConstString * is NULL,
+ /// then this name doesn't get filled in
+ ///
+ /// @param[in] name
+ /// A fully specified objective C function name. The string might
+ /// contain a category and it includes the leading "+" or "-" and
+ /// the square brackets, no types for the arguments, just the plain
+ /// selector. A few examples:
+ /// "-[NSStringDrawingContext init]"
+ /// "-[NSStringDrawingContext addString:inRect:]"
+ /// "-[NSString(NSStringDrawing) sizeWithAttributes:]"
+ /// "+[NSString(NSStringDrawing) usesFontLeading]"
+ ///
+ /// @param[out] class_name
+ /// If non-NULL, this string will be filled in with the class
+ /// name including the category. The examples above would return:
+ /// "NSStringDrawingContext"
+ /// "NSStringDrawingContext"
+ /// "NSString(NSStringDrawing)"
+ /// "NSString(NSStringDrawing)"
+ ///
+ /// @param[out] selector_name
+ /// If non-NULL, this string will be filled in with the selector
+ /// name. The examples above would return:
+ /// "init"
+ /// "addString:inRect:"
+ /// "sizeWithAttributes:"
+ /// "usesFontLeading"
+ ///
+ /// @param[out] name_sans_category
+ /// If non-NULL, this string will be filled in with the class
+ /// name _without_ the category. If there is no category, and empty
+ /// string will be returned (as the result would be normally returned
+ /// in the "class_name" argument). The examples above would return:
+ /// <empty>
+ /// <empty>
+ /// "-[NSString sizeWithAttributes:]"
+ /// "+[NSString usesFontLeading]"
+ ///
+ /// @param[out] class_name_sans_category
+ /// If non-NULL, this string will be filled in with the prototype
+ /// name _without_ the category. If there is no category, and empty
+ /// string will be returned (as this is already the value that was
+ /// passed in). The examples above would return:
+ /// <empty>
+ /// <empty>
+ /// "NSString"
+ /// "NSString"
+ ///
+ /// @return
+ /// Returns the number of strings that were successfully filled
+ /// in.
+ //------------------------------------------------------------------
+// static uint32_t
+// ParseMethodName (const char *name,
+// ConstString *class_name, // Class name (with category if there is one)
+// ConstString *selector_name, // selector only
+// ConstString *name_sans_category, // full function name with no category (empty if no category)
+// ConstString *class_name_sans_category);// Class name without category (empty if no category)
+
+ static bool
+ IsPossibleObjCMethodName (const char *name)
+ {
+ if (!name)
+ return false;
+ bool starts_right = (name[0] == '+' || name[0] == '-') && name[1] == '[';
+ bool ends_right = (name[strlen(name) - 1] == ']');
+ return (starts_right && ends_right);
+ }
+
+ static bool
+ IsPossibleObjCSelector (const char *name)
+ {
+ if (!name)
+ return false;
+
+ if (strchr(name, ':') == NULL)
+ return true;
+ else if (name[strlen(name) - 1] == ':')
+ return true;
+ else
+ return false;
+ }
+
+ bool
+ HasNewLiteralsAndIndexing ()
+ {
+ if (m_has_new_literals_and_indexing == eLazyBoolCalculate)
+ {
+ if (CalculateHasNewLiteralsAndIndexing())
+ m_has_new_literals_and_indexing = eLazyBoolYes;
+ else
+ m_has_new_literals_and_indexing = eLazyBoolNo;
+ }
+
+ return (m_has_new_literals_and_indexing == eLazyBoolYes);
+ }
+
+ virtual void
+ SymbolsDidLoad (const ModuleList& module_list)
+ {
+ m_negative_complete_class_cache.clear();
+ }
+
+protected:
+ //------------------------------------------------------------------
+ // Classes that inherit from ObjCLanguageRuntime can see and modify these
+ //------------------------------------------------------------------
+ ObjCLanguageRuntime(Process *process);
+
+ virtual bool CalculateHasNewLiteralsAndIndexing()
+ {
+ return false;
+ }
+
+
+ bool
+ ISAIsCached (ObjCISA isa) const
+ {
+ return m_isa_to_descriptor.find(isa) != m_isa_to_descriptor.end();
+ }
+
+ bool
+ AddClass (ObjCISA isa, const ClassDescriptorSP &descriptor_sp)
+ {
+ if (isa != 0)
+ {
+ m_isa_to_descriptor[isa] = descriptor_sp;
+ return true;
+ }
+ return false;
+ }
+
+ bool
+ AddClass (ObjCISA isa, const ClassDescriptorSP &descriptor_sp, const char *class_name);
+
+ bool
+ AddClass (ObjCISA isa, const ClassDescriptorSP &descriptor_sp, uint32_t class_name_hash)
+ {
+ if (isa != 0)
+ {
+ m_isa_to_descriptor[isa] = descriptor_sp;
+ m_hash_to_isa_map.insert(std::make_pair(class_name_hash, isa));
+ return true;
+ }
+ return false;
+ }
+
+private:
+ // We keep a map of <Class,Selector>->Implementation so we don't have to call the resolver
+ // function over and over.
+
+ // FIXME: We need to watch for the loading of Protocols, and flush the cache for any
+ // class that we see so changed.
+
+ struct ClassAndSel
+ {
+ ClassAndSel()
+ {
+ sel_addr = LLDB_INVALID_ADDRESS;
+ class_addr = LLDB_INVALID_ADDRESS;
+ }
+ ClassAndSel (lldb::addr_t in_sel_addr, lldb::addr_t in_class_addr) :
+ class_addr (in_class_addr),
+ sel_addr(in_sel_addr)
+ {
+ }
+ bool operator== (const ClassAndSel &rhs)
+ {
+ if (class_addr == rhs.class_addr
+ && sel_addr == rhs.sel_addr)
+ return true;
+ else
+ return false;
+ }
+
+ bool operator< (const ClassAndSel &rhs) const
+ {
+ if (class_addr < rhs.class_addr)
+ return true;
+ else if (class_addr > rhs.class_addr)
+ return false;
+ else
+ {
+ if (sel_addr < rhs.sel_addr)
+ return true;
+ else
+ return false;
+ }
+ }
+
+ lldb::addr_t class_addr;
+ lldb::addr_t sel_addr;
+ };
+
+ typedef std::map<ClassAndSel,lldb::addr_t> MsgImplMap;
+ typedef std::map<ObjCISA, ClassDescriptorSP> ISAToDescriptorMap;
+ typedef std::multimap<uint32_t, ObjCISA> HashToISAMap;
+ typedef ISAToDescriptorMap::iterator ISAToDescriptorIterator;
+ typedef HashToISAMap::iterator HashToISAIterator;
+
+ MsgImplMap m_impl_cache;
+ LazyBool m_has_new_literals_and_indexing;
+ ISAToDescriptorMap m_isa_to_descriptor;
+ HashToISAMap m_hash_to_isa_map;
+
+protected:
+ uint32_t m_isa_to_descriptor_stop_id;
+
+ typedef std::map<ConstString, lldb::TypeWP> CompleteClassMap;
+ CompleteClassMap m_complete_class_cache;
+
+ struct ConstStringSetHelpers {
+ size_t operator () (const ConstString& arg) const // for hashing
+ {
+ return (size_t)arg.GetCString();
+ }
+ bool operator () (const ConstString& arg1, const ConstString& arg2) const // for equality
+ {
+ return arg1.operator==(arg2);
+ }
+ };
+ typedef std::unordered_set<ConstString, ConstStringSetHelpers, ConstStringSetHelpers> CompleteClassSet;
+ CompleteClassSet m_negative_complete_class_cache;
+
+ ISAToDescriptorIterator
+ GetDescriptorIterator (const ConstString &name);
+
+ DISALLOW_COPY_AND_ASSIGN (ObjCLanguageRuntime);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ObjCLanguageRuntime_h_
diff --git a/include/lldb/Target/OperatingSystem.h b/include/lldb/Target/OperatingSystem.h
new file mode 100644
index 000000000000..f1c0eb06026f
--- /dev/null
+++ b/include/lldb/Target/OperatingSystem.h
@@ -0,0 +1,101 @@
+//===-- OperatingSystem.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_OperatingSystem_h_
+#define liblldb_OperatingSystem_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+
+#include "lldb/lldb-private.h"
+#include "lldb/Core/PluginInterface.h"
+
+namespace lldb_private {
+
+//----------------------------------------------------------------------
+/// @class OperatingSystem OperatingSystem.h "lldb/Target/OperatingSystem.h"
+/// @brief A plug-in interface definition class for halted OS helpers.
+///
+/// Halted OS plug-ins can be used by any process to locate and create
+/// OS objects, like threads, during the lifetime of a debug session.
+/// This is commonly used when attaching to an operating system that is
+/// halted, such as when debugging over JTAG or connecting to low level
+/// kernel debug services.
+//----------------------------------------------------------------------
+
+class OperatingSystem :
+ public PluginInterface
+
+{
+public:
+ //------------------------------------------------------------------
+ /// Find a halted OS plugin for a given process.
+ ///
+ /// Scans the installed OperatingSystem plug-ins and tries to find
+ /// an instance that matches the current target triple and
+ /// executable.
+ ///
+ /// @param[in] process
+ /// The process for which to try and locate a halted OS
+ /// plug-in instance.
+ ///
+ /// @param[in] plugin_name
+ /// An optional name of a specific halted OS plug-in that
+ /// should be used. If NULL, pick the best plug-in.
+ //------------------------------------------------------------------
+ static OperatingSystem*
+ FindPlugin (Process *process, const char *plugin_name);
+
+ //------------------------------------------------------------------
+ // Class Methods
+ //------------------------------------------------------------------
+ OperatingSystem (Process *process);
+
+ virtual
+ ~OperatingSystem();
+
+ //------------------------------------------------------------------
+ // Plug-in Methods
+ //------------------------------------------------------------------
+ virtual bool
+ UpdateThreadList (ThreadList &old_thread_list,
+ ThreadList &real_thread_list,
+ ThreadList &new_thread_list) = 0;
+
+ virtual void
+ ThreadWasSelected (Thread *thread) = 0;
+
+ virtual lldb::RegisterContextSP
+ CreateRegisterContextForThread (Thread *thread, lldb::addr_t reg_data_addr) = 0;
+
+ virtual lldb::StopInfoSP
+ CreateThreadStopReason (Thread *thread) = 0;
+
+ virtual lldb::ThreadSP
+ CreateThread (lldb::tid_t tid, lldb::addr_t context)
+ {
+ return lldb::ThreadSP();
+ }
+
+ virtual bool
+ IsOperatingSystemPluginThread (const lldb::ThreadSP &thread_sp);
+
+protected:
+ //------------------------------------------------------------------
+ // Member variables.
+ //------------------------------------------------------------------
+ Process* m_process; ///< The process that this dynamic loader plug-in is tracking.
+private:
+ DISALLOW_COPY_AND_ASSIGN (OperatingSystem);
+};
+
+} // namespace lldb_private
+
+#endif // #ifndef liblldb_OperatingSystem_h_
diff --git a/include/lldb/Target/PathMappingList.h b/include/lldb/Target/PathMappingList.h
new file mode 100644
index 000000000000..b5bcbbfd768f
--- /dev/null
+++ b/include/lldb/Target/PathMappingList.h
@@ -0,0 +1,171 @@
+//===-- PathMappingList.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_PathMappingList_h_
+#define liblldb_PathMappingList_h_
+
+// C Includes
+// C++ Includes
+#include <map>
+#include <vector>
+// Other libraries and framework includes
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Error.h"
+// Project includes
+
+namespace lldb_private {
+
+class PathMappingList
+{
+public:
+
+ typedef void (*ChangedCallback) (const PathMappingList &path_list,
+ void *baton);
+
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ PathMappingList ();
+
+ PathMappingList (ChangedCallback callback,
+ void *callback_baton);
+
+ PathMappingList (const PathMappingList &rhs);
+
+ ~PathMappingList ();
+
+ const PathMappingList &
+ operator =(const PathMappingList &rhs);
+
+ void
+ Append (const ConstString &path, const ConstString &replacement, bool notify);
+
+ void
+ Append (const PathMappingList &rhs, bool notify);
+
+ void
+ Clear (bool notify);
+
+ // By default, dump all pairs.
+ void
+ Dump (Stream *s, int pair_index=-1);
+
+ bool
+ IsEmpty() const
+ {
+ return m_pairs.empty();
+ }
+
+ size_t
+ GetSize () const
+ {
+ return m_pairs.size();
+ }
+
+ bool
+ GetPathsAtIndex (uint32_t idx, ConstString &path, ConstString &new_path) const;
+
+ void
+ Insert (const ConstString &path,
+ const ConstString &replacement,
+ uint32_t insert_idx,
+ bool notify);
+
+ bool
+ Remove (off_t index, bool notify);
+
+ bool
+ Remove (const ConstString &path, bool notify);
+
+ bool
+ Replace (const ConstString &path,
+ const ConstString &replacement,
+ bool notify);
+
+ bool
+ Replace (const ConstString &path,
+ const ConstString &replacement,
+ uint32_t index,
+ bool notify);
+ bool
+ RemapPath (const ConstString &path, ConstString &new_path) const;
+
+ //------------------------------------------------------------------
+ /// Remaps a source file given \a path into \a new_path.
+ ///
+ /// Remaps \a path if any source remappings match. This function
+ /// does NOT stat the file system so it can be used in tight loops
+ /// where debug info is being parsed.
+ ///
+ /// @param[in] path
+ /// The original source file path to try and remap.
+ ///
+ /// @param[out] new_path
+ /// The newly remapped filespec that is may or may not exist.
+ ///
+ /// @return
+ /// /b true if \a path was successfully located and \a new_path
+ /// is filled in with a new source path, \b false otherwise.
+ //------------------------------------------------------------------
+ bool
+ RemapPath (const char *path, std::string &new_path) const;
+
+
+ //------------------------------------------------------------------
+ /// Finds a source file given a file spec using the path remappings.
+ ///
+ /// Tries to resolve \a orig_spec by checking the path remappings.
+ /// It makes sure the file exists by checking with the file system,
+ /// so this call can be expensive if the remappings are on a network
+ /// or are even on the local file system, so use this function
+ /// sparingly (not in a tight debug info parsing loop).
+ ///
+ /// @param[in] orig_spec
+ /// The original source file path to try and remap.
+ ///
+ /// @param[out] new_spec
+ /// The newly remapped filespec that is guaranteed to exist.
+ ///
+ /// @return
+ /// /b true if \a orig_spec was successfully located and
+ /// \a new_spec is filled in with an existing file spec,
+ /// \b false otherwise.
+ //------------------------------------------------------------------
+ bool
+ FindFile (const FileSpec &orig_spec, FileSpec &new_spec) const;
+
+ uint32_t
+ FindIndexForPath (const ConstString &path) const;
+
+ uint32_t
+ GetModificationID() const
+ {
+ return m_mod_id;
+ }
+protected:
+ typedef std::pair <ConstString, ConstString> pair;
+ typedef std::vector <pair> collection;
+ typedef collection::iterator iterator;
+ typedef collection::const_iterator const_iterator;
+
+ iterator
+ FindIteratorForPath (const ConstString &path);
+
+ const_iterator
+ FindIteratorForPath (const ConstString &path) const;
+
+ collection m_pairs;
+ ChangedCallback m_callback;
+ void * m_callback_baton;
+ uint32_t m_mod_id; // Incremented anytime anything is added or removed.
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_PathMappingList_h_
diff --git a/include/lldb/Target/Platform.h b/include/lldb/Target/Platform.h
new file mode 100644
index 000000000000..b0a07946e74e
--- /dev/null
+++ b/include/lldb/Target/Platform.h
@@ -0,0 +1,755 @@
+//===-- Platform.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_Platform_h_
+#define liblldb_Platform_h_
+
+// C Includes
+// C++ Includes
+#include <map>
+#include <string>
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-public.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/PluginInterface.h"
+#include "lldb/Host/Mutex.h"
+
+namespace lldb_private {
+
+ //----------------------------------------------------------------------
+ /// @class Platform Platform.h "lldb/Target/Platform.h"
+ /// @brief A plug-in interface definition class for debug platform that
+ /// includes many platform abilities such as:
+ /// @li getting platform information such as supported architectures,
+ /// supported binary file formats and more
+ /// @li launching new processes
+ /// @li attaching to existing processes
+ /// @li download/upload files
+ /// @li execute shell commands
+ /// @li listing and getting info for existing processes
+ /// @li attaching and possibly debugging the platform's kernel
+ //----------------------------------------------------------------------
+ class Platform : public PluginInterface
+ {
+ public:
+
+ //------------------------------------------------------------------
+ /// Get the native host platform plug-in.
+ ///
+ /// There should only be one of these for each host that LLDB runs
+ /// upon that should be statically compiled in and registered using
+ /// preprocessor macros or other similar build mechanisms in a
+ /// PlatformSubclass::Initialize() function.
+ ///
+ /// This platform will be used as the default platform when launching
+ /// or attaching to processes unless another platform is specified.
+ //------------------------------------------------------------------
+ static lldb::PlatformSP
+ GetDefaultPlatform ();
+
+ static lldb::PlatformSP
+ GetPlatformForArchitecture (const ArchSpec &arch,
+ ArchSpec *platform_arch_ptr);
+
+ static const char *
+ GetHostPlatformName ();
+
+ static void
+ SetDefaultPlatform (const lldb::PlatformSP &platform_sp);
+
+ static lldb::PlatformSP
+ Create (const char *platform_name, Error &error);
+
+ static lldb::PlatformSP
+ Create (const ArchSpec &arch, ArchSpec *platform_arch_ptr, Error &error);
+
+ static uint32_t
+ GetNumConnectedRemotePlatforms ();
+
+ static lldb::PlatformSP
+ GetConnectedRemotePlatformAtIndex (uint32_t idx);
+
+ //------------------------------------------------------------------
+ /// Default Constructor
+ //------------------------------------------------------------------
+ Platform (bool is_host_platform);
+
+ //------------------------------------------------------------------
+ /// Destructor.
+ ///
+ /// The destructor is virtual since this class is designed to be
+ /// inherited from by the plug-in instance.
+ //------------------------------------------------------------------
+ virtual
+ ~Platform();
+
+ //------------------------------------------------------------------
+ /// Find a platform plugin for a given process.
+ ///
+ /// Scans the installed Platform plug-ins and tries to find
+ /// an instance that can be used for \a process
+ ///
+ /// @param[in] process
+ /// The process for which to try and locate a platform
+ /// plug-in instance.
+ ///
+ /// @param[in] plugin_name
+ /// An optional name of a specific platform plug-in that
+ /// should be used. If NULL, pick the best plug-in.
+ //------------------------------------------------------------------
+ static Platform*
+ FindPlugin (Process *process, const ConstString &plugin_name);
+
+ //------------------------------------------------------------------
+ /// Set the target's executable based off of the existing
+ /// architecture information in \a target given a path to an
+ /// executable \a exe_file.
+ ///
+ /// Each platform knows the architectures that it supports and can
+ /// select the correct architecture slice within \a exe_file by
+ /// inspecting the architecture in \a target. If the target had an
+ /// architecture specified, then in can try and obey that request
+ /// and optionally fail if the architecture doesn't match up.
+ /// If no architecture is specified, the platform should select the
+ /// default architecture from \a exe_file. Any application bundles
+ /// or executable wrappers can also be inspected for the actual
+ /// application binary within the bundle that should be used.
+ ///
+ /// @return
+ /// Returns \b true if this Platform plug-in was able to find
+ /// a suitable executable, \b false otherwise.
+ //------------------------------------------------------------------
+ virtual Error
+ ResolveExecutable (const FileSpec &exe_file,
+ const ArchSpec &arch,
+ lldb::ModuleSP &module_sp,
+ const FileSpecList *module_search_paths_ptr);
+
+
+ //------------------------------------------------------------------
+ /// Find a symbol file given a symbol file module specification.
+ ///
+ /// Each platform might have tricks to find symbol files for an
+ /// executable given information in a symbol file ModuleSpec. Some
+ /// platforms might also support symbol files that are bundles and
+ /// know how to extract the right symbol file given a bundle.
+ ///
+ /// @param[in] target
+ /// The target in which we are trying to resolve the symbol file.
+ /// The target has a list of modules that we might be able to
+ /// use in order to help find the right symbol file. If the
+ /// "m_file" or "m_platform_file" entries in the \a sym_spec
+ /// are filled in, then we might be able to locate a module in
+ /// the target, extract its UUID and locate a symbol file.
+ /// If just the "m_uuid" is specified, then we might be able
+ /// to find the module in the target that matches that UUID
+ /// and pair the symbol file along with it. If just "m_symbol_file"
+ /// is specified, we can use a variety of tricks to locate the
+ /// symbols in an SDK, PDK, or other development kit location.
+ ///
+ /// @param[in] sym_spec
+ /// A module spec that describes some information about the
+ /// symbol file we are trying to resolve. The ModuleSpec might
+ /// contain the following:
+ /// m_file - A full or partial path to an executable from the
+ /// target (might be empty).
+ /// m_platform_file - Another executable hint that contains
+ /// the path to the file as known on the
+ /// local/remote platform.
+ /// m_symbol_file - A full or partial path to a symbol file
+ /// or symbol bundle that should be used when
+ /// trying to resolve the symbol file.
+ /// m_arch - The architecture we are looking for when resolving
+ /// the symbol file.
+ /// m_uuid - The UUID of the executable and symbol file. This
+ /// can often be used to match up an exectuable with
+ /// a symbol file, or resolve an symbol file in a
+ /// symbol file bundle.
+ ///
+ /// @param[out] sym_file
+ /// The resolved symbol file spec if the returned error
+ /// indicates succes.
+ ///
+ /// @return
+ /// Returns an error that describes success or failure.
+ //------------------------------------------------------------------
+ virtual Error
+ ResolveSymbolFile (Target &target,
+ const ModuleSpec &sym_spec,
+ FileSpec &sym_file);
+
+ //------------------------------------------------------------------
+ /// Resolves the FileSpec to a (possibly) remote path. Remote
+ /// platforms must override this to resolve to a path on the remote
+ /// side.
+ //------------------------------------------------------------------
+ virtual bool
+ ResolveRemotePath (const FileSpec &platform_path,
+ FileSpec &resolved_platform_path);
+
+ bool
+ GetOSVersion (uint32_t &major,
+ uint32_t &minor,
+ uint32_t &update);
+
+ bool
+ SetOSVersion (uint32_t major,
+ uint32_t minor,
+ uint32_t update);
+
+ bool
+ GetOSBuildString (std::string &s);
+
+ bool
+ GetOSKernelDescription (std::string &s);
+
+ // Returns the the hostname if we are connected, else the short plugin
+ // name.
+ ConstString
+ GetName ();
+
+ virtual const char *
+ GetHostname ();
+
+ virtual const char *
+ GetDescription () = 0;
+
+ //------------------------------------------------------------------
+ /// Report the current status for this platform.
+ ///
+ /// The returned string usually involves returning the OS version
+ /// (if available), and any SDK directory that might be being used
+ /// for local file caching, and if connected a quick blurb about
+ /// what this platform is connected to.
+ //------------------------------------------------------------------
+ virtual void
+ GetStatus (Stream &strm);
+
+ //------------------------------------------------------------------
+ // Subclasses must be able to fetch the current OS version
+ //
+ // Remote classes must be connected for this to succeed. Local
+ // subclasses don't need to override this function as it will just
+ // call the Host::GetOSVersion().
+ //------------------------------------------------------------------
+ virtual bool
+ GetRemoteOSVersion ()
+ {
+ return false;
+ }
+
+ virtual bool
+ GetRemoteOSBuildString (std::string &s)
+ {
+ s.clear();
+ return false;
+ }
+
+ virtual bool
+ GetRemoteOSKernelDescription (std::string &s)
+ {
+ s.clear();
+ return false;
+ }
+
+ // Remote Platform subclasses need to override this function
+ virtual ArchSpec
+ GetRemoteSystemArchitecture ()
+ {
+ return ArchSpec(); // Return an invalid architecture
+ }
+
+ virtual const char *
+ GetUserName (uint32_t uid);
+
+ virtual const char *
+ GetGroupName (uint32_t gid);
+
+ //------------------------------------------------------------------
+ /// Locate a file for a platform.
+ ///
+ /// The default implementation of this function will return the same
+ /// file patch in \a local_file as was in \a platform_file.
+ ///
+ /// @param[in] platform_file
+ /// The platform file path to locate and cache locally.
+ ///
+ /// @param[in] uuid_ptr
+ /// If we know the exact UUID of the file we are looking for, it
+ /// can be specified. If it is not specified, we might now know
+ /// the exact file. The UUID is usually some sort of MD5 checksum
+ /// for the file and is sometimes known by dynamic linkers/loaders.
+ /// If the UUID is known, it is best to supply it to platform
+ /// file queries to ensure we are finding the correct file, not
+ /// just a file at the correct path.
+ ///
+ /// @param[out] local_file
+ /// A locally cached version of the platform file. For platforms
+ /// that describe the current host computer, this will just be
+ /// the same file. For remote platforms, this file might come from
+ /// and SDK directory, or might need to be sync'ed over to the
+ /// current machine for efficient debugging access.
+ ///
+ /// @return
+ /// An error object.
+ //------------------------------------------------------------------
+ virtual Error
+ GetFile (const FileSpec &platform_file,
+ const UUID *uuid_ptr,
+ FileSpec &local_file);
+
+ //----------------------------------------------------------------------
+ // Locate the scripting resource given a module specification.
+ //
+ // Locating the file should happen only on the local computer or using
+ // the current computers global settings.
+ //----------------------------------------------------------------------
+ virtual FileSpecList
+ LocateExecutableScriptingResources (Target *target,
+ Module &module);
+
+ virtual Error
+ GetSharedModule (const ModuleSpec &module_spec,
+ lldb::ModuleSP &module_sp,
+ const FileSpecList *module_search_paths_ptr,
+ lldb::ModuleSP *old_module_sp_ptr,
+ bool *did_create_ptr);
+
+ virtual Error
+ ConnectRemote (Args& args);
+
+ virtual Error
+ DisconnectRemote ();
+
+ //------------------------------------------------------------------
+ /// Get the platform's supported architectures in the order in which
+ /// they should be searched.
+ ///
+ /// @param[in] idx
+ /// A zero based architecture index
+ ///
+ /// @param[out] arch
+ /// A copy of the archgitecture at index if the return value is
+ /// \b true.
+ ///
+ /// @return
+ /// \b true if \a arch was filled in and is valid, \b false
+ /// otherwise.
+ //------------------------------------------------------------------
+ virtual bool
+ GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) = 0;
+
+ virtual size_t
+ GetSoftwareBreakpointTrapOpcode (Target &target,
+ BreakpointSite *bp_site) = 0;
+
+ //------------------------------------------------------------------
+ /// Launch a new process on a platform, not necessarily for
+ /// debugging, it could be just for running the process.
+ //------------------------------------------------------------------
+ virtual Error
+ LaunchProcess (ProcessLaunchInfo &launch_info);
+
+ //------------------------------------------------------------------
+ /// Lets a platform answer if it is compatible with a given
+ /// architecture and the target triple contained within.
+ //------------------------------------------------------------------
+ virtual bool
+ IsCompatibleArchitecture (const ArchSpec &arch,
+ bool exact_arch_match,
+ ArchSpec *compatible_arch_ptr);
+
+ //------------------------------------------------------------------
+ /// Not all platforms will support debugging a process by spawning
+ /// somehow halted for a debugger (specified using the
+ /// "eLaunchFlagDebug" launch flag) and then attaching. If your
+ /// platform doesn't support this, override this function and return
+ /// false.
+ //------------------------------------------------------------------
+ virtual bool
+ CanDebugProcess ()
+ {
+ return true;
+ }
+
+ //------------------------------------------------------------------
+ /// Subclasses should NOT need to implement this function as it uses
+ /// the Platform::LaunchProcess() followed by Platform::Attach ()
+ //------------------------------------------------------------------
+ lldb::ProcessSP
+ DebugProcess (ProcessLaunchInfo &launch_info,
+ Debugger &debugger,
+ Target *target, // Can be NULL, if NULL create a new target, else use existing one
+ Listener &listener,
+ Error &error);
+
+ //------------------------------------------------------------------
+ /// Attach to an existing process using a process ID.
+ ///
+ /// Each platform subclass needs to implement this function and
+ /// attempt to attach to the process with the process ID of \a pid.
+ /// The platform subclass should return an appropriate ProcessSP
+ /// subclass that is attached to the process, or an empty shared
+ /// pointer with an appriopriate error.
+ ///
+ /// @param[in] pid
+ /// The process ID that we should attempt to attach to.
+ ///
+ /// @return
+ /// An appropriate ProcessSP containing a valid shared pointer
+ /// to the default Process subclass for the platform that is
+ /// attached to the process, or an empty shared pointer with an
+ /// appriopriate error fill into the \a error object.
+ //------------------------------------------------------------------
+ virtual lldb::ProcessSP
+ Attach (ProcessAttachInfo &attach_info,
+ Debugger &debugger,
+ Target *target, // Can be NULL, if NULL create a new target, else use existing one
+ Listener &listener,
+ Error &error) = 0;
+
+ //------------------------------------------------------------------
+ /// Attach to an existing process by process name.
+ ///
+ /// This function is not meant to be overridden by Process
+ /// subclasses. It will first call
+ /// Process::WillAttach (const char *) and if that returns \b
+ /// true, Process::DoAttach (const char *) will be called to
+ /// actually do the attach. If DoAttach returns \b true, then
+ /// Process::DidAttach() will be called.
+ ///
+ /// @param[in] process_name
+ /// A process name to match against the current process list.
+ ///
+ /// @return
+ /// Returns \a pid if attaching was successful, or
+ /// LLDB_INVALID_PROCESS_ID if attaching fails.
+ //------------------------------------------------------------------
+// virtual lldb::ProcessSP
+// Attach (const char *process_name,
+// bool wait_for_launch,
+// Error &error) = 0;
+
+ //------------------------------------------------------------------
+ // The base class Platform will take care of the host platform.
+ // Subclasses will need to fill in the remote case.
+ //------------------------------------------------------------------
+ virtual uint32_t
+ FindProcesses (const ProcessInstanceInfoMatch &match_info,
+ ProcessInstanceInfoList &proc_infos);
+
+ virtual bool
+ GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &proc_info);
+
+ //------------------------------------------------------------------
+ // Set a breakpoint on all functions that can end up creating a thread
+ // for this platform. This is needed when running expressions and
+ // also for process control.
+ //------------------------------------------------------------------
+ virtual lldb::BreakpointSP
+ SetThreadCreationBreakpoint (Target &target);
+
+
+ const std::string &
+ GetRemoteURL () const
+ {
+ return m_remote_url;
+ }
+
+ bool
+ IsHost () const
+ {
+ return m_is_host; // Is this the default host platform?
+ }
+
+ bool
+ IsRemote () const
+ {
+ return !m_is_host;
+ }
+
+ virtual bool
+ IsConnected () const
+ {
+ // Remote subclasses should override this function
+ return IsHost();
+ }
+
+ const ArchSpec &
+ GetSystemArchitecture();
+
+ void
+ SetSystemArchitecture (const ArchSpec &arch)
+ {
+ m_system_arch = arch;
+ if (IsHost())
+ m_os_version_set_while_connected = m_system_arch.IsValid();
+ }
+
+ // Used for column widths
+ size_t
+ GetMaxUserIDNameLength() const
+ {
+ return m_max_uid_name_len;
+ }
+ // Used for column widths
+ size_t
+ GetMaxGroupIDNameLength() const
+ {
+ return m_max_gid_name_len;
+ }
+
+ const ConstString &
+ GetSDKRootDirectory () const
+ {
+ return m_sdk_sysroot;
+ }
+
+ void
+ SetSDKRootDirectory (const ConstString &dir)
+ {
+ m_sdk_sysroot = dir;
+ }
+
+ const ConstString &
+ GetSDKBuild () const
+ {
+ return m_sdk_build;
+ }
+
+ void
+ SetSDKBuild (const ConstString &sdk_build)
+ {
+ m_sdk_build = sdk_build;
+ }
+
+ // There may be modules that we don't want to find by default for operations like "setting breakpoint by name".
+ // The platform will return "true" from this call if the passed in module happens to be one of these.
+
+ virtual bool
+ ModuleIsExcludedForNonModuleSpecificSearches (Target &target, const lldb::ModuleSP &module_sp)
+ {
+ return false;
+ }
+
+ virtual size_t
+ GetEnvironment (StringList &environment);
+
+ protected:
+ bool m_is_host;
+ // Set to true when we are able to actually set the OS version while
+ // being connected. For remote platforms, we might set the version ahead
+ // of time before we actually connect and this version might change when
+ // we actually connect to a remote platform. For the host platform this
+ // will be set to the once we call Host::GetOSVersion().
+ bool m_os_version_set_while_connected;
+ bool m_system_arch_set_while_connected;
+ ConstString m_sdk_sysroot; // the root location of where the SDK files are all located
+ ConstString m_sdk_build;
+ std::string m_remote_url;
+ std::string m_name;
+ uint32_t m_major_os_version;
+ uint32_t m_minor_os_version;
+ uint32_t m_update_os_version;
+ ArchSpec m_system_arch; // The architecture of the kernel or the remote platform
+ typedef std::map<uint32_t, ConstString> IDToNameMap;
+ Mutex m_uid_map_mutex;
+ Mutex m_gid_map_mutex;
+ IDToNameMap m_uid_map;
+ IDToNameMap m_gid_map;
+ size_t m_max_uid_name_len;
+ size_t m_max_gid_name_len;
+
+ const char *
+ GetCachedUserName (uint32_t uid)
+ {
+ Mutex::Locker locker (m_uid_map_mutex);
+ IDToNameMap::iterator pos = m_uid_map.find (uid);
+ if (pos != m_uid_map.end())
+ {
+ // return the empty string if our string is NULL
+ // so we can tell when things were in the negative
+ // cached (didn't find a valid user name, don't keep
+ // trying)
+ return pos->second.AsCString("");
+ }
+ return NULL;
+ }
+
+ const char *
+ SetCachedUserName (uint32_t uid, const char *name, size_t name_len)
+ {
+ Mutex::Locker locker (m_uid_map_mutex);
+ ConstString const_name (name);
+ m_uid_map[uid] = const_name;
+ if (m_max_uid_name_len < name_len)
+ m_max_uid_name_len = name_len;
+ // Const strings lives forever in our const string pool, so we can return the const char *
+ return const_name.GetCString();
+ }
+
+ void
+ SetUserNameNotFound (uint32_t uid)
+ {
+ Mutex::Locker locker (m_uid_map_mutex);
+ m_uid_map[uid] = ConstString();
+ }
+
+
+ void
+ ClearCachedUserNames ()
+ {
+ Mutex::Locker locker (m_uid_map_mutex);
+ m_uid_map.clear();
+ }
+
+ const char *
+ GetCachedGroupName (uint32_t gid)
+ {
+ Mutex::Locker locker (m_gid_map_mutex);
+ IDToNameMap::iterator pos = m_gid_map.find (gid);
+ if (pos != m_gid_map.end())
+ {
+ // return the empty string if our string is NULL
+ // so we can tell when things were in the negative
+ // cached (didn't find a valid group name, don't keep
+ // trying)
+ return pos->second.AsCString("");
+ }
+ return NULL;
+ }
+
+ const char *
+ SetCachedGroupName (uint32_t gid, const char *name, size_t name_len)
+ {
+ Mutex::Locker locker (m_gid_map_mutex);
+ ConstString const_name (name);
+ m_gid_map[gid] = const_name;
+ if (m_max_gid_name_len < name_len)
+ m_max_gid_name_len = name_len;
+ // Const strings lives forever in our const string pool, so we can return the const char *
+ return const_name.GetCString();
+ }
+
+ void
+ SetGroupNameNotFound (uint32_t gid)
+ {
+ Mutex::Locker locker (m_gid_map_mutex);
+ m_gid_map[gid] = ConstString();
+ }
+
+ void
+ ClearCachedGroupNames ()
+ {
+ Mutex::Locker locker (m_gid_map_mutex);
+ m_gid_map.clear();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN (Platform);
+ };
+
+
+ class PlatformList
+ {
+ public:
+ PlatformList() :
+ m_mutex (Mutex::eMutexTypeRecursive),
+ m_platforms (),
+ m_selected_platform_sp()
+ {
+ }
+
+ ~PlatformList()
+ {
+ }
+
+ void
+ Append (const lldb::PlatformSP &platform_sp, bool set_selected)
+ {
+ Mutex::Locker locker (m_mutex);
+ m_platforms.push_back (platform_sp);
+ if (set_selected)
+ m_selected_platform_sp = m_platforms.back();
+ }
+
+ size_t
+ GetSize()
+ {
+ Mutex::Locker locker (m_mutex);
+ return m_platforms.size();
+ }
+
+ lldb::PlatformSP
+ GetAtIndex (uint32_t idx)
+ {
+ lldb::PlatformSP platform_sp;
+ {
+ Mutex::Locker locker (m_mutex);
+ if (idx < m_platforms.size())
+ platform_sp = m_platforms[idx];
+ }
+ return platform_sp;
+ }
+
+ //------------------------------------------------------------------
+ /// Select the active platform.
+ ///
+ /// In order to debug remotely, other platform's can be remotely
+ /// connected to and set as the selected platform for any subsequent
+ /// debugging. This allows connection to remote targets and allows
+ /// the ability to discover process info, launch and attach to remote
+ /// processes.
+ //------------------------------------------------------------------
+ lldb::PlatformSP
+ GetSelectedPlatform ()
+ {
+ Mutex::Locker locker (m_mutex);
+ if (!m_selected_platform_sp && !m_platforms.empty())
+ m_selected_platform_sp = m_platforms.front();
+
+ return m_selected_platform_sp;
+ }
+
+ void
+ SetSelectedPlatform (const lldb::PlatformSP &platform_sp)
+ {
+ if (platform_sp)
+ {
+ Mutex::Locker locker (m_mutex);
+ const size_t num_platforms = m_platforms.size();
+ for (size_t idx=0; idx<num_platforms; ++idx)
+ {
+ if (m_platforms[idx].get() == platform_sp.get())
+ {
+ m_selected_platform_sp = m_platforms[idx];
+ return;
+ }
+ }
+ m_platforms.push_back (platform_sp);
+ m_selected_platform_sp = m_platforms.back();
+ }
+ }
+
+ protected:
+ typedef std::vector<lldb::PlatformSP> collection;
+ mutable Mutex m_mutex;
+ collection m_platforms;
+ lldb::PlatformSP m_selected_platform_sp;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN (PlatformList);
+ };
+} // namespace lldb_private
+
+#endif // liblldb_Platform_h_
diff --git a/include/lldb/Target/Process.h b/include/lldb/Target/Process.h
new file mode 100644
index 000000000000..ef89a1eb1418
--- /dev/null
+++ b/include/lldb/Target/Process.h
@@ -0,0 +1,3786 @@
+//===-- Process.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_Process_h_
+#define liblldb_Process_h_
+
+// C Includes
+#include <limits.h>
+#include <spawn.h>
+
+// C++ Includes
+#include <list>
+#include <iosfwd>
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Broadcaster.h"
+#include "lldb/Core/Communication.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Event.h"
+#include "lldb/Core/RangeMap.h"
+#include "lldb/Core/StringList.h"
+#include "lldb/Core/ThreadSafeValue.h"
+#include "lldb/Core/PluginInterface.h"
+#include "lldb/Core/UserSettingsController.h"
+#include "lldb/Breakpoint/BreakpointSiteList.h"
+#include "lldb/Expression/ClangPersistentVariables.h"
+#include "lldb/Expression/IRDynamicChecks.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Host/ProcessRunLock.h"
+#include "lldb/Interpreter/Args.h"
+#include "lldb/Interpreter/Options.h"
+#include "lldb/Target/ExecutionContextScope.h"
+#include "lldb/Target/Memory.h"
+#include "lldb/Target/ThreadList.h"
+#include "lldb/Target/UnixSignals.h"
+#include "lldb/Utility/PseudoTerminal.h"
+
+namespace lldb_private {
+
+//----------------------------------------------------------------------
+// ProcessProperties
+//----------------------------------------------------------------------
+class ProcessProperties : public Properties
+{
+public:
+ ProcessProperties(bool is_global);
+
+ virtual
+ ~ProcessProperties();
+
+ bool
+ GetDisableMemoryCache() const;
+
+ Args
+ GetExtraStartupCommands () const;
+
+ void
+ SetExtraStartupCommands (const Args &args);
+
+ FileSpec
+ GetPythonOSPluginPath () const;
+
+ void
+ SetPythonOSPluginPath (const FileSpec &file);
+
+ bool
+ GetIgnoreBreakpointsInExpressions () const;
+
+ void
+ SetIgnoreBreakpointsInExpressions (bool ignore);
+
+ bool
+ GetUnwindOnErrorInExpressions () const;
+
+ void
+ SetUnwindOnErrorInExpressions (bool ignore);
+
+ bool
+ GetStopOnSharedLibraryEvents () const;
+
+ void
+ SetStopOnSharedLibraryEvents (bool stop);
+
+ bool
+ GetDetachKeepsStopped () const;
+
+ void
+ SetDetachKeepsStopped (bool keep_stopped);
+};
+
+typedef std::shared_ptr<ProcessProperties> ProcessPropertiesSP;
+
+//----------------------------------------------------------------------
+// ProcessInfo
+//
+// A base class for information for a process. This can be used to fill
+// out information for a process prior to launching it, or it can be
+// used for an instance of a process and can be filled in with the
+// existing values for that process.
+//----------------------------------------------------------------------
+class ProcessInfo
+{
+public:
+ ProcessInfo () :
+ m_executable (),
+ m_arguments (),
+ m_environment (),
+ m_uid (UINT32_MAX),
+ m_gid (UINT32_MAX),
+ m_arch(),
+ m_pid (LLDB_INVALID_PROCESS_ID)
+ {
+ }
+
+ ProcessInfo (const char *name,
+ const ArchSpec &arch,
+ lldb::pid_t pid) :
+ m_executable (name, false),
+ m_arguments (),
+ m_environment(),
+ m_uid (UINT32_MAX),
+ m_gid (UINT32_MAX),
+ m_arch (arch),
+ m_pid (pid)
+ {
+ }
+
+ void
+ Clear ()
+ {
+ m_executable.Clear();
+ m_arguments.Clear();
+ m_environment.Clear();
+ m_uid = UINT32_MAX;
+ m_gid = UINT32_MAX;
+ m_arch.Clear();
+ m_pid = LLDB_INVALID_PROCESS_ID;
+ }
+
+ const char *
+ GetName() const
+ {
+ return m_executable.GetFilename().GetCString();
+ }
+
+ size_t
+ GetNameLength() const
+ {
+ return m_executable.GetFilename().GetLength();
+ }
+
+ FileSpec &
+ GetExecutableFile ()
+ {
+ return m_executable;
+ }
+
+ void
+ SetExecutableFile (const FileSpec &exe_file, bool add_exe_file_as_first_arg)
+ {
+ if (exe_file)
+ {
+ m_executable = exe_file;
+ if (add_exe_file_as_first_arg)
+ {
+ char filename[PATH_MAX];
+ if (exe_file.GetPath(filename, sizeof(filename)))
+ m_arguments.InsertArgumentAtIndex (0, filename);
+ }
+ }
+ else
+ {
+ m_executable.Clear();
+ }
+ }
+
+ const FileSpec &
+ GetExecutableFile () const
+ {
+ return m_executable;
+ }
+
+ uint32_t
+ GetUserID() const
+ {
+ return m_uid;
+ }
+
+ uint32_t
+ GetGroupID() const
+ {
+ return m_gid;
+ }
+
+ bool
+ UserIDIsValid () const
+ {
+ return m_uid != UINT32_MAX;
+ }
+
+ bool
+ GroupIDIsValid () const
+ {
+ return m_gid != UINT32_MAX;
+ }
+
+ void
+ SetUserID (uint32_t uid)
+ {
+ m_uid = uid;
+ }
+
+ void
+ SetGroupID (uint32_t gid)
+ {
+ m_gid = gid;
+ }
+
+ ArchSpec &
+ GetArchitecture ()
+ {
+ return m_arch;
+ }
+
+ const ArchSpec &
+ GetArchitecture () const
+ {
+ return m_arch;
+ }
+
+ lldb::pid_t
+ GetProcessID () const
+ {
+ return m_pid;
+ }
+
+ void
+ SetProcessID (lldb::pid_t pid)
+ {
+ m_pid = pid;
+ }
+
+ bool
+ ProcessIDIsValid() const
+ {
+ return m_pid != LLDB_INVALID_PROCESS_ID;
+ }
+
+ void
+ Dump (Stream &s, Platform *platform) const;
+
+ Args &
+ GetArguments ()
+ {
+ return m_arguments;
+ }
+
+ const Args &
+ GetArguments () const
+ {
+ return m_arguments;
+ }
+
+ const char *
+ GetArg0 () const
+ {
+ if (m_arg0.empty())
+ return NULL;
+ return m_arg0.c_str();
+ }
+
+ void
+ SetArg0 (const char *arg)
+ {
+ if (arg && arg[0])
+ m_arg0 = arg;
+ else
+ m_arg0.clear();
+ }
+
+ void
+ SetArguments (const Args& args, bool first_arg_is_executable);
+
+ void
+ SetArguments (char const **argv, bool first_arg_is_executable);
+
+ Args &
+ GetEnvironmentEntries ()
+ {
+ return m_environment;
+ }
+
+ const Args &
+ GetEnvironmentEntries () const
+ {
+ return m_environment;
+ }
+
+protected:
+ FileSpec m_executable;
+ std::string m_arg0; // argv[0] if supported. If empty, then use m_executable.
+ // Not all process plug-ins support specifying an argv[0]
+ // that differs from the resolved platform executable
+ // (which is in m_executable)
+ Args m_arguments; // All program arguments except argv[0]
+ Args m_environment;
+ uint32_t m_uid;
+ uint32_t m_gid;
+ ArchSpec m_arch;
+ lldb::pid_t m_pid;
+};
+
+//----------------------------------------------------------------------
+// ProcessInstanceInfo
+//
+// Describes an existing process and any discoverable information that
+// pertains to that process.
+//----------------------------------------------------------------------
+class ProcessInstanceInfo : public ProcessInfo
+{
+public:
+ ProcessInstanceInfo () :
+ ProcessInfo (),
+ m_euid (UINT32_MAX),
+ m_egid (UINT32_MAX),
+ m_parent_pid (LLDB_INVALID_PROCESS_ID)
+ {
+ }
+
+ ProcessInstanceInfo (const char *name,
+ const ArchSpec &arch,
+ lldb::pid_t pid) :
+ ProcessInfo (name, arch, pid),
+ m_euid (UINT32_MAX),
+ m_egid (UINT32_MAX),
+ m_parent_pid (LLDB_INVALID_PROCESS_ID)
+ {
+ }
+
+ void
+ Clear ()
+ {
+ ProcessInfo::Clear();
+ m_euid = UINT32_MAX;
+ m_egid = UINT32_MAX;
+ m_parent_pid = LLDB_INVALID_PROCESS_ID;
+ }
+
+ uint32_t
+ GetEffectiveUserID() const
+ {
+ return m_euid;
+ }
+
+ uint32_t
+ GetEffectiveGroupID() const
+ {
+ return m_egid;
+ }
+
+ bool
+ EffectiveUserIDIsValid () const
+ {
+ return m_euid != UINT32_MAX;
+ }
+
+ bool
+ EffectiveGroupIDIsValid () const
+ {
+ return m_egid != UINT32_MAX;
+ }
+
+ void
+ SetEffectiveUserID (uint32_t uid)
+ {
+ m_euid = uid;
+ }
+
+ void
+ SetEffectiveGroupID (uint32_t gid)
+ {
+ m_egid = gid;
+ }
+
+ lldb::pid_t
+ GetParentProcessID () const
+ {
+ return m_parent_pid;
+ }
+
+ void
+ SetParentProcessID (lldb::pid_t pid)
+ {
+ m_parent_pid = pid;
+ }
+
+ bool
+ ParentProcessIDIsValid() const
+ {
+ return m_parent_pid != LLDB_INVALID_PROCESS_ID;
+ }
+
+ void
+ Dump (Stream &s, Platform *platform) const;
+
+ static void
+ DumpTableHeader (Stream &s, Platform *platform, bool show_args, bool verbose);
+
+ void
+ DumpAsTableRow (Stream &s, Platform *platform, bool show_args, bool verbose) const;
+
+protected:
+ uint32_t m_euid;
+ uint32_t m_egid;
+ lldb::pid_t m_parent_pid;
+};
+
+
+//----------------------------------------------------------------------
+// ProcessLaunchInfo
+//
+// Describes any information that is required to launch a process.
+//----------------------------------------------------------------------
+
+class ProcessLaunchInfo : public ProcessInfo
+{
+public:
+
+ class FileAction
+ {
+ public:
+ enum Action
+ {
+ eFileActionNone,
+ eFileActionClose,
+ eFileActionDuplicate,
+ eFileActionOpen
+ };
+
+
+ FileAction () :
+ m_action (eFileActionNone),
+ m_fd (-1),
+ m_arg (-1),
+ m_path ()
+ {
+ }
+
+ void
+ Clear()
+ {
+ m_action = eFileActionNone;
+ m_fd = -1;
+ m_arg = -1;
+ m_path.clear();
+ }
+
+ bool
+ Close (int fd);
+
+ bool
+ Duplicate (int fd, int dup_fd);
+
+ bool
+ Open (int fd, const char *path, bool read, bool write);
+
+ static bool
+ AddPosixSpawnFileAction (posix_spawn_file_actions_t *file_actions,
+ const FileAction *info,
+ Log *log,
+ Error& error);
+
+ int
+ GetFD () const
+ {
+ return m_fd;
+ }
+
+ Action
+ GetAction () const
+ {
+ return m_action;
+ }
+
+ int
+ GetActionArgument () const
+ {
+ return m_arg;
+ }
+
+ const char *
+ GetPath () const
+ {
+ if (m_path.empty())
+ return NULL;
+ return m_path.c_str();
+ }
+
+ protected:
+ Action m_action; // The action for this file
+ int m_fd; // An existing file descriptor
+ int m_arg; // oflag for eFileActionOpen*, dup_fd for eFileActionDuplicate
+ std::string m_path; // A file path to use for opening after fork or posix_spawn
+ };
+
+ ProcessLaunchInfo () :
+ ProcessInfo(),
+ m_working_dir (),
+ m_plugin_name (),
+ m_shell (),
+ m_flags (0),
+ m_file_actions (),
+ m_pty (),
+ m_resume_count (0),
+ m_monitor_callback (NULL),
+ m_monitor_callback_baton (NULL),
+ m_monitor_signals (false)
+ {
+ }
+
+ ProcessLaunchInfo (const char *stdin_path,
+ const char *stdout_path,
+ const char *stderr_path,
+ const char *working_directory,
+ uint32_t launch_flags) :
+ ProcessInfo(),
+ m_working_dir (),
+ m_plugin_name (),
+ m_shell (),
+ m_flags (launch_flags),
+ m_file_actions (),
+ m_pty (),
+ m_resume_count (0),
+ m_monitor_callback (NULL),
+ m_monitor_callback_baton (NULL),
+ m_monitor_signals (false)
+ {
+ if (stdin_path)
+ {
+ ProcessLaunchInfo::FileAction file_action;
+ const bool read = true;
+ const bool write = false;
+ if (file_action.Open(STDIN_FILENO, stdin_path, read, write))
+ AppendFileAction (file_action);
+ }
+ if (stdout_path)
+ {
+ ProcessLaunchInfo::FileAction file_action;
+ const bool read = false;
+ const bool write = true;
+ if (file_action.Open(STDOUT_FILENO, stdout_path, read, write))
+ AppendFileAction (file_action);
+ }
+ if (stderr_path)
+ {
+ ProcessLaunchInfo::FileAction file_action;
+ const bool read = false;
+ const bool write = true;
+ if (file_action.Open(STDERR_FILENO, stderr_path, read, write))
+ AppendFileAction (file_action);
+ }
+ if (working_directory)
+ SetWorkingDirectory(working_directory);
+ }
+
+ void
+ AppendFileAction (const FileAction &info)
+ {
+ m_file_actions.push_back(info);
+ }
+
+ bool
+ AppendCloseFileAction (int fd)
+ {
+ FileAction file_action;
+ if (file_action.Close (fd))
+ {
+ AppendFileAction (file_action);
+ return true;
+ }
+ return false;
+ }
+
+ bool
+ AppendDuplicateFileAction (int fd, int dup_fd)
+ {
+ FileAction file_action;
+ if (file_action.Duplicate (fd, dup_fd))
+ {
+ AppendFileAction (file_action);
+ return true;
+ }
+ return false;
+ }
+
+ bool
+ AppendOpenFileAction (int fd, const char *path, bool read, bool write)
+ {
+ FileAction file_action;
+ if (file_action.Open (fd, path, read, write))
+ {
+ AppendFileAction (file_action);
+ return true;
+ }
+ return false;
+ }
+
+ bool
+ AppendSuppressFileAction (int fd, bool read, bool write)
+ {
+ FileAction file_action;
+ if (file_action.Open (fd, "/dev/null", read, write))
+ {
+ AppendFileAction (file_action);
+ return true;
+ }
+ return false;
+ }
+
+ void
+ FinalizeFileActions (Target *target,
+ bool default_to_use_pty);
+
+ size_t
+ GetNumFileActions () const
+ {
+ return m_file_actions.size();
+ }
+
+ const FileAction *
+ GetFileActionAtIndex (size_t idx) const
+ {
+ if (idx < m_file_actions.size())
+ return &m_file_actions[idx];
+ return NULL;
+ }
+
+ const FileAction *
+ GetFileActionForFD (int fd) const
+ {
+ for (size_t idx=0, count=m_file_actions.size(); idx < count; ++idx)
+ {
+ if (m_file_actions[idx].GetFD () == fd)
+ return &m_file_actions[idx];
+ }
+ return NULL;
+ }
+
+ Flags &
+ GetFlags ()
+ {
+ return m_flags;
+ }
+
+ const Flags &
+ GetFlags () const
+ {
+ return m_flags;
+ }
+
+ const char *
+ GetWorkingDirectory () const
+ {
+ if (m_working_dir.empty())
+ return NULL;
+ return m_working_dir.c_str();
+ }
+
+ void
+ SetWorkingDirectory (const char *working_dir)
+ {
+ if (working_dir && working_dir[0])
+ m_working_dir.assign (working_dir);
+ else
+ m_working_dir.clear();
+ }
+
+ void
+ SwapWorkingDirectory (std::string &working_dir)
+ {
+ m_working_dir.swap (working_dir);
+ }
+
+
+ const char *
+ GetProcessPluginName () const
+ {
+ if (m_plugin_name.empty())
+ return NULL;
+ return m_plugin_name.c_str();
+ }
+
+ void
+ SetProcessPluginName (const char *plugin)
+ {
+ if (plugin && plugin[0])
+ m_plugin_name.assign (plugin);
+ else
+ m_plugin_name.clear();
+ }
+
+ const char *
+ GetShell () const
+ {
+ if (m_shell.empty())
+ return NULL;
+ return m_shell.c_str();
+ }
+
+ void
+ SetShell (const char * path)
+ {
+ if (path && path[0])
+ {
+ m_shell.assign (path);
+ m_flags.Set (lldb::eLaunchFlagLaunchInShell);
+ }
+ else
+ {
+ m_shell.clear();
+ m_flags.Clear (lldb::eLaunchFlagLaunchInShell);
+ }
+ }
+
+ uint32_t
+ GetResumeCount () const
+ {
+ return m_resume_count;
+ }
+
+ void
+ SetResumeCount (uint32_t c)
+ {
+ m_resume_count = c;
+ }
+
+ bool
+ GetLaunchInSeparateProcessGroup ()
+ {
+ return m_flags.Test(lldb::eLaunchFlagLaunchInSeparateProcessGroup);
+ }
+
+ void
+ SetLaunchInSeparateProcessGroup (bool separate)
+ {
+ if (separate)
+ m_flags.Set(lldb::eLaunchFlagLaunchInSeparateProcessGroup);
+ else
+ m_flags.Clear (lldb::eLaunchFlagLaunchInSeparateProcessGroup);
+
+ }
+
+ void
+ Clear ()
+ {
+ ProcessInfo::Clear();
+ m_working_dir.clear();
+ m_plugin_name.clear();
+ m_shell.clear();
+ m_flags.Clear();
+ m_file_actions.clear();
+ m_resume_count = 0;
+ }
+
+ bool
+ ConvertArgumentsForLaunchingInShell (Error &error,
+ bool localhost,
+ bool will_debug,
+ bool first_arg_is_full_shell_command);
+
+ void
+ SetMonitorProcessCallback (Host::MonitorChildProcessCallback callback,
+ void *baton,
+ bool monitor_signals)
+ {
+ m_monitor_callback = callback;
+ m_monitor_callback_baton = baton;
+ m_monitor_signals = monitor_signals;
+ }
+
+ bool
+ MonitorProcess () const
+ {
+ if (m_monitor_callback && ProcessIDIsValid())
+ {
+ Host::StartMonitoringChildProcess (m_monitor_callback,
+ m_monitor_callback_baton,
+ GetProcessID(),
+ m_monitor_signals);
+ return true;
+ }
+ return false;
+ }
+
+ lldb_utility::PseudoTerminal &
+ GetPTY ()
+ {
+ return m_pty;
+ }
+
+protected:
+ std::string m_working_dir;
+ std::string m_plugin_name;
+ std::string m_shell;
+ Flags m_flags; // Bitwise OR of bits from lldb::LaunchFlags
+ std::vector<FileAction> m_file_actions; // File actions for any other files
+ lldb_utility::PseudoTerminal m_pty;
+ uint32_t m_resume_count; // How many times do we resume after launching
+ Host::MonitorChildProcessCallback m_monitor_callback;
+ void *m_monitor_callback_baton;
+ bool m_monitor_signals;
+
+};
+
+//----------------------------------------------------------------------
+// ProcessLaunchInfo
+//
+// Describes any information that is required to launch a process.
+//----------------------------------------------------------------------
+
+class ProcessAttachInfo : public ProcessInstanceInfo
+{
+public:
+ ProcessAttachInfo() :
+ ProcessInstanceInfo(),
+ m_plugin_name (),
+ m_resume_count (0),
+ m_wait_for_launch (false),
+ m_ignore_existing (true),
+ m_continue_once_attached (false)
+ {
+ }
+
+ ProcessAttachInfo (const ProcessLaunchInfo &launch_info) :
+ ProcessInstanceInfo(),
+ m_plugin_name (),
+ m_resume_count (0),
+ m_wait_for_launch (false),
+ m_ignore_existing (true),
+ m_continue_once_attached (false)
+ {
+ ProcessInfo::operator= (launch_info);
+ SetProcessPluginName (launch_info.GetProcessPluginName());
+ SetResumeCount (launch_info.GetResumeCount());
+ }
+
+ bool
+ GetWaitForLaunch () const
+ {
+ return m_wait_for_launch;
+ }
+
+ void
+ SetWaitForLaunch (bool b)
+ {
+ m_wait_for_launch = b;
+ }
+
+ bool
+ GetIgnoreExisting () const
+ {
+ return m_ignore_existing;
+ }
+
+ void
+ SetIgnoreExisting (bool b)
+ {
+ m_ignore_existing = b;
+ }
+
+ bool
+ GetContinueOnceAttached () const
+ {
+ return m_continue_once_attached;
+ }
+
+ void
+ SetContinueOnceAttached (bool b)
+ {
+ m_continue_once_attached = b;
+ }
+
+ uint32_t
+ GetResumeCount () const
+ {
+ return m_resume_count;
+ }
+
+ void
+ SetResumeCount (uint32_t c)
+ {
+ m_resume_count = c;
+ }
+
+ const char *
+ GetProcessPluginName () const
+ {
+ if (m_plugin_name.empty())
+ return NULL;
+ return m_plugin_name.c_str();
+ }
+
+ void
+ SetProcessPluginName (const char *plugin)
+ {
+ if (plugin && plugin[0])
+ m_plugin_name.assign (plugin);
+ else
+ m_plugin_name.clear();
+ }
+
+ void
+ Clear ()
+ {
+ ProcessInstanceInfo::Clear();
+ m_plugin_name.clear();
+ m_resume_count = 0;
+ m_wait_for_launch = false;
+ m_ignore_existing = true;
+ m_continue_once_attached = false;
+ }
+
+ bool
+ ProcessInfoSpecified () const
+ {
+ if (GetExecutableFile())
+ return true;
+ if (GetProcessID() != LLDB_INVALID_PROCESS_ID)
+ return true;
+ if (GetParentProcessID() != LLDB_INVALID_PROCESS_ID)
+ return true;
+ return false;
+ }
+protected:
+ std::string m_plugin_name;
+ uint32_t m_resume_count; // How many times do we resume after launching
+ bool m_wait_for_launch;
+ bool m_ignore_existing;
+ bool m_continue_once_attached; // Supports the use-case scenario of immediately continuing the process once attached.
+};
+
+class ProcessLaunchCommandOptions : public Options
+{
+public:
+
+ ProcessLaunchCommandOptions (CommandInterpreter &interpreter) :
+ Options(interpreter)
+ {
+ // Keep default values of all options in one place: OptionParsingStarting ()
+ OptionParsingStarting ();
+ }
+
+ ~ProcessLaunchCommandOptions ()
+ {
+ }
+
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg);
+
+ void
+ OptionParsingStarting ()
+ {
+ launch_info.Clear();
+ }
+
+ 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.
+
+ ProcessLaunchInfo launch_info;
+};
+
+//----------------------------------------------------------------------
+// ProcessInstanceInfoMatch
+//
+// A class to help matching one ProcessInstanceInfo to another.
+//----------------------------------------------------------------------
+
+class ProcessInstanceInfoMatch
+{
+public:
+ ProcessInstanceInfoMatch () :
+ m_match_info (),
+ m_name_match_type (eNameMatchIgnore),
+ m_match_all_users (false)
+ {
+ }
+
+ ProcessInstanceInfoMatch (const char *process_name,
+ NameMatchType process_name_match_type) :
+ m_match_info (),
+ m_name_match_type (process_name_match_type),
+ m_match_all_users (false)
+ {
+ m_match_info.GetExecutableFile().SetFile(process_name, false);
+ }
+
+ ProcessInstanceInfo &
+ GetProcessInfo ()
+ {
+ return m_match_info;
+ }
+
+ const ProcessInstanceInfo &
+ GetProcessInfo () const
+ {
+ return m_match_info;
+ }
+
+ bool
+ GetMatchAllUsers () const
+ {
+ return m_match_all_users;
+ }
+
+ void
+ SetMatchAllUsers (bool b)
+ {
+ m_match_all_users = b;
+ }
+
+ NameMatchType
+ GetNameMatchType () const
+ {
+ return m_name_match_type;
+ }
+
+ void
+ SetNameMatchType (NameMatchType name_match_type)
+ {
+ m_name_match_type = name_match_type;
+ }
+
+ bool
+ NameMatches (const char *process_name) const;
+
+ bool
+ Matches (const ProcessInstanceInfo &proc_info) const;
+
+ bool
+ MatchAllProcesses () const;
+ void
+ Clear ();
+
+protected:
+ ProcessInstanceInfo m_match_info;
+ NameMatchType m_name_match_type;
+ bool m_match_all_users;
+};
+
+class ProcessInstanceInfoList
+{
+public:
+ ProcessInstanceInfoList () :
+ m_infos()
+ {
+ }
+
+ void
+ Clear()
+ {
+ m_infos.clear();
+ }
+
+ size_t
+ GetSize()
+ {
+ return m_infos.size();
+ }
+
+ void
+ Append (const ProcessInstanceInfo &info)
+ {
+ m_infos.push_back (info);
+ }
+
+ const char *
+ GetProcessNameAtIndex (size_t idx)
+ {
+ if (idx < m_infos.size())
+ return m_infos[idx].GetName();
+ return NULL;
+ }
+
+ size_t
+ GetProcessNameLengthAtIndex (size_t idx)
+ {
+ if (idx < m_infos.size())
+ return m_infos[idx].GetNameLength();
+ return 0;
+ }
+
+ lldb::pid_t
+ GetProcessIDAtIndex (size_t idx)
+ {
+ if (idx < m_infos.size())
+ return m_infos[idx].GetProcessID();
+ return 0;
+ }
+
+ bool
+ GetInfoAtIndex (size_t idx, ProcessInstanceInfo &info)
+ {
+ if (idx < m_infos.size())
+ {
+ info = m_infos[idx];
+ return true;
+ }
+ return false;
+ }
+
+ // You must ensure "idx" is valid before calling this function
+ const ProcessInstanceInfo &
+ GetProcessInfoAtIndex (size_t idx) const
+ {
+ assert (idx < m_infos.size());
+ return m_infos[idx];
+ }
+
+protected:
+ typedef std::vector<ProcessInstanceInfo> collection;
+ collection m_infos;
+};
+
+
+// This class tracks the Modification state of the process. Things that can currently modify
+// the program are running the program (which will up the StopID) and writing memory (which
+// will up the MemoryID.)
+// FIXME: Should we also include modification of register states?
+
+class ProcessModID
+{
+friend bool operator== (const ProcessModID &lhs, const ProcessModID &rhs);
+public:
+ ProcessModID () :
+ m_stop_id (0),
+ m_last_natural_stop_id(0),
+ m_resume_id (0),
+ m_memory_id (0),
+ m_last_user_expression_resume (0),
+ m_running_user_expression (false)
+ {}
+
+ ProcessModID (const ProcessModID &rhs) :
+ m_stop_id (rhs.m_stop_id),
+ m_memory_id (rhs.m_memory_id)
+ {}
+
+ const ProcessModID & operator= (const ProcessModID &rhs)
+ {
+ if (this != &rhs)
+ {
+ m_stop_id = rhs.m_stop_id;
+ m_memory_id = rhs.m_memory_id;
+ }
+ return *this;
+ }
+
+ ~ProcessModID () {}
+
+ void BumpStopID () {
+ m_stop_id++;
+ if (!IsLastResumeForUserExpression())
+ m_last_natural_stop_id++;
+ }
+
+ void BumpMemoryID () { m_memory_id++; }
+
+ void BumpResumeID () {
+ m_resume_id++;
+ if (m_running_user_expression > 0)
+ m_last_user_expression_resume = m_resume_id;
+ }
+
+ uint32_t GetStopID() const { return m_stop_id; }
+ uint32_t GetLastNaturalStopID() const { return m_last_natural_stop_id; }
+ uint32_t GetMemoryID () const { return m_memory_id; }
+ uint32_t GetResumeID () const { return m_resume_id; }
+ uint32_t GetLastUserExpressionResumeID () const { return m_last_user_expression_resume; }
+
+ bool MemoryIDEqual (const ProcessModID &compare) const
+ {
+ return m_memory_id == compare.m_memory_id;
+ }
+
+ bool StopIDEqual (const ProcessModID &compare) const
+ {
+ return m_stop_id == compare.m_stop_id;
+ }
+
+ void SetInvalid ()
+ {
+ m_stop_id = UINT32_MAX;
+ }
+
+ bool IsValid () const
+ {
+ return m_stop_id != UINT32_MAX;
+ }
+
+ bool
+ IsLastResumeForUserExpression () const
+ {
+ return m_resume_id == m_last_user_expression_resume;
+ }
+
+ void
+ SetRunningUserExpression (bool on)
+ {
+ // REMOVEME printf ("Setting running user expression %s at resume id %d - value: %d.\n", on ? "on" : "off", m_resume_id, m_running_user_expression);
+ if (on)
+ m_running_user_expression++;
+ else
+ m_running_user_expression--;
+ }
+
+private:
+ uint32_t m_stop_id;
+ uint32_t m_last_natural_stop_id;
+ uint32_t m_resume_id;
+ uint32_t m_memory_id;
+ uint32_t m_last_user_expression_resume;
+ uint32_t m_running_user_expression;
+};
+inline bool operator== (const ProcessModID &lhs, const ProcessModID &rhs)
+{
+ if (lhs.StopIDEqual (rhs)
+ && lhs.MemoryIDEqual (rhs))
+ return true;
+ else
+ return false;
+}
+
+inline bool operator!= (const ProcessModID &lhs, const ProcessModID &rhs)
+{
+ if (!lhs.StopIDEqual (rhs)
+ || !lhs.MemoryIDEqual (rhs))
+ return true;
+ else
+ return false;
+}
+
+class MemoryRegionInfo
+{
+public:
+ typedef Range<lldb::addr_t, lldb::addr_t> RangeType;
+
+ enum OptionalBool {
+ eDontKnow = -1,
+ eNo = 0,
+ eYes = 1
+ };
+
+ MemoryRegionInfo () :
+ m_range (),
+ m_read (eDontKnow),
+ m_write (eDontKnow),
+ m_execute (eDontKnow)
+ {
+ }
+
+ ~MemoryRegionInfo ()
+ {
+ }
+
+ RangeType &
+ GetRange()
+ {
+ return m_range;
+ }
+
+ void
+ Clear()
+ {
+ m_range.Clear();
+ m_read = m_write = m_execute = eDontKnow;
+ }
+
+ const RangeType &
+ GetRange() const
+ {
+ return m_range;
+ }
+
+ OptionalBool
+ GetReadable () const
+ {
+ return m_read;
+ }
+
+ OptionalBool
+ GetWritable () const
+ {
+ return m_write;
+ }
+
+ OptionalBool
+ GetExecutable () const
+ {
+ return m_execute;
+ }
+
+ void
+ SetReadable (OptionalBool val)
+ {
+ m_read = val;
+ }
+
+ void
+ SetWritable (OptionalBool val)
+ {
+ m_write = val;
+ }
+
+ void
+ SetExecutable (OptionalBool val)
+ {
+ m_execute = val;
+ }
+
+protected:
+ RangeType m_range;
+ OptionalBool m_read;
+ OptionalBool m_write;
+ OptionalBool m_execute;
+};
+
+//----------------------------------------------------------------------
+/// @class Process Process.h "lldb/Target/Process.h"
+/// @brief A plug-in interface definition class for debugging a process.
+//----------------------------------------------------------------------
+class Process :
+ public std::enable_shared_from_this<Process>,
+ public ProcessProperties,
+ public UserID,
+ public Broadcaster,
+ public ExecutionContextScope,
+ public PluginInterface
+{
+friend class ThreadList;
+friend class ClangFunction; // For WaitForStateChangeEventsPrivate
+friend class CommandObjectProcessLaunch;
+friend class ProcessEventData;
+friend class CommandObjectBreakpointCommand;
+friend class StopInfo;
+
+public:
+
+ //------------------------------------------------------------------
+ /// Broadcaster event bits definitions.
+ //------------------------------------------------------------------
+ enum
+ {
+ eBroadcastBitStateChanged = (1 << 0),
+ eBroadcastBitInterrupt = (1 << 1),
+ eBroadcastBitSTDOUT = (1 << 2),
+ eBroadcastBitSTDERR = (1 << 3),
+ eBroadcastBitProfileData = (1 << 4)
+ };
+
+ enum
+ {
+ eBroadcastInternalStateControlStop = (1<<0),
+ eBroadcastInternalStateControlPause = (1<<1),
+ eBroadcastInternalStateControlResume = (1<<2)
+ };
+
+ typedef Range<lldb::addr_t, lldb::addr_t> LoadRange;
+ // We use a read/write lock to allow on or more clients to
+ // access the process state while the process is stopped (reader).
+ // We lock the write lock to control access to the process
+ // while it is running (readers, or clients that want the process
+ // stopped can block waiting for the process to stop, or just
+ // try to lock it to see if they can immediately access the stopped
+ // process. If the try read lock fails, then the process is running.
+ typedef ProcessRunLock::ProcessRunLocker StopLocker;
+
+ // These two functions fill out the Broadcaster interface:
+
+ static ConstString &GetStaticBroadcasterClass ();
+
+ virtual ConstString &GetBroadcasterClass() const
+ {
+ return GetStaticBroadcasterClass();
+ }
+
+
+ //------------------------------------------------------------------
+ /// A notification structure that can be used by clients to listen
+ /// for changes in a process's lifetime.
+ ///
+ /// @see RegisterNotificationCallbacks (const Notifications&)
+ /// @see UnregisterNotificationCallbacks (const Notifications&)
+ //------------------------------------------------------------------
+#ifndef SWIG
+ typedef struct
+ {
+ void *baton;
+ void (*initialize)(void *baton, Process *process);
+ void (*process_state_changed) (void *baton, Process *process, lldb::StateType state);
+ } Notifications;
+
+ class ProcessEventData :
+ public EventData
+ {
+ friend class Process;
+
+ public:
+ ProcessEventData ();
+ ProcessEventData (const lldb::ProcessSP &process, lldb::StateType state);
+
+ virtual ~ProcessEventData();
+
+ static const ConstString &
+ GetFlavorString ();
+
+ virtual const ConstString &
+ GetFlavor () const;
+
+ const lldb::ProcessSP &
+ GetProcessSP() const
+ {
+ return m_process_sp;
+ }
+ lldb::StateType
+ GetState() const
+ {
+ return m_state;
+ }
+ bool
+ GetRestarted () const
+ {
+ return m_restarted;
+ }
+
+ size_t
+ GetNumRestartedReasons ()
+ {
+ return m_restarted_reasons.size();
+ }
+
+ const char *
+ GetRestartedReasonAtIndex(size_t idx)
+ {
+ if (idx > m_restarted_reasons.size())
+ return NULL;
+ else
+ return m_restarted_reasons[idx].c_str();
+ }
+
+ bool
+ GetInterrupted () const
+ {
+ return m_interrupted;
+ }
+
+ virtual void
+ Dump (Stream *s) const;
+
+ virtual void
+ DoOnRemoval (Event *event_ptr);
+
+ static const Process::ProcessEventData *
+ GetEventDataFromEvent (const Event *event_ptr);
+
+ static lldb::ProcessSP
+ GetProcessFromEvent (const Event *event_ptr);
+
+ static lldb::StateType
+ GetStateFromEvent (const Event *event_ptr);
+
+ static bool
+ GetRestartedFromEvent (const Event *event_ptr);
+
+ static size_t
+ GetNumRestartedReasons(const Event *event_ptr);
+
+ static const char *
+ GetRestartedReasonAtIndex(const Event *event_ptr, size_t idx);
+
+ static void
+ AddRestartedReason (Event *event_ptr, const char *reason);
+
+ static void
+ SetRestartedInEvent (Event *event_ptr, bool new_value);
+
+ static bool
+ GetInterruptedFromEvent (const Event *event_ptr);
+
+ static void
+ SetInterruptedInEvent (Event *event_ptr, bool new_value);
+
+ static bool
+ SetUpdateStateOnRemoval (Event *event_ptr);
+
+ private:
+
+ void
+ SetUpdateStateOnRemoval()
+ {
+ m_update_state++;
+ }
+ void
+ SetRestarted (bool new_value)
+ {
+ m_restarted = new_value;
+ }
+ void
+ SetInterrupted (bool new_value)
+ {
+ m_interrupted = new_value;
+ }
+ void
+ AddRestartedReason (const char *reason)
+ {
+ m_restarted_reasons.push_back(reason);
+ }
+
+ lldb::ProcessSP m_process_sp;
+ lldb::StateType m_state;
+ std::vector<std::string> m_restarted_reasons;
+ bool m_restarted; // For "eStateStopped" events, this is true if the target was automatically restarted.
+ int m_update_state;
+ bool m_interrupted;
+ DISALLOW_COPY_AND_ASSIGN (ProcessEventData);
+
+ };
+
+#endif
+
+ static void
+ SettingsInitialize ();
+
+ static void
+ SettingsTerminate ();
+
+ static const ProcessPropertiesSP &
+ GetGlobalProperties();
+
+ //------------------------------------------------------------------
+ /// Construct with a shared pointer to a target, and the Process listener.
+ //------------------------------------------------------------------
+ Process(Target &target, Listener &listener);
+
+ //------------------------------------------------------------------
+ /// Destructor.
+ ///
+ /// The destructor is virtual since this class is designed to be
+ /// inherited from by the plug-in instance.
+ //------------------------------------------------------------------
+ virtual
+ ~Process();
+
+ //------------------------------------------------------------------
+ /// Find a Process plug-in that can debug \a module using the
+ /// currently selected architecture.
+ ///
+ /// Scans all loaded plug-in interfaces that implement versions of
+ /// the Process plug-in interface and returns the first instance
+ /// that can debug the file.
+ ///
+ /// @param[in] module_sp
+ /// The module shared pointer that this process will debug.
+ ///
+ /// @param[in] plugin_name
+ /// If NULL, select the best plug-in for the binary. If non-NULL
+ /// then look for a plugin whose PluginInfo's name matches
+ /// this string.
+ ///
+ /// @see Process::CanDebug ()
+ //------------------------------------------------------------------
+ static lldb::ProcessSP
+ FindPlugin (Target &target,
+ const char *plugin_name,
+ Listener &listener,
+ const FileSpec *crash_file_path);
+
+
+
+ //------------------------------------------------------------------
+ /// Static function that can be used with the \b host function
+ /// Host::StartMonitoringChildProcess ().
+ ///
+ /// This function can be used by lldb_private::Process subclasses
+ /// when they want to watch for a local process and have its exit
+ /// status automatically set when the host child process exits.
+ /// Subclasses should call Host::StartMonitoringChildProcess ()
+ /// with:
+ /// callback = Process::SetHostProcessExitStatus
+ /// callback_baton = NULL
+ /// pid = Process::GetID()
+ /// monitor_signals = false
+ //------------------------------------------------------------------
+ static bool
+ SetProcessExitStatus (void *callback_baton, // The callback baton which should be set to NULL
+ lldb::pid_t pid, // The process ID we want to monitor
+ bool exited,
+ int signo, // Zero for no signal
+ int status); // Exit value of process if signal is zero
+
+ lldb::ByteOrder
+ GetByteOrder () const;
+
+ uint32_t
+ GetAddressByteSize () const;
+
+ uint32_t
+ GetUniqueID() const
+ {
+ return m_process_unique_id;
+ }
+ //------------------------------------------------------------------
+ /// Check if a plug-in instance can debug the file in \a module.
+ ///
+ /// Each plug-in is given a chance to say whether it can debug
+ /// the file in \a module. If the Process plug-in instance can
+ /// debug a file on the current system, it should return \b true.
+ ///
+ /// @return
+ /// Returns \b true if this Process plug-in instance can
+ /// debug the executable, \b false otherwise.
+ //------------------------------------------------------------------
+ virtual bool
+ CanDebug (Target &target,
+ bool plugin_specified_by_name) = 0;
+
+
+ //------------------------------------------------------------------
+ /// This object is about to be destroyed, do any necessary cleanup.
+ ///
+ /// Subclasses that override this method should always call this
+ /// superclass method.
+ //------------------------------------------------------------------
+ virtual void
+ Finalize();
+
+
+ //------------------------------------------------------------------
+ /// Return whether this object is valid (i.e. has not been finalized.)
+ ///
+ /// @return
+ /// Returns \b true if this Process has not been finalized
+ /// and \b false otherwise.
+ //------------------------------------------------------------------
+ bool
+ IsValid() const
+ {
+ return !m_finalize_called;
+ }
+
+ //------------------------------------------------------------------
+ /// Return a multi-word command object that can be used to expose
+ /// plug-in specific commands.
+ ///
+ /// This object will be used to resolve plug-in commands and can be
+ /// triggered by a call to:
+ ///
+ /// (lldb) process commmand <args>
+ ///
+ /// @return
+ /// A CommandObject which can be one of the concrete subclasses
+ /// of CommandObject like CommandObjectRaw, CommandObjectParsed,
+ /// or CommandObjectMultiword.
+ //------------------------------------------------------------------
+ virtual CommandObject *
+ GetPluginCommandObject()
+ {
+ return NULL;
+ }
+
+ //------------------------------------------------------------------
+ /// Launch a new process.
+ ///
+ /// Launch a new process by spawning a new process using the
+ /// target object's executable module's file as the file to launch.
+ /// Arguments are given in \a argv, and the environment variables
+ /// are in \a envp. Standard input and output files can be
+ /// optionally re-directed to \a stdin_path, \a stdout_path, and
+ /// \a stderr_path.
+ ///
+ /// This function is not meant to be overridden by Process
+ /// subclasses. It will first call Process::WillLaunch (Module *)
+ /// and if that returns \b true, Process::DoLaunch (Module*,
+ /// char const *[],char const *[],const char *,const char *,
+ /// const char *) will be called to actually do the launching. If
+ /// DoLaunch returns \b true, then Process::DidLaunch() will be
+ /// called.
+ ///
+ /// @param[in] argv
+ /// The argument array.
+ ///
+ /// @param[in] envp
+ /// The environment array.
+ ///
+ /// @param[in] launch_flags
+ /// Flags to modify the launch (@see lldb::LaunchFlags)
+ ///
+ /// @param[in] stdin_path
+ /// The path to use when re-directing the STDIN of the new
+ /// process. If all stdXX_path arguments are NULL, a pseudo
+ /// terminal will be used.
+ ///
+ /// @param[in] stdout_path
+ /// The path to use when re-directing the STDOUT of the new
+ /// process. If all stdXX_path arguments are NULL, a pseudo
+ /// terminal will be used.
+ ///
+ /// @param[in] stderr_path
+ /// The path to use when re-directing the STDERR of the new
+ /// process. If all stdXX_path arguments are NULL, a pseudo
+ /// terminal will be used.
+ ///
+ /// @param[in] working_directory
+ /// The working directory to have the child process run in
+ ///
+ /// @return
+ /// An error object. Call GetID() to get the process ID if
+ /// the error object is success.
+ //------------------------------------------------------------------
+ virtual Error
+ Launch (const ProcessLaunchInfo &launch_info);
+
+ virtual Error
+ LoadCore ();
+
+ virtual Error
+ DoLoadCore ()
+ {
+ Error error;
+ error.SetErrorStringWithFormat("error: %s does not support loading core files.", GetPluginName().GetCString());
+ return error;
+ }
+
+ //------------------------------------------------------------------
+ /// Get the dynamic loader plug-in for this process.
+ ///
+ /// The default action is to let the DynamicLoader plug-ins check
+ /// the main executable and the DynamicLoader will select itself
+ /// automatically. Subclasses can override this if inspecting the
+ /// executable is not desired, or if Process subclasses can only
+ /// use a specific DynamicLoader plug-in.
+ //------------------------------------------------------------------
+ virtual DynamicLoader *
+ GetDynamicLoader ();
+
+ //------------------------------------------------------------------
+ /// Attach to an existing process using the process attach info.
+ ///
+ /// This function is not meant to be overridden by Process
+ /// subclasses. It will first call WillAttach (lldb::pid_t)
+ /// or WillAttach (const char *), and if that returns \b
+ /// true, DoAttach (lldb::pid_t) or DoAttach (const char *) will
+ /// be called to actually do the attach. If DoAttach returns \b
+ /// true, then Process::DidAttach() will be called.
+ ///
+ /// @param[in] pid
+ /// The process ID that we should attempt to attach to.
+ ///
+ /// @return
+ /// Returns \a pid if attaching was successful, or
+ /// LLDB_INVALID_PROCESS_ID if attaching fails.
+ //------------------------------------------------------------------
+ virtual Error
+ Attach (ProcessAttachInfo &attach_info);
+
+ //------------------------------------------------------------------
+ /// Attach to a remote system via a URL
+ ///
+ /// @param[in] strm
+ /// A stream where output intended for the user
+ /// (if the driver has a way to display that) generated during
+ /// the connection. This may be NULL if no output is needed.A
+ ///
+ /// @param[in] remote_url
+ /// The URL format that we are connecting to.
+ ///
+ /// @return
+ /// Returns an error object.
+ //------------------------------------------------------------------
+ virtual Error
+ ConnectRemote (Stream *strm, const char *remote_url);
+
+ bool
+ GetShouldDetach () const
+ {
+ return m_should_detach;
+ }
+
+ void
+ SetShouldDetach (bool b)
+ {
+ m_should_detach = b;
+ }
+
+ //------------------------------------------------------------------
+ /// Get the image information address for the current process.
+ ///
+ /// Some runtimes have system functions that can help dynamic
+ /// loaders locate the dynamic loader information needed to observe
+ /// shared libraries being loaded or unloaded. This function is
+ /// in the Process interface (as opposed to the DynamicLoader
+ /// interface) to ensure that remote debugging can take advantage of
+ /// this functionality.
+ ///
+ /// @return
+ /// The address of the dynamic loader information, or
+ /// LLDB_INVALID_ADDRESS if this is not supported by this
+ /// interface.
+ //------------------------------------------------------------------
+ virtual lldb::addr_t
+ GetImageInfoAddress ();
+
+ //------------------------------------------------------------------
+ /// Load a shared library into this process.
+ ///
+ /// Try and load a shared library into the current process. This
+ /// call might fail in the dynamic loader plug-in says it isn't safe
+ /// to try and load shared libraries at the moment.
+ ///
+ /// @param[in] image_spec
+ /// The image file spec that points to the shared library that
+ /// you want to load.
+ ///
+ /// @param[out] error
+ /// An error object that gets filled in with any errors that
+ /// might occur when trying to load the shared library.
+ ///
+ /// @return
+ /// A token that represents the shared library that can be
+ /// later used to unload the shared library. A value of
+ /// LLDB_INVALID_IMAGE_TOKEN will be returned if the shared
+ /// library can't be opened.
+ //------------------------------------------------------------------
+ virtual uint32_t
+ LoadImage (const FileSpec &image_spec, Error &error);
+
+ virtual Error
+ UnloadImage (uint32_t image_token);
+
+ //------------------------------------------------------------------
+ /// Register for process and thread notifications.
+ ///
+ /// Clients can register nofication callbacks by filling out a
+ /// Process::Notifications structure and calling this function.
+ ///
+ /// @param[in] callbacks
+ /// A structure that contains the notification baton and
+ /// callback functions.
+ ///
+ /// @see Process::Notifications
+ //------------------------------------------------------------------
+#ifndef SWIG
+ void
+ RegisterNotificationCallbacks (const Process::Notifications& callbacks);
+#endif
+ //------------------------------------------------------------------
+ /// Unregister for process and thread notifications.
+ ///
+ /// Clients can unregister nofication callbacks by passing a copy of
+ /// the original baton and callbacks in \a callbacks.
+ ///
+ /// @param[in] callbacks
+ /// A structure that contains the notification baton and
+ /// callback functions.
+ ///
+ /// @return
+ /// Returns \b true if the notification callbacks were
+ /// successfully removed from the process, \b false otherwise.
+ ///
+ /// @see Process::Notifications
+ //------------------------------------------------------------------
+#ifndef SWIG
+ bool
+ UnregisterNotificationCallbacks (const Process::Notifications& callbacks);
+#endif
+ //==================================================================
+ // Built in Process Control functions
+ //==================================================================
+ //------------------------------------------------------------------
+ /// Resumes all of a process's threads as configured using the
+ /// Thread run control functions.
+ ///
+ /// Threads for a process should be updated with one of the run
+ /// control actions (resume, step, or suspend) that they should take
+ /// when the process is resumed. If no run control action is given
+ /// to a thread it will be resumed by default.
+ ///
+ /// This function is not meant to be overridden by Process
+ /// subclasses. This function will take care of disabling any
+ /// breakpoints that threads may be stopped at, single stepping, and
+ /// re-enabling breakpoints, and enabling the basic flow control
+ /// that the plug-in instances need not worry about.
+ ///
+ /// N.B. This function also sets the Write side of the Run Lock,
+ /// which is unset when the corresponding stop event is pulled off
+ /// the Public Event Queue. If you need to resume the process without
+ /// setting the Run Lock, use PrivateResume (though you should only do
+ /// that from inside the Process class.
+ ///
+ /// @return
+ /// Returns an error object.
+ ///
+ /// @see Thread:Resume()
+ /// @see Thread:Step()
+ /// @see Thread:Suspend()
+ //------------------------------------------------------------------
+ Error
+ Resume();
+
+ //------------------------------------------------------------------
+ /// Halts a running process.
+ ///
+ /// This function is not meant to be overridden by Process
+ /// subclasses.
+ /// If the process is successfully halted, a eStateStopped
+ /// process event with GetInterrupted will be broadcast. If false, we will
+ /// halt the process with no events generated by the halt.
+ ///
+ /// @param[in] clear_thread_plans
+ /// If true, when the process stops, clear all thread plans.
+ ///
+ /// @return
+ /// Returns an error object. If the error is empty, the process is halted.
+ /// otherwise the halt has failed.
+ //------------------------------------------------------------------
+ Error
+ Halt (bool clear_thread_plans = false);
+
+ //------------------------------------------------------------------
+ /// Detaches from a running or stopped process.
+ ///
+ /// This function is not meant to be overridden by Process
+ /// subclasses.
+ ///
+ /// @param[in] keep_stopped
+ /// If true, don't resume the process on detach.
+ ///
+ /// @return
+ /// Returns an error object.
+ //------------------------------------------------------------------
+ Error
+ Detach (bool keep_stopped);
+
+ //------------------------------------------------------------------
+ /// Kills the process and shuts down all threads that were spawned
+ /// to track and monitor the process.
+ ///
+ /// This function is not meant to be overridden by Process
+ /// subclasses.
+ ///
+ /// @return
+ /// Returns an error object.
+ //------------------------------------------------------------------
+ Error
+ Destroy();
+
+ //------------------------------------------------------------------
+ /// Sends a process a UNIX signal \a signal.
+ ///
+ /// This function is not meant to be overridden by Process
+ /// subclasses.
+ ///
+ /// @return
+ /// Returns an error object.
+ //------------------------------------------------------------------
+ Error
+ Signal (int signal);
+
+ virtual UnixSignals &
+ GetUnixSignals ()
+ {
+ return m_unix_signals;
+ }
+
+ //==================================================================
+ // Plug-in Process Control Overrides
+ //==================================================================
+
+ //------------------------------------------------------------------
+ /// Called before attaching to a process.
+ ///
+ /// Allow Process plug-ins to execute some code before attaching a
+ /// process.
+ ///
+ /// @return
+ /// Returns an error object.
+ //------------------------------------------------------------------
+ virtual Error
+ WillAttachToProcessWithID (lldb::pid_t pid)
+ {
+ return Error();
+ }
+
+ //------------------------------------------------------------------
+ /// Called before attaching to a process.
+ ///
+ /// Allow Process plug-ins to execute some code before attaching a
+ /// process.
+ ///
+ /// @return
+ /// Returns an error object.
+ //------------------------------------------------------------------
+ virtual Error
+ WillAttachToProcessWithName (const char *process_name, bool wait_for_launch)
+ {
+ return Error();
+ }
+
+ //------------------------------------------------------------------
+ /// Attach to a remote system via a URL
+ ///
+ /// @param[in] strm
+ /// A stream where output intended for the user
+ /// (if the driver has a way to display that) generated during
+ /// the connection. This may be NULL if no output is needed.A
+ ///
+ /// @param[in] remote_url
+ /// The URL format that we are connecting to.
+ ///
+ /// @return
+ /// Returns an error object.
+ //------------------------------------------------------------------
+ virtual Error
+ DoConnectRemote (Stream *strm, const char *remote_url)
+ {
+ Error error;
+ error.SetErrorString ("remote connections are not supported");
+ return error;
+ }
+
+ //------------------------------------------------------------------
+ /// Attach to an existing process using a process ID.
+ ///
+ /// @param[in] pid
+ /// The process ID that we should attempt to attach to.
+ ///
+ /// @return
+ /// Returns \a pid if attaching was successful, or
+ /// LLDB_INVALID_PROCESS_ID if attaching fails.
+ //------------------------------------------------------------------
+ virtual Error
+ DoAttachToProcessWithID (lldb::pid_t pid)
+ {
+ Error error;
+ error.SetErrorStringWithFormat("error: %s does not support attaching to a process by pid", GetPluginName().GetCString());
+ return error;
+ }
+
+ //------------------------------------------------------------------
+ /// Attach to an existing process using a process ID.
+ ///
+ /// @param[in] pid
+ /// The process ID that we should attempt to attach to.
+ ///
+ /// @param[in] attach_info
+ /// Information on how to do the attach. For example, GetUserID()
+ /// will return the uid to attach as.
+ ///
+ /// @return
+ /// Returns \a pid if attaching was successful, or
+ /// LLDB_INVALID_PROCESS_ID if attaching fails.
+ /// hanming : need flag
+ //------------------------------------------------------------------
+ virtual Error
+ DoAttachToProcessWithID (lldb::pid_t pid, const ProcessAttachInfo &attach_info)
+ {
+ Error error;
+ error.SetErrorStringWithFormat("error: %s does not support attaching to a process by pid", GetPluginName().GetCString());
+ return error;
+ }
+
+ //------------------------------------------------------------------
+ /// Attach to an existing process using a partial process name.
+ ///
+ /// @param[in] process_name
+ /// The name of the process to attach to.
+ ///
+ /// @param[in] wait_for_launch
+ /// If \b true, wait for the process to be launched and attach
+ /// as soon as possible after it does launch. If \b false, then
+ /// search for a matching process the currently exists.
+ ///
+ /// @param[in] attach_info
+ /// Information on how to do the attach. For example, GetUserID()
+ /// will return the uid to attach as.
+ ///
+ /// @return
+ /// Returns \a pid if attaching was successful, or
+ /// LLDB_INVALID_PROCESS_ID if attaching fails.
+ //------------------------------------------------------------------
+ virtual Error
+ DoAttachToProcessWithName (const char *process_name, bool wait_for_launch, const ProcessAttachInfo &attach_info)
+ {
+ Error error;
+ error.SetErrorString("attach by name is not supported");
+ return error;
+ }
+
+ //------------------------------------------------------------------
+ /// Called after attaching a process.
+ ///
+ /// Allow Process plug-ins to execute some code after attaching to
+ /// a process.
+ //------------------------------------------------------------------
+ virtual void
+ DidAttach () {}
+
+
+ //------------------------------------------------------------------
+ /// Called after a process re-execs itself.
+ ///
+ /// Allow Process plug-ins to execute some code after a process has
+ /// exec'ed itself. Subclasses typically should override DoDidExec()
+ /// as the lldb_private::Process class needs to remove its dynamic
+ /// loader, runtime, ABI and other plug-ins, as well as unload all
+ /// shared libraries.
+ //------------------------------------------------------------------
+ virtual void
+ DidExec ();
+
+ //------------------------------------------------------------------
+ /// Subclasses of Process should implement this function if they
+ /// need to do anything after a process exec's itself.
+ //------------------------------------------------------------------
+ virtual void
+ DoDidExec ()
+ {
+ }
+
+ //------------------------------------------------------------------
+ /// Called before launching to a process.
+ ///
+ /// Allow Process plug-ins to execute some code before launching a
+ /// process.
+ ///
+ /// @return
+ /// Returns an error object.
+ //------------------------------------------------------------------
+ virtual Error
+ WillLaunch (Module* module)
+ {
+ return Error();
+ }
+
+ //------------------------------------------------------------------
+ /// Launch a new process.
+ ///
+ /// Launch a new process by spawning a new process using \a module's
+ /// file as the file to launch. Arguments are given in \a argv,
+ /// and the environment variables are in \a envp. Standard input
+ /// and output files can be optionally re-directed to \a stdin_path,
+ /// \a stdout_path, and \a stderr_path.
+ ///
+ /// @param[in] module
+ /// The module from which to extract the file specification and
+ /// launch.
+ ///
+ /// @param[in] argv
+ /// The argument array.
+ ///
+ /// @param[in] envp
+ /// The environment array.
+ ///
+ /// @param[in] launch_flags
+ /// Flags to modify the launch (@see lldb::LaunchFlags)
+ ///
+ /// @param[in] stdin_path
+ /// The path to use when re-directing the STDIN of the new
+ /// process. If all stdXX_path arguments are NULL, a pseudo
+ /// terminal will be used.
+ ///
+ /// @param[in] stdout_path
+ /// The path to use when re-directing the STDOUT of the new
+ /// process. If all stdXX_path arguments are NULL, a pseudo
+ /// terminal will be used.
+ ///
+ /// @param[in] stderr_path
+ /// The path to use when re-directing the STDERR of the new
+ /// process. If all stdXX_path arguments are NULL, a pseudo
+ /// terminal will be used.
+ ///
+ /// @param[in] working_directory
+ /// The working directory to have the child process run in
+ ///
+ /// @return
+ /// A new valid process ID, or LLDB_INVALID_PROCESS_ID if
+ /// launching fails.
+ //------------------------------------------------------------------
+ virtual Error
+ DoLaunch (Module *exe_module,
+ const ProcessLaunchInfo &launch_info)
+ {
+ Error error;
+ error.SetErrorStringWithFormat("error: %s does not support launching processes", GetPluginName().GetCString());
+ return error;
+ }
+
+
+ //------------------------------------------------------------------
+ /// Called after launching a process.
+ ///
+ /// Allow Process plug-ins to execute some code after launching
+ /// a process.
+ //------------------------------------------------------------------
+ virtual void
+ DidLaunch () {}
+
+
+
+ //------------------------------------------------------------------
+ /// Called before resuming to a process.
+ ///
+ /// Allow Process plug-ins to execute some code before resuming a
+ /// process.
+ ///
+ /// @return
+ /// Returns an error object.
+ //------------------------------------------------------------------
+ virtual Error
+ WillResume () { return Error(); }
+
+ //------------------------------------------------------------------
+ /// Resumes all of a process's threads as configured using the
+ /// Thread run control functions.
+ ///
+ /// Threads for a process should be updated with one of the run
+ /// control actions (resume, step, or suspend) that they should take
+ /// when the process is resumed. If no run control action is given
+ /// to a thread it will be resumed by default.
+ ///
+ /// @return
+ /// Returns \b true if the process successfully resumes using
+ /// the thread run control actions, \b false otherwise.
+ ///
+ /// @see Thread:Resume()
+ /// @see Thread:Step()
+ /// @see Thread:Suspend()
+ //------------------------------------------------------------------
+ virtual Error
+ DoResume ()
+ {
+ Error error;
+ error.SetErrorStringWithFormat("error: %s does not support resuming processes", GetPluginName().GetCString());
+ return error;
+ }
+
+
+ //------------------------------------------------------------------
+ /// Called after resuming a process.
+ ///
+ /// Allow Process plug-ins to execute some code after resuming
+ /// a process.
+ //------------------------------------------------------------------
+ virtual void
+ DidResume () {}
+
+
+ //------------------------------------------------------------------
+ /// Called before halting to a process.
+ ///
+ /// Allow Process plug-ins to execute some code before halting a
+ /// process.
+ ///
+ /// @return
+ /// Returns an error object.
+ //------------------------------------------------------------------
+ virtual Error
+ WillHalt () { return Error(); }
+
+ //------------------------------------------------------------------
+ /// Halts a running process.
+ ///
+ /// DoHalt must produce one and only one stop StateChanged event if it actually
+ /// stops the process. If the stop happens through some natural event (for
+ /// instance a SIGSTOP), then forwarding that event will do. Otherwise, you must
+ /// generate the event manually. Note also, the private event thread is stopped when
+ /// DoHalt is run to prevent the events generated while halting to trigger
+ /// other state changes before the halt is complete.
+ ///
+ /// @param[out] caused_stop
+ /// If true, then this Halt caused the stop, otherwise, the
+ /// process was already stopped.
+ ///
+ /// @return
+ /// Returns \b true if the process successfully halts, \b false
+ /// otherwise.
+ //------------------------------------------------------------------
+ virtual Error
+ DoHalt (bool &caused_stop)
+ {
+ Error error;
+ error.SetErrorStringWithFormat("error: %s does not support halting processes", GetPluginName().GetCString());
+ return error;
+ }
+
+
+ //------------------------------------------------------------------
+ /// Called after halting a process.
+ ///
+ /// Allow Process plug-ins to execute some code after halting
+ /// a process.
+ //------------------------------------------------------------------
+ virtual void
+ DidHalt () {}
+
+ //------------------------------------------------------------------
+ /// Called before detaching from a process.
+ ///
+ /// Allow Process plug-ins to execute some code before detaching
+ /// from a process.
+ ///
+ /// @return
+ /// Returns an error object.
+ //------------------------------------------------------------------
+ virtual Error
+ WillDetach ()
+ {
+ return Error();
+ }
+
+ //------------------------------------------------------------------
+ /// Detaches from a running or stopped process.
+ ///
+ /// @return
+ /// Returns \b true if the process successfully detaches, \b
+ /// false otherwise.
+ //------------------------------------------------------------------
+ virtual Error
+ DoDetach (bool keep_stopped)
+ {
+ Error error;
+ error.SetErrorStringWithFormat("error: %s does not support detaching from processes", GetPluginName().GetCString());
+ return error;
+ }
+
+
+ //------------------------------------------------------------------
+ /// Called after detaching from a process.
+ ///
+ /// Allow Process plug-ins to execute some code after detaching
+ /// from a process.
+ //------------------------------------------------------------------
+ virtual void
+ DidDetach () {}
+
+ virtual bool
+ DetachRequiresHalt() { return false; }
+
+ //------------------------------------------------------------------
+ /// Called before sending a signal to a process.
+ ///
+ /// Allow Process plug-ins to execute some code before sending a
+ /// signal to a process.
+ ///
+ /// @return
+ /// Returns no error if it is safe to proceed with a call to
+ /// Process::DoSignal(int), otherwise an error describing what
+ /// prevents the signal from being sent.
+ //------------------------------------------------------------------
+ virtual Error
+ WillSignal () { return Error(); }
+
+ //------------------------------------------------------------------
+ /// Sends a process a UNIX signal \a signal.
+ ///
+ /// @return
+ /// Returns an error object.
+ //------------------------------------------------------------------
+ virtual Error
+ DoSignal (int signal)
+ {
+ Error error;
+ error.SetErrorStringWithFormat("error: %s does not support senging signals to processes", GetPluginName().GetCString());
+ return error;
+ }
+
+ virtual Error
+ WillDestroy () { return Error(); }
+
+ virtual Error
+ DoDestroy () = 0;
+
+ virtual void
+ DidDestroy () { }
+
+ virtual bool
+ DestroyRequiresHalt() { return true; }
+
+
+ //------------------------------------------------------------------
+ /// Called after sending a signal to a process.
+ ///
+ /// Allow Process plug-ins to execute some code after sending a
+ /// signal to a process.
+ //------------------------------------------------------------------
+ virtual void
+ DidSignal () {}
+
+ //------------------------------------------------------------------
+ /// Currently called as part of ShouldStop.
+ /// FIXME: Should really happen when the target stops before the
+ /// event is taken from the queue...
+ ///
+ /// This callback is called as the event
+ /// is about to be queued up to allow Process plug-ins to execute
+ /// some code prior to clients being notified that a process was
+ /// stopped. Common operations include updating the thread list,
+ /// invalidating any thread state (registers, stack, etc) prior to
+ /// letting the notification go out.
+ ///
+ //------------------------------------------------------------------
+ virtual void
+ RefreshStateAfterStop () = 0;
+
+ //------------------------------------------------------------------
+ /// Get the target object pointer for this module.
+ ///
+ /// @return
+ /// A Target object pointer to the target that owns this
+ /// module.
+ //------------------------------------------------------------------
+ Target &
+ GetTarget ()
+ {
+ return m_target;
+ }
+
+ //------------------------------------------------------------------
+ /// Get the const target object pointer for this module.
+ ///
+ /// @return
+ /// A const Target object pointer to the target that owns this
+ /// module.
+ //------------------------------------------------------------------
+ const Target &
+ GetTarget () const
+ {
+ return m_target;
+ }
+
+ //------------------------------------------------------------------
+ /// Flush all data in the process.
+ ///
+ /// Flush the memory caches, all threads, and any other cached data
+ /// in the process.
+ ///
+ /// This function can be called after a world changing event like
+ /// adding a new symbol file, or after the process makes a large
+ /// context switch (from boot ROM to booted into an OS).
+ //------------------------------------------------------------------
+ void
+ Flush ();
+
+ //------------------------------------------------------------------
+ /// Get accessor for the current process state.
+ ///
+ /// @return
+ /// The current state of the process.
+ ///
+ /// @see lldb::StateType
+ //------------------------------------------------------------------
+ lldb::StateType
+ GetState ();
+
+ ExecutionResults
+ RunThreadPlan (ExecutionContext &exe_ctx,
+ lldb::ThreadPlanSP &thread_plan_sp,
+ bool stop_others,
+ bool run_others,
+ bool unwind_on_error,
+ bool ignore_breakpoints,
+ uint32_t timeout_usec,
+ Stream &errors);
+
+ static const char *
+ ExecutionResultAsCString (ExecutionResults result);
+
+ void
+ GetStatus (Stream &ostrm);
+
+ size_t
+ GetThreadStatus (Stream &ostrm,
+ bool only_threads_with_stop_reason,
+ uint32_t start_frame,
+ uint32_t num_frames,
+ uint32_t num_frames_with_source);
+
+ void
+ SendAsyncInterrupt ();
+
+protected:
+
+ void
+ SetState (lldb::EventSP &event_sp);
+
+ lldb::StateType
+ GetPrivateState ();
+
+ //------------------------------------------------------------------
+ /// The "private" side of resuming a process. This doesn't alter the
+ /// state of m_run_lock, but just causes the process to resume.
+ ///
+ /// @return
+ /// An Error object describing the success or failure of the resume.
+ //------------------------------------------------------------------
+ Error
+ PrivateResume ();
+
+ //------------------------------------------------------------------
+ // Called internally
+ //------------------------------------------------------------------
+ void
+ CompleteAttach ();
+
+public:
+ //------------------------------------------------------------------
+ /// Get the exit status for a process.
+ ///
+ /// @return
+ /// The process's return code, or -1 if the current process
+ /// state is not eStateExited.
+ //------------------------------------------------------------------
+ int
+ GetExitStatus ();
+
+ //------------------------------------------------------------------
+ /// Get a textual description of what the process exited.
+ ///
+ /// @return
+ /// The textual description of why the process exited, or NULL
+ /// if there is no description available.
+ //------------------------------------------------------------------
+ const char *
+ GetExitDescription ();
+
+
+ virtual void
+ DidExit ()
+ {
+ }
+
+ //------------------------------------------------------------------
+ /// Get the Modification ID of the process.
+ ///
+ /// @return
+ /// The modification ID of the process.
+ //------------------------------------------------------------------
+ ProcessModID
+ GetModID () const
+ {
+ return m_mod_id;
+ }
+
+ const ProcessModID &
+ GetModIDRef () const
+ {
+ return m_mod_id;
+ }
+
+ uint32_t
+ GetStopID () const
+ {
+ return m_mod_id.GetStopID();
+ }
+
+ uint32_t
+ GetResumeID () const
+ {
+ return m_mod_id.GetResumeID();
+ }
+
+ uint32_t
+ GetLastUserExpressionResumeID () const
+ {
+ return m_mod_id.GetLastUserExpressionResumeID();
+ }
+
+ uint32_t
+ GetLastNaturalStopID()
+ {
+ return m_mod_id.GetLastNaturalStopID();
+ }
+
+ //------------------------------------------------------------------
+ /// Set accessor for the process exit status (return code).
+ ///
+ /// Sometimes a child exits and the exit can be detected by global
+ /// functions (signal handler for SIGCHLD for example). This
+ /// accessor allows the exit status to be set from an external
+ /// source.
+ ///
+ /// Setting this will cause a eStateExited event to be posted to
+ /// the process event queue.
+ ///
+ /// @param[in] exit_status
+ /// The value for the process's return code.
+ ///
+ /// @see lldb::StateType
+ //------------------------------------------------------------------
+ virtual bool
+ SetExitStatus (int exit_status, const char *cstr);
+
+ //------------------------------------------------------------------
+ /// Check if a process is still alive.
+ ///
+ /// @return
+ /// Returns \b true if the process is still valid, \b false
+ /// otherwise.
+ //------------------------------------------------------------------
+ virtual bool
+ IsAlive () = 0;
+
+ //------------------------------------------------------------------
+ /// Before lldb detaches from a process, it warns the user that they are about to lose their debug session.
+ /// In some cases, this warning doesn't need to be emitted -- for instance, with core file debugging where
+ /// the user can reconstruct the "state" by simply re-running the debugger on the core file.
+ ///
+ /// @return
+ // true if the user should be warned about detaching from this process.
+ //------------------------------------------------------------------
+ virtual bool
+ WarnBeforeDetach () const
+ {
+ return true;
+ }
+
+ //------------------------------------------------------------------
+ /// Actually do the reading of memory from a process.
+ ///
+ /// Subclasses must override this function and can return fewer
+ /// bytes than requested when memory requests are too large. This
+ /// class will break up the memory requests and keep advancing the
+ /// arguments along as needed.
+ ///
+ /// @param[in] vm_addr
+ /// A virtual load address that indicates where to start reading
+ /// memory from.
+ ///
+ /// @param[in] size
+ /// The number of bytes to read.
+ ///
+ /// @param[out] buf
+ /// A byte buffer that is at least \a size bytes long that
+ /// will receive the memory bytes.
+ ///
+ /// @return
+ /// The number of bytes that were actually read into \a buf.
+ //------------------------------------------------------------------
+ virtual size_t
+ DoReadMemory (lldb::addr_t vm_addr,
+ void *buf,
+ size_t size,
+ Error &error) = 0;
+
+ //------------------------------------------------------------------
+ /// Read of memory from a process.
+ ///
+ /// This function will read memory from the current process's
+ /// address space and remove any traps that may have been inserted
+ /// into the memory.
+ ///
+ /// This function is not meant to be overridden by Process
+ /// subclasses, the subclasses should implement
+ /// Process::DoReadMemory (lldb::addr_t, size_t, void *).
+ ///
+ /// @param[in] vm_addr
+ /// A virtual load address that indicates where to start reading
+ /// memory from.
+ ///
+ /// @param[out] buf
+ /// A byte buffer that is at least \a size bytes long that
+ /// will receive the memory bytes.
+ ///
+ /// @param[in] size
+ /// The number of bytes to read.
+ ///
+ /// @return
+ /// The number of bytes that were actually read into \a buf. If
+ /// the returned number is greater than zero, yet less than \a
+ /// size, then this function will get called again with \a
+ /// vm_addr, \a buf, and \a size updated appropriately. Zero is
+ /// returned to indicate an error.
+ //------------------------------------------------------------------
+ virtual size_t
+ ReadMemory (lldb::addr_t vm_addr,
+ void *buf,
+ size_t size,
+ Error &error);
+
+ //------------------------------------------------------------------
+ /// Read a NULL terminated string from memory
+ ///
+ /// This function will read a cache page at a time until a NULL
+ /// string terminator is found. It will stop reading if an aligned
+ /// sequence of NULL termination \a type_width bytes is not found
+ /// before reading \a cstr_max_len bytes. The results are always
+ /// guaranteed to be NULL terminated, and that no more than
+ /// (max_bytes - type_width) bytes will be read.
+ ///
+ /// @param[in] vm_addr
+ /// The virtual load address to start the memory read.
+ ///
+ /// @param[in] str
+ /// A character buffer containing at least max_bytes.
+ ///
+ /// @param[in] max_bytes
+ /// The maximum number of bytes to read.
+ ///
+ /// @param[in] error
+ /// The error status of the read operation.
+ ///
+ /// @param[in] type_width
+ /// The size of the null terminator (1 to 4 bytes per
+ /// character). Defaults to 1.
+ ///
+ /// @return
+ /// The error status or the number of bytes prior to the null terminator.
+ //------------------------------------------------------------------
+ size_t
+ ReadStringFromMemory (lldb::addr_t vm_addr,
+ char *str,
+ size_t max_bytes,
+ Error &error,
+ size_t type_width = 1);
+
+ //------------------------------------------------------------------
+ /// Read a NULL terminated C string from memory
+ ///
+ /// This function will read a cache page at a time until the NULL
+ /// C string terminator is found. It will stop reading if the NULL
+ /// termination byte isn't found before reading \a cstr_max_len
+ /// bytes, and the results are always guaranteed to be NULL
+ /// terminated (at most cstr_max_len - 1 bytes will be read).
+ //------------------------------------------------------------------
+ size_t
+ ReadCStringFromMemory (lldb::addr_t vm_addr,
+ char *cstr,
+ size_t cstr_max_len,
+ Error &error);
+
+ size_t
+ ReadCStringFromMemory (lldb::addr_t vm_addr,
+ std::string &out_str,
+ Error &error);
+
+ size_t
+ ReadMemoryFromInferior (lldb::addr_t vm_addr,
+ void *buf,
+ size_t size,
+ Error &error);
+
+ //------------------------------------------------------------------
+ /// Reads an unsigned integer of the specified byte size from
+ /// process memory.
+ ///
+ /// @param[in] load_addr
+ /// A load address of the integer to read.
+ ///
+ /// @param[in] byte_size
+ /// The size in byte of the integer to read.
+ ///
+ /// @param[in] fail_value
+ /// The value to return if we fail to read an integer.
+ ///
+ /// @param[out] error
+ /// An error that indicates the success or failure of this
+ /// operation. If error indicates success (error.Success()),
+ /// then the value returned can be trusted, otherwise zero
+ /// will be returned.
+ ///
+ /// @return
+ /// The unsigned integer that was read from the process memory
+ /// space. If the integer was smaller than a uint64_t, any
+ /// unused upper bytes will be zero filled. If the process
+ /// byte order differs from the host byte order, the integer
+ /// value will be appropriately byte swapped into host byte
+ /// order.
+ //------------------------------------------------------------------
+ uint64_t
+ ReadUnsignedIntegerFromMemory (lldb::addr_t load_addr,
+ size_t byte_size,
+ uint64_t fail_value,
+ Error &error);
+
+ lldb::addr_t
+ ReadPointerFromMemory (lldb::addr_t vm_addr,
+ Error &error);
+
+ bool
+ WritePointerToMemory (lldb::addr_t vm_addr,
+ lldb::addr_t ptr_value,
+ Error &error);
+
+ //------------------------------------------------------------------
+ /// Actually do the writing of memory to a process.
+ ///
+ /// @param[in] vm_addr
+ /// A virtual load address that indicates where to start writing
+ /// memory to.
+ ///
+ /// @param[in] buf
+ /// A byte buffer that is at least \a size bytes long that
+ /// contains the data to write.
+ ///
+ /// @param[in] size
+ /// The number of bytes to write.
+ ///
+ /// @param[out] error
+ /// An error value in case the memory write fails.
+ ///
+ /// @return
+ /// The number of bytes that were actually written.
+ //------------------------------------------------------------------
+ virtual size_t
+ DoWriteMemory (lldb::addr_t vm_addr, const void *buf, size_t size, Error &error)
+ {
+ error.SetErrorStringWithFormat("error: %s does not support writing to processes", GetPluginName().GetCString());
+ return 0;
+ }
+
+
+ //------------------------------------------------------------------
+ /// Write all or part of a scalar value to memory.
+ ///
+ /// The value contained in \a scalar will be swapped to match the
+ /// byte order of the process that is being debugged. If \a size is
+ /// less than the size of scalar, the least significate \a size bytes
+ /// from scalar will be written. If \a size is larger than the byte
+ /// size of scalar, then the extra space will be padded with zeros
+ /// and the scalar value will be placed in the least significant
+ /// bytes in memory.
+ ///
+ /// @param[in] vm_addr
+ /// A virtual load address that indicates where to start writing
+ /// memory to.
+ ///
+ /// @param[in] scalar
+ /// The scalar to write to the debugged process.
+ ///
+ /// @param[in] size
+ /// This value can be smaller or larger than the scalar value
+ /// itself. If \a size is smaller than the size of \a scalar,
+ /// the least significant bytes in \a scalar will be used. If
+ /// \a size is larger than the byte size of \a scalar, then
+ /// the extra space will be padded with zeros. If \a size is
+ /// set to UINT32_MAX, then the size of \a scalar will be used.
+ ///
+ /// @param[out] error
+ /// An error value in case the memory write fails.
+ ///
+ /// @return
+ /// The number of bytes that were actually written.
+ //------------------------------------------------------------------
+ size_t
+ WriteScalarToMemory (lldb::addr_t vm_addr,
+ const Scalar &scalar,
+ size_t size,
+ Error &error);
+
+ size_t
+ ReadScalarIntegerFromMemory (lldb::addr_t addr,
+ uint32_t byte_size,
+ bool is_signed,
+ Scalar &scalar,
+ Error &error);
+
+ //------------------------------------------------------------------
+ /// Write memory to a process.
+ ///
+ /// This function will write memory to the current process's
+ /// address space and maintain any traps that might be present due
+ /// to software breakpoints.
+ ///
+ /// This function is not meant to be overridden by Process
+ /// subclasses, the subclasses should implement
+ /// Process::DoWriteMemory (lldb::addr_t, size_t, void *).
+ ///
+ /// @param[in] vm_addr
+ /// A virtual load address that indicates where to start writing
+ /// memory to.
+ ///
+ /// @param[in] buf
+ /// A byte buffer that is at least \a size bytes long that
+ /// contains the data to write.
+ ///
+ /// @param[in] size
+ /// The number of bytes to write.
+ ///
+ /// @return
+ /// The number of bytes that were actually written.
+ //------------------------------------------------------------------
+ size_t
+ WriteMemory (lldb::addr_t vm_addr, const void *buf, size_t size, Error &error);
+
+
+ //------------------------------------------------------------------
+ /// Actually allocate memory in the process.
+ ///
+ /// This function will allocate memory in the process's address
+ /// space. This can't rely on the generic function calling mechanism,
+ /// since that requires this function.
+ ///
+ /// @param[in] size
+ /// The size of the allocation requested.
+ ///
+ /// @return
+ /// The address of the allocated buffer in the process, or
+ /// LLDB_INVALID_ADDRESS if the allocation failed.
+ //------------------------------------------------------------------
+
+ virtual lldb::addr_t
+ DoAllocateMemory (size_t size, uint32_t permissions, Error &error)
+ {
+ error.SetErrorStringWithFormat("error: %s does not support allocating in the debug process", GetPluginName().GetCString());
+ return LLDB_INVALID_ADDRESS;
+ }
+
+
+ //------------------------------------------------------------------
+ /// The public interface to allocating memory in the process.
+ ///
+ /// This function will allocate memory in the process's address
+ /// space. This can't rely on the generic function calling mechanism,
+ /// since that requires this function.
+ ///
+ /// @param[in] size
+ /// The size of the allocation requested.
+ ///
+ /// @param[in] permissions
+ /// Or together any of the lldb::Permissions bits. The permissions on
+ /// a given memory allocation can't be changed after allocation. Note
+ /// that a block that isn't set writable can still be written on from lldb,
+ /// just not by the process itself.
+ ///
+ /// @param[in/out] error
+ /// An error object to fill in if things go wrong.
+ /// @return
+ /// The address of the allocated buffer in the process, or
+ /// LLDB_INVALID_ADDRESS if the allocation failed.
+ //------------------------------------------------------------------
+
+ lldb::addr_t
+ AllocateMemory (size_t size, uint32_t permissions, Error &error);
+
+
+ //------------------------------------------------------------------
+ /// Resolve dynamically loaded indirect functions.
+ ///
+ /// @param[in] address
+ /// The load address of the indirect function to resolve.
+ ///
+ /// @param[out] error
+ /// An error value in case the resolve fails.
+ ///
+ /// @return
+ /// The address of the resolved function.
+ /// LLDB_INVALID_ADDRESS if the resolution failed.
+ //------------------------------------------------------------------
+
+ virtual lldb::addr_t
+ ResolveIndirectFunction(const Address *address, Error &error)
+ {
+ error.SetErrorStringWithFormat("error: %s does not support indirect functions in the debug process", GetPluginName().GetCString());
+ return LLDB_INVALID_ADDRESS;
+ }
+
+ virtual Error
+ GetMemoryRegionInfo (lldb::addr_t load_addr,
+ MemoryRegionInfo &range_info)
+ {
+ Error error;
+ error.SetErrorString ("Process::GetMemoryRegionInfo() not supported");
+ return error;
+ }
+
+ virtual Error
+ GetWatchpointSupportInfo (uint32_t &num)
+ {
+ Error error;
+ num = 0;
+ error.SetErrorString ("Process::GetWatchpointSupportInfo() not supported");
+ return error;
+ }
+
+ virtual Error
+ GetWatchpointSupportInfo (uint32_t &num, bool& after)
+ {
+ Error error;
+ num = 0;
+ after = true;
+ error.SetErrorString ("Process::GetWatchpointSupportInfo() not supported");
+ return error;
+ }
+
+ lldb::ModuleSP
+ ReadModuleFromMemory (const FileSpec& file_spec,
+ lldb::addr_t header_addr);
+
+ //------------------------------------------------------------------
+ /// Attempt to get the attributes for a region of memory in the process.
+ ///
+ /// It may be possible for the remote debug server to inspect attributes
+ /// for a region of memory in the process, such as whether there is a
+ /// valid page of memory at a given address or whether that page is
+ /// readable/writable/executable by the process.
+ ///
+ /// @param[in] load_addr
+ /// The address of interest in the process.
+ ///
+ /// @param[out] permissions
+ /// If this call returns successfully, this bitmask will have
+ /// its Permissions bits set to indicate whether the region is
+ /// readable/writable/executable. If this call fails, the
+ /// bitmask values are undefined.
+ ///
+ /// @return
+ /// Returns true if it was able to determine the attributes of the
+ /// memory region. False if not.
+ //------------------------------------------------------------------
+
+ virtual bool
+ GetLoadAddressPermissions (lldb::addr_t load_addr, uint32_t &permissions)
+ {
+ MemoryRegionInfo range_info;
+ permissions = 0;
+ Error error (GetMemoryRegionInfo (load_addr, range_info));
+ if (!error.Success())
+ return false;
+ if (range_info.GetReadable() == MemoryRegionInfo::eDontKnow
+ || range_info.GetWritable() == MemoryRegionInfo::eDontKnow
+ || range_info.GetExecutable() == MemoryRegionInfo::eDontKnow)
+ {
+ return false;
+ }
+
+ if (range_info.GetReadable() == MemoryRegionInfo::eYes)
+ permissions |= lldb::ePermissionsReadable;
+
+ if (range_info.GetWritable() == MemoryRegionInfo::eYes)
+ permissions |= lldb::ePermissionsWritable;
+
+ if (range_info.GetExecutable() == MemoryRegionInfo::eYes)
+ permissions |= lldb::ePermissionsExecutable;
+
+ return true;
+ }
+
+ //------------------------------------------------------------------
+ /// Determines whether executing JIT-compiled code in this process
+ /// is possible.
+ ///
+ /// @return
+ /// True if execution of JIT code is possible; false otherwise.
+ //------------------------------------------------------------------
+ bool CanJIT ();
+
+ //------------------------------------------------------------------
+ /// Sets whether executing JIT-compiled code in this process
+ /// is possible.
+ ///
+ /// @param[in] can_jit
+ /// True if execution of JIT code is possible; false otherwise.
+ //------------------------------------------------------------------
+ void SetCanJIT (bool can_jit);
+
+ //------------------------------------------------------------------
+ /// Actually deallocate memory in the process.
+ ///
+ /// This function will deallocate memory in the process's address
+ /// space that was allocated with AllocateMemory.
+ ///
+ /// @param[in] ptr
+ /// A return value from AllocateMemory, pointing to the memory you
+ /// want to deallocate.
+ ///
+ /// @return
+ /// \btrue if the memory was deallocated, \bfalse otherwise.
+ //------------------------------------------------------------------
+
+ virtual Error
+ DoDeallocateMemory (lldb::addr_t ptr)
+ {
+ Error error;
+ error.SetErrorStringWithFormat("error: %s does not support deallocating in the debug process", GetPluginName().GetCString());
+ return error;
+ }
+
+
+ //------------------------------------------------------------------
+ /// The public interface to deallocating memory in the process.
+ ///
+ /// This function will deallocate memory in the process's address
+ /// space that was allocated with AllocateMemory.
+ ///
+ /// @param[in] ptr
+ /// A return value from AllocateMemory, pointing to the memory you
+ /// want to deallocate.
+ ///
+ /// @return
+ /// \btrue if the memory was deallocated, \bfalse otherwise.
+ //------------------------------------------------------------------
+
+ Error
+ DeallocateMemory (lldb::addr_t ptr);
+
+ //------------------------------------------------------------------
+ /// Get any available STDOUT.
+ ///
+ /// If the process was launched without supplying valid file paths
+ /// for stdin, stdout, and stderr, then the Process class might
+ /// try to cache the STDOUT for the process if it is able. Events
+ /// will be queued indicating that there is STDOUT available that
+ /// can be retrieved using this function.
+ ///
+ /// @param[out] buf
+ /// A buffer that will receive any STDOUT bytes that are
+ /// currently available.
+ ///
+ /// @param[out] buf_size
+ /// The size in bytes for the buffer \a buf.
+ ///
+ /// @return
+ /// The number of bytes written into \a buf. If this value is
+ /// equal to \a buf_size, another call to this function should
+ /// be made to retrieve more STDOUT data.
+ //------------------------------------------------------------------
+ virtual size_t
+ GetSTDOUT (char *buf, size_t buf_size, Error &error);
+
+ //------------------------------------------------------------------
+ /// Get any available STDERR.
+ ///
+ /// If the process was launched without supplying valid file paths
+ /// for stdin, stdout, and stderr, then the Process class might
+ /// try to cache the STDERR for the process if it is able. Events
+ /// will be queued indicating that there is STDERR available that
+ /// can be retrieved using this function.
+ ///
+ /// @param[out] buf
+ /// A buffer that will receive any STDERR bytes that are
+ /// currently available.
+ ///
+ /// @param[out] buf_size
+ /// The size in bytes for the buffer \a buf.
+ ///
+ /// @return
+ /// The number of bytes written into \a buf. If this value is
+ /// equal to \a buf_size, another call to this function should
+ /// be made to retrieve more STDERR data.
+ //------------------------------------------------------------------
+ virtual size_t
+ GetSTDERR (char *buf, size_t buf_size, Error &error);
+
+ virtual size_t
+ PutSTDIN (const char *buf, size_t buf_size, Error &error)
+ {
+ error.SetErrorString("stdin unsupported");
+ return 0;
+ }
+
+ //------------------------------------------------------------------
+ /// Get any available profile data.
+ ///
+ /// @param[out] buf
+ /// A buffer that will receive any profile data bytes that are
+ /// currently available.
+ ///
+ /// @param[out] buf_size
+ /// The size in bytes for the buffer \a buf.
+ ///
+ /// @return
+ /// The number of bytes written into \a buf. If this value is
+ /// equal to \a buf_size, another call to this function should
+ /// be made to retrieve more profile data.
+ //------------------------------------------------------------------
+ virtual size_t
+ GetAsyncProfileData (char *buf, size_t buf_size, Error &error);
+
+ //----------------------------------------------------------------------
+ // Process Breakpoints
+ //----------------------------------------------------------------------
+ size_t
+ GetSoftwareBreakpointTrapOpcode (BreakpointSite* bp_site);
+
+ virtual Error
+ EnableBreakpointSite (BreakpointSite *bp_site)
+ {
+ Error error;
+ error.SetErrorStringWithFormat("error: %s does not support enabling breakpoints", GetPluginName().GetCString());
+ return error;
+ }
+
+
+ virtual Error
+ DisableBreakpointSite (BreakpointSite *bp_site)
+ {
+ Error error;
+ error.SetErrorStringWithFormat("error: %s does not support disabling breakpoints", GetPluginName().GetCString());
+ return error;
+ }
+
+
+ // This is implemented completely using the lldb::Process API. Subclasses
+ // don't need to implement this function unless the standard flow of
+ // read existing opcode, write breakpoint opcode, verify breakpoint opcode
+ // doesn't work for a specific process plug-in.
+ virtual Error
+ EnableSoftwareBreakpoint (BreakpointSite *bp_site);
+
+ // This is implemented completely using the lldb::Process API. Subclasses
+ // don't need to implement this function unless the standard flow of
+ // restoring original opcode in memory and verifying the restored opcode
+ // doesn't work for a specific process plug-in.
+ virtual Error
+ DisableSoftwareBreakpoint (BreakpointSite *bp_site);
+
+ BreakpointSiteList &
+ GetBreakpointSiteList();
+
+ const BreakpointSiteList &
+ GetBreakpointSiteList() const;
+
+ void
+ DisableAllBreakpointSites ();
+
+ Error
+ ClearBreakpointSiteByID (lldb::user_id_t break_id);
+
+ lldb::break_id_t
+ CreateBreakpointSite (const lldb::BreakpointLocationSP &owner,
+ bool use_hardware);
+
+ Error
+ DisableBreakpointSiteByID (lldb::user_id_t break_id);
+
+ Error
+ EnableBreakpointSiteByID (lldb::user_id_t break_id);
+
+
+ // BreakpointLocations use RemoveOwnerFromBreakpointSite to remove
+ // themselves from the owner's list of this breakpoint sites.
+ void
+ RemoveOwnerFromBreakpointSite (lldb::user_id_t owner_id,
+ lldb::user_id_t owner_loc_id,
+ lldb::BreakpointSiteSP &bp_site_sp);
+
+ //----------------------------------------------------------------------
+ // Process Watchpoints (optional)
+ //----------------------------------------------------------------------
+ virtual Error
+ EnableWatchpoint (Watchpoint *wp, bool notify = true);
+
+ virtual Error
+ DisableWatchpoint (Watchpoint *wp, bool notify = true);
+
+ //------------------------------------------------------------------
+ // Thread Queries
+ //------------------------------------------------------------------
+ virtual bool
+ UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list) = 0;
+
+ void
+ UpdateThreadListIfNeeded ();
+
+ ThreadList &
+ GetThreadList ()
+ {
+ return m_thread_list;
+ }
+
+ uint32_t
+ GetNextThreadIndexID (uint64_t thread_id);
+
+ lldb::ThreadSP
+ CreateOSPluginThread (lldb::tid_t tid, lldb::addr_t context);
+
+ // Returns true if an index id has been assigned to a thread.
+ bool
+ HasAssignedIndexIDToThread(uint64_t sb_thread_id);
+
+ // Given a thread_id, it will assign a more reasonable index id for display to the user.
+ // If the thread_id has previously been assigned, the same index id will be used.
+ uint32_t
+ AssignIndexIDToThread(uint64_t thread_id);
+
+ //------------------------------------------------------------------
+ // Event Handling
+ //------------------------------------------------------------------
+ lldb::StateType
+ GetNextEvent (lldb::EventSP &event_sp);
+
+ lldb::StateType
+ WaitForProcessToStop (const TimeValue *timeout, lldb::EventSP *event_sp_ptr = NULL);
+
+ lldb::StateType
+ WaitForStateChangedEvents (const TimeValue *timeout, lldb::EventSP &event_sp);
+
+ Event *
+ PeekAtStateChangedEvents ();
+
+
+ class
+ ProcessEventHijacker
+ {
+ public:
+ ProcessEventHijacker (Process &process, Listener *listener) :
+ m_process (process)
+ {
+ m_process.HijackProcessEvents (listener);
+ }
+ ~ProcessEventHijacker ()
+ {
+ m_process.RestoreProcessEvents();
+ }
+
+ private:
+ Process &m_process;
+ };
+ friend class ProcessEventHijacker;
+ //------------------------------------------------------------------
+ /// If you need to ensure that you and only you will hear about some public
+ /// event, then make a new listener, set to listen to process events, and
+ /// then call this with that listener. Then you will have to wait on that
+ /// listener explicitly for events (rather than using the GetNextEvent & WaitFor*
+ /// calls above. Be sure to call RestoreProcessEvents when you are done.
+ ///
+ /// @param[in] listener
+ /// This is the new listener to whom all process events will be delivered.
+ ///
+ /// @return
+ /// Returns \b true if the new listener could be installed,
+ /// \b false otherwise.
+ //------------------------------------------------------------------
+ bool
+ HijackProcessEvents (Listener *listener);
+
+ //------------------------------------------------------------------
+ /// Restores the process event broadcasting to its normal state.
+ ///
+ //------------------------------------------------------------------
+ void
+ RestoreProcessEvents ();
+
+private:
+ //------------------------------------------------------------------
+ /// This is the part of the event handling that for a process event.
+ /// It decides what to do with the event and returns true if the
+ /// event needs to be propagated to the user, and false otherwise.
+ /// If the event is not propagated, this call will most likely set
+ /// the target to executing again.
+ /// There is only one place where this call should be called, HandlePrivateEvent.
+ /// Don't call it from anywhere else...
+ ///
+ /// @param[in] event_ptr
+ /// This is the event we are handling.
+ ///
+ /// @return
+ /// Returns \b true if the event should be reported to the
+ /// user, \b false otherwise.
+ //------------------------------------------------------------------
+ bool
+ ShouldBroadcastEvent (Event *event_ptr);
+
+public:
+ const lldb::ABISP &
+ GetABI ();
+
+ OperatingSystem *
+ GetOperatingSystem ()
+ {
+ return m_os_ap.get();
+ }
+
+
+ virtual LanguageRuntime *
+ GetLanguageRuntime (lldb::LanguageType language, bool retry_if_null = true);
+
+ virtual CPPLanguageRuntime *
+ GetCPPLanguageRuntime (bool retry_if_null = true);
+
+ virtual ObjCLanguageRuntime *
+ GetObjCLanguageRuntime (bool retry_if_null = true);
+
+ bool
+ IsPossibleDynamicValue (ValueObject& in_value);
+
+ bool
+ IsRunning () const;
+
+ DynamicCheckerFunctions *GetDynamicCheckers()
+ {
+ return m_dynamic_checkers_ap.get();
+ }
+
+ void SetDynamicCheckers(DynamicCheckerFunctions *dynamic_checkers)
+ {
+ m_dynamic_checkers_ap.reset(dynamic_checkers);
+ }
+
+ //------------------------------------------------------------------
+ /// Call this to set the lldb in the mode where it breaks on new thread
+ /// creations, and then auto-restarts. This is useful when you are trying
+ /// to run only one thread, but either that thread or the kernel is creating
+ /// new threads in the process. If you stop when the thread is created, you
+ /// can immediately suspend it, and keep executing only the one thread you intend.
+ ///
+ /// @return
+ /// Returns \b true if we were able to start up the notification
+ /// \b false otherwise.
+ //------------------------------------------------------------------
+ virtual bool
+ StartNoticingNewThreads()
+ {
+ return true;
+ }
+
+ //------------------------------------------------------------------
+ /// Call this to turn off the stop & notice new threads mode.
+ ///
+ /// @return
+ /// Returns \b true if we were able to start up the notification
+ /// \b false otherwise.
+ //------------------------------------------------------------------
+ virtual bool
+ StopNoticingNewThreads()
+ {
+ return true;
+ }
+
+ void
+ SetRunningUserExpression (bool on);
+
+ //------------------------------------------------------------------
+ // lldb::ExecutionContextScope pure virtual functions
+ //------------------------------------------------------------------
+ virtual lldb::TargetSP
+ CalculateTarget ();
+
+ virtual lldb::ProcessSP
+ CalculateProcess ()
+ {
+ return shared_from_this();
+ }
+
+ virtual lldb::ThreadSP
+ CalculateThread ()
+ {
+ return lldb::ThreadSP();
+ }
+
+ virtual lldb::StackFrameSP
+ CalculateStackFrame ()
+ {
+ return lldb::StackFrameSP();
+ }
+
+ virtual void
+ CalculateExecutionContext (ExecutionContext &exe_ctx);
+
+ void
+ SetSTDIOFileDescriptor (int file_descriptor);
+
+ //------------------------------------------------------------------
+ // Add a permanent region of memory that should never be read or
+ // written to. This can be used to ensure that memory reads or writes
+ // to certain areas of memory never end up being sent to the
+ // DoReadMemory or DoWriteMemory functions which can improve
+ // performance.
+ //------------------------------------------------------------------
+ void
+ AddInvalidMemoryRegion (const LoadRange &region);
+
+ //------------------------------------------------------------------
+ // Remove a permanent region of memory that should never be read or
+ // written to that was previously added with AddInvalidMemoryRegion.
+ //------------------------------------------------------------------
+ bool
+ RemoveInvalidMemoryRange (const LoadRange &region);
+
+ //------------------------------------------------------------------
+ // If the setup code of a thread plan needs to do work that might involve
+ // calling a function in the target, it should not do that work directly
+ // in one of the thread plan functions (DidPush/WillResume) because
+ // such work needs to be handled carefully. Instead, put that work in
+ // a PreResumeAction callback, and register it with the process. It will
+ // get done before the actual "DoResume" gets called.
+ //------------------------------------------------------------------
+
+ typedef bool (PreResumeActionCallback)(void *);
+
+ void
+ AddPreResumeAction (PreResumeActionCallback callback, void *baton);
+
+ bool
+ RunPreResumeActions ();
+
+ void
+ ClearPreResumeActions ();
+
+ ProcessRunLock &
+ GetRunLock ()
+ {
+ if (Host::GetCurrentThread() == m_private_state_thread)
+ return m_private_run_lock;
+ else
+ return m_public_run_lock;
+ }
+
+protected:
+ //------------------------------------------------------------------
+ // NextEventAction provides a way to register an action on the next
+ // event that is delivered to this process. There is currently only
+ // one next event action allowed in the process at one time. If a
+ // new "NextEventAction" is added while one is already present, the
+ // old action will be discarded (with HandleBeingUnshipped called
+ // after it is discarded.)
+ //
+ // If you want to resume the process as a result of a resume action,
+ // call RequestResume, don't call Resume directly.
+ //------------------------------------------------------------------
+ class NextEventAction
+ {
+ public:
+ typedef enum EventActionResult
+ {
+ eEventActionSuccess,
+ eEventActionRetry,
+ eEventActionExit
+ } EventActionResult;
+
+ NextEventAction (Process *process) :
+ m_process(process)
+ {
+ }
+
+ virtual
+ ~NextEventAction()
+ {
+ }
+
+ virtual EventActionResult PerformAction (lldb::EventSP &event_sp) = 0;
+ virtual void HandleBeingUnshipped () {}
+ virtual EventActionResult HandleBeingInterrupted () = 0;
+ virtual const char *GetExitString() = 0;
+ void RequestResume()
+ {
+ m_process->m_resume_requested = true;
+ }
+ protected:
+ Process *m_process;
+ };
+
+ void SetNextEventAction (Process::NextEventAction *next_event_action)
+ {
+ if (m_next_event_action_ap.get())
+ m_next_event_action_ap->HandleBeingUnshipped();
+
+ m_next_event_action_ap.reset(next_event_action);
+ }
+
+ // This is the completer for Attaching:
+ class AttachCompletionHandler : public NextEventAction
+ {
+ public:
+ AttachCompletionHandler (Process *process, uint32_t exec_count) :
+ NextEventAction (process),
+ m_exec_count (exec_count)
+ {
+ }
+
+ virtual
+ ~AttachCompletionHandler()
+ {
+ }
+
+ virtual EventActionResult PerformAction (lldb::EventSP &event_sp);
+ virtual EventActionResult HandleBeingInterrupted ();
+ virtual const char *GetExitString();
+ private:
+ uint32_t m_exec_count;
+ std::string m_exit_string;
+ };
+
+ bool
+ HijackPrivateProcessEvents (Listener *listener);
+
+ void
+ RestorePrivateProcessEvents ();
+
+ bool
+ PrivateStateThreadIsValid () const
+ {
+ return IS_VALID_LLDB_HOST_THREAD(m_private_state_thread);
+ }
+
+ //------------------------------------------------------------------
+ // Type definitions
+ //------------------------------------------------------------------
+ typedef std::map<lldb::LanguageType, lldb::LanguageRuntimeSP> LanguageRuntimeCollection;
+
+ struct PreResumeCallbackAndBaton
+ {
+ bool (*callback) (void *);
+ void *baton;
+ PreResumeCallbackAndBaton (PreResumeActionCallback in_callback, void *in_baton) :
+ callback (in_callback),
+ baton (in_baton)
+ {
+ }
+ };
+
+ //------------------------------------------------------------------
+ // Member variables
+ //------------------------------------------------------------------
+ Target & m_target; ///< The target that owns this process.
+ ThreadSafeValue<lldb::StateType> m_public_state;
+ ThreadSafeValue<lldb::StateType> m_private_state; // The actual state of our process
+ Broadcaster m_private_state_broadcaster; // This broadcaster feeds state changed events into the private state thread's listener.
+ Broadcaster m_private_state_control_broadcaster; // This is the control broadcaster, used to pause, resume & stop the private state thread.
+ Listener m_private_state_listener; // This is the listener for the private state thread.
+ Predicate<bool> m_private_state_control_wait; /// This Predicate is used to signal that a control operation is complete.
+ lldb::thread_t m_private_state_thread; // Thread ID for the thread that watches interal state events
+ ProcessModID m_mod_id; ///< Tracks the state of the process over stops and other alterations.
+ uint32_t m_process_unique_id; ///< Each lldb_private::Process class that is created gets a unique integer ID that increments with each new instance
+ uint32_t m_thread_index_id; ///< Each thread is created with a 1 based index that won't get re-used.
+ std::map<uint64_t, uint32_t> m_thread_id_to_index_id_map;
+ int m_exit_status; ///< The exit status of the process, or -1 if not set.
+ std::string m_exit_string; ///< A textual description of why a process exited.
+ Mutex m_thread_mutex;
+ ThreadList m_thread_list_real; ///< The threads for this process as are known to the protocol we are debugging with
+ ThreadList m_thread_list; ///< The threads for this process as the user will see them. This is usually the same as
+ ///< m_thread_list_real, but might be different if there is an OS plug-in creating memory threads
+ std::vector<Notifications> m_notifications; ///< The list of notifications that this process can deliver.
+ std::vector<lldb::addr_t> m_image_tokens;
+ Listener &m_listener;
+ BreakpointSiteList m_breakpoint_site_list; ///< This is the list of breakpoint locations we intend to insert in the target.
+ std::unique_ptr<DynamicLoader> m_dyld_ap;
+ std::unique_ptr<DynamicCheckerFunctions> m_dynamic_checkers_ap; ///< The functions used by the expression parser to validate data that expressions use.
+ std::unique_ptr<OperatingSystem> m_os_ap;
+ UnixSignals m_unix_signals; /// This is the current signal set for this process.
+ lldb::ABISP m_abi_sp;
+ lldb::InputReaderSP m_process_input_reader;
+ Communication m_stdio_communication;
+ Mutex m_stdio_communication_mutex;
+ std::string m_stdout_data;
+ std::string m_stderr_data;
+ Mutex m_profile_data_comm_mutex;
+ std::vector<std::string> m_profile_data;
+ MemoryCache m_memory_cache;
+ AllocatedMemoryCache m_allocated_memory_cache;
+ bool m_should_detach; /// Should we detach if the process object goes away with an explicit call to Kill or Detach?
+ LanguageRuntimeCollection m_language_runtimes;
+ std::unique_ptr<NextEventAction> m_next_event_action_ap;
+ std::vector<PreResumeCallbackAndBaton> m_pre_resume_actions;
+ ProcessRunLock m_public_run_lock;
+ ProcessRunLock m_private_run_lock;
+ Predicate<bool> m_currently_handling_event; // This predicate is set in HandlePrivateEvent while all its business is being done.
+ bool m_currently_handling_do_on_removals;
+ bool m_resume_requested; // If m_currently_handling_event or m_currently_handling_do_on_removals are true, Resume will only request a resume, using this flag to check.
+ bool m_finalize_called;
+ bool m_clear_thread_plans_on_stop;
+ lldb::StateType m_last_broadcast_state; /// This helps with the Public event coalescing in ShouldBroadcastEvent.
+ bool m_destroy_in_process;
+
+ enum {
+ eCanJITDontKnow= 0,
+ eCanJITYes,
+ eCanJITNo
+ } m_can_jit;
+
+ size_t
+ RemoveBreakpointOpcodesFromBuffer (lldb::addr_t addr, size_t size, uint8_t *buf) const;
+
+ void
+ SynchronouslyNotifyStateChanged (lldb::StateType state);
+
+ void
+ SetPublicState (lldb::StateType new_state, bool restarted);
+
+ void
+ SetPrivateState (lldb::StateType state);
+
+ bool
+ StartPrivateStateThread (bool force = false);
+
+ void
+ StopPrivateStateThread ();
+
+ void
+ PausePrivateStateThread ();
+
+ void
+ ResumePrivateStateThread ();
+
+ static void *
+ PrivateStateThread (void *arg);
+
+ void *
+ RunPrivateStateThread ();
+
+ void
+ HandlePrivateEvent (lldb::EventSP &event_sp);
+
+ lldb::StateType
+ WaitForProcessStopPrivate (const TimeValue *timeout, lldb::EventSP &event_sp);
+
+ // This waits for both the state change broadcaster, and the control broadcaster.
+ // If control_only, it only waits for the control broadcaster.
+
+ bool
+ WaitForEventsPrivate (const TimeValue *timeout, lldb::EventSP &event_sp, bool control_only);
+
+ lldb::StateType
+ WaitForStateChangedEventsPrivate (const TimeValue *timeout, lldb::EventSP &event_sp);
+
+ lldb::StateType
+ WaitForState (const TimeValue *timeout,
+ const lldb::StateType *match_states,
+ const uint32_t num_match_states);
+
+ size_t
+ WriteMemoryPrivate (lldb::addr_t addr, const void *buf, size_t size, Error &error);
+
+ void
+ AppendSTDOUT (const char *s, size_t len);
+
+ void
+ AppendSTDERR (const char *s, size_t len);
+
+ void
+ BroadcastAsyncProfileData(const std::string &one_profile_data);
+
+ static void
+ STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len);
+
+ void
+ PushProcessInputReader ();
+
+ void
+ PopProcessInputReader ();
+
+ void
+ ResetProcessInputReader ();
+
+ static size_t
+ ProcessInputReaderCallback (void *baton,
+ InputReader &reader,
+ lldb::InputReaderAction notification,
+ const char *bytes,
+ size_t bytes_len);
+
+ Error
+ HaltForDestroyOrDetach(lldb::EventSP &exit_event_sp);
+
+private:
+ //------------------------------------------------------------------
+ // For Process only
+ //------------------------------------------------------------------
+ void ControlPrivateStateThread (uint32_t signal);
+
+ DISALLOW_COPY_AND_ASSIGN (Process);
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_Process_h_
diff --git a/include/lldb/Target/RegisterContext.h b/include/lldb/Target/RegisterContext.h
new file mode 100644
index 000000000000..dd0e73fc7eb3
--- /dev/null
+++ b/include/lldb/Target/RegisterContext.h
@@ -0,0 +1,213 @@
+//===-- RegisterContext.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_RegisterContext_h_
+#define liblldb_RegisterContext_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/ExecutionContextScope.h"
+
+namespace lldb_private {
+
+class RegisterContext :
+ public std::enable_shared_from_this<RegisterContext>,
+ public ExecutionContextScope
+{
+public:
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ RegisterContext (Thread &thread, uint32_t concrete_frame_idx);
+
+ virtual
+ ~RegisterContext ();
+
+ void
+ InvalidateIfNeeded (bool force);
+
+ //------------------------------------------------------------------
+ // Subclasses must override these functions
+ //------------------------------------------------------------------
+ virtual void
+ InvalidateAllRegisters () = 0;
+
+ virtual size_t
+ GetRegisterCount () = 0;
+
+ virtual const RegisterInfo *
+ GetRegisterInfoAtIndex (size_t reg) = 0;
+
+ virtual size_t
+ GetRegisterSetCount () = 0;
+
+ virtual const RegisterSet *
+ GetRegisterSet (size_t reg_set) = 0;
+
+ virtual bool
+ ReadRegister (const RegisterInfo *reg_info, RegisterValue &reg_value) = 0;
+
+ virtual bool
+ WriteRegister (const RegisterInfo *reg_info, const RegisterValue &reg_value) = 0;
+
+ // These two functions are used to implement "push" and "pop" of register states. They are used primarily
+ // for expression evaluation, where we need to push a new state (storing the old one in data_sp) and then
+ // restoring the original state by passing the data_sp we got from ReadAllRegisters to WriteAllRegisterValues.
+ // ReadAllRegisters will do what is necessary to return a coherent set of register values for this thread, which
+ // may mean e.g. interrupting a thread that is sitting in a kernel trap. That is a somewhat disruptive operation,
+ // so these API's should only be used when this behavior is needed.
+
+ virtual bool
+ ReadAllRegisterValues (lldb::DataBufferSP &data_sp) = 0;
+
+ virtual bool
+ WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) = 0;
+
+ bool
+ CopyFromRegisterContext (lldb::RegisterContextSP context);
+
+ virtual uint32_t
+ ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) = 0;
+
+ //------------------------------------------------------------------
+ // Subclasses can override these functions if desired
+ //------------------------------------------------------------------
+ virtual uint32_t
+ NumSupportedHardwareBreakpoints ();
+
+ virtual uint32_t
+ SetHardwareBreakpoint (lldb::addr_t addr, size_t size);
+
+ virtual bool
+ ClearHardwareBreakpoint (uint32_t hw_idx);
+
+ virtual uint32_t
+ NumSupportedHardwareWatchpoints ();
+
+ virtual uint32_t
+ SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write);
+
+ virtual bool
+ ClearHardwareWatchpoint (uint32_t hw_index);
+
+ virtual bool
+ HardwareSingleStep (bool enable);
+
+ virtual Error
+ ReadRegisterValueFromMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t src_addr, uint32_t src_len, RegisterValue &reg_value);
+
+ virtual Error
+ WriteRegisterValueToMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t dst_addr, uint32_t dst_len, const RegisterValue &reg_value);
+
+ //------------------------------------------------------------------
+ // Subclasses should not override these
+ //------------------------------------------------------------------
+ virtual lldb::tid_t
+ GetThreadID() const;
+
+ virtual Thread &
+ GetThread ()
+ {
+ return m_thread;
+ }
+
+ const RegisterInfo *
+ GetRegisterInfoByName (const char *reg_name, uint32_t start_idx = 0);
+
+ uint64_t
+ GetPC (uint64_t fail_value = LLDB_INVALID_ADDRESS);
+
+ bool
+ SetPC (uint64_t pc);
+
+ uint64_t
+ GetSP (uint64_t fail_value = LLDB_INVALID_ADDRESS);
+
+ bool
+ SetSP (uint64_t sp);
+
+ uint64_t
+ GetFP (uint64_t fail_value = LLDB_INVALID_ADDRESS);
+
+ bool
+ SetFP (uint64_t fp);
+
+ const char *
+ GetRegisterName (uint32_t reg);
+
+ uint64_t
+ GetReturnAddress (uint64_t fail_value = LLDB_INVALID_ADDRESS);
+
+ uint64_t
+ GetFlags (uint64_t fail_value = 0);
+
+ uint64_t
+ ReadRegisterAsUnsigned (uint32_t reg, uint64_t fail_value);
+
+ uint64_t
+ ReadRegisterAsUnsigned (const RegisterInfo *reg_info, uint64_t fail_value);
+
+ bool
+ WriteRegisterFromUnsigned (uint32_t reg, uint64_t uval);
+
+ bool
+ WriteRegisterFromUnsigned (const RegisterInfo *reg_info, uint64_t uval);
+ bool
+ ConvertBetweenRegisterKinds (int source_rk, uint32_t source_regnum, int target_rk, uint32_t& target_regnum);
+
+ //------------------------------------------------------------------
+ // lldb::ExecutionContextScope pure virtual functions
+ //------------------------------------------------------------------
+ virtual lldb::TargetSP
+ CalculateTarget ();
+
+ virtual lldb::ProcessSP
+ CalculateProcess ();
+
+ virtual lldb::ThreadSP
+ CalculateThread ();
+
+ virtual lldb::StackFrameSP
+ CalculateStackFrame ();
+
+ virtual void
+ CalculateExecutionContext (ExecutionContext &exe_ctx);
+
+ uint32_t
+ GetStopID () const
+ {
+ return m_stop_id;
+ }
+
+ void
+ SetStopID (uint32_t stop_id)
+ {
+ m_stop_id = stop_id;
+ }
+
+protected:
+ //------------------------------------------------------------------
+ // Classes that inherit from RegisterContext can see and modify these
+ //------------------------------------------------------------------
+ Thread &m_thread; // The thread that this register context belongs to.
+ uint32_t m_concrete_frame_idx; // The concrete frame index for this register context
+ uint32_t m_stop_id; // The stop ID that any data in this context is valid for
+private:
+ //------------------------------------------------------------------
+ // For RegisterContext only
+ //------------------------------------------------------------------
+ DISALLOW_COPY_AND_ASSIGN (RegisterContext);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_RegisterContext_h_
diff --git a/include/lldb/Target/SectionLoadList.h b/include/lldb/Target/SectionLoadList.h
new file mode 100644
index 000000000000..ac05bf7a9cb4
--- /dev/null
+++ b/include/lldb/Target/SectionLoadList.h
@@ -0,0 +1,89 @@
+//===-- SectionLoadList.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_SectionLoadList_h_
+#define liblldb_SectionLoadList_h_
+
+// C Includes
+// C++ Includes
+#include <map>
+
+// Other libraries and framework includes
+#include "llvm/ADT/DenseMap.h"
+// Project includes
+#include "lldb/lldb-public.h"
+#include "lldb/Host/Mutex.h"
+
+namespace lldb_private {
+
+class SectionLoadList
+{
+public:
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ SectionLoadList () :
+ m_addr_to_sect (),
+ m_sect_to_addr (),
+ m_mutex (Mutex::eMutexTypeRecursive)
+
+ {
+ }
+
+ ~SectionLoadList()
+ {
+ // Call clear since this takes a lock and clears the section load list
+ // in case another thread is currently using this section load list
+ Clear();
+ }
+
+ bool
+ IsEmpty() const;
+
+ void
+ Clear ();
+
+ lldb::addr_t
+ GetSectionLoadAddress (const lldb::SectionSP &section_sp) const;
+
+ bool
+ ResolveLoadAddress (lldb::addr_t load_addr, Address &so_addr) const;
+
+ bool
+ SetSectionLoadAddress (const lldb::SectionSP &section_sp, lldb::addr_t load_addr, bool warn_multiple = false);
+
+ // The old load address should be specified when unloading to ensure we get
+ // the correct instance of the section as a shared library could be loaded
+ // at more than one location.
+ bool
+ SetSectionUnloaded (const lldb::SectionSP &section_sp, lldb::addr_t load_addr);
+
+ // Unload all instances of a section. This function can be used on systems
+ // that don't support multiple copies of the same shared library to be
+ // loaded at the same time.
+ size_t
+ SetSectionUnloaded (const lldb::SectionSP &section_sp);
+
+ void
+ Dump (Stream &s, Target *target);
+
+protected:
+ typedef std::map<lldb::addr_t, lldb::SectionSP> addr_to_sect_collection;
+ typedef llvm::DenseMap<const Section *, lldb::addr_t> sect_to_addr_collection;
+ addr_to_sect_collection m_addr_to_sect;
+ sect_to_addr_collection m_sect_to_addr;
+ mutable Mutex m_mutex;
+
+private:
+ DISALLOW_COPY_AND_ASSIGN (SectionLoadList);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_SectionLoadList_h_
diff --git a/include/lldb/Target/StackFrame.h b/include/lldb/Target/StackFrame.h
new file mode 100644
index 000000000000..877bd8ce661b
--- /dev/null
+++ b/include/lldb/Target/StackFrame.h
@@ -0,0 +1,207 @@
+//===-- StackFrame.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_StackFrame_h_
+#define liblldb_StackFrame_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Flags.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/UserID.h"
+#include "lldb/Core/ValueObjectList.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Target/ExecutionContextScope.h"
+#include "lldb/Target/StackID.h"
+
+namespace lldb_private {
+
+class StackFrame :
+ public std::enable_shared_from_this<StackFrame>,
+ public ExecutionContextScope
+{
+public:
+ enum ExpressionPathOption
+ {
+ eExpressionPathOptionCheckPtrVsMember = (1u << 0),
+ eExpressionPathOptionsNoFragileObjcIvar = (1u << 1),
+ eExpressionPathOptionsNoSyntheticChildren = (1u << 2),
+ eExpressionPathOptionsNoSyntheticArrayRange = (1u << 3),
+ eExpressionPathOptionsAllowDirectIVarAccess = (1u << 4)
+ };
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ StackFrame (const lldb::ThreadSP &thread_sp,
+ lldb::user_id_t frame_idx,
+ lldb::user_id_t concrete_frame_idx,
+ lldb::addr_t cfa,
+ lldb::addr_t pc,
+ const SymbolContext *sc_ptr);
+
+ StackFrame (const lldb::ThreadSP &thread_sp,
+ lldb::user_id_t frame_idx,
+ lldb::user_id_t concrete_frame_idx,
+ const lldb::RegisterContextSP &reg_context_sp,
+ lldb::addr_t cfa,
+ lldb::addr_t pc,
+ const SymbolContext *sc_ptr);
+
+ StackFrame (const lldb::ThreadSP &thread_sp,
+ lldb::user_id_t frame_idx,
+ lldb::user_id_t concrete_frame_idx,
+ const lldb::RegisterContextSP &reg_context_sp,
+ lldb::addr_t cfa,
+ const Address& pc,
+ const SymbolContext *sc_ptr);
+
+ virtual ~StackFrame ();
+
+ lldb::ThreadSP
+ GetThread () const
+ {
+ return m_thread_wp.lock();
+ }
+
+ StackID&
+ GetStackID();
+
+ const Address&
+ GetFrameCodeAddress();
+
+ void
+ ChangePC (lldb::addr_t pc);
+
+ const SymbolContext&
+ GetSymbolContext (uint32_t resolve_scope);
+
+ bool
+ GetFrameBaseValue(Scalar &value, Error *error_ptr);
+
+ Block *
+ GetFrameBlock ();
+
+ lldb::RegisterContextSP
+ GetRegisterContext ();
+
+ const lldb::RegisterContextSP &
+ GetRegisterContextSP () const
+ {
+ return m_reg_context_sp;
+ }
+
+ VariableList *
+ GetVariableList (bool get_file_globals);
+
+ lldb::VariableListSP
+ GetInScopeVariableList (bool get_file_globals);
+
+ // See ExpressionPathOption enumeration for "options" values
+ lldb::ValueObjectSP
+ GetValueForVariableExpressionPath (const char *var_expr,
+ lldb::DynamicValueType use_dynamic,
+ uint32_t options,
+ lldb::VariableSP &var_sp,
+ Error &error);
+
+ bool
+ HasDebugInformation ();
+
+ const char *
+ Disassemble ();
+
+ void
+ DumpUsingSettingsFormat (Stream *strm);
+
+ void
+ Dump (Stream *strm, bool show_frame_index, bool show_fullpaths);
+
+ bool
+ IsInlined ();
+
+ uint32_t
+ GetFrameIndex () const;
+
+ uint32_t
+ GetConcreteFrameIndex () const
+ {
+ return m_concrete_frame_index;
+ }
+
+ lldb::ValueObjectSP
+ GetValueObjectForFrameVariable (const lldb::VariableSP &variable_sp, lldb::DynamicValueType use_dynamic);
+
+ lldb::ValueObjectSP
+ TrackGlobalVariable (const lldb::VariableSP &variable_sp, lldb::DynamicValueType use_dynamic);
+
+ //------------------------------------------------------------------
+ // lldb::ExecutionContextScope pure virtual functions
+ //------------------------------------------------------------------
+ virtual lldb::TargetSP
+ CalculateTarget ();
+
+ virtual lldb::ProcessSP
+ CalculateProcess ();
+
+ virtual lldb::ThreadSP
+ CalculateThread ();
+
+ virtual lldb::StackFrameSP
+ CalculateStackFrame ();
+
+ virtual void
+ CalculateExecutionContext (ExecutionContext &exe_ctx);
+
+ bool
+ GetStatus (Stream &strm,
+ bool show_frame_info,
+ bool show_source);
+
+protected:
+ friend class StackFrameList;
+
+ void
+ SetSymbolContextScope (SymbolContextScope *symbol_scope);
+
+ void
+ UpdateCurrentFrameFromPreviousFrame (StackFrame &prev_frame);
+
+ void
+ UpdatePreviousFrameFromCurrentFrame (StackFrame &curr_frame);
+
+ bool
+ HasCachedData () const;
+
+private:
+ //------------------------------------------------------------------
+ // For StackFrame only
+ //------------------------------------------------------------------
+ lldb::ThreadWP m_thread_wp;
+ uint32_t m_frame_index;
+ uint32_t m_concrete_frame_index;
+ lldb::RegisterContextSP m_reg_context_sp;
+ StackID m_id;
+ Address m_frame_code_addr; // The frame code address (might not be the same as the actual PC for inlined frames) as a section/offset address
+ SymbolContext m_sc;
+ Flags m_flags;
+ Scalar m_frame_base;
+ Error m_frame_base_error;
+ lldb::VariableListSP m_variable_list_sp;
+ ValueObjectList m_variable_list_value_objects; // Value objects for each variable in m_variable_list_sp
+ StreamString m_disassembly;
+ DISALLOW_COPY_AND_ASSIGN (StackFrame);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_StackFrame_h_
diff --git a/include/lldb/Target/StackFrameList.h b/include/lldb/Target/StackFrameList.h
new file mode 100644
index 000000000000..b2689d0391e9
--- /dev/null
+++ b/include/lldb/Target/StackFrameList.h
@@ -0,0 +1,157 @@
+//===-- StackFrameList.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_StackFrameList_h_
+#define liblldb_StackFrameList_h_
+
+// C Includes
+// C++ Includes
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Host/Mutex.h"
+#include "lldb/Target/StackFrame.h"
+
+namespace lldb_private {
+
+class StackFrameList
+{
+public:
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ StackFrameList (Thread &thread,
+ const lldb::StackFrameListSP &prev_frames_sp,
+ bool show_inline_frames);
+
+ ~StackFrameList();
+
+ uint32_t
+ GetNumFrames (bool can_create = true);
+
+ lldb::StackFrameSP
+ GetFrameAtIndex (uint32_t idx);
+
+ lldb::StackFrameSP
+ GetFrameWithConcreteFrameIndex (uint32_t unwind_idx);
+
+ lldb::StackFrameSP
+ GetFrameWithStackID (const StackID &stack_id);
+
+ // Mark a stack frame as the current frame
+ uint32_t
+ SetSelectedFrame (lldb_private::StackFrame *frame);
+
+ uint32_t
+ GetSelectedFrameIndex () const;
+
+ // Mark a stack frame as the current frame using the frame index
+ bool
+ SetSelectedFrameByIndex (uint32_t idx);
+
+ uint32_t
+ GetVisibleStackFrameIndex(uint32_t idx)
+ {
+ if (m_current_inlined_depth < UINT32_MAX)
+ return idx - m_current_inlined_depth;
+ else
+ return idx;
+ }
+
+ void
+ CalculateCurrentInlinedDepth ();
+
+ void
+ SetDefaultFileAndLineToSelectedFrame();
+
+ void
+ Clear ();
+
+ void
+ InvalidateFrames (uint32_t start_idx);
+
+ void
+ Dump (Stream *s);
+
+ lldb::StackFrameSP
+ GetStackFrameSPForStackFramePtr (StackFrame *stack_frame_ptr);
+
+ size_t
+ GetStatus (Stream &strm,
+ uint32_t first_frame,
+ uint32_t num_frames,
+ bool show_frame_info,
+ uint32_t num_frames_with_source);
+
+protected:
+
+ friend class Thread;
+
+ bool
+ SetFrameAtIndex (uint32_t idx, lldb::StackFrameSP &frame_sp);
+
+ static void
+ Merge (std::unique_ptr<StackFrameList>& curr_ap,
+ lldb::StackFrameListSP& prev_sp);
+
+ void
+ GetFramesUpTo (uint32_t end_idx);
+
+ bool
+ GetAllFramesFetched()
+ {
+ return m_concrete_frames_fetched == UINT32_MAX;
+ }
+
+ void
+ SetAllFramesFetched ()
+ {
+ m_concrete_frames_fetched = UINT32_MAX;
+ }
+
+ bool
+ DecrementCurrentInlinedDepth ();
+
+ void
+ ResetCurrentInlinedDepth();
+
+ uint32_t
+ GetCurrentInlinedDepth ();
+
+ void
+ SetCurrentInlinedDepth (uint32_t new_depth);
+
+ //------------------------------------------------------------------
+ // Classes that inherit from StackFrameList can see and modify these
+ //------------------------------------------------------------------
+ typedef std::vector<lldb::StackFrameSP> collection;
+ typedef collection::iterator iterator;
+ typedef collection::const_iterator const_iterator;
+
+ Thread &m_thread;
+ lldb::StackFrameListSP m_prev_frames_sp;
+ mutable Mutex m_mutex;
+ collection m_frames;
+ uint32_t m_selected_frame_idx;
+ uint32_t m_concrete_frames_fetched;
+ uint32_t m_current_inlined_depth;
+ lldb::addr_t m_current_inlined_pc;
+ bool m_show_inlined_frames;
+
+private:
+ //------------------------------------------------------------------
+ // For StackFrameList only
+ //------------------------------------------------------------------
+ DISALLOW_COPY_AND_ASSIGN (StackFrameList);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_StackFrameList_h_
diff --git a/include/lldb/Target/StackID.h b/include/lldb/Target/StackID.h
new file mode 100644
index 000000000000..7e713c73d972
--- /dev/null
+++ b/include/lldb/Target/StackID.h
@@ -0,0 +1,149 @@
+//===-- StackID.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_StackID_h_
+#define liblldb_StackID_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Core/AddressRange.h"
+
+namespace lldb_private {
+
+class StackID
+{
+public:
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ StackID () :
+ m_pc (LLDB_INVALID_ADDRESS),
+ m_cfa (LLDB_INVALID_ADDRESS),
+ m_symbol_scope (NULL)
+ {
+ }
+
+ explicit
+ StackID (lldb::addr_t pc, lldb::addr_t cfa, SymbolContextScope *symbol_scope) :
+ m_pc (pc),
+ m_cfa (cfa),
+ m_symbol_scope (symbol_scope)
+ {
+ }
+
+ StackID (const StackID& rhs) :
+ m_pc (rhs.m_pc),
+ m_cfa (rhs.m_cfa),
+ m_symbol_scope (rhs.m_symbol_scope)
+ {
+ }
+
+ ~StackID()
+ {
+ }
+
+ lldb::addr_t
+ GetPC() const
+ {
+ return m_pc;
+ }
+
+ lldb::addr_t
+ GetCallFrameAddress() const
+ {
+ return m_cfa;
+ }
+
+ SymbolContextScope *
+ GetSymbolContextScope () const
+ {
+ return m_symbol_scope;
+ }
+
+ void
+ SetSymbolContextScope (SymbolContextScope *symbol_scope)
+ {
+ m_symbol_scope = symbol_scope;
+ }
+
+ void
+ Clear ()
+ {
+ m_pc = LLDB_INVALID_ADDRESS;
+ m_cfa = LLDB_INVALID_ADDRESS;
+ m_symbol_scope = NULL;
+ }
+
+ bool
+ IsValid () const
+ {
+ return m_pc != LLDB_INVALID_ADDRESS || m_cfa != LLDB_INVALID_ADDRESS;
+ }
+
+ void
+ Dump (Stream *s);
+
+ //------------------------------------------------------------------
+ // Operators
+ //------------------------------------------------------------------
+ const StackID&
+ operator=(const StackID& rhs)
+ {
+ if (this != &rhs)
+ {
+ m_pc = rhs.m_pc;
+ m_cfa = rhs.m_cfa;
+ m_symbol_scope = rhs.m_symbol_scope;
+ }
+ return *this;
+ }
+
+protected:
+
+ friend class StackFrame;
+
+ void
+ SetPC (lldb::addr_t pc)
+ {
+ m_pc = pc;
+ }
+
+
+ //------------------------------------------------------------------
+ // Classes that inherit from StackID can see and modify these
+ //------------------------------------------------------------------
+ lldb::addr_t m_pc; // The pc value for the function/symbol for this frame. This will
+ // only get used if the symbol scope is NULL (the code where we are
+ // stopped is not represented by any function or symbol in any
+ // shared library).
+ lldb::addr_t m_cfa; // The call frame address (stack pointer) value
+ // at the beginning of the function that uniquely
+ // identifies this frame (along with m_symbol_scope below)
+ SymbolContextScope *m_symbol_scope; // If NULL, there is no block or symbol for this frame.
+ // If not NULL, this will either be the scope for the
+ // lexical block for the frame, or the scope
+ // for the symbol. Symbol context scopes are
+ // always be unique pointers since the are part
+ // of the Block and Symbol objects and can easily
+ // be used to tell if a stack ID is the same as
+ // another.
+};
+
+bool operator== (const StackID& lhs, const StackID& rhs);
+bool operator!= (const StackID& lhs, const StackID& rhs);
+
+// frame_id_1 < frame_id_2 means "frame_id_1 is YOUNGER than frame_id_2"
+bool operator< (const StackID& lhs, const StackID& rhs);
+
+} // namespace lldb_private
+
+#endif // liblldb_StackID_h_
diff --git a/include/lldb/Target/StopInfo.h b/include/lldb/Target/StopInfo.h
new file mode 100644
index 000000000000..3435d392e2b9
--- /dev/null
+++ b/include/lldb/Target/StopInfo.h
@@ -0,0 +1,227 @@
+//===-- StopInfo.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_StopInfo_h_
+#define liblldb_StopInfo_h_
+
+// C Includes
+// C++ Includes
+#include <string>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-public.h"
+#include "lldb/Target/Process.h"
+
+namespace lldb_private {
+
+class StopInfo
+{
+ friend class Process::ProcessEventData;
+ friend class ThreadPlanBase;
+
+public:
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ StopInfo (Thread &thread, uint64_t value);
+
+ virtual ~StopInfo()
+ {
+ }
+
+
+ bool
+ IsValid () const;
+
+ void
+ SetThread (const lldb::ThreadSP &thread_sp)
+ {
+ m_thread_wp = thread_sp;
+ }
+
+ lldb::ThreadSP
+ GetThread() const
+ {
+ return m_thread_wp.lock();
+ }
+
+ // The value of the StopInfo depends on the StopReason.
+ // StopReason Meaning
+ // ----------------------------------------------
+ // eStopReasonBreakpoint BreakpointSiteID
+ // eStopReasonSignal Signal number
+ // eStopReasonWatchpoint WatchpointLocationID
+ // eStopReasonPlanComplete No significance
+
+ uint64_t
+ GetValue() const
+ {
+ return m_value;
+ }
+
+ virtual lldb::StopReason
+ GetStopReason () const = 0;
+
+ // ShouldStopSynchronous will get called before any thread plans are consulted, and if it says we should
+ // resume the target, then we will just immediately resume. This should not run any code in or resume the
+ // target.
+
+ virtual bool
+ ShouldStopSynchronous (Event *event_ptr)
+ {
+ return true;
+ }
+
+ void
+ OverrideShouldNotify (bool override_value)
+ {
+ m_override_should_notify = override_value ? eLazyBoolYes : eLazyBoolNo;
+ }
+
+ // If should stop returns false, check if we should notify of this event
+ virtual bool
+ ShouldNotify (Event *event_ptr)
+ {
+ if (m_override_should_notify == eLazyBoolCalculate)
+ return DoShouldNotify (event_ptr);
+ else
+ return m_override_should_notify == eLazyBoolYes;
+ }
+
+ virtual void
+ WillResume (lldb::StateType resume_state)
+ {
+ // By default, don't do anything
+ }
+
+ virtual const char *
+ GetDescription ()
+ {
+ return m_description.c_str();
+ }
+
+ virtual void
+ SetDescription (const char *desc_cstr)
+ {
+ if (desc_cstr && desc_cstr[0])
+ m_description.assign (desc_cstr);
+ else
+ m_description.clear();
+ }
+
+ // Sometimes the thread plan logic will know that it wants a given stop to stop or not,
+ // regardless of what the ordinary logic for that StopInfo would dictate. The main example
+ // of this is the ThreadPlanCallFunction, which for instance knows - based on how that particular
+ // expression was executed - whether it wants all breakpoints to auto-continue or not.
+ // Use OverrideShouldStop on the StopInfo to implement this.
+
+ void
+ OverrideShouldStop (bool override_value)
+ {
+ m_override_should_stop = override_value ? eLazyBoolYes : eLazyBoolNo;
+ }
+
+ bool
+ GetOverrideShouldStop()
+ {
+ return m_override_should_stop != eLazyBoolCalculate;
+ }
+
+ bool
+ GetOverriddenShouldStopValue ()
+ {
+ return m_override_should_stop == eLazyBoolYes;
+ }
+
+ static lldb::StopInfoSP
+ CreateStopReasonWithBreakpointSiteID (Thread &thread, lldb::break_id_t break_id);
+
+ // This creates a StopInfo for the thread where the should_stop is already set, and won't be recalculated.
+ static lldb::StopInfoSP
+ CreateStopReasonWithBreakpointSiteID (Thread &thread, lldb::break_id_t break_id, bool should_stop);
+
+ static lldb::StopInfoSP
+ CreateStopReasonWithWatchpointID (Thread &thread, lldb::break_id_t watch_id);
+
+ static lldb::StopInfoSP
+ CreateStopReasonWithSignal (Thread &thread, int signo);
+
+ static lldb::StopInfoSP
+ CreateStopReasonToTrace (Thread &thread);
+
+ static lldb::StopInfoSP
+ CreateStopReasonWithPlan (lldb::ThreadPlanSP &plan, lldb::ValueObjectSP return_valobj_sp);
+
+ static lldb::StopInfoSP
+ CreateStopReasonWithException (Thread &thread, const char *description);
+
+ static lldb::StopInfoSP
+ CreateStopReasonWithExec (Thread &thread);
+
+ static lldb::ValueObjectSP
+ GetReturnValueObject (lldb::StopInfoSP &stop_info_sp);
+
+protected:
+ // Perform any action that is associated with this stop. This is done as the
+ // Event is removed from the event queue. ProcessEventData::DoOnRemoval does the job.
+
+ virtual void
+ PerformAction (Event *event_ptr)
+ {
+ }
+
+ virtual bool
+ DoShouldNotify (Event *event_ptr)
+ {
+ return false;
+ }
+
+ // Stop the thread by default. Subclasses can override this to allow
+ // the thread to continue if desired. The ShouldStop method should not do anything
+ // that might run code. If you need to run code when deciding whether to stop
+ // at this StopInfo, that must be done in the PerformAction.
+ // The PerformAction will always get called before the ShouldStop. This is done by the
+ // ProcessEventData::DoOnRemoval, though the ThreadPlanBase needs to consult this later on.
+ virtual bool
+ ShouldStop (Event *event_ptr)
+ {
+ return true;
+ }
+
+ //------------------------------------------------------------------
+ // Classes that inherit from StackID can see and modify these
+ //------------------------------------------------------------------
+ lldb::ThreadWP m_thread_wp; // The thread corresponding to the stop reason.
+ uint32_t m_stop_id; // The process stop ID for which this stop info is valid
+ uint32_t m_resume_id; // This is the resume ID when we made this stop ID.
+ uint64_t m_value; // A generic value that can be used for things pertaining to this stop info
+ std::string m_description; // A textual description describing this stop.
+ LazyBool m_override_should_notify;
+ LazyBool m_override_should_stop;
+
+ // This determines whether the target has run since this stop info.
+ // N.B. running to evaluate a user expression does not count.
+ bool HasTargetRunSinceMe ();
+
+ // MakeStopInfoValid is necessary to allow saved stop infos to resurrect themselves as valid.
+ // It should only be used by Thread::RestoreThreadStateFromCheckpoint and to make sure the one-step
+ // needed for before-the-fact watchpoints does not prevent us from stopping
+ void
+ MakeStopInfoValid ();
+
+private:
+ friend class Thread;
+
+ DISALLOW_COPY_AND_ASSIGN (StopInfo);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_StopInfo_h_
diff --git a/include/lldb/Target/Target.h b/include/lldb/Target/Target.h
new file mode 100644
index 000000000000..87fa57b3a299
--- /dev/null
+++ b/include/lldb/Target/Target.h
@@ -0,0 +1,1223 @@
+//===-- Target.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_Target_h_
+#define liblldb_Target_h_
+
+// C Includes
+// C++ Includes
+#include <list>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-public.h"
+#include "lldb/Breakpoint/BreakpointList.h"
+#include "lldb/Breakpoint/BreakpointLocationCollection.h"
+#include "lldb/Breakpoint/WatchpointList.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Broadcaster.h"
+#include "lldb/Core/Disassembler.h"
+#include "lldb/Core/Event.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/UserSettingsController.h"
+#include "lldb/Expression/ClangPersistentVariables.h"
+#include "lldb/Interpreter/Args.h"
+#include "lldb/Interpreter/OptionValueBoolean.h"
+#include "lldb/Interpreter/OptionValueEnumeration.h"
+#include "lldb/Interpreter/OptionValueFileSpec.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Target/ABI.h"
+#include "lldb/Target/ExecutionContextScope.h"
+#include "lldb/Target/PathMappingList.h"
+#include "lldb/Target/SectionLoadList.h"
+
+namespace lldb_private {
+
+extern OptionEnumValueElement g_dynamic_value_types[];
+
+typedef enum InlineStrategy
+{
+ eInlineBreakpointsNever = 0,
+ eInlineBreakpointsHeaders,
+ eInlineBreakpointsAlways
+} InlineStrategy;
+
+typedef enum LoadScriptFromSymFile
+{
+ eLoadScriptFromSymFileTrue,
+ eLoadScriptFromSymFileFalse,
+ eLoadScriptFromSymFileWarn
+} LoadScriptFromSymFile;
+
+//----------------------------------------------------------------------
+// TargetProperties
+//----------------------------------------------------------------------
+class TargetProperties : public Properties
+{
+public:
+ TargetProperties(Target *target);
+
+ virtual
+ ~TargetProperties();
+
+ ArchSpec
+ GetDefaultArchitecture () const;
+
+ void
+ SetDefaultArchitecture (const ArchSpec& arch);
+
+ lldb::DynamicValueType
+ GetPreferDynamicValue() const;
+
+ bool
+ GetDisableASLR () const;
+
+ void
+ SetDisableASLR (bool b);
+
+ bool
+ GetDisableSTDIO () const;
+
+ void
+ SetDisableSTDIO (bool b);
+
+ const char *
+ GetDisassemblyFlavor() const;
+
+// void
+// SetDisassemblyFlavor(const char *flavor);
+
+ InlineStrategy
+ GetInlineStrategy () const;
+
+ const char *
+ GetArg0 () const;
+
+ void
+ SetArg0 (const char *arg);
+
+ bool
+ GetRunArguments (Args &args) const;
+
+ void
+ SetRunArguments (const Args &args);
+
+ size_t
+ GetEnvironmentAsArgs (Args &env) const;
+
+ bool
+ GetSkipPrologue() const;
+
+ PathMappingList &
+ GetSourcePathMap () const;
+
+ FileSpecList &
+ GetExecutableSearchPaths ();
+
+ FileSpecList &
+ GetDebugFileSearchPaths ();
+
+ bool
+ GetEnableSyntheticValue () const;
+
+ uint32_t
+ GetMaximumNumberOfChildrenToDisplay() const;
+
+ uint32_t
+ GetMaximumSizeOfStringSummary() const;
+
+ uint32_t
+ GetMaximumMemReadSize () const;
+
+ FileSpec
+ GetStandardInputPath () const;
+
+ void
+ SetStandardInputPath (const char *path);
+
+ FileSpec
+ GetStandardOutputPath () const;
+
+ void
+ SetStandardOutputPath (const char *path);
+
+ FileSpec
+ GetStandardErrorPath () const;
+
+ void
+ SetStandardErrorPath (const char *path);
+
+ bool
+ GetBreakpointsConsultPlatformAvoidList ();
+
+ const char *
+ GetExpressionPrefixContentsAsCString ();
+
+ bool
+ GetUseHexImmediates() const;
+
+ bool
+ GetUseFastStepping() const;
+
+ LoadScriptFromSymFile
+ GetLoadScriptFromSymbolFile() const;
+
+ Disassembler::HexImmediateStyle
+ GetHexImmediateStyle() const;
+
+ MemoryModuleLoadLevel
+ GetMemoryModuleLoadLevel() const;
+
+};
+
+typedef std::shared_ptr<TargetProperties> TargetPropertiesSP;
+
+class EvaluateExpressionOptions
+{
+public:
+ static const uint32_t default_timeout = 500000;
+ EvaluateExpressionOptions() :
+ m_execution_policy(eExecutionPolicyOnlyWhenNeeded),
+ m_coerce_to_id(false),
+ m_unwind_on_error(true),
+ m_ignore_breakpoints (false),
+ m_keep_in_memory(false),
+ m_run_others(true),
+ m_use_dynamic(lldb::eNoDynamicValues),
+ m_timeout_usec(default_timeout)
+ {}
+
+ ExecutionPolicy
+ GetExecutionPolicy () const
+ {
+ return m_execution_policy;
+ }
+
+ EvaluateExpressionOptions&
+ SetExecutionPolicy (ExecutionPolicy policy = eExecutionPolicyAlways)
+ {
+ m_execution_policy = policy;
+ return *this;
+ }
+
+ bool
+ DoesCoerceToId () const
+ {
+ return m_coerce_to_id;
+ }
+
+ EvaluateExpressionOptions&
+ SetCoerceToId (bool coerce = true)
+ {
+ m_coerce_to_id = coerce;
+ return *this;
+ }
+
+ bool
+ DoesUnwindOnError () const
+ {
+ return m_unwind_on_error;
+ }
+
+ EvaluateExpressionOptions&
+ SetUnwindOnError (bool unwind = false)
+ {
+ m_unwind_on_error = unwind;
+ return *this;
+ }
+
+ bool
+ DoesIgnoreBreakpoints () const
+ {
+ return m_ignore_breakpoints;
+ }
+
+ EvaluateExpressionOptions&
+ SetIgnoreBreakpoints (bool ignore = false)
+ {
+ m_ignore_breakpoints = ignore;
+ return *this;
+ }
+
+ bool
+ DoesKeepInMemory () const
+ {
+ return m_keep_in_memory;
+ }
+
+ EvaluateExpressionOptions&
+ SetKeepInMemory (bool keep = true)
+ {
+ m_keep_in_memory = keep;
+ return *this;
+ }
+
+ lldb::DynamicValueType
+ GetUseDynamic () const
+ {
+ return m_use_dynamic;
+ }
+
+ EvaluateExpressionOptions&
+ SetUseDynamic (lldb::DynamicValueType dynamic = lldb::eDynamicCanRunTarget)
+ {
+ m_use_dynamic = dynamic;
+ return *this;
+ }
+
+ uint32_t
+ GetTimeoutUsec () const
+ {
+ return m_timeout_usec;
+ }
+
+ EvaluateExpressionOptions&
+ SetTimeoutUsec (uint32_t timeout = 0)
+ {
+ m_timeout_usec = timeout;
+ return *this;
+ }
+
+ bool
+ GetRunOthers () const
+ {
+ return m_run_others;
+ }
+
+ EvaluateExpressionOptions&
+ SetRunOthers (bool run_others = true)
+ {
+ m_run_others = run_others;
+ return *this;
+ }
+
+private:
+ ExecutionPolicy m_execution_policy;
+ bool m_coerce_to_id;
+ bool m_unwind_on_error;
+ bool m_ignore_breakpoints;
+ bool m_keep_in_memory;
+ bool m_run_others;
+ lldb::DynamicValueType m_use_dynamic;
+ uint32_t m_timeout_usec;
+};
+
+//----------------------------------------------------------------------
+// Target
+//----------------------------------------------------------------------
+class Target :
+ public std::enable_shared_from_this<Target>,
+ public TargetProperties,
+ public Broadcaster,
+ public ExecutionContextScope,
+ public ModuleList::Notifier
+{
+public:
+ friend class TargetList;
+
+ //------------------------------------------------------------------
+ /// Broadcaster event bits definitions.
+ //------------------------------------------------------------------
+ enum
+ {
+ eBroadcastBitBreakpointChanged = (1 << 0),
+ eBroadcastBitModulesLoaded = (1 << 1),
+ eBroadcastBitModulesUnloaded = (1 << 2),
+ eBroadcastBitWatchpointChanged = (1 << 3),
+ eBroadcastBitSymbolsLoaded = (1 << 4)
+ };
+
+ // These two functions fill out the Broadcaster interface:
+
+ static ConstString &GetStaticBroadcasterClass ();
+
+ virtual ConstString &GetBroadcasterClass() const
+ {
+ return GetStaticBroadcasterClass();
+ }
+
+ // This event data class is for use by the TargetList to broadcast new target notifications.
+ class TargetEventData : public EventData
+ {
+ public:
+
+ static const ConstString &
+ GetFlavorString ();
+
+ virtual const ConstString &
+ GetFlavor () const;
+
+ TargetEventData (const lldb::TargetSP &new_target_sp);
+
+ lldb::TargetSP &
+ GetTarget()
+ {
+ return m_target_sp;
+ }
+
+ virtual
+ ~TargetEventData();
+
+ virtual void
+ Dump (Stream *s) const;
+
+ static const lldb::TargetSP
+ GetTargetFromEvent (const lldb::EventSP &event_sp);
+
+ static const TargetEventData *
+ GetEventDataFromEvent (const Event *event_sp);
+
+ private:
+ lldb::TargetSP m_target_sp;
+
+ DISALLOW_COPY_AND_ASSIGN (TargetEventData);
+ };
+
+ static void
+ SettingsInitialize ();
+
+ static void
+ SettingsTerminate ();
+
+// static lldb::UserSettingsControllerSP &
+// GetSettingsController ();
+
+ static FileSpecList
+ GetDefaultExecutableSearchPaths ();
+
+ static FileSpecList
+ GetDefaultDebugFileSearchPaths ();
+
+ static ArchSpec
+ GetDefaultArchitecture ();
+
+ static void
+ SetDefaultArchitecture (const ArchSpec &arch);
+
+// void
+// UpdateInstanceName ();
+
+ lldb::ModuleSP
+ GetSharedModule (const ModuleSpec &module_spec,
+ Error *error_ptr = NULL);
+
+ //----------------------------------------------------------------------
+ // Settings accessors
+ //----------------------------------------------------------------------
+
+ static const TargetPropertiesSP &
+ GetGlobalProperties();
+
+
+private:
+ //------------------------------------------------------------------
+ /// Construct with optional file and arch.
+ ///
+ /// This member is private. Clients must use
+ /// TargetList::CreateTarget(const FileSpec*, const ArchSpec*)
+ /// so all targets can be tracked from the central target list.
+ ///
+ /// @see TargetList::CreateTarget(const FileSpec*, const ArchSpec*)
+ //------------------------------------------------------------------
+ Target (Debugger &debugger,
+ const ArchSpec &target_arch,
+ const lldb::PlatformSP &platform_sp);
+
+ // Helper function.
+ bool
+ ProcessIsValid ();
+
+public:
+ ~Target();
+
+ Mutex &
+ GetAPIMutex ()
+ {
+ return m_mutex;
+ }
+
+ void
+ DeleteCurrentProcess ();
+
+ void
+ CleanupProcess ();
+ //------------------------------------------------------------------
+ /// Dump a description of this object to a Stream.
+ ///
+ /// Dump a description of the contents of this object to the
+ /// supplied stream \a s. The dumped content will be only what has
+ /// been loaded or parsed up to this point at which this function
+ /// is called, so this is a good way to see what has been parsed
+ /// in a target.
+ ///
+ /// @param[in] s
+ /// The stream to which to dump the object descripton.
+ //------------------------------------------------------------------
+ void
+ Dump (Stream *s, lldb::DescriptionLevel description_level);
+
+ const lldb::ProcessSP &
+ CreateProcess (Listener &listener,
+ const char *plugin_name,
+ const FileSpec *crash_file);
+
+ const lldb::ProcessSP &
+ GetProcessSP () const;
+
+ bool
+ IsValid()
+ {
+ return m_valid;
+ }
+
+ void
+ Destroy();
+
+ //------------------------------------------------------------------
+ // This part handles the breakpoints.
+ //------------------------------------------------------------------
+
+ BreakpointList &
+ GetBreakpointList(bool internal = false);
+
+ const BreakpointList &
+ GetBreakpointList(bool internal = false) const;
+
+ lldb::BreakpointSP
+ GetLastCreatedBreakpoint ()
+ {
+ return m_last_created_breakpoint;
+ }
+
+ lldb::BreakpointSP
+ GetBreakpointByID (lldb::break_id_t break_id);
+
+ // Use this to create a file and line breakpoint to a given module or all module it is NULL
+ lldb::BreakpointSP
+ CreateBreakpoint (const FileSpecList *containingModules,
+ const FileSpec &file,
+ uint32_t line_no,
+ LazyBool check_inlines = eLazyBoolCalculate,
+ LazyBool skip_prologue = eLazyBoolCalculate,
+ bool internal = false);
+
+ // Use this to create breakpoint that matches regex against the source lines in files given in source_file_list:
+ lldb::BreakpointSP
+ CreateSourceRegexBreakpoint (const FileSpecList *containingModules,
+ const FileSpecList *source_file_list,
+ RegularExpression &source_regex,
+ bool internal = false);
+
+ // Use this to create a breakpoint from a load address
+ lldb::BreakpointSP
+ CreateBreakpoint (lldb::addr_t load_addr,
+ bool internal = false);
+
+ // Use this to create Address breakpoints:
+ lldb::BreakpointSP
+ CreateBreakpoint (Address &addr,
+ bool internal = false);
+
+ // Use this to create a function breakpoint by regexp in containingModule/containingSourceFiles, or all modules if it is NULL
+ // When "skip_prologue is set to eLazyBoolCalculate, we use the current target
+ // setting, else we use the values passed in
+ lldb::BreakpointSP
+ CreateFuncRegexBreakpoint (const FileSpecList *containingModules,
+ const FileSpecList *containingSourceFiles,
+ RegularExpression &func_regexp,
+ LazyBool skip_prologue = eLazyBoolCalculate,
+ bool internal = false);
+
+ // Use this to create a function breakpoint by name in containingModule, or all modules if it is NULL
+ // When "skip_prologue is set to eLazyBoolCalculate, we use the current target
+ // setting, else we use the values passed in
+ lldb::BreakpointSP
+ CreateBreakpoint (const FileSpecList *containingModules,
+ const FileSpecList *containingSourceFiles,
+ const char *func_name,
+ uint32_t func_name_type_mask,
+ LazyBool skip_prologue = eLazyBoolCalculate,
+ bool internal = false);
+
+ lldb::BreakpointSP
+ CreateExceptionBreakpoint (enum lldb::LanguageType language, bool catch_bp, bool throw_bp, bool internal = false);
+
+ // This is the same as the func_name breakpoint except that you can specify a vector of names. This is cheaper
+ // than a regular expression breakpoint in the case where you just want to set a breakpoint on a set of names
+ // you already know.
+ lldb::BreakpointSP
+ CreateBreakpoint (const FileSpecList *containingModules,
+ const FileSpecList *containingSourceFiles,
+ const char *func_names[],
+ size_t num_names,
+ uint32_t func_name_type_mask,
+ LazyBool skip_prologue = eLazyBoolCalculate,
+ bool internal = false);
+
+ lldb::BreakpointSP
+ CreateBreakpoint (const FileSpecList *containingModules,
+ const FileSpecList *containingSourceFiles,
+ const std::vector<std::string> &func_names,
+ uint32_t func_name_type_mask,
+ LazyBool skip_prologue = eLazyBoolCalculate,
+ bool internal = false);
+
+
+ // Use this to create a general breakpoint:
+ lldb::BreakpointSP
+ CreateBreakpoint (lldb::SearchFilterSP &filter_sp,
+ lldb::BreakpointResolverSP &resolver_sp,
+ bool internal = false);
+
+ // Use this to create a watchpoint:
+ lldb::WatchpointSP
+ CreateWatchpoint (lldb::addr_t addr,
+ size_t size,
+ const ClangASTType *type,
+ uint32_t kind,
+ Error &error);
+
+ lldb::WatchpointSP
+ GetLastCreatedWatchpoint ()
+ {
+ return m_last_created_watchpoint;
+ }
+
+ WatchpointList &
+ GetWatchpointList()
+ {
+ return m_watchpoint_list;
+ }
+
+ void
+ RemoveAllBreakpoints (bool internal_also = false);
+
+ void
+ DisableAllBreakpoints (bool internal_also = false);
+
+ void
+ EnableAllBreakpoints (bool internal_also = false);
+
+ bool
+ DisableBreakpointByID (lldb::break_id_t break_id);
+
+ bool
+ EnableBreakpointByID (lldb::break_id_t break_id);
+
+ bool
+ RemoveBreakpointByID (lldb::break_id_t break_id);
+
+ // The flag 'end_to_end', default to true, signifies that the operation is
+ // performed end to end, for both the debugger and the debuggee.
+
+ bool
+ RemoveAllWatchpoints (bool end_to_end = true);
+
+ bool
+ DisableAllWatchpoints (bool end_to_end = true);
+
+ bool
+ EnableAllWatchpoints (bool end_to_end = true);
+
+ bool
+ ClearAllWatchpointHitCounts ();
+
+ bool
+ IgnoreAllWatchpoints (uint32_t ignore_count);
+
+ bool
+ DisableWatchpointByID (lldb::watch_id_t watch_id);
+
+ bool
+ EnableWatchpointByID (lldb::watch_id_t watch_id);
+
+ bool
+ RemoveWatchpointByID (lldb::watch_id_t watch_id);
+
+ bool
+ IgnoreWatchpointByID (lldb::watch_id_t watch_id, uint32_t ignore_count);
+
+ //------------------------------------------------------------------
+ /// Get \a load_addr as a callable code load address for this target
+ ///
+ /// Take \a load_addr and potentially add any address bits that are
+ /// needed to make the address callable. For ARM this can set bit
+ /// zero (if it already isn't) if \a load_addr is a thumb function.
+ /// If \a addr_class is set to eAddressClassInvalid, then the address
+ /// adjustment will always happen. If it is set to an address class
+ /// that doesn't have code in it, LLDB_INVALID_ADDRESS will be
+ /// returned.
+ //------------------------------------------------------------------
+ lldb::addr_t
+ GetCallableLoadAddress (lldb::addr_t load_addr, lldb::AddressClass addr_class = lldb::eAddressClassInvalid) const;
+
+ //------------------------------------------------------------------
+ /// Get \a load_addr as an opcode for this target.
+ ///
+ /// Take \a load_addr and potentially strip any address bits that are
+ /// needed to make the address point to an opcode. For ARM this can
+ /// clear bit zero (if it already isn't) if \a load_addr is a
+ /// thumb function and load_addr is in code.
+ /// If \a addr_class is set to eAddressClassInvalid, then the address
+ /// adjustment will always happen. If it is set to an address class
+ /// that doesn't have code in it, LLDB_INVALID_ADDRESS will be
+ /// returned.
+ //------------------------------------------------------------------
+ lldb::addr_t
+ GetOpcodeLoadAddress (lldb::addr_t load_addr, lldb::AddressClass addr_class = lldb::eAddressClassInvalid) const;
+
+protected:
+ //------------------------------------------------------------------
+ /// Implementing of ModuleList::Notifier.
+ //------------------------------------------------------------------
+
+ virtual void
+ ModuleAdded (const ModuleList& module_list, const lldb::ModuleSP& module_sp);
+
+ virtual void
+ ModuleRemoved (const ModuleList& module_list, const lldb::ModuleSP& module_sp);
+
+ virtual void
+ ModuleUpdated (const ModuleList& module_list,
+ const lldb::ModuleSP& old_module_sp,
+ const lldb::ModuleSP& new_module_sp);
+ virtual void
+ WillClearList (const ModuleList& module_list);
+
+public:
+
+ void
+ ModulesDidLoad (ModuleList &module_list);
+
+ void
+ ModulesDidUnload (ModuleList &module_list);
+
+ void
+ SymbolsDidLoad (ModuleList &module_list);
+
+ //------------------------------------------------------------------
+ /// Gets the module for the main executable.
+ ///
+ /// Each process has a notion of a main executable that is the file
+ /// that will be executed or attached to. Executable files can have
+ /// dependent modules that are discovered from the object files, or
+ /// discovered at runtime as things are dynamically loaded.
+ ///
+ /// @return
+ /// The shared pointer to the executable module which can
+ /// contains a NULL Module object if no executable has been
+ /// set.
+ ///
+ /// @see DynamicLoader
+ /// @see ObjectFile::GetDependentModules (FileSpecList&)
+ /// @see Process::SetExecutableModule(lldb::ModuleSP&)
+ //------------------------------------------------------------------
+ lldb::ModuleSP
+ GetExecutableModule ();
+
+ Module*
+ GetExecutableModulePointer ();
+
+ //------------------------------------------------------------------
+ /// Set the main executable module.
+ ///
+ /// Each process has a notion of a main executable that is the file
+ /// that will be executed or attached to. Executable files can have
+ /// dependent modules that are discovered from the object files, or
+ /// discovered at runtime as things are dynamically loaded.
+ ///
+ /// Setting the executable causes any of the current dependant
+ /// image information to be cleared and replaced with the static
+ /// dependent image information found by calling
+ /// ObjectFile::GetDependentModules (FileSpecList&) on the main
+ /// executable and any modules on which it depends. Calling
+ /// Process::GetImages() will return the newly found images that
+ /// were obtained from all of the object files.
+ ///
+ /// @param[in] module_sp
+ /// A shared pointer reference to the module that will become
+ /// the main executable for this process.
+ ///
+ /// @param[in] get_dependent_files
+ /// If \b true then ask the object files to track down any
+ /// known dependent files.
+ ///
+ /// @see ObjectFile::GetDependentModules (FileSpecList&)
+ /// @see Process::GetImages()
+ //------------------------------------------------------------------
+ void
+ SetExecutableModule (lldb::ModuleSP& module_sp, bool get_dependent_files);
+
+ bool
+ LoadScriptingResources (std::list<Error>& errors,
+ Stream* feedback_stream = NULL,
+ bool continue_on_error = true)
+ {
+ return m_images.LoadScriptingResourcesInTarget(this,errors,feedback_stream,continue_on_error);
+ }
+
+ //------------------------------------------------------------------
+ /// Get accessor for the images for this process.
+ ///
+ /// Each process has a notion of a main executable that is the file
+ /// that will be executed or attached to. Executable files can have
+ /// dependent modules that are discovered from the object files, or
+ /// discovered at runtime as things are dynamically loaded. After
+ /// a main executable has been set, the images will contain a list
+ /// of all the files that the executable depends upon as far as the
+ /// object files know. These images will usually contain valid file
+ /// virtual addresses only. When the process is launched or attached
+ /// to, the DynamicLoader plug-in will discover where these images
+ /// were loaded in memory and will resolve the load virtual
+ /// addresses is each image, and also in images that are loaded by
+ /// code.
+ ///
+ /// @return
+ /// A list of Module objects in a module list.
+ //------------------------------------------------------------------
+ const ModuleList&
+ GetImages () const
+ {
+ return m_images;
+ }
+
+ ModuleList&
+ GetImages ()
+ {
+ return m_images;
+ }
+
+ //------------------------------------------------------------------
+ /// Return whether this FileSpec corresponds to a module that should be considered for general searches.
+ ///
+ /// This API will be consulted by the SearchFilterForNonModuleSpecificSearches
+ /// and any module that returns \b true will not be searched. Note the
+ /// SearchFilterForNonModuleSpecificSearches is the search filter that
+ /// gets used in the CreateBreakpoint calls when no modules is provided.
+ ///
+ /// The target call at present just consults the Platform's call of the
+ /// same name.
+ ///
+ /// @param[in] module_sp
+ /// A shared pointer reference to the module that checked.
+ ///
+ /// @return \b true if the module should be excluded, \b false otherwise.
+ //------------------------------------------------------------------
+ bool
+ ModuleIsExcludedForNonModuleSpecificSearches (const FileSpec &module_spec);
+
+ //------------------------------------------------------------------
+ /// Return whether this module should be considered for general searches.
+ ///
+ /// This API will be consulted by the SearchFilterForNonModuleSpecificSearches
+ /// and any module that returns \b true will not be searched. Note the
+ /// SearchFilterForNonModuleSpecificSearches is the search filter that
+ /// gets used in the CreateBreakpoint calls when no modules is provided.
+ ///
+ /// The target call at present just consults the Platform's call of the
+ /// same name.
+ ///
+ /// FIXME: When we get time we should add a way for the user to set modules that they
+ /// don't want searched, in addition to or instead of the platform ones.
+ ///
+ /// @param[in] module_sp
+ /// A shared pointer reference to the module that checked.
+ ///
+ /// @return \b true if the module should be excluded, \b false otherwise.
+ //------------------------------------------------------------------
+ bool
+ ModuleIsExcludedForNonModuleSpecificSearches (const lldb::ModuleSP &module_sp);
+
+ ArchSpec &
+ GetArchitecture ()
+ {
+ return m_arch;
+ }
+
+ const ArchSpec &
+ GetArchitecture () const
+ {
+ return m_arch;
+ }
+
+ //------------------------------------------------------------------
+ /// Set the architecture for this target.
+ ///
+ /// If the current target has no Images read in, then this just sets the architecture, which will
+ /// be used to select the architecture of the ExecutableModule when that is set.
+ /// If the current target has an ExecutableModule, then calling SetArchitecture with a different
+ /// architecture from the currently selected one will reset the ExecutableModule to that slice
+ /// of the file backing the ExecutableModule. If the file backing the ExecutableModule does not
+ /// contain a fork of this architecture, then this code will return false, and the architecture
+ /// won't be changed.
+ /// If the input arch_spec is the same as the already set architecture, this is a no-op.
+ ///
+ /// @param[in] arch_spec
+ /// The new architecture.
+ ///
+ /// @return
+ /// \b true if the architecture was successfully set, \bfalse otherwise.
+ //------------------------------------------------------------------
+ bool
+ SetArchitecture (const ArchSpec &arch_spec);
+
+ Debugger &
+ GetDebugger ()
+ {
+ return m_debugger;
+ }
+
+ size_t
+ ReadMemoryFromFileCache (const Address& addr,
+ void *dst,
+ size_t dst_len,
+ Error &error);
+
+ // Reading memory through the target allows us to skip going to the process
+ // for reading memory if possible and it allows us to try and read from
+ // any constant sections in our object files on disk. If you always want
+ // live program memory, read straight from the process. If you possibly
+ // want to read from const sections in object files, read from the target.
+ // This version of ReadMemory will try and read memory from the process
+ // if the process is alive. The order is:
+ // 1 - if (prefer_file_cache == true) then read from object file cache
+ // 2 - if there is a valid process, try and read from its memory
+ // 3 - if (prefer_file_cache == false) then read from object file cache
+ size_t
+ ReadMemory (const Address& addr,
+ bool prefer_file_cache,
+ void *dst,
+ size_t dst_len,
+ Error &error,
+ lldb::addr_t *load_addr_ptr = NULL);
+
+ size_t
+ ReadCStringFromMemory (const Address& addr, std::string &out_str, Error &error);
+
+ size_t
+ ReadCStringFromMemory (const Address& addr, char *dst, size_t dst_max_len, Error &result_error);
+
+ size_t
+ ReadScalarIntegerFromMemory (const Address& addr,
+ bool prefer_file_cache,
+ uint32_t byte_size,
+ bool is_signed,
+ Scalar &scalar,
+ Error &error);
+
+ uint64_t
+ ReadUnsignedIntegerFromMemory (const Address& addr,
+ bool prefer_file_cache,
+ size_t integer_byte_size,
+ uint64_t fail_value,
+ Error &error);
+
+ bool
+ ReadPointerFromMemory (const Address& addr,
+ bool prefer_file_cache,
+ Error &error,
+ Address &pointer_addr);
+
+ SectionLoadList&
+ GetSectionLoadList()
+ {
+ return m_section_load_list;
+ }
+
+ const SectionLoadList&
+ GetSectionLoadList() const
+ {
+ return m_section_load_list;
+ }
+
+ static Target *
+ GetTargetFromContexts (const ExecutionContext *exe_ctx_ptr,
+ const SymbolContext *sc_ptr);
+
+ //------------------------------------------------------------------
+ // lldb::ExecutionContextScope pure virtual functions
+ //------------------------------------------------------------------
+ virtual lldb::TargetSP
+ CalculateTarget ();
+
+ virtual lldb::ProcessSP
+ CalculateProcess ();
+
+ virtual lldb::ThreadSP
+ CalculateThread ();
+
+ virtual lldb::StackFrameSP
+ CalculateStackFrame ();
+
+ virtual void
+ CalculateExecutionContext (ExecutionContext &exe_ctx);
+
+ PathMappingList &
+ GetImageSearchPathList ();
+
+ ClangASTContext *
+ GetScratchClangASTContext(bool create_on_demand=true);
+
+ ClangASTImporter *
+ GetClangASTImporter();
+
+
+ // Since expressions results can persist beyond the lifetime of a process,
+ // and the const expression results are available after a process is gone,
+ // we provide a way for expressions to be evaluated from the Target itself.
+ // If an expression is going to be run, then it should have a frame filled
+ // in in th execution context.
+ ExecutionResults
+ EvaluateExpression (const char *expression,
+ StackFrame *frame,
+ lldb::ValueObjectSP &result_valobj_sp,
+ const EvaluateExpressionOptions& options = EvaluateExpressionOptions());
+
+ ClangPersistentVariables &
+ GetPersistentVariables()
+ {
+ return m_persistent_variables;
+ }
+
+ //------------------------------------------------------------------
+ // Target Stop Hooks
+ //------------------------------------------------------------------
+ class StopHook : public UserID
+ {
+ public:
+ ~StopHook ();
+
+ StopHook (const StopHook &rhs);
+
+ StringList *
+ GetCommandPointer ()
+ {
+ return &m_commands;
+ }
+
+ const StringList &
+ GetCommands()
+ {
+ return m_commands;
+ }
+
+ lldb::TargetSP &
+ GetTarget()
+ {
+ return m_target_sp;
+ }
+
+ void
+ SetCommands (StringList &in_commands)
+ {
+ m_commands = in_commands;
+ }
+
+ // Set the specifier. The stop hook will own the specifier, and is responsible for deleting it when we're done.
+ void
+ SetSpecifier (SymbolContextSpecifier *specifier)
+ {
+ m_specifier_sp.reset (specifier);
+ }
+
+ SymbolContextSpecifier *
+ GetSpecifier ()
+ {
+ return m_specifier_sp.get();
+ }
+
+ // Set the Thread Specifier. The stop hook will own the thread specifier, and is responsible for deleting it when we're done.
+ void
+ SetThreadSpecifier (ThreadSpec *specifier);
+
+ ThreadSpec *
+ GetThreadSpecifier()
+ {
+ return m_thread_spec_ap.get();
+ }
+
+ bool
+ IsActive()
+ {
+ return m_active;
+ }
+
+ void
+ SetIsActive (bool is_active)
+ {
+ m_active = is_active;
+ }
+
+ void
+ GetDescription (Stream *s, lldb::DescriptionLevel level) const;
+
+ private:
+ lldb::TargetSP m_target_sp;
+ StringList m_commands;
+ lldb::SymbolContextSpecifierSP m_specifier_sp;
+ std::unique_ptr<ThreadSpec> m_thread_spec_ap;
+ bool m_active;
+
+ // Use AddStopHook to make a new empty stop hook. The GetCommandPointer and fill it with commands,
+ // and SetSpecifier to set the specifier shared pointer (can be null, that will match anything.)
+ StopHook (lldb::TargetSP target_sp, lldb::user_id_t uid);
+ friend class Target;
+ };
+ typedef std::shared_ptr<StopHook> StopHookSP;
+
+ // Add an empty stop hook to the Target's stop hook list, and returns a shared pointer to it in new_hook.
+ // Returns the id of the new hook.
+ lldb::user_id_t
+ AddStopHook (StopHookSP &new_hook);
+
+ void
+ RunStopHooks ();
+
+ size_t
+ GetStopHookSize();
+
+ bool
+ SetSuppresStopHooks (bool suppress)
+ {
+ bool old_value = m_suppress_stop_hooks;
+ m_suppress_stop_hooks = suppress;
+ return old_value;
+ }
+
+ bool
+ GetSuppressStopHooks ()
+ {
+ return m_suppress_stop_hooks;
+ }
+
+ bool
+ SetSuppressSyntheticValue (bool suppress)
+ {
+ bool old_value = m_suppress_synthetic_value;
+ m_suppress_synthetic_value = suppress;
+ return old_value;
+ }
+
+ bool
+ GetSuppressSyntheticValue ()
+ {
+ return m_suppress_synthetic_value;
+ }
+
+// StopHookSP &
+// GetStopHookByIndex (size_t index);
+//
+ bool
+ RemoveStopHookByID (lldb::user_id_t uid);
+
+ void
+ RemoveAllStopHooks ();
+
+ StopHookSP
+ GetStopHookByID (lldb::user_id_t uid);
+
+ bool
+ SetStopHookActiveStateByID (lldb::user_id_t uid, bool active_state);
+
+ void
+ SetAllStopHooksActiveState (bool active_state);
+
+ size_t GetNumStopHooks () const
+ {
+ return m_stop_hooks.size();
+ }
+
+ StopHookSP
+ GetStopHookAtIndex (size_t index)
+ {
+ if (index >= GetNumStopHooks())
+ return StopHookSP();
+ StopHookCollection::iterator pos = m_stop_hooks.begin();
+
+ while (index > 0)
+ {
+ pos++;
+ index--;
+ }
+ return (*pos).second;
+ }
+
+ lldb::PlatformSP
+ GetPlatform ()
+ {
+ return m_platform_sp;
+ }
+
+ void
+ SetPlatform (const lldb::PlatformSP &platform_sp)
+ {
+ m_platform_sp = platform_sp;
+ }
+
+ SourceManager &
+ GetSourceManager ();
+
+ //------------------------------------------------------------------
+ // Methods.
+ //------------------------------------------------------------------
+ lldb::SearchFilterSP
+ GetSearchFilterForModule (const FileSpec *containingModule);
+
+ lldb::SearchFilterSP
+ GetSearchFilterForModuleList (const FileSpecList *containingModuleList);
+
+ lldb::SearchFilterSP
+ GetSearchFilterForModuleAndCUList (const FileSpecList *containingModules, const FileSpecList *containingSourceFiles);
+
+protected:
+ //------------------------------------------------------------------
+ // Member variables.
+ //------------------------------------------------------------------
+ Debugger & m_debugger;
+ lldb::PlatformSP m_platform_sp; ///< The platform for this target.
+ Mutex m_mutex; ///< An API mutex that is used by the lldb::SB* classes make the SB interface thread safe
+ ArchSpec m_arch;
+ ModuleList m_images; ///< The list of images for this process (shared libraries and anything dynamically loaded).
+ SectionLoadList m_section_load_list;
+ BreakpointList m_breakpoint_list;
+ BreakpointList m_internal_breakpoint_list;
+ lldb::BreakpointSP m_last_created_breakpoint;
+ WatchpointList m_watchpoint_list;
+ lldb::WatchpointSP m_last_created_watchpoint;
+ // We want to tightly control the process destruction process so
+ // we can correctly tear down everything that we need to, so the only
+ // class that knows about the process lifespan is this target class.
+ lldb::ProcessSP m_process_sp;
+ bool m_valid;
+ lldb::SearchFilterSP m_search_filter_sp;
+ PathMappingList m_image_search_paths;
+ std::unique_ptr<ClangASTContext> m_scratch_ast_context_ap;
+ std::unique_ptr<ClangASTSource> m_scratch_ast_source_ap;
+ std::unique_ptr<ClangASTImporter> m_ast_importer_ap;
+ ClangPersistentVariables m_persistent_variables; ///< These are the persistent variables associated with this process for the expression parser.
+
+ std::unique_ptr<SourceManager> m_source_manager_ap;
+
+ typedef std::map<lldb::user_id_t, StopHookSP> StopHookCollection;
+ StopHookCollection m_stop_hooks;
+ lldb::user_id_t m_stop_hook_next_id;
+ bool m_suppress_stop_hooks;
+ bool m_suppress_synthetic_value;
+
+ static void
+ ImageSearchPathsChanged (const PathMappingList &path_list,
+ void *baton);
+
+private:
+ DISALLOW_COPY_AND_ASSIGN (Target);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_Target_h_
diff --git a/include/lldb/Target/TargetList.h b/include/lldb/Target/TargetList.h
new file mode 100644
index 000000000000..41404e11c7fa
--- /dev/null
+++ b/include/lldb/Target/TargetList.h
@@ -0,0 +1,239 @@
+//===-- TargetList.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_TargetList_h_
+#define liblldb_TargetList_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Broadcaster.h"
+#include "lldb/Host/Mutex.h"
+#include "lldb/Target/Target.h"
+
+namespace lldb_private {
+
+class TargetList : public Broadcaster
+{
+private:
+ friend class Debugger;
+
+ //------------------------------------------------------------------
+ /// Constructor
+ ///
+ /// The constructor for the target list is private. Clients can
+ /// get ahold of of the one and only target list through the
+ /// lldb_private::Debugger::GetSharedInstance().GetTargetList().
+ ///
+ /// @see static TargetList& lldb_private::Debugger::GetTargetList().
+ //------------------------------------------------------------------
+ TargetList(Debugger &debugger);
+
+public:
+
+ //------------------------------------------------------------------
+ /// Broadcaster event bits definitions.
+ //------------------------------------------------------------------
+ enum
+ {
+ eBroadcastBitInterrupt = (1 << 0)
+ };
+
+
+ // These two functions fill out the Broadcaster interface:
+
+ static ConstString &GetStaticBroadcasterClass ();
+
+ virtual ConstString &GetBroadcasterClass() const
+ {
+ return GetStaticBroadcasterClass();
+ }
+
+ virtual ~TargetList();
+
+ //------------------------------------------------------------------
+ /// Create a new Target.
+ ///
+ /// Clients must use this function to create a Target. This allows
+ /// a global list of targets to be maintained in a central location
+ /// so signal handlers and other global functions can use it to
+ /// locate an appropriate target to deliver asynchronous information
+ /// to.
+ ///
+ /// @param[in] debugger
+ /// The debugger to associate this target with
+ ///
+ /// @param[in] file_spec
+ /// The main executable file for a debug target. This value
+ /// can be NULL and the file can be set later using:
+ /// Target::SetExecutableModule (ModuleSP&)
+ ///
+ /// @param[in] triple_cstr
+ /// A target triple string to be used for the target. This can
+ /// be NULL if the triple is not known or when attaching to a
+ /// process.
+ ///
+ /// @param[in] get_dependent_modules
+ /// Track down the dependent modules for an executable and
+ /// load those into the module list.
+ ///
+ /// @param[in] platform_options
+ /// A pointer to the platform options to use when creating this
+ /// target. If this value is NULL, then the currently selected
+ /// platform will be used.
+ ///
+ /// @param[out] target_sp
+ /// A shared pointer to a target that will be filled in if
+ /// this call is successful.
+ ///
+ /// @return
+ /// An error object that indicates success or failure
+ //------------------------------------------------------------------
+ Error
+ CreateTarget (Debugger &debugger,
+ const char *user_exe_path,
+ const char *triple_cstr,
+ bool get_dependent_modules,
+ const OptionGroupPlatform *platform_options,
+ lldb::TargetSP &target_sp);
+
+ //------------------------------------------------------------------
+ /// Create a new Target.
+ ///
+ /// Same as the function above, but used when you already know the
+ /// platform you will be using
+ //------------------------------------------------------------------
+ Error
+ CreateTarget (Debugger &debugger,
+ const char *user_exe_path,
+ const ArchSpec& arch,
+ bool get_dependent_modules,
+ lldb::PlatformSP &platform_sp,
+ lldb::TargetSP &target_sp);
+
+ //------------------------------------------------------------------
+ /// Delete a Target object from the list.
+ ///
+ /// When clients are done with the Target objets, this function
+ /// should be called to release the memory associated with a target
+ /// object.
+ ///
+ /// @param[in] target_sp
+ /// The shared pointer to a target.
+ ///
+ /// @return
+ /// Returns \b true if the target was successfully removed from
+ /// from this target list, \b false otherwise. The client will
+ /// be left with the last remaining shared pointer to the target
+ /// in \a target_sp which can then be properly released.
+ //------------------------------------------------------------------
+ bool
+ DeleteTarget (lldb::TargetSP &target_sp);
+
+ int
+ GetNumTargets () const;
+
+ lldb::TargetSP
+ GetTargetAtIndex (uint32_t index) const;
+
+ uint32_t
+ GetIndexOfTarget (lldb::TargetSP target_sp) const;
+
+ //------------------------------------------------------------------
+ /// Find the target that contains has an executable whose path
+ /// matches \a exe_file_spec, and whose architecture matches
+ /// \a arch_ptr if arch_ptr is not NULL.
+ ///
+ /// @param[in] exe_file_spec
+ /// A file spec containing a basename, or a full path (directory
+ /// and basename). If \a exe_file_spec contains only a filename
+ /// (empty GetDirectory() value) then matching will be done
+ /// solely based on the filenames and directories won't be
+ /// compared. If \a exe_file_spec contains a filename and a
+ /// directory, then both must match.
+ ///
+ /// @param[in] exe_arch_ptr
+ /// If not NULL then the architecture also needs to match, else
+ /// the architectures will be compared.
+ ///
+ /// @return
+ /// A shared pointer to a target object. The returned shared
+ /// pointer will contain NULL if no target objects have a
+ /// executable whose full or partial path matches
+ /// with a matching process ID.
+ //------------------------------------------------------------------
+ lldb::TargetSP
+ FindTargetWithExecutableAndArchitecture (const FileSpec &exe_file_spec,
+ const ArchSpec *exe_arch_ptr = NULL) const;
+
+ //------------------------------------------------------------------
+ /// Find the target that contains a process with process ID \a
+ /// pid.
+ ///
+ /// @param[in] pid
+ /// The process ID to search our target list for.
+ ///
+ /// @return
+ /// A shared pointer to a target object. The returned shared
+ /// pointer will contain NULL if no target objects own a process
+ /// with a matching process ID.
+ //------------------------------------------------------------------
+ lldb::TargetSP
+ FindTargetWithProcessID (lldb::pid_t pid) const;
+
+ lldb::TargetSP
+ FindTargetWithProcess (lldb_private::Process *process) const;
+
+ lldb::TargetSP
+ GetTargetSP (Target *target) const;
+
+ //------------------------------------------------------------------
+ /// Send an async interrupt to one or all processes.
+ ///
+ /// Find the target that contains the process with process ID \a
+ /// pid and send a LLDB_EVENT_ASYNC_INTERRUPT event to the process's
+ /// event queue.
+ ///
+ /// @param[in] pid
+ /// The process ID to search our target list for, if \a pid is
+ /// LLDB_INVALID_PROCESS_ID, then the interrupt will be sent to
+ /// all processes.
+ ///
+ /// @return
+ /// The number of async interrupts sent.
+ //------------------------------------------------------------------
+ uint32_t
+ SendAsyncInterrupt (lldb::pid_t pid = LLDB_INVALID_PROCESS_ID);
+
+ uint32_t
+ SignalIfRunning (lldb::pid_t pid, int signo);
+
+ uint32_t
+ SetSelectedTarget (Target *target);
+
+ lldb::TargetSP
+ GetSelectedTarget ();
+
+
+protected:
+ typedef std::vector<lldb::TargetSP> collection;
+ //------------------------------------------------------------------
+ // Member variables.
+ //------------------------------------------------------------------
+ collection m_target_list;
+ mutable Mutex m_target_list_mutex;
+ uint32_t m_selected_target_idx;
+private:
+ DISALLOW_COPY_AND_ASSIGN (TargetList);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_TargetList_h_
diff --git a/include/lldb/Target/Thread.h b/include/lldb/Target/Thread.h
new file mode 100644
index 000000000000..e4e532e4b331
--- /dev/null
+++ b/include/lldb/Target/Thread.h
@@ -0,0 +1,1067 @@
+//===-- Thread.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_Thread_h_
+#define liblldb_Thread_h_
+
+#include "lldb/lldb-private.h"
+#include "lldb/Host/Mutex.h"
+#include "lldb/Core/Broadcaster.h"
+#include "lldb/Core/Event.h"
+#include "lldb/Core/UserID.h"
+#include "lldb/Core/UserSettingsController.h"
+#include "lldb/Target/ExecutionContextScope.h"
+#include "lldb/Target/StackFrameList.h"
+
+#define LLDB_THREAD_MAX_STOP_EXC_DATA 8
+
+namespace lldb_private {
+
+class ThreadProperties : public Properties
+{
+public:
+ ThreadProperties(bool is_global);
+
+ virtual
+ ~ThreadProperties();
+
+ //------------------------------------------------------------------
+ /// The regular expression returned determines symbols that this
+ /// thread won't stop in during "step-in" operations.
+ ///
+ /// @return
+ /// A pointer to a regular expression to compare against symbols,
+ /// or NULL if all symbols are allowed.
+ ///
+ //------------------------------------------------------------------
+ const RegularExpression *
+ GetSymbolsToAvoidRegexp();
+
+ bool
+ GetTraceEnabledState() const;
+};
+
+typedef std::shared_ptr<ThreadProperties> ThreadPropertiesSP;
+
+class Thread :
+ public std::enable_shared_from_this<Thread>,
+ public ThreadProperties,
+ public UserID,
+ public ExecutionContextScope,
+ public Broadcaster
+{
+public:
+ //------------------------------------------------------------------
+ /// Broadcaster event bits definitions.
+ //------------------------------------------------------------------
+ enum
+ {
+ eBroadcastBitStackChanged = (1 << 0),
+ eBroadcastBitThreadSuspended = (1 << 1),
+ eBroadcastBitThreadResumed = (1 << 2),
+ eBroadcastBitSelectedFrameChanged = (1 << 3),
+ eBroadcastBitThreadSelected = (1 << 4)
+ };
+
+ static ConstString &GetStaticBroadcasterClass ();
+
+ virtual ConstString &GetBroadcasterClass() const
+ {
+ return GetStaticBroadcasterClass();
+ }
+
+ class ThreadEventData :
+ public EventData
+ {
+ public:
+ ThreadEventData (const lldb::ThreadSP thread_sp);
+
+ ThreadEventData (const lldb::ThreadSP thread_sp, const StackID &stack_id);
+
+ ThreadEventData();
+
+ virtual ~ThreadEventData();
+
+ static const ConstString &
+ GetFlavorString ();
+
+ virtual const ConstString &
+ GetFlavor () const
+ {
+ return ThreadEventData::GetFlavorString ();
+ }
+
+ virtual void
+ Dump (Stream *s) const;
+
+ static const ThreadEventData *
+ GetEventDataFromEvent (const Event *event_ptr);
+
+ static lldb::ThreadSP
+ GetThreadFromEvent (const Event *event_ptr);
+
+ static StackID
+ GetStackIDFromEvent (const Event *event_ptr);
+
+ static lldb::StackFrameSP
+ GetStackFrameFromEvent (const Event *event_ptr);
+
+ lldb::ThreadSP
+ GetThread () const
+ {
+ return m_thread_sp;
+ }
+
+ StackID
+ GetStackID () const
+ {
+ return m_stack_id;
+ }
+
+ private:
+ lldb::ThreadSP m_thread_sp;
+ StackID m_stack_id;
+ DISALLOW_COPY_AND_ASSIGN (ThreadEventData);
+ };
+
+ // TODO: You shouldn't just checkpoint the register state alone, so this should get
+ // moved to protected. To do that ThreadStateCheckpoint needs to be returned as a token...
+ class RegisterCheckpoint
+ {
+ public:
+
+ RegisterCheckpoint() :
+ m_stack_id (),
+ m_data_sp ()
+ {
+ }
+
+ RegisterCheckpoint (const StackID &stack_id) :
+ m_stack_id (stack_id),
+ m_data_sp ()
+ {
+ }
+
+ ~RegisterCheckpoint()
+ {
+ }
+
+ const RegisterCheckpoint&
+ operator= (const RegisterCheckpoint &rhs)
+ {
+ if (this != &rhs)
+ {
+ this->m_stack_id = rhs.m_stack_id;
+ this->m_data_sp = rhs.m_data_sp;
+ }
+ return *this;
+ }
+
+ RegisterCheckpoint (const RegisterCheckpoint &rhs) :
+ m_stack_id (rhs.m_stack_id),
+ m_data_sp (rhs.m_data_sp)
+ {
+ }
+
+ const StackID &
+ GetStackID()
+ {
+ return m_stack_id;
+ }
+
+ void
+ SetStackID (const StackID &stack_id)
+ {
+ m_stack_id = stack_id;
+ }
+
+ lldb::DataBufferSP &
+ GetData()
+ {
+ return m_data_sp;
+ }
+
+ const lldb::DataBufferSP &
+ GetData() const
+ {
+ return m_data_sp;
+ }
+
+ protected:
+ StackID m_stack_id;
+ lldb::DataBufferSP m_data_sp;
+ };
+
+ struct ThreadStateCheckpoint
+ {
+ uint32_t orig_stop_id; // Dunno if I need this yet but it is an interesting bit of data.
+ lldb::StopInfoSP stop_info_sp; // You have to restore the stop info or you might continue with the wrong signals.
+ RegisterCheckpoint register_backup; // You need to restore the registers, of course...
+ uint32_t current_inlined_depth;
+ lldb::addr_t current_inlined_pc;
+ };
+
+ static void
+ SettingsInitialize ();
+
+ static void
+ SettingsTerminate ();
+
+ static const ThreadPropertiesSP &
+ GetGlobalProperties();
+
+ Thread (Process &process, lldb::tid_t tid);
+ virtual ~Thread();
+
+ lldb::ProcessSP
+ GetProcess() const
+ {
+ return m_process_wp.lock();
+ }
+
+ int
+ GetResumeSignal () const
+ {
+ return m_resume_signal;
+ }
+
+ void
+ SetResumeSignal (int signal)
+ {
+ m_resume_signal = signal;
+ }
+
+ lldb::StateType
+ GetState() const;
+
+ void
+ SetState (lldb::StateType state);
+
+ lldb::StateType
+ GetResumeState () const
+ {
+ return m_resume_state;
+ }
+
+ void
+ SetResumeState (lldb::StateType state)
+ {
+ m_resume_state = state;
+ }
+
+ // This function is called on all the threads before "ShouldResume" and
+ // "WillResume" in case a thread needs to change its state before the
+ // ThreadList polls all the threads to figure out which ones actually
+ // will get to run and how.
+ void
+ SetupForResume ();
+
+ // Do not override this function, it is for thread plan logic only
+ bool
+ ShouldResume (lldb::StateType resume_state);
+
+ // Override this to do platform specific tasks before resume.
+ virtual void
+ WillResume (lldb::StateType resume_state)
+ {
+ }
+
+ // This clears generic thread state after a resume. If you subclass this,
+ // be sure to call it.
+ virtual void
+ DidResume ();
+
+ // This notifies the thread when a private stop occurs.
+ virtual void
+ DidStop ();
+
+ virtual void
+ RefreshStateAfterStop() = 0;
+
+ void
+ WillStop ();
+
+ bool
+ ShouldStop (Event *event_ptr);
+
+ Vote
+ ShouldReportStop (Event *event_ptr);
+
+ Vote
+ ShouldReportRun (Event *event_ptr);
+
+ void
+ Flush ();
+
+ // Return whether this thread matches the specification in ThreadSpec. This is a virtual
+ // method because at some point we may extend the thread spec with a platform specific
+ // dictionary of attributes, which then only the platform specific Thread implementation
+ // would know how to match. For now, this just calls through to the ThreadSpec's
+ // ThreadPassesBasicTests method.
+ virtual bool
+ MatchesSpec (const ThreadSpec *spec);
+
+ lldb::StopInfoSP
+ GetStopInfo ();
+
+ lldb::StopReason
+ GetStopReason();
+
+ // This sets the stop reason to a "blank" stop reason, so you can call functions on the thread
+ // without having the called function run with whatever stop reason you stopped with.
+ void
+ SetStopInfoToNothing();
+
+ bool
+ ThreadStoppedForAReason ();
+
+ static const char *
+ RunModeAsCString (lldb::RunMode mode);
+
+ static const char *
+ StopReasonAsCString (lldb::StopReason reason);
+
+ virtual const char *
+ GetInfo ()
+ {
+ return NULL;
+ }
+
+ virtual const char *
+ GetName ()
+ {
+ return NULL;
+ }
+
+ virtual const char *
+ GetQueueName ()
+ {
+ return NULL;
+ }
+
+ virtual uint32_t
+ GetStackFrameCount()
+ {
+ return GetStackFrameList()->GetNumFrames();
+ }
+
+ virtual lldb::StackFrameSP
+ GetStackFrameAtIndex (uint32_t idx)
+ {
+ return GetStackFrameList()->GetFrameAtIndex(idx);
+ }
+
+ virtual lldb::StackFrameSP
+ GetFrameWithConcreteFrameIndex (uint32_t unwind_idx);
+
+ bool
+ DecrementCurrentInlinedDepth()
+ {
+ return GetStackFrameList()->DecrementCurrentInlinedDepth();
+ }
+
+ uint32_t
+ GetCurrentInlinedDepth()
+ {
+ return GetStackFrameList()->GetCurrentInlinedDepth();
+ }
+
+ Error
+ ReturnFromFrameWithIndex (uint32_t frame_idx, lldb::ValueObjectSP return_value_sp, bool broadcast = false);
+
+ Error
+ ReturnFromFrame (lldb::StackFrameSP frame_sp, lldb::ValueObjectSP return_value_sp, bool broadcast = false);
+
+ virtual lldb::StackFrameSP
+ GetFrameWithStackID (const StackID &stack_id)
+ {
+ if (stack_id.IsValid())
+ return GetStackFrameList()->GetFrameWithStackID (stack_id);
+ return lldb::StackFrameSP();
+ }
+
+ uint32_t
+ GetSelectedFrameIndex ()
+ {
+ return GetStackFrameList()->GetSelectedFrameIndex();
+ }
+
+ lldb::StackFrameSP
+ GetSelectedFrame ()
+ {
+ lldb::StackFrameListSP stack_frame_list_sp(GetStackFrameList());
+ return stack_frame_list_sp->GetFrameAtIndex (stack_frame_list_sp->GetSelectedFrameIndex());
+ }
+
+ uint32_t
+ SetSelectedFrame (lldb_private::StackFrame *frame, bool broadcast = false);
+
+
+ bool
+ SetSelectedFrameByIndex (uint32_t frame_idx, bool broadcast = false);
+
+ bool
+ SetSelectedFrameByIndexNoisily (uint32_t frame_idx, Stream &output_stream);
+
+ void
+ SetDefaultFileAndLineToSelectedFrame()
+ {
+ GetStackFrameList()->SetDefaultFileAndLineToSelectedFrame();
+ }
+
+ virtual lldb::RegisterContextSP
+ GetRegisterContext () = 0;
+
+ virtual lldb::RegisterContextSP
+ CreateRegisterContextForFrame (StackFrame *frame) = 0;
+
+ virtual void
+ ClearStackFrames ();
+
+ virtual bool
+ SetBackingThread (const lldb::ThreadSP &thread_sp)
+ {
+ return false;
+ }
+
+ virtual lldb::ThreadSP
+ GetBackingThread () const
+ {
+ return lldb::ThreadSP();
+ }
+
+ virtual void
+ ClearBackingThread ()
+ {
+ // Subclasses can use this function if a thread is actually backed by
+ // another thread. This is currently used for the OperatingSystem plug-ins
+ // where they might have a thread that is in memory, yet its registers
+ // are available through the lldb_private::Thread subclass for the current
+ // lldb_private::Process class. Since each time the process stops the backing
+ // threads for memory threads can change, we need a way to clear the backing
+ // thread for all memory threads each time we stop.
+ }
+
+ void
+ DumpUsingSettingsFormat (Stream &strm, uint32_t frame_idx);
+
+ //------------------------------------------------------------------
+ // Thread Plan Providers:
+ // This section provides the basic thread plans that the Process control
+ // machinery uses to run the target. ThreadPlan.h provides more details on
+ // how this mechanism works.
+ // The thread provides accessors to a set of plans that perform basic operations.
+ // The idea is that particular Platform plugins can override these methods to
+ // provide the implementation of these basic operations appropriate to their
+ // environment.
+ //
+ // NB: All the QueueThreadPlanXXX providers return Shared Pointers to
+ // Thread plans. This is useful so that you can modify the plans after
+ // creation in ways specific to that plan type. Also, it is often necessary for
+ // ThreadPlans that utilize other ThreadPlans to implement their task to keep a shared
+ // pointer to the sub-plan.
+ // But besides that, the shared pointers should only be held onto by entities who live no longer
+ // than the thread containing the ThreadPlan.
+ // FIXME: If this becomes a problem, we can make a version that just returns a pointer,
+ // which it is clearly unsafe to hold onto, and a shared pointer version, and only allow
+ // ThreadPlan and Co. to use the latter. That is made more annoying to do because there's
+ // no elegant way to friend a method to all sub-classes of a given class.
+ //
+ //------------------------------------------------------------------
+
+ //------------------------------------------------------------------
+ /// Queues the base plan for a thread.
+ /// The version returned by Process does some things that are useful,
+ /// like handle breakpoints and signals, so if you return a plugin specific
+ /// one you probably want to call through to the Process one for anything
+ /// your plugin doesn't explicitly handle.
+ ///
+ /// @param[in] abort_other_plans
+ /// \b true if we discard the currently queued plans and replace them with this one.
+ /// Otherwise this plan will go on the end of the plan stack.
+ ///
+ /// @return
+ /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued.
+ //------------------------------------------------------------------
+ virtual lldb::ThreadPlanSP
+ QueueFundamentalPlan (bool abort_other_plans);
+
+ //------------------------------------------------------------------
+ /// Queues the plan used to step over a breakpoint at the current PC of \a thread.
+ /// The default version returned by Process handles trap based breakpoints, and
+ /// will disable the breakpoint, single step over it, then re-enable it.
+ ///
+ /// @param[in] abort_other_plans
+ /// \b true if we discard the currently queued plans and replace them with this one.
+ /// Otherwise this plan will go on the end of the plan stack.
+ ///
+ /// @return
+ /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued.
+ //------------------------------------------------------------------
+ virtual lldb::ThreadPlanSP
+ QueueThreadPlanForStepOverBreakpointPlan (bool abort_other_plans);
+
+ //------------------------------------------------------------------
+ /// Queues the plan used to step one instruction from the current PC of \a thread.
+ ///
+ /// @param[in] step_over
+ /// \b true if we step over calls to functions, false if we step in.
+ ///
+ /// @param[in] abort_other_plans
+ /// \b true if we discard the currently queued plans and replace them with this one.
+ /// Otherwise this plan will go on the end of the plan stack.
+ ///
+ /// @param[in] stop_other_threads
+ /// \b true if we will stop other threads while we single step this one.
+ ///
+ /// @return
+ /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued.
+ //------------------------------------------------------------------
+ virtual lldb::ThreadPlanSP
+ QueueThreadPlanForStepSingleInstruction (bool step_over,
+ bool abort_other_plans,
+ bool stop_other_threads);
+
+ //------------------------------------------------------------------
+ /// Queues the plan used to step through an address range, stepping over
+ /// function calls.
+ ///
+ /// @param[in] abort_other_plans
+ /// \b true if we discard the currently queued plans and replace them with this one.
+ /// Otherwise this plan will go on the end of the plan stack.
+ ///
+ /// @param[in] type
+ /// Type of step to do, only eStepTypeInto and eStepTypeOver are supported by this plan.
+ ///
+ /// @param[in] range
+ /// The address range to step through.
+ ///
+ /// @param[in] addr_context
+ /// When dealing with stepping through inlined functions the current PC is not enough information to know
+ /// what "step" means. For instance a series of nested inline functions might start at the same address.
+ // The \a addr_context provides the current symbol context the step
+ /// is supposed to be out of.
+ // FIXME: Currently unused.
+ ///
+ /// @param[in] stop_other_threads
+ /// \b true if we will stop other threads while we single step this one.
+ ///
+ /// @return
+ /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued.
+ //------------------------------------------------------------------
+ virtual lldb::ThreadPlanSP
+ QueueThreadPlanForStepOverRange (bool abort_other_plans,
+ const AddressRange &range,
+ const SymbolContext &addr_context,
+ lldb::RunMode stop_other_threads);
+
+ //------------------------------------------------------------------
+ /// Queues the plan used to step through an address range, stepping into functions.
+ ///
+ /// @param[in] abort_other_plans
+ /// \b true if we discard the currently queued plans and replace them with this one.
+ /// Otherwise this plan will go on the end of the plan stack.
+ ///
+ /// @param[in] type
+ /// Type of step to do, only eStepTypeInto and eStepTypeOver are supported by this plan.
+ ///
+ /// @param[in] range
+ /// The address range to step through.
+ ///
+ /// @param[in] addr_context
+ /// When dealing with stepping through inlined functions the current PC is not enough information to know
+ /// what "step" means. For instance a series of nested inline functions might start at the same address.
+ // The \a addr_context provides the current symbol context the step
+ /// is supposed to be out of.
+ // FIXME: Currently unused.
+ ///
+ /// @param[in] step_in_target
+ /// Name if function we are trying to step into. We will step out if we don't land in that function.
+ ///
+ /// @param[in] stop_other_threads
+ /// \b true if we will stop other threads while we single step this one.
+ ///
+ /// @param[in] avoid_code_without_debug_info
+ /// If \b true we will step out if we step into code with no debug info.
+ ///
+ /// @return
+ /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued.
+ //------------------------------------------------------------------
+ virtual lldb::ThreadPlanSP
+ QueueThreadPlanForStepInRange (bool abort_other_plans,
+ const AddressRange &range,
+ const SymbolContext &addr_context,
+ const char *step_in_target,
+ lldb::RunMode stop_other_threads,
+ bool avoid_code_without_debug_info);
+
+ //------------------------------------------------------------------
+ /// Queue the plan used to step out of the function at the current PC of
+ /// \a thread.
+ ///
+ /// @param[in] abort_other_plans
+ /// \b true if we discard the currently queued plans and replace them with this one.
+ /// Otherwise this plan will go on the end of the plan stack.
+ ///
+ /// @param[in] addr_context
+ /// When dealing with stepping through inlined functions the current PC is not enough information to know
+ /// what "step" means. For instance a series of nested inline functions might start at the same address.
+ // The \a addr_context provides the current symbol context the step
+ /// is supposed to be out of.
+ // FIXME: Currently unused.
+ ///
+ /// @param[in] first_insn
+ /// \b true if this is the first instruction of a function.
+ ///
+ /// @param[in] stop_other_threads
+ /// \b true if we will stop other threads while we single step this one.
+ ///
+ /// @param[in] stop_vote
+ /// @param[in] run_vote
+ /// See standard meanings for the stop & run votes in ThreadPlan.h.
+ ///
+ /// @return
+ /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued.
+ //------------------------------------------------------------------
+ virtual lldb::ThreadPlanSP
+ QueueThreadPlanForStepOut (bool abort_other_plans,
+ SymbolContext *addr_context,
+ bool first_insn,
+ bool stop_other_threads,
+ Vote stop_vote, // = eVoteYes,
+ Vote run_vote, // = eVoteNoOpinion);
+ uint32_t frame_idx);
+
+ //------------------------------------------------------------------
+ /// Gets the plan used to step through the code that steps from a function
+ /// call site at the current PC into the actual function call.
+ ///
+ ///
+ /// @param[in] return_stack_id
+ /// The stack id that we will return to (by setting backstop breakpoints on the return
+ /// address to that frame) if we fail to step through.
+ ///
+ /// @param[in] abort_other_plans
+ /// \b true if we discard the currently queued plans and replace them with this one.
+ /// Otherwise this plan will go on the end of the plan stack.
+ ///
+ /// @param[in] stop_other_threads
+ /// \b true if we will stop other threads while we single step this one.
+ ///
+ /// @return
+ /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued.
+ //------------------------------------------------------------------
+ virtual lldb::ThreadPlanSP
+ QueueThreadPlanForStepThrough (StackID &return_stack_id,
+ bool abort_other_plans,
+ bool stop_other_threads);
+
+ //------------------------------------------------------------------
+ /// Gets the plan used to continue from the current PC.
+ /// This is a simple plan, mostly useful as a backstop when you are continuing
+ /// for some particular purpose.
+ ///
+ /// @param[in] abort_other_plans
+ /// \b true if we discard the currently queued plans and replace them with this one.
+ /// Otherwise this plan will go on the end of the plan stack.
+ ///
+ /// @param[in] target_addr
+ /// The address to which we're running.
+ ///
+ /// @param[in] stop_other_threads
+ /// \b true if we will stop other threads while we single step this one.
+ ///
+ /// @return
+ /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued.
+ //------------------------------------------------------------------
+ virtual lldb::ThreadPlanSP
+ QueueThreadPlanForRunToAddress (bool abort_other_plans,
+ Address &target_addr,
+ bool stop_other_threads);
+
+ virtual lldb::ThreadPlanSP
+ QueueThreadPlanForStepUntil (bool abort_other_plans,
+ lldb::addr_t *address_list,
+ size_t num_addresses,
+ bool stop_others,
+ uint32_t frame_idx);
+
+ virtual lldb::ThreadPlanSP
+ QueueThreadPlanForCallFunction (bool abort_other_plans,
+ Address& function,
+ lldb::addr_t arg,
+ bool stop_other_threads,
+ bool unwind_on_error = false,
+ bool ignore_breakpoints = true);
+
+ //------------------------------------------------------------------
+ // Thread Plan accessors:
+ //------------------------------------------------------------------
+
+ //------------------------------------------------------------------
+ /// Gets the plan which will execute next on the plan stack.
+ ///
+ /// @return
+ /// A pointer to the next executed plan.
+ //------------------------------------------------------------------
+ ThreadPlan *
+ GetCurrentPlan ();
+
+ //------------------------------------------------------------------
+ /// Unwinds the thread stack for the innermost expression plan currently
+ /// on the thread plan stack.
+ ///
+ /// @return
+ /// An error if the thread plan could not be unwound.
+ //------------------------------------------------------------------
+
+ Error
+ UnwindInnermostExpression();
+
+private:
+ bool
+ PlanIsBasePlan (ThreadPlan *plan_ptr);
+
+ void
+ BroadcastSelectedFrameChange(StackID &new_frame_id);
+
+public:
+
+ //------------------------------------------------------------------
+ /// Gets the outer-most plan that was popped off the plan stack in the
+ /// most recent stop. Useful for printing the stop reason accurately.
+ ///
+ /// @return
+ /// A pointer to the last completed plan.
+ //------------------------------------------------------------------
+ lldb::ThreadPlanSP
+ GetCompletedPlan ();
+
+ //------------------------------------------------------------------
+ /// Gets the outer-most return value from the completed plans
+ ///
+ /// @return
+ /// A ValueObjectSP, either empty if there is no return value,
+ /// or containing the return value.
+ //------------------------------------------------------------------
+ lldb::ValueObjectSP
+ GetReturnValueObject ();
+
+ //------------------------------------------------------------------
+ /// Checks whether the given plan is in the completed plans for this
+ /// stop.
+ ///
+ /// @param[in] plan
+ /// Pointer to the plan you're checking.
+ ///
+ /// @return
+ /// Returns true if the input plan is in the completed plan stack,
+ /// false otherwise.
+ //------------------------------------------------------------------
+ bool
+ IsThreadPlanDone (ThreadPlan *plan);
+
+ //------------------------------------------------------------------
+ /// Checks whether the given plan is in the discarded plans for this
+ /// stop.
+ ///
+ /// @param[in] plan
+ /// Pointer to the plan you're checking.
+ ///
+ /// @return
+ /// Returns true if the input plan is in the discarded plan stack,
+ /// false otherwise.
+ //------------------------------------------------------------------
+ bool
+ WasThreadPlanDiscarded (ThreadPlan *plan);
+
+ //------------------------------------------------------------------
+ /// Queues a generic thread plan.
+ ///
+ /// @param[in] plan_sp
+ /// The plan to queue.
+ ///
+ /// @param[in] abort_other_plans
+ /// \b true if we discard the currently queued plans and replace them with this one.
+ /// Otherwise this plan will go on the end of the plan stack.
+ ///
+ /// @return
+ /// A pointer to the last completed plan.
+ //------------------------------------------------------------------
+ void
+ QueueThreadPlan (lldb::ThreadPlanSP &plan_sp, bool abort_other_plans);
+
+
+ //------------------------------------------------------------------
+ /// Discards the plans queued on the plan stack of the current thread. This is
+ /// arbitrated by the "Master" ThreadPlans, using the "OkayToDiscard" call.
+ // But if \a force is true, all thread plans are discarded.
+ //------------------------------------------------------------------
+ void
+ DiscardThreadPlans (bool force);
+
+ //------------------------------------------------------------------
+ /// Discards the plans queued on the plan stack of the current thread up to and
+ /// including up_to_plan_sp.
+ //
+ // @param[in] up_to_plan_sp
+ // Discard all plans up to and including this one.
+ //------------------------------------------------------------------
+ void
+ DiscardThreadPlansUpToPlan (lldb::ThreadPlanSP &up_to_plan_sp);
+
+ void
+ DiscardThreadPlansUpToPlan (ThreadPlan *up_to_plan_ptr);
+
+ //------------------------------------------------------------------
+ /// Prints the current plan stack.
+ ///
+ /// @param[in] s
+ /// The stream to which to dump the plan stack info.
+ ///
+ //------------------------------------------------------------------
+ void
+ DumpThreadPlans (Stream *s) const;
+
+ virtual bool
+ CheckpointThreadState (ThreadStateCheckpoint &saved_state);
+
+ virtual bool
+ RestoreRegisterStateFromCheckpoint (ThreadStateCheckpoint &saved_state);
+
+ virtual bool
+ RestoreThreadStateFromCheckpoint (ThreadStateCheckpoint &saved_state);
+
+ void
+ EnableTracer (bool value, bool single_step);
+
+ void
+ SetTracer (lldb::ThreadPlanTracerSP &tracer_sp);
+
+ //------------------------------------------------------------------
+ // Get the thread index ID. The index ID that is guaranteed to not
+ // be re-used by a process. They start at 1 and increase with each
+ // new thread. This allows easy command line access by a unique ID
+ // that is easier to type than the actual system thread ID.
+ //------------------------------------------------------------------
+ uint32_t
+ GetIndexID () const;
+
+
+ //------------------------------------------------------------------
+ // The API ID is often the same as the Thread::GetID(), but not in
+ // all cases. Thread::GetID() is the user visible thread ID that
+ // clients would want to see. The API thread ID is the thread ID
+ // that is used when sending data to/from the debugging protocol.
+ //------------------------------------------------------------------
+ virtual lldb::user_id_t
+ GetProtocolID () const
+ {
+ return GetID();
+ }
+
+ //------------------------------------------------------------------
+ // lldb::ExecutionContextScope pure virtual functions
+ //------------------------------------------------------------------
+ virtual lldb::TargetSP
+ CalculateTarget ();
+
+ virtual lldb::ProcessSP
+ CalculateProcess ();
+
+ virtual lldb::ThreadSP
+ CalculateThread ();
+
+ virtual lldb::StackFrameSP
+ CalculateStackFrame ();
+
+ virtual void
+ CalculateExecutionContext (ExecutionContext &exe_ctx);
+
+ lldb::StackFrameSP
+ GetStackFrameSPForStackFramePtr (StackFrame *stack_frame_ptr);
+
+ size_t
+ GetStatus (Stream &strm,
+ uint32_t start_frame,
+ uint32_t num_frames,
+ uint32_t num_frames_with_source);
+
+ size_t
+ GetStackFrameStatus (Stream& strm,
+ uint32_t first_frame,
+ uint32_t num_frames,
+ bool show_frame_info,
+ uint32_t num_frames_with_source);
+
+ // We need a way to verify that even though we have a thread in a shared
+ // pointer that the object itself is still valid. Currently this won't be
+ // the case if DestroyThread() was called. DestroyThread is called when
+ // a thread has been removed from the Process' thread list.
+ bool
+ IsValid () const
+ {
+ return !m_destroy_called;
+ }
+
+ // Sets and returns a valid stop info based on the process stop ID and the
+ // current thread plan. If the thread stop ID does not match the process'
+ // stop ID, the private stop reason is not set and an invalid StopInfoSP may
+ // be returned.
+ //
+ // NOTE: This function must be called before the current thread plan is
+ // moved to the completed plan stack (in Thread::ShouldStop()).
+ //
+ // NOTE: If subclasses override this function, ensure they do not overwrite
+ // the m_actual_stop_info if it is valid. The stop info may be a
+ // "checkpointed and restored" stop info, so if it is still around it is
+ // right even if you have not calculated this yourself, or if it disagrees
+ // with what you might have calculated.
+ virtual lldb::StopInfoSP
+ GetPrivateStopInfo ();
+
+ //----------------------------------------------------------------------
+ // Ask the thread subclass to set its stop info.
+ //
+ // Thread subclasses should call Thread::SetStopInfo(...) with the
+ // reason the thread stopped.
+ //
+ // @return
+ // True if Thread::SetStopInfo(...) was called, false otherwise.
+ //----------------------------------------------------------------------
+ virtual bool
+ CalculateStopInfo () = 0;
+
+ //----------------------------------------------------------------------
+ // Gets the temporary resume state for a thread.
+ //
+ // This value gets set in each thread by complex debugger logic in
+ // Thread::ShouldResume() and an appropriate thread resume state will get
+ // set in each thread every time the process is resumed prior to calling
+ // Process::DoResume(). The lldb_private::Process subclass should adhere
+ // to the thread resume state request which will be one of:
+ //
+ // eStateRunning - thread will resume when process is resumed
+ // eStateStepping - thread should step 1 instruction and stop when process
+ // is resumed
+ // eStateSuspended - thread should not execute any instructions when
+ // process is resumed
+ //----------------------------------------------------------------------
+ lldb::StateType
+ GetTemporaryResumeState() const
+ {
+ return m_temporary_resume_state;
+ }
+
+ void
+ SetStopInfo (const lldb::StopInfoSP &stop_info_sp);
+
+ void
+ SetShouldReportStop (Vote vote);
+
+protected:
+
+ friend class ThreadPlan;
+ friend class ThreadList;
+ friend class ThreadEventData;
+ friend class StackFrameList;
+ friend class StackFrame;
+ friend class OperatingSystem;
+
+ // This is necessary to make sure thread assets get destroyed while the thread is still in good shape
+ // to call virtual thread methods. This must be called by classes that derive from Thread in their destructor.
+ virtual void DestroyThread ();
+
+ void
+ PushPlan (lldb::ThreadPlanSP &plan_sp);
+
+ void
+ PopPlan ();
+
+ void
+ DiscardPlan ();
+
+ ThreadPlan *GetPreviousPlan (ThreadPlan *plan);
+
+ typedef std::vector<lldb::ThreadPlanSP> plan_stack;
+
+ virtual bool
+ SaveFrameZeroState (RegisterCheckpoint &checkpoint);
+
+ virtual bool
+ RestoreSaveFrameZero (const RegisterCheckpoint &checkpoint);
+
+ // register_data_sp must be a DataSP passed to ReadAllRegisterValues.
+ bool
+ ResetFrameZeroRegisters (lldb::DataBufferSP register_data_sp);
+
+ virtual lldb_private::Unwind *
+ GetUnwinder ();
+
+ // Check to see whether the thread is still at the last breakpoint hit that stopped it.
+ virtual bool
+ IsStillAtLastBreakpointHit();
+
+ // Some threads are threads that are made up by OperatingSystem plugins that
+ // are threads that exist and are context switched out into memory. The
+ // OperatingSystem plug-in need a ways to know if a thread is "real" or made
+ // up.
+ virtual bool
+ IsOperatingSystemPluginThread () const
+ {
+ return false;
+ }
+
+
+ lldb::StackFrameListSP
+ GetStackFrameList ();
+
+ struct ThreadState
+ {
+ uint32_t orig_stop_id;
+ lldb::StopInfoSP stop_info_sp;
+ RegisterCheckpoint register_backup;
+ };
+
+ //------------------------------------------------------------------
+ // Classes that inherit from Process can see and modify these
+ //------------------------------------------------------------------
+ lldb::ProcessWP m_process_wp; ///< The process that owns this thread.
+ lldb::StopInfoSP m_stop_info_sp; ///< The private stop reason for this thread
+ uint32_t m_stop_info_stop_id; // This is the stop id for which the StopInfo is valid. Can use this so you know that
+ // the thread's m_stop_info_sp is current and you don't have to fetch it again
+ const uint32_t m_index_id; ///< A unique 1 based index assigned to each thread for easy UI/command line access.
+ lldb::RegisterContextSP m_reg_context_sp; ///< The register context for this thread's current register state.
+ lldb::StateType m_state; ///< The state of our process.
+ mutable Mutex m_state_mutex; ///< Multithreaded protection for m_state.
+ plan_stack m_plan_stack; ///< The stack of plans this thread is executing.
+ plan_stack m_completed_plan_stack; ///< Plans that have been completed by this stop. They get deleted when the thread resumes.
+ plan_stack m_discarded_plan_stack; ///< Plans that have been discarded by this stop. They get deleted when the thread resumes.
+ mutable Mutex m_frame_mutex; ///< Multithreaded protection for m_state.
+ lldb::StackFrameListSP m_curr_frames_sp; ///< The stack frames that get lazily populated after a thread stops.
+ lldb::StackFrameListSP m_prev_frames_sp; ///< The previous stack frames from the last time this thread stopped.
+ int m_resume_signal; ///< The signal that should be used when continuing this thread.
+ lldb::StateType m_resume_state; ///< This state is used to force a thread to be suspended from outside the ThreadPlan logic.
+ lldb::StateType m_temporary_resume_state; ///< This state records what the thread was told to do by the thread plan logic for the current resume.
+ /// It gets set in Thread::ShoudResume.
+ std::unique_ptr<lldb_private::Unwind> m_unwinder_ap;
+ bool m_destroy_called; // This is used internally to make sure derived Thread classes call DestroyThread.
+ LazyBool m_override_should_notify;
+private:
+ //------------------------------------------------------------------
+ // For Thread only
+ //------------------------------------------------------------------
+
+ DISALLOW_COPY_AND_ASSIGN (Thread);
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_Thread_h_
diff --git a/include/lldb/Target/ThreadList.h b/include/lldb/Target/ThreadList.h
new file mode 100644
index 000000000000..ddf49b002ecf
--- /dev/null
+++ b/include/lldb/Target/ThreadList.h
@@ -0,0 +1,163 @@
+//===-- ThreadList.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_ThreadList_h_
+#define liblldb_ThreadList_h_
+
+#include <vector>
+
+#include "lldb/lldb-private.h"
+#include "lldb/Core/UserID.h"
+
+
+// FIXME: Currently this is a thread list with lots of functionality for use only by
+// the process for which this is the thread list. If we ever want a container class
+// to hand out that is just a random subset of threads, with iterator functionality,
+// then we should make that part a base class, and make a ProcessThreadList for the
+// process.
+namespace lldb_private {
+
+class ThreadList
+{
+friend class Process;
+
+public:
+
+ ThreadList (Process *process);
+
+ ThreadList (const ThreadList &rhs);
+
+ ~ThreadList ();
+
+ const ThreadList&
+ operator = (const ThreadList& rhs);
+
+ uint32_t
+ GetSize(bool can_update = true);
+
+ void
+ AddThread (const lldb::ThreadSP &thread_sp);
+
+ // Return the selected thread if there is one. Otherwise, return the thread
+ // selected at index 0.
+ lldb::ThreadSP
+ GetSelectedThread ();
+
+ bool
+ SetSelectedThreadByID (lldb::tid_t tid, bool notify = false);
+
+ bool
+ SetSelectedThreadByIndexID (uint32_t index_id, bool notify = false);
+
+ void
+ Clear();
+
+ void
+ Flush();
+
+ void
+ Destroy();
+
+ // Note that "idx" is not the same as the "thread_index". It is a zero
+ // based index to accessing the current threads, whereas "thread_index"
+ // is a unique index assigned
+ lldb::ThreadSP
+ GetThreadAtIndex (uint32_t idx, bool can_update = true);
+
+ lldb::ThreadSP
+ FindThreadByID (lldb::tid_t tid, bool can_update = true);
+
+ lldb::ThreadSP
+ FindThreadByProtocolID (lldb::tid_t tid, bool can_update = true);
+
+ lldb::ThreadSP
+ RemoveThreadByID (lldb::tid_t tid, bool can_update = true);
+
+ lldb::ThreadSP
+ RemoveThreadByProtocolID (lldb::tid_t tid, bool can_update = true);
+
+ lldb::ThreadSP
+ FindThreadByIndexID (uint32_t index_id, bool can_update = true);
+
+ lldb::ThreadSP
+ GetThreadSPForThreadPtr (Thread *thread_ptr);
+
+ bool
+ ShouldStop (Event *event_ptr);
+
+ Vote
+ ShouldReportStop (Event *event_ptr);
+
+ Vote
+ ShouldReportRun (Event *event_ptr);
+
+ void
+ RefreshStateAfterStop ();
+
+ //------------------------------------------------------------------
+ /// The thread list asks tells all the threads it is about to resume.
+ /// If a thread can "resume" without having to resume the target, it
+ /// will return false for WillResume, and then the process will not be
+ /// restarted.
+ ///
+ /// @return
+ /// \b true instructs the process to resume normally,
+ /// \b false means start & stopped events will be generated, but
+ /// the process will not actually run. The thread must then return
+ /// the correct StopInfo when asked.
+ ///
+ //------------------------------------------------------------------
+ bool
+ WillResume ();
+
+ void
+ DidResume ();
+
+ void
+ DidStop ();
+
+ void
+ DiscardThreadPlans();
+
+ uint32_t
+ GetStopID () const;
+
+ void
+ SetStopID (uint32_t stop_id);
+
+ Mutex &
+ GetMutex ();
+
+ void
+ Update (ThreadList &rhs);
+
+protected:
+
+ void
+ SetShouldReportStop (Vote vote);
+
+ void
+ NotifySelectedThreadChanged (lldb::tid_t tid);
+
+ typedef std::vector<lldb::ThreadSP> collection;
+ //------------------------------------------------------------------
+ // Classes that inherit from Process can see and modify these
+ //------------------------------------------------------------------
+ Process *m_process; ///< The process that manages this thread list.
+ uint32_t m_stop_id; ///< The process stop ID that this thread list is valid for.
+ collection m_threads; ///< The threads for this process.
+ lldb::tid_t m_selected_tid; ///< For targets that need the notion of a current thread.
+
+private:
+ ThreadList ();
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ThreadList_h_
diff --git a/include/lldb/Target/ThreadPlan.h b/include/lldb/Target/ThreadPlan.h
new file mode 100644
index 000000000000..3c83fd1b9630
--- /dev/null
+++ b/include/lldb/Target/ThreadPlan.h
@@ -0,0 +1,658 @@
+//===-- ThreadPlan.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_h_
+#define liblldb_ThreadPlan_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/ThreadPlanTracer.h"
+#include "lldb/Target/StopInfo.h"
+
+namespace lldb_private {
+
+//------------------------------------------------------------------
+// ThreadPlan:
+// This is the pure virtual base class for thread plans.
+//
+// The thread plans provide the "atoms" of behavior that
+// all the logical process control, either directly from commands or through
+// more complex composite plans will rely on.
+//
+// Plan Stack:
+//
+// The thread maintaining a thread plan stack, and you program the actions of a particular thread
+// by pushing plans onto the plan stack.
+// There is always a "Current" plan, which is the head of the plan stack, though in some cases
+// a plan may defer to plans higher in the stack for some piece of information.
+//
+// The plan stack is never empty, there is always a Base Plan which persists through the life
+// of the running process.
+//
+//
+// Creating Plans:
+//
+// The thread plan is generally created and added to the plan stack through the QueueThreadPlanFor... API
+// in lldb::Thread. Those API's will return the plan that performs the named operation in a manner
+// appropriate for the current process. The plans in lldb/source/Target are generic
+// implementations, but a Process plugin can override them.
+//
+// ValidatePlan is then called. If it returns false, the plan is unshipped. This is a little
+// convenience which keeps us from having to error out of the constructor.
+//
+// Then the plan is added to the plan stack. When the plan is added to the plan stack its DidPush
+// will get called. This is useful if a plan wants to push any additional plans as it is constructed,
+// since you need to make sure you're already on the stack before you push additional plans.
+//
+// Completed Plans:
+//
+// When the target process stops the plans are queried, among other things, for whether their job is done.
+// If it is they are moved from the plan stack to the Completed Plan stack in reverse order from their position
+// on the plan stack (since multiple plans may be done at a given stop.) This is used primarily so that
+// the lldb::Thread::StopInfo for the thread can be set properly. If one plan pushes another to achieve part of
+// its job, but it doesn't want that sub-plan to be the one that sets the StopInfo, then call SetPrivate on the
+// sub-plan when you create it, and the Thread will pass over that plan in reporting the reason for the stop.
+//
+// Discarded plans:
+//
+// Your plan may also get discarded, i.e. moved from the plan stack to the "discarded plan stack". This can
+// happen, for instance, if the plan is calling a function and the function call crashes and you want
+// to unwind the attempt to call. So don't assume that your plan will always successfully stop. Which leads to:
+//
+// Cleaning up after your plans:
+//
+// When the plan is moved from the plan stack its WillPop method is always called, no matter why. Once it is
+// moved off the plan stack it is done, and won't get a chance to run again. So you should
+// undo anything that affects target state in this method. But be sure to leave the plan able to correctly
+// fill the StopInfo, however.
+// N.B. Don't wait to do clean up target state till the destructor, since that will usually get called when
+// the target resumes, and you want to leave the target state correct for new plans in the time between when
+// your plan gets unshipped and the next resume.
+//
+// Over the lifetime of the plan, various methods of the ThreadPlan are then called in response to changes of state in
+// the process we are debugging as follows:
+//
+// Resuming:
+//
+// When the target process is about to be restarted, the plan's WillResume method is called,
+// giving the plan a chance to prepare for the run. If WillResume returns false, then the
+// process is not restarted. Be sure to set an appropriate error value in the Process if
+// you have to do this. Note, ThreadPlans actually implement DoWillResume, WillResume wraps that call.
+//
+// Next the "StopOthers" method of all the threads are polled, and if one thread's Current plan
+// returns "true" then only that thread gets to run. If more than one returns "true" the threads that want to run solo
+// get run one by one round robin fashion. Otherwise all are let to run.
+//
+// Note, the way StopOthers is implemented, the base class implementation just asks the previous plan. So if your plan
+// has no opinion about whether it should run stopping others or not, just don't implement StopOthers, and the parent
+// will be asked.
+//
+// Finally, for each thread that is running, it run state is set to the return of RunState from the
+// thread's Current plan.
+//
+// Responding to a stop:
+//
+// When the target process stops, the plan is called in the following stages:
+//
+// First the thread asks the Current Plan if it can handle this stop by calling PlanExplainsStop.
+// If the Current plan answers "true" then it is asked if the stop should percolate all the way to the
+// user by calling the ShouldStop method. If the current plan doesn't explain the stop, then we query down
+// the plan stack for a plan that does explain the stop. The plan that does explain the stop then needs to
+// figure out what to do about the plans below it in the stack. If the stop is recoverable, then the plan that
+// understands it can just do what it needs to set up to restart, and then continue.
+// Otherwise, the plan that understood the stop should call DiscardPlanStack to clean up the stack below it.
+// Note, plans actually implement DoPlanExplainsStop, the result is cached in PlanExplainsStop so the DoPlanExplainsStop
+// itself will only get called once per stop.
+//
+// Master plans:
+//
+// In the normal case, when we decide to stop, we will collapse the plan stack up to the point of the plan that understood
+// the stop reason. However, if a plan wishes to stay on the stack after an event it didn't directly handle
+// it can designate itself a "Master" plan by responding true to IsMasterPlan, and then if it wants not to be
+// discarded, it can return true to OkayToDiscard, and it and all its dependent plans will be preserved when
+// we resume execution.
+//
+// The other effect of being a master plan is that when the Master plan is done , if it has set "OkayToDiscard" to false,
+// then it will be popped & execution will stop and return to the user. Remember that if OkayToDiscard is false, the
+// plan will be popped and control will be given to the next plan above it on the stack So setting OkayToDiscard to
+// false means the user will regain control when the MasterPlan is completed.
+//
+// Between these two controls this allows things like: a MasterPlan/DontDiscard Step Over to hit a breakpoint, stop and
+// return control to the user, but then when the user continues, the step out succeeds.
+// Even more tricky, when the breakpoint is hit, the user can continue to step in/step over/etc, and finally when they
+// continue, they will finish up the Step Over.
+//
+// FIXME: MasterPlan & OkayToDiscard aren't really orthogonal. MasterPlan designation means that this plan controls
+// it's fate and the fate of plans below it. OkayToDiscard tells whether the MasterPlan wants to stay on the stack. I
+// originally thought "MasterPlan-ness" would need to be a fixed characteristic of a ThreadPlan, in which case you needed
+// the extra control. But that doesn't seem to be true. So we should be able to convert to only MasterPlan status to mean
+// the current "MasterPlan/DontDiscard". Then no plans would be MasterPlans by default, and you would set the ones you
+// wanted to be "user level" in this way.
+//
+//
+// Actually Stopping:
+//
+// If a plan says responds "true" to ShouldStop, then it is asked if it's job is complete by calling
+// MischiefManaged. If that returns true, the thread is popped from the plan stack and added to the
+// Completed Plan Stack. Then the next plan in the stack is asked if it ShouldStop, and it returns "true",
+// it is asked if it is done, and if yes popped, and so on till we reach a plan that is not done.
+//
+// Since you often know in the ShouldStop method whether your plan is complete, as a convenience you can call
+// SetPlanComplete and the ThreadPlan implementation of MischiefManaged will return "true", without your having
+// to redo the calculation when your sub-classes MischiefManaged is called. If you call SetPlanComplete, you can
+// later use IsPlanComplete to determine whether the plan is complete. This is only a convenience for sub-classes,
+// the logic in lldb::Thread will only call MischiefManaged.
+//
+// One slightly tricky point is you have to be careful using SetPlanComplete in PlanExplainsStop because you
+// are not guaranteed that PlanExplainsStop for a plan will get called before ShouldStop gets called. If your sub-plan
+// explained the stop and then popped itself, only your ShouldStop will get called.
+//
+// If ShouldStop for any thread returns "true", then the WillStop method of the Current plan of
+// all threads will be called, the stop event is placed on the Process's public broadcaster, and
+// control returns to the upper layers of the debugger.
+//
+// Reporting the stop:
+//
+// When the process stops, the thread is given a StopReason, in the form of a StopInfo object. If there is a completed
+// plan corresponding to the stop, then the "actual" stop reason will be suppressed, and instead a StopInfoThreadPlan
+// object will be cons'ed up from the highest completed plan in the stack. However, if the plan doesn't want to be
+// the stop reason, then it can call SetPlanComplete and pass in "false" for the "success" parameter. In that case,
+// the real stop reason will be used instead. One exapmle of this is the "StepRangeStepIn" thread plan. If it stops
+// because of a crash or breakpoint hit, it wants to unship itself, because it isn't so useful to have step in keep going
+// after a breakpoint hit. But it can't be the reason for the stop or no-one would see that they had hit a breakpoint.
+//
+// Cleaning up the plan stack:
+//
+// One of the complications of MasterPlans is that you may get past the limits of a plan without triggering it to clean
+// itself up. For instance, if you are doing a MasterPlan StepOver, and hit a breakpoint in a called function, then
+// step over enough times to step out of the initial StepOver range, each of the step overs will explain the stop &
+// take themselves off the stack, but control would never be returned to the original StepOver. Eventually, the user
+// will continue, and when that continue stops, the old stale StepOver plan that was left on the stack will get woken
+// up and notice it is done. But that can leave junk on the stack for a while. To avoid that, the plans implement a
+// "IsPlanStale" method, that can check whether it is relevant anymore. On stop, after the regular plan negotiation,
+// the remaining plan stack is consulted and if any plan says it is stale, it and the plans below it are discarded from
+// the stack.
+//
+// Automatically Resuming:
+//
+// If ShouldStop for all threads returns "false", then the target process will resume. This then cycles back to
+// Resuming above.
+//
+// Reporting eStateStopped events when the target is restarted:
+//
+// If a plan decides to auto-continue the target by returning "false" from ShouldStop, then it will be asked
+// whether the Stopped event should still be reported. For instance, if you hit a breakpoint that is a User set
+// breakpoint, but the breakpoint callback said to continue the target process, you might still want to inform
+// the upper layers of lldb that the stop had happened.
+// The way this works is every thread gets to vote on whether to report the stop. If all votes are eVoteNoOpinion,
+// then the thread list will decide what to do (at present it will pretty much always suppress these stopped events.)
+// If there is an eVoteYes, then the event will be reported regardless of the other votes. If there is an eVoteNo
+// and no eVoteYes's, then the event won't be reported.
+//
+// One other little detail here, sometimes a plan will push another plan onto the plan stack to do some part of
+// the first plan's job, and it would be convenient to tell that plan how it should respond to ShouldReportStop.
+// You can do that by setting the stop_vote in the child plan when you create it.
+//
+// Suppressing the initial eStateRunning event:
+//
+// The private process running thread will take care of ensuring that only one "eStateRunning" event will be
+// delivered to the public Process broadcaster per public eStateStopped event. However there are some cases
+// where the public state of this process is eStateStopped, but a thread plan needs to restart the target, but
+// doesn't want the running event to be publically broadcast. The obvious example of this is running functions
+// by hand as part of expression evaluation. To suppress the running event return eVoteNo from ShouldReportStop,
+// to force a running event to be reported return eVoteYes, in general though you should return eVoteNoOpinion
+// which will allow the ThreadList to figure out the right thing to do.
+// The run_vote argument to the constructor works like stop_vote, and is a way for a plan to instruct a sub-plan
+// on how to respond to ShouldReportStop.
+//
+//------------------------------------------------------------------
+
+class ThreadPlan :
+ public UserID
+{
+public:
+ typedef enum
+ {
+ eAllThreads,
+ eSomeThreads,
+ eThisThread
+ } ThreadScope;
+
+ // We use these enums so that we can cast a base thread plan to it's real type without having to resort
+ // to dynamic casting.
+ typedef enum
+ {
+ eKindGeneric,
+ eKindNull,
+ eKindBase,
+ eKindCallFunction,
+ eKindStepInstruction,
+ eKindStepOut,
+ eKindStepOverBreakpoint,
+ eKindStepOverRange,
+ eKindStepInRange,
+ eKindRunToAddress,
+ eKindStepThrough,
+ eKindStepUntil,
+ eKindTestCondition
+
+ } ThreadPlanKind;
+
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ ThreadPlan (ThreadPlanKind kind,
+ const char *name,
+ Thread &thread,
+ Vote stop_vote,
+ Vote run_vote);
+
+ virtual
+ ~ThreadPlan();
+
+ //------------------------------------------------------------------
+ /// Returns the name of this thread plan.
+ ///
+ /// @return
+ /// A const char * pointer to the thread plan's name.
+ //------------------------------------------------------------------
+ const char *
+ GetName () const
+ {
+ return m_name.c_str();
+ }
+
+ //------------------------------------------------------------------
+ /// Returns the Thread that is using this thread plan.
+ ///
+ /// @return
+ /// A pointer to the thread plan's owning thread.
+ //------------------------------------------------------------------
+ Thread &
+ GetThread()
+ {
+ return m_thread;
+ }
+
+ const Thread &
+ GetThread() const
+ {
+ return m_thread;
+ }
+
+ Target &
+ GetTarget()
+ {
+ return m_thread.GetProcess()->GetTarget();
+ }
+
+ const Target &
+ GetTarget() const
+ {
+ return m_thread.GetProcess()->GetTarget();
+ }
+
+ //------------------------------------------------------------------
+ /// Print a description of this thread to the stream \a s.
+ /// \a thread.
+ ///
+ /// @param[in] s
+ /// The stream to which to print the description.
+ ///
+ /// @param[in] level
+ /// The level of description desired. Note that eDescriptionLevelBrief
+ /// will be used in the stop message printed when the plan is complete.
+ //------------------------------------------------------------------
+ virtual void
+ GetDescription (Stream *s,
+ lldb::DescriptionLevel level) = 0;
+
+ //------------------------------------------------------------------
+ /// Returns whether this plan could be successfully created.
+ ///
+ /// @param[in] error
+ /// A stream to which to print some reason why the plan could not be created.
+ /// Can be NULL.
+ ///
+ /// @return
+ /// \b true if the plan should be queued, \b false otherwise.
+ //------------------------------------------------------------------
+ virtual bool
+ ValidatePlan (Stream *error) = 0;
+
+ bool
+ TracerExplainsStop ()
+ {
+ if (!m_tracer_sp)
+ return false;
+ else
+ return m_tracer_sp->TracerExplainsStop();
+ }
+
+
+ lldb::StateType
+ RunState ();
+
+ bool
+ PlanExplainsStop (Event *event_ptr);
+
+ virtual bool
+ ShouldStop (Event *event_ptr) = 0;
+
+ virtual bool
+ ShouldAutoContinue (Event *event_ptr)
+ {
+ return false;
+ }
+
+ // Whether a "stop class" event should be reported to the "outside world". In general
+ // if a thread plan is active, events should not be reported.
+
+ virtual Vote
+ ShouldReportStop (Event *event_ptr);
+
+ virtual Vote
+ ShouldReportRun (Event *event_ptr);
+
+ virtual void
+ SetStopOthers (bool new_value);
+
+ virtual bool
+ StopOthers ();
+
+ // This is the wrapper for DoWillResume that does generic ThreadPlan logic, then
+ // calls DoWillResume.
+ bool
+ WillResume (lldb::StateType resume_state, bool current_plan);
+
+ virtual bool
+ WillStop () = 0;
+
+ bool
+ IsMasterPlan()
+ {
+ return m_is_master_plan;
+ }
+
+ bool
+ SetIsMasterPlan (bool value)
+ {
+ bool old_value = m_is_master_plan;
+ m_is_master_plan = value;
+ return old_value;
+ }
+
+ virtual bool
+ OkayToDiscard();
+
+ void
+ SetOkayToDiscard (bool value)
+ {
+ m_okay_to_discard = value;
+ }
+
+ // The base class MischiefManaged does some cleanup - so you have to call it
+ // in your MischiefManaged derived class.
+ virtual bool
+ MischiefManaged ();
+
+ virtual void
+ ThreadDestroyed ()
+ {
+ // Any cleanup that a plan might want to do in case the thread goes away
+ // in the middle of the plan being queued on a thread can be done here.
+ }
+
+ bool
+ GetPrivate ()
+ {
+ return m_plan_private;
+ }
+
+ void
+ SetPrivate (bool input)
+ {
+ m_plan_private = input;
+ }
+
+ virtual void
+ DidPush();
+
+ virtual void
+ WillPop();
+
+ // This pushes a plan onto the plan stack of the current plan's thread.
+ void
+ PushPlan (lldb::ThreadPlanSP &thread_plan_sp)
+ {
+ m_thread.PushPlan (thread_plan_sp);
+ }
+
+ ThreadPlanKind GetKind() const
+ {
+ return m_kind;
+ }
+
+ bool
+ IsPlanComplete();
+
+ void
+ SetPlanComplete (bool success = true);
+
+ virtual bool
+ IsPlanStale ()
+ {
+ return false;
+ }
+
+ bool
+ PlanSucceeded ()
+ {
+ return m_plan_succeeded;
+ }
+
+ virtual bool
+ IsBasePlan()
+ {
+ return false;
+ }
+
+ lldb::ThreadPlanTracerSP &
+ GetThreadPlanTracer()
+ {
+ return m_tracer_sp;
+ }
+
+ void
+ SetThreadPlanTracer (lldb::ThreadPlanTracerSP new_tracer_sp)
+ {
+ m_tracer_sp = new_tracer_sp;
+ }
+
+ void
+ DoTraceLog ()
+ {
+ if (m_tracer_sp && m_tracer_sp->TracingEnabled())
+ m_tracer_sp->Log();
+ }
+
+ // Some thread plans hide away the actual stop info which caused any particular stop. For
+ // instance the ThreadPlanCallFunction restores the original stop reason so that stopping and
+ // calling a few functions won't lose the history of the run.
+ // This call can be implemented to get you back to the real stop info.
+ virtual lldb::StopInfoSP
+ GetRealStopInfo ()
+ {
+ return m_thread.GetStopInfo ();
+ }
+
+ virtual lldb::ValueObjectSP
+ GetReturnValueObject ()
+ {
+ return lldb::ValueObjectSP();
+ }
+
+ // If a thread plan stores the state before it was run, then you might
+ // want to restore the state when it is done. This will do that job.
+ // This is mostly useful for artificial plans like CallFunction plans.
+
+ virtual bool
+ RestoreThreadState()
+ {
+ // Nothing to do in general.
+ return true;
+ }
+
+ virtual bool
+ IsVirtualStep()
+ {
+ return false;
+ }
+
+protected:
+ //------------------------------------------------------------------
+ // Classes that inherit from ThreadPlan can see and modify these
+ //------------------------------------------------------------------
+
+ virtual bool
+ DoWillResume (lldb::StateType resume_state, bool current_plan) { return true; };
+
+ virtual bool
+ DoPlanExplainsStop (Event *event_ptr) = 0;
+
+ // This gets the previous plan to the current plan (for forwarding requests).
+ // This is mostly a formal requirement, it allows us to make the Thread's
+ // GetPreviousPlan protected, but only friend ThreadPlan to thread.
+
+ ThreadPlan *
+ GetPreviousPlan ()
+ {
+ return m_thread.GetPreviousPlan (this);
+ }
+
+ // This forwards the private Thread::GetPrivateStopInfo which is generally what
+ // ThreadPlan's need to know.
+
+ lldb::StopInfoSP
+ GetPrivateStopInfo()
+ {
+ return m_thread.GetPrivateStopInfo ();
+ }
+
+ void
+ SetStopInfo (lldb::StopInfoSP stop_reason_sp)
+ {
+ m_thread.SetStopInfo (stop_reason_sp);
+ }
+
+ void
+ CachePlanExplainsStop (bool does_explain)
+ {
+ m_cached_plan_explains_stop = does_explain ? eLazyBoolYes : eLazyBoolNo;
+ }
+
+ LazyBool
+ GetCachedPlanExplainsStop () const
+ {
+ return m_cached_plan_explains_stop;
+ }
+
+ virtual lldb::StateType
+ GetPlanRunState () = 0;
+
+ Thread &m_thread;
+ Vote m_stop_vote;
+ Vote m_run_vote;
+
+private:
+ //------------------------------------------------------------------
+ // For ThreadPlan only
+ //------------------------------------------------------------------
+ static lldb::user_id_t GetNextID ();
+
+ ThreadPlanKind m_kind;
+ std::string m_name;
+ Mutex m_plan_complete_mutex;
+ LazyBool m_cached_plan_explains_stop;
+ bool m_plan_complete;
+ bool m_plan_private;
+ bool m_okay_to_discard;
+ bool m_is_master_plan;
+ bool m_plan_succeeded;
+
+ lldb::ThreadPlanTracerSP m_tracer_sp;
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(ThreadPlan);
+};
+
+//----------------------------------------------------------------------
+// ThreadPlanNull:
+// Threads are assumed to always have at least one plan on the plan stack.
+// This is put on the plan stack when a thread is destroyed so that if you
+// accidentally access a thread after it is destroyed you won't crash.
+// But asking questions of the ThreadPlanNull is definitely an error.
+//----------------------------------------------------------------------
+
+class ThreadPlanNull : public ThreadPlan
+{
+public:
+ ThreadPlanNull (Thread &thread);
+ virtual ~ThreadPlanNull ();
+
+ 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
+ IsBasePlan()
+ {
+ return true;
+ }
+
+ virtual bool
+ OkayToDiscard ()
+ {
+ return false;
+ }
+
+protected:
+ virtual bool
+ DoPlanExplainsStop (Event *event_ptr);
+
+ virtual lldb::StateType
+ GetPlanRunState ();
+
+};
+
+
+} // namespace lldb_private
+
+#endif // liblldb_ThreadPlan_h_
diff --git a/include/lldb/Target/ThreadPlanBase.h b/include/lldb/Target/ThreadPlanBase.h
new file mode 100644
index 000000000000..69959e12f848
--- /dev/null
+++ b/include/lldb/Target/ThreadPlanBase.h
@@ -0,0 +1,71 @@
+//===-- ThreadPlanBase.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_ThreadPlanFundamental_h_
+#define liblldb_ThreadPlanFundamental_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
+
+namespace lldb_private {
+
+
+//------------------------------------------------------------------
+// Base thread plans:
+// This is the generic version of the bottom most plan on the plan stack. It should
+// be able to handle generic breakpoint hitting, and signals and exceptions.
+//------------------------------------------------------------------
+
+class ThreadPlanBase : public ThreadPlan
+{
+friend class Process; // RunThreadPlan manages "stopper" base plans.
+public:
+ virtual ~ThreadPlanBase ();
+
+ virtual void GetDescription (Stream *s, lldb::DescriptionLevel level);
+ virtual bool ValidatePlan (Stream *error);
+ virtual bool ShouldStop (Event *event_ptr);
+ virtual Vote ShouldReportStop (Event *event_ptr);
+ virtual bool StopOthers ();
+ virtual lldb::StateType GetPlanRunState ();
+ virtual bool WillStop ();
+ virtual bool MischiefManaged ();
+
+ virtual bool OkayToDiscard()
+ {
+ return false;
+ }
+
+ virtual bool
+ IsBasePlan()
+ {
+ return true;
+ }
+
+protected:
+ virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan);
+ virtual bool DoPlanExplainsStop (Event *event_ptr);
+ ThreadPlanBase (Thread &thread);
+
+private:
+ friend lldb::ThreadPlanSP
+ Thread::QueueFundamentalPlan(bool abort_other_plans);
+
+ DISALLOW_COPY_AND_ASSIGN (ThreadPlanBase);
+};
+
+
+} // namespace lldb_private
+
+#endif // liblldb_ThreadPlanFundamental_h_
diff --git a/include/lldb/Target/ThreadPlanCallFunction.h b/include/lldb/Target/ThreadPlanCallFunction.h
new file mode 100644
index 000000000000..d747706c6393
--- /dev/null
+++ b/include/lldb/Target/ThreadPlanCallFunction.h
@@ -0,0 +1,193 @@
+//===-- ThreadPlanCallFunction.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_ThreadPlanCallFunction_h_
+#define liblldb_ThreadPlanCallFunction_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
+
+namespace lldb_private {
+
+class ThreadPlanCallFunction : public ThreadPlan
+{
+ // Create a thread plan to call a function at the address passed in the "function"
+ // argument. If you plan to call GetReturnValueObject, then pass in the
+ // return type, otherwise just pass in an invalid ClangASTType.
+public:
+ ThreadPlanCallFunction (Thread &thread,
+ const Address &function,
+ const ClangASTType &return_type,
+ lldb::addr_t arg,
+ bool stop_other_threads,
+ bool unwind_on_error = true,
+ bool ignore_breakpoints = false,
+ lldb::addr_t *this_arg = 0,
+ lldb::addr_t *cmd_arg = 0);
+
+ ThreadPlanCallFunction (Thread &thread,
+ const Address &function,
+ const ClangASTType &return_type,
+ bool stop_other_threads,
+ bool unwind_on_error,
+ bool ignore_breakpoints,
+ lldb::addr_t *arg1_ptr = NULL,
+ lldb::addr_t *arg2_ptr = NULL,
+ lldb::addr_t *arg3_ptr = NULL,
+ lldb::addr_t *arg4_ptr = NULL,
+ lldb::addr_t *arg5_ptr = NULL,
+ lldb::addr_t *arg6_ptr = NULL);
+
+ virtual
+ ~ThreadPlanCallFunction ();
+
+ virtual void
+ GetDescription (Stream *s, lldb::DescriptionLevel level);
+
+ virtual bool
+ ValidatePlan (Stream *error);
+
+ virtual bool
+ ShouldStop (Event *event_ptr);
+
+ virtual Vote
+ ShouldReportStop(Event *event_ptr);
+
+ virtual bool
+ StopOthers ();
+
+ virtual void
+ SetStopOthers (bool new_value);
+
+ virtual lldb::StateType
+ GetPlanRunState ();
+
+ virtual void
+ DidPush ();
+
+ virtual bool
+ WillStop ();
+
+ virtual bool
+ MischiefManaged ();
+
+ // To get the return value from a function call you must create a
+ // lldb::ValueSP that contains a valid clang type in its context and call
+ // RequestReturnValue. The ValueSP will be stored and when the function is
+ // done executing, the object will check if there is a requested return
+ // value. If there is, the return value will be retrieved using the
+ // ABI::GetReturnValue() for the ABI in the process. Then after the thread
+ // plan is complete, you can call "GetReturnValue()" to retrieve the value
+ // that was extracted.
+
+ virtual lldb::ValueObjectSP
+ GetReturnValueObject ()
+ {
+ return m_return_valobj_sp;
+ }
+
+ // Return the stack pointer that the function received
+ // on entry. Any stack address below this should be
+ // considered invalid after the function has been
+ // cleaned up.
+ lldb::addr_t
+ GetFunctionStackPointer()
+ {
+ return m_function_sp;
+ }
+
+ // Classes that derive from ClangFunction, and implement
+ // their own WillPop methods should call this so that the
+ // thread state gets restored if the plan gets discarded.
+ virtual void
+ WillPop ();
+
+ // If the thread plan stops mid-course, this will be the stop reason that interrupted us.
+ // Once DoTakedown is called, this will be the real stop reason at the end of the function call.
+ // If it hasn't been set for one or the other of these reasons, we'll return the PrivateStopReason.
+ // This is needed because we want the CallFunction thread plans not to show up as the stop reason.
+ // But if something bad goes wrong, it is nice to be able to tell the user what really happened.
+
+ virtual lldb::StopInfoSP
+ GetRealStopInfo()
+ {
+ if (m_real_stop_info_sp)
+ return m_real_stop_info_sp;
+ else
+ return GetPrivateStopInfo ();
+ }
+
+ lldb::addr_t
+ GetStopAddress ()
+ {
+ return m_stop_address;
+ }
+
+ virtual bool
+ RestoreThreadState();
+
+protected:
+ void ReportRegisterState (const char *message);
+
+ virtual bool
+ DoPlanExplainsStop (Event *event_ptr);
+
+private:
+
+ bool
+ ConstructorSetup (Thread &thread,
+ ABI *& abi,
+ lldb::addr_t &start_load_addr,
+ lldb::addr_t &function_load_addr);
+
+ void
+ DoTakedown (bool success);
+
+ void
+ SetBreakpoints ();
+
+ void
+ ClearBreakpoints ();
+
+ bool
+ BreakpointsExplainStop ();
+
+ bool m_valid;
+ bool m_stop_other_threads;
+ Address m_function_addr;
+ Address m_start_addr;
+ lldb::addr_t m_function_sp;
+ Thread::RegisterCheckpoint m_register_backup;
+ lldb::ThreadPlanSP m_subplan_sp;
+ LanguageRuntime *m_cxx_language_runtime;
+ LanguageRuntime *m_objc_language_runtime;
+ Thread::ThreadStateCheckpoint m_stored_thread_state;
+ lldb::StopInfoSP m_real_stop_info_sp; // In general we want to hide call function
+ // thread plans, but for reporting purposes,
+ // it's nice to know the real stop reason.
+ // This gets set in DoTakedown.
+ StreamString m_constructor_errors;
+ ClangASTType m_return_type;
+ lldb::ValueObjectSP m_return_valobj_sp; // If this contains a valid pointer, use the ABI to extract values when complete
+ bool m_takedown_done; // We want to ensure we only do the takedown once. This ensures that.
+ lldb::addr_t m_stop_address; // This is the address we stopped at. Also set in DoTakedown;
+ bool m_unwind_on_error;
+ bool m_ignore_breakpoints;
+
+ DISALLOW_COPY_AND_ASSIGN (ThreadPlanCallFunction);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ThreadPlanCallFunction_h_
diff --git a/include/lldb/Target/ThreadPlanCallUserExpression.h b/include/lldb/Target/ThreadPlanCallUserExpression.h
new file mode 100644
index 000000000000..7a7ec33049e0
--- /dev/null
+++ b/include/lldb/Target/ThreadPlanCallUserExpression.h
@@ -0,0 +1,65 @@
+//===-- ThreadPlanCallUserExpression.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_ThreadPlanCallUserExpression_h_
+#define liblldb_ThreadPlanCallUserExpression_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Expression/ClangUserExpression.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanCallFunction.h"
+
+namespace lldb_private {
+
+class ThreadPlanCallUserExpression : public ThreadPlanCallFunction
+{
+public:
+ ThreadPlanCallUserExpression (Thread &thread,
+ Address &function,
+ lldb::addr_t arg,
+ bool stop_other_threads,
+ bool unwind_on_error,
+ bool ignore_breakpoints,
+ lldb::addr_t *this_arg,
+ lldb::addr_t *cmd_arg,
+ ClangUserExpression::ClangUserExpressionSP &user_expression_sp);
+
+ virtual
+ ~ThreadPlanCallUserExpression ();
+
+ virtual void
+ GetDescription (Stream *s, lldb::DescriptionLevel level);
+
+ virtual void
+ WillPop ()
+ {
+ ThreadPlanCallFunction::WillPop();
+ if (m_user_expression_sp)
+ m_user_expression_sp.reset();
+ }
+
+ virtual lldb::StopInfoSP
+ GetRealStopInfo();
+
+protected:
+private:
+ ClangUserExpression::ClangUserExpressionSP m_user_expression_sp; // This is currently just used to ensure the
+ // User expression the initiated this ThreadPlan
+ // lives as long as the thread plan does.
+ DISALLOW_COPY_AND_ASSIGN (ThreadPlanCallUserExpression);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ThreadPlanCallUserExpression_h_
diff --git a/include/lldb/Target/ThreadPlanRunToAddress.h b/include/lldb/Target/ThreadPlanRunToAddress.h
new file mode 100644
index 000000000000..d94820668017
--- /dev/null
+++ b/include/lldb/Target/ThreadPlanRunToAddress.h
@@ -0,0 +1,85 @@
+//===-- ThreadPlanRunToAddress.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_ThreadPlanRunToAddress_h_
+#define liblldb_ThreadPlanRunToAddress_h_
+
+// C Includes
+// C++ Includes
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/ThreadPlan.h"
+
+namespace lldb_private {
+
+class ThreadPlanRunToAddress : public ThreadPlan
+{
+public:
+ ThreadPlanRunToAddress (Thread &thread,
+ Address &address,
+ bool stop_others);
+
+ ThreadPlanRunToAddress (Thread &thread,
+ lldb::addr_t address,
+ bool stop_others);
+
+ ThreadPlanRunToAddress (Thread &thread,
+ const std::vector<lldb::addr_t> &addresses,
+ bool stop_others);
+
+
+ virtual
+ ~ThreadPlanRunToAddress ();
+
+ virtual void
+ GetDescription (Stream *s, lldb::DescriptionLevel level);
+
+ virtual bool
+ ValidatePlan (Stream *error);
+
+ virtual bool
+ ShouldStop (Event *event_ptr);
+
+ virtual bool
+ StopOthers ();
+
+ virtual void
+ SetStopOthers (bool new_value);
+
+ virtual lldb::StateType
+ GetPlanRunState ();
+
+ virtual bool
+ WillStop ();
+
+ virtual bool
+ MischiefManaged ();
+
+protected:
+ virtual bool
+ DoPlanExplainsStop (Event *event_ptr);
+
+ void SetInitialBreakpoints();
+ bool AtOurAddress();
+private:
+ bool m_stop_others;
+ std::vector<lldb::addr_t> m_addresses; // This is the address we are going to run to.
+ // TODO: Would it be useful to have multiple addresses?
+ std::vector<lldb::break_id_t> m_break_ids; // This is the breakpoint we are using to stop us at m_address.
+
+ DISALLOW_COPY_AND_ASSIGN (ThreadPlanRunToAddress);
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ThreadPlanRunToAddress_h_
diff --git a/include/lldb/Target/ThreadPlanShouldStopHere.h b/include/lldb/Target/ThreadPlanShouldStopHere.h
new file mode 100644
index 000000000000..62068b78ae4e
--- /dev/null
+++ b/include/lldb/Target/ThreadPlanShouldStopHere.h
@@ -0,0 +1,94 @@
+//===-- ThreadPlanShouldStopHere.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_ThreadPlanShouldStopHere_h_
+#define liblldb_ThreadPlanShouldStopHere_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Target/ThreadPlan.h"
+
+namespace lldb_private {
+
+// This is an interface that ThreadPlans can adopt to allow flexible modifications of the behavior
+// when a thread plan comes to a place where it would ordinarily stop. If such modification makes
+// sense for your plan, inherit from this class, and when you would be about to stop (in your ShouldStop
+// method), call InvokeShouldStopHereCallback, and if that returns a non-NULL plan, execute that
+// plan instead of stopping.
+//
+// The classic example of the use of this is ThreadPlanStepInRange not stopping in frames that have
+// no debug information.
+//
+// This class also defines a set of flags to control general aspects of this "ShouldStop" behavior.
+// A class implementing this protocol needs to define a default set of flags, and can provide access to
+// changing that default flag set if it wishes.
+
+class ThreadPlanShouldStopHere
+{
+public:
+ enum
+ {
+ eNone = 0,
+ eAvoidInlines = (1 << 0),
+ eAvoidNoDebug = (1 << 1)
+ };
+
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ ThreadPlanShouldStopHere (ThreadPlan *owner,
+ ThreadPlanShouldStopHereCallback callback = NULL,
+ void *baton = NULL);
+ virtual
+ ~ThreadPlanShouldStopHere();
+
+ void
+ SetShouldStopHereCallback (ThreadPlanShouldStopHereCallback callback, void *baton);
+
+ lldb::ThreadPlanSP
+ InvokeShouldStopHereCallback ();
+
+ lldb_private::Flags &
+ GetFlags ()
+ {
+ return m_flags;
+ }
+
+ const lldb_private::Flags &
+ GetFlags () const
+ {
+ return m_flags;
+ }
+
+protected:
+ // Implement this, and call it in the plan's constructor to set the default flags.
+ virtual void SetFlagsToDefault () = 0;
+
+ //------------------------------------------------------------------
+ // Classes that inherit from ThreadPlanShouldStopHere can see and modify these
+ //------------------------------------------------------------------
+ ThreadPlanShouldStopHereCallback m_callback;
+ void * m_baton;
+ ThreadPlan *m_owner;
+ lldb_private::Flags m_flags;
+
+private:
+ //------------------------------------------------------------------
+ // For ThreadPlanShouldStopHere only
+ //------------------------------------------------------------------
+
+ DISALLOW_COPY_AND_ASSIGN (ThreadPlanShouldStopHere);
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ThreadPlanShouldStopHere_h_
diff --git a/include/lldb/Target/ThreadPlanStepInRange.h b/include/lldb/Target/ThreadPlanStepInRange.h
new file mode 100644
index 000000000000..dbc8446b2e18
--- /dev/null
+++ b/include/lldb/Target/ThreadPlanStepInRange.h
@@ -0,0 +1,110 @@
+//===-- ThreadPlanStepInRange.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_ThreadPlanStepInRange_h_
+#define liblldb_ThreadPlanStepInRange_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/AddressRange.h"
+#include "lldb/Target/StackID.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlanStepRange.h"
+#include "lldb/Target/ThreadPlanShouldStopHere.h"
+
+namespace lldb_private {
+
+class ThreadPlanStepInRange :
+ public ThreadPlanStepRange,
+ public ThreadPlanShouldStopHere
+{
+public:
+ ThreadPlanStepInRange (Thread &thread,
+ const AddressRange &range,
+ const SymbolContext &addr_context,
+ lldb::RunMode stop_others);
+
+ ThreadPlanStepInRange (Thread &thread,
+ const AddressRange &range,
+ const SymbolContext &addr_context,
+ const char *step_into_function_name,
+ lldb::RunMode stop_others);
+
+ virtual
+ ~ThreadPlanStepInRange ();
+
+ virtual void
+ GetDescription (Stream *s, lldb::DescriptionLevel level);
+
+ virtual bool
+ ShouldStop (Event *event_ptr);
+
+ void SetAvoidRegexp(const char *name);
+
+ void SetStepInTarget (const char *target)
+ {
+ m_step_into_target.SetCString(target);
+ }
+
+ static lldb::ThreadPlanSP
+ DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, void *baton);
+
+ static void
+ SetDefaultFlagValue (uint32_t new_value);
+
+ bool
+ IsVirtualStep();
+
+protected:
+ virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan);
+
+ virtual bool
+ DoPlanExplainsStop (Event *event_ptr);
+
+ virtual void
+ SetFlagsToDefault ();
+
+ bool
+ FrameMatchesAvoidRegexp ();
+
+private:
+
+ friend lldb::ThreadPlanSP
+ Thread::QueueThreadPlanForStepOverRange (bool abort_other_plans,
+ const AddressRange &range,
+ const SymbolContext &addr_context,
+ lldb::RunMode stop_others);
+ friend lldb::ThreadPlanSP
+ Thread::QueueThreadPlanForStepInRange (bool abort_other_plans,
+ const AddressRange &range,
+ const SymbolContext &addr_context,
+ const char *step_in_target,
+ lldb::RunMode stop_others,
+ bool avoid_code_without_debug_info);
+
+
+ // Need an appropriate marker for the current stack so we can tell step out
+ // from step in.
+
+ static uint32_t s_default_flag_values;
+ lldb::ThreadPlanSP m_sub_plan_sp; // Keep track of the last plan we were running. If it fails, we should stop.
+ std::unique_ptr<RegularExpression> m_avoid_regexp_ap;
+ bool m_step_past_prologue; // FIXME: For now hard-coded to true, we could put a switch in for this if there's
+ // demand for that.
+ bool m_virtual_step; // true if we've just done a "virtual step", i.e. just moved the inline stack depth.
+ ConstString m_step_into_target;
+ DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepInRange);
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ThreadPlanStepInRange_h_
diff --git a/include/lldb/Target/ThreadPlanStepInstruction.h b/include/lldb/Target/ThreadPlanStepInstruction.h
new file mode 100644
index 000000000000..eb4a64bcbc84
--- /dev/null
+++ b/include/lldb/Target/ThreadPlanStepInstruction.h
@@ -0,0 +1,64 @@
+//===-- ThreadPlanStepInstruction.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_ThreadPlanStepInstruction_h_
+#define liblldb_ThreadPlanStepInstruction_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
+
+namespace lldb_private {
+
+class ThreadPlanStepInstruction : public ThreadPlan
+{
+public:
+ virtual ~ThreadPlanStepInstruction ();
+
+ virtual void GetDescription (Stream *s, lldb::DescriptionLevel level);
+ virtual bool ValidatePlan (Stream *error);
+ virtual bool ShouldStop (Event *event_ptr);
+ virtual bool StopOthers ();
+ virtual lldb::StateType GetPlanRunState ();
+ virtual bool WillStop ();
+ virtual bool MischiefManaged ();
+
+protected:
+ virtual bool DoPlanExplainsStop (Event *event_ptr);
+
+ ThreadPlanStepInstruction (Thread &thread,
+ bool step_over,
+ bool stop_others,
+ Vote stop_vote,
+ Vote run_vote);
+
+private:
+ friend lldb::ThreadPlanSP
+ Thread::QueueThreadPlanForStepSingleInstruction (bool step_over, bool abort_other_plans, bool stop_other_threads);
+
+ lldb::addr_t m_instruction_addr;
+ bool m_stop_other_threads;
+ bool m_step_over;
+ // These two are used only for the step over case.
+ bool m_start_has_symbol;
+ StackID m_stack_id;
+ StackID m_parent_frame_id;
+
+ DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepInstruction);
+
+};
+
+
+} // namespace lldb_private
+
+#endif // liblldb_ThreadPlanStepInstruction_h_
diff --git a/include/lldb/Target/ThreadPlanStepOut.h b/include/lldb/Target/ThreadPlanStepOut.h
new file mode 100644
index 000000000000..2737978a4edc
--- /dev/null
+++ b/include/lldb/Target/ThreadPlanStepOut.h
@@ -0,0 +1,90 @@
+//===-- ThreadPlanStepOut.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_ThreadPlanStepOut_h_
+#define liblldb_ThreadPlanStepOut_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
+
+namespace lldb_private {
+
+class ThreadPlanStepOut : public ThreadPlan
+{
+public:
+ ThreadPlanStepOut (Thread &thread,
+ SymbolContext *addr_context,
+ bool first_insn,
+ bool stop_others,
+ Vote stop_vote,
+ Vote run_vote,
+ uint32_t frame_idx);
+
+ virtual ~ThreadPlanStepOut ();
+
+ virtual void GetDescription (Stream *s, lldb::DescriptionLevel level);
+ virtual bool ValidatePlan (Stream *error);
+ virtual bool ShouldStop (Event *event_ptr);
+ virtual bool StopOthers ();
+ virtual lldb::StateType GetPlanRunState ();
+ virtual bool WillStop ();
+ virtual bool MischiefManaged ();
+ virtual void DidPush();
+ virtual bool IsPlanStale();
+
+ virtual lldb::ValueObjectSP GetReturnValueObject()
+ {
+ return m_return_valobj_sp;
+ }
+
+protected:
+ virtual bool DoPlanExplainsStop (Event *event_ptr);
+ virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan);
+ bool QueueInlinedStepPlan (bool queue_now);
+
+private:
+ SymbolContext *m_step_from_context;
+ lldb::addr_t m_step_from_insn;
+ StackID m_step_out_to_id;
+ StackID m_immediate_step_from_id;
+ lldb::break_id_t m_return_bp_id;
+ lldb::addr_t m_return_addr;
+ bool m_first_insn;
+ bool m_stop_others;
+ lldb::ThreadPlanSP m_step_through_inline_plan_sp;
+ lldb::ThreadPlanSP m_step_out_plan_sp;
+ Function *m_immediate_step_from_function;
+ lldb::ValueObjectSP m_return_valobj_sp;
+
+ friend lldb::ThreadPlanSP
+ Thread::QueueThreadPlanForStepOut (bool abort_other_plans,
+ SymbolContext *addr_context,
+ bool first_insn,
+ bool stop_others,
+ Vote stop_vote,
+ Vote run_vote,
+ uint32_t frame_idx);
+
+ // Need an appropriate marker for the current stack so we can tell step out
+ // from step in.
+
+ void
+ CalculateReturnValue();
+
+ DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepOut);
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ThreadPlanStepOut_h_
diff --git a/include/lldb/Target/ThreadPlanStepOverBreakpoint.h b/include/lldb/Target/ThreadPlanStepOverBreakpoint.h
new file mode 100644
index 000000000000..41cac5c9b0b4
--- /dev/null
+++ b/include/lldb/Target/ThreadPlanStepOverBreakpoint.h
@@ -0,0 +1,57 @@
+//===-- ThreadPlanStepOverBreakpoint.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_ThreadPlanStepOverBreakpoint_h_
+#define liblldb_ThreadPlanStepOverBreakpoint_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
+
+namespace lldb_private {
+
+class ThreadPlanStepOverBreakpoint : public ThreadPlan
+{
+public:
+ virtual ~ThreadPlanStepOverBreakpoint ();
+
+ ThreadPlanStepOverBreakpoint (Thread &thread);
+ virtual void GetDescription (Stream *s, lldb::DescriptionLevel level);
+ virtual bool ValidatePlan (Stream *error);
+ virtual bool ShouldStop (Event *event_ptr);
+ virtual bool StopOthers ();
+ virtual lldb::StateType GetPlanRunState ();
+ virtual bool WillStop ();
+ virtual bool MischiefManaged ();
+ virtual void ThreadDestroyed ();
+ void SetAutoContinue (bool do_it);
+ virtual bool ShouldAutoContinue(Event *event_ptr);
+
+protected:
+ virtual bool DoPlanExplainsStop (Event *event_ptr);
+ virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan);
+
+ void ReenableBreakpointSite ();
+private:
+
+ lldb::addr_t m_breakpoint_addr;
+ lldb::user_id_t m_breakpoint_site_id;
+ bool m_auto_continue;
+ bool m_reenabled_breakpoint_site;
+
+ DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepOverBreakpoint);
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ThreadPlanStepOverBreakpoint_h_
diff --git a/include/lldb/Target/ThreadPlanStepOverRange.h b/include/lldb/Target/ThreadPlanStepOverRange.h
new file mode 100644
index 000000000000..de9e66829dc7
--- /dev/null
+++ b/include/lldb/Target/ThreadPlanStepOverRange.h
@@ -0,0 +1,52 @@
+//===-- ThreadPlanStepOverRange.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_ThreadPlanStepOverRange_h_
+#define liblldb_ThreadPlanStepOverRange_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/AddressRange.h"
+#include "lldb/Target/StackID.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlanStepRange.h"
+
+namespace lldb_private {
+
+class ThreadPlanStepOverRange : public ThreadPlanStepRange
+{
+public:
+
+ ThreadPlanStepOverRange (Thread &thread,
+ const AddressRange &range,
+ const SymbolContext &addr_context,
+ lldb::RunMode stop_others);
+
+ virtual ~ThreadPlanStepOverRange ();
+
+ virtual void GetDescription (Stream *s, lldb::DescriptionLevel level);
+ virtual bool ShouldStop (Event *event_ptr);
+
+protected:
+ virtual bool DoPlanExplainsStop (Event *event_ptr);
+ virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan);
+
+private:
+
+ bool m_first_resume;
+
+ DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepOverRange);
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ThreadPlanStepOverRange_h_
diff --git a/include/lldb/Target/ThreadPlanStepRange.h b/include/lldb/Target/ThreadPlanStepRange.h
new file mode 100644
index 000000000000..486fd6528390
--- /dev/null
+++ b/include/lldb/Target/ThreadPlanStepRange.h
@@ -0,0 +1,94 @@
+//===-- ThreadPlanStepRange.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_ThreadPlanStepRange_h_
+#define liblldb_ThreadPlanStepRange_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/AddressRange.h"
+#include "lldb/Target/StackID.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanShouldStopHere.h"
+
+namespace lldb_private {
+
+class ThreadPlanStepRange : public ThreadPlan
+{
+public:
+ ThreadPlanStepRange (ThreadPlanKind kind,
+ const char *name,
+ Thread &thread,
+ const AddressRange &range,
+ const SymbolContext &addr_context,
+ lldb::RunMode stop_others);
+
+ virtual ~ThreadPlanStepRange ();
+
+ virtual void GetDescription (Stream *s, lldb::DescriptionLevel level) = 0;
+ virtual bool ValidatePlan (Stream *error);
+ virtual bool ShouldStop (Event *event_ptr) = 0;
+ virtual Vote ShouldReportStop (Event *event_ptr);
+ virtual bool StopOthers ();
+ virtual lldb::StateType GetPlanRunState ();
+ virtual bool WillStop ();
+ virtual bool MischiefManaged ();
+ virtual void DidPush ();
+ virtual bool IsPlanStale ();
+
+
+ void AddRange(const AddressRange &new_range);
+
+protected:
+
+ bool InRange();
+ lldb::FrameComparison CompareCurrentFrameToStartFrame();
+ bool InSymbol();
+ void DumpRanges (Stream *s);
+
+ Disassembler *
+ GetDisassembler ();
+
+ InstructionList *
+ GetInstructionsForAddress(lldb::addr_t addr, size_t &range_index, size_t &insn_offset);
+
+ // Pushes a plan to proceed through the next section of instructions in the range - usually just a RunToAddress
+ // plan to run to the next branch. Returns true if it pushed such a plan. If there was no available 'quick run'
+ // plan, then just single step.
+ bool
+ SetNextBranchBreakpoint ();
+
+ void
+ ClearNextBranchBreakpoint();
+
+ bool
+ NextRangeBreakpointExplainsStop (lldb::StopInfoSP stop_info_sp);
+
+ SymbolContext m_addr_context;
+ std::vector<AddressRange> m_address_ranges;
+ lldb::RunMode m_stop_others;
+ StackID m_stack_id; // Use the stack ID so we can tell step out from step in.
+ bool m_no_more_plans; // Need this one so we can tell if we stepped into a call,
+ // but can't continue, in which case we are done.
+ 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;
+
+private:
+ std::vector<lldb::DisassemblerSP> m_instruction_ranges;
+ DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepRange);
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ThreadPlanStepRange_h_
diff --git a/include/lldb/Target/ThreadPlanStepThrough.h b/include/lldb/Target/ThreadPlanStepThrough.h
new file mode 100644
index 000000000000..16979663eb1b
--- /dev/null
+++ b/include/lldb/Target/ThreadPlanStepThrough.h
@@ -0,0 +1,71 @@
+//===-- ThreadPlanStepThrough.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_ThreadPlanStepThrough_h_
+#define liblldb_ThreadPlanStepThrough_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
+
+namespace lldb_private {
+
+class ThreadPlanStepThrough : public ThreadPlan
+{
+public:
+ virtual ~ThreadPlanStepThrough ();
+
+ virtual void GetDescription (Stream *s, lldb::DescriptionLevel level);
+ virtual bool ValidatePlan (Stream *error);
+ virtual bool ShouldStop (Event *event_ptr);
+ virtual bool StopOthers ();
+ virtual lldb::StateType GetPlanRunState ();
+ virtual bool WillStop ();
+ virtual bool MischiefManaged ();
+ virtual void DidPush();
+
+protected:
+ virtual bool DoPlanExplainsStop (Event *event_ptr);
+ virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan);
+
+ ThreadPlanStepThrough (Thread &thread,
+ StackID &return_stack_id,
+ bool stop_others);
+
+ void
+ LookForPlanToStepThroughFromCurrentPC ();
+
+ bool
+ HitOurBackstopBreakpoint();
+
+private:
+ friend lldb::ThreadPlanSP
+ Thread::QueueThreadPlanForStepThrough (StackID &return_stack_id,
+ bool abort_other_plans,
+ bool stop_others);
+
+ void ClearBackstopBreakpoint();
+
+ lldb::ThreadPlanSP m_sub_plan_sp;
+ lldb::addr_t m_start_address;
+ lldb::break_id_t m_backstop_bkpt_id;
+ lldb::addr_t m_backstop_addr;
+ StackID m_return_stack_id;
+ bool m_stop_others;
+
+ DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepThrough);
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ThreadPlanStepThrough_h_
diff --git a/include/lldb/Target/ThreadPlanStepUntil.h b/include/lldb/Target/ThreadPlanStepUntil.h
new file mode 100644
index 000000000000..5aa3876df53c
--- /dev/null
+++ b/include/lldb/Target/ThreadPlanStepUntil.h
@@ -0,0 +1,80 @@
+//===-- ThreadPlanStepUntil.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_ThreadPlanStepUntil_h_
+#define liblldb_ThreadPlanStepUntil_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
+
+namespace lldb_private {
+
+
+class ThreadPlanStepUntil : public ThreadPlan
+{
+public:
+ virtual ~ThreadPlanStepUntil ();
+
+ virtual void GetDescription (Stream *s, lldb::DescriptionLevel level);
+ virtual bool ValidatePlan (Stream *error);
+ virtual bool ShouldStop (Event *event_ptr);
+ virtual bool StopOthers ();
+ virtual lldb::StateType GetPlanRunState ();
+ virtual bool WillStop ();
+ virtual bool MischiefManaged ();
+
+protected:
+ virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan);
+ virtual bool DoPlanExplainsStop (Event *event_ptr);
+
+ ThreadPlanStepUntil (Thread &thread,
+ lldb::addr_t *address_list,
+ size_t num_addresses,
+ bool stop_others,
+ uint32_t frame_idx = 0);
+ void AnalyzeStop(void);
+
+private:
+
+ StackID m_stack_id;
+ lldb::addr_t m_step_from_insn;
+ lldb::break_id_t m_return_bp_id;
+ lldb::addr_t m_return_addr;
+ bool m_stepped_out;
+ bool m_should_stop;
+ bool m_ran_analyze;
+ bool m_explains_stop;
+
+ typedef std::map<lldb::addr_t,lldb::break_id_t> until_collection;
+ until_collection m_until_points;
+ bool m_stop_others;
+
+ void Clear();
+
+ friend lldb::ThreadPlanSP
+ Thread::QueueThreadPlanForStepUntil (bool abort_other_plans,
+ lldb::addr_t *address_list,
+ size_t num_addresses,
+ bool stop_others,
+ uint32_t frame_idx);
+
+ // Need an appropriate marker for the current stack so we can tell step out
+ // from step in.
+
+ DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepUntil);
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ThreadPlanStepUntil_h_
diff --git a/include/lldb/Target/ThreadPlanTracer.h b/include/lldb/Target/ThreadPlanTracer.h
new file mode 100644
index 000000000000..4eb0c783e57d
--- /dev/null
+++ b/include/lldb/Target/ThreadPlanTracer.h
@@ -0,0 +1,131 @@
+//===-- ThreadPlanTracer.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_ThreadPlanTracer_h_
+#define liblldb_ThreadPlanTracer_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Symbol/TaggedASTType.h"
+#include "lldb/Target/Thread.h"
+
+namespace lldb_private {
+
+class ThreadPlanTracer
+{
+friend class ThreadPlan;
+
+public:
+
+ typedef enum ThreadPlanTracerStyle
+ {
+ eLocation = 0,
+ eStateChange,
+ eCheckFrames,
+ ePython
+ } ThreadPlanTracerStyle;
+ ThreadPlanTracer (Thread &thread, lldb::StreamSP &stream_sp);
+ ThreadPlanTracer (Thread &thread);
+
+ virtual ~ThreadPlanTracer()
+ {
+ }
+
+ virtual void TracingStarted ()
+ {
+
+ }
+
+ virtual void TracingEnded ()
+ {
+
+ }
+
+ bool
+ EnableTracing(bool value)
+ {
+ bool old_value = m_enabled;
+ m_enabled = value;
+ if (old_value == false && value == true)
+ TracingStarted();
+ else if (old_value == true && value == false)
+ TracingEnded();
+
+ return old_value;
+ }
+
+ bool
+ TracingEnabled()
+ {
+ return m_enabled;
+ }
+
+ bool
+ EnableSingleStep (bool value)
+ {
+ bool old_value = m_single_step;
+ m_single_step = value;
+ return old_value;
+ }
+
+ bool
+ SingleStepEnabled ()
+ {
+ return m_single_step;
+ }
+
+protected:
+ Thread &m_thread;
+
+ Stream *
+ GetLogStream ();
+
+
+
+ virtual void Log();
+
+private:
+ bool
+ TracerExplainsStop ();
+
+ bool m_single_step;
+ bool m_enabled;
+ lldb::StreamSP m_stream_sp;
+};
+
+class ThreadPlanAssemblyTracer : public ThreadPlanTracer
+{
+public:
+ ThreadPlanAssemblyTracer (Thread &thread, lldb::StreamSP &stream_sp);
+ ThreadPlanAssemblyTracer (Thread &thread);
+ virtual ~ThreadPlanAssemblyTracer ();
+ virtual void TracingStarted ();
+ virtual void TracingEnded ();
+ virtual void Log();
+private:
+
+ Disassembler *
+ GetDisassembler ();
+
+ TypeFromUser
+ GetIntPointerType();
+
+ lldb::DisassemblerSP m_disassembler_sp;
+ TypeFromUser m_intptr_type;
+ std::vector<RegisterValue> m_register_values;
+ lldb::DataBufferSP m_buffer_sp;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ThreadPlanTracer_h_
diff --git a/include/lldb/Target/ThreadSpec.h b/include/lldb/Target/ThreadSpec.h
new file mode 100644
index 000000000000..e0d30934f373
--- /dev/null
+++ b/include/lldb/Target/ThreadSpec.h
@@ -0,0 +1,155 @@
+//===-- ThreadSpec.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_ThreadSpec_h_
+#define liblldb_ThreadSpec_h_
+
+#include <map>
+#include <string>
+
+#include "lldb/lldb-private.h"
+
+namespace lldb_private {
+
+// Note: For now the thread spec has only fixed elements -
+// Thread ID
+// Thread Index
+// Thread Name
+// Thread Queue Name
+//
+// But if we need more generality, we can hang a key/value map off of this structure.
+// That's why the thread matches spec test is done as a virtual method in Thread::MatchesSpec,
+// since it is the native thread that would know how to interpret the keys.
+// I was going to do the Queue Name this way out of sheer orneriness, but that seems a
+// sufficiently general concept, so I put it in here on its own.
+
+class ThreadSpec
+{
+public:
+ ThreadSpec ();
+
+ ThreadSpec (const ThreadSpec &rhs);
+
+ const ThreadSpec &
+ operator=(const ThreadSpec &rhs);
+
+ void
+ SetIndex (uint32_t index)
+ {
+ m_index = index;
+ }
+
+ void
+ SetTID (lldb::tid_t tid)
+ {
+ m_tid = tid;
+ }
+
+ void
+ SetName (const char *name)
+ {
+ m_name = name;
+ }
+
+ void
+ SetQueueName (const char *queue_name)
+ {
+ m_queue_name = queue_name;
+ }
+
+ uint32_t
+ GetIndex () const
+ {
+ return m_index;
+ }
+
+ lldb::tid_t
+ GetTID () const
+ {
+ return m_tid;
+ }
+
+ const char *
+ GetName () const;
+
+ const char *
+ GetQueueName () const;
+
+ bool
+ TIDMatches (lldb::tid_t thread_id) const
+ {
+ if (m_tid == LLDB_INVALID_THREAD_ID || thread_id == LLDB_INVALID_THREAD_ID)
+ return true;
+ else
+ return thread_id == m_tid;
+ }
+
+ bool
+ TIDMatches (Thread &thread) const;
+
+ bool
+ IndexMatches (uint32_t index) const
+ {
+ if (m_index == UINT32_MAX || index == UINT32_MAX)
+ return true;
+ else
+ return index == m_index;
+ }
+
+ bool
+ IndexMatches (Thread &thread) const;
+
+ bool
+ NameMatches (const char *name) const
+ {
+ if (m_name.empty())
+ return true;
+ else if (name == NULL)
+ return false;
+ else
+ return m_name == name;
+ }
+
+ bool
+ NameMatches (Thread &thread) const;
+
+ bool
+ QueueNameMatches (const char *queue_name) const
+ {
+ if (m_queue_name.empty())
+ return true;
+ else if (queue_name == NULL)
+ return false;
+ else
+ return m_queue_name == queue_name;
+ }
+
+ bool
+ QueueNameMatches (Thread &thread) const;
+
+ bool
+ ThreadPassesBasicTests (Thread &thread) const;
+
+ bool
+ HasSpecification () const;
+
+ void
+ GetDescription (Stream *s, lldb::DescriptionLevel level) const;
+
+protected:
+private:
+ uint32_t m_index;
+ lldb::tid_t m_tid;
+ std::string m_name;
+ std::string m_queue_name;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ThreadSpec_h_
diff --git a/include/lldb/Target/UnixSignals.h b/include/lldb/Target/UnixSignals.h
new file mode 100644
index 000000000000..f47a90bbf545
--- /dev/null
+++ b/include/lldb/Target/UnixSignals.h
@@ -0,0 +1,144 @@
+//===-- UnixSignals.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_UnixSignals_h_
+#define lldb_UnixSignals_h_
+
+// C Includes
+// C++ Includes
+#include <string>
+#include <map>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ConstString.h"
+
+namespace lldb_private
+{
+
+class UnixSignals
+{
+public:
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ UnixSignals();
+
+ virtual
+ ~UnixSignals();
+
+ const char *
+ GetSignalAsCString (int32_t signo) const;
+
+ bool
+ SignalIsValid (int32_t signo) const;
+
+ int32_t
+ GetSignalNumberFromName (const char *name) const;
+
+ const char *
+ GetSignalInfo (int32_t signo,
+ bool &should_suppress,
+ bool &should_stop,
+ bool &should_notify) const;
+
+ bool
+ GetShouldSuppress (int32_t signo) const;
+
+ bool
+ SetShouldSuppress (int32_t signo,
+ bool value);
+
+ bool
+ SetShouldSuppress (const char *signal_name,
+ bool value);
+
+ bool
+ GetShouldStop (int32_t signo) const;
+
+ bool
+ SetShouldStop (int32_t signo,
+ bool value);
+ bool
+ SetShouldStop (const char *signal_name,
+ bool value);
+
+ bool
+ GetShouldNotify (int32_t signo) const;
+
+ bool
+ SetShouldNotify (int32_t signo, bool value);
+
+ bool
+ SetShouldNotify (const char *signal_name,
+ bool value);
+
+ // These provide an iterator through the signals available on this system.
+ // Call GetFirstSignalNumber to get the first entry, then iterate on GetNextSignalNumber
+ // till you get back LLDB_INVALID_SIGNAL_NUMBER.
+ int32_t
+ GetFirstSignalNumber () const;
+
+ int32_t
+ GetNextSignalNumber (int32_t current_signal) const;
+
+ // We assume that the elements of this object are constant once it is constructed,
+ // since a process should never need to add or remove symbols as it runs. So don't
+ // call these functions anywhere but the constructor of your subclass of UnixSignals or in
+ // your Process Plugin's GetUnixSignals method before you return the UnixSignal object.
+
+ void
+ AddSignal (int signo,
+ const char *name,
+ const char *short_name,
+ bool default_suppress,
+ bool default_stop,
+ bool default_notify,
+ const char *description);
+
+ void
+ RemoveSignal (int signo);
+
+protected:
+ //------------------------------------------------------------------
+ // Classes that inherit from UnixSignals can see and modify these
+ //------------------------------------------------------------------
+
+ struct Signal
+ {
+ ConstString m_name;
+ ConstString m_short_name;
+ std::string m_description;
+ bool m_suppress:1,
+ m_stop:1,
+ m_notify:1;
+
+ Signal (const char *name,
+ const char *short_name,
+ bool default_suppress,
+ bool default_stop,
+ bool default_notify,
+ const char *description);
+
+ ~Signal () {}
+ };
+
+ void
+ Reset ();
+
+ typedef std::map <int32_t, Signal> collection;
+
+ collection m_signals;
+
+ DISALLOW_COPY_AND_ASSIGN (UnixSignals);
+};
+
+} // Namespace lldb
+#endif // lldb_UnixSignals_h_
diff --git a/include/lldb/Target/Unwind.h b/include/lldb/Target/Unwind.h
new file mode 100644
index 000000000000..7cda4aeb2e18
--- /dev/null
+++ b/include/lldb/Target/Unwind.h
@@ -0,0 +1,120 @@
+//===-- Unwind.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_Unwind_h_
+#define liblldb_Unwind_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Host/Mutex.h"
+
+namespace lldb_private {
+
+class Unwind
+{
+protected:
+ //------------------------------------------------------------------
+ // Classes that inherit from Unwind can see and modify these
+ //------------------------------------------------------------------
+ Unwind(Thread &thread) :
+ m_thread (thread),
+ m_unwind_mutex()
+ {
+ }
+
+public:
+ virtual
+ ~Unwind()
+ {
+ }
+
+ void
+ Clear()
+ {
+ Mutex::Locker locker(m_unwind_mutex);
+ DoClear();
+
+ }
+
+ uint32_t
+ GetFrameCount()
+ {
+ Mutex::Locker locker(m_unwind_mutex);
+ return DoGetFrameCount();
+ }
+
+ uint32_t
+ GetFramesUpTo (uint32_t end_idx)
+ {
+ lldb::addr_t cfa;
+ lldb::addr_t pc;
+ uint32_t idx;
+
+ for (idx = 0; idx < end_idx; idx++)
+ {
+ if (!DoGetFrameInfoAtIndex (idx, cfa, pc))
+ {
+ break;
+ }
+ }
+ return idx;
+ }
+
+ bool
+ GetFrameInfoAtIndex (uint32_t frame_idx,
+ lldb::addr_t& cfa,
+ lldb::addr_t& pc)
+ {
+ Mutex::Locker locker(m_unwind_mutex);
+ return DoGetFrameInfoAtIndex (frame_idx, cfa, pc);
+ }
+
+ lldb::RegisterContextSP
+ CreateRegisterContextForFrame (StackFrame *frame)
+ {
+ Mutex::Locker locker(m_unwind_mutex);
+ return DoCreateRegisterContextForFrame (frame);
+ }
+
+ Thread &
+ GetThread()
+ {
+ return m_thread;
+ }
+
+protected:
+ //------------------------------------------------------------------
+ // Classes that inherit from Unwind can see and modify these
+ //------------------------------------------------------------------
+ virtual void
+ DoClear() = 0;
+
+ virtual uint32_t
+ DoGetFrameCount() = 0;
+
+ virtual bool
+ DoGetFrameInfoAtIndex (uint32_t frame_idx,
+ lldb::addr_t& cfa,
+ lldb::addr_t& pc) = 0;
+
+ virtual lldb::RegisterContextSP
+ DoCreateRegisterContextForFrame (StackFrame *frame) = 0;
+
+ Thread &m_thread;
+ Mutex m_unwind_mutex;
+private:
+ DISALLOW_COPY_AND_ASSIGN (Unwind);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_Unwind_h_
diff --git a/include/lldb/Target/UnwindAssembly.h b/include/lldb/Target/UnwindAssembly.h
new file mode 100644
index 000000000000..6a4ae0c30f27
--- /dev/null
+++ b/include/lldb/Target/UnwindAssembly.h
@@ -0,0 +1,58 @@
+//===-- UnwindAssembly.h --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef utility_UnwindAssembly_h_
+#define utility_UnwindAssembly_h_
+
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/PluginInterface.h"
+
+namespace lldb_private {
+
+class UnwindAssembly :
+ public PluginInterface
+{
+public:
+ static UnwindAssembly*
+ FindPlugin (const ArchSpec &arch);
+
+ virtual
+ ~UnwindAssembly();
+
+ virtual bool
+ GetNonCallSiteUnwindPlanFromAssembly (AddressRange& func,
+ Thread& thread,
+ UnwindPlan& unwind_plan) = 0;
+
+ virtual bool
+ GetFastUnwindPlan (AddressRange& func,
+ Thread& thread,
+ UnwindPlan &unwind_plan) = 0;
+
+ // thread may be NULL in which case we only use the Target (e.g. if this is called pre-process-launch).
+ virtual bool
+ FirstNonPrologueInsn (AddressRange& func,
+ const lldb_private::ExecutionContext &exe_ctx,
+ Address& first_non_prologue_insn) = 0;
+
+protected:
+ UnwindAssembly (const ArchSpec &arch);
+ ArchSpec m_arch;
+
+private:
+ UnwindAssembly(); // Outlaw default constructor
+ DISALLOW_COPY_AND_ASSIGN (UnwindAssembly);
+};
+
+} // namespace lldb_private
+
+#endif //utility_UnwindAssembly_h_
+
+