diff options
29 files changed, 1288 insertions, 1050 deletions
diff --git a/lldb/include/lldb/Breakpoint/Breakpoint.h b/lldb/include/lldb/Breakpoint/Breakpoint.h index 7c3fc0edad2..299707f0741 100644 --- a/lldb/include/lldb/Breakpoint/Breakpoint.h +++ b/lldb/include/lldb/Breakpoint/Breakpoint.h @@ -444,22 +444,6 @@ public: GetOptions (); -protected: - friend class Target; - friend class BreakpointLocation; // To call InvokeCallback - //------------------------------------------------------------------ - /// Constructors and Destructors - /// Only the Target can make a breakpoint, and it owns the breakpoint lifespans. - /// The constructor takes a filter and a resolver. Up in Target there are convenience - /// variants that make breakpoints for some common cases. - //------------------------------------------------------------------ - // This is the generic constructor - Breakpoint(Target &target, lldb::SearchFilterSP &filter_sp, lldb::BreakpointResolverSP &resolver_sp); - - //------------------------------------------------------------------ - // Protected Methods - //------------------------------------------------------------------ - //------------------------------------------------------------------ /// Invoke the callback action when the breakpoint is hit. /// @@ -478,8 +462,6 @@ protected: InvokeCallback (StoppointCallbackContext *context, lldb::break_id_t bp_loc_id); -protected: - //------------------------------------------------------------------ /// Returns the shared pointer that this breakpoint holds for the /// breakpoint location passed in as \a bp_loc_ptr. Passing in a @@ -494,6 +476,23 @@ protected: lldb::BreakpointLocationSP GetLocationSP (BreakpointLocation *bp_loc_ptr); + +protected: + friend class Target; + //------------------------------------------------------------------ + // Protected Methods + //------------------------------------------------------------------ + + + //------------------------------------------------------------------ + /// Constructors and Destructors + /// Only the Target can make a breakpoint, and it owns the breakpoint lifespans. + /// The constructor takes a filter and a resolver. Up in Target there are convenience + /// variants that make breakpoints for some common cases. + //------------------------------------------------------------------ + // This is the generic constructor + Breakpoint(Target &target, lldb::SearchFilterSP &filter_sp, lldb::BreakpointResolverSP &resolver_sp); + private: //------------------------------------------------------------------ // For Breakpoint only diff --git a/lldb/include/lldb/Breakpoint/BreakpointLocation.h b/lldb/include/lldb/Breakpoint/BreakpointLocation.h index d11cd103415..179d39a33dc 100644 --- a/lldb/include/lldb/Breakpoint/BreakpointLocation.h +++ b/lldb/include/lldb/Breakpoint/BreakpointLocation.h @@ -265,10 +265,6 @@ public: bool ValidForThisThread (Thread *thread); -protected: - friend class Breakpoint; - friend class CommandObjectBreakpointCommandAdd; - friend class Process; //------------------------------------------------------------------ /// Invoke the callback action when the breakpoint is hit. @@ -288,6 +284,11 @@ protected: bool InvokeCallback (StoppointCallbackContext *context); +protected: + friend class Breakpoint; + friend class CommandObjectBreakpointCommandAdd; + friend class Process; + //------------------------------------------------------------------ /// Set the breakpoint site for this location to \a bp_site_sp. /// diff --git a/lldb/include/lldb/Target/StopInfo.h b/lldb/include/lldb/Target/StopInfo.h new file mode 100644 index 00000000000..63cfd019690 --- /dev/null +++ b/lldb/include/lldb/Target/StopInfo.h @@ -0,0 +1,112 @@ +//===-- StopInfo.h ----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_StopInfo_h_ +#define liblldb_StopInfo_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-include.h" + +namespace lldb_private { + +class StopInfo +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + StopInfo (Thread &thread, uint64_t value); + + virtual ~StopInfo() + { + } + + + bool + IsValid () const; + + Thread & + GetThread() + { + return m_thread; + } + + const Thread & + GetThread() const + { + return m_thread; + } + + uint64_t + GetValue() const + { + return m_value; + } + + virtual lldb::StopReason + GetStopReason () const = 0; + + // Stop the thread by default. Subclasses can override this to allow + // the thread to continue if desired. + virtual bool + ShouldStop (Event *event_ptr) + { + return true; + } + + // If should stop returns false, check if we should notify of this event + virtual bool + ShouldNotify (Event *event_ptr) + { + return false; + } + + virtual void + WillResume (lldb::StateType resume_state) + { + // By default, don't do anything + } + + virtual const char * + GetDescription () = 0; + + + static lldb::StopInfoSP + CreateStopReasonWithBreakpointSiteID (Thread &thread, lldb::break_id_t break_id); + + static lldb::StopInfoSP + CreateStopReasonWithWatchpointID (Thread &thread, lldb::break_id_t watch_id); + + static lldb::StopInfoSP + CreateStopReasonWithSignal (Thread &thread, int signo); + + static lldb::StopInfoSP + CreateStopReasonToTrace (Thread &thread); + + static lldb::StopInfoSP + CreateStopReasonWithPlan (lldb::ThreadPlanSP &plan); + +protected: + //------------------------------------------------------------------ + // Classes that inherit from StackID can see and modify these + //------------------------------------------------------------------ + Thread & m_thread; // The thread corresponding to the stop reason. + const uint32_t m_stop_id; // The process stop ID for which this stop info is valid + uint64_t m_value; // A generic value that can be used for things pertaining to this stop info +private: + DISALLOW_COPY_AND_ASSIGN (StopInfo); +}; + + +} // namespace lldb_private + +#endif // liblldb_StopInfo_h_ diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h index 345f5154136..ea767fdc71b 100644 --- a/lldb/include/lldb/Target/Thread.h +++ b/lldb/include/lldb/Target/Thread.h @@ -29,133 +29,133 @@ class Thread : { friend class ThreadPlan; public: - //---------------------------------------------------------------------- - // StopInfo - // - // Describes the reason the thread it was created with stopped. - //---------------------------------------------------------------------- - class StopInfo - { - public: - StopInfo(Thread *thread = NULL); - - ~StopInfo(); - - // Clear clears the stop reason, but it does not clear the thread this - // StopInfo is tied to. - void - Clear(); - - lldb::StopReason - GetStopReason() const; - - void - SetThread (Thread *thread); - - Thread * - GetThread (); - - void - SetStopReasonWithBreakpointSiteID (lldb::user_id_t break_id); - - void - SetStopReasonWithWatchpointID (lldb::user_id_t watch_id); - - void - SetStopReasonWithSignal (int signo); - - void - SetStopReasonToTrace (); - - void - SetStopReasonWithGenericException (uint32_t exc_type, size_t exc_data_count); - - void - SetStopReasonWithPlan (lldb::ThreadPlanSP &plan); - - void - SetStopReasonToNone (); - - const char * - GetStopDescription() const; - - void - SetStopDescription(const char *desc); - - void - SetStopReasonWithMachException (uint32_t exc_type, - size_t exc_data_count, - const lldb::addr_t *exc_data); - - lldb::user_id_t - GetBreakpointSiteID() const; - - lldb::user_id_t - GetWatchpointID() const; - - int - GetSignal() const; - - lldb::user_id_t - GetPlanID () const; - - uint32_t - GetExceptionType() const; - - size_t - GetExceptionDataCount() const; - - lldb::addr_t - GetExceptionDataAtIndex (uint32_t idx) const; - - bool - SetExceptionDataAtIndex (uint32_t idx, lldb::addr_t data); - - void - Dump (Stream *s) const; - - protected: - lldb::StopReason m_reason; - //-------------------------------------------------------------- - // For eStopReasonPlan the completed plan is stored in this shared pointer. - //-------------------------------------------------------------- - lldb::ThreadPlanSP m_completed_plan_sp; - Thread *m_thread; - char m_description[256]; - union - { - //-------------------------------------------------------------- - // eStopReasonBreakpoint - //-------------------------------------------------------------- - struct - { - lldb::user_id_t bp_site_id; - } breakpoint; - //-------------------------------------------------------------- - // eStopReasonWatchpoint - //-------------------------------------------------------------- - struct - { - lldb::user_id_t watch_id; - } watchpoint; - //-------------------------------------------------------------- - // eStopReasonSignal - //-------------------------------------------------------------- - struct - { - int signo; - } signal; - //-------------------------------------------------------------- - // eStopReasonException - //-------------------------------------------------------------- - struct - { - uint32_t type; - size_t data_count; - lldb::addr_t data[LLDB_THREAD_MAX_STOP_EXC_DATA]; - } exception; - } m_details; - }; +// //---------------------------------------------------------------------- +// // StopInfo +// // +// // Describes the reason the thread it was created with stopped. +// //---------------------------------------------------------------------- +// class StopInfo +// { +// public: +// StopInfo(Thread *thread = NULL); +// +// ~StopInfo(); +// +// // Clear clears the stop reason, but it does not clear the thread this +// // StopInfo is tied to. +// void +// Clear(); +// +// lldb::StopReason +// GetStopReason() const; +// +// void +// SetThread (Thread *thread); +// +// Thread * +// GetThread (); +// +// void +// SetStopReasonWithBreakpointSiteID (lldb::user_id_t break_id); +// +// void +// SetStopReasonWithWatchpointID (lldb::user_id_t watch_id); +// +// void +// SetStopReasonWithSignal (int signo); +// +// void +// SetStopReasonToTrace (); +// +// void +// SetStopReasonWithGenericException (uint32_t exc_type, size_t exc_data_count); +// +// void +// SetStopReasonWithPlan (lldb::ThreadPlanSP &plan); +// +// void +// SetStopReasonToNone (); +// +// const char * +// GetStopDescription() const; +// +// void +// SetStopDescription(const char *desc); +// +// void +// SetStopReasonWithMachException (uint32_t exc_type, +// size_t exc_data_count, +// const lldb::addr_t *exc_data); +// +// lldb::user_id_t +// GetBreakpointSiteID() const; +// +// lldb::user_id_t +// GetWatchpointID() const; +// +// int +// GetSignal() const; +// +// lldb::user_id_t +// GetPlanID () const; +// +// uint32_t +// GetExceptionType() const; +// +// size_t +// GetExceptionDataCount() const; +// +// lldb::addr_t +// GetExceptionDataAtIndex (uint32_t idx) const; +// +// bool +// SetExceptionDataAtIndex (uint32_t idx, lldb::addr_t data); +// +// void +// Dump (Stream *s) const; +// +// protected: +// lldb::StopReason m_reason; +// //-------------------------------------------------------------- +// // For eStopReasonPlan the completed plan is stored in this shared pointer. +// //-------------------------------------------------------------- +// lldb::ThreadPlanSP m_completed_plan_sp; +// Thread *m_thread; +// char m_description[256]; +// union +// { +// //-------------------------------------------------------------- +// // eStopReasonBreakpoint +// //-------------------------------------------------------------- +// struct +// { +// lldb::user_id_t bp_site_id; +// } breakpoint; +// //-------------------------------------------------------------- +// // eStopReasonWatchpoint +// //-------------------------------------------------------------- +// struct +// { +// lldb::user_id_t watch_id; +// } watchpoint; +// //-------------------------------------------------------------- +// // eStopReasonSignal +// //-------------------------------------------------------------- +// struct +// { +// int signo; +// } signal; +// //-------------------------------------------------------------- +// // eStopReasonException +// //-------------------------------------------------------------- +// struct +// { +// uint32_t type; +// size_t data_count; +// lldb::addr_t data[LLDB_THREAD_MAX_STOP_EXC_DATA]; +// } exception; +// } m_details; +// }; class RegisterCheckpoint { @@ -276,8 +276,8 @@ public: virtual bool MatchesSpec (const ThreadSpec *spec); - bool - GetStopInfo (StopInfo *stop_info); + StopInfo * + GetStopInfo (); bool ThreadStoppedForAReason (); @@ -656,8 +656,8 @@ protected: ThreadPlan *GetPreviousPlan (ThreadPlan *plan); - virtual bool - GetRawStopReason (StopInfo *stop_info) = 0; + virtual lldb::StopInfoSP + GetPrivateStopReason () = 0; typedef std::vector<lldb::ThreadPlanSP> plan_stack; @@ -665,6 +665,8 @@ protected: // Classes that inherit from Process can see and modify these //------------------------------------------------------------------ Process & m_process; ///< The process that owns this thread. + lldb::StopInfoSP m_public_stop_info_sp; ///< The public stop reason for this thread + lldb::StopInfoSP m_actual_stop_info_sp; ///< The private stop reason for this thread const uint32_t m_index_id; ///< A unique 1 based index assigned to each thread for easy UI/command line access. lldb::RegisterContextSP m_reg_context_sp; ///< The register context for this thread's current register state. lldb::StateType m_state; ///< The state of our process. diff --git a/lldb/include/lldb/lldb-forward-rtti.h b/lldb/include/lldb/lldb-forward-rtti.h index f76de63449c..c372be46017 100644 --- a/lldb/include/lldb/lldb-forward-rtti.h +++ b/lldb/include/lldb/lldb-forward-rtti.h @@ -50,6 +50,7 @@ namespace lldb { typedef SharedPtr<lldb_private::SearchFilter>::Type SearchFilterSP; typedef SharedPtr<lldb_private::StackFrame>::Type StackFrameSP; typedef SharedPtr<lldb_private::StateVariable>::Type StateVariableSP; + typedef SharedPtr<lldb_private::StopInfo>::Type StopInfoSP; typedef SharedPtr<lldb_private::StoppointLocation>::Type StoppointLocationSP; typedef SharedPtr<lldb_private::Stream>::Type StreamSP; typedef SharedPtr<lldb_private::SymbolFile>::Type SymbolFileSP; diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h index 8deb3297778..2427e505bcc 100644 --- a/lldb/include/lldb/lldb-forward.h +++ b/lldb/include/lldb/lldb-forward.h @@ -102,6 +102,7 @@ class StackFrame; class StackFrameList; class StackID; class StateVariable; +class StopInfo; class Stoppoint; class StoppointCallbackContext; class StoppointLocation; diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index e5011df47f9..8471b0ca9f3 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -8,6 +8,10 @@ /* Begin PBXBuildFile section */ 260C876A10F538E700BB2B04 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 260C876910F538E700BB2B04 /* Foundation.framework */; }; + 2615DB851208A9C90021781D /* StopInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 2615DB841208A9C90021781D /* StopInfo.h */; }; + 2615DB871208A9E40021781D /* StopInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2615DB861208A9E40021781D /* StopInfo.cpp */; }; + 2615DBCA1208B5FC0021781D /* StopInfoMachException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2615DBC81208B5FC0021781D /* StopInfoMachException.cpp */; }; + 2615DBCB1208B5FC0021781D /* StopInfoMachException.h in Headers */ = {isa = PBXBuildFile; fileRef = 2615DBC91208B5FC0021781D /* StopInfoMachException.h */; }; 261744781168585B005ADD65 /* SBType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 261744771168585B005ADD65 /* SBType.cpp */; }; 2617447A11685869005ADD65 /* SBType.h in Headers */ = {isa = PBXBuildFile; fileRef = 2617447911685869005ADD65 /* SBType.h */; settings = {ATTRIBUTES = (Public, ); }; }; 261B5A5411C3F2AD00AABD0A /* SharingPtr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 261B5A5211C3F2AD00AABD0A /* SharingPtr.cpp */; }; @@ -503,6 +507,10 @@ 260C89E310F57C5600BB2B04 /* SymbolVendorMacOSX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SymbolVendorMacOSX.h; sourceTree = "<group>"; }; 26109B3B1155D70100CC3529 /* LogChannelDWARF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LogChannelDWARF.cpp; sourceTree = "<group>"; }; 26109B3C1155D70100CC3529 /* LogChannelDWARF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LogChannelDWARF.h; sourceTree = "<group>"; }; + 2615DB841208A9C90021781D /* StopInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StopInfo.h; path = include/lldb/Target/StopInfo.h; sourceTree = "<group>"; }; + 2615DB861208A9E40021781D /* StopInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StopInfo.cpp; path = source/Target/StopInfo.cpp; sourceTree = "<group>"; }; + 2615DBC81208B5FC0021781D /* StopInfoMachException.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StopInfoMachException.cpp; path = Utility/StopInfoMachException.cpp; sourceTree = "<group>"; }; + 2615DBC91208B5FC0021781D /* StopInfoMachException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StopInfoMachException.h; path = Utility/StopInfoMachException.h; sourceTree = "<group>"; }; 261744771168585B005ADD65 /* SBType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBType.cpp; path = source/API/SBType.cpp; sourceTree = "<group>"; }; 2617447911685869005ADD65 /* SBType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBType.h; path = include/lldb/API/SBType.h; sourceTree = "<group>"; }; 261B5A5211C3F2AD00AABD0A /* SharingPtr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SharingPtr.cpp; path = source/Utility/SharingPtr.cpp; sourceTree = "<group>"; }; @@ -1535,16 +1543,18 @@ isa = PBXGroup; children = ( 9654F79F1197DA3F00F72B43 /* libunwind */, - 26B4666F11A2091600CF6220 /* LibUnwindRegisterContext.cpp */, 26B4667011A2091600CF6220 /* LibUnwindRegisterContext.h */, - 9654F79C1197DA1300F72B43 /* MacOSXLibunwindCallbacks.cpp */, + 26B4666F11A2091600CF6220 /* LibUnwindRegisterContext.cpp */, 9654F79D1197DA1300F72B43 /* MacOSXLibunwindCallbacks.h */, - 26E3EEF711A994E800FBADB6 /* RegisterContextMacOSXFrameBackchain.cpp */, + 9654F79C1197DA1300F72B43 /* MacOSXLibunwindCallbacks.cpp */, 26E3EEF811A994E800FBADB6 /* RegisterContextMacOSXFrameBackchain.h */, - 26E3EEBE11A98A1900FBADB6 /* UnwindLibUnwind.cpp */, + 26E3EEF711A994E800FBADB6 /* RegisterContextMacOSXFrameBackchain.cpp */, + 2615DBC91208B5FC0021781D /* StopInfoMachException.h */, + 2615DBC81208B5FC0021781D /* StopInfoMachException.cpp */, 26E3EEBF11A98A1900FBADB6 /* UnwindLibUnwind.h */, - 26E3EEE311A9901300FBADB6 /* UnwindMacOSXFrameBackchain.cpp */, + 26E3EEBE11A98A1900FBADB6 /* UnwindLibUnwind.cpp */, 26E3EEE411A9901300FBADB6 /* UnwindMacOSXFrameBackchain.h */, + 26E3EEE311A9901300FBADB6 /* UnwindMacOSXFrameBackchain.cpp */, ); name = Utility; sourceTree = "<group>"; @@ -1930,6 +1940,8 @@ 26BC7F3910F1B90C00F91463 /* StackFrameList.cpp */, 26BC7DF710F1B81A00F91463 /* StackID.h */, 26BC7F3A10F1B90C00F91463 /* StackID.cpp */, + 2615DB841208A9C90021781D /* StopInfo.h */, + 2615DB861208A9E40021781D /* StopInfo.cpp */, 26BC7DF810F1B81A00F91463 /* Target.h */, 26BC7F3B10F1B90C00F91463 /* Target.cpp */, 26BC7DF910F1B81A00F91463 /* TargetList.h */, @@ -2210,6 +2222,8 @@ 49E45FAA11F660DC008F7B28 /* ClangASTType.h in Headers */, 49BB309611F79450001A4197 /* TaggedASTType.h in Headers */, 264723A611FA076E00DE380C /* CleanUp.h in Headers */, + 2615DB851208A9C90021781D /* StopInfo.h in Headers */, + 2615DBCB1208B5FC0021781D /* StopInfoMachException.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2664,6 +2678,8 @@ 4C5DBBC811E3FEC60035160F /* CommandObjectCommands.cpp in Sources */, 26D27C9F11ED3A4E0024D721 /* ELFHeader.cpp in Sources */, 49E45FAF11F660FE008F7B28 /* ClangASTType.cpp in Sources */, + 2615DB871208A9E40021781D /* StopInfo.cpp in Sources */, + 2615DBCA1208B5FC0021781D /* StopInfoMachException.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp index e52496a699f..c5285fdbd41 100644 --- a/lldb/source/API/SBThread.cpp +++ b/lldb/source/API/SBThread.cpp @@ -19,6 +19,7 @@ #include "lldb/Target/Process.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/CompileUnit.h" +#include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" #include "lldb/Target/ThreadPlan.h" #include "lldb/Target/ThreadPlanStepInstruction.h" @@ -79,9 +80,9 @@ SBThread::GetStopReason() { if (m_opaque_sp) { - lldb_private::Thread::StopInfo thread_stop_info; - if (m_opaque_sp->GetStopInfo(&thread_stop_info)) - return thread_stop_info.GetStopReason(); + lldb_private::StopInfo *stop_info = m_opaque_sp->GetStopInfo (); + if (stop_info) + return stop_info->GetStopReason(); } return eStopReasonInvalid; } @@ -91,10 +92,10 @@ SBThread::GetStopDescription (char *dst, size_t dst_len) { if (m_opaque_sp) { - lldb_private::Thread::StopInfo thread_stop_info; - if (m_opaque_sp->GetStopInfo(&thread_stop_info)) + lldb_private::StopInfo *stop_info = m_opaque_sp->GetStopInfo (); + if (stop_info) { - const char *stop_desc = thread_stop_info.GetStopDescription(); + const char *stop_desc = stop_info->GetDescription(); if (stop_desc) { if (dst) @@ -108,7 +109,7 @@ SBThread::GetStopDescription (char *dst, size_t dst_len) else { size_t stop_desc_len = 0; - switch (thread_stop_info.GetStopReason()) + switch (stop_info->GetStopReason()) { case eStopReasonTrace: case eStopReasonPlanComplete: @@ -137,7 +138,7 @@ SBThread::GetStopDescription (char *dst, size_t dst_len) case eStopReasonSignal: { - stop_desc = m_opaque_sp->GetProcess().GetUnixSignals ().GetSignalAsCString (thread_stop_info.GetSignal()); + stop_desc = m_opaque_sp->GetProcess().GetUnixSignals ().GetSignalAsCString (stop_info->GetValue()); if (stop_desc == NULL || stop_desc[0] == '\0') { static char signal_desc[] = "signal"; diff --git a/lldb/source/Breakpoint/BreakpointLocationCollection.cpp b/lldb/source/Breakpoint/BreakpointLocationCollection.cpp index af3f8e54be7..870686a9e4d 100644 --- a/lldb/source/Breakpoint/BreakpointLocationCollection.cpp +++ b/lldb/source/Breakpoint/BreakpointLocationCollection.cpp @@ -138,11 +138,10 @@ bool BreakpointLocationCollection::ShouldStop (StoppointCallbackContext *context) { bool shouldStop = false; - const size_t count = GetSize(); - for (size_t i = 0; i < count; i++) { - bool one_result = GetByIndex(i)->ShouldStop(context); - if (one_result) + for (size_t i = 0; i < count; i++) + { + if (GetByIndex(i)->ShouldStop(context)) shouldStop = true; } return shouldStop; diff --git a/lldb/source/Breakpoint/BreakpointSiteList.cpp b/lldb/source/Breakpoint/BreakpointSiteList.cpp index 9a5ee92f37b..155c8a7d7bc 100644 --- a/lldb/source/Breakpoint/BreakpointSiteList.cpp +++ b/lldb/source/Breakpoint/BreakpointSiteList.cpp @@ -49,15 +49,15 @@ BreakpointSiteList::Add(const BreakpointSiteSP &bp) } bool -BreakpointSiteList::ShouldStop (StoppointCallbackContext *context, lldb::break_id_t break_id) +BreakpointSiteList::ShouldStop (StoppointCallbackContext *context, lldb::break_id_t site_id) { - BreakpointSiteSP bp = FindByID (break_id); - if (bp) + BreakpointSiteSP site_sp (FindByID (site_id)); + if (site_sp) { // Let the BreakpointSite decide if it should stop here (could not have // reached it's target hit count yet, or it could have a callback // that decided it shouldn't stop (shared library loads/unloads). - return bp->ShouldStop (context); + return site_sp->ShouldStop (context); } // We should stop here since this BreakpointSite isn't valid anymore or it // doesn't exist. diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp index 8f49237767f..380aaa5a969 100644 --- a/lldb/source/Commands/CommandObjectThread.cpp +++ b/lldb/source/Commands/CommandObjectThread.cpp @@ -50,14 +50,8 @@ lldb_private::DisplayThreadInfo { if (only_threads_with_stop_reason) { - StopReason thread_stop_reason = eStopReasonNone; - Thread::StopInfo thread_stop_info; - if (thread->GetStopInfo(&thread_stop_info)) - { - thread_stop_reason = thread_stop_info.GetStopReason(); - if (thread_stop_reason == eStopReasonNone) - return false; - } + if (thread->GetStopInfo() == NULL) + return false; } strm.Indent(); diff --git a/lldb/source/Expression/ClangFunction.cpp b/lldb/source/Expression/ClangFunction.cpp index 5401b1c1343..df872229504 100644 --- a/lldb/source/Expression/ClangFunction.cpp +++ b/lldb/source/Expression/ClangFunction.cpp @@ -33,6 +33,7 @@ #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/Target/StopInfo.h" #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadPlan.h" #include "lldb/Target/ThreadPlanCallFunction.h" @@ -629,9 +630,6 @@ ClangFunction::ExecuteFunction ( continue; } - Thread::StopInfo stop_info; - thread->GetStopInfo(&stop_info); - ts.Printf("<"); RegisterContext *register_context = thread->GetRegisterContext(); @@ -640,7 +638,13 @@ ClangFunction::ExecuteFunction ( else ts.Printf("[ip unknown] "); - stop_info.Dump(&ts); + StopInfo *stop_info = thread->GetStopInfo(); + if (stop_info) + { + const char *stop_desc = stop_info->GetDescription(); + if (stop_desc) + ts.PutCString (stop_desc); + } ts.Printf(">"); } diff --git a/lldb/source/Plugins/Process/MacOSX-User/source/MacOSX/MachException.cpp b/lldb/source/Plugins/Process/MacOSX-User/source/MacOSX/MachException.cpp index d32ed5cd4cf..cfea47518ca 100644 --- a/lldb/source/Plugins/Process/MacOSX-User/source/MacOSX/MachException.cpp +++ b/lldb/source/Plugins/Process/MacOSX-User/source/MacOSX/MachException.cpp @@ -13,6 +13,7 @@ #include "lldb/Core/StreamString.h" #include "lldb/Host/Host.h" +#include "StopInfoMachException.h" #include "MachException.h" #include "ProcessMacOSXLog.h" @@ -198,22 +199,16 @@ MachException::Message::PutToLog(Log *log) const } } -bool -MachException::Data::GetStopInfo(Thread::StopInfo *stop_info) const +lldb::StopInfoSP +MachException::Data::GetStopInfo (lldb_private::Thread &thread) const { - // Zero out the structure. - stop_info->Clear(); - - // Make sure we have a valid exception before we return anything valid - if (exc_type == 0) - return true; - // We always stop with a mach exceptions + const size_t exc_data_count = exc_data.size(); - stop_info->SetStopReasonWithMachException (exc_type, - exc_data_count, - exc_data_count ? &exc_data[0] : NULL); - - return true; + return StopInfoMachException::CreateStopReasonWithMachException (thread, + exc_type, + exc_data_count, + exc_data_count >= 1 ? exc_data[0] : 0, + exc_data_count >= 2 ? exc_data[1] : 0); } diff --git a/lldb/source/Plugins/Process/MacOSX-User/source/MacOSX/MachException.h b/lldb/source/Plugins/Process/MacOSX-User/source/MacOSX/MachException.h index 886cbabc20c..761f433405b 100644 --- a/lldb/source/Plugins/Process/MacOSX-User/source/MacOSX/MachException.h +++ b/lldb/source/Plugins/Process/MacOSX-User/source/MacOSX/MachException.h @@ -98,7 +98,7 @@ public: } void PutToLog(lldb_private::Log *log) const; void DumpStopReason() const; - bool GetStopInfo(lldb_private::Thread::StopInfo *stop_info) const; + lldb::StopInfoSP GetStopInfo (lldb_private::Thread &thread) const; }; struct Message diff --git a/lldb/source/Plugins/Process/MacOSX-User/source/ThreadMacOSX.cpp b/lldb/source/Plugins/Process/MacOSX-User/source/ThreadMacOSX.cpp index 826407662ad..974421074a9 100644 --- a/lldb/source/Plugins/Process/MacOSX-User/source/ThreadMacOSX.cpp +++ b/lldb/source/Plugins/Process/MacOSX-User/source/ThreadMacOSX.cpp @@ -13,6 +13,7 @@ #include "lldb/Core/ArchSpec.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Target/Process.h" +#include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" #include "ProcessMacOSX.h" @@ -63,70 +64,12 @@ ThreadMacOSX::~ThreadMacOSX () #endif -bool -ThreadMacOSX::GetRawStopReason (Thread::StopInfo *stop_info ) +StopInfoSP +ThreadMacOSX::GetPrivateStopReason () { - stop_info->SetThread(this); - - bool success = GetStopException().GetStopInfo(stop_info); - - -#if defined (MACH_SOFTWARE_BREAKPOINT_DATA_0) || defined (MACH_TRAP_DATA_0) - if (stop_info->GetStopReason() == eStopReasonException) - { - if (stop_info->GetExceptionType() == EXC_BREAKPOINT && stop_info->GetExceptionDataCount() == 2) - { - const lldb::addr_t data_0 = stop_info->GetExceptionDataAtIndex(0); -#if defined (MACH_SOFTWARE_BREAKPOINT_DATA_0) - if (data_0 == MACH_SOFTWARE_BREAKPOINT_DATA_0) - { - lldb::addr_t pc = GetRegisterContext()->GetPC(); - lldb::BreakpointSiteSP bp_site_sp = m_process.GetBreakpointSiteList().FindByAddress(pc); - if (bp_site_sp) - { - if (bp_site_sp->ValidForThisThread (this)) - { - stop_info->Clear (); - stop_info->SetStopReasonWithBreakpointSiteID (GetID()); - } - else - { - stop_info->Clear (); - stop_info->SetStopReasonToNone(); - } - return success; - } - } -#endif -#if defined (MACH_TRAP_DATA_0) - if (data_0 == MACH_TRAP_DATA_0) - { - stop_info->Clear (); - stop_info->SetStopReasonToTrace (); - return success; - } -#endif - } - } -#endif - - if (stop_info->GetStopReason() == eStopReasonException) - { - if (stop_info->GetExceptionType() == EXC_SOFTWARE && - stop_info->GetExceptionDataCount() == 2 && - stop_info->GetExceptionDataAtIndex(0) == EXC_SOFT_SIGNAL) - { - int signo = stop_info->GetExceptionDataAtIndex(1); - stop_info->Clear (); - stop_info->SetStopReasonWithSignal (signo); - } - } - else - { - stop_info->SetStopReasonToNone(); - } - - return success; + if (m_actual_stop_info_sp.get() == NULL || m_actual_stop_info_sp->IsValid() == false) + m_actual_stop_info_sp = GetStopException().GetStopInfo(*this); + return m_actual_stop_info_sp; } const char * diff --git a/lldb/source/Plugins/Process/MacOSX-User/source/ThreadMacOSX.h b/lldb/source/Plugins/Process/MacOSX-User/source/ThreadMacOSX.h index 0039f3639f1..2e57ca93112 100644 --- a/lldb/source/Plugins/Process/MacOSX-User/source/ThreadMacOSX.h +++ b/lldb/source/Plugins/Process/MacOSX-User/source/ThreadMacOSX.h @@ -126,8 +126,8 @@ public: size_t GetStackFrameData (std::vector<std::pair<lldb::addr_t, lldb::addr_t> >& fp_pc_pairs); - virtual bool - GetRawStopReason (lldb_private::Thread::StopInfo *stop_info); + virtual lldb::StopInfoSP + GetPrivateStopReason (); protected: bool diff --git a/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp b/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp new file mode 100644 index 00000000000..c7e85f736c7 --- /dev/null +++ b/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp @@ -0,0 +1,344 @@ +//===-- StopInfoMachException.cpp -------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "StopInfoMachException.h" + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlan.h" +#include "lldb/Target/UnixSignals.h" + +using namespace lldb; +using namespace lldb_private; + +const char * +StopInfoMachException::GetDescription () +{ + if (m_description.empty() && m_value != 0) + { + ArchSpec::CPU cpu = m_thread.GetProcess().GetTarget().GetArchitecture().GetGenericCPUType(); + + const char *exc_desc = NULL; + const char *code_label = "code"; + const char *code_desc = NULL; + const char *subcode_label = "subcode"; + const char *subcode_desc = NULL; + switch (m_value) + { + case 1: // EXC_BAD_ACCESS + exc_desc = "EXC_BAD_ACCESS"; + subcode_label = "address"; + switch (cpu) + { + case ArchSpec::eCPU_arm: + switch (m_exc_code) + { + case 0x101: code_desc = "EXC_ARM_DA_ALIGN"; break; + case 0x102: code_desc = "EXC_ARM_DA_DEBUG"; break; + } + break; + + case ArchSpec::eCPU_ppc: + case ArchSpec::eCPU_ppc64: + switch (m_exc_code) + { + case 0x101: code_desc = "EXC_PPC_VM_PROT_READ"; break; + case 0x102: code_desc = "EXC_PPC_BADSPACE"; break; + case 0x103: code_desc = "EXC_PPC_UNALIGNED"; break; + } + break; + + default: + break; + } + break; + + case 2: // EXC_BAD_INSTRUCTION + exc_desc = "EXC_BAD_INSTRUCTION"; + switch (cpu) + { + case ArchSpec::eCPU_i386: + case ArchSpec::eCPU_x86_64: + if (m_exc_code == 1) + code_desc = "EXC_I386_INVOP"; + break; + + case ArchSpec::eCPU_ppc: + case ArchSpec::eCPU_ppc64: + switch (m_exc_code) + { + case 1: code_desc = "EXC_PPC_INVALID_SYSCALL"; break; + case 2: code_desc = "EXC_PPC_UNIPL_INST"; break; + case 3: code_desc = "EXC_PPC_PRIVINST"; break; + case 4: code_desc = "EXC_PPC_PRIVREG"; break; + case 5: code_desc = "EXC_PPC_TRACE"; break; + case 6: code_desc = "EXC_PPC_PERFMON"; break; + } + break; + + case ArchSpec::eCPU_arm: + if (m_exc_code == 1) + code_desc = "EXC_ARM_UNDEFINED"; + break; + + default: + break; + } + break; + + case 3: // EXC_ARITHMETIC + exc_desc = "EXC_ARITHMETIC"; + switch (cpu) + { + case ArchSpec::eCPU_i386: + case ArchSpec::eCPU_x86_64: + switch (m_exc_code) + { + case 1: code_desc = "EXC_I386_DIV"; break; + case 2: code_desc = "EXC_I386_INTO"; break; + case 3: code_desc = "EXC_I386_NOEXT"; break; + case 4: code_desc = "EXC_I386_EXTOVR"; break; + case 5: code_desc = "EXC_I386_EXTERR"; break; + case 6: code_desc = "EXC_I386_EMERR"; break; + case 7: code_desc = "EXC_I386_BOUND"; break; + case 8: code_desc = "EXC_I386_SSEEXTERR"; break; + } + break; + + case ArchSpec::eCPU_ppc: + case ArchSpec::eCPU_ppc64: + switch (m_exc_code) + { + case 1: code_desc = "EXC_PPC_OVERFLOW"; break; + case 2: code_desc = "EXC_PPC_ZERO_DIVIDE"; break; + case 3: code_desc = "EXC_PPC_FLT_INEXACT"; break; + case 4: code_desc = "EXC_PPC_FLT_ZERO_DIVIDE"; break; + case 5: code_desc = "EXC_PPC_FLT_UNDERFLOW"; break; + case 6: code_desc = "EXC_PPC_FLT_OVERFLOW"; break; + case 7: code_desc = "EXC_PPC_FLT_NOT_A_NUMBER"; break; + } + break; + + default: + break; + } + break; + + case 4: // EXC_EMULATION + exc_desc = "EXC_EMULATION"; + break; + + + case 5: // EXC_SOFTWARE + exc_desc = "EXC_SOFTWARE"; + if (m_exc_code == 0x10003) + { + subcode_desc = "EXC_SOFT_SIGNAL"; + subcode_label = "signo"; + } + break; + + case 6: // EXC_BREAKPOINT + { + exc_desc = "EXC_BREAKPOINT"; + switch (cpu) + { + case ArchSpec::eCPU_i386: + case ArchSpec::eCPU_x86_64: + switch (m_exc_code) + { + case 1: subcode_desc = "EXC_I386_SGL"; break; + case 2: subcode_desc = "EXC_I386_BPT"; break; + } + break; + + case ArchSpec::eCPU_ppc: + case ArchSpec::eCPU_ppc64: + switch (m_exc_code) + { + case 1: subcode_desc = "EXC_PPC_BREAKPOINT"; break; + } + break; + + case ArchSpec::eCPU_arm: + switch (m_exc_code) + { + case 1: subcode_desc = "EXC_ARM_BREAKPOINT"; break; + } + break; + + default: + break; + } + } + break; + + case 7: + exc_desc = "EXC_SYSCALL"; + break; + + case 8: + exc_desc = "EXC_MACH_SYSCALL"; + break; + + case 9: + exc_desc = "EXC_RPC_ALERT"; + break; + + case 10: + exc_desc = "EXC_CRASH"; + break; + } + + StreamString strm; + + if (exc_desc) + strm.PutCString(exc_desc); + else + strm.Printf("EXC_??? (%llu)", m_value); + + if (m_exc_data_count >= 1) + { + if (code_desc) + strm.Printf(" (%s=%s", code_label, code_desc); + else + strm.Printf(" (%s=%llu", code_label, m_exc_code); + } + + if (m_exc_data_count >= 2) + { + if (subcode_desc) + strm.Printf(", %s=%s", subcode_label, subcode_desc); + else + strm.Printf(", %s=0x%llx", subcode_label, m_exc_subcode); + } + + if (m_exc_data_count > 0) + strm.PutChar(')'); + + m_description.swap (strm.GetString()); + } + return m_description.c_str(); +} + + +StopInfoSP +StopInfoMachException::CreateStopReasonWithMachException +( + Thread &thread, + uint32_t exc_type, + uint32_t exc_data_count, + uint64_t exc_code, + uint64_t exc_sub_code +) +{ + if (exc_type != 0) + { + ArchSpec::CPU cpu = thread.GetProcess().GetTarget().GetArchitecture().GetGenericCPUType(); + + switch (exc_type) + { + case 1: // EXC_BAD_ACCESS + break; + + case 2: // EXC_BAD_INSTRUCTION + switch (cpu) + { + case ArchSpec::eCPU_ppc: + case ArchSpec::eCPU_ppc64: + switch (exc_code) + { + case 1: // EXC_PPC_INVALID_SYSCALL + case 2: // EXC_PPC_UNIPL_INST + case 3: // EXC_PPC_PRIVINST + case 4: // EXC_PPC_PRIVREG + break; + case 5: // EXC_PPC_TRACE + return StopInfo::CreateStopReasonToTrace (thread); + case 6: // EXC_PPC_PERFMON + break; + } + break; + + default: + break; + } + break; + + case 3: // EXC_ARITHMETIC + case 4: // EXC_EMULATION + break; + + case 5: // EXC_SOFTWARE + if (exc_code == 0x10003) // EXC_SOFT_SIGNAL + return StopInfo::CreateStopReasonWithSignal (thread, exc_sub_code); + break; + + case 6: // EXC_BREAKPOINT + { + bool is_software_breakpoint = false; + switch (cpu) + { + case ArchSpec::eCPU_i386: + case ArchSpec::eCPU_x86_64: + if (exc_code == 1) // EXC_I386_SGL + { + return StopInfo::CreateStopReasonToTrace(thread); + } + else if (exc_code == 2) // EXC_I386_BPT + { + is_software_breakpoint = true; + } + break; + + case ArchSpec::eCPU_ppc: + case ArchSpec::eCPU_ppc64: + is_software_breakpoint = exc_code == 1; // EXC_PPC_BREAKPOINT + break; + + case ArchSpec::eCPU_arm: + is_software_breakpoint = exc_code == 1; // EXC_ARM_BREAKPOINT + break; + + default: + break; + } + + if (is_software_breakpoint) + { + addr_t pc = thread.GetRegisterContext()->GetPC(); + lldb::BreakpointSiteSP bp_site_sp = thread.GetProcess().GetBreakpointSiteList().FindByAddress(pc); + if (bp_site_sp) + { + if (bp_site_sp->ValidForThisThread (&thread)) + return StopInfo::CreateStopReasonWithBreakpointSiteID (thread, bp_site_sp->GetID()); + } + } + } + break; + + case 7: // EXC_SYSCALL + case 8: // EXC_MACH_SYSCALL + case 9: // EXC_RPC_ALERT + case 10: // EXC_CRASH + break; + } + + return StopInfoSP(new StopInfoMachException (thread, exc_type, exc_data_count, exc_code, exc_sub_code)); + } + return StopInfoSP(); +} diff --git a/lldb/source/Plugins/Process/Utility/StopInfoMachException.h b/lldb/source/Plugins/Process/Utility/StopInfoMachException.h new file mode 100644 index 00000000000..f9036a47169 --- /dev/null +++ b/lldb/source/Plugins/Process/Utility/StopInfoMachException.h @@ -0,0 +1,75 @@ +//===-- StopInfoMachException.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_StopInfoMachException_h_ +#define liblldb_StopInfoMachException_h_ + +// C Includes +// C++ Includes +#include <string> + +// Other libraries and framework includes +// Project includes +#include "lldb/Target/StopInfo.h" + +namespace lldb_private { + +class StopInfoMachException : public StopInfo +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + StopInfoMachException (Thread &thread, + uint32_t exc_type, + uint32_t exc_data_count, + uint64_t exc_code, + uint64_t exc_subcode) : + StopInfo (thread, exc_type), + m_exc_data_count (exc_data_count), + m_exc_code (exc_code), + m_exc_subcode (exc_subcode) + { + } + + virtual ~StopInfoMachException() + { + } + + + virtual lldb::StopReason + GetStopReason () const + { + return lldb::eStopReasonException; + } + + virtual const char * + GetDescription (); + + // Since some mach exceptions will be reported as breakpoints, signals, + // or trace, we use this static accessor which will translate the mach + // exception into the correct StopInfo. + static lldb::StopInfoSP + CreateStopReasonWithMachException (Thread &thread, + uint32_t exc_type, + uint32_t exc_data_count, + uint64_t exc_code, + uint64_t exc_subcode); + +protected: + uint32_t m_exc_data_count; + uint64_t m_exc_code; + uint64_t m_exc_subcode; + std::string m_description; +}; + + +} // namespace lldb_private + +#endif // liblldb_StopInfoMachException_h_ diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 2bb7a1033a4..759f20dafb4 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -46,6 +46,8 @@ #include "ProcessGDBRemoteLog.h" #include "ThreadGDBRemote.h" #include "MacOSXLibunwindCallbacks.h" +#include "StopInfoMachException.h" + #define DEBUGSERVER_BASENAME "debugserver" @@ -1021,21 +1023,24 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) gdb_thread->SetThreadDispatchQAddr (thread_dispatch_qaddr); gdb_thread->SetName (thread_name.empty() ? thread_name.c_str() : NULL); - Thread::StopInfo& stop_info = gdb_thread->GetStopInfoRef(); - gdb_thread->SetStopInfoStopID (GetStopID()); if (exc_type != 0) { - stop_info.SetStopReasonWithMachException (exc_type, - exc_data.size(), - &exc_data[0]); + const size_t exc_data_count = exc_data.size(); + + gdb_thread->SetStopInfo (StopInfoMachException::CreateStopReasonWithMachException (*thread_sp, + exc_type, + exc_data_count, + exc_data_count >= 1 ? exc_data[0] : 0, + exc_data_count >= 2 ? exc_data[1] : 0)); } else if (signo) { - stop_info.SetStopReasonWithSignal (signo); + gdb_thread->SetStopInfo (StopInfo::CreateStopReasonWithSignal (*thread_sp, signo)); } else { - stop_info.SetStopReasonToNone (); + StopInfoSP invalid_stop_info_sp; + gdb_thread->SetStopInfo (invalid_stop_info_sp); } } return eStateStopped; diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp index 4eae1e6d41b..6f7cf7bc4fd 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp @@ -15,6 +15,7 @@ #include "lldb/Core/StreamString.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" #include "lldb/Target/Unwind.h" #include "lldb/Breakpoint/WatchpointLocation.h" @@ -35,8 +36,6 @@ using namespace lldb_private; ThreadGDBRemote::ThreadGDBRemote (ProcessGDBRemote &process, lldb::tid_t tid) : Thread(process, tid), - m_stop_info_stop_id (0), - m_stop_info (this), m_thread_name (), m_dispatch_queue_name (), m_thread_dispatch_qaddr (LLDB_INVALID_ADDRESS), @@ -83,7 +82,7 @@ ThreadGDBRemote::WillResume (StateType resume_state) // TODO: cache for next time in case we can match things up?? ClearStackFrames(); int signo = GetResumeSignal(); - m_stop_info.Clear(); + switch (resume_state) { case eStateSuspended: @@ -269,11 +268,13 @@ ThreadGDBRemote::RestoreSaveFrameZero (const RegisterCheckpoint &checkpoint) return false; } -bool -ThreadGDBRemote::GetRawStopReason (StopInfo *stop_info) +lldb::StopInfoSP +ThreadGDBRemote::GetPrivateStopReason () { - if (m_stop_info_stop_id != m_process.GetStopID()) + if (m_actual_stop_info_sp.get() == NULL || m_actual_stop_info_sp->IsValid() == false) { + m_actual_stop_info_sp.reset(); + char packet[256]; ::snprintf(packet, sizeof(packet), "qThreadStopInfo%x", GetID()); StringExtractorGDBRemote stop_packet; @@ -281,18 +282,9 @@ ThreadGDBRemote::GetRawStopReason (StopInfo *stop_info) { std::string copy(stop_packet.GetStringRef()); GetGDBProcess().SetThreadStopInfo (stop_packet); - // The process should have set the stop info stop ID and also - // filled this thread in with valid stop info - if (m_stop_info_stop_id != m_process.GetStopID()) - { - //ProcessGDBRemoteLog::LogIf(GDBR_LOG_THREAD, "warning: qThreadStopInfo problem: '%s' => '%s'", packet, stop_packet.GetStringRef().c_str()); - printf("warning: qThreadStopInfo problem: '%s' => '%s'\n\torig '%s'\n", packet, stop_packet.GetStringRef().c_str(), copy.c_str()); /// REMOVE THIS - return false; - } } } - *stop_info = m_stop_info; - return true; + return m_actual_stop_info_sp; } diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h index d40c2e1f6ab..01c37d8b5df 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h @@ -87,22 +87,10 @@ public: const char * GetBasicInfoAsString (); - lldb_private::Thread::StopInfo & - GetStopInfoRef () - { - return m_stop_info; - } - - uint32_t - GetStopInfoStopID() - { - return m_stop_info_stop_id; - } - void - SetStopInfoStopID (uint32_t stop_id) + SetStopInfo (const lldb::StopInfoSP &stop_info) { - m_stop_info_stop_id = stop_id; + m_actual_stop_info_sp = stop_info; } void @@ -130,8 +118,6 @@ protected: //------------------------------------------------------------------ // Member variables. //------------------------------------------------------------------ - uint32_t m_stop_info_stop_id; - lldb_private::Thread::StopInfo m_stop_info; std::string m_thread_name; std::string m_dispatch_queue_name; lldb::addr_t m_thread_dispatch_qaddr; @@ -146,8 +132,8 @@ protected: void SetStopInfoFromPacket (StringExtractor &stop_packet, uint32_t stop_id); - virtual bool - GetRawStopReason (StopInfo *stop_info); + virtual lldb::StopInfoSP + GetPrivateStopReason (); }; diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index f351c7115f2..9f5c42a73f6 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -21,6 +21,7 @@ #include "lldb/Host/Host.h" #include "lldb/Target/ABI.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" #include "lldb/Target/TargetList.h" #include "lldb/Target/Thread.h" @@ -1706,48 +1707,35 @@ Process::ProcessEventData::DoOnRemoval (Event *event_ptr) { int num_threads = m_process_sp->GetThreadList().GetSize(); int idx; - + + int32_t should_stop_count = -1; + int32_t should_run_count = -1; for (idx = 0; idx < num_threads; ++idx) { lldb::ThreadSP thread_sp = m_process_sp->GetThreadList().GetThreadAtIndex(idx); - Thread::StopInfo stop_info; - if (thread_sp->GetStopInfo(&stop_info)) + StopInfo *stop_info = thread_sp->GetStopInfo (); + if (stop_info) { - StopReason reason = stop_info.GetStopReason(); - if (reason == eStopReasonBreakpoint) + if (stop_info->ShouldStop(event_ptr)) { - BreakpointSiteSP bp_site_sp; - // Look up the breakpoint site in the stop info, but the breakpoint - // might be a temporary one that's been deleted between the time we - // hit the breakpoint and now, if so there's nothing to do. - - bp_site_sp = m_process_sp->GetBreakpointSiteList().FindByID (stop_info.GetBreakpointSiteID()); - if (bp_site_sp) - { - size_t num_owners = bp_site_sp->GetNumberOfOwners(); - for (size_t j = 0; j < num_owners; j++) - { - lldb::BreakpointLocationSP bp_loc_sp = bp_site_sp->GetOwnerAtIndex(j); - StoppointCallbackContext context (event_ptr, - m_process_sp.get(), - thread_sp.get(), - thread_sp->GetStackFrameAtIndex(0).get(), - false); - bp_loc_sp->InvokeCallback (&context); - } - } + if (should_stop_count < 0) + should_stop_count = 1; else - { - Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS); - - if (log) - log->Printf ("Process::%s could not find breakpoint site id: %d...", __FUNCTION__, stop_info.GetBreakpointSiteID()); - } - + should_stop_count++; + } + else + { + if (should_run_count < 0) + should_run_count = 1; + else + should_run_count++; } } } + + // Are we secretly watching the private state here? Should we look at the + // should_run_count or the "should_stop_count" and the "should_run_count"??? if (m_process_sp->GetPrivateState() == eStateRunning) SetRestarted(true); } diff --git a/lldb/source/Target/StopInfo.cpp b/lldb/source/Target/StopInfo.cpp new file mode 100644 index 00000000000..9d48e8188d4 --- /dev/null +++ b/lldb/source/Target/StopInfo.cpp @@ -0,0 +1,351 @@ +//===-- StopInfo.cpp ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Target/StopInfo.h" + +// C Includes +// C++ Includes +#include <string> + +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Log.h" +#include "lldb/Breakpoint/BreakpointLocation.h" +#include "lldb/Breakpoint/StoppointCallbackContext.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlan.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/UnixSignals.h" + +using namespace lldb; +using namespace lldb_private; + +StopInfo::StopInfo (Thread &thread, uint64_t value) : + m_thread (thread), + m_stop_id (thread.GetProcess().GetStopID()), + m_value (value) +{ +} + +bool +StopInfo::IsValid () const +{ + return m_thread.GetProcess().GetStopID() == m_stop_id; +} + +//---------------------------------------------------------------------- +// StopInfoBreakpoint +//---------------------------------------------------------------------- + +class StopInfoBreakpoint : public StopInfo +{ +public: + + StopInfoBreakpoint (Thread &thread, break_id_t break_id) : + StopInfo (thread, break_id), + m_description(), + m_should_stop (false), + m_should_stop_is_valid (false) + { + } + + virtual ~StopInfoBreakpoint () + { + } + + virtual StopReason + GetStopReason () const + { + return eStopReasonBreakpoint; + } + + virtual bool + ShouldStop (Event *event_ptr) + { + if (!m_should_stop_is_valid) + { + // Only check once if we should stop at a breakpoint + BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value)); + if (bp_site_sp) + { + StoppointCallbackContext context (event_ptr, + &m_thread.GetProcess(), + &m_thread, + m_thread.GetStackFrameAtIndex(0).get(), + false); + + m_should_stop = bp_site_sp->ShouldStop (&context); + } + else + { + Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS); + + if (log) + log->Printf ("Process::%s could not find breakpoint site id: %lld...", __FUNCTION__, m_value); + + m_should_stop = true; + } + m_should_stop_is_valid = true; + } + return m_should_stop; + } + + virtual bool + ShouldNotify (Event *event_ptr) + { + BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value)); + if (bp_site_sp) + { + bool all_internal = true; + + for (uint32_t i = 0; i < bp_site_sp->GetNumberOfOwners(); i++) + { + if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal()) + { + all_internal = false; + break; + } + } + return all_internal == false; + } + return true; + } + + virtual const char * + GetDescription () + { + if (m_description.empty()) + { + StreamString strm; + strm.Printf("breakpoint %lli", m_value); + m_description.swap (strm.GetString()); + } + return m_description.c_str(); + } + +private: + std::string m_description; + bool m_should_stop; + bool m_should_stop_is_valid; +}; + + +//---------------------------------------------------------------------- +// StopInfoWatchpoint +//---------------------------------------------------------------------- + +class StopInfoWatchpoint : public StopInfo +{ +public: + + StopInfoWatchpoint (Thread &thread, break_id_t watch_id) : + StopInfo (thread, watch_id), + m_description() + { + } + + virtual ~StopInfoWatchpoint () + { + } + + virtual StopReason + GetStopReason () const + { + return eStopReasonWatchpoint; + } + + virtual const char * + GetDescription () + { + if (m_description.empty()) + { + StreamString strm; + strm.Printf("watchpoint %lli", m_value); + m_description.swap (strm.GetString()); + } + return m_description.c_str(); + } + + + +private: + std::string m_description; +}; + + + +//---------------------------------------------------------------------- +// StopInfoUnixSignal +//---------------------------------------------------------------------- + +class StopInfoUnixSignal : public StopInfo +{ +public: + + StopInfoUnixSignal (Thread &thread, int signo) : + StopInfo (thread, signo), + m_description() + { + } + + virtual ~StopInfoUnixSignal () + { + } + + + virtual StopReason + GetStopReason () const + { + return eStopReasonSignal; + } + + virtual bool + ShouldStop (Event *event_ptr) + { + return m_thread.GetProcess().GetUnixSignals().GetShouldStop (m_value); + } + + + // If should stop returns false, check if we should notify of this event + virtual bool + ShouldNotify (Event *event_ptr) + { + return m_thread.GetProcess().GetUnixSignals().GetShouldNotify (m_value); + } + + + virtual void + WillResume (lldb::StateType resume_state) + { + if (m_thread.GetProcess().GetUnixSignals().GetShouldSuppress(m_value) == false) + m_thread.SetResumeSignal(m_value); + } + + virtual const char * + GetDescription () + { + if (m_description.empty()) + { + StreamString strm; + const char *signal_name = m_thread.GetProcess().GetUnixSignals().GetSignalAsCString (m_value); + if (signal_name) + strm.Printf("signal = %s", signal_name); + else + strm.Printf("signal = %lli", m_value); + m_description.swap (strm.GetString()); + } + return m_description.c_str(); + } + +private: + std::string m_description; +}; + +//---------------------------------------------------------------------- +// StopInfoTrace +//---------------------------------------------------------------------- + +class StopInfoTrace : public StopInfo +{ +public: + + StopInfoTrace (Thread &thread) : + StopInfo (thread, LLDB_INVALID_UID) + { + } + + virtual ~StopInfoTrace () + { + } + + virtual StopReason + GetStopReason () const + { + return eStopReasonTrace; + } + + virtual const char * + GetDescription () + { + return "trace"; + } +}; + + +//---------------------------------------------------------------------- +// StopInfoThreadPlan +//---------------------------------------------------------------------- + +class StopInfoThreadPlan : public StopInfo +{ +public: + + StopInfoThreadPlan (ThreadPlanSP &plan_sp) : + StopInfo (plan_sp->GetThread(), LLDB_INVALID_UID), + m_plan_sp (plan_sp) + { + } + + virtual ~StopInfoThreadPlan () + { + } + + virtual StopReason + GetStopReason () const + { + return eStopReasonPlanComplete; + } + + virtual const char * + GetDescription () + { + if (m_description.empty()) + { + StreamString strm; + m_plan_sp->GetDescription (&strm, eDescriptionLevelBrief); + m_description.swap (strm.GetString()); + } + return m_description.c_str(); + } + +private: + ThreadPlanSP m_plan_sp; + std::string m_description; +}; + +StopInfoSP +StopInfo::CreateStopReasonWithBreakpointSiteID (Thread &thread, break_id_t break_id) +{ + return StopInfoSP (new StopInfoBreakpoint (thread, break_id)); +} + +StopInfoSP +StopInfo::CreateStopReasonWithWatchpointID (Thread &thread, break_id_t watch_id) +{ + return StopInfoSP (new StopInfoWatchpoint (thread, watch_id)); +} + +StopInfoSP +StopInfo::CreateStopReasonWithSignal (Thread &thread, int signo) +{ + return StopInfoSP (new StopInfoUnixSignal (thread, signo)); +} + +StopInfoSP +StopInfo::CreateStopReasonToTrace (Thread &thread) +{ + return StopInfoSP (new StopInfoTrace (thread)); +} + +StopInfoSP +StopInfo::CreateStopReasonWithPlan (ThreadPlanSP &plan_sp) +{ + return StopInfoSP (new StopInfoThreadPlan (plan_sp)); +} diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp index e761503eec1..1769cb97b55 100644 --- a/lldb/source/Target/Thread.cpp +++ b/lldb/source/Target/Thread.cpp @@ -17,6 +17,7 @@ #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadPlan.h" @@ -38,6 +39,8 @@ using namespace lldb_private; Thread::Thread (Process &process, lldb::tid_t tid) : UserID (tid), m_process (process), + m_public_stop_info_sp (), + m_actual_stop_info_sp (), m_index_id (process.GetNextThreadIndexID ()), m_reg_context_sp (), m_state (eStateUnloaded), @@ -89,550 +92,24 @@ Thread::SetResumeState (StateType state) m_resume_state = state; } -Thread::StopInfo::StopInfo(Thread *thread) : - m_reason (eStopReasonInvalid), - m_thread (thread), - m_description (), - m_details () +StopInfo * +Thread::GetStopInfo () { - m_description[0] = '\0'; -} - -Thread::StopInfo::~StopInfo() -{ -} - - -void -Thread::StopInfo::Clear() -{ - m_reason = eStopReasonInvalid; - m_completed_plan_sp.reset(); - m_description[0] = '\0'; - ::bzero (&m_details, sizeof(m_details)); -} - -StopReason -Thread::StopInfo::GetStopReason() const -{ - return m_reason; -} - -const char * -Thread::StopInfo::GetStopDescription() const -{ - if (m_description[0]) - return m_description; - return NULL; -} - -void -Thread::StopInfo::SetStopDescription(const char *desc) -{ - if (desc && desc[0]) - { - ::snprintf (m_description, sizeof(m_description), "%s", desc); - } - else - { - m_description[0] = '\0'; - } -} - -void -Thread::StopInfo::SetStopReasonWithMachException -( - uint32_t exc_type, - size_t exc_data_count, - const addr_t *exc_data -) -{ - assert (exc_data_count < LLDB_THREAD_MAX_STOP_EXC_DATA); - assert (m_thread != NULL); - m_reason = eStopReasonException; - m_details.exception.type = exc_type; - m_details.exception.data_count = exc_data_count; - for (size_t i=0; i<exc_data_count; ++i) - m_details.exception.data[i] = exc_data[i]; - - if (m_details.exception.type != 0) - { - ArchSpec::CPU cpu = m_thread->GetProcess().GetTarget().GetArchitecture().GetGenericCPUType(); - - bool exc_translated = false; - const char *exc_desc = NULL; - const char *code_label = "code"; - const char *code_desc = NULL; - const char *subcode_label = "subcode"; - const char *subcode_desc = NULL; - switch (m_details.exception.type) - { - case 1: // EXC_BAD_ACCESS - exc_desc = "EXC_BAD_ACCESS"; - subcode_label = "address"; - switch (cpu) - { - case ArchSpec::eCPU_arm: - switch (m_details.exception.data[0]) - { - case 0x101: code_desc = "EXC_ARM_DA_ALIGN"; break; - case 0x102: code_desc = "EXC_ARM_DA_DEBUG"; break; - } - break; - - case ArchSpec::eCPU_ppc: - case ArchSpec::eCPU_ppc64: - switch (m_details.exception.data[0]) - { - case 0x101: code_desc = "EXC_PPC_VM_PROT_READ"; break; - case 0x102: code_desc = "EXC_PPC_BADSPACE"; break; - case 0x103: code_desc = "EXC_PPC_UNALIGNED"; break; - } - break; - - default: - break; - } - break; - - case 2: // EXC_BAD_INSTRUCTION - exc_desc = "EXC_BAD_INSTRUCTION"; - switch (cpu) - { - case ArchSpec::eCPU_i386: - case ArchSpec::eCPU_x86_64: - if (m_details.exception.data[0] == 1) - code_desc = "EXC_I386_INVOP"; - break; - - case ArchSpec::eCPU_ppc: - case ArchSpec::eCPU_ppc64: - switch (m_details.exception.data[0]) - { - case 1: code_desc = "EXC_PPC_INVALID_SYSCALL"; break; - case 2: code_desc = "EXC_PPC_UNIPL_INST"; break; - case 3: code_desc = "EXC_PPC_PRIVINST"; break; - case 4: code_desc = "EXC_PPC_PRIVREG"; break; - case 5: // EXC_PPC_TRACE - SetStopReasonToTrace(); - exc_translated = true; - break; - case 6: code_desc = "EXC_PPC_PERFMON"; break; - } - break; - - case ArchSpec::eCPU_arm: - if (m_details.exception.data[0] == 1) - code_desc = "EXC_ARM_UNDEFINED"; - break; - - default: - break; - } - break; - - case 3: // EXC_ARITHMETIC - exc_desc = "EXC_ARITHMETIC"; - switch (cpu) - { - case ArchSpec::eCPU_i386: - case ArchSpec::eCPU_x86_64: - switch (m_details.exception.data[0]) - { - case 1: code_desc = "EXC_I386_DIV"; break; - case 2: code_desc = "EXC_I386_INTO"; break; - case 3: code_desc = "EXC_I386_NOEXT"; break; - case 4: code_desc = "EXC_I386_EXTOVR"; break; - case 5: code_desc = "EXC_I386_EXTERR"; break; - case 6: code_desc = "EXC_I386_EMERR"; break; - case 7: code_desc = "EXC_I386_BOUND"; break; - case 8: code_desc = "EXC_I386_SSEEXTERR"; break; - } - break; - - case ArchSpec::eCPU_ppc: - case ArchSpec::eCPU_ppc64: - switch (m_details.exception.data[0]) - { - case 1: code_desc = "EXC_PPC_OVERFLOW"; break; - case 2: code_desc = "EXC_PPC_ZERO_DIVIDE"; break; - case 3: code_desc = "EXC_PPC_FLT_INEXACT"; break; - case 4: code_desc = "EXC_PPC_FLT_ZERO_DIVIDE"; break; - case 5: code_desc = "EXC_PPC_FLT_UNDERFLOW"; break; - case 6: code_desc = "EXC_PPC_FLT_OVERFLOW"; break; - case 7: code_desc = "EXC_PPC_FLT_NOT_A_NUMBER"; break; - } - break; - - default: - break; - } - break; - - case 4: // EXC_EMULATION - exc_desc = "EXC_EMULATION"; - break; - - - case 5: // EXC_SOFTWARE - exc_desc = "EXC_SOFTWARE"; - // Check for EXC_SOFT_SIGNAL - if (m_details.exception.data[0] == 0x10003 && m_details.exception.data_count == 2) - { - SetStopReasonWithSignal(m_details.exception.data[1]); - exc_translated = true; - } - break; - - case 6: - { - exc_desc = "EXC_SOFTWARE"; - bool is_software_breakpoint = false; - switch (cpu) - { - case ArchSpec::eCPU_i386: - case ArchSpec::eCPU_x86_64: - if (m_details.exception.data[0] == 1) // EXC_I386_SGL - { - exc_translated = true; - SetStopReasonToTrace (); - } - else if (m_details.exception.data[0] == 2) // EXC_I386_BPT - { - is_software_breakpoint = true; - } - break; - - case ArchSpec::eCPU_ppc: - case ArchSpec::eCPU_ppc64: - is_software_breakpoint = m_details.exception.data[0] == 1; // EXC_PPC_BREAKPOINT - break; - - case ArchSpec::eCPU_arm: - is_software_breakpoint = m_details.exception.data[0] == 1; // EXC_ARM_BREAKPOINT - break; - - default: - break; - } - - if (is_software_breakpoint) - { - addr_t pc = m_thread->GetRegisterContext()->GetPC(); - lldb::BreakpointSiteSP bp_site_sp = m_thread->GetProcess().GetBreakpointSiteList().FindByAddress(pc); - if (bp_site_sp) - { - exc_translated = true; - if (bp_site_sp->ValidForThisThread (m_thread)) - { - Clear (); - SetStopReasonWithBreakpointSiteID (bp_site_sp->GetID()); - } - else - { - Clear (); - SetStopReasonToNone(); - } - - } - } - } - break; - - case 7: - exc_desc = "EXC_SYSCALL"; - break; - - case 8: - exc_desc = "EXC_MACH_SYSCALL"; - break; - - case 9: - exc_desc = "EXC_RPC_ALERT"; - break; - - case 10: - exc_desc = "EXC_CRASH"; - break; - } - - if (!exc_translated) - { - StreamString desc_strm; - - if (exc_desc) - desc_strm.PutCString(exc_desc); - else - desc_strm.Printf("EXC_??? (%u)", exc_type); - - if (m_details.exception.data_count >= 1) - { - if (code_desc) - desc_strm.Printf(" (%s=%s", code_label, code_desc); - else - desc_strm.Printf(" (%s=%llu", code_label, exc_data[0]); - } - - if (m_details.exception.data_count >= 2) - { - if (subcode_desc) - desc_strm.Printf(", %s=%s", subcode_label, subcode_desc); - else - desc_strm.Printf(", %s=0x%llx", subcode_label, exc_data[1]); - } - - if (m_details.exception.data_count > 0) - desc_strm.PutChar(')'); - - SetStopDescription(desc_strm.GetString().c_str()); - } - } -} -void -Thread::StopInfo::SetThread (Thread* thread) -{ - m_thread = thread; -} - -Thread * -Thread::StopInfo::GetThread () -{ - return m_thread; -} - -lldb::user_id_t -Thread::StopInfo::GetBreakpointSiteID() const -{ - if (m_reason == eStopReasonBreakpoint) - return m_details.breakpoint.bp_site_id; - return LLDB_INVALID_BREAK_ID; -} - -void -Thread::StopInfo::SetStopReasonWithBreakpointSiteID (lldb::user_id_t bp_site_id) -{ - m_reason = eStopReasonBreakpoint; - m_details.breakpoint.bp_site_id = bp_site_id; -} - -lldb::user_id_t -Thread::StopInfo::GetWatchpointID() const -{ - if (m_reason == eStopReasonWatchpoint) - return m_details.watchpoint.watch_id; - return LLDB_INVALID_WATCH_ID; -} - -void -Thread::StopInfo::SetStopReasonWithWatchpointID (lldb::user_id_t watch_id) -{ - m_reason = eStopReasonWatchpoint; - m_details.watchpoint.watch_id = watch_id; -} - - -int -Thread::StopInfo::GetSignal() const -{ - if (m_reason == eStopReasonSignal) - return m_details.signal.signo; - return 0; -} - -lldb::user_id_t -Thread::StopInfo::GetPlanID() const -{ - if (m_reason == eStopReasonPlanComplete) - return m_completed_plan_sp->GetID(); - return LLDB_INVALID_UID; -} - -void -Thread::StopInfo::SetStopReasonWithSignal (int signo) -{ - m_reason = eStopReasonSignal; - m_details.signal.signo = signo; -} - -void -Thread::StopInfo::SetStopReasonToTrace () -{ - m_reason = eStopReasonTrace; -} - -uint32_t -Thread::StopInfo::GetExceptionType() const -{ - if (m_reason == eStopReasonException) - return m_details.exception.type; - return 0; -} - -size_t -Thread::StopInfo::GetExceptionDataCount() const -{ - if (m_reason == eStopReasonException) - return m_details.exception.data_count; - return 0; -} - -void -Thread::StopInfo::SetStopReasonWithGenericException (uint32_t exc_type, size_t exc_data_count) -{ - m_reason = eStopReasonException; - m_details.exception.type = exc_type; - m_details.exception.data_count = exc_data_count; -} - -void -Thread::StopInfo::SetStopReasonWithPlan (ThreadPlanSP &thread_plan_sp) -{ - m_reason = eStopReasonPlanComplete; - m_completed_plan_sp = thread_plan_sp; -} - -void -Thread::StopInfo::SetStopReasonToNone () -{ - Clear(); - m_reason = eStopReasonNone; -} - -lldb::addr_t -Thread::StopInfo::GetExceptionDataAtIndex (uint32_t idx) const -{ - if (m_reason == eStopReasonException && idx < m_details.exception.data_count) - return m_details.exception.data[idx]; - return 0; - -} - - -bool -Thread::StopInfo::SetExceptionDataAtIndex (uint32_t idx, lldb::addr_t data) -{ - if (m_reason == eStopReasonException && idx < m_details.exception.data_count) + if (m_public_stop_info_sp.get() == NULL) { - m_details.exception.data[idx] = data; - return true; - } - return false; -} - -void -Thread::StopInfo::Dump (Stream *s) const -{ - if (m_description[0]) - s->Printf("%s", m_description); - else - { - switch (m_reason) - { - case eStopReasonInvalid: - s->PutCString("invalid"); - break; - - case eStopReasonNone: - s->PutCString("none"); - break; - - case eStopReasonTrace: - s->PutCString("trace"); - break; - - case eStopReasonBreakpoint: - { - bool no_details = true; - s->PutCString ("breakpoint"); - if (m_thread) - { - BreakpointSiteSP bp_site_sp = m_thread->GetProcess().GetBreakpointSiteList().FindByID(m_details.breakpoint.bp_site_id); - if (bp_site_sp) - { - // Only report the breakpoint locations that actually caused this hit - some of them may - // have options that would have caused us not to stop here... - uint32_t num_locations = bp_site_sp->GetNumberOfOwners(); - for (uint32_t i = 0; i < num_locations; i++) - { - BreakpointLocationSP bp_loc_sp = bp_site_sp->GetOwnerAtIndex(i); - if (bp_loc_sp->ValidForThisThread(m_thread)) - { - s->PutCString(" "); - bp_loc_sp->GetDescription(s, lldb::eDescriptionLevelBrief); - no_details = false; - } - } - } - } - - if (no_details) - s->Printf ("site id: %d", m_details.breakpoint.bp_site_id); - } - break; - - case eStopReasonWatchpoint: - s->Printf("watchpoint (site id = %u)", m_details.watchpoint.watch_id); - break; - - case eStopReasonSignal: - { - s->Printf("signal: signo = %i", m_details.signal.signo); - const char * signal_name = m_thread->GetProcess().GetUnixSignals().GetSignalAsCString (m_details.signal.signo); - if (signal_name) - s->Printf(" (%s)", signal_name); - } - break; - - case eStopReasonException: - { - s->Printf("exception: type = 0x%8.8x, data_count = %zu", m_details.exception.type, m_details.exception.data_count); - uint32_t i; - for (i=0; i<m_details.exception.data_count; ++i) - { - s->Printf(", data[%u] = 0x%8.8llx", i, m_details.exception.data[i]); - } - } - break; - - case eStopReasonPlanComplete: - { - m_completed_plan_sp->GetDescription (s, lldb::eDescriptionLevelBrief); - } - break; - } - } -} - -bool -Thread::GetStopInfo (Thread::StopInfo *stop_info) -{ - stop_info->SetThread(this); - ThreadPlanSP completed_plan = GetCompletedPlan(); - if (completed_plan != NULL) - { - stop_info->Clear (); - stop_info->SetStopReasonWithPlan (completed_plan); - return true; + ThreadPlanSP plan_sp (GetCompletedPlan()); + if (plan_sp) + m_public_stop_info_sp = StopInfo::CreateStopReasonWithPlan (plan_sp); + else + m_public_stop_info_sp = GetPrivateStopReason (); } - else - return GetRawStopReason (stop_info); + return m_public_stop_info_sp.get(); } bool Thread::ThreadStoppedForAReason (void) { - Thread::StopInfo stop_info; - stop_info.SetThread(this); - if (GetRawStopReason (&stop_info)) - { - StopReason reason = stop_info.GetStopReason(); - if (reason == eStopReasonInvalid || reason == eStopReasonNone) - return false; - else - return true; - } - else - return false; + return GetPrivateStopReason () != NULL; } StateType @@ -710,26 +187,9 @@ Thread::WillResume (StateType resume_state) m_completed_plan_stack.clear(); m_discarded_plan_stack.clear(); - // If this thread stopped with a signal, work out what its resume state should - // be. Note if the thread resume state is already set, then don't override it, - // the user must have asked us to resume with some other signal. - - if (GetResumeSignal() == LLDB_INVALID_SIGNAL_NUMBER) - { - Thread::StopInfo stop_info; - GetRawStopReason(&stop_info); - - StopReason reason = stop_info.GetStopReason(); - if (reason == eStopReasonSignal) - { - UnixSignals &signals = GetProcess().GetUnixSignals(); - int32_t signo = stop_info.GetSignal(); - if (!signals.GetShouldSuppress(signo)) - { - SetResumeSignal(signo); - } - } - } + StopInfo *stop_info = GetPrivateStopReason().get(); + if (stop_info) + stop_info->WillResume (resume_state); // Tell all the plans that we are about to resume in case they need to clear any state. // We distinguish between the plan on the top of the stack and the lower @@ -742,6 +202,9 @@ Thread::WillResume (StateType resume_state) { plan_ptr->WillResume (resume_state, false); } + + m_public_stop_info_sp.reset(); + m_actual_stop_info_sp.reset(); return true; } @@ -1369,14 +832,13 @@ Thread::DumpInfo if (show_stop_reason) { - Thread::StopInfo thread_stop_info; - if (GetStopInfo(&thread_stop_info)) + StopInfo *stop_info = GetStopInfo(); + + if (stop_info) { - if (thread_stop_info.GetStopReason() != eStopReasonNone) - { - strm.PutCString(", stop reason = "); - thread_stop_info.Dump(&strm); - } + const char *stop_description = stop_info->GetDescription(); + if (stop_description) + strm.Printf (", stop reason = %s", stop_description); } } diff --git a/lldb/source/Target/ThreadPlanBase.cpp b/lldb/source/Target/ThreadPlanBase.cpp index 5f5845429c0..81fe21550f2 100644 --- a/lldb/source/Target/ThreadPlanBase.cpp +++ b/lldb/source/Target/ThreadPlanBase.cpp @@ -21,6 +21,7 @@ #include "lldb/Core/Stream.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/Target/StopInfo.h" using namespace lldb; using namespace lldb_private; @@ -66,110 +67,80 @@ ThreadPlanBase::ShouldStop (Event *event_ptr) m_stop_vote = eVoteYes; m_run_vote = eVoteYes; - Thread::StopInfo stop_info; - if (m_thread.GetStopInfo(&stop_info)) + StopInfo *stop_info = m_thread.GetStopInfo(); + if (stop_info) { - StopReason reason = stop_info.GetStopReason(); + StopReason reason = stop_info->GetStopReason(); switch (reason) { - case eStopReasonInvalid: - case eStopReasonNone: + case eStopReasonInvalid: + case eStopReasonNone: + m_run_vote = eVoteNo; + m_stop_vote = eVoteNo; + return false; + + case eStopReasonBreakpoint: + if (stop_info->ShouldStop(event_ptr)) { - m_run_vote = eVoteNo; - m_stop_vote = eVoteNo; - return false; + // If we are going to stop for a breakpoint, then unship the other plans + // at this point. Don't force the discard, however, so Master plans can stay + // in place if they want to. + m_thread.DiscardThreadPlans(false); + return true; } - case eStopReasonBreakpoint: + // If we aren't going to stop at this breakpoint, and it is internal, + // don't report this stop or the subsequent running event. + // Otherwise we will post the stopped & running, but the stopped event will get marked + // with "restarted" so the UI will know to wait and expect the consequent "running". + if (stop_info->ShouldNotify (event_ptr)) { - // The base plan checks for breakpoint hits. - - BreakpointSiteSP bp_site_sp; - //RegisterContext *reg_ctx = m_thread.GetRegisterContext(); - //lldb::addr_t pc = reg_ctx->GetPC(); - bp_site_sp = m_thread.GetProcess().GetBreakpointSiteList().FindByID (stop_info.GetBreakpointSiteID()); - - if (bp_site_sp && bp_site_sp->IsEnabled()) - { - // We want to step over the breakpoint and then continue. So push these two plans. - - StoppointCallbackContext hit_context(event_ptr, &m_thread.GetProcess(), &m_thread, - m_thread.GetStackFrameAtIndex(0).get()); - bool should_stop = m_thread.GetProcess().GetBreakpointSiteList().ShouldStop(&hit_context, - bp_site_sp->GetID()); - - if (!should_stop) - { - // If we aren't going to stop at this breakpoint, and it is internal, - // don't report this stop or the subsequent running event. - // Otherwise we will post the stopped & running, but the stopped event will get marked - // with "restarted" so the UI will know to wait and expect the consequent "running". - uint32_t i; - bool is_wholly_internal = true; - - for (i = 0; i < bp_site_sp->GetNumberOfOwners(); i++) - { - if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal()) - { - is_wholly_internal = false; - break; - } - } - if (is_wholly_internal) - { - m_stop_vote = eVoteNo; - m_run_vote = eVoteNo; - } - else - { - m_stop_vote = eVoteYes; - m_run_vote = eVoteYes; - } - - } - else - { - // If we are going to stop for a breakpoint, then unship the other plans - // at this point. Don't force the discard, however, so Master plans can stay - // in place if they want to. - m_thread.DiscardThreadPlans(false); - } - - return should_stop; - } + m_stop_vote = eVoteYes; + m_run_vote = eVoteYes; + } + else + { + m_stop_vote = eVoteNo; + m_run_vote = eVoteNo; } - case eStopReasonException: - // If we crashed, discard thread plans and stop. Don't force the discard, however, - // since on rerun the target may clean up this exception and continue normally from there. + return false; + + // TODO: the break below was missing, was this intentional??? If so + // please mention it + break; + + case eStopReasonException: + // If we crashed, discard thread plans and stop. Don't force the discard, however, + // since on rerun the target may clean up this exception and continue normally from there. + m_thread.DiscardThreadPlans(false); + return true; + + case eStopReasonSignal: + if (stop_info->ShouldStop(event_ptr)) + { m_thread.DiscardThreadPlans(false); return true; - case eStopReasonSignal: + } + else { - // Check the signal handling, and if we are stopping for the signal, - // discard the plans and stop. - UnixSignals &signals = m_thread.GetProcess().GetUnixSignals(); - uint32_t signo = stop_info.GetSignal(); - if (signals.GetShouldStop(signo)) - { - m_thread.DiscardThreadPlans(false); - return true; - } + // We're not going to stop, but while we are here, let's figure out + // whether to report this. + if (stop_info->ShouldNotify(event_ptr)) + m_stop_vote = eVoteYes; else - { - // We're not going to stop, but while we are here, let's figure out - // whether to report this. - if (signals.GetShouldNotify(signo)) - m_stop_vote = eVoteYes; - else - m_stop_vote = eVoteNo; - - return false; - } + m_stop_vote = eVoteNo; } - default: - return true; + return false; + + default: + return true; } } + else + { + m_run_vote = eVoteNo; + m_stop_vote = eVoteNo; + } // If there's no explicit reason to stop, then we will continue. return false; diff --git a/lldb/source/Target/ThreadPlanStepInstruction.cpp b/lldb/source/Target/ThreadPlanStepInstruction.cpp index a59d928624c..b469566b2c2 100644 --- a/lldb/source/Target/ThreadPlanStepInstruction.cpp +++ b/lldb/source/Target/ThreadPlanStepInstruction.cpp @@ -17,10 +17,11 @@ #include "lldb/lldb-private-log.h" #include "lldb/Core/Log.h" #include "lldb/Core/Stream.h" +#include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" -#include "lldb/Target/Target.h" #include "lldb/Target/RegisterContext.h" -#include "lldb/Target/Process.h" +#include "lldb/Target/StopInfo.h" +#include "lldb/Target/Target.h" using namespace lldb; using namespace lldb_private; @@ -83,11 +84,11 @@ ThreadPlanStepInstruction::ValidatePlan (Stream *error) bool ThreadPlanStepInstruction::PlanExplainsStop () { - Thread::StopInfo info; - if (m_thread.GetStopInfo (&info)) + StopInfo *stop_info = m_thread.GetStopInfo(); + if (stop_info) { - StopReason reason = info.GetStopReason(); - if (reason == eStopReasonTrace || reason ==eStopReasonNone) + StopReason reason = stop_info->GetStopReason(); + if (reason == eStopReasonTrace || reason == eStopReasonNone) return true; else return false; diff --git a/lldb/source/Target/ThreadPlanStepOut.cpp b/lldb/source/Target/ThreadPlanStepOut.cpp index 10576b017e5..fd9f8faf99d 100644 --- a/lldb/source/Target/ThreadPlanStepOut.cpp +++ b/lldb/source/Target/ThreadPlanStepOut.cpp @@ -18,6 +18,7 @@ #include "lldb/Core/Log.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" using namespace lldb; @@ -102,44 +103,37 @@ ThreadPlanStepOut::PlanExplainsStop () { // We don't explain signals or breakpoints (breakpoints that handle stepping in or // out will be handled by a child plan. - Thread::StopInfo info; - if (m_thread.GetStopInfo (&info)) + StopInfo *stop_info = m_thread.GetStopInfo(); + if (stop_info) { - StopReason reason = info.GetStopReason(); - + StopReason reason = stop_info->GetStopReason(); switch (reason) { - case eStopReasonBreakpoint: + case eStopReasonBreakpoint: + { + // If this is OUR breakpoint, we're fine, otherwise we don't know why this happened... + BreakpointSiteSP site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (stop_info->GetValue())); + if (site_sp && site_sp->IsBreakpointAtThisSite (m_return_bp_id)) { - // If this is OUR breakpoint, we're fine, otherwise we don't know why this happened... - BreakpointSiteSP this_site = m_thread.GetProcess().GetBreakpointSiteList().FindByID (info.GetBreakpointSiteID()); - if (!this_site) - return false; - - if (this_site->IsBreakpointAtThisSite (m_return_bp_id)) - { - // If there was only one owner, then we're done. But if we also hit some - // user breakpoint on our way out, we should mark ourselves as done, but - // also not claim to explain the stop, since it is more important to report - // the user breakpoint than the step out completion. - - if (this_site->GetNumberOfOwners() == 1) - return true; - else - { - SetPlanComplete(); - return false; - } - } - else - return false; + // If there was only one owner, then we're done. But if we also hit some + // user breakpoint on our way out, we should mark ourselves as done, but + // also not claim to explain the stop, since it is more important to report + // the user breakpoint than the step out completion. + + if (site_sp->GetNumberOfOwners() == 1) + return true; + + SetPlanComplete(); } - case eStopReasonWatchpoint: - case eStopReasonSignal: - case eStopReasonException: - return false; - default: - return true; + return false; + } + case eStopReasonWatchpoint: + case eStopReasonSignal: + case eStopReasonException: + return false; + + default: + return true; } } return true; diff --git a/lldb/source/Target/ThreadPlanStepRange.cpp b/lldb/source/Target/ThreadPlanStepRange.cpp index 76ec5b854bd..0885e954f40 100644 --- a/lldb/source/Target/ThreadPlanStepRange.cpp +++ b/lldb/source/Target/ThreadPlanStepRange.cpp @@ -17,11 +17,12 @@ #include "lldb/lldb-private-log.h" #include "lldb/Core/Log.h" #include "lldb/Core/Stream.h" -#include "lldb/Target/RegisterContext.h" -#include "lldb/Target/Thread.h" -#include "lldb/Target/Process.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/Symbol.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/StopInfo.h" +#include "lldb/Target/Thread.h" using namespace lldb; using namespace lldb_private; @@ -61,20 +62,20 @@ ThreadPlanStepRange::PlanExplainsStop () { // We don't explain signals or breakpoints (breakpoints that handle stepping in or // out will be handled by a child plan. - Thread::StopInfo info; - if (m_thread.GetStopInfo (&info)) + StopInfo *stop_info = m_thread.GetStopInfo(); + if (stop_info) { - StopReason reason = info.GetStopReason(); + StopReason reason = stop_info->GetStopReason(); switch (reason) { - case eStopReasonBreakpoint: - case eStopReasonWatchpoint: - case eStopReasonSignal: - case eStopReasonException: - return false; - default: - return true; + case eStopReasonBreakpoint: + case eStopReasonWatchpoint: + case eStopReasonSignal: + case eStopReasonException: + return false; + default: + return true; } } return true; diff --git a/lldb/source/Target/ThreadPlanStepUntil.cpp b/lldb/source/Target/ThreadPlanStepUntil.cpp index 99f1a5e4d4c..8c0748bce33 100644 --- a/lldb/source/Target/ThreadPlanStepUntil.cpp +++ b/lldb/source/Target/ThreadPlanStepUntil.cpp @@ -22,6 +22,7 @@ #include "lldb/Core/Log.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" using namespace lldb; @@ -168,20 +169,20 @@ ThreadPlanStepUntil::AnalyzeStop() if (m_ran_analyze) return; - Thread::StopInfo info; + StopInfo *stop_info = m_thread.GetStopInfo(); m_should_stop = true; m_explains_stop = false; - if (m_thread.GetStopInfo (&info)) + if (stop_info) { - StopReason reason = info.GetStopReason(); + StopReason reason = stop_info->GetStopReason(); switch (reason) { case eStopReasonBreakpoint: { // If this is OUR breakpoint, we're fine, otherwise we don't know why this happened... - BreakpointSiteSP this_site = m_thread.GetProcess().GetBreakpointSiteList().FindByID (info.GetBreakpointSiteID()); + BreakpointSiteSP this_site = m_thread.GetProcess().GetBreakpointSiteList().FindByID (stop_info->GetValue()); if (!this_site) { m_explains_stop = false; @@ -273,9 +274,8 @@ ThreadPlanStepUntil::ShouldStop (Event *event_ptr) // do so here. Otherwise, as long as this thread has stopped for a reason, // we will stop. - Thread::StopInfo stop_info (&m_thread); - if (!m_thread.GetStopInfo(&stop_info) - || stop_info.GetStopReason() == eStopReasonNone) + StopInfo *stop_info = m_thread.GetStopInfo (); + if (stop_info == NULL || stop_info->GetStopReason() == eStopReasonNone) return false; AnalyzeStop(); |