diff options
Diffstat (limited to 'include/lldb/Target')
36 files changed, 1975 insertions, 995 deletions
diff --git a/include/lldb/Target/ABI.h b/include/lldb/Target/ABI.h index cc6c46cf0ec9d..8809c0047fa0c 100644 --- a/include/lldb/Target/ABI.h +++ b/include/lldb/Target/ABI.h @@ -20,24 +20,58 @@ #include "llvm/ADT/ArrayRef.h" +// forward define the llvm::Type class +namespace llvm { class Type; } + namespace lldb_private { class ABI : public PluginInterface { public: + + struct CallArgument + { + enum eType + { + HostPointer = 0, /* pointer to host data */ + TargetValue , /* value is on the target or literal */ + }; + eType type; /* value of eType */ + size_t size; /* size in bytes of this argument */ + union { + lldb::addr_t value; /* literal value */ + uint8_t *data; /* host data pointer */ + }; + }; + 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, - llvm::ArrayRef<lldb::addr_t> args) const = 0; + PrepareTrivialCall ( lldb_private::Thread &thread, + lldb::addr_t sp, + lldb::addr_t functionAddress, + lldb::addr_t returnAddress, + llvm::ArrayRef<lldb::addr_t> args) const = 0; + + // Prepare trivial call used from ThreadPlanFunctionCallGDB + // AD: + // . Because i don't want to change other ABI's this is not declared pure virtual. + // The dummy implementation will simply fail. Only HexagonABI will currently + // use this method. + // . Two PrepareTrivialCall's is not good design so perhaps this should be combined. + // + virtual bool + PrepareTrivialCall ( lldb_private::Thread &thread, + lldb::addr_t sp, + lldb::addr_t functionAddress, + lldb::addr_t returnAddress, + llvm::Type &prototype, + llvm::ArrayRef<CallArgument> args) const; virtual bool GetArgumentValues (Thread &thread, @@ -48,16 +82,26 @@ public: ClangASTType &type, bool persistent = true) const; + // specialized to work with llvm IR types + lldb::ValueObjectSP + GetReturnValueObject (Thread &thread, + llvm::Type &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. + // Don't put it in a persistent value object, that will be done by the ABI::GetReturnValueObject. virtual lldb::ValueObjectSP - GetReturnValueObjectImpl (Thread &thread, - ClangASTType &type) const = 0; + GetReturnValueObjectImpl (Thread &thread, ClangASTType &ast_type) const = 0; + + // specialized to work with llvm IR types + virtual lldb::ValueObjectSP + GetReturnValueObjectImpl( Thread &thread, llvm::Type &ir_type ) const; + public: virtual bool CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) = 0; @@ -108,7 +152,6 @@ public: virtual bool FunctionCallsChangeCFA () = 0; - bool GetRegisterInfoByName (const ConstString &name, RegisterInfo &info); diff --git a/include/lldb/Target/CPPLanguageRuntime.h b/include/lldb/Target/CPPLanguageRuntime.h index 98a4ab88cb25e..daf8a67d2a9db 100644 --- a/include/lldb/Target/CPPLanguageRuntime.h +++ b/include/lldb/Target/CPPLanguageRuntime.h @@ -136,7 +136,7 @@ public: 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 + // in some cases, compilers will output different names for one same type. when that 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 diff --git a/include/lldb/Target/ExecutionContext.h b/include/lldb/Target/ExecutionContext.h index f825c2e72e6da..50f2beaf949b0 100644 --- a/include/lldb/Target/ExecutionContext.h +++ b/include/lldb/Target/ExecutionContext.h @@ -18,10 +18,10 @@ /// 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. +/// objects are described below. /// /// Not all objects in an ExectionContext objects will be valid. If you want -/// to refer stronly (ExectionContext) or weakly (ExectionContextRef) to +/// to refer strongly (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. @@ -49,7 +49,7 @@ namespace lldb_private { /// 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 +/// might change over time and instances 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 @@ -64,7 +64,7 @@ namespace lldb_private { /// 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. +/// refer to execution contexts should use ExecutionContextRef objects. /// 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 @@ -89,7 +89,7 @@ public: /// 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 + /// valid objects in the ExecutionContext, otherwise no weak /// references to any execution context objects will be made. //------------------------------------------------------------------ ExecutionContextRef (const ExecutionContext *exe_ctx_ptr); @@ -104,7 +104,7 @@ public: //------------------------------------------------------------------ /// Assignment operator /// - /// Copy all weak refernces in \a rhs. + /// Copy all weak references in \a rhs. //------------------------------------------------------------------ ExecutionContextRef & operator =(const ExecutionContextRef &rhs); @@ -112,7 +112,7 @@ public: //------------------------------------------------------------------ /// Assignment operator from a ExecutionContext /// - /// Make weak refernces to any stringly referenced objects in \a exe_ctx. + /// Make weak references to any strongly referenced objects in \a exe_ctx. //------------------------------------------------------------------ ExecutionContextRef & operator =(const ExecutionContext &exe_ctx); @@ -129,13 +129,13 @@ public: /// 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. + /// make weak references 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. + /// make weak references 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. + /// make weak references too the process and target. /// If the ExecutionContextScope object is valid and refers to a target, - /// make weak refernces too the target. + /// make weak references too the target. //------------------------------------------------------------------ ExecutionContextRef (ExecutionContextScope *exe_scope); @@ -143,13 +143,13 @@ public: /// Construct using an execution context scope. /// /// If the ExecutionContextScope object refers to a frame, - /// make weak refernces too the frame, thread, process and target. + /// make weak references too the frame, thread, process and target. /// If the ExecutionContextScope object refers to a thread, - /// make weak refernces too the thread, process and target. + /// make weak references too the thread, process and target. /// If the ExecutionContextScope object refers to a process, - /// make weak refernces too the process and target. + /// make weak references too the process and target. /// If the ExecutionContextScope object refers to a target, - /// make weak refernces too the target. + /// make weak references too the target. //------------------------------------------------------------------ ExecutionContextRef (ExecutionContextScope &exe_scope); @@ -302,8 +302,8 @@ public: //------------------------------------------------------------------ /// 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 + /// The return value is only an indication of whether this object has + /// a weak reference and does not indicate whether the weak reference /// is valid or not. //------------------------------------------------------------------ bool @@ -314,8 +314,8 @@ public: //------------------------------------------------------------------ /// 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 + /// The return value is only an indication of whether this object has + /// a weak reference and does not indicate whether the weak reference /// is valid or not. //------------------------------------------------------------------ bool diff --git a/include/lldb/Target/ExecutionContextScope.h b/include/lldb/Target/ExecutionContextScope.h index 7ba40971af2c1..4a1b17d5a1142 100644 --- a/include/lldb/Target/ExecutionContextScope.h +++ b/include/lldb/Target/ExecutionContextScope.h @@ -29,7 +29,7 @@ namespace lldb_private { /// 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 +/// Objects 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 diff --git a/include/lldb/Target/FileAction.h b/include/lldb/Target/FileAction.h new file mode 100644 index 0000000000000..db84c0ef468c5 --- /dev/null +++ b/include/lldb/Target/FileAction.h @@ -0,0 +1,68 @@ +//===-- ProcessLaunchInfo.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_FileAction_h +#define liblldb_Target_FileAction_h + +#include <string> + +namespace lldb_private +{ + +class FileAction +{ + public: + enum Action + { + eFileActionNone, + eFileActionClose, + eFileActionDuplicate, + eFileActionOpen + }; + + FileAction(); + + void Clear(); + + bool Close(int fd); + + bool Duplicate(int fd, int dup_fd); + + bool Open(int fd, const char *path, bool read, bool write); + + int + GetFD() const + { + return m_fd; + } + + Action + GetAction() const + { + return m_action; + } + + int + GetActionArgument() const + { + return m_arg; + } + + const char *GetPath() const; + + 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 +}; + +} // namespace lldb_private + +#endif diff --git a/include/lldb/Target/JITLoader.h b/include/lldb/Target/JITLoader.h new file mode 100644 index 0000000000000..c15ae5a876f11 --- /dev/null +++ b/include/lldb/Target/JITLoader.h @@ -0,0 +1,90 @@ +//===-- JITLoader.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_JITLoader_h_ +#define liblldb_JITLoader_h_ + +#include <vector> + +#include "lldb/Core/PluginInterface.h" +#include "lldb/Target/JITLoaderList.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class JITLoader JITLoader.h "lldb/Target/JITLoader.h" +/// @brief A plug-in interface definition class for JIT loaders. +/// +/// Plugins of this kind listen for code generated at runtime in the +/// target. They are very similar to dynamic loader, with the difference +/// that they do not have information about the target's dyld and +/// that there may be multiple JITLoader plugins per process, while +/// there is at most one DynamicLoader. +//---------------------------------------------------------------------- +class JITLoader : + public PluginInterface +{ +public: + //------------------------------------------------------------------ + /// Find a JIT loader plugin for a given process. + /// + /// Scans the installed DynamicLoader plug-ins and tries to find + /// all applicable instances for the current process. + /// + /// @param[in] process + /// The process for which to try and locate a JIT loader + /// plug-in instance. + /// + //------------------------------------------------------------------ + static void + LoadPlugins (Process *process, lldb_private::JITLoaderList &list); + + //------------------------------------------------------------------ + /// Construct with a process. + //------------------------------------------------------------------ + JITLoader (Process *process); + + virtual + ~JITLoader (); + + //------------------------------------------------------------------ + /// Called after attaching a process. + /// + /// Allow JITLoader plug-ins to execute some code after + /// attaching to a process. + //------------------------------------------------------------------ + virtual void + DidAttach () = 0; + + //------------------------------------------------------------------ + /// Called after launching a process. + /// + /// Allow JITLoader plug-ins to execute some code after + /// the process has stopped for the first time on launch. + //------------------------------------------------------------------ + virtual void + DidLaunch () = 0; + + //------------------------------------------------------------------ + /// Called after a new shared object has been loaded so that it can + /// be probed for JIT entry point hooks. + //------------------------------------------------------------------ + virtual void + ModulesDidLoad (lldb_private::ModuleList &module_list) = 0; + +protected: + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + Process* m_process; +}; + +} // namespace lldb_private + +#endif // liblldb_JITLoader_h_ diff --git a/include/lldb/Target/JITLoaderList.h b/include/lldb/Target/JITLoaderList.h new file mode 100644 index 0000000000000..f933a61e9952f --- /dev/null +++ b/include/lldb/Target/JITLoaderList.h @@ -0,0 +1,60 @@ +//===-- JITLoaderList.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_JITLoaderList_h_ +#define liblldb_JITLoaderList_h_ + +#include <vector> + +#include "lldb/lldb-forward.h" +#include "lldb/Host/Mutex.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class JITLoaderList JITLoaderList.h "lldb/Target/JITLoaderList.h" +/// +/// Class used by the Process to hold a list of its JITLoaders. +//---------------------------------------------------------------------- +class JITLoaderList +{ +public: + + JITLoaderList(); + ~JITLoaderList(); + + void + Append (const lldb::JITLoaderSP &jit_loader_sp); + + void + Remove (const lldb::JITLoaderSP &jit_loader_sp); + + size_t + GetSize() const; + + lldb::JITLoaderSP + GetLoaderAtIndex (size_t idx); + + void + DidLaunch(); + + void + DidAttach(); + + void + ModulesDidLoad (ModuleList &module_list); + +private: + std::vector<lldb::JITLoaderSP> m_jit_loaders_vec; + lldb_private::Mutex m_jit_loaders_mutex; +}; + +} // namespace lldb_private + +#endif // liblldb_JITLoaderList_h_ diff --git a/include/lldb/Target/MemoryRegionInfo.h b/include/lldb/Target/MemoryRegionInfo.h new file mode 100644 index 0000000000000..0726ad15e8769 --- /dev/null +++ b/include/lldb/Target/MemoryRegionInfo.h @@ -0,0 +1,104 @@ +//===-- MemoryRegionInfo.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_MemoryRegionInfo_h +#define lldb_MemoryRegionInfo_h + +#include "lldb/Core/RangeMap.h" +#include "lldb/Utility/Range.h" + +namespace lldb_private +{ + 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; + }; +} + +#endif // #ifndef lldb_MemoryRegionInfo_h diff --git a/include/lldb/Target/NativeRegisterContext.h b/include/lldb/Target/NativeRegisterContext.h new file mode 100644 index 0000000000000..fa4ab013f2341 --- /dev/null +++ b/include/lldb/Target/NativeRegisterContext.h @@ -0,0 +1,190 @@ +//===-- NativeRegisterContext.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_NativeRegisterContext_h_ +#define liblldb_NativeRegisterContext_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" + +namespace lldb_private { + +class NativeThreadProtocol; + +class NativeRegisterContext: + public std::enable_shared_from_this<NativeRegisterContext> +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + NativeRegisterContext (NativeThreadProtocol &thread, uint32_t concrete_frame_idx); + + virtual + ~NativeRegisterContext (); + + // void + // InvalidateIfNeeded (bool force); + + //------------------------------------------------------------------ + // Subclasses must override these functions + //------------------------------------------------------------------ + // virtual void + // InvalidateAllRegisters () = 0; + + virtual uint32_t + GetRegisterCount () const = 0; + + virtual const RegisterInfo * + GetRegisterInfoAtIndex (uint32_t reg) const = 0; + + const char * + GetRegisterSetNameForRegisterAtIndex (uint32_t reg_index) const; + + virtual uint32_t + GetRegisterSetCount () const = 0; + + virtual const RegisterSet * + GetRegisterSet (uint32_t set_index) const = 0; + + virtual Error + ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value) = 0; + + virtual Error + WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) = 0; + + virtual Error + ReadAllRegisterValues (lldb::DataBufferSP &data_sp) = 0; + + virtual Error + WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) = 0; + + uint32_t + ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) const; + + //------------------------------------------------------------------ + // 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, uint32_t watch_flags); + + 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, lldb::addr_t src_len, RegisterValue ®_value); + + virtual Error + WriteRegisterValueToMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t dst_addr, lldb::addr_t dst_len, const RegisterValue ®_value); + + //------------------------------------------------------------------ + // Subclasses should not override these + //------------------------------------------------------------------ + virtual lldb::tid_t + GetThreadID() const; + + virtual NativeThreadProtocol & + GetThread () + { + return m_thread; + } + + const RegisterInfo * + GetRegisterInfoByName (const char *reg_name, uint32_t start_idx = 0); + + const RegisterInfo * + GetRegisterInfo (uint32_t reg_kind, uint32_t reg_num); + + lldb::addr_t + GetPC (lldb::addr_t fail_value = LLDB_INVALID_ADDRESS); + + Error + SetPC (lldb::addr_t pc); + + lldb::addr_t + GetSP (lldb::addr_t fail_value = LLDB_INVALID_ADDRESS); + + Error + SetSP (lldb::addr_t sp); + + lldb::addr_t + GetFP (lldb::addr_t fail_value = LLDB_INVALID_ADDRESS); + + Error + SetFP (lldb::addr_t fp); + + const char * + GetRegisterName (uint32_t reg); + + lldb::addr_t + GetReturnAddress (lldb::addr_t fail_value = LLDB_INVALID_ADDRESS); + + lldb::addr_t + GetFlags (lldb::addr_t fail_value = 0); + + lldb::addr_t + ReadRegisterAsUnsigned (uint32_t reg, lldb::addr_t fail_value); + + lldb::addr_t + ReadRegisterAsUnsigned (const RegisterInfo *reg_info, lldb::addr_t fail_value); + + Error + WriteRegisterFromUnsigned (uint32_t reg, uint64_t uval); + + Error + WriteRegisterFromUnsigned (const RegisterInfo *reg_info, uint64_t uval); + + // 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 + //------------------------------------------------------------------ + NativeThreadProtocol &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 (NativeRegisterContext); +}; + +} // namespace lldb_private + +#endif // liblldb_NativeRegisterContext_h_ diff --git a/include/lldb/Target/NativeRegisterContextRegisterInfo.h b/include/lldb/Target/NativeRegisterContextRegisterInfo.h new file mode 100644 index 0000000000000..5631005ca56e4 --- /dev/null +++ b/include/lldb/Target/NativeRegisterContextRegisterInfo.h @@ -0,0 +1,44 @@ +//===-- NativeRegisterContextRegisterInfo.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_NativeRegisterContextRegisterInfo_h +#define lldb_NativeRegisterContextRegisterInfo_h + +#include <memory> + +#include "NativeRegisterContext.h" +#include "Plugins/Process/Utility/RegisterInfoInterface.h" + +namespace lldb_private +{ + class NativeRegisterContextRegisterInfo: public NativeRegisterContext + { + public: + /// + /// Construct a NativeRegisterContextRegisterInfo, taking ownership + /// of the register_info_interface pointer. + /// + NativeRegisterContextRegisterInfo (NativeThreadProtocol &thread, + uint32_t concrete_frame_idx, + RegisterInfoInterface *register_info_interface); + + uint32_t + GetRegisterCount () const override; + + const RegisterInfo * + GetRegisterInfoAtIndex (uint32_t reg_index) const override; + + const RegisterInfoInterface& + GetRegisterInfoInterface () const; + + private: + std::unique_ptr<RegisterInfoInterface> m_register_info_interface_up; + }; +} +#endif diff --git a/include/lldb/Target/ObjCLanguageRuntime.h b/include/lldb/Target/ObjCLanguageRuntime.h index 7bac57256444b..12254f942e426 100644 --- a/include/lldb/Target/ObjCLanguageRuntime.h +++ b/include/lldb/Target/ObjCLanguageRuntime.h @@ -20,6 +20,7 @@ // Project includes #include "lldb/lldb-private.h" #include "lldb/Core/PluginInterface.h" +#include "lldb/Symbol/ClangASTType.h" #include "lldb/Symbol/Type.h" #include "lldb/Symbol/TypeVendor.h" #include "lldb/Target/LanguageRuntime.h" @@ -221,7 +222,7 @@ public: 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) + std::function <bool (const char *, const char *, lldb::addr_t, uint64_t)> const &ivar_func) const { return false; } @@ -238,6 +239,25 @@ public: m_type_wp = type_sp; } + struct iVarDescriptor { + ConstString m_name; + ClangASTType m_type; + uint64_t m_size; + int32_t m_offset; + }; + + virtual size_t + GetNumIVars () + { + return 0; + } + + virtual iVarDescriptor + GetIVarAtIndex (size_t idx) + { + return iVarDescriptor(); + } + protected: bool IsPointerValid (lldb::addr_t value, @@ -252,6 +272,25 @@ public: lldb::TypeWP m_type_wp; }; + class EncodingToType + { + public: + virtual ClangASTType RealizeType (ClangASTContext& ast_ctx, const char* name, bool allow_unknownanytype); + virtual ClangASTType RealizeType (const char* name, bool allow_unknownanytype); + + virtual ClangASTType RealizeType (clang::ASTContext& ast_ctx, const char* name, bool allow_unknownanytype) = 0; + + virtual ~EncodingToType(); + + protected: + std::unique_ptr<ClangASTContext> m_scratch_ast_ctx_ap; + }; + + typedef std::shared_ptr<EncodingToType> EncodingToTypeSP; + + virtual EncodingToTypeSP + GetEncodingToType (); + virtual ClassDescriptorSP GetClassDescriptor (ValueObject& in_value); diff --git a/include/lldb/Target/PathMappingList.h b/include/lldb/Target/PathMappingList.h index b5bcbbfd768fe..17185cb684958 100644 --- a/include/lldb/Target/PathMappingList.h +++ b/include/lldb/Target/PathMappingList.h @@ -78,7 +78,7 @@ public: bool notify); bool - Remove (off_t index, bool notify); + Remove (size_t index, bool notify); bool Remove (const ConstString &path, bool notify); diff --git a/include/lldb/Target/Platform.h b/include/lldb/Target/Platform.h index 80011fd120de2..e3d6abe3f398e 100644 --- a/include/lldb/Target/Platform.h +++ b/include/lldb/Target/Platform.h @@ -18,6 +18,7 @@ // Other libraries and framework includes // Project includes +#include "lldb/lldb-private-forward.h" #include "lldb/lldb-public.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/ConstString.h" @@ -25,6 +26,10 @@ #include "lldb/Interpreter/Options.h" #include "lldb/Host/Mutex.h" +// TODO pull NativeDelegate class out of NativeProcessProtocol so we +// can just forward ref the NativeDelegate rather than include it here. +#include "../../../source/Host/common/NativeProcessProtocol.h" + namespace lldb_private { //---------------------------------------------------------------------- @@ -174,13 +179,13 @@ namespace lldb_private { /// 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 + /// can often be used to match up an executable 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. + /// indicates success. /// /// @return /// Returns an error that describes success or failure. @@ -215,7 +220,7 @@ namespace lldb_private { bool GetOSKernelDescription (std::string &s); - // Returns the the name of the platform + // Returns the name of the platform ConstString GetName (); @@ -241,7 +246,7 @@ namespace lldb_private { // // 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(). + // call the HostInfo::GetOSVersion(). //------------------------------------------------------------------ virtual bool GetRemoteOSVersion () @@ -326,7 +331,8 @@ namespace lldb_private { //---------------------------------------------------------------------- virtual FileSpecList LocateExecutableScriptingResources (Target *target, - Module &module); + Module &module, + Stream* feedback_stream); virtual Error GetSharedModule (const ModuleSpec &module_spec, @@ -349,7 +355,7 @@ namespace lldb_private { /// A zero based architecture index /// /// @param[out] arch - /// A copy of the archgitecture at index if the return value is + /// A copy of the architecture at index if the return value is /// \b true. /// /// @return @@ -413,7 +419,7 @@ namespace lldb_private { /// 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. + /// pointer with an appropriate error. /// /// @param[in] pid /// The process ID that we should attempt to attach to. @@ -422,7 +428,7 @@ namespace lldb_private { /// 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. + /// appropriate error fill into the \a error object. //------------------------------------------------------------------ virtual lldb::ProcessSP Attach (ProcessAttachInfo &attach_info, @@ -858,13 +864,72 @@ namespace lldb_private { virtual const std::vector<ConstString> & GetTrapHandlerSymbolNames (); + //------------------------------------------------------------------ + /// Launch a process for debugging. + /// + /// This differs from Launch in that it returns a NativeProcessProtocol. + /// Currently used by lldb-gdbserver. + /// + /// @param[in] launch_info + /// Information required to launch the process. + /// + /// @param[in] native_delegate + /// The delegate that will receive messages regarding the + /// inferior. Must outlive the NativeProcessProtocol + /// instance. + /// + /// @param[out] process_sp + /// On successful return from the method, this parameter + /// contains the shared pointer to the + /// NativeProcessProtocol that can be used to manipulate + /// the native process. + /// + /// @return + /// An error object indicating if the operation succeeded, + /// and if not, what error occurred. + //------------------------------------------------------------------ + virtual Error + LaunchNativeProcess ( + ProcessLaunchInfo &launch_info, + lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate, + NativeProcessProtocolSP &process_sp); + + //------------------------------------------------------------------ + /// Attach to an existing process on the given platform. + /// + /// This method differs from Attach() in that it returns a + /// NativeProcessProtocol. Currently this is used by lldb-gdbserver. + /// + /// @param[in] pid + /// pid of the process locatable by the platform. + /// + /// @param[in] native_delegate + /// The delegate that will receive messages regarding the + /// inferior. Must outlive the NativeProcessProtocol + /// instance. + /// + /// @param[out] process_sp + /// On successful return from the method, this parameter + /// contains the shared pointer to the + /// NativeProcessProtocol that can be used to manipulate + /// the native process. + /// + /// @return + /// An error object indicating if the operation succeeded, + /// and if not, what error occurred. + //------------------------------------------------------------------ + virtual Error + AttachNativeProcess (lldb::pid_t pid, + lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate, + NativeProcessProtocolSP &process_sp); + 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(). + // will be set to the once we call HostInfo::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 @@ -892,6 +957,7 @@ namespace lldb_private { std::string m_local_cache_directory; std::vector<ConstString> m_trap_handlers; bool m_calculated_trap_handlers; + Mutex m_trap_handler_mutex; //------------------------------------------------------------------ /// Ask the Platform subclass to fill in the list of trap handler names diff --git a/include/lldb/Target/Process.h b/include/lldb/Target/Process.h index b74347d37e686..641707c58deba 100644 --- a/include/lldb/Target/Process.h +++ b/include/lldb/Target/Process.h @@ -42,7 +42,11 @@ #include "lldb/Interpreter/Args.h" #include "lldb/Interpreter/Options.h" #include "lldb/Target/ExecutionContextScope.h" +#include "lldb/Target/JITLoaderList.h" #include "lldb/Target/Memory.h" +#include "lldb/Target/MemoryRegionInfo.h" +#include "lldb/Target/ProcessInfo.h" +#include "lldb/Target/ProcessLaunchInfo.h" #include "lldb/Target/QueueList.h" #include "lldb/Target/ThreadList.h" #include "lldb/Target/UnixSignals.h" @@ -104,232 +108,6 @@ public: 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; - } - - void - SetArchitecture (ArchSpec arch) - { - m_arch = 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 @@ -434,445 +212,10 @@ protected: lldb::pid_t m_parent_pid; }; - //---------------------------------------------------------------------- -// ProcessLaunchInfo +// ProcessAttachInfo // -// 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); - -#ifndef LLDB_DISABLE_POSIX - static bool - AddPosixSpawnFileAction (void *file_actions, - const FileAction *info, - Log *log, - Error& error); -#endif - - 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), - m_hijack_listener_sp () - { - } - - 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), - m_hijack_listener_sp () - { - 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; - m_hijack_listener_sp.reset(); - } - - bool - ConvertArgumentsForLaunchingInShell (Error &error, - bool localhost, - bool will_debug, - bool first_arg_is_full_shell_command, - int32_t num_resumes); - - void - SetMonitorProcessCallback (Host::MonitorChildProcessCallback callback, - void *baton, - bool monitor_signals) - { - m_monitor_callback = callback; - m_monitor_callback_baton = baton; - m_monitor_signals = monitor_signals; - } - - Host::MonitorChildProcessCallback - GetMonitorProcessCallback () - { - return m_monitor_callback; - } - - const void* - GetMonitorProcessBaton () const - { - return m_monitor_callback_baton; - } - - // If the LaunchInfo has a monitor callback, then arrange to monitor the process. - // Return true if the LaunchInfo has taken care of monitoring the process, and false if the - // caller might want to monitor the process themselves. - - bool - MonitorProcess () const - { - if (GetFlags().Test(lldb::eLaunchFlagsDontMonitorProcess)) - return true; - - 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; - } - - lldb::ListenerSP - GetHijackListener () const - { - return m_hijack_listener_sp; - } - - void - SetHijackListener (const lldb::ListenerSP &listener_sp) - { - m_hijack_listener_sp = listener_sp; - } - - -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; - lldb::ListenerSP m_hijack_listener_sp; -}; - -//---------------------------------------------------------------------- -// ProcessLaunchInfo -// -// Describes any information that is required to launch a process. +// Describes any information that is required to attach to a process. //---------------------------------------------------------------------- class ProcessAttachInfo : public ProcessInstanceInfo @@ -884,7 +227,8 @@ public: m_resume_count (0), m_wait_for_launch (false), m_ignore_existing (true), - m_continue_once_attached (false) + m_continue_once_attached (false), + m_detach_on_error (true) { } @@ -894,12 +238,14 @@ public: m_resume_count (0), m_wait_for_launch (false), m_ignore_existing (true), - m_continue_once_attached (false) + m_continue_once_attached (false), + m_detach_on_error(true) { ProcessInfo::operator= (launch_info); SetProcessPluginName (launch_info.GetProcessPluginName()); SetResumeCount (launch_info.GetResumeCount()); SetHijackListener(launch_info.GetHijackListener()); + m_detach_on_error = launch_info.GetDetachOnError(); } bool @@ -1002,7 +348,18 @@ public: m_hijack_listener_sp = listener_sp; } - + bool + GetDetachOnError () const + { + return m_detach_on_error; + } + + void + SetDetachOnError (bool enable) + { + m_detach_on_error = enable; + } + protected: lldb::ListenerSP m_hijack_listener_sp; std::string m_plugin_name; @@ -1010,6 +367,7 @@ protected: 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. + bool m_detach_on_error; // If we are debugging remotely, instruct the stub to detach rather than killing the target on error. }; class ProcessLaunchCommandOptions : public Options @@ -1034,6 +392,7 @@ public: OptionParsingStarting () { launch_info.Clear(); + disable_aslr = eLazyBoolCalculate; } const OptionDefinition* @@ -1049,6 +408,7 @@ public: // Instance variables to hold the values for command options. ProcessLaunchInfo launch_info; + lldb_private::LazyBool disable_aslr; }; //---------------------------------------------------------------------- @@ -1321,91 +681,6 @@ inline bool operator!= (const ProcessModID &lhs, const ProcessModID &rhs) 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. @@ -1418,7 +693,8 @@ class Process : public ExecutionContextScope, public PluginInterface { - friend class ClangFunction; // For WaitForStateChangeEventsPrivate + friend class ClangFunction; // For WaitForStateChangeEventsPrivate + friend class Debugger; // For PopProcessIOHandler and ProcessIOHandlerIsActive friend class ProcessEventData; friend class StopInfo; friend class Target; @@ -1619,10 +895,17 @@ public: //------------------------------------------------------------------ /// Construct with a shared pointer to a target, and the Process listener. + /// Uses the Host UnixSignalsSP by default. //------------------------------------------------------------------ Process(Target &target, Listener &listener); //------------------------------------------------------------------ + /// Construct with a shared pointer to a target, the Process listener, + /// and the appropriate UnixSignalsSP for the process. + //------------------------------------------------------------------ + Process(Target &target, Listener &listener, const UnixSignalsSP &unix_signals_sp); + + //------------------------------------------------------------------ /// Destructor. /// /// The destructor is virtual since this class is designed to be @@ -1753,10 +1036,6 @@ public: /// /// 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 *) @@ -1766,32 +1045,9 @@ public: /// 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 + /// @param[in] launch_info + /// Details regarding the environment, STDIN/STDOUT/STDERR + /// redirection, working path, etc. related to the requested launch. /// /// @return /// An error object. Call GetID() to get the process ID if @@ -1824,6 +1080,22 @@ public: GetDynamicLoader (); //------------------------------------------------------------------ + // Returns AUXV structure found in many ELF-based environments. + // + // The default action is to return an empty data buffer. + // + // @return + // A data buffer containing the contents of the AUXV data. + //------------------------------------------------------------------ + virtual const lldb::DataBufferSP + GetAuxvData(); + +protected: + virtual JITLoaderList & + GetJITLoaders (); + +public: + //------------------------------------------------------------------ /// Get the system runtime plug-in for this process. /// /// @return @@ -1930,7 +1202,7 @@ public: //------------------------------------------------------------------ /// Register for process and thread notifications. /// - /// Clients can register nofication callbacks by filling out a + /// Clients can register notification callbacks by filling out a /// Process::Notifications structure and calling this function. /// /// @param[in] callbacks @@ -1946,7 +1218,7 @@ public: //------------------------------------------------------------------ /// Unregister for process and thread notifications. /// - /// Clients can unregister nofication callbacks by passing a copy of + /// Clients can unregister notification callbacks by passing a copy of /// the original baton and callbacks in \a callbacks. /// /// @param[in] callbacks @@ -2056,10 +1328,18 @@ public: Error Signal (int signal); - virtual UnixSignals & + void + SetUnixSignals (const UnixSignalsSP &signals_sp) + { + assert (signals_sp && "null signals_sp"); + m_unix_signals_sp = signals_sp; + } + + UnixSignals & GetUnixSignals () { - return m_unix_signals; + assert (m_unix_signals_sp && "null m_unix_signals_sp"); + return *m_unix_signals_sp; } //================================================================== @@ -2183,11 +1463,17 @@ public: //------------------------------------------------------------------ /// Called after attaching a process. /// + /// @param[in] process_arch + /// If you can figure out the process architecture after attach, fill it in here. + /// /// Allow Process plug-ins to execute some code after attaching to /// a process. //------------------------------------------------------------------ virtual void - DidAttach () {} + DidAttach (ArchSpec &process_arch) + { + process_arch.Clear(); + } //------------------------------------------------------------------ @@ -2229,46 +1515,21 @@ public: //------------------------------------------------------------------ /// 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. + /// Launch a new process by spawning a new process using + /// \a exe_module's file as the file to launch. Launch details are + /// provided in \a launch_info. /// - /// @param[in] module + /// @param[in] exe_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 + /// @param[in] launch_info + /// Details (e.g. arguments, stdio redirection, etc.) for the + /// requested launch. /// /// @return - /// A new valid process ID, or LLDB_INVALID_PROCESS_ID if - /// launching fails. + /// An Error instance indicating success or failure of the + /// operation. //------------------------------------------------------------------ virtual Error DoLaunch (Module *exe_module, @@ -2454,7 +1715,7 @@ public: DoSignal (int signal) { Error error; - error.SetErrorStringWithFormat("error: %s does not support senging signals to processes", GetPluginName().GetCString()); + error.SetErrorStringWithFormat("error: %s does not support sending signals to processes", GetPluginName().GetCString()); return error; } @@ -2546,14 +1807,14 @@ public: lldb::StateType GetState (); - ExecutionResults + lldb::ExpressionResults RunThreadPlan (ExecutionContext &exe_ctx, lldb::ThreadPlanSP &thread_plan_sp, const EvaluateExpressionOptions &options, Stream &errors); static const char * - ExecutionResultAsCString (ExecutionResults result); + ExecutionResultAsCString (lldb::ExpressionResults result); void GetStatus (Stream &ostrm); @@ -2568,6 +1829,9 @@ public: void SendAsyncInterrupt (); + void + ModulesDidLoad (ModuleList &module_list); + protected: void @@ -2904,7 +2168,7 @@ public: /// /// 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 + /// less than the size of scalar, the least significant \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 @@ -3070,7 +2334,8 @@ public: lldb::ModuleSP ReadModuleFromMemory (const FileSpec& file_spec, - lldb::addr_t header_addr); + lldb::addr_t header_addr, + size_t size_to_read = 512); //------------------------------------------------------------------ /// Attempt to get the attributes for a region of memory in the process. @@ -3412,6 +2677,25 @@ public: bool wait_always = true, Listener *hijack_listener = NULL); + + //-------------------------------------------------------------------------------------- + /// Waits for the process state to be running within a given msec timeout. + /// + /// The main purpose of this is to implement an interlock waiting for HandlePrivateEvent + /// to push an IOHandler. + /// + /// @param[in] timeout_msec + /// The maximum time length to wait for the process to transition to the + /// eStateRunning state, specified in milliseconds. + /// + /// @return + /// true if successfully signalled that process started and IOHandler pushes, false + /// if it timed out. + //-------------------------------------------------------------------------------------- + bool + SyncIOHandler (uint64_t timeout_msec); + + lldb::StateType WaitForStateChangedEvents (const TimeValue *timeout, lldb::EventSP &event_sp, @@ -3582,12 +2866,6 @@ public: void SetSTDIOFileDescriptor (int file_descriptor); - void - WatchForSTDIN (IOHandler &io_handler); - - void - CancelWatchForSTDIN (bool exited); - //------------------------------------------------------------------ // 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 @@ -3633,8 +2911,17 @@ public: else return m_public_run_lock; } - + +public: + virtual Error + SendEventData(const char *data) + { + Error return_error ("Sending an event is not supported for this process."); + return return_error; + } + protected: + //------------------------------------------------------------------ // NextEventAction provides a way to register an action on the next // event that is delivered to this process. There is currently only @@ -3690,13 +2977,9 @@ protected: class AttachCompletionHandler : public NextEventAction { public: - AttachCompletionHandler (Process *process, uint32_t exec_count) : - NextEventAction (process), - m_exec_count (exec_count) - { - } + AttachCompletionHandler (Process *process, uint32_t exec_count); - virtual + virtual ~AttachCompletionHandler() { } @@ -3753,7 +3036,7 @@ protected: 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 + lldb::thread_t m_private_state_thread; // Thread ID for the thread that watches internal 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. @@ -3773,10 +3056,11 @@ protected: 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<JITLoaderList> m_jit_loaders_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; std::unique_ptr<SystemRuntime> m_system_runtime_ap; - UnixSignals m_unix_signals; /// This is the current signal set for this process. + UnixSignalsSP m_unix_signals_sp; /// This is the current signal set for this process. lldb::ABISP m_abi_sp; lldb::IOHandlerSP m_process_input_reader; Communication m_stdio_communication; @@ -3785,6 +3069,7 @@ protected: std::string m_stderr_data; Mutex m_profile_data_comm_mutex; std::vector<std::string> m_profile_data; + Predicate<bool> m_iohandler_sync; 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? @@ -3874,15 +3159,15 @@ protected: static void STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len); - void + bool PushProcessIOHandler (); - void + bool PopProcessIOHandler (); - void - ResetProcessIOHandler (); - + bool + ProcessIOHandlerIsActive (); + Error HaltForDestroyOrDetach(lldb::EventSP &exit_event_sp); diff --git a/include/lldb/Target/ProcessInfo.h b/include/lldb/Target/ProcessInfo.h new file mode 100644 index 0000000000000..0570cfc986510 --- /dev/null +++ b/include/lldb/Target/ProcessInfo.h @@ -0,0 +1,188 @@ +//===-- ProcessInfo.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_ProcessInfo_h_ +#define liblldb_ProcessInfo_h_ + +// LLDB headers +#include "lldb/Core/ArchSpec.h" +#include "lldb/Host/FileSpec.h" +#include "lldb/Interpreter/Args.h" + +namespace lldb_private +{ + //---------------------------------------------------------------------- + // 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 (); + + ProcessInfo (const char *name, + const ArchSpec &arch, + lldb::pid_t pid); + + void + Clear (); + + const char * + GetName() const; + + size_t + GetNameLength() const; + + FileSpec & + GetExecutableFile () + { + return m_executable; + } + + void + SetExecutableFile (const FileSpec &exe_file, bool add_exe_file_as_first_arg); + + 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; + } + + void + SetArchitecture (ArchSpec arch) + { + m_arch = 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; + + void + SetArg0 (const char *arg); + + 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; + }; +} + +#endif // #ifndef liblldb_ProcessInfo_h_ + diff --git a/include/lldb/Target/ProcessLaunchInfo.h b/include/lldb/Target/ProcessLaunchInfo.h new file mode 100644 index 0000000000000..77d829a7e4762 --- /dev/null +++ b/include/lldb/Target/ProcessLaunchInfo.h @@ -0,0 +1,225 @@ +//===-- ProcessLaunchInfo.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_ProcessLaunch_Info_h +#define liblldb_ProcessLaunch_Info_h + +// C++ Headers +#include <string> + +// LLDB Headers +#include "lldb/Core/Flags.h" +#include "lldb/Host/Host.h" +#include "lldb/Target/FileAction.h" +#include "lldb/Target/ProcessInfo.h" +#include "lldb/Utility/PseudoTerminal.h" + +namespace lldb_private +{ + + //---------------------------------------------------------------------- + // ProcessLaunchInfo + // + // Describes any information that is required to launch a process. + //---------------------------------------------------------------------- + + class ProcessLaunchInfo : public ProcessInfo + { + public: + + ProcessLaunchInfo (); + + ProcessLaunchInfo (const char *stdin_path, + const char *stdout_path, + const char *stderr_path, + const char *working_directory, + uint32_t launch_flags); + + void + AppendFileAction (const FileAction &info) + { + m_file_actions.push_back(info); + } + + bool + AppendCloseFileAction (int fd); + + bool + AppendDuplicateFileAction (int fd, int dup_fd); + + bool + AppendOpenFileAction (int fd, const char *path, bool read, bool write); + + bool + AppendSuppressFileAction (int fd, bool read, bool write); + + 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; + + const FileAction * + GetFileActionForFD (int fd) const; + + Flags & + GetFlags () + { + return m_flags; + } + + const Flags & + GetFlags () const + { + return m_flags; + } + + const char * + GetWorkingDirectory () const; + + void + SetWorkingDirectory (const char *working_dir); + + void + SwapWorkingDirectory (std::string &working_dir) + { + m_working_dir.swap (working_dir); + } + + const char * + GetProcessPluginName () const; + + void + SetProcessPluginName (const char *plugin); + + const char * + GetShell () const; + + void + SetShell (const char * path); + + 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); + + void + Clear (); + + bool + ConvertArgumentsForLaunchingInShell (Error &error, + bool localhost, + bool will_debug, + bool first_arg_is_full_shell_command, + int32_t num_resumes); + + void + SetMonitorProcessCallback (Host::MonitorChildProcessCallback callback, + void *baton, + bool monitor_signals); + + Host::MonitorChildProcessCallback + GetMonitorProcessCallback () + { + return m_monitor_callback; + } + + const void* + GetMonitorProcessBaton () const + { + return m_monitor_callback_baton; + } + + // If the LaunchInfo has a monitor callback, then arrange to monitor the process. + // Return true if the LaunchInfo has taken care of monitoring the process, and false if the + // caller might want to monitor the process themselves. + + bool + MonitorProcess () const; + + lldb_utility::PseudoTerminal & + GetPTY () + { + return m_pty; + } + + lldb::ListenerSP + GetHijackListener () const + { + return m_hijack_listener_sp; + } + + void + SetHijackListener (const lldb::ListenerSP &listener_sp) + { + m_hijack_listener_sp = listener_sp; + } + + + void + SetLaunchEventData (const char *data) + { + m_event_data.assign (data); + } + + const char * + GetLaunchEventData () const + { + return m_event_data.c_str(); + } + + void + SetDetachOnError (bool enable); + + bool + GetDetachOnError () const + { + return m_flags.Test(lldb::eLaunchFlagDetachOnError); + } + + 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; + std::string m_event_data; // A string passed to the plugin launch, having no meaning to the upper levels of lldb. + lldb::ListenerSP m_hijack_listener_sp; + }; +} + +#endif // liblldb_ProcessLaunch_Info_h diff --git a/include/lldb/Target/Queue.h b/include/lldb/Target/Queue.h index 32ee24aebc118..514481fe8c9d8 100644 --- a/include/lldb/Target/Queue.h +++ b/include/lldb/Target/Queue.h @@ -168,6 +168,18 @@ public: m_pending_items.push_back (item); } + //------------------------------------------------------------------ + /// Return the kind (serial, concurrent) of this queue + /// + /// @return + // Whether this is a serial or a concurrent queue + //------------------------------------------------------------------ + lldb::QueueKind + GetKind (); + + void + SetKind (lldb::QueueKind kind); + private: //------------------------------------------------------------------ // For Queue only @@ -180,6 +192,7 @@ private: uint32_t m_pending_work_items_count; std::vector<lldb::QueueItemSP> m_pending_items; lldb::addr_t m_dispatch_queue_t_addr; // address of libdispatch dispatch_queue_t for this Queue + lldb::QueueKind m_kind; DISALLOW_COPY_AND_ASSIGN (Queue); }; diff --git a/include/lldb/Target/QueueItem.h b/include/lldb/Target/QueueItem.h index 76270da3bee6f..c69c825a7976d 100644 --- a/include/lldb/Target/QueueItem.h +++ b/include/lldb/Target/QueueItem.h @@ -14,6 +14,7 @@ #include "lldb/lldb-private.h" #include "lldb/lldb-enumerations.h" +#include "lldb/lldb-forward.h" #include "lldb/Core/Address.h" #include "lldb/Core/ConstString.h" @@ -37,7 +38,7 @@ class QueueItem : { public: - QueueItem (lldb::QueueSP queue_sp); + QueueItem (lldb::QueueSP queue_sp, lldb::ProcessSP process_sp, lldb::addr_t item_ref, lldb_private::Address address); ~QueueItem (); @@ -49,7 +50,7 @@ public: /// represents. eQueueItemKindUnknown may be returned. //------------------------------------------------------------------ lldb::QueueItemKind - GetKind () const; + GetKind (); //------------------------------------------------------------------ /// Set the type of work item this is @@ -124,10 +125,7 @@ public: } lldb::addr_t - GetItemThatEnqueuedThis () - { - return m_item_that_enqueued_this_ref; - } + GetItemThatEnqueuedThis (); void SetEnqueueingThreadID (lldb::tid_t tid) @@ -136,10 +134,7 @@ public: } lldb::tid_t - GetEnqueueingThreadID () - { - return m_enqueueing_thread_id; - } + GetEnqueueingThreadID (); void SetEnqueueingQueueID (lldb::queue_id_t qid) @@ -148,10 +143,7 @@ public: } lldb::queue_id_t - GetEnqueueingQueueID () - { - return m_enqueueing_queue_id; - } + GetEnqueueingQueueID (); void SetTargetQueueID (lldb::queue_id_t qid) @@ -166,10 +158,7 @@ public: } uint32_t - GetStopID () - { - return m_stop_id; - } + GetStopID (); void SetEnqueueingBacktrace (std::vector<lldb::addr_t> backtrace) @@ -178,10 +167,7 @@ public: } std::vector<lldb::addr_t> & - GetEnqueueingBacktrace () - { - return m_backtrace; - } + GetEnqueueingBacktrace (); void SetThreadLabel (std::string thread_name) @@ -190,10 +176,7 @@ public: } std::string - GetThreadLabel () - { - return m_thread_label; - } + GetThreadLabel (); void SetQueueLabel (std::string queue_name) @@ -202,10 +185,7 @@ public: } std::string - GetQueueLabel () - { - return m_queue_label; - } + GetQueueLabel (); void SetTargetQueueLabel (std::string queue_name) @@ -213,11 +193,22 @@ public: m_target_queue_label = queue_name; } + lldb::ProcessSP + GetProcessSP (); + protected: + void + FetchEntireItem (); + + lldb::QueueWP m_queue_wp; - lldb::QueueItemKind m_kind; + lldb::ProcessWP m_process_wp; + + lldb::addr_t m_item_ref; // the token we can be used to fetch more information about this queue item lldb_private::Address m_address; + bool m_have_fetched_entire_item; + lldb::QueueItemKind m_kind; lldb::addr_t m_item_that_enqueued_this_ref; // a handle that we can pass into libBacktraceRecording // to get the QueueItem that enqueued this item lldb::tid_t m_enqueueing_thread_id; // thread that enqueued this item diff --git a/include/lldb/Target/QueueList.h b/include/lldb/Target/QueueList.h index 964c1099233e8..12a0ea52d7f4a 100644 --- a/include/lldb/Target/QueueList.h +++ b/include/lldb/Target/QueueList.h @@ -98,7 +98,7 @@ public: /// /// @return /// A QueueSP to the queue requested, if it is present in the QueueList. - /// An empty QueueSP willbe returned if this queue was not found. + /// An empty QueueSP will be returned if this queue was not found. //------------------------------------------------------------------ lldb::QueueSP FindQueueByID (lldb::queue_id_t qid); @@ -114,7 +114,7 @@ public: /// /// @return /// A QueueSP to the queue requested, if it is present in the QueueList. - /// An empty QueueSP willbe returned if this queue was not found. + /// An empty QueueSP will be returned if this queue was not found. //------------------------------------------------------------------ lldb::QueueSP FindQueueByIndexID (uint32_t index_id); diff --git a/include/lldb/Target/RegisterContext.h b/include/lldb/Target/RegisterContext.h index 421acc03cb227..9108d4575259c 100644 --- a/include/lldb/Target/RegisterContext.h +++ b/include/lldb/Target/RegisterContext.h @@ -86,9 +86,44 @@ public: bool CopyFromRegisterContext (lldb::RegisterContextSP context); - + + //------------------------------------------------------------------ + /// Convert from a given register numbering scheme to the lldb register + /// numbering scheme + /// + /// There may be multiple ways to enumerate the registers for a given + /// architecture. ABI references will specify one to be used with + /// DWARF, the register numberings from stabs (aka "gcc"), there may + /// be a variation used for eh_frame unwind instructions (e.g. on Darwin), + /// and so on. Register 5 by itself is meaningless - RegisterKind + /// enumeration tells you what context that number should be translated as. + /// + /// Inside lldb, register numbers are in the eRegisterKindLLDB scheme; + /// arguments which take a register number should take one in that + /// scheme. + /// + /// eRegisterKindGeneric is a special numbering scheme which gives us + /// constant values for the pc, frame register, stack register, etc., for + /// use within lldb. They may not be defined for all architectures but + /// it allows generic code to translate these common registers into the + /// lldb numbering scheme. + /// + /// This method translates a given register kind + register number into + /// the eRegisterKindLLDB register numbering. + /// + /// @param [in] kind + /// The register numbering scheme (RegisterKind) that the following + /// register number is in. + /// + /// @param [in] num + /// A register number in the 'kind' register numbering scheme. + /// + /// @return + /// The equivalent register number in the eRegisterKindLLDB + /// numbering scheme, if possible, else LLDB_INVALID_REGNUM. + //------------------------------------------------------------------ virtual uint32_t - ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) = 0; + ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num) = 0; //------------------------------------------------------------------ // Subclasses can override these functions if desired @@ -136,7 +171,7 @@ public: GetRegisterInfoByName (const char *reg_name, uint32_t start_idx = 0); const RegisterInfo * - GetRegisterInfo (uint32_t reg_kind, uint32_t reg_num); + GetRegisterInfo (lldb::RegisterKind reg_kind, uint32_t reg_num); uint64_t GetPC (uint64_t fail_value = LLDB_INVALID_ADDRESS); @@ -179,7 +214,7 @@ public: 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); + ConvertBetweenRegisterKinds (lldb::RegisterKind source_rk, uint32_t source_regnum, lldb::RegisterKind target_rk, uint32_t& target_regnum); //------------------------------------------------------------------ // lldb::ExecutionContextScope pure virtual functions diff --git a/include/lldb/Target/StackFrame.h b/include/lldb/Target/StackFrame.h index e7b57cd26ac95..1274dcc64bd3b 100644 --- a/include/lldb/Target/StackFrame.h +++ b/include/lldb/Target/StackFrame.h @@ -177,7 +177,7 @@ public: /// /// The StackFrame maintains this SymbolContext and adds additional information /// to it on an as-needed basis. This helps to avoid different functions - /// looking up symbolic information for a given pc value multple times. + /// looking up symbolic information for a given pc value multiple times. /// /// @params [in] resolve_scope /// Flags from the SymbolContextItem enumerated type which specify what @@ -261,7 +261,7 @@ public: /// /// @param[in] get_file_globals /// Whether to also retrieve compilation-unit scoped variables - /// that are visisble to the entire compilation unit (e.g. file + /// that are visible to the entire compilation unit (e.g. file /// static in C, globals that are homed in this CU). /// /// @return @@ -279,7 +279,7 @@ public: /// /// @param[in] get_file_globals /// Whether to also retrieve compilation-unit scoped variables - /// that are visisble to the entire compilation unit (e.g. file + /// that are visible to the entire compilation unit (e.g. file /// static in C, globals that are homed in this CU). /// /// @return diff --git a/include/lldb/Target/StopInfo.h b/include/lldb/Target/StopInfo.h index 3435d392e2b99..8de40e852f4c8 100644 --- a/include/lldb/Target/StopInfo.h +++ b/include/lldb/Target/StopInfo.h @@ -157,7 +157,9 @@ public: CreateStopReasonToTrace (Thread &thread); static lldb::StopInfoSP - CreateStopReasonWithPlan (lldb::ThreadPlanSP &plan, lldb::ValueObjectSP return_valobj_sp); + CreateStopReasonWithPlan (lldb::ThreadPlanSP &plan, + lldb::ValueObjectSP return_valobj_sp, + lldb::ClangExpressionVariableSP expression_variable_sp); static lldb::StopInfoSP CreateStopReasonWithException (Thread &thread, const char *description); @@ -168,6 +170,9 @@ public: static lldb::ValueObjectSP GetReturnValueObject (lldb::StopInfoSP &stop_info_sp); + static lldb::ClangExpressionVariableSP + GetExpressionVariable (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. diff --git a/include/lldb/Target/SystemRuntime.h b/include/lldb/Target/SystemRuntime.h index 363ce122c4f3c..18f38f79bdbdd 100644 --- a/include/lldb/Target/SystemRuntime.h +++ b/include/lldb/Target/SystemRuntime.h @@ -20,6 +20,7 @@ #include "lldb/Core/ConstString.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/PluginInterface.h" +#include "lldb/Core/StructuredData.h" #include "lldb/Target/QueueList.h" #include "lldb/Target/QueueItem.h" #include "lldb/lldb-private.h" @@ -222,7 +223,7 @@ public: /// get the queue name and return it. /// /// @param [in] dispatch_qaddr - /// The address of the dispatch_queue_t structure for this thread. + /// The address of the dispatch_qaddr pointer for this thread. /// /// @return /// The string of this queue's name. An empty string is returned if the @@ -244,7 +245,7 @@ public: /// get the queue ID and return it. /// /// @param [in] dispatch_qaddr - /// The address of the dispatch_queue_t structure for this thread. + /// The address of the dispatch_qaddr pointer for this thread. /// /// @return /// The queue ID, or if it could not be retrieved, LLDB_INVALID_QUEUE_ID. @@ -256,6 +257,26 @@ public: } //------------------------------------------------------------------ + /// Get the libdispatch_queue_t address for the queue given the thread's dispatch_qaddr. + /// + /// On systems using libdispatch queues, a thread may be associated with a queue. + /// There will be a call to get the thread's dispatch_qaddr. + /// Given the thread's dispatch_qaddr, find the libdispatch_queue_t address and + /// return it. + /// + /// @param [in] dispatch_qaddr + /// The address of the dispatch_qaddr pointer for this thread. + /// + /// @return + /// The libdispatch_queue_t address, or LLDB_INVALID_ADDRESS if unavailable/not found. + //------------------------------------------------------------------ + virtual lldb::addr_t + GetLibdispatchQueueAddressFromThreadQAddress (lldb::addr_t dispatch_qaddr) + { + return LLDB_INVALID_ADDRESS; + } + + //------------------------------------------------------------------ /// Get the pending work items for a libdispatch Queue /// /// If this system/process is using libdispatch and the runtime can do so, @@ -270,6 +291,60 @@ public: { } + //------------------------------------------------------------------ + /// Complete the fields in a QueueItem + /// + /// PopulatePendingItemsForQueue() may not fill in all of the QueueItem + /// details; when the remaining fields are needed, they will be + /// fetched by call this method. + /// + /// @param [in] queue_item + /// The QueueItem that we will be completing. + /// + /// @param [in] item_ref + /// The item_ref token that is needed to retrieve the rest of the + /// information about the QueueItem. + //------------------------------------------------------------------ + virtual void + CompleteQueueItem (lldb_private::QueueItem *queue_item, lldb::addr_t item_ref) + { + } + + //------------------------------------------------------------------ + /// Add key-value pairs to the StructuredData dictionary object with + /// information debugserver may need when constructing the jThreadExtendedInfo + /// packet. + /// + /// @param [out] dict + /// Dictionary to which key-value pairs should be added; they will + /// be sent to the remote gdb server stub as arguments in the + /// jThreadExtendedInfo request. + //------------------------------------------------------------------ + virtual void + AddThreadExtendedInfoPacketHints (lldb_private::StructuredData::ObjectSP dict) + { + } + + /// Determine whether it is safe to run an expression on a given thread + /// + /// If a system must not run functions on a thread in some particular state, + /// this method gives a way for it to flag that the expression should not be + /// run. + /// + /// @param [in] thread_sp + /// The thread we want to run the expression on. + /// + /// @return + /// True will be returned if there are no known problems with running an + /// expression on this thread. False means that the inferior function + /// call should not be made on this thread. + //------------------------------------------------------------------ + virtual bool + SafeToCallFunctionsOnThisThread (lldb::ThreadSP thread_sp) + { + return true; + } + protected: //------------------------------------------------------------------ // Member variables. diff --git a/include/lldb/Target/Target.h b/include/lldb/Target/Target.h index e65a511ab77aa..64f3edf0fc4f8 100644 --- a/include/lldb/Target/Target.h +++ b/include/lldb/Target/Target.h @@ -82,6 +82,12 @@ public: SetDisableASLR (bool b); bool + GetDetachOnError () const; + + void + SetDetachOnError (bool b); + + bool GetDisableSTDIO () const; void @@ -201,9 +207,15 @@ public: m_stop_others(true), m_debug(false), m_trap_exceptions(true), + m_generate_debug_info(false), + m_result_is_internal(false), m_use_dynamic(lldb::eNoDynamicValues), - m_timeout_usec(default_timeout) - {} + m_timeout_usec(default_timeout), + m_one_thread_timeout_usec(0), + m_cancel_callback (nullptr), + m_cancel_callback_baton (nullptr) + { + } ExecutionPolicy GetExecutionPolicy () const @@ -301,6 +313,18 @@ public: m_timeout_usec = timeout; } + uint32_t + GetOneThreadTimeoutUsec () const + { + return m_one_thread_timeout_usec; + } + + void + SetOneThreadTimeoutUsec (uint32_t timeout = 0) + { + m_one_thread_timeout_usec = timeout; + } + bool GetTryAllThreads () const { @@ -335,6 +359,20 @@ public: SetDebug(bool b) { m_debug = b; + if (m_debug) + m_generate_debug_info = true; + } + + bool + GetGenerateDebugInfo() const + { + return m_generate_debug_info; + } + + void + SetGenerateDebugInfo(bool b) + { + m_generate_debug_info = b; } bool @@ -348,6 +386,34 @@ public: { m_trap_exceptions = b; } + + void + SetCancelCallback (lldb::ExpressionCancelCallback callback, void *baton) + { + m_cancel_callback_baton = baton; + m_cancel_callback = callback; + } + + bool + InvokeCancelCallback (lldb::ExpressionEvaluationPhase phase) const + { + if (m_cancel_callback == nullptr) + return false; + else + return m_cancel_callback (phase, m_cancel_callback_baton); + } + + void + SetResultIsInternal (bool b) + { + m_result_is_internal = b; + } + + bool + GetResultIsInternal () const + { + return m_result_is_internal; + } private: ExecutionPolicy m_execution_policy; @@ -360,8 +426,13 @@ private: bool m_stop_others; bool m_debug; bool m_trap_exceptions; + bool m_generate_debug_info; + bool m_result_is_internal; lldb::DynamicValueType m_use_dynamic; uint32_t m_timeout_usec; + uint32_t m_one_thread_timeout_usec; + lldb::ExpressionCancelCallback m_cancel_callback; + void *m_cancel_callback_baton; }; //---------------------------------------------------------------------- @@ -513,7 +584,7 @@ public: /// in a target. /// /// @param[in] s - /// The stream to which to dump the object descripton. + /// The stream to which to dump the object description. //------------------------------------------------------------------ void Dump (Stream *s, lldb::DescriptionLevel description_level); @@ -1086,7 +1157,7 @@ public: // 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 + lldb::ExpressionResults EvaluateExpression (const char *expression, StackFrame *frame, lldb::ValueObjectSP &result_valobj_sp, diff --git a/include/lldb/Target/TargetList.h b/include/lldb/Target/TargetList.h index 41404e11c7fa0..6abf13e8704c2 100644 --- a/include/lldb/Target/TargetList.h +++ b/include/lldb/Target/TargetList.h @@ -121,7 +121,7 @@ public: //------------------------------------------------------------------ /// Delete a Target object from the list. /// - /// When clients are done with the Target objets, this function + /// When clients are done with the Target objects, this function /// should be called to release the memory associated with a target /// object. /// diff --git a/include/lldb/Target/Thread.h b/include/lldb/Target/Thread.h index 20687e977bff6..cba09e1641056 100644 --- a/include/lldb/Target/Thread.h +++ b/include/lldb/Target/Thread.h @@ -14,6 +14,7 @@ #include "lldb/Host/Mutex.h" #include "lldb/Core/Broadcaster.h" #include "lldb/Core/Event.h" +#include "lldb/Core/StructuredData.h" #include "lldb/Core/UserID.h" #include "lldb/Core/UserSettingsController.h" #include "lldb/Target/ExecutionContextScope.h" @@ -49,6 +50,12 @@ public: bool GetTraceEnabledState() const; + + bool + GetStepInAvoidsNoDebug () const; + + bool + GetStepOutAvoidsNoDebug () const; }; typedef std::shared_ptr<ThreadProperties> ThreadPropertiesSP; @@ -153,7 +160,25 @@ public: static const ThreadPropertiesSP & GetGlobalProperties(); - Thread (Process &process, lldb::tid_t tid); + //------------------------------------------------------------------ + /// Constructor + /// + /// @param [in] process + /// + /// @param [in] tid + /// + /// @param [in] use_invalid_index_id + /// Optional parameter, defaults to false. The only subclass that + /// is likely to set use_invalid_index_id == true is the HistoryThread + /// class. In that case, the Thread we are constructing represents + /// a thread from earlier in the program execution. We may have the + /// tid of the original thread that they represent but we don't want + /// to reuse the IndexID of that thread, or create a new one. If a + /// client wants to know the original thread's IndexID, they should use + /// Thread::GetExtendedBacktraceOriginatingIndexID(). + //------------------------------------------------------------------ + Thread (Process &process, lldb::tid_t tid, bool use_invalid_index_id = false); + virtual ~Thread(); lldb::ProcessSP @@ -185,10 +210,22 @@ public: { return m_resume_state; } - + + // This sets the "external resume state" of the thread. If the thread is suspended here, it should never + // get scheduled. Note that just because a thread is marked as "running" does not mean we will let it run in + // a given bit of process control. For instance "step" tries to stay on the selected thread it was issued on, + // which may involve suspending other threads temporarily. This temporary suspension is NOT reflected in the + // state set here and reported in GetResumeState. + // + // If you are just preparing all threads to run, you should not override the threads that are + // marked as suspended by the debugger. In that case, pass override_suspend = false. If you want + // to force the thread to run (e.g. the "thread continue" command, or are resetting the state + // (e.g. in SBThread::Resume()), then pass true to override_suspend. void - SetResumeState (lldb::StateType state) + SetResumeState (lldb::StateType state, bool override_suspend = false) { + if (m_resume_state == lldb::eStateSuspended && !override_suspend) + return; m_resume_state = state; } @@ -270,6 +307,28 @@ public: return NULL; } + //------------------------------------------------------------------ + /// Retrieve a dictionary of information about this thread + /// + /// On Mac OS X systems there may be voucher information. + /// The top level dictionary returned will have an "activity" key and the + /// value of the activity is a dictionary. Keys in that dictionary will + /// be "name" and "id", among others. + /// There may also be "trace_messages" (an array) with each entry in that array + /// being a dictionary (keys include "message" with the text of the trace + /// message). + //------------------------------------------------------------------ + StructuredData::ObjectSP + GetExtendedInfo () + { + if (m_extended_info_fetched == false) + { + m_extended_info = FetchThreadExtendedInfo (); + m_extended_info_fetched = true; + } + return m_extended_info; + } + virtual const char * GetName () { @@ -281,6 +340,21 @@ public: { } + //------------------------------------------------------------------ + /// Retrieve the Queue ID for the queue currently using this Thread + /// + /// If this Thread is doing work on behalf of a libdispatch/GCD queue, + /// retrieve the QueueID. + /// + /// This is a unique identifier for the libdispatch/GCD queue in a + /// process. Often starting at 1 for the initial system-created + /// queues and incrementing, a QueueID will not be reused for a + /// different queue during the lifetime of a proces. + /// + /// @return + /// A QueueID if the Thread subclass implements this, else + /// LLDB_INVALID_QUEUE_ID. + //------------------------------------------------------------------ virtual lldb::queue_id_t GetQueueID () { @@ -292,6 +366,16 @@ public: { } + //------------------------------------------------------------------ + /// Retrieve the Queue name for the queue currently using this Thread + /// + /// If this Thread is doing work on behalf of a libdispatch/GCD queue, + /// retrieve the Queue name. + /// + /// @return + /// The Queue name, if the Thread subclass implements this, else + /// NULL. + //------------------------------------------------------------------ virtual const char * GetQueueName () { @@ -303,6 +387,44 @@ public: { } + //------------------------------------------------------------------ + /// Retrieve the Queue for this thread, if any. + /// + /// @return + /// A QueueSP for the queue that is currently associated with this + /// thread. + /// An empty shared pointer indicates that this thread is not + /// associated with a queue, or libdispatch queues are not + /// supported on this target. + //------------------------------------------------------------------ + virtual lldb::QueueSP + GetQueue () + { + return lldb::QueueSP(); + } + + //------------------------------------------------------------------ + /// Retrieve the address of the libdispatch_queue_t struct for queue + /// currently using this Thread + /// + /// If this Thread is doing work on behalf of a libdispatch/GCD queue, + /// retrieve the address of the libdispatch_queue_t structure describing + /// the queue. + /// + /// This address may be reused for different queues later in the Process + /// lifetime and should not be used to identify a queue uniquely. Use + /// the GetQueueID() call for that. + /// + /// @return + /// The Queue's libdispatch_queue_t address if the Thread subclass + /// implements this, else LLDB_INVALID_ADDRESS. + //------------------------------------------------------------------ + virtual lldb::addr_t + GetQueueLibdispatchQueueAddress () + { + return LLDB_INVALID_ADDRESS; + } + virtual uint32_t GetStackFrameCount() { @@ -412,6 +534,9 @@ public: void DumpUsingSettingsFormat (Stream &strm, uint32_t frame_idx); + bool + GetDescription (Stream &s, lldb::DescriptionLevel level, bool json_output); + //------------------------------------------------------------------ /// Default implementation for stepping into. /// @@ -422,17 +547,22 @@ public: /// If true and the frame has debug info, then do a source level /// step in, else do a single instruction step in. /// - /// @param[in] avoid_code_without_debug_info + /// @param[in] step_in_avoids_code_without_debug_info /// If \a true, then avoid stepping into code that doesn't have - /// debug info, else step into any code regardless of wether it + /// debug info, else step into any code regardless of whether it /// has debug info. /// + /// @param[in] step_out_avoids_code_without_debug_info + /// If \a true, then if you step out to code with no debug info, keep + /// stepping out till you get to code with debug info. + /// /// @return /// An error that describes anything that went wrong //------------------------------------------------------------------ virtual Error StepIn (bool source_step, - bool avoid_code_without_debug_info); + LazyBool step_in_avoids_code_without_debug_info = eLazyBoolCalculate, + LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate); //------------------------------------------------------------------ /// Default implementation for stepping over. @@ -448,7 +578,8 @@ public: /// An error that describes anything that went wrong //------------------------------------------------------------------ virtual Error - StepOver (bool source_step); + StepOver (bool source_step, + LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate); //------------------------------------------------------------------ /// Default implementation for stepping out. @@ -487,6 +618,19 @@ public: virtual lldb::addr_t GetThreadLocalData (const lldb::ModuleSP module); + //------------------------------------------------------------------ + /// Check whether this thread is safe to run functions + /// + /// The SystemRuntime may know of certain thread states (functions in + /// process of execution, for instance) which can make it unsafe for + /// functions to be called. + /// + /// @return + /// True if it is safe to call functions on this thread. + /// False if function calls should be avoided on this thread. + //------------------------------------------------------------------ + virtual bool + SafeToCallFunctions (); //------------------------------------------------------------------ // Thread Plan Providers: @@ -574,14 +718,19 @@ public: /// @param[in] stop_other_threads /// \b true if we will stop other threads while we single step this one. /// + /// @param[in] step_out_avoids_code_without_debug_info + /// If eLazyBoolYes, if the step over steps out it will continue to step out till it comes to a frame with debug info. + /// If eLazyBoolCalculate, we will consult the default set in the thread. + /// /// @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); + const AddressRange &range, + const SymbolContext &addr_context, + lldb::RunMode stop_other_threads, + LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate); //------------------------------------------------------------------ /// Queues the plan used to step through an address range, stepping into functions. @@ -609,19 +758,25 @@ public: /// @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. + /// @param[in] step_in_avoids_code_without_debug_info + /// If eLazyBoolYes we will step out if we step into code with no debug info. + /// If eLazyBoolCalculate we will consult the default set in the thread. + /// + /// @param[in] step_out_avoids_code_without_debug_info + /// If eLazyBoolYes, if the step over steps out it will continue to step out till it comes to a frame with debug info. + /// If eLazyBoolCalculate, it will consult the default set in the thread. /// /// @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); + const AddressRange &range, + const SymbolContext &addr_context, + const char *step_in_target, + lldb::RunMode stop_other_threads, + LazyBool step_in_avoids_code_without_debug_info = eLazyBoolCalculate, + LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate); //------------------------------------------------------------------ /// Queue the plan used to step out of the function at the current PC of @@ -648,6 +803,10 @@ public: /// @param[in] run_vote /// See standard meanings for the stop & run votes in ThreadPlan.h. /// + /// @param[in] step_out_avoids_code_without_debug_info + /// If eLazyBoolYes, if the step over steps out it will continue to step out till it comes to a frame with debug info. + /// If eLazyBoolCalculate, it will consult the default set in the thread. + /// /// @return /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued. //------------------------------------------------------------------ @@ -658,7 +817,46 @@ public: bool stop_other_threads, Vote stop_vote, // = eVoteYes, Vote run_vote, // = eVoteNoOpinion); - uint32_t frame_idx); + uint32_t frame_idx, + LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate); + + //------------------------------------------------------------------ + /// Queue the plan used to step out of the function at the current PC of + /// a thread. This version does not consult the should stop here callback, and should only + /// be used by other thread plans when they need to retain control of the step out. + /// + /// @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 + QueueThreadPlanForStepOutNoShouldStop (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 @@ -768,6 +966,17 @@ public: GetReturnValueObject (); //------------------------------------------------------------------ + /// Gets the outer-most expression variable from the completed plans + /// + /// @return + /// A ClangExpressionVariableSP, either empty if there is no + /// plan completed an expression during the current stop + /// or the expression variable that was made for the completed expression. + //------------------------------------------------------------------ + lldb::ClangExpressionVariableSP + GetExpressionVariable (); + + //------------------------------------------------------------------ /// Checks whether the given plan is in the completed plans for this /// stop. /// @@ -1066,6 +1275,13 @@ protected: return false; } + // Subclasses that have a way to get an extended info dictionary for this thread should + // fill + virtual lldb_private::StructuredData::ObjectSP + FetchThreadExtendedInfo () + { + return StructuredData::ObjectSP(); + } lldb::StackFrameListSP GetStackFrameList (); @@ -1091,11 +1307,13 @@ protected: 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. + /// It gets set in Thread::ShouldResume. 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: + bool m_extended_info_fetched; // Have we tried to retrieve the m_extended_info for this thread? + StructuredData::ObjectSP m_extended_info; // The extended info for this thread //------------------------------------------------------------------ // For Thread only //------------------------------------------------------------------ diff --git a/include/lldb/Target/ThreadPlan.h b/include/lldb/Target/ThreadPlan.h index 3c83fd1b9630d..1f20841906d33 100644 --- a/include/lldb/Target/ThreadPlan.h +++ b/include/lldb/Target/ThreadPlan.h @@ -501,11 +501,26 @@ public: return m_thread.GetStopInfo (); } + // If the completion of the thread plan stepped out of a function, the return value of the function + // might have been captured by the thread plan (currently only ThreadPlanStepOut does this.) + // If so, the ReturnValueObject can be retrieved from here. + virtual lldb::ValueObjectSP GetReturnValueObject () { return lldb::ValueObjectSP(); } + + // If the thread plan managing the evaluation of a user expression lives longer than the command + // that instigated the expression (generally because the expression evaluation hit a breakpoint, and + // the user regained control at that point) a subsequent process control command step/continue/etc. might + // complete the expression evaluations. If so, the result of the expression evaluation will show up here. + + virtual lldb::ClangExpressionVariableSP + GetExpressionVariable () + { + return lldb::ClangExpressionVariableSP(); + } // 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. @@ -524,6 +539,27 @@ public: return false; } + virtual bool + SetIterationCount (size_t count) + { + if (m_takes_iteration_count) + { + // Don't tell me to do something 0 times... + if (count == 0) + return false; + m_iteration_count = count; + } + return m_takes_iteration_count; + } + + virtual size_t + GetIterationCount () + { + if (!m_takes_iteration_count) + return 0; + else + return m_iteration_count; + } protected: //------------------------------------------------------------------ // Classes that inherit from ThreadPlan can see and modify these @@ -578,6 +614,8 @@ protected: Thread &m_thread; Vote m_stop_vote; Vote m_run_vote; + bool m_takes_iteration_count = false; + int32_t m_iteration_count = 1; private: //------------------------------------------------------------------ diff --git a/include/lldb/Target/ThreadPlanCallFunction.h b/include/lldb/Target/ThreadPlanCallFunction.h index 18f1d0facbf6a..12200ab765534 100644 --- a/include/lldb/Target/ThreadPlanCallFunction.h +++ b/include/lldb/Target/ThreadPlanCallFunction.h @@ -52,9 +52,6 @@ public: virtual bool StopOthers (); - virtual void - SetStopOthers (bool new_value); - virtual lldb::StateType GetPlanRunState (); @@ -128,7 +125,10 @@ public: m_takedown_done = true; } -protected: + virtual void + SetStopOthers (bool new_value); + +protected: void ReportRegisterState (const char *message); virtual bool diff --git a/include/lldb/Target/ThreadPlanCallUserExpression.h b/include/lldb/Target/ThreadPlanCallUserExpression.h index 5eb7cc1cd4525..67ac642de7bdf 100644 --- a/include/lldb/Target/ThreadPlanCallUserExpression.h +++ b/include/lldb/Target/ThreadPlanCallUserExpression.h @@ -40,21 +40,35 @@ public: GetDescription (Stream *s, lldb::DescriptionLevel level); virtual void - WillPop () - { - ThreadPlanCallFunction::WillPop(); - if (m_user_expression_sp) - m_user_expression_sp.reset(); - } + WillPop (); virtual lldb::StopInfoSP GetRealStopInfo(); + virtual bool + MischiefManaged (); + + void + TransferExpressionOwnership () + { + m_manage_materialization = true; + } + + virtual lldb::ClangExpressionVariableSP + GetExpressionVariable () + { + return m_result_var_sp; + } + 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. + bool m_manage_materialization = false; + lldb::ClangExpressionVariableSP m_result_var_sp; // If we are left to manage the materialization, + // then stuff the result expression variable here. + DISALLOW_COPY_AND_ASSIGN (ThreadPlanCallUserExpression); }; diff --git a/include/lldb/Target/ThreadPlanShouldStopHere.h b/include/lldb/Target/ThreadPlanShouldStopHere.h index 62068b78ae4e2..26e4a1ec4fe77 100644 --- a/include/lldb/Target/ThreadPlanShouldStopHere.h +++ b/include/lldb/Target/ThreadPlanShouldStopHere.h @@ -21,8 +21,9 @@ 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. +// method), call InvokeShouldStopHereCallback, passing in the frame comparison between where the step operation +// started and where you arrived. If it returns true, then QueueStepOutFromHere will queue the plan +// to execute instead of stopping. // // The classic example of the use of this is ThreadPlanStepInRange not stopping in frames that have // no debug information. @@ -34,27 +35,84 @@ namespace lldb_private { class ThreadPlanShouldStopHere { public: + struct ThreadPlanShouldStopHereCallbacks + { + ThreadPlanShouldStopHereCallbacks() + { + should_stop_here_callback = nullptr; + step_from_here_callback = nullptr; + } + + ThreadPlanShouldStopHereCallbacks(ThreadPlanShouldStopHereCallback should_stop, + ThreadPlanStepFromHereCallback step_from_here) + { + should_stop_here_callback = should_stop; + step_from_here_callback = step_from_here; + } + + void + Clear() + { + should_stop_here_callback = nullptr; + step_from_here_callback = nullptr; + } + + ThreadPlanShouldStopHereCallback should_stop_here_callback; + ThreadPlanStepFromHereCallback step_from_here_callback; + }; + enum { eNone = 0, - eAvoidInlines = (1 << 0), - eAvoidNoDebug = (1 << 1) + eAvoidInlines = (1 << 0), + eStepInAvoidNoDebug = (1 << 1), + eStepOutAvoidNoDebug = (1 << 2) }; //------------------------------------------------------------------ // Constructors and Destructors //------------------------------------------------------------------ + ThreadPlanShouldStopHere (ThreadPlan *owner); + ThreadPlanShouldStopHere (ThreadPlan *owner, - ThreadPlanShouldStopHereCallback callback = NULL, + const ThreadPlanShouldStopHereCallbacks *callbacks, void *baton = NULL); virtual ~ThreadPlanShouldStopHere(); - + + // Set the ShouldStopHere callbacks. Pass in null to clear them and have no special behavior (though you + // can also call ClearShouldStopHereCallbacks for that purpose. If you pass in a valid pointer, it will + // adopt the non-null fields, and any null fields will be set to the default values. + void - SetShouldStopHereCallback (ThreadPlanShouldStopHereCallback callback, void *baton); + SetShouldStopHereCallbacks (const ThreadPlanShouldStopHereCallbacks *callbacks, void *baton) + { + if (callbacks) + { + m_callbacks = *callbacks; + if (!m_callbacks.should_stop_here_callback) + m_callbacks.should_stop_here_callback = ThreadPlanShouldStopHere::DefaultShouldStopHereCallback; + if (!m_callbacks.step_from_here_callback) + m_callbacks.step_from_here_callback = ThreadPlanShouldStopHere::DefaultStepFromHereCallback; + } + else + { + ClearShouldStopHereCallbacks (); + } + m_baton = baton; + } + + void + ClearShouldStopHereCallbacks() + { + m_callbacks.Clear(); + } + bool + InvokeShouldStopHereCallback (lldb::FrameComparison operation); + lldb::ThreadPlanSP - InvokeShouldStopHereCallback (); + CheckShouldStopHereAndQueueStepOut (lldb::FrameComparison operation); lldb_private::Flags & GetFlags () @@ -69,13 +127,22 @@ public: } protected: + static bool + DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, lldb::FrameComparison operation, void *baton); + + static lldb::ThreadPlanSP + DefaultStepFromHereCallback (ThreadPlan *current_plan, Flags &flags, lldb::FrameComparison operation, void *baton); + + virtual lldb::ThreadPlanSP + QueueStepOutFromHerePlan (Flags &flags, lldb::FrameComparison operation); + // 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; + ThreadPlanShouldStopHereCallbacks m_callbacks; void * m_baton; ThreadPlan *m_owner; lldb_private::Flags m_flags; diff --git a/include/lldb/Target/ThreadPlanStepInRange.h b/include/lldb/Target/ThreadPlanStepInRange.h index 2f741f179bd43..3a22e97e30d0b 100644 --- a/include/lldb/Target/ThreadPlanStepInRange.h +++ b/include/lldb/Target/ThreadPlanStepInRange.h @@ -30,13 +30,17 @@ public: ThreadPlanStepInRange (Thread &thread, const AddressRange &range, const SymbolContext &addr_context, - lldb::RunMode stop_others); - + lldb::RunMode stop_others, + LazyBool step_in_avoids_code_without_debug_info, + LazyBool step_out_avoids_code_without_debug_info); + ThreadPlanStepInRange (Thread &thread, const AddressRange &range, const SymbolContext &addr_context, const char *step_into_function_name, - lldb::RunMode stop_others); + lldb::RunMode stop_others, + LazyBool step_in_avoids_code_without_debug_info, + LazyBool step_out_avoids_code_without_debug_info); virtual ~ThreadPlanStepInRange (); @@ -54,9 +58,6 @@ public: m_step_into_target.SetCString(target); } - static lldb::ThreadPlanSP - DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, void *baton); - static void SetDefaultFlagValue (uint32_t new_value); @@ -64,13 +65,26 @@ public: IsVirtualStep(); protected: + static bool + DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, lldb::FrameComparison operation, void *baton); + virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan); virtual bool DoPlanExplainsStop (Event *event_ptr); virtual void - SetFlagsToDefault (); + SetFlagsToDefault () + { + GetFlags().Set(ThreadPlanStepInRange::s_default_flag_values); + } + + void + SetCallbacks() + { + ThreadPlanShouldStopHere::ThreadPlanShouldStopHereCallbacks callbacks(ThreadPlanStepInRange::DefaultShouldStopHereCallback, nullptr); + SetShouldStopHereCallbacks (&callbacks, nullptr); + } bool FrameMatchesAvoidCriteria (); @@ -81,20 +95,23 @@ private: Thread::QueueThreadPlanForStepOverRange (bool abort_other_plans, const AddressRange &range, const SymbolContext &addr_context, - lldb::RunMode stop_others); + lldb::RunMode stop_others, + LazyBool avoid_code_without_debug_info); 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); - + LazyBool step_in_avoids_code_without_debug_info, + LazyBool step_out_avoids_code_without_debug_info); + void SetupAvoidNoDebug(LazyBool step_in_avoids_code_without_debug_info, + LazyBool step_out_avoids_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; + static uint32_t s_default_flag_values; // These are the default flag values for the ThreadPlanStepThrough. 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 diff --git a/include/lldb/Target/ThreadPlanStepInstruction.h b/include/lldb/Target/ThreadPlanStepInstruction.h index eb4a64bcbc84c..86069ffd9eb5e 100644 --- a/include/lldb/Target/ThreadPlanStepInstruction.h +++ b/include/lldb/Target/ThreadPlanStepInstruction.h @@ -32,6 +32,7 @@ public: virtual lldb::StateType GetPlanRunState (); virtual bool WillStop (); virtual bool MischiefManaged (); + virtual bool IsPlanStale (); protected: virtual bool DoPlanExplainsStop (Event *event_ptr); @@ -41,6 +42,7 @@ protected: bool stop_others, Vote stop_vote, Vote run_vote); + void SetUpState (); private: friend lldb::ThreadPlanSP diff --git a/include/lldb/Target/ThreadPlanStepOut.h b/include/lldb/Target/ThreadPlanStepOut.h index 2737978a4edc8..8c140dc9d95d1 100644 --- a/include/lldb/Target/ThreadPlanStepOut.h +++ b/include/lldb/Target/ThreadPlanStepOut.h @@ -16,10 +16,12 @@ // Project includes #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadPlan.h" +#include "lldb/Target/ThreadPlanShouldStopHere.h" namespace lldb_private { -class ThreadPlanStepOut : public ThreadPlan +class ThreadPlanStepOut : public ThreadPlan, + public ThreadPlanShouldStopHere { public: ThreadPlanStepOut (Thread &thread, @@ -28,7 +30,8 @@ public: bool stop_others, Vote stop_vote, Vote run_vote, - uint32_t frame_idx); + uint32_t frame_idx, + LazyBool step_out_avoids_code_without_debug_info); virtual ~ThreadPlanStepOut (); @@ -48,21 +51,29 @@ public: } protected: + virtual void + SetFlagsToDefault () + { + GetFlags().Set(ThreadPlanStepOut::s_default_flag_values); + } + 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; + static uint32_t s_default_flag_values; // These are the default flag values for the ThreadPlanStepThrough. + 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; + lldb::ThreadPlanSP m_step_out_to_inline_plan_sp; // This plan implements step out to the real function containing + // an inlined frame so we can then step out of that. + lldb::ThreadPlanSP m_step_through_inline_plan_sp; // This plan then steps past the inlined frame(s). + lldb::ThreadPlanSP m_step_out_further_plan_sp; // This plan keeps stepping out if ShouldStopHere told us to. Function *m_immediate_step_from_function; lldb::ValueObjectSP m_return_valobj_sp; @@ -73,8 +84,10 @@ private: bool stop_others, Vote stop_vote, Vote run_vote, - uint32_t frame_idx); + uint32_t frame_idx, + LazyBool step_out_avoids_code_without_debug_info); + void SetupAvoidNoDebug(LazyBool step_out_avoids_code_without_debug_info); // Need an appropriate marker for the current stack so we can tell step out // from step in. diff --git a/include/lldb/Target/ThreadPlanStepOverRange.h b/include/lldb/Target/ThreadPlanStepOverRange.h index 2cb5288272ea4..d47c6c9429d54 100644 --- a/include/lldb/Target/ThreadPlanStepOverRange.h +++ b/include/lldb/Target/ThreadPlanStepOverRange.h @@ -21,14 +21,16 @@ namespace lldb_private { -class ThreadPlanStepOverRange : public ThreadPlanStepRange +class ThreadPlanStepOverRange : public ThreadPlanStepRange, + ThreadPlanShouldStopHere { public: ThreadPlanStepOverRange (Thread &thread, const AddressRange &range, const SymbolContext &addr_context, - lldb::RunMode stop_others); + lldb::RunMode stop_others, + LazyBool step_out_avoids_no_debug); virtual ~ThreadPlanStepOverRange (); @@ -38,9 +40,20 @@ public: protected: virtual bool DoPlanExplainsStop (Event *event_ptr); virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan); - + + virtual void + SetFlagsToDefault () + { + GetFlags().Set(ThreadPlanStepOverRange::s_default_flag_values); + } + + + private: + static uint32_t s_default_flag_values; + + void SetupAvoidNoDebug(LazyBool step_out_avoids_code_without_debug_info); bool IsEquivalentContext(const SymbolContext &context); bool m_first_resume; diff --git a/include/lldb/Target/ThreadPlanStepRange.h b/include/lldb/Target/ThreadPlanStepRange.h index 486fd6528390b..3487e9ad66cbe 100644 --- a/include/lldb/Target/ThreadPlanStepRange.h +++ b/include/lldb/Target/ThreadPlanStepRange.h @@ -77,6 +77,7 @@ protected: 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. + StackID m_parent_stack_id; // Use the parent stack ID so we can identify tail calls and the like. 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. diff --git a/include/lldb/Target/UnwindAssembly.h b/include/lldb/Target/UnwindAssembly.h index 254382ac029d4..963949cf07d56 100644 --- a/include/lldb/Target/UnwindAssembly.h +++ b/include/lldb/Target/UnwindAssembly.h @@ -33,6 +33,11 @@ public: UnwindPlan& unwind_plan) = 0; virtual bool + AugmentUnwindPlanFromCallSite (AddressRange& func, + Thread& thread, + UnwindPlan& unwind_plan) = 0; + + virtual bool GetFastUnwindPlan (AddressRange& func, Thread& thread, UnwindPlan &unwind_plan) = 0; |