summaryrefslogtreecommitdiff
path: root/source/Target/Process.cpp
diff options
context:
space:
mode:
authorEd Maste <emaste@FreeBSD.org>2015-02-06 21:38:51 +0000
committerEd Maste <emaste@FreeBSD.org>2015-02-06 21:38:51 +0000
commit205afe679855a4ce8149cdaa94d3f0868ce796dc (patch)
tree09bc83f73246ee3c7a779605cd0122093d2a8a19 /source/Target/Process.cpp
parent0cac4ca3916ac24ab6139d03cbfd18db9e715bfe (diff)
downloadsrc-test2-205afe679855a4ce8149cdaa94d3f0868ce796dc.tar.gz
src-test2-205afe679855a4ce8149cdaa94d3f0868ce796dc.zip
Notes
Diffstat (limited to 'source/Target/Process.cpp')
-rw-r--r--source/Target/Process.cpp518
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;
}