diff options
author | Ed Maste <emaste@FreeBSD.org> | 2015-02-06 21:38:51 +0000 |
---|---|---|
committer | Ed Maste <emaste@FreeBSD.org> | 2015-02-06 21:38:51 +0000 |
commit | 205afe679855a4ce8149cdaa94d3f0868ce796dc (patch) | |
tree | 09bc83f73246ee3c7a779605cd0122093d2a8a19 /source/Target/Process.cpp | |
parent | 0cac4ca3916ac24ab6139d03cbfd18db9e715bfe (diff) | |
download | src-test2-205afe679855a4ce8149cdaa94d3f0868ce796dc.tar.gz src-test2-205afe679855a4ce8149cdaa94d3f0868ce796dc.zip |
Notes
Diffstat (limited to 'source/Target/Process.cpp')
-rw-r--r-- | source/Target/Process.cpp | 518 |
1 files changed, 439 insertions, 79 deletions
diff --git a/source/Target/Process.cpp b/source/Target/Process.cpp index a1049787d821..106678da2684 100644 --- a/source/Target/Process.cpp +++ b/source/Target/Process.cpp @@ -16,22 +16,25 @@ #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Core/Event.h" -#include "lldb/Core/ConnectionFileDescriptor.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" -#include "lldb/Symbol/Symbol.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/State.h" #include "lldb/Core/StreamFile.h" #include "lldb/Expression/ClangUserExpression.h" -#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/Host.h" +#include "lldb/Host/HostInfo.h" #include "lldb/Host/Pipe.h" #include "lldb/Host/Terminal.h" +#include "lldb/Host/ThreadLauncher.h" +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Symbol/Symbol.h" #include "lldb/Target/ABI.h" #include "lldb/Target/DynamicLoader.h" #include "lldb/Target/JITLoader.h" +#include "lldb/Target/MemoryHistory.h" #include "lldb/Target/OperatingSystem.h" #include "lldb/Target/LanguageRuntime.h" #include "lldb/Target/CPPLanguageRuntime.h" @@ -45,6 +48,7 @@ #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadPlan.h" #include "lldb/Target/ThreadPlanBase.h" +#include "lldb/Target/InstrumentationRuntime.h" #include "Plugins/Process/Utility/InferiorCallPOSIX.h" using namespace lldb; @@ -108,6 +112,7 @@ g_properties[] = { "python-os-plugin-path", OptionValue::eTypeFileSpec, false, true, NULL, NULL, "A path to a python OS plug-in module file that contains a OperatingSystemPlugIn class." }, { "stop-on-sharedlibrary-events" , OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true, stop when a shared library is loaded or unloaded." }, { "detach-keeps-stopped" , OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true, detach will attempt to keep the process stopped." }, + { "memory-cache-line-size" , OptionValue::eTypeUInt64, false, 512, NULL, NULL, "The memory cache line size" }, { NULL , OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL } }; @@ -118,14 +123,17 @@ enum { ePropertyUnwindOnErrorInExpressions, ePropertyPythonOSPluginPath, ePropertyStopOnSharedLibraryEvents, - ePropertyDetachKeepsStopped + ePropertyDetachKeepsStopped, + ePropertyMemCacheLineSize }; -ProcessProperties::ProcessProperties (bool is_global) : - Properties () +ProcessProperties::ProcessProperties (lldb_private::Process *process) : + Properties (), + m_process (process) // Can be NULL for global ProcessProperties { - if (is_global) + if (process == NULL) { + // Global process properties, set them up one time m_collection_sp.reset (new ProcessOptionValueProperties(ConstString("process"))); m_collection_sp->Initialize(g_properties); m_collection_sp->AppendProperty(ConstString("thread"), @@ -134,13 +142,24 @@ ProcessProperties::ProcessProperties (bool is_global) : Thread::GetGlobalProperties()->GetValueProperties()); } else + { m_collection_sp.reset (new ProcessOptionValueProperties(Process::GetGlobalProperties().get())); + m_collection_sp->SetValueChangedCallback(ePropertyPythonOSPluginPath, ProcessProperties::OptionValueChangedCallback, this); + } } ProcessProperties::~ProcessProperties() { } +void +ProcessProperties::OptionValueChangedCallback (void *baton, OptionValue *option_value) +{ + ProcessProperties *properties = (ProcessProperties *)baton; + if (properties->m_process) + properties->m_process->LoadOperatingSystemPlugin(true); +} + bool ProcessProperties::GetDisableMemoryCache() const { @@ -148,6 +167,13 @@ ProcessProperties::GetDisableMemoryCache() const return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); } +uint64_t +ProcessProperties::GetMemoryCacheLineSize() const +{ + const uint32_t idx = ePropertyMemCacheLineSize; + return m_collection_sp->GetPropertyAtIndexAsUInt64 (NULL, idx, g_properties[idx].default_uint_value); +} + Args ProcessProperties::GetExtraStartupCommands () const { @@ -467,9 +493,9 @@ ProcessLaunchCommandOptions::SetOptionValue (uint32_t option_idx, const char *op case 'c': if (option_arg && option_arg[0]) - launch_info.SetShell (option_arg); + launch_info.SetShell (FileSpec(option_arg, false)); else - launch_info.SetShell (LLDB_DEFAULT_SHELL); + launch_info.SetShell (HostInfo::GetDefaultShell()); break; case 'v': @@ -660,7 +686,7 @@ Process::Process(Target &target, Listener &listener) : } Process::Process(Target &target, Listener &listener, const UnixSignalsSP &unix_signals_sp) : - ProcessProperties (false), + ProcessProperties (this), UserID (LLDB_INVALID_PROCESS_ID), Broadcaster (&(target.GetDebugger()), "lldb.process"), m_target (target), @@ -670,13 +696,13 @@ Process::Process(Target &target, Listener &listener, const UnixSignalsSP &unix_s m_private_state_control_broadcaster (NULL, "lldb.process.internal_state_control_broadcaster"), m_private_state_listener ("lldb.process.internal_state_listener"), m_private_state_control_wait(), - m_private_state_thread (LLDB_INVALID_HOST_THREAD), m_mod_id (), m_process_unique_id(0), m_thread_index_id (0), m_thread_id_to_index_id_map (), m_exit_status (-1), m_exit_string (), + m_exit_status_mutex(), m_thread_mutex (Mutex::eMutexTypeRecursive), m_thread_list_real (this), m_thread_list (this), @@ -706,6 +732,7 @@ Process::Process(Target &target, Listener &listener, const UnixSignalsSP &unix_s m_public_run_lock (), m_private_run_lock (), m_currently_handling_event(false), + m_stop_info_override_callback (NULL), m_finalize_called(false), m_clear_thread_plans_on_stop (false), m_force_next_event_delivery(false), @@ -760,6 +787,11 @@ Process::~Process() if (log) log->Printf ("%p Process::~Process()", static_cast<void*>(this)); StopPrivateStateThread(); + + // ThreadList::Clear() will try to acquire this process's mutex, so + // explicitly clear the thread list here to ensure that the mutex + // is not destroyed before the thread list. + m_thread_list.Clear(); } const ProcessPropertiesSP & @@ -767,7 +799,7 @@ Process::GetGlobalProperties() { static ProcessPropertiesSP g_settings_sp; if (!g_settings_sp) - g_settings_sp.reset (new ProcessProperties (true)); + g_settings_sp.reset (new ProcessProperties (NULL)); return g_settings_sp; } @@ -826,7 +858,9 @@ Process::Finalize() m_memory_cache.Clear(); m_allocated_memory_cache.Clear(); m_language_runtimes.clear(); + m_instrumentation_runtimes.clear(); m_next_event_action_ap.reset(); + m_stop_info_override_callback = NULL; //#ifdef LLDB_CONFIGURATION_DEBUG // StreamFile s(stdout, false); // EventSP event_sp; @@ -924,7 +958,7 @@ Process::SyncIOHandler (uint64_t timeout_msec) log->Printf ("Process::%s pid %" PRIu64 ": SUCCESS", __FUNCTION__, GetID ()); } - // reset sync one-shot so it will be ready for next time + // reset sync one-shot so it will be ready for next launch m_iohandler_sync.SetValue(false, eBroadcastNever); } @@ -932,7 +966,11 @@ Process::SyncIOHandler (uint64_t timeout_msec) } StateType -Process::WaitForProcessToStop (const TimeValue *timeout, lldb::EventSP *event_sp_ptr, bool wait_always, Listener *hijack_listener) +Process::WaitForProcessToStop (const TimeValue *timeout, + EventSP *event_sp_ptr, + bool wait_always, + Listener *hijack_listener, + Stream *stream) { // We can't just wait for a "stopped" event, because the stopped event may have restarted the target. // We have to actually check each event, and in the case of a stopped event check the restarted flag @@ -966,6 +1004,9 @@ Process::WaitForProcessToStop (const TimeValue *timeout, lldb::EventSP *event_sp if (event_sp_ptr && event_sp) *event_sp_ptr = event_sp; + bool pop_process_io_handler = hijack_listener != NULL; + Process::HandleProcessStateChangedEvent (event_sp, stream, pop_process_io_handler); + switch (state) { case eStateCrashed: @@ -995,6 +1036,195 @@ Process::WaitForProcessToStop (const TimeValue *timeout, lldb::EventSP *event_sp return state; } +bool +Process::HandleProcessStateChangedEvent (const EventSP &event_sp, + Stream *stream, + bool &pop_process_io_handler) +{ + const bool handle_pop = pop_process_io_handler == true; + + pop_process_io_handler = false; + ProcessSP process_sp = Process::ProcessEventData::GetProcessFromEvent(event_sp.get()); + + if (!process_sp) + return false; + + StateType event_state = Process::ProcessEventData::GetStateFromEvent (event_sp.get()); + if (event_state == eStateInvalid) + return false; + + switch (event_state) + { + case eStateInvalid: + case eStateUnloaded: + case eStateAttaching: + case eStateLaunching: + case eStateStepping: + case eStateDetached: + { + if (stream) + stream->Printf ("Process %" PRIu64 " %s\n", + process_sp->GetID(), + StateAsCString (event_state)); + + if (event_state == eStateDetached) + pop_process_io_handler = true; + } + break; + + case eStateConnected: + case eStateRunning: + // Don't be chatty when we run... + break; + + case eStateExited: + if (stream) + process_sp->GetStatus(*stream); + pop_process_io_handler = true; + break; + + case eStateStopped: + case eStateCrashed: + case eStateSuspended: + // Make sure the program hasn't been auto-restarted: + if (Process::ProcessEventData::GetRestartedFromEvent (event_sp.get())) + { + if (stream) + { + size_t num_reasons = Process::ProcessEventData::GetNumRestartedReasons(event_sp.get()); + if (num_reasons > 0) + { + // FIXME: Do we want to report this, or would that just be annoyingly chatty? + if (num_reasons == 1) + { + const char *reason = Process::ProcessEventData::GetRestartedReasonAtIndex (event_sp.get(), 0); + stream->Printf ("Process %" PRIu64 " stopped and restarted: %s\n", + process_sp->GetID(), + reason ? reason : "<UNKNOWN REASON>"); + } + else + { + stream->Printf ("Process %" PRIu64 " stopped and restarted, reasons:\n", + process_sp->GetID()); + + + for (size_t i = 0; i < num_reasons; i++) + { + const char *reason = Process::ProcessEventData::GetRestartedReasonAtIndex (event_sp.get(), i); + stream->Printf("\t%s\n", reason ? reason : "<UNKNOWN REASON>"); + } + } + } + } + } + else + { + // Lock the thread list so it doesn't change on us, this is the scope for the locker: + { + ThreadList &thread_list = process_sp->GetThreadList(); + Mutex::Locker locker (thread_list.GetMutex()); + + ThreadSP curr_thread (thread_list.GetSelectedThread()); + ThreadSP thread; + StopReason curr_thread_stop_reason = eStopReasonInvalid; + if (curr_thread) + curr_thread_stop_reason = curr_thread->GetStopReason(); + if (!curr_thread || + !curr_thread->IsValid() || + curr_thread_stop_reason == eStopReasonInvalid || + curr_thread_stop_reason == eStopReasonNone) + { + // Prefer a thread that has just completed its plan over another thread as current thread. + ThreadSP plan_thread; + ThreadSP other_thread; + const size_t num_threads = thread_list.GetSize(); + size_t i; + for (i = 0; i < num_threads; ++i) + { + thread = thread_list.GetThreadAtIndex(i); + StopReason thread_stop_reason = thread->GetStopReason(); + switch (thread_stop_reason) + { + case eStopReasonInvalid: + case eStopReasonNone: + break; + + case eStopReasonTrace: + case eStopReasonBreakpoint: + case eStopReasonWatchpoint: + case eStopReasonSignal: + case eStopReasonException: + case eStopReasonExec: + case eStopReasonThreadExiting: + case eStopReasonInstrumentation: + if (!other_thread) + other_thread = thread; + break; + case eStopReasonPlanComplete: + if (!plan_thread) + plan_thread = thread; + break; + } + } + if (plan_thread) + thread_list.SetSelectedThreadByID (plan_thread->GetID()); + else if (other_thread) + thread_list.SetSelectedThreadByID (other_thread->GetID()); + else + { + if (curr_thread && curr_thread->IsValid()) + thread = curr_thread; + else + thread = thread_list.GetThreadAtIndex(0); + + if (thread) + thread_list.SetSelectedThreadByID (thread->GetID()); + } + } + } + // Drop the ThreadList mutex by here, since GetThreadStatus below might have to run code, + // e.g. for Data formatters, and if we hold the ThreadList mutex, then the process is going to + // have a hard time restarting the process. + if (stream) + { + Debugger &debugger = process_sp->GetTarget().GetDebugger(); + if (debugger.GetTargetList().GetSelectedTarget().get() == &process_sp->GetTarget()) + { + const bool only_threads_with_stop_reason = true; + const uint32_t start_frame = 0; + const uint32_t num_frames = 1; + const uint32_t num_frames_with_source = 1; + process_sp->GetStatus(*stream); + process_sp->GetThreadStatus (*stream, + only_threads_with_stop_reason, + start_frame, + num_frames, + num_frames_with_source); + } + else + { + uint32_t target_idx = debugger.GetTargetList().GetIndexOfTarget(process_sp->GetTarget().shared_from_this()); + if (target_idx != UINT32_MAX) + stream->Printf ("Target %d: (", target_idx); + else + stream->Printf ("Target <unknown index>: ("); + process_sp->GetTarget().Dump (stream, eDescriptionLevelBrief); + stream->Printf (") stopped.\n"); + } + } + + // Pop the process IO handler + pop_process_io_handler = true; + } + break; + } + + if (handle_pop && pop_process_io_handler) + process_sp->PopProcessIOHandler(); + + return true; +} + StateType Process::WaitForState @@ -1170,6 +1400,8 @@ Process::IsRunning () const int Process::GetExitStatus () { + Mutex::Locker locker (m_exit_status_mutex); + if (m_public_state.GetValue() == eStateExited) return m_exit_status; return -1; @@ -1179,6 +1411,8 @@ Process::GetExitStatus () const char * Process::GetExitDescription () { + Mutex::Locker locker (m_exit_status_mutex); + if (m_public_state.GetValue() == eStateExited && !m_exit_string.empty()) return m_exit_string.c_str(); return NULL; @@ -1203,11 +1437,16 @@ Process::SetExitStatus (int status, const char *cstr) return false; } - m_exit_status = status; - if (cstr) - m_exit_string = cstr; - else - m_exit_string.clear(); + // use a mutex to protect the status and string during updating + { + Mutex::Locker locker (m_exit_status_mutex); + + m_exit_status = status; + if (cstr) + m_exit_string = cstr; + else + m_exit_string.clear(); + } DidExit (); @@ -1392,6 +1631,17 @@ Process::GetState() return m_public_state.GetValue (); } +bool +Process::StateChangedIsExternallyHijacked() +{ + if (IsHijackedForEvent(eBroadcastBitStateChanged)) + { + if (strcmp(m_hijacking_listeners.back()->GetName(), "lldb.Process.ResumeSynchronous.hijack")) + return true; + } + return false; +} + void Process::SetPublicState (StateType new_state, bool restarted) { @@ -1404,7 +1654,7 @@ Process::SetPublicState (StateType new_state, bool restarted) // On the transition from Run to Stopped, we unlock the writer end of the // run lock. The lock gets locked in Resume, which is the public API // to tell the program to run. - if (!IsHijackedForEvent(eBroadcastBitStateChanged)) + if (!StateChangedIsExternallyHijacked()) { if (new_state == eStateDetached) { @@ -1445,6 +1695,36 @@ Process::Resume () return PrivateResume(); } +Error +Process::ResumeSynchronous (Stream *stream) +{ + Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STATE | LIBLLDB_LOG_PROCESS)); + if (log) + log->Printf("Process::ResumeSynchronous -- locking run lock"); + if (!m_public_run_lock.TrySetRunning()) + { + Error error("Resume request failed - process still running."); + if (log) + log->Printf ("Process::Resume: -- TrySetRunning failed, not resuming."); + return error; + } + + ListenerSP listener_sp (new Listener("lldb.Process.ResumeSynchronous.hijack")); + HijackProcessEvents(listener_sp.get()); + + Error error = PrivateResume(); + + StateType state = WaitForProcessToStop (NULL, NULL, true, listener_sp.get(), stream); + + // Undo the hijacking of process events... + RestoreProcessEvents(); + + if (error.Success() && !StateIsStoppedState(state, false)) + error.SetErrorStringWithFormat("process not in stopped state after synchronous resume: %s", StateAsCString(state)); + + return error; +} + StateType Process::GetPrivateState () { @@ -1617,12 +1897,17 @@ Process::LoadImage (const FileSpec &image_spec, Error &error) { if (error_str_sp->IsCStringContainer(true)) { - StreamString s; - size_t num_chars = error_str_sp->ReadPointedString (s, error); + DataBufferSP buffer_sp(new DataBufferHeap(10240,0)); + size_t num_chars = error_str_sp->ReadPointedString (buffer_sp, error, 10240); if (error.Success() && num_chars > 0) { error.Clear(); - error.SetErrorStringWithFormat("dlopen error: %s", s.GetData()); + error.SetErrorStringWithFormat("dlopen error: %s", buffer_sp->GetBytes()); + } + else + { + error.Clear(); + error.SetErrorStringWithFormat("dlopen failed for unknown reasons."); } } } @@ -2507,10 +2792,10 @@ Process::WriteMemory (addr_t addr, const void *buf, size_t size, Error &error) }); if (bytes_written < size) - bytes_written += WriteMemoryPrivate (addr + bytes_written, - ubuf + bytes_written, - size - bytes_written, - error); + WriteMemoryPrivate (addr + bytes_written, + ubuf + bytes_written, + size - bytes_written, + error); } } else @@ -2722,6 +3007,16 @@ Process::WaitForProcessStopPrivate (const TimeValue *timeout, EventSP &event_sp) return state; } +void +Process::LoadOperatingSystemPlugin(bool flush) +{ + if (flush) + m_thread_list.Clear(); + m_os_ap.reset (OperatingSystem::FindPlugin (this, NULL)); + if (flush) + Flush(); +} + Error Process::Launch (ProcessLaunchInfo &launch_info) { @@ -2732,6 +3027,7 @@ Process::Launch (ProcessLaunchInfo &launch_info) m_system_runtime_ap.reset(); m_os_ap.reset(); m_process_input_reader.reset(); + m_stop_info_override_callback = NULL; Module *exe_module = m_target.GetExecutableModulePointer(); if (exe_module) @@ -2811,15 +3107,20 @@ Process::Launch (ProcessLaunchInfo &launch_info) if (system_runtime) system_runtime->DidLaunch(); - m_os_ap.reset (OperatingSystem::FindPlugin (this, NULL)); - // This delays passing the stopped event to listeners till DidLaunch gets - // a chance to complete... - HandlePrivateEvent (event_sp); + LoadOperatingSystemPlugin(false); + + // Note, the stop event was consumed above, but not handled. This was done + // to give DidLaunch a chance to run. The target is either stopped or crashed. + // Directly set the state. This is done to prevent a stop message with a bunch + // of spurious output on thread status, as well as not pop a ProcessIOHandler. + SetPublicState(state, false); if (PrivateStateThreadIsValid ()) ResumePrivateStateThread (); else StartPrivateStateThread (); + + m_stop_info_override_callback = GetTarget().GetArchitecture().GetStopInfoOverrideCallback(); } else if (state == eStateExited) { @@ -2979,6 +3280,15 @@ Process::AttachCompletionHandler::GetExitString () return m_exit_string.c_str(); } +Listener & +ProcessAttachInfo::GetListenerForProcess (Debugger &debugger) +{ + if (m_listener_sp) + return *m_listener_sp; + else + return debugger.GetListener(); +} + Error Process::Attach (ProcessAttachInfo &attach_info) { @@ -2988,6 +3298,7 @@ Process::Attach (ProcessAttachInfo &attach_info) m_jit_loaders_ap.reset(); m_system_runtime_ap.reset(); m_os_ap.reset(); + m_stop_info_override_callback = NULL; lldb::pid_t attach_pid = attach_info.GetProcessID(); Error error; @@ -3115,14 +3426,13 @@ Process::Attach (ProcessAttachInfo &attach_info) else { if (GetID() != LLDB_INVALID_PROCESS_ID) - { SetID (LLDB_INVALID_PROCESS_ID); - const char *error_string = error.AsCString(); - if (error_string == NULL) - error_string = "attach failed"; - SetExitStatus(-1, error_string); - } + const char *error_string = error.AsCString(); + if (error_string == NULL) + error_string = "attach failed"; + + SetExitStatus(-1, error_string); } } } @@ -3246,6 +3556,8 @@ Process::CompleteAttach () exe_module_sp ? exe_module_sp->GetFileSpec().GetPath().c_str () : "<none>"); } } + + m_stop_info_override_callback = process_arch.GetStopInfoOverrideCallback(); } Error @@ -3823,26 +4135,25 @@ Process::StartPrivateStateThread (bool force) // events make it to clients (into the DCProcess event queue). char thread_name[1024]; - if (Host::MAX_THREAD_NAME_LENGTH <= 16) + if (HostInfo::GetMaxThreadNameLength() <= 30) { - // On platforms with abbreviated thread name lengths, choose thread names that fit within the limit. - if (already_running) - snprintf(thread_name, sizeof(thread_name), "intern-state-OV"); - else - snprintf(thread_name, sizeof(thread_name), "intern-state"); + // On platforms with abbreviated thread name lengths, choose thread names that fit within the limit. + if (already_running) + snprintf(thread_name, sizeof(thread_name), "intern-state-OV"); + else + snprintf(thread_name, sizeof(thread_name), "intern-state"); } else { if (already_running) - snprintf(thread_name, sizeof(thread_name), "<lldb.process.internal-state-override(pid=%" PRIu64 ")>", GetID()); + snprintf(thread_name, sizeof(thread_name), "<lldb.process.internal-state-override(pid=%" PRIu64 ")>", GetID()); else - snprintf(thread_name, sizeof(thread_name), "<lldb.process.internal-state(pid=%" PRIu64 ")>", GetID()); + snprintf(thread_name, sizeof(thread_name), "<lldb.process.internal-state(pid=%" PRIu64 ")>", GetID()); } // Create the private state thread, and start it running. - m_private_state_thread = Host::ThreadCreate (thread_name, Process::PrivateStateThread, this, NULL); - bool success = IS_VALID_LLDB_HOST_THREAD(m_private_state_thread); - if (success) + m_private_state_thread = ThreadLauncher::LaunchThread(thread_name, Process::PrivateStateThread, this, NULL); + if (m_private_state_thread.IsJoinable()) { ResumePrivateStateThread(); return true; @@ -3891,8 +4202,8 @@ Process::ControlPrivateStateThread (uint32_t signal) // Signal the private state thread. First we should copy this is case the // thread starts exiting since the private state thread will NULL this out // when it exits - const lldb::thread_t private_state_thread = m_private_state_thread; - if (IS_VALID_LLDB_HOST_THREAD(private_state_thread)) + HostThread private_state_thread(m_private_state_thread); + if (private_state_thread.IsJoinable()) { TimeValue timeout_time; bool timed_out; @@ -3910,8 +4221,7 @@ Process::ControlPrivateStateThread (uint32_t signal) { if (timed_out) { - Error error; - Host::ThreadCancel (private_state_thread, &error); + Error error = private_state_thread.Cancel(); if (log) log->Printf ("Timed out responding to the control event, cancel got error: \"%s\".", error.AsCString()); } @@ -3922,8 +4232,8 @@ Process::ControlPrivateStateThread (uint32_t signal) } thread_result_t result = NULL; - Host::ThreadJoin (private_state_thread, &result, NULL); - m_private_state_thread = LLDB_INVALID_HOST_THREAD; + private_state_thread.Join(&result); + m_private_state_thread.Reset(); } } else @@ -4005,7 +4315,8 @@ Process::HandlePrivateEvent (EventSP &event_sp) { // Only push the input handler if we aren't fowarding events, // as this means the curses GUI is in use... - if (!GetTarget().GetDebugger().IsForwardingEvents()) + // Or don't push it if we are launching since it will come up stopped. + if (!GetTarget().GetDebugger().IsForwardingEvents() && new_state != eStateLaunching) PushProcessIOHandler (); m_iohandler_sync.SetValue(true, eBroadcastAlways); } @@ -4167,7 +4478,7 @@ Process::RunPrivateStateThread () m_public_run_lock.SetStopped(); m_private_state_control_wait.SetValue (true, eBroadcastAlways); - m_private_state_thread = LLDB_INVALID_HOST_THREAD; + m_private_state_thread.Reset(); return NULL; } @@ -4621,7 +4932,7 @@ class IOHandlerProcessSTDIO : public: IOHandlerProcessSTDIO (Process *process, int write_fd) : - IOHandler(process->GetTarget().GetDebugger()), + IOHandler(process->GetTarget().GetDebugger(), IOHandler::Type::ProcessIO), m_process (process), m_read_file (), m_write_file (write_fd, false), @@ -4639,9 +4950,10 @@ public: bool OpenPipes () { - if (m_pipe.IsValid()) + if (m_pipe.CanRead() && m_pipe.CanWrite()) return true; - return m_pipe.Open(); + Error result = m_pipe.CreateNew(false); + return result.Success(); } void @@ -4702,8 +5014,10 @@ public: } if (FD_ISSET (pipe_read_fd, &read_fdset)) { + size_t bytes_read; // Consume the interrupt byte - if (m_pipe.Read (&ch, 1) == 1) + Error error = m_pipe.Read(&ch, 1, bytes_read); + if (error.Success()) { switch (ch) { @@ -4751,7 +5065,8 @@ public: Cancel () { char ch = 'q'; // Send 'q' for quit - m_pipe.Write (&ch, 1); + size_t bytes_written = 0; + m_pipe.Write(&ch, 1, bytes_written); } virtual bool @@ -4765,7 +5080,9 @@ public: if (m_active) { char ch = 'i'; // Send 'i' for interrupt - return m_pipe.Write (&ch, 1) == 1; + size_t bytes_written = 0; + Error result = m_pipe.Write(&ch, 1, bytes_written); + return result.Success(); } else { @@ -4944,12 +5261,12 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, selected_tid = LLDB_INVALID_THREAD_ID; } - lldb::thread_t backup_private_state_thread = LLDB_INVALID_HOST_THREAD; - lldb::StateType old_state; + HostThread backup_private_state_thread; + lldb::StateType old_state = eStateInvalid; lldb::ThreadPlanSP stopper_base_plan_sp; Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP | LIBLLDB_LOG_PROCESS)); - if (Host::GetCurrentThread() == m_private_state_thread) + if (m_private_state_thread.EqualsThread(Host::GetCurrentThread())) { // Yikes, we are running on the private state thread! So we can't wait for public events on this thread, since // we are the thread that is generating public events. @@ -5554,7 +5871,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, } // END WAIT LOOP // If we had to start up a temporary private state thread to run this thread plan, shut it down now. - if (IS_VALID_LLDB_HOST_THREAD(backup_private_state_thread)) + if (backup_private_state_thread.IsJoinable()) { StopPrivateStateThread(); Error error; @@ -5563,8 +5880,8 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, { thread->DiscardThreadPlansUpToPlan(stopper_base_plan_sp); } - m_public_state.SetValueNoLock(old_state); - + if (old_state != eStateInvalid) + m_public_state.SetValueNoLock(old_state); } // Restore the thread state if we are going to discard the plan execution. There are three cases where this @@ -5848,21 +6165,21 @@ Process::GetThreadStatus (Stream &strm, // ID's, and look them up one by one: uint32_t num_threads; - std::vector<uint32_t> thread_index_array; + std::vector<lldb::tid_t> thread_id_array; //Scope for thread list locker; { Mutex::Locker locker (GetThreadList().GetMutex()); ThreadList &curr_thread_list = GetThreadList(); num_threads = curr_thread_list.GetSize(); uint32_t idx; - thread_index_array.resize(num_threads); + thread_id_array.resize(num_threads); for (idx = 0; idx < num_threads; ++idx) - thread_index_array[idx] = curr_thread_list.GetThreadAtIndex(idx)->GetID(); + thread_id_array[idx] = curr_thread_list.GetThreadAtIndex(idx)->GetID(); } for (uint32_t i = 0; i < num_threads; i++) { - ThreadSP thread_sp(GetThreadList().FindThreadByID(thread_index_array[i])); + ThreadSP thread_sp(GetThreadList().FindThreadByID(thread_id_array[i])); if (thread_sp) { if (only_threads_with_stop_reason) @@ -5915,7 +6232,8 @@ Process::RunPreResumeActions () struct PreResumeCallbackAndBaton action = m_pre_resume_actions.back(); m_pre_resume_actions.pop_back(); bool this_result = action.callback (action.baton); - if (result == true) result = this_result; + if (result == true) + result = this_result; } return result; } @@ -5955,8 +6273,10 @@ Process::DidExec () m_image_tokens.clear(); m_allocated_memory_cache.Clear(); m_language_runtimes.clear(); + m_instrumentation_runtimes.clear(); m_thread_list.DiscardThreadPlans(); m_memory_cache.Clear(true); + m_stop_info_override_callback = NULL; DoDidExec(); CompleteAttach (); // Flush the process (threads and all stack frames) after running CompleteAttach() @@ -6005,11 +6325,51 @@ Process::ResolveIndirectFunction(const Address *address, Error &error) void Process::ModulesDidLoad (ModuleList &module_list) { - SystemRuntime *sys_runtime = GetSystemRuntime(); - if (sys_runtime) - { - sys_runtime->ModulesDidLoad (module_list); - } + SystemRuntime *sys_runtime = GetSystemRuntime(); + if (sys_runtime) + { + sys_runtime->ModulesDidLoad (module_list); + } + + GetJITLoaders().ModulesDidLoad (module_list); + + // Give runtimes a chance to be created. + InstrumentationRuntime::ModulesDidLoad(module_list, this, m_instrumentation_runtimes); + + // Tell runtimes about new modules. + for (auto pos = m_instrumentation_runtimes.begin(); pos != m_instrumentation_runtimes.end(); ++pos) + { + InstrumentationRuntimeSP runtime = pos->second; + runtime->ModulesDidLoad(module_list); + } + +} + +ThreadCollectionSP +Process::GetHistoryThreads(lldb::addr_t addr) +{ + ThreadCollectionSP threads; + + const MemoryHistorySP &memory_history = MemoryHistory::FindPlugin(shared_from_this()); + + if (! memory_history.get()) { + return threads; + } + + threads.reset(new ThreadCollection(memory_history->GetHistoryThreads(addr))); + + return threads; +} - GetJITLoaders().ModulesDidLoad (module_list); +InstrumentationRuntimeSP +Process::GetInstrumentationRuntime(lldb::InstrumentationRuntimeType type) +{ + InstrumentationRuntimeCollection::iterator pos; + pos = m_instrumentation_runtimes.find (type); + if (pos == m_instrumentation_runtimes.end()) + { + return InstrumentationRuntimeSP(); + } + else + return (*pos).second; } |