Author: ki.stfu Date: Wed May 20 05:15:47 2015 New Revision: 237781 URL: http://llvm.org/viewvc/llvm-project?rev=237781&view=rev Log: Fix handling of hijacked events in synchronous mode
Summary: This patch includes the following changes: * Fix Target::Launch to handle hijacked event in synchronous mode * Improve MiStartupOptionsTestCase tests to expect *stopped (MI) * Add SBProcess::GetStopEventForStopID * Add ProcessModID::SetStopEventForLastNaturalStopID/GetStopEventForStopID * Add const qualifier to ProcessModID::GetLastNaturalStopID * Add SBProcess::GetStopEventForStopID * Don't broadcast hijacked event in Target::Launch * Add CMICmnLLDBDebugger::CheckIfNeedToRebroadcastStopEvent/RebroadcastStopEvent Test Plan: ./dotest.py -v --executable $BUILDDIR/bin/lldb tools/lldb-mi/startup_options/ Reviewers: zturner, jingham, clayborg, abidh Reviewed By: clayborg Subscribers: abidh, zturner, lldb-commits, clayborg, jingham Differential Revision: http://reviews.llvm.org/D9371 Modified: lldb/trunk/include/lldb/API/SBProcess.h lldb/trunk/include/lldb/Target/Process.h lldb/trunk/source/API/SBProcess.cpp lldb/trunk/source/Target/Process.cpp lldb/trunk/source/Target/Target.cpp lldb/trunk/test/tools/lldb-mi/startup_options/TestMiStartupOptions.py lldb/trunk/tools/lldb-mi/MICmnLLDBDebugger.cpp lldb/trunk/tools/lldb-mi/MICmnLLDBDebugger.h lldb/trunk/tools/lldb-mi/MIDriver.cpp Modified: lldb/trunk/include/lldb/API/SBProcess.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBProcess.h?rev=237781&r1=237780&r2=237781&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBProcess.h (original) +++ lldb/trunk/include/lldb/API/SBProcess.h Wed May 20 05:15:47 2015 @@ -229,7 +229,22 @@ public: uint32_t GetStopID(bool include_expression_stops = false); - + + //------------------------------------------------------------------ + /// Gets the stop event corresponding to stop ID. + // + /// Note that it wasn't fully implemented and tracks only the stop + /// event for the last natural stop ID. + /// + /// @param [in] stop_id + /// The ID of the stop event to return. + /// + /// @return + /// The stop event corresponding to stop ID. + //------------------------------------------------------------------ + lldb::SBEvent + GetStopEventForStopID(uint32_t stop_id); + size_t ReadMemory (addr_t addr, void *buf, size_t size, lldb::SBError &error); Modified: lldb/trunk/include/lldb/Target/Process.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Process.h?rev=237781&r1=237780&r2=237781&view=diff ============================================================================== --- lldb/trunk/include/lldb/Target/Process.h (original) +++ lldb/trunk/include/lldb/Target/Process.h Wed May 20 05:15:47 2015 @@ -685,7 +685,20 @@ public: else m_running_user_expression--; } - + + void + SetStopEventForLastNaturalStopID (lldb::EventSP event_sp) + { + m_last_natural_stop_event = event_sp; + } + + lldb::EventSP GetStopEventForStopID (uint32_t stop_id) const + { + if (stop_id == m_last_natural_stop_id) + return m_last_natural_stop_event; + return lldb::EventSP(); + } + private: uint32_t m_stop_id; uint32_t m_last_natural_stop_id; @@ -693,6 +706,7 @@ private: uint32_t m_memory_id; uint32_t m_last_user_expression_resume; uint32_t m_running_user_expression; + lldb::EventSP m_last_natural_stop_event; }; inline bool operator== (const ProcessModID &lhs, const ProcessModID &rhs) { @@ -1954,11 +1968,17 @@ public: } uint32_t - GetLastNaturalStopID() + GetLastNaturalStopID() const { return m_mod_id.GetLastNaturalStopID(); } - + + lldb::EventSP + GetStopEventForStopID (uint32_t stop_id) const + { + return m_mod_id.GetStopEventForStopID(stop_id); + } + //------------------------------------------------------------------ /// Set accessor for the process exit status (return code). /// Modified: lldb/trunk/source/API/SBProcess.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBProcess.cpp?rev=237781&r1=237780&r2=237781&view=diff ============================================================================== --- lldb/trunk/source/API/SBProcess.cpp (original) +++ lldb/trunk/source/API/SBProcess.cpp Wed May 20 05:15:47 2015 @@ -603,6 +603,30 @@ SBProcess::GetStopID(bool include_expres return 0; } +SBEvent +SBProcess::GetStopEventForStopID(uint32_t stop_id) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + + SBEvent sb_event; + EventSP event_sp; + ProcessSP process_sp(GetSP()); + if (process_sp) + { + Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); + event_sp = process_sp->GetStopEventForStopID(stop_id); + sb_event.reset(event_sp); + } + + if (log) + log->Printf ("SBProcess(%p)::GetStopEventForStopID (stop_id=%" PRIu32 ") => SBEvent(%p)", + static_cast<void*>(process_sp.get()), + stop_id, + static_cast<void*>(event_sp.get())); + + return sb_event; +} + StateType SBProcess::GetState () { Modified: lldb/trunk/source/Target/Process.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Process.cpp?rev=237781&r1=237780&r2=237781&view=diff ============================================================================== --- lldb/trunk/source/Target/Process.cpp (original) +++ lldb/trunk/source/Target/Process.cpp Wed May 20 05:15:47 2015 @@ -1796,6 +1796,7 @@ Process::SetPrivateState (StateType new_ if (state_changed) { m_private_state.SetValueNoLock (new_state); + EventSP event_sp (new Event (eBroadcastBitStateChanged, new ProcessEventData (shared_from_this(), new_state))); if (StateIsStoppedState(new_state, false)) { // Note, this currently assumes that all threads in the list @@ -1812,15 +1813,18 @@ Process::SetPrivateState (StateType new_ m_thread_list.DidStop(); m_mod_id.BumpStopID(); + if (!m_mod_id.IsLastResumeForUserExpression()) + m_mod_id.SetStopEventForLastNaturalStopID(event_sp); m_memory_cache.Clear(); if (log) log->Printf("Process::SetPrivateState (%s) stop_id = %u", StateAsCString(new_state), m_mod_id.GetStopID()); } + // Use our target to get a shared pointer to ourselves... if (m_finalize_called && PrivateStateThreadIsValid() == false) - BroadcastEvent (eBroadcastBitStateChanged, new ProcessEventData (shared_from_this(), new_state)); + BroadcastEvent (event_sp); else - m_private_state_broadcaster.BroadcastEvent (eBroadcastBitStateChanged, new ProcessEventData (shared_from_this(), new_state)); + m_private_state_broadcaster.BroadcastEvent (event_sp); } else { Modified: lldb/trunk/source/Target/Target.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Target.cpp?rev=237781&r1=237780&r2=237781&view=diff ============================================================================== --- lldb/trunk/source/Target/Target.cpp (original) +++ lldb/trunk/source/Target/Target.cpp Wed May 20 05:15:47 2015 @@ -2617,7 +2617,6 @@ Target::Launch (ProcessLaunchInfo &launc { if (synchronous_execution || launch_info.GetFlags().Test(eLaunchFlagStopAtEntry) == false) { - EventSP event_sp; ListenerSP hijack_listener_sp (launch_info.GetHijackListener()); if (!hijack_listener_sp) { @@ -2626,7 +2625,7 @@ Target::Launch (ProcessLaunchInfo &launc m_process_sp->HijackProcessEvents(hijack_listener_sp.get()); } - StateType state = m_process_sp->WaitForProcessToStop (NULL, &event_sp, false, hijack_listener_sp.get(), NULL); + StateType state = m_process_sp->WaitForProcessToStop (NULL, NULL, false, hijack_listener_sp.get(), NULL); if (state == eStateStopped) { @@ -2657,14 +2656,6 @@ Target::Launch (ProcessLaunchInfo &launc error = error2; } } - else - { - assert(synchronous_execution && launch_info.GetFlags().Test(eLaunchFlagStopAtEntry)); - - // Target was stopped at entry as was intended. Need to notify the listeners about it. - m_process_sp->RestoreProcessEvents(); - m_process_sp->HandlePrivateEvent(event_sp); - } } else if (state == eStateExited) { Modified: lldb/trunk/test/tools/lldb-mi/startup_options/TestMiStartupOptions.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/tools/lldb-mi/startup_options/TestMiStartupOptions.py?rev=237781&r1=237780&r2=237781&view=diff ============================================================================== --- lldb/trunk/test/tools/lldb-mi/startup_options/TestMiStartupOptions.py (original) +++ lldb/trunk/test/tools/lldb-mi/startup_options/TestMiStartupOptions.py Wed May 20 05:15:47 2015 @@ -143,6 +143,7 @@ class MiStartupOptionsTestCase(lldbmi_te # After '-exec-run' self.expect("-exec-run") self.expect("\^running") + self.expect("\*stopped,reason=\"breakpoint-hit\"") # After '-break-insert main.cpp:BP_return' line = line_number('main.cpp', '//BP_return') @@ -152,6 +153,7 @@ class MiStartupOptionsTestCase(lldbmi_te # After '-exec-continue' self.expect("-exec-continue") self.expect("\^running") + self.expect("\*stopped,reason=\"breakpoint-hit\"") # Test that lldb-mi is ready after execution of --source start_script self.expect(self.child_prompt, exactly = True) @@ -184,6 +186,7 @@ class MiStartupOptionsTestCase(lldbmi_te # After '-exec-run' self.expect("-exec-run") self.expect("\^running") + self.expect("\*stopped,reason=\"breakpoint-hit\"") # After '-break-insert main.cpp:BP_return' line = line_number('main.cpp', '//BP_return') @@ -193,6 +196,7 @@ class MiStartupOptionsTestCase(lldbmi_te # After '-exec-continue' self.expect("-exec-continue") self.expect("\^running") + self.expect("\*stopped,reason=\"breakpoint-hit\"") # After '-data-evaluate-expression a' self.expect("-data-evaluate-expression a") @@ -201,6 +205,7 @@ class MiStartupOptionsTestCase(lldbmi_te # After '-gdb-exit' self.expect("-gdb-exit") self.expect("\^exit") + self.expect("\*stopped,reason=\"exited-normally\"") @lldbmi_test @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") Modified: lldb/trunk/tools/lldb-mi/MICmnLLDBDebugger.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MICmnLLDBDebugger.cpp?rev=237781&r1=237780&r2=237781&view=diff ============================================================================== --- lldb/trunk/tools/lldb-mi/MICmnLLDBDebugger.cpp (original) +++ lldb/trunk/tools/lldb-mi/MICmnLLDBDebugger.cpp Wed May 20 05:15:47 2015 @@ -244,6 +244,51 @@ CMICmnLLDBDebugger::WaitForHandleEvent(v } //++ ------------------------------------------------------------------------------------ +// Details: Check if need to rebroadcast stop event. This function will return true if +// debugger is in synchronouse mode. In such case the +// CMICmnLLDBDebugger::RebroadcastStopEvent should be called to rebroadcast +// a new stop event (if any). +// Type: Method. +// Args: None. +// Return: bool - True = Need to rebroadcast stop event, false = otherwise. +// Throws: None. +//-- +bool +CMICmnLLDBDebugger::CheckIfNeedToRebroadcastStopEvent(void) +{ + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + if (!rSessionInfo.GetDebugger().GetAsync()) + { + const bool include_expression_stops = false; + m_nLastStopId = CMICmnLLDBDebugSessionInfo::Instance().GetProcess().GetStopID(include_expression_stops); + return true; + } + + return false; +} + +//++ ------------------------------------------------------------------------------------ +// Details: Rebroadcast stop event if needed. This function should be called only if the +// CMICmnLLDBDebugger::CheckIfNeedToRebroadcastStopEvent() returned true. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. +//-- +void +CMICmnLLDBDebugger::RebroadcastStopEvent(void) +{ + lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); + const bool include_expression_stops = false; + const uint32_t nStopId = process.GetStopID(include_expression_stops); + if (m_nLastStopId != nStopId) + { + lldb::SBEvent event = process.GetStopEventForStopID(nStopId); + process.GetBroadcaster().BroadcastEvent(event); + } +} + +//++ ------------------------------------------------------------------------------------ // Details: Initialize the LLDB Debugger object. // Type: Method. // Args: None. Modified: lldb/trunk/tools/lldb-mi/MICmnLLDBDebugger.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MICmnLLDBDebugger.h?rev=237781&r1=237780&r2=237781&view=diff ============================================================================== --- lldb/trunk/tools/lldb-mi/MICmnLLDBDebugger.h (original) +++ lldb/trunk/tools/lldb-mi/MICmnLLDBDebugger.h Wed May 20 05:15:47 2015 @@ -50,6 +50,8 @@ class CMICmnLLDBDebugger : public CMICmn lldb::SBDebugger &GetTheDebugger(void); lldb::SBListener &GetTheListener(void); void WaitForHandleEvent(void); + bool CheckIfNeedToRebroadcastStopEvent(void); + void RebroadcastStopEvent(void); // MI Commands can use these functions to listen for events they require bool RegisterForEvent(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass, const MIuint vEventMask); @@ -110,4 +112,5 @@ class CMICmnLLDBDebugger : public CMICmn MapIdToEventMask_t m_mapIdToEventMask; std::mutex m_mutexEventQueue; std::condition_variable m_conditionEventQueueEmpty; + uint32_t m_nLastStopId; }; Modified: lldb/trunk/tools/lldb-mi/MIDriver.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MIDriver.cpp?rev=237781&r1=237780&r2=237781&view=diff ============================================================================== --- lldb/trunk/tools/lldb-mi/MIDriver.cpp (original) +++ lldb/trunk/tools/lldb-mi/MIDriver.cpp Wed May 20 05:15:47 2015 @@ -823,11 +823,15 @@ CMIDriver::GetId(void) const bool CMIDriver::InterpretCommand(const CMIUtilString &vTextLine) { + const bool bNeedToRebroadcastStopEvent = m_rLldbDebugger.CheckIfNeedToRebroadcastStopEvent(); bool bCmdYesValid = false; bool bOk = InterpretCommandThisDriver(vTextLine, bCmdYesValid); if (bOk && !bCmdYesValid) bOk = InterpretCommandFallThruDriver(vTextLine, bCmdYesValid); + if (bNeedToRebroadcastStopEvent) + m_rLldbDebugger.RebroadcastStopEvent(); + return bOk; } _______________________________________________ lldb-commits mailing list lldb-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits