diff options
Diffstat (limited to 'source/Target/Process.cpp')
-rw-r--r-- | source/Target/Process.cpp | 951 |
1 files changed, 504 insertions, 447 deletions
diff --git a/source/Target/Process.cpp b/source/Target/Process.cpp index e4fe419660e2..3d1065450e81 100644 --- a/source/Target/Process.cpp +++ b/source/Target/Process.cpp @@ -9,21 +9,25 @@ // C Includes // C++ Includes +#include <atomic> +#include <mutex> + // Other libraries and framework includes // Project includes -#include "lldb/Target/Process.h" -#include "lldb/Breakpoint/StoppointCallbackContext.h" +#include "Plugins/Process/Utility/InferiorCallPOSIX.h" #include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/Event.h" +#include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Core/Debugger.h" +#include "lldb/Core/Event.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/State.h" #include "lldb/Core/StreamFile.h" -#include "lldb/Expression/UserExpression.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/IRDynamicChecks.h" +#include "lldb/Expression/UserExpression.h" #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" @@ -36,17 +40,18 @@ #include "lldb/Symbol/Function.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Target/ABI.h" +#include "lldb/Target/CPPLanguageRuntime.h" #include "lldb/Target/DynamicLoader.h" #include "lldb/Target/InstrumentationRuntime.h" #include "lldb/Target/JITLoader.h" #include "lldb/Target/JITLoaderList.h" +#include "lldb/Target/LanguageRuntime.h" #include "lldb/Target/MemoryHistory.h" #include "lldb/Target/MemoryRegionInfo.h" -#include "lldb/Target/OperatingSystem.h" -#include "lldb/Target/LanguageRuntime.h" -#include "lldb/Target/CPPLanguageRuntime.h" #include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/OperatingSystem.h" #include "lldb/Target/Platform.h" +#include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/StopInfo.h" #include "lldb/Target/SystemRuntime.h" @@ -57,7 +62,6 @@ #include "lldb/Target/ThreadPlanBase.h" #include "lldb/Target/UnixSignals.h" #include "lldb/Utility/NameMatches.h" -#include "Plugins/Process/Utility/InferiorCallPOSIX.h" using namespace lldb; using namespace lldb_private; @@ -111,17 +115,17 @@ public: static PropertyDefinition g_properties[] = { - { "disable-memory-cache" , OptionValue::eTypeBoolean, false, DISABLE_MEM_CACHE_DEFAULT, NULL, NULL, "Disable reading and caching of memory in fixed-size units." }, - { "extra-startup-command", OptionValue::eTypeArray , false, OptionValue::eTypeString, NULL, NULL, "A list containing extra commands understood by the particular process plugin used. " + { "disable-memory-cache" , OptionValue::eTypeBoolean, false, DISABLE_MEM_CACHE_DEFAULT, nullptr, nullptr, "Disable reading and caching of memory in fixed-size units." }, + { "extra-startup-command", OptionValue::eTypeArray , false, OptionValue::eTypeString, nullptr, nullptr, "A list containing extra commands understood by the particular process plugin used. " "For instance, to turn on debugserver logging set this to \"QSetLogging:bitmask=LOG_DEFAULT;\"" }, - { "ignore-breakpoints-in-expressions", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, breakpoints will be ignored during expression evaluation." }, - { "unwind-on-error-in-expressions", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, errors in expression evaluation will unwind the stack back to the state before the call." }, - { "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" }, - { "optimization-warnings" , OptionValue::eTypeBoolean, false, true, NULL, NULL, "If true, warn when stopped in code that is optimized where stepping and variable availability may not behave as expected." }, - { NULL , OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL } + { "ignore-breakpoints-in-expressions", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, "If true, breakpoints will be ignored during expression evaluation." }, + { "unwind-on-error-in-expressions", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, "If true, errors in expression evaluation will unwind the stack back to the state before the call." }, + { "python-os-plugin-path", OptionValue::eTypeFileSpec, false, true, nullptr, nullptr, "A path to a python OS plug-in module file that contains a OperatingSystemPlugIn class." }, + { "stop-on-sharedlibrary-events" , OptionValue::eTypeBoolean, true, false, nullptr, nullptr, "If true, stop when a shared library is loaded or unloaded." }, + { "detach-keeps-stopped" , OptionValue::eTypeBoolean, true, false, nullptr, nullptr, "If true, detach will attempt to keep the process stopped." }, + { "memory-cache-line-size" , OptionValue::eTypeUInt64, false, 512, nullptr, nullptr, "The memory cache line size" }, + { "optimization-warnings" , OptionValue::eTypeBoolean, false, true, nullptr, nullptr, "If true, warn when stopped in code that is optimized where stepping and variable availability may not behave as expected." }, + { nullptr , OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr } }; enum { @@ -137,10 +141,10 @@ enum { }; ProcessProperties::ProcessProperties (lldb_private::Process *process) : - Properties (), - m_process (process) // Can be NULL for global ProcessProperties + Properties(), + m_process(process) // Can be nullptr for global ProcessProperties { - if (process == NULL) + if (process == nullptr) { // Global process properties, set them up one time m_collection_sp.reset (new ProcessOptionValueProperties(ConstString("process"))); @@ -171,14 +175,14 @@ bool ProcessProperties::GetDisableMemoryCache() const { const uint32_t idx = ePropertyDisableMemCache; - return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); + return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, 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); + return m_collection_sp->GetPropertyAtIndexAsUInt64(nullptr, idx, g_properties[idx].default_uint_value); } Args @@ -186,7 +190,7 @@ ProcessProperties::GetExtraStartupCommands () const { Args args; const uint32_t idx = ePropertyExtraStartCommand; - m_collection_sp->GetPropertyAtIndexAsArgs(NULL, idx, args); + m_collection_sp->GetPropertyAtIndexAsArgs(nullptr, idx, args); return args; } @@ -194,84 +198,84 @@ void ProcessProperties::SetExtraStartupCommands (const Args &args) { const uint32_t idx = ePropertyExtraStartCommand; - m_collection_sp->SetPropertyAtIndexFromArgs(NULL, idx, args); + m_collection_sp->SetPropertyAtIndexFromArgs(nullptr, idx, args); } FileSpec ProcessProperties::GetPythonOSPluginPath () const { const uint32_t idx = ePropertyPythonOSPluginPath; - return m_collection_sp->GetPropertyAtIndexAsFileSpec(NULL, idx); + return m_collection_sp->GetPropertyAtIndexAsFileSpec(nullptr, idx); } void ProcessProperties::SetPythonOSPluginPath (const FileSpec &file) { const uint32_t idx = ePropertyPythonOSPluginPath; - m_collection_sp->SetPropertyAtIndexAsFileSpec(NULL, idx, file); + m_collection_sp->SetPropertyAtIndexAsFileSpec(nullptr, idx, file); } bool ProcessProperties::GetIgnoreBreakpointsInExpressions () const { const uint32_t idx = ePropertyIgnoreBreakpointsInExpressions; - return m_collection_sp->GetPropertyAtIndexAsBoolean(NULL, idx, g_properties[idx].default_uint_value != 0); + return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, g_properties[idx].default_uint_value != 0); } void ProcessProperties::SetIgnoreBreakpointsInExpressions (bool ignore) { const uint32_t idx = ePropertyIgnoreBreakpointsInExpressions; - m_collection_sp->SetPropertyAtIndexAsBoolean(NULL, idx, ignore); + m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, ignore); } bool ProcessProperties::GetUnwindOnErrorInExpressions () const { const uint32_t idx = ePropertyUnwindOnErrorInExpressions; - return m_collection_sp->GetPropertyAtIndexAsBoolean(NULL, idx, g_properties[idx].default_uint_value != 0); + return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, g_properties[idx].default_uint_value != 0); } void ProcessProperties::SetUnwindOnErrorInExpressions (bool ignore) { const uint32_t idx = ePropertyUnwindOnErrorInExpressions; - m_collection_sp->SetPropertyAtIndexAsBoolean(NULL, idx, ignore); + m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, ignore); } bool ProcessProperties::GetStopOnSharedLibraryEvents () const { const uint32_t idx = ePropertyStopOnSharedLibraryEvents; - return m_collection_sp->GetPropertyAtIndexAsBoolean(NULL, idx, g_properties[idx].default_uint_value != 0); + return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, g_properties[idx].default_uint_value != 0); } void ProcessProperties::SetStopOnSharedLibraryEvents (bool stop) { const uint32_t idx = ePropertyStopOnSharedLibraryEvents; - m_collection_sp->SetPropertyAtIndexAsBoolean(NULL, idx, stop); + m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, stop); } bool ProcessProperties::GetDetachKeepsStopped () const { const uint32_t idx = ePropertyDetachKeepsStopped; - return m_collection_sp->GetPropertyAtIndexAsBoolean(NULL, idx, g_properties[idx].default_uint_value != 0); + return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, g_properties[idx].default_uint_value != 0); } void ProcessProperties::SetDetachKeepsStopped (bool stop) { const uint32_t idx = ePropertyDetachKeepsStopped; - m_collection_sp->SetPropertyAtIndexAsBoolean(NULL, idx, stop); + m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, stop); } bool ProcessProperties::GetWarningsOptimization () const { const uint32_t idx = ePropertyWarningOptimization; - return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); + return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, g_properties[idx].default_uint_value != 0); } void @@ -294,7 +298,7 @@ ProcessInstanceInfo::Dump (Stream &s, Platform *platform) const const uint32_t argc = m_arguments.GetArgumentCount(); if (argc > 0) { - for (uint32_t i=0; i<argc; i++) + for (uint32_t i = 0; i < argc; i++) { const char *arg = m_arguments.GetArgumentAtIndex(i); if (i < 10) @@ -307,7 +311,7 @@ ProcessInstanceInfo::Dump (Stream &s, Platform *platform) const const uint32_t envc = m_environment.GetArgumentCount(); if (envc > 0) { - for (uint32_t i=0; i<envc; i++) + for (uint32_t i = 0; i < envc; i++) { const char *env = m_environment.GetArgumentAtIndex(i); if (i < 10) @@ -419,7 +423,7 @@ ProcessInstanceInfo::DumpAsTableRow (Stream &s, Platform *platform, bool show_ar const uint32_t argc = m_arguments.GetArgumentCount(); if (argc > 0) { - for (uint32_t i=0; i<argc; i++) + for (uint32_t i = 0; i < argc; i++) { if (i > 0) s.PutChar (' '); @@ -545,29 +549,29 @@ ProcessLaunchCommandOptions::SetOptionValue (uint32_t option_idx, const char *op OptionDefinition ProcessLaunchCommandOptions::g_option_table[] = { -{ LLDB_OPT_SET_ALL, false, "stop-at-entry", 's', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Stop at the entry point of the program when launching a process."}, -{ LLDB_OPT_SET_ALL, false, "disable-aslr", 'A', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "Set whether to disable address space layout randomization when launching a process."}, -{ LLDB_OPT_SET_ALL, false, "plugin", 'p', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, -{ LLDB_OPT_SET_ALL, false, "working-dir", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeDirectoryName, "Set the current working directory to <path> when running the inferior."}, -{ LLDB_OPT_SET_ALL, false, "arch", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeArchitecture, "Set the architecture for the process to launch when ambiguous."}, -{ LLDB_OPT_SET_ALL, false, "environment", 'v', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNone, "Specify an environment variable name/value string (--environment NAME=VALUE). Can be specified multiple times for subsequent environment entries."}, -{ LLDB_OPT_SET_1|LLDB_OPT_SET_2|LLDB_OPT_SET_3, false, "shell", 'c', OptionParser::eOptionalArgument, NULL, NULL, 0, eArgTypeFilename, "Run the process in a shell (not supported on all platforms)."}, +{ LLDB_OPT_SET_ALL, false, "stop-at-entry", 's', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Stop at the entry point of the program when launching a process." }, +{ LLDB_OPT_SET_ALL, false, "disable-aslr", 'A', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Set whether to disable address space layout randomization when launching a process." }, +{ LLDB_OPT_SET_ALL, false, "plugin", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlugin, "Name of the process plugin you want to use." }, +{ LLDB_OPT_SET_ALL, false, "working-dir", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeDirectoryName, "Set the current working directory to <path> when running the inferior." }, +{ LLDB_OPT_SET_ALL, false, "arch", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeArchitecture, "Set the architecture for the process to launch when ambiguous." }, +{ LLDB_OPT_SET_ALL, false, "environment", 'v', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "Specify an environment variable name/value string (--environment NAME=VALUE). Can be specified multiple times for subsequent environment entries." }, +{ LLDB_OPT_SET_1|LLDB_OPT_SET_2|LLDB_OPT_SET_3, false, "shell", 'c', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeFilename, "Run the process in a shell (not supported on all platforms)." }, -{ LLDB_OPT_SET_1 , false, "stdin", 'i', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename, "Redirect stdin for the process to <filename>."}, -{ LLDB_OPT_SET_1 , false, "stdout", 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename, "Redirect stdout for the process to <filename>."}, -{ LLDB_OPT_SET_1 , false, "stderr", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename, "Redirect stderr for the process to <filename>."}, +{ LLDB_OPT_SET_1 , false, "stdin", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFilename, "Redirect stdin for the process to <filename>." }, +{ LLDB_OPT_SET_1 , false, "stdout", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFilename, "Redirect stdout for the process to <filename>." }, +{ LLDB_OPT_SET_1 , false, "stderr", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFilename, "Redirect stderr for the process to <filename>." }, -{ LLDB_OPT_SET_2 , false, "tty", 't', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Start the process in a terminal (not supported on all platforms)."}, +{ LLDB_OPT_SET_2 , false, "tty", 't', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Start the process in a terminal (not supported on all platforms)." }, -{ LLDB_OPT_SET_3 , false, "no-stdio", 'n', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Do not set up for terminal I/O to go to running process."}, -{ LLDB_OPT_SET_4, false, "shell-expand-args", 'X', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "Set whether to shell expand arguments to the process when launching."}, -{ 0 , false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } +{ LLDB_OPT_SET_3 , false, "no-stdio", 'n', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Do not set up for terminal I/O to go to running process." }, +{ LLDB_OPT_SET_4, false, "shell-expand-args", 'X', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Set whether to shell expand arguments to the process when launching." }, +{ 0 , false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } }; bool ProcessInstanceInfoMatch::NameMatches (const char *process_name) const { - if (m_name_match_type == eNameMatchIgnore || process_name == NULL) + if (m_name_match_type == eNameMatchIgnore || process_name == nullptr) return true; const char *match_name = m_match_info.GetName(); if (!match_name) @@ -654,19 +658,19 @@ ProcessInstanceInfoMatch::Clear() } ProcessSP -Process::FindPlugin (lldb::TargetSP target_sp, const char *plugin_name, Listener &listener, const FileSpec *crash_file_path) +Process::FindPlugin (lldb::TargetSP target_sp, const char *plugin_name, ListenerSP listener_sp, const FileSpec *crash_file_path) { static uint32_t g_process_unique_id = 0; ProcessSP process_sp; - ProcessCreateInstance create_callback = NULL; + ProcessCreateInstance create_callback = nullptr; if (plugin_name) { ConstString const_plugin_name(plugin_name); create_callback = PluginManager::GetProcessCreateCallbackForPluginName (const_plugin_name); if (create_callback) { - process_sp = create_callback(target_sp, listener, crash_file_path); + process_sp = create_callback(target_sp, listener_sp, crash_file_path); if (process_sp) { if (process_sp->CanDebug(target_sp, true)) @@ -680,9 +684,9 @@ Process::FindPlugin (lldb::TargetSP target_sp, const char *plugin_name, Listener } else { - for (uint32_t idx = 0; (create_callback = PluginManager::GetProcessCreateCallbackAtIndex(idx)) != NULL; ++idx) + for (uint32_t idx = 0; (create_callback = PluginManager::GetProcessCreateCallbackAtIndex(idx)) != nullptr; ++idx) { - process_sp = create_callback(target_sp, listener, crash_file_path); + process_sp = create_callback(target_sp, listener_sp, crash_file_path); if (process_sp) { if (process_sp->CanDebug(target_sp, false)) @@ -705,113 +709,107 @@ Process::GetStaticBroadcasterClass () return class_name; } -Process::Process(lldb::TargetSP target_sp, Listener &listener) : - Process(target_sp, listener, UnixSignals::Create(HostInfo::GetArchitecture())) +Process::Process(lldb::TargetSP target_sp, ListenerSP listener_sp) : + Process(target_sp, listener_sp, UnixSignals::Create(HostInfo::GetArchitecture())) { // This constructor just delegates to the full Process constructor, // defaulting to using the Host's UnixSignals. } -Process::Process(lldb::TargetSP target_sp, Listener &listener, const UnixSignalsSP &unix_signals_sp) : - ProcessProperties (this), - UserID (LLDB_INVALID_PROCESS_ID), - Broadcaster (&(target_sp->GetDebugger()), Process::GetStaticBroadcasterClass().AsCString()), - m_target_sp (target_sp), - m_public_state (eStateUnloaded), - m_private_state (eStateUnloaded), - m_private_state_broadcaster (NULL, "lldb.process.internal_state_broadcaster"), - 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_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), - m_extended_thread_list (this), - m_extended_thread_stop_id (0), - m_queue_list (this), - m_queue_list_stop_id (0), - m_notifications (), - m_image_tokens (), - m_listener (listener), - m_breakpoint_site_list (), - m_dynamic_checkers_ap (), - m_unix_signals_sp (unix_signals_sp), - m_abi_sp (), - m_process_input_reader (), - m_stdio_communication ("process.stdio"), - m_stdio_communication_mutex (Mutex::eMutexTypeRecursive), - m_stdin_forward (false), - m_stdout_data (), - m_stderr_data (), - m_profile_data_comm_mutex (Mutex::eMutexTypeRecursive), - m_profile_data (), - m_iohandler_sync (0), - m_memory_cache (*this), - m_allocated_memory_cache (*this), - m_should_detach (false), - m_next_event_action_ap(), - m_public_run_lock (), - m_private_run_lock (), - m_stop_info_override_callback (NULL), - m_finalizing (false), - m_finalize_called (false), - m_clear_thread_plans_on_stop (false), - m_force_next_event_delivery (false), - m_last_broadcast_state (eStateInvalid), - m_destroy_in_process (false), - m_can_interpret_function_calls(false), - m_warnings_issued (), - m_can_jit(eCanJITDontKnow) -{ - CheckInWithManager (); - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); +Process::Process(lldb::TargetSP target_sp, ListenerSP listener_sp, const UnixSignalsSP &unix_signals_sp) + : ProcessProperties(this), + UserID(LLDB_INVALID_PROCESS_ID), + Broadcaster((target_sp->GetDebugger().GetBroadcasterManager()), Process::GetStaticBroadcasterClass().AsCString()), + m_target_sp(target_sp), + m_public_state(eStateUnloaded), + m_private_state(eStateUnloaded), + m_private_state_broadcaster(nullptr, "lldb.process.internal_state_broadcaster"), + m_private_state_control_broadcaster(nullptr, "lldb.process.internal_state_control_broadcaster"), + m_private_state_listener_sp(Listener::MakeListener("lldb.process.internal_state_listener")), + 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(), + m_thread_list_real(this), + m_thread_list(this), + m_extended_thread_list(this), + m_extended_thread_stop_id(0), + m_queue_list(this), + m_queue_list_stop_id(0), + m_notifications(), + m_image_tokens(), + m_listener_sp(listener_sp), + m_breakpoint_site_list(), + m_dynamic_checkers_ap(), + m_unix_signals_sp(unix_signals_sp), + m_abi_sp(), + m_process_input_reader(), + m_stdio_communication("process.stdio"), + m_stdio_communication_mutex(), + m_stdin_forward(false), + m_stdout_data(), + m_stderr_data(), + m_profile_data_comm_mutex(), + m_profile_data(), + m_iohandler_sync(0), + m_memory_cache(*this), + m_allocated_memory_cache(*this), + m_should_detach(false), + m_next_event_action_ap(), + m_public_run_lock(), + m_private_run_lock(), + m_stop_info_override_callback(nullptr), + m_finalizing(false), + m_finalize_called(false), + m_clear_thread_plans_on_stop(false), + m_force_next_event_delivery(false), + m_last_broadcast_state(eStateInvalid), + m_destroy_in_process(false), + m_can_interpret_function_calls(false), + m_warnings_issued(), + m_run_thread_plan_lock(), + m_can_jit(eCanJITDontKnow) +{ + CheckInWithManager(); + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); if (log) - log->Printf ("%p Process::Process()", static_cast<void*>(this)); + log->Printf("%p Process::Process()", static_cast<void *>(this)); if (!m_unix_signals_sp) m_unix_signals_sp = std::make_shared<UnixSignals>(); - SetEventName (eBroadcastBitStateChanged, "state-changed"); - SetEventName (eBroadcastBitInterrupt, "interrupt"); - SetEventName (eBroadcastBitSTDOUT, "stdout-available"); - SetEventName (eBroadcastBitSTDERR, "stderr-available"); - SetEventName (eBroadcastBitProfileData, "profile-data-available"); - - m_private_state_control_broadcaster.SetEventName (eBroadcastInternalStateControlStop , "control-stop" ); - m_private_state_control_broadcaster.SetEventName (eBroadcastInternalStateControlPause , "control-pause" ); - m_private_state_control_broadcaster.SetEventName (eBroadcastInternalStateControlResume, "control-resume"); - - listener.StartListeningForEvents (this, - eBroadcastBitStateChanged | - eBroadcastBitInterrupt | - eBroadcastBitSTDOUT | - eBroadcastBitSTDERR | - eBroadcastBitProfileData); - - m_private_state_listener.StartListeningForEvents(&m_private_state_broadcaster, - eBroadcastBitStateChanged | - eBroadcastBitInterrupt); - - m_private_state_listener.StartListeningForEvents(&m_private_state_control_broadcaster, - eBroadcastInternalStateControlStop | - eBroadcastInternalStateControlPause | - eBroadcastInternalStateControlResume); + SetEventName(eBroadcastBitStateChanged, "state-changed"); + SetEventName(eBroadcastBitInterrupt, "interrupt"); + SetEventName(eBroadcastBitSTDOUT, "stdout-available"); + SetEventName(eBroadcastBitSTDERR, "stderr-available"); + SetEventName(eBroadcastBitProfileData, "profile-data-available"); + + m_private_state_control_broadcaster.SetEventName(eBroadcastInternalStateControlStop, "control-stop"); + m_private_state_control_broadcaster.SetEventName(eBroadcastInternalStateControlPause, "control-pause"); + m_private_state_control_broadcaster.SetEventName(eBroadcastInternalStateControlResume, "control-resume"); + + m_listener_sp->StartListeningForEvents(this, eBroadcastBitStateChanged | eBroadcastBitInterrupt | + eBroadcastBitSTDOUT | eBroadcastBitSTDERR | + eBroadcastBitProfileData); + + m_private_state_listener_sp->StartListeningForEvents(&m_private_state_broadcaster, + eBroadcastBitStateChanged | eBroadcastBitInterrupt); + + m_private_state_listener_sp->StartListeningForEvents( + &m_private_state_control_broadcaster, eBroadcastInternalStateControlStop | eBroadcastInternalStateControlPause | + eBroadcastInternalStateControlResume); // We need something valid here, even if just the default UnixSignalsSP. - assert (m_unix_signals_sp && "null m_unix_signals_sp after initialization"); + assert(m_unix_signals_sp && "null m_unix_signals_sp after initialization"); // Allow the platform to override the default cache line size - OptionValueSP value_sp = - m_collection_sp->GetPropertyAtIndex(nullptr, true, ePropertyMemCacheLineSize)->GetValue(); + OptionValueSP value_sp = m_collection_sp->GetPropertyAtIndex(nullptr, true, ePropertyMemCacheLineSize)->GetValue(); uint32_t platform_cache_line_size = target_sp->GetPlatform()->GetDefaultMemoryCacheLineSize(); - if (! value_sp->OptionWasSet() && platform_cache_line_size != 0) + if (!value_sp->OptionWasSet() && platform_cache_line_size != 0) value_sp->SetUInt64Value(platform_cache_line_size); } @@ -831,10 +829,14 @@ Process::~Process() const ProcessPropertiesSP & Process::GetGlobalProperties() { - static ProcessPropertiesSP g_settings_sp; - if (!g_settings_sp) - g_settings_sp.reset (new ProcessProperties (NULL)); - return g_settings_sp; + // NOTE: intentional leak so we don't crash if global destructor chain gets + // called as other threads still use the result of this function + static ProcessPropertiesSP *g_settings_sp_ptr = nullptr; + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + g_settings_sp_ptr = new ProcessPropertiesSP(new ProcessProperties(nullptr)); + }); + return *g_settings_sp_ptr; } void @@ -890,14 +892,14 @@ Process::Finalize() m_language_runtimes.clear(); m_instrumentation_runtimes.clear(); m_next_event_action_ap.reset(); - m_stop_info_override_callback = NULL; + m_stop_info_override_callback = nullptr; // Clear the last natural stop ID since it has a strong // reference to this process m_mod_id.SetStopEventForLastNaturalStopID(EventSP()); //#ifdef LLDB_CONFIGURATION_DEBUG // StreamFile s(stdout, false); // EventSP event_sp; -// while (m_private_state_listener.GetNextEvent(event_sp)) +// while (m_private_state_listener_sp->GetNextEvent(event_sp)) // { // event_sp->Dump (&s); // s.EOL(); @@ -906,7 +908,7 @@ Process::Finalize() // We have to be very careful here as the m_private_state_listener might // contain events that have ProcessSP values in them which can keep this // process around forever. These events need to be cleared out. - m_private_state_listener.Clear(); + m_private_state_listener_sp->Clear(); m_public_run_lock.TrySetRunning(); // This will do nothing if already locked m_public_run_lock.SetStopped(); m_private_run_lock.TrySetRunning(); // This will do nothing if already locked @@ -918,7 +920,7 @@ void Process::RegisterNotificationCallbacks (const Notifications& callbacks) { m_notifications.push_back(callbacks); - if (callbacks.initialize != NULL) + if (callbacks.initialize != nullptr) callbacks.initialize (callbacks.baton, this); } @@ -963,7 +965,7 @@ Process::GetNextEvent (EventSP &event_sp) { StateType state = eStateInvalid; - if (m_listener.GetNextEventForBroadcaster (this, event_sp) && event_sp) + if (m_listener_sp->GetNextEventForBroadcaster (this, event_sp) && event_sp) state = Process::ProcessEventData::GetStateFromEvent (event_sp.get()); return state; @@ -973,7 +975,7 @@ void Process::SyncIOHandler (uint32_t iohandler_id, uint64_t timeout_msec) { // don't sync (potentially context switch) in case where there is no process IO - if (! m_process_input_reader) + if (!m_process_input_reader) return; TimeValue timeout = TimeValue::Now(); @@ -990,7 +992,7 @@ StateType Process::WaitForProcessToStop (const TimeValue *timeout, EventSP *event_sp_ptr, bool wait_always, - Listener *hijack_listener, + ListenerSP hijack_listener_sp, Stream *stream, bool use_run_lock) { @@ -1019,7 +1021,7 @@ Process::WaitForProcessToStop (const TimeValue *timeout, __FUNCTION__); // We need to toggle the run lock as this won't get done in // SetPublicState() if the process is hijacked. - if (hijack_listener && use_run_lock) + if (hijack_listener_sp && use_run_lock) m_public_run_lock.SetStopped(); return state; } @@ -1027,11 +1029,11 @@ Process::WaitForProcessToStop (const TimeValue *timeout, while (state != eStateInvalid) { EventSP event_sp; - state = WaitForStateChangedEvents (timeout, event_sp, hijack_listener); + state = WaitForStateChangedEvents (timeout, event_sp, hijack_listener_sp); if (event_sp_ptr && event_sp) *event_sp_ptr = event_sp; - bool pop_process_io_handler = hijack_listener != NULL; + bool pop_process_io_handler = (hijack_listener_sp.get() != nullptr); Process::HandleProcessStateChangedEvent (event_sp, stream, pop_process_io_handler); switch (state) @@ -1042,7 +1044,7 @@ Process::WaitForProcessToStop (const TimeValue *timeout, case eStateUnloaded: // We need to toggle the run lock as this won't get done in // SetPublicState() if the process is hijacked. - if (hijack_listener && use_run_lock) + if (hijack_listener_sp && use_run_lock) m_public_run_lock.SetStopped(); return state; case eStateStopped: @@ -1052,7 +1054,7 @@ Process::WaitForProcessToStop (const TimeValue *timeout, { // We need to toggle the run lock as this won't get done in // SetPublicState() if the process is hijacked. - if (hijack_listener && use_run_lock) + if (hijack_listener_sp && use_run_lock) m_public_run_lock.SetStopped(); return state; } @@ -1068,7 +1070,7 @@ Process::HandleProcessStateChangedEvent (const EventSP &event_sp, Stream *stream, bool &pop_process_io_handler) { - const bool handle_pop = pop_process_io_handler == true; + const bool handle_pop = pop_process_io_handler; pop_process_io_handler = false; ProcessSP process_sp = Process::ProcessEventData::GetProcessFromEvent(event_sp.get()); @@ -1088,15 +1090,12 @@ Process::HandleProcessStateChangedEvent (const EventSP &event_sp, 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; - } + 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: @@ -1149,7 +1148,7 @@ Process::HandleProcessStateChangedEvent (const EventSP &event_sp, // 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()); + std::lock_guard<std::recursive_mutex> guard(thread_list.GetMutex()); ThreadSP curr_thread (thread_list.GetSelectedThread()); ThreadSP thread; @@ -1271,7 +1270,6 @@ Process::WaitForState(const TimeValue *timeout, const uint32_t num_match_states) { EventSP event_sp; - uint32_t i; StateType state = GetState(); while (state != eStateInvalid) { @@ -1280,9 +1278,9 @@ Process::WaitForState(const TimeValue *timeout, if (state == eStateDetached || state == eStateExited) return state; - state = WaitForStateChangedEvents (timeout, event_sp, NULL); + state = WaitForStateChangedEvents(timeout, event_sp, nullptr); - for (i=0; i<num_match_states; ++i) + for (uint32_t i = 0; i < num_match_states; ++i) { if (match_states[i] == state) return state; @@ -1292,11 +1290,11 @@ Process::WaitForState(const TimeValue *timeout, } bool -Process::HijackProcessEvents (Listener *listener) +Process::HijackProcessEvents (ListenerSP listener_sp) { - if (listener != NULL) + if (listener_sp) { - return HijackBroadcaster(listener, eBroadcastBitStateChanged | eBroadcastBitInterrupt); + return HijackBroadcaster(listener_sp, eBroadcastBitStateChanged | eBroadcastBitInterrupt); } else return false; @@ -1309,7 +1307,7 @@ Process::RestoreProcessEvents () } StateType -Process::WaitForStateChangedEvents (const TimeValue *timeout, EventSP &event_sp, Listener *hijack_listener) +Process::WaitForStateChangedEvents (const TimeValue *timeout, EventSP &event_sp, ListenerSP hijack_listener_sp) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); @@ -1317,15 +1315,15 @@ Process::WaitForStateChangedEvents (const TimeValue *timeout, EventSP &event_sp, log->Printf ("Process::%s (timeout = %p, event_sp)...", __FUNCTION__, static_cast<const void*>(timeout)); - Listener *listener = hijack_listener; - if (listener == NULL) - listener = &m_listener; + ListenerSP listener_sp = hijack_listener_sp; + if (!listener_sp) + listener_sp = m_listener_sp; StateType state = eStateInvalid; - if (listener->WaitForEventForBroadcasterWithType (timeout, - this, - eBroadcastBitStateChanged | eBroadcastBitInterrupt, - event_sp)) + if (listener_sp->WaitForEventForBroadcasterWithType (timeout, + this, + eBroadcastBitStateChanged | eBroadcastBitInterrupt, + event_sp)) { if (event_sp && event_sp->GetType() == eBroadcastBitStateChanged) state = Process::ProcessEventData::GetStateFromEvent(event_sp.get()); @@ -1349,7 +1347,7 @@ Process::PeekAtStateChangedEvents () log->Printf ("Process::%s...", __FUNCTION__); Event *event_ptr; - event_ptr = m_listener.PeekAtNextEventForBroadcasterWithType (this, + event_ptr = m_listener_sp->PeekAtNextEventForBroadcasterWithType (this, eBroadcastBitStateChanged); if (log) { @@ -1378,7 +1376,7 @@ Process::WaitForStateChangedEventsPrivate (const TimeValue *timeout, EventSP &ev static_cast<const void*>(timeout)); StateType state = eStateInvalid; - if (m_private_state_listener.WaitForEventForBroadcasterWithType (timeout, + if (m_private_state_listener_sp->WaitForEventForBroadcasterWithType (timeout, &m_private_state_broadcaster, eBroadcastBitStateChanged | eBroadcastBitInterrupt, event_sp)) @@ -1405,9 +1403,9 @@ Process::WaitForEventsPrivate (const TimeValue *timeout, EventSP &event_sp, bool static_cast<const void*>(timeout)); if (control_only) - return m_private_state_listener.WaitForEventForBroadcaster(timeout, &m_private_state_control_broadcaster, event_sp); + return m_private_state_listener_sp->WaitForEventForBroadcaster(timeout, &m_private_state_control_broadcaster, event_sp); else - return m_private_state_listener.WaitForEvent(timeout, event_sp); + return m_private_state_listener_sp->WaitForEvent(timeout, event_sp); } bool @@ -1419,7 +1417,7 @@ Process::IsRunning () const int Process::GetExitStatus () { - Mutex::Locker locker (m_exit_status_mutex); + std::lock_guard<std::mutex> guard(m_exit_status_mutex); if (m_public_state.GetValue() == eStateExited) return m_exit_status; @@ -1429,18 +1427,18 @@ Process::GetExitStatus () const char * Process::GetExitDescription () { - Mutex::Locker locker (m_exit_status_mutex); + std::lock_guard<std::mutex> guard(m_exit_status_mutex); if (m_public_state.GetValue() == eStateExited && !m_exit_string.empty()) return m_exit_string.c_str(); - return NULL; + return nullptr; } bool Process::SetExitStatus (int status, const char *cstr) { // Use a mutex to protect setting the exit status. - Mutex::Locker locker (m_exit_status_mutex); + std::lock_guard<std::mutex> guard(m_exit_status_mutex); Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STATE | LIBLLDB_LOG_PROCESS)); if (log) @@ -1464,14 +1462,6 @@ Process::SetExitStatus (int status, const char *cstr) else m_exit_string.clear(); - // When we exit, we don't need the input reader anymore - if (m_process_input_reader) - { - m_process_input_reader->SetIsDone(true); - m_process_input_reader->Cancel(); - m_process_input_reader.reset(); - } - // Clear the last natural stop ID since it has a strong // reference to this process m_mod_id.SetStopEventForLastNaturalStopID(EventSP()); @@ -1489,12 +1479,6 @@ Process::IsAlive () { switch (m_private_state.GetValue()) { - case eStateInvalid: - case eStateUnloaded: - case eStateDetached: - case eStateExited: - return false; - case eStateConnected: case eStateAttaching: case eStateLaunching: @@ -1504,6 +1488,8 @@ Process::IsAlive () case eStateCrashed: case eStateSuspended: return true; + default: + return false; } } @@ -1512,21 +1498,15 @@ Process::IsAlive () // found in the global target list (we want to be completely sure that the // lldb_private::Process doesn't go away before we can deliver the signal. bool -Process::SetProcessExitStatus (void *callback_baton, - lldb::pid_t pid, - bool exited, - int signo, // Zero for no signal - int exit_status // Exit value of process if signal is zero -) +Process::SetProcessExitStatus(lldb::pid_t pid, bool exited, + int signo, // Zero for no signal + int exit_status // Exit value of process if signal is zero + ) { Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS)); if (log) - log->Printf ("Process::SetProcessExitStatus (baton=%p, pid=%" PRIu64 ", exited=%i, signal=%i, exit_status=%i)\n", - callback_baton, - pid, - exited, - signo, - exit_status); + log->Printf("Process::SetProcessExitStatus (pid=%" PRIu64 ", exited=%i, signal=%i, exit_status=%i)\n", pid, + exited, signo, exit_status); if (exited) { @@ -1536,7 +1516,7 @@ Process::SetProcessExitStatus (void *callback_baton, ProcessSP process_sp (target_sp->GetProcessSP()); if (process_sp) { - const char *signal_cstr = NULL; + const char *signal_cstr = nullptr; if (signo) signal_cstr = process_sp->GetUnixSignals()->GetSignalAsCString(signo); @@ -1557,7 +1537,7 @@ Process::UpdateThreadListIfNeeded () const StateType state = GetPrivateState(); if (StateIsStoppedState (state, true)) { - Mutex::Locker locker (m_thread_list.GetMutex ()); + std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex()); // m_thread_list does have its own mutex, but we need to // hold onto the mutex between the call to UpdateThreadList(...) // and the os->UpdateThreadList(...) so it doesn't change on us @@ -1577,7 +1557,7 @@ Process::UpdateThreadListIfNeeded () // Clear any old backing threads where memory threads might have been // backed by actual threads from the lldb_private::Process subclass size_t num_old_threads = old_thread_list.GetSize(false); - for (size_t i=0; i<num_old_threads; ++i) + for (size_t i = 0; i < num_old_threads; ++i) old_thread_list.GetThreadAtIndex(i, false)->ClearBackingThread(); // Turn off dynamic types to ensure we don't run any expressions. Objective C @@ -1626,7 +1606,7 @@ Process::UpdateThreadListIfNeeded () void Process::UpdateQueueListIfNeeded () { - if (m_system_runtime_ap.get()) + if (m_system_runtime_ap) { if (m_queue_list.GetSize() == 0 || m_queue_list_stop_id != GetLastNaturalStopID()) { @@ -1691,7 +1671,8 @@ Process::StateChangedIsExternallyHijacked() { if (IsHijackedForEvent(eBroadcastBitStateChanged)) { - if (strcmp(m_hijacking_listeners.back()->GetName(), "lldb.Process.ResumeSynchronous.hijack")) + const char *hijacking_name = GetHijackingListenerName(); + if (hijacking_name && strcmp(hijacking_name, "lldb.Process.ResumeSynchronous.hijack")) return true; } return false; @@ -1764,13 +1745,13 @@ Process::ResumeSynchronous (Stream *stream) return error; } - ListenerSP listener_sp (new Listener("lldb.Process.ResumeSynchronous.hijack")); - HijackProcessEvents(listener_sp.get()); + ListenerSP listener_sp (Listener::MakeListener("lldb.Process.ResumeSynchronous.hijack")); + HijackProcessEvents(listener_sp); Error error = PrivateResume(); if (error.Success()) { - StateType state = WaitForProcessToStop (NULL, NULL, true, listener_sp.get(), stream); + StateType state = WaitForProcessToStop (NULL, NULL, true, listener_sp, stream); const bool must_be_alive = false; // eStateExited is ok, so this must be false if (!StateIsStoppedState(state, must_be_alive)) error.SetErrorStringWithFormat("process not in stopped state after synchronous resume: %s", StateAsCString(state)); @@ -1800,8 +1781,8 @@ Process::SetPrivateState (StateType new_state) if (log) log->Printf("Process::SetPrivateState (%s)", StateAsCString(new_state)); - Mutex::Locker thread_locker(m_thread_list.GetMutex()); - Mutex::Locker locker(m_private_state.GetMutex()); + std::lock_guard<std::recursive_mutex> thread_guard(m_thread_list.GetMutex()); + std::lock_guard<std::recursive_mutex> guard(m_private_state.GetMutex()); const StateType old_state = m_private_state.GetValueNoLock (); state_changed = old_state != new_state; @@ -1844,7 +1825,7 @@ Process::SetPrivateState (StateType new_state) } // Use our target to get a shared pointer to ourselves... - if (m_finalize_called && PrivateStateThreadIsValid() == false) + if (m_finalize_called && !PrivateStateThreadIsValid()) BroadcastEvent (event_sp); else m_private_state_broadcaster.BroadcastEvent (event_sp); @@ -1899,18 +1880,18 @@ CPPLanguageRuntime * Process::GetCPPLanguageRuntime (bool retry_if_null) { LanguageRuntime *runtime = GetLanguageRuntime(eLanguageTypeC_plus_plus, retry_if_null); - if (runtime != NULL && runtime->GetLanguageType() == eLanguageTypeC_plus_plus) + if (runtime != nullptr && runtime->GetLanguageType() == eLanguageTypeC_plus_plus) return static_cast<CPPLanguageRuntime *> (runtime); - return NULL; + return nullptr; } ObjCLanguageRuntime * Process::GetObjCLanguageRuntime (bool retry_if_null) { LanguageRuntime *runtime = GetLanguageRuntime(eLanguageTypeObjC, retry_if_null); - if (runtime != NULL && runtime->GetLanguageType() == eLanguageTypeObjC) + if (runtime != nullptr && runtime->GetLanguageType() == eLanguageTypeObjC) return static_cast<ObjCLanguageRuntime *> (runtime); - return NULL; + return nullptr; } bool @@ -2167,7 +2148,7 @@ Error Process::EnableSoftwareBreakpoint (BreakpointSite *bp_site) { Error error; - assert (bp_site != NULL); + assert(bp_site != nullptr); Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); const addr_t bp_addr = bp_site->GetLoadAddress(); if (log) @@ -2196,7 +2177,7 @@ Process::EnableSoftwareBreakpoint (BreakpointSite *bp_site) { const uint8_t * const bp_opcode_bytes = bp_site->GetTrapOpcodeBytes(); - if (bp_opcode_bytes == NULL) + if (bp_opcode_bytes == nullptr) { error.SetErrorString ("BreakpointSite doesn't contain a valid breakpoint trap opcode."); return error; @@ -2244,7 +2225,7 @@ Error Process::DisableSoftwareBreakpoint (BreakpointSite *bp_site) { Error error; - assert (bp_site != NULL); + assert(bp_site != nullptr); Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); addr_t bp_addr = bp_site->GetLoadAddress(); lldb::user_id_t breakID = bp_site->GetID(); @@ -2388,7 +2369,7 @@ Process::ReadCStringFromMemory (addr_t addr, std::string &out_str, Error &error) char buf[256]; out_str.clear(); addr_t curr_addr = addr; - while (1) + while (true) { size_t length = ReadCStringFromMemory (curr_addr, buf, sizeof(buf), error); if (length == 0) @@ -2436,7 +2417,7 @@ Process::ReadStringFromMemory (addr_t addr, char *dst, size_t max_bytes, Error & // Search for a null terminator of correct size and alignment in bytes_read size_t aligned_start = total_bytes_read - total_bytes_read % type_width; for (size_t i = aligned_start; i + type_width <= total_bytes_read + bytes_read; i += type_width) - if (::strncmp(&dst[i], terminator, type_width) == 0) + if (::memcmp(&dst[i], terminator, type_width) == 0) { error.Clear(); return i; @@ -2499,7 +2480,7 @@ Process::ReadCStringFromMemory (addr_t addr, char *dst, size_t dst_max_len, Erro } else { - if (dst == NULL) + if (dst == nullptr) result_error.SetErrorString("invalid arguments"); else result_error.Clear(); @@ -2510,7 +2491,7 @@ Process::ReadCStringFromMemory (addr_t addr, char *dst, size_t dst_max_len, Erro size_t Process::ReadMemoryFromInferior (addr_t addr, void *buf, size_t size, Error &error) { - if (buf == NULL || size == 0) + if (buf == nullptr || size == 0) return 0; size_t bytes_read = 0; @@ -2536,7 +2517,8 @@ Process::ReadMemoryFromInferior (addr_t addr, void *buf, size_t size, Error &err } uint64_t -Process::ReadUnsignedIntegerFromMemory (lldb::addr_t vm_addr, size_t integer_byte_size, uint64_t fail_value, Error &error) +Process::ReadUnsignedIntegerFromMemory(lldb::addr_t vm_addr, size_t integer_byte_size, uint64_t fail_value, + Error &error) { Scalar scalar; if (ReadScalarIntegerFromMemory(vm_addr, integer_byte_size, false, scalar, error)) @@ -2544,6 +2526,15 @@ Process::ReadUnsignedIntegerFromMemory (lldb::addr_t vm_addr, size_t integer_byt return fail_value; } +int64_t +Process::ReadSignedIntegerFromMemory(lldb::addr_t vm_addr, size_t integer_byte_size, int64_t fail_value, Error &error) +{ + Scalar scalar; + if (ReadScalarIntegerFromMemory(vm_addr, integer_byte_size, true, scalar, error)) + return scalar.SLongLong(fail_value); + return fail_value; +} + addr_t Process::ReadPointerFromMemory (lldb::addr_t vm_addr, Error &error) { @@ -2594,7 +2585,7 @@ Process::WriteMemory (addr_t addr, const void *buf, size_t size, Error &error) m_memory_cache.Flush (addr, size); #endif - if (buf == NULL || size == 0) + if (buf == nullptr || size == 0) return 0; m_mod_id.BumpMemoryID(); @@ -2905,7 +2896,7 @@ Process::WaitForProcessStopPrivate (const TimeValue *timeout, EventSP &event_sp) StateType state; // Now wait for the process to launch and return control to us, and then // call DidLaunch: - while (1) + while (true) { event_sp.reset(); state = WaitForStateChangedEventsPrivate (timeout, event_sp); @@ -2928,7 +2919,7 @@ Process::LoadOperatingSystemPlugin(bool flush) { if (flush) m_thread_list.Clear(); - m_os_ap.reset (OperatingSystem::FindPlugin (this, NULL)); + m_os_ap.reset(OperatingSystem::FindPlugin(this, nullptr)); if (flush) Flush(); } @@ -2943,7 +2934,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; + m_stop_info_override_callback = nullptr; Module *exe_module = GetTarget().GetExecutableModulePointer(); if (exe_module) @@ -2988,7 +2979,7 @@ Process::Launch (ProcessLaunchInfo &launch_info) { SetID (LLDB_INVALID_PROCESS_ID); const char *error_string = error.AsCString(); - if (error_string == NULL) + if (error_string == nullptr) error_string = "launch failed"; SetExitStatus (-1, error_string); } @@ -3001,7 +2992,7 @@ Process::Launch (ProcessLaunchInfo &launch_info) timeout_time.OffsetWithSeconds(10); StateType state = WaitForProcessStopPrivate(&timeout_time, event_sp); - if (state == eStateInvalid || event_sp.get() == NULL) + if (state == eStateInvalid || !event_sp) { // We were able to launch the process, but we failed to // catch the initial stop. @@ -3066,8 +3057,8 @@ Process::LoadCore () Error error = DoLoadCore(); if (error.Success()) { - Listener listener ("lldb.process.load_core_listener"); - HijackProcessEvents(&listener); + ListenerSP listener_sp (Listener::MakeListener("lldb.process.load_core_listener")); + HijackProcessEvents(listener_sp); if (PrivateStateThreadIsValid ()) ResumePrivateStateThread (); @@ -3084,7 +3075,7 @@ Process::LoadCore () if (system_runtime) system_runtime->DidAttach(); - m_os_ap.reset (OperatingSystem::FindPlugin (this, NULL)); + m_os_ap.reset(OperatingSystem::FindPlugin(this, nullptr)); // We successfully loaded a core file, now pretend we stopped so we can // show all of the threads in the core file and explore the crashed // state. @@ -3092,7 +3083,7 @@ Process::LoadCore () // Wait indefinitely for a stopped event since we just posted one above... lldb::EventSP event_sp; - listener.WaitForEvent (NULL, event_sp); + listener_sp->WaitForEvent (nullptr, event_sp); StateType state = ProcessEventData::GetStateFromEvent(event_sp.get()); if (!StateIsStoppedState (state, false)) @@ -3110,8 +3101,8 @@ Process::LoadCore () DynamicLoader * Process::GetDynamicLoader () { - if (m_dyld_ap.get() == NULL) - m_dyld_ap.reset (DynamicLoader::FindPlugin(this, NULL)); + if (!m_dyld_ap) + m_dyld_ap.reset(DynamicLoader::FindPlugin(this, nullptr)); return m_dyld_ap.get(); } @@ -3135,8 +3126,8 @@ Process::GetJITLoaders () SystemRuntime * Process::GetSystemRuntime () { - if (m_system_runtime_ap.get() == NULL) - m_system_runtime_ap.reset (SystemRuntime::FindPlugin(this)); + if (!m_system_runtime_ap) + m_system_runtime_ap.reset(SystemRuntime::FindPlugin(this)); return m_system_runtime_ap.get(); } @@ -3169,31 +3160,29 @@ Process::AttachCompletionHandler::PerformAction (lldb::EventSP &event_sp) case eStateStopped: case eStateCrashed: + // During attach, prior to sending the eStateStopped event, + // lldb_private::Process subclasses must set the new process ID. + assert (m_process->GetID() != LLDB_INVALID_PROCESS_ID); + // We don't want these events to be reported, so go set the ShouldReportStop here: + m_process->GetThreadList().SetShouldReportStop (eVoteNo); + + if (m_exec_count > 0) { - // During attach, prior to sending the eStateStopped event, - // lldb_private::Process subclasses must set the new process ID. - assert (m_process->GetID() != LLDB_INVALID_PROCESS_ID); - // We don't want these events to be reported, so go set the ShouldReportStop here: - m_process->GetThreadList().SetShouldReportStop (eVoteNo); - - if (m_exec_count > 0) - { - --m_exec_count; + --m_exec_count; - if (log) - log->Printf ("Process::AttachCompletionHandler::%s state %s: reduced remaining exec count to %" PRIu32 ", requesting resume", __FUNCTION__, StateAsCString(state), m_exec_count); + if (log) + log->Printf ("Process::AttachCompletionHandler::%s state %s: reduced remaining exec count to %" PRIu32 ", requesting resume", __FUNCTION__, StateAsCString(state), m_exec_count); - RequestResume(); - return eEventActionRetry; - } - else - { - if (log) - log->Printf ("Process::AttachCompletionHandler::%s state %s: no more execs expected to start, continuing with attach", __FUNCTION__, StateAsCString(state)); + RequestResume(); + return eEventActionRetry; + } + else + { + if (log) + log->Printf ("Process::AttachCompletionHandler::%s state %s: no more execs expected to start, continuing with attach", __FUNCTION__, StateAsCString(state)); - m_process->CompleteAttach (); - return eEventActionSuccess; - } + m_process->CompleteAttach (); + return eEventActionSuccess; } break; @@ -3219,11 +3208,11 @@ Process::AttachCompletionHandler::GetExitString () return m_exit_string.c_str(); } -Listener & +ListenerSP ProcessAttachInfo::GetListenerForProcess (Debugger &debugger) { if (m_listener_sp) - return *m_listener_sp; + return m_listener_sp; else return debugger.GetListener(); } @@ -3237,7 +3226,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; + m_stop_info_override_callback = nullptr; lldb::pid_t attach_pid = attach_info.GetProcessID(); Error error; @@ -3273,7 +3262,7 @@ Process::Attach (ProcessAttachInfo &attach_info) if (GetID() != LLDB_INVALID_PROCESS_ID) { SetID (LLDB_INVALID_PROCESS_ID); - if (error.AsCString() == NULL) + if (error.AsCString() == nullptr) error.SetErrorString("attach failed"); SetExitStatus(-1, error.AsCString()); @@ -3358,7 +3347,6 @@ Process::Attach (ProcessAttachInfo &attach_info) if (error.Success()) { - SetNextEventAction(new Process::AttachCompletionHandler(this, attach_info.GetResumeCount())); StartPrivateStateThread(); } @@ -3368,7 +3356,7 @@ Process::Attach (ProcessAttachInfo &attach_info) SetID (LLDB_INVALID_PROCESS_ID); const char *error_string = error.AsCString(); - if (error_string == NULL) + if (error_string == nullptr) error_string = "attach failed"; SetExitStatus(-1, error_string); @@ -3381,7 +3369,7 @@ Process::Attach (ProcessAttachInfo &attach_info) void Process::CompleteAttach () { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); + Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TARGET)); if (log) log->Printf ("Process::%s()", __FUNCTION__); @@ -3405,11 +3393,11 @@ Process::CompleteAttach () // We just attached. If we have a platform, ask it for the process architecture, and if it isn't // the same as the one we've already set, switch architectures. PlatformSP platform_sp (GetTarget().GetPlatform ()); - assert (platform_sp.get()); + assert(platform_sp); if (platform_sp) { const ArchSpec &target_arch = GetTarget().GetArchitecture(); - if (target_arch.IsValid() && !platform_sp->IsCompatibleArchitecture (target_arch, false, NULL)) + if (target_arch.IsValid() && !platform_sp->IsCompatibleArchitecture(target_arch, false, nullptr)) { ArchSpec platform_arch; platform_sp = platform_sp->GetPlatformForArchitecture (target_arch, &platform_arch); @@ -3424,7 +3412,7 @@ Process::CompleteAttach () else if (!process_arch.IsValid()) { ProcessInstanceInfo process_info; - platform_sp->GetProcessInfo (GetID(), process_info); + GetProcessInfo(process_info); const ArchSpec &process_arch = process_info.GetArchitecture(); if (process_arch.IsValid() && !GetTarget().GetArchitecture().IsExactMatch(process_arch)) { @@ -3467,10 +3455,10 @@ Process::CompleteAttach () } } - m_os_ap.reset (OperatingSystem::FindPlugin (this, NULL)); + m_os_ap.reset(OperatingSystem::FindPlugin(this, nullptr)); // Figure out which one is the executable, and set that in our target: const ModuleList &target_modules = GetTarget().GetImages(); - Mutex::Locker modules_locker(target_modules.GetMutex()); + std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); size_t num_modules = target_modules.GetSize(); ModuleSP new_executable_module_sp; @@ -3514,7 +3502,7 @@ Process::ConnectRemote (Stream *strm, const char *remote_url) if (GetID() != LLDB_INVALID_PROCESS_ID) { EventSP event_sp; - StateType state = WaitForProcessStopPrivate(NULL, event_sp); + StateType state = WaitForProcessStopPrivate(nullptr, event_sp); if (state == eStateStopped || state == eStateCrashed) { @@ -3525,7 +3513,6 @@ Process::ConnectRemote (Stream *strm, const char *remote_url) // This delays passing the stopped event to listeners till // CompleteAttach gets a chance to complete... HandlePrivateEvent (event_sp); - } } @@ -3607,8 +3594,8 @@ Process::Halt (bool clear_thread_plans, bool use_run_lock) // own. m_clear_thread_plans_on_stop |= clear_thread_plans; - Listener halt_listener ("lldb.process.halt_listener"); - HijackProcessEvents(&halt_listener); + ListenerSP halt_listener_sp (Listener::MakeListener("lldb.process.halt_listener")); + HijackProcessEvents(halt_listener_sp); EventSP event_sp; @@ -3628,7 +3615,7 @@ Process::Halt (bool clear_thread_plans, bool use_run_lock) TimeValue timeout_time; timeout_time = TimeValue::Now(); timeout_time.OffsetWithSeconds(10); - StateType state = WaitForProcessToStop(&timeout_time, &event_sp, true, &halt_listener, + StateType state = WaitForProcessToStop(&timeout_time, &event_sp, true, halt_listener_sp, nullptr, use_run_lock); RestoreProcessEvents(); @@ -3653,8 +3640,8 @@ Process::StopForDestroyOrDetach(lldb::EventSP &exit_event_sp) if (log) log->Printf("Process::%s() About to stop.", __FUNCTION__); - ListenerSP listener_sp (new Listener("lldb.Process.StopForDestroyOrDetach.hijack")); - HijackProcessEvents(listener_sp.get()); + ListenerSP listener_sp (Listener::MakeListener("lldb.Process.StopForDestroyOrDetach.hijack")); + HijackProcessEvents(listener_sp); SendAsyncInterrupt(); @@ -3662,7 +3649,7 @@ Process::StopForDestroyOrDetach(lldb::EventSP &exit_event_sp) TimeValue timeout (TimeValue::Now()); timeout.OffsetWithSeconds(10); - StateType state = WaitForProcessToStop (&timeout, &exit_event_sp, true, listener_sp.get()); + StateType state = WaitForProcessToStop (&timeout, &exit_event_sp, true, listener_sp); RestoreProcessEvents(); @@ -3688,7 +3675,7 @@ Process::StopForDestroyOrDetach(lldb::EventSP &exit_event_sp) StateType private_state = m_private_state.GetValue(); if (private_state != eStateStopped) { - return error; + return Error("Attempt to stop the target in order to detach timed out. State = %s", StateAsCString(GetState())); } } } @@ -3888,7 +3875,7 @@ Process::ShouldBroadcastEvent (Event *event_ptr) m_stdio_communication.StopReadThread(); m_stdin_forward = false; - // fall-through + LLVM_FALLTHROUGH; case eStateConnected: case eStateAttaching: case eStateLaunching: @@ -3945,7 +3932,6 @@ Process::ShouldBroadcastEvent (Event *event_ptr) case eStateStopped: case eStateCrashed: case eStateSuspended: - { // We've stopped. First see if we're going to restart the target. // If we are going to stop, then we always broadcast the event. // If we aren't going to stop, let the thread plans decide if we're going to report this event. @@ -3974,7 +3960,7 @@ Process::ShouldBroadcastEvent (Event *event_ptr) // So in that case just report the event. if (!was_restarted) - should_resume = m_thread_list.ShouldStop (event_ptr) == false; + should_resume = !m_thread_list.ShouldStop(event_ptr); if (was_restarted || should_resume || m_resume_requested) { @@ -4011,8 +3997,7 @@ Process::ShouldBroadcastEvent (Event *event_ptr) SynchronouslyNotifyStateChanged (state); } } - } - break; + break; } // Forcing the next event delivery is a one shot deal. So reset it here. @@ -4069,8 +4054,8 @@ Process::StartPrivateStateThread (bool is_secondary_thread) } // Create the private state thread, and start it running. - PrivateStateThreadArgs args = {this, is_secondary_thread}; - m_private_state_thread = ThreadLauncher::LaunchThread(thread_name, Process::PrivateStateThread, (void *) &args, NULL, 8 * 1024 * 1024); + PrivateStateThreadArgs *args_ptr = new PrivateStateThreadArgs(this, is_secondary_thread); + m_private_state_thread = ThreadLauncher::LaunchThread(thread_name, Process::PrivateStateThread, (void *) args_ptr, nullptr, 8 * 1024 * 1024); if (m_private_state_thread.IsJoinable()) { ResumePrivateStateThread(); @@ -4095,7 +4080,7 @@ Process::ResumePrivateStateThread () void Process::StopPrivateStateThread () { - if (PrivateStateThreadIsValid ()) + if (m_private_state_thread.IsJoinable ()) ControlPrivateStateThread (eBroadcastInternalStateControlStop); else { @@ -4117,47 +4102,52 @@ Process::ControlPrivateStateThread (uint32_t signal) if (log) log->Printf ("Process::%s (signal = %d)", __FUNCTION__, 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 - HostThread private_state_thread(m_private_state_thread); - if (private_state_thread.IsJoinable()) + // Signal the private state thread + if (m_private_state_thread.IsJoinable()) { - TimeValue timeout_time; - bool timed_out; - - m_private_state_control_broadcaster.BroadcastEvent (signal, NULL); - - timeout_time = TimeValue::Now(); - timeout_time.OffsetWithSeconds(2); + // Broadcast the event. + // It is important to do this outside of the if below, because + // it's possible that the thread state is invalid but that the + // thread is waiting on a control event instead of simply being + // on its way out (this should not happen, but it apparently can). if (log) log->Printf ("Sending control event of type: %d.", signal); - m_private_state_control_wait.WaitForValueEqualTo (true, &timeout_time, &timed_out); - m_private_state_control_wait.SetValue (false, eBroadcastNever); + std::shared_ptr<EventDataReceipt> event_receipt_sp(new EventDataReceipt()); + m_private_state_control_broadcaster.BroadcastEvent(signal, event_receipt_sp); - if (signal == eBroadcastInternalStateControlStop) + // Wait for the event receipt or for the private state thread to exit + bool receipt_received = false; + if (PrivateStateThreadIsValid()) { - if (timed_out) - { - Error error = private_state_thread.Cancel(); - if (log) - log->Printf ("Timed out responding to the control event, cancel got error: \"%s\".", error.AsCString()); - } - else + while (!receipt_received) { - if (log) - log->Printf ("The control event killed the private state thread without having to cancel."); + bool timed_out = false; + TimeValue timeout_time; + timeout_time = TimeValue::Now(); + timeout_time.OffsetWithSeconds(2); + // Check for a receipt for 2 seconds and then check if the private state + // thread is still around. + receipt_received = event_receipt_sp->WaitForEventReceived (&timeout_time, &timed_out); + if (!receipt_received) + { + // Check if the private state thread is still around. If it isn't then we are done waiting + if (!PrivateStateThreadIsValid()) + break; // Private state thread exited or is exiting, we are done + } } + } + if (signal == eBroadcastInternalStateControlStop) + { thread_result_t result = NULL; - private_state_thread.Join(&result); + m_private_state_thread.Join(&result); m_private_state_thread.Reset(); } } else { if (log) - log->Printf ("Private state thread already dead, no need to signal it to stop."); + log->Printf("Private state thread already dead, no need to signal it to stop."); } } @@ -4165,9 +4155,9 @@ void Process::SendAsyncInterrupt () { if (PrivateStateThreadIsValid()) - m_private_state_broadcaster.BroadcastEvent (Process::eBroadcastBitInterrupt, NULL); + m_private_state_broadcaster.BroadcastEvent(Process::eBroadcastBitInterrupt, nullptr); else - BroadcastEvent (Process::eBroadcastBitInterrupt, NULL); + BroadcastEvent(Process::eBroadcastBitInterrupt, nullptr); } void @@ -4179,7 +4169,7 @@ Process::HandlePrivateEvent (EventSP &event_sp) const StateType new_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get()); // First check to see if anybody wants a shot at this event: - if (m_next_event_action_ap.get() != NULL) + if (m_next_event_action_ap) { NextEventAction::EventActionResult action_result = m_next_event_action_ap->PerformAction(event_sp); if (log) @@ -4188,7 +4178,7 @@ Process::HandlePrivateEvent (EventSP &event_sp) switch (action_result) { case NextEventAction::eEventActionSuccess: - SetNextEventAction(NULL); + SetNextEventAction(nullptr); break; case NextEventAction::eEventActionRetry: @@ -4202,10 +4192,10 @@ Process::HandlePrivateEvent (EventSP &event_sp) { // FIXME: should cons up an exited event, and discard this one. SetExitStatus(0, m_next_event_action_ap->GetExitString()); - SetNextEventAction(NULL); + SetNextEventAction(nullptr); return; } - SetNextEventAction(NULL); + SetNextEventAction(nullptr); break; } } @@ -4273,7 +4263,7 @@ Process::HandlePrivateEvent (EventSP &event_sp) // events) and we do need the IO handler to be pushed and popped // correctly. - if (is_hijacked || GetTarget().GetDebugger().IsHandlingEvents() == false) + if (is_hijacked || !GetTarget().GetDebugger().IsHandlingEvents()) PopProcessIOHandler (); } } @@ -4312,8 +4302,9 @@ Process::HaltPrivate() thread_result_t Process::PrivateStateThread (void *arg) { - PrivateStateThreadArgs *real_args = static_cast<PrivateStateThreadArgs *> (arg); - thread_result_t result = real_args->process->RunPrivateStateThread(real_args->is_secondary_thread); + PrivateStateThreadArgs real_args = *static_cast<PrivateStateThreadArgs *> (arg); + free (arg); + thread_result_t result = real_args.process->RunPrivateStateThread(real_args.is_secondary_thread); return result; } @@ -4321,7 +4312,6 @@ thread_result_t Process::RunPrivateStateThread (bool is_secondary_thread) { bool control_only = true; - m_private_state_control_wait.SetValue (false, eBroadcastNever); Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); if (log) @@ -4333,7 +4323,7 @@ Process::RunPrivateStateThread (bool is_secondary_thread) while (!exit_now) { EventSP event_sp; - WaitForEventsPrivate (NULL, event_sp, control_only); + WaitForEventsPrivate(nullptr, event_sp, control_only); if (event_sp->BroadcasterIs(&m_private_state_control_broadcaster)) { if (log) @@ -4356,7 +4346,6 @@ Process::RunPrivateStateThread (bool is_secondary_thread) break; } - m_private_state_control_wait.SetValue (true, eBroadcastAlways); continue; } else if (event_sp->GetType() == eBroadcastBitInterrupt) @@ -4367,7 +4356,7 @@ Process::RunPrivateStateThread (bool is_secondary_thread) log->Printf ("Process::%s (arg = %p, pid = %" PRIu64 ") woke up with an interrupt while attaching - forwarding interrupt.", __FUNCTION__, static_cast<void*>(this), GetID()); - BroadcastEvent (eBroadcastBitInterrupt, NULL); + BroadcastEvent(eBroadcastBitInterrupt, nullptr); } else if(StateIsRunningState(m_last_broadcast_state)) { @@ -4452,8 +4441,6 @@ Process::RunPrivateStateThread (bool is_secondary_thread) // try to change it on the way out. if (!is_secondary_thread) m_public_run_lock.SetStopped(); - m_private_state_control_wait.SetValue (true, eBroadcastAlways); - m_private_state_thread.Reset(); return NULL; } @@ -4610,7 +4597,7 @@ Process::ProcessEventData::DoOnRemoval (Event *event_ptr) this_thread_wants_to_stop = stop_info_sp->ShouldStop(event_ptr); } - if (still_should_stop == false) + if (!still_should_stop) still_should_stop = this_thread_wants_to_stop; } } @@ -4660,7 +4647,7 @@ Process::ProcessEventData::GetEventDataFromEvent (const Event *event_ptr) if (event_data && event_data->GetFlavor() == ProcessEventData::GetFlavorString()) return static_cast <const ProcessEventData *> (event_ptr->GetData()); } - return NULL; + return nullptr; } ProcessSP @@ -4677,7 +4664,7 @@ StateType Process::ProcessEventData::GetStateFromEvent (const Event *event_ptr) { const ProcessEventData *data = GetEventDataFromEvent (event_ptr); - if (data == NULL) + if (data == nullptr) return eStateInvalid; else return data->GetState(); @@ -4687,7 +4674,7 @@ bool Process::ProcessEventData::GetRestartedFromEvent (const Event *event_ptr) { const ProcessEventData *data = GetEventDataFromEvent (event_ptr); - if (data == NULL) + if (data == nullptr) return false; else return data->GetRestarted(); @@ -4697,7 +4684,7 @@ void Process::ProcessEventData::SetRestartedInEvent (Event *event_ptr, bool new_value) { ProcessEventData *data = const_cast<ProcessEventData *>(GetEventDataFromEvent (event_ptr)); - if (data != NULL) + if (data != nullptr) data->SetRestarted(new_value); } @@ -4705,7 +4692,7 @@ size_t Process::ProcessEventData::GetNumRestartedReasons(const Event *event_ptr) { ProcessEventData *data = const_cast<ProcessEventData *>(GetEventDataFromEvent (event_ptr)); - if (data != NULL) + if (data != nullptr) return data->GetNumRestartedReasons(); else return 0; @@ -4715,17 +4702,17 @@ const char * Process::ProcessEventData::GetRestartedReasonAtIndex(const Event *event_ptr, size_t idx) { ProcessEventData *data = const_cast<ProcessEventData *>(GetEventDataFromEvent (event_ptr)); - if (data != NULL) + if (data != nullptr) return data->GetRestartedReasonAtIndex(idx); else - return NULL; + return nullptr; } void Process::ProcessEventData::AddRestartedReason (Event *event_ptr, const char *reason) { ProcessEventData *data = const_cast<ProcessEventData *>(GetEventDataFromEvent (event_ptr)); - if (data != NULL) + if (data != nullptr) data->AddRestartedReason(reason); } @@ -4733,7 +4720,7 @@ bool Process::ProcessEventData::GetInterruptedFromEvent (const Event *event_ptr) { const ProcessEventData *data = GetEventDataFromEvent (event_ptr); - if (data == NULL) + if (data == nullptr) return false; else return data->GetInterrupted (); @@ -4743,7 +4730,7 @@ void Process::ProcessEventData::SetInterruptedInEvent (Event *event_ptr, bool new_value) { ProcessEventData *data = const_cast<ProcessEventData *>(GetEventDataFromEvent (event_ptr)); - if (data != NULL) + if (data != nullptr) data->SetInterrupted(new_value); } @@ -4770,8 +4757,8 @@ Process::CalculateExecutionContext (ExecutionContext &exe_ctx) { exe_ctx.SetTargetPtr (&GetTarget()); exe_ctx.SetProcessPtr (this); - exe_ctx.SetThreadPtr(NULL); - exe_ctx.SetFramePtr (NULL); + exe_ctx.SetThreadPtr(nullptr); + exe_ctx.SetFramePtr(nullptr); } //uint32_t @@ -4791,11 +4778,11 @@ Process::CalculateExecutionContext (ExecutionContext &exe_ctx) //{ // return Host::GetArchSpecForExistingProcess (process_name); //} -// + void Process::AppendSTDOUT (const char * s, size_t len) { - Mutex::Locker locker (m_stdio_communication_mutex); + std::lock_guard<std::recursive_mutex> guard(m_stdio_communication_mutex); m_stdout_data.append (s, len); BroadcastEventIfUnique (eBroadcastBitSTDOUT, new ProcessEventData (shared_from_this(), GetState())); } @@ -4803,7 +4790,7 @@ Process::AppendSTDOUT (const char * s, size_t len) void Process::AppendSTDERR (const char * s, size_t len) { - Mutex::Locker locker (m_stdio_communication_mutex); + std::lock_guard<std::recursive_mutex> guard(m_stdio_communication_mutex); m_stderr_data.append (s, len); BroadcastEventIfUnique (eBroadcastBitSTDERR, new ProcessEventData (shared_from_this(), GetState())); } @@ -4811,7 +4798,7 @@ Process::AppendSTDERR (const char * s, size_t len) void Process::BroadcastAsyncProfileData(const std::string &one_profile_data) { - Mutex::Locker locker (m_profile_data_comm_mutex); + std::lock_guard<std::recursive_mutex> guard(m_profile_data_comm_mutex); m_profile_data.push_back(one_profile_data); BroadcastEventIfUnique (eBroadcastBitProfileData, new ProcessEventData (shared_from_this(), GetState())); } @@ -4819,7 +4806,7 @@ Process::BroadcastAsyncProfileData(const std::string &one_profile_data) size_t Process::GetAsyncProfileData (char *buf, size_t buf_size, Error &error) { - Mutex::Locker locker(m_profile_data_comm_mutex); + std::lock_guard<std::recursive_mutex> guard(m_profile_data_comm_mutex); if (m_profile_data.empty()) return 0; @@ -4854,7 +4841,7 @@ Process::GetAsyncProfileData (char *buf, size_t buf_size, Error &error) size_t Process::GetSTDOUT (char *buf, size_t buf_size, Error &error) { - Mutex::Locker locker(m_stdio_communication_mutex); + std::lock_guard<std::recursive_mutex> guard(m_stdio_communication_mutex); size_t bytes_available = m_stdout_data.size(); if (bytes_available > 0) { @@ -4881,7 +4868,7 @@ Process::GetSTDOUT (char *buf, size_t buf_size, Error &error) size_t Process::GetSTDERR (char *buf, size_t buf_size, Error &error) { - Mutex::Locker locker(m_stdio_communication_mutex); + std::lock_guard<std::recursive_mutex> gaurd(m_stdio_communication_mutex); size_t bytes_available = m_stderr_data.size(); if (bytes_available > 0) { @@ -4952,6 +4939,7 @@ public: // FD_ZERO, FD_SET are not supported on windows #ifndef _WIN32 const int pipe_read_fd = m_pipe.GetReadFileDescriptor(); + m_is_running = true; while (!GetIsDone()) { fd_set read_fdset; @@ -4959,7 +4947,8 @@ public: FD_SET (read_fd, &read_fdset); FD_SET (pipe_read_fd, &read_fdset); const int nfds = std::max<int>(read_fd, pipe_read_fd) + 1; - int num_set_fds = select (nfds, &read_fdset, NULL, NULL, NULL); + int num_set_fds = select(nfds, &read_fdset, nullptr, nullptr, nullptr); + if (num_set_fds < 0) { const int select_errno = errno; @@ -5003,6 +4992,7 @@ public: } } } + m_is_running = false; #endif terminal_state.Restore(); } @@ -5010,9 +5000,24 @@ public: void Cancel () override { - char ch = 'q'; // Send 'q' for quit - size_t bytes_written = 0; - m_pipe.Write(&ch, 1, bytes_written); + SetIsDone(true); + // Only write to our pipe to cancel if we are in IOHandlerProcessSTDIO::Run(). + // We can end up with a python command that is being run from the command + // interpreter: + // + // (lldb) step_process_thousands_of_times + // + // In this case the command interpreter will be in the middle of handling + // the command and if the process pushes and pops the IOHandler thousands + // of times, we can end up writing to m_pipe without ever consuming the + // bytes from the pipe in IOHandlerProcessSTDIO::Run() and end up + // deadlocking when the pipe gets fed up and blocks until data is consumed. + if (m_is_running) + { + char ch = 'q'; // Send 'q' for quit + size_t bytes_written = 0; + m_pipe.Write(&ch, 1, bytes_written); + } } bool @@ -5059,6 +5064,7 @@ protected: File m_read_file; // Read from this file (usually actual STDIN for LLDB File m_write_file; // Write to this file (usually the master pty for getting io to debuggee) Pipe m_pipe; + std::atomic<bool> m_is_running; }; void @@ -5068,7 +5074,7 @@ Process::SetSTDIOFileDescriptor (int fd) std::unique_ptr<ConnectionFileDescriptor> conn_ap (new ConnectionFileDescriptor (fd, true)); - if (conn_ap.get()) + if (conn_ap) { m_stdio_communication.SetConnection (conn_ap.release()); if (m_stdio_communication.IsConnected()) @@ -5078,7 +5084,7 @@ Process::SetSTDIOFileDescriptor (int fd) // Now read thread is set up, set up input reader. - if (!m_process_input_reader.get()) + if (!m_process_input_reader) m_process_input_reader.reset (new IOHandlerProcessSTDIO (this, fd)); } } @@ -5180,41 +5186,41 @@ namespace } // anonymous namespace ExpressionResults -Process::RunThreadPlan (ExecutionContext &exe_ctx, - lldb::ThreadPlanSP &thread_plan_sp, - const EvaluateExpressionOptions &options, - Stream &errors) +Process::RunThreadPlan(ExecutionContext &exe_ctx, lldb::ThreadPlanSP &thread_plan_sp, + const EvaluateExpressionOptions &options, DiagnosticManager &diagnostic_manager) { ExpressionResults return_value = eExpressionSetupError; + + std::lock_guard<std::mutex> run_thread_plan_locker(m_run_thread_plan_lock); - if (thread_plan_sp.get() == NULL) + if (!thread_plan_sp) { - errors.Printf("RunThreadPlan called with empty thread plan."); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "RunThreadPlan called with empty thread plan."); return eExpressionSetupError; } - if (!thread_plan_sp->ValidatePlan(NULL)) + if (!thread_plan_sp->ValidatePlan(nullptr)) { - errors.Printf ("RunThreadPlan called with an invalid thread plan."); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "RunThreadPlan called with an invalid thread plan."); return eExpressionSetupError; } if (exe_ctx.GetProcessPtr() != this) { - errors.Printf("RunThreadPlan called on wrong process."); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "RunThreadPlan called on wrong process."); return eExpressionSetupError; } Thread *thread = exe_ctx.GetThreadPtr(); - if (thread == NULL) + if (thread == nullptr) { - errors.Printf("RunThreadPlan called with invalid thread."); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "RunThreadPlan called with invalid thread."); return eExpressionSetupError; } // We need to change some of the thread plan attributes for the thread plan runner. This will restore them // when we are done: - + RestorePlanState thread_plan_restorer(thread_plan_sp); // We rely on the thread plan we are running returning "PlanCompleted" if when it successfully completes. @@ -5231,7 +5237,8 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, if (m_private_state.GetValue() != eStateStopped) { - errors.Printf ("RunThreadPlan called while the private state was not stopped."); + diagnostic_manager.PutCString(eDiagnosticSeverityError, + "RunThreadPlan called while the private state was not stopped."); return eExpressionSetupError; } @@ -5240,11 +5247,12 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, StackFrameSP selected_frame_sp = thread->GetSelectedFrame(); if (!selected_frame_sp) { - thread->SetSelectedFrame(0); + thread->SetSelectedFrame(nullptr); selected_frame_sp = thread->GetSelectedFrame(); if (!selected_frame_sp) { - errors.Printf("RunThreadPlan called without a selected frame on thread %d", thread_idx_id); + diagnostic_manager.Printf(eDiagnosticSeverityError, + "RunThreadPlan called without a selected frame on thread %d", thread_idx_id); return eExpressionSetupError; } } @@ -5313,7 +5321,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, return eExpressionStoppedForDebug; } - Listener listener("lldb.process.listener.run-thread-plan"); + ListenerSP listener_sp(Listener::MakeListener("lldb.process.listener.run-thread-plan")); lldb::EventSP event_to_broadcast_sp; @@ -5324,7 +5332,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, // If the event needs to propagate beyond the hijacker (e.g., the process exits during execution), then the event // is put into event_to_broadcast_sp for rebroadcasting. - ProcessEventHijacker run_thread_plan_hijacker (*this, &listener); + ProcessEventHijacker run_thread_plan_hijacker (*this, listener_sp); if (log) { @@ -5340,7 +5348,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, lldb::EventSP event_sp; lldb::StateType stop_state = lldb::eStateInvalid; - TimeValue* timeout_ptr = NULL; + TimeValue* timeout_ptr = nullptr; TimeValue real_timeout; bool before_first_timeout = true; // This is set to false the first time that we have to halt the target. @@ -5386,7 +5394,9 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, { if (timeout_usec < option_one_thread_timeout) { - errors.Printf("RunThreadPlan called without one thread timeout greater than total timeout"); + diagnostic_manager.PutCString( + eDiagnosticSeverityError, + "RunThreadPlan called without one thread timeout greater than total timeout"); return eExpressionSetupError; } computed_one_thread_timeout = option_one_thread_timeout; @@ -5414,10 +5424,11 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, // Are there cases where we might want to run the remaining events here, and then try to // call the function? That's probably being too tricky for our own good. - Event *other_events = listener.PeekAtNextEvent(); - if (other_events != NULL) + Event *other_events = listener_sp->PeekAtNextEvent(); + if (other_events != nullptr) { - errors.Printf("Calling RunThreadPlan with pending events on the queue."); + diagnostic_manager.PutCString(eDiagnosticSeverityError, + "RunThreadPlan called with pending events on the queue."); return eExpressionSetupError; } @@ -5441,7 +5452,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, TimeValue one_thread_timeout; TimeValue final_timeout; - while (1) + while (true) { // We usually want to resume the process if we get to the top of the loop. // The only exception is if we get two running events with no intervening @@ -5459,12 +5470,12 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, if (do_resume) { num_resumes++; - Error resume_error = PrivateResume (); + Error resume_error = PrivateResume(); if (!resume_error.Success()) { - errors.Printf("Error resuming inferior the %d time: \"%s\".\n", - num_resumes, - resume_error.AsCString()); + diagnostic_manager.Printf(eDiagnosticSeverityError, + "couldn't resume inferior the %d time: \"%s\".", num_resumes, + resume_error.AsCString()); return_value = eExpressionSetupError; break; } @@ -5473,14 +5484,15 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, TimeValue resume_timeout = TimeValue::Now(); resume_timeout.OffsetWithMicroSeconds(500000); - got_event = listener.WaitForEvent(&resume_timeout, event_sp); + got_event = listener_sp->WaitForEvent(&resume_timeout, event_sp); if (!got_event) { if (log) - log->Printf ("Process::RunThreadPlan(): didn't get any event after resume %d, exiting.", - num_resumes); + log->Printf("Process::RunThreadPlan(): didn't get any event after resume %" PRIu32 ", exiting.", + num_resumes); - errors.Printf("Didn't get any event after resume %d, exiting.", num_resumes); + diagnostic_manager.Printf(eDiagnosticSeverityError, + "didn't get any event after resume %" PRIu32 ", exiting.", num_resumes); return_value = eExpressionSetupError; break; } @@ -5513,8 +5525,9 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, Halt(clear_thread_plans, use_run_lock); } - errors.Printf("Didn't get running event after initial resume, got %s instead.", - StateAsCString(stop_state)); + diagnostic_manager.Printf(eDiagnosticSeverityError, + "didn't get running event after initial resume, got %s instead.", + StateAsCString(stop_state)); return_value = eExpressionSetupError; break; } @@ -5544,7 +5557,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, else { if (timeout_usec == 0) - timeout_ptr = NULL; + timeout_ptr = nullptr; else { final_timeout = TimeValue::Now(); @@ -5556,7 +5569,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, else { if (timeout_usec == 0) - timeout_ptr = NULL; + timeout_ptr = nullptr; else { final_timeout = TimeValue::Now(); @@ -5595,11 +5608,11 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, } else #endif - got_event = listener.WaitForEvent (timeout_ptr, event_sp); + got_event = listener_sp->WaitForEvent (timeout_ptr, event_sp); if (got_event) { - if (event_sp.get()) + if (event_sp) { bool keep_going = false; if (event_sp->GetType() == eBroadcastBitInterrupt) @@ -5608,9 +5621,10 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, const bool use_run_lock = false; Halt(clear_thread_plans, use_run_lock); return_value = eExpressionInterrupted; - errors.Printf ("Execution halted by user interrupt."); + diagnostic_manager.PutCString(eDiagnosticSeverityRemark, "execution halted by user interrupt."); if (log) - log->Printf ("Process::RunThreadPlan(): Got interrupted by eBroadcastBitInterrupted, exiting."); + log->Printf( + "Process::RunThreadPlan(): Got interrupted by eBroadcastBitInterrupted, exiting."); break; } else @@ -5713,7 +5727,8 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, if (stop_state == eStateExited) event_to_broadcast_sp = event_sp; - errors.Printf ("Execution stopped with unexpected state.\n"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, + "execution stopped with unexpected state."); return_value = eExpressionInterrupted; break; } @@ -5795,7 +5810,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, real_timeout = TimeValue::Now(); real_timeout.OffsetWithMicroSeconds(500000); - got_event = listener.WaitForEvent(&real_timeout, event_sp); + got_event = listener_sp->WaitForEvent(&real_timeout, event_sp); if (got_event) { @@ -5943,7 +5958,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, StreamString ts; - const char *event_explanation = NULL; + const char *event_explanation = nullptr; do { @@ -6091,7 +6106,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, if (GetThreadList().SetSelectedThreadByIndexID (selected_tid) && selected_stack_id.IsValid()) { // We were able to restore the selected thread, now restore the frame: - Mutex::Locker lock(GetThreadList().GetMutex()); + std::lock_guard<std::recursive_mutex> guard(GetThreadList().GetMutex()); StackFrameSP old_frame_sp = GetThreadList().GetSelectedThread()->GetFrameWithStackID(selected_stack_id); if (old_frame_sp) GetThreadList().GetSelectedThread()->SetSelectedFrame(old_frame_sp.get()); @@ -6196,7 +6211,7 @@ Process::GetThreadStatus (Stream &strm, std::vector<lldb::tid_t> thread_id_array; //Scope for thread list locker; { - Mutex::Locker locker (GetThreadList().GetMutex()); + std::lock_guard<std::recursive_mutex> guard(GetThreadList().GetMutex()); ThreadList &curr_thread_list = GetThreadList(); num_threads = curr_thread_list.GetSize(); uint32_t idx; @@ -6213,7 +6228,7 @@ Process::GetThreadStatus (Stream &strm, if (only_threads_with_stop_reason) { StopInfoSP stop_info_sp = thread_sp->GetStopInfo(); - if (stop_info_sp.get() == NULL || !stop_info_sp->IsValid()) + if (!stop_info_sp || !stop_info_sp->IsValid()) continue; } thread_sp->GetStatus (strm, @@ -6259,7 +6274,7 @@ 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) + if (result) result = this_result; } return result; @@ -6312,7 +6327,7 @@ Process::DidExec () m_instrumentation_runtimes.clear(); m_thread_list.DiscardThreadPlans(); m_memory_cache.Clear(true); - m_stop_info_override_callback = NULL; + m_stop_info_override_callback = nullptr; DoDidExec(); CompleteAttach (); // Flush the process (threads and all stack frames) after running CompleteAttach() @@ -6389,14 +6404,17 @@ Process::ModulesDidLoad (ModuleList &module_list) for (const auto &pair: language_runtimes) { // We must check language_runtime_sp to make sure it is not - // NULL as we might cache the fact that we didn't have a + // nullptr as we might cache the fact that we didn't have a // language runtime for a language. LanguageRuntimeSP language_runtime_sp = pair.second; if (language_runtime_sp) language_runtime_sp->ModulesDidLoad(module_list); } - LoadOperatingSystemPlugin(false); + // If we don't have an operating system plug-in, try to load one since + // loading shared libraries might cause a new one to try and load + if (!m_os_ap) + LoadOperatingSystemPlugin(false); } void @@ -6405,10 +6423,10 @@ Process::PrintWarning (uint64_t warning_type, const void *repeat_key, const char bool print_warning = true; StreamSP stream_sp = GetTarget().GetDebugger().GetAsyncOutputStream(); - if (stream_sp.get() == nullptr) + if (!stream_sp) return; if (warning_type == eWarningsOptimization - && GetWarningsOptimization() == false) + && !GetWarningsOptimization()) { return; } @@ -6446,16 +6464,28 @@ Process::PrintWarning (uint64_t warning_type, const void *repeat_key, const char void Process::PrintWarningOptimization (const SymbolContext &sc) { - if (GetWarningsOptimization() == true - && sc.module_sp.get() - && sc.module_sp->GetFileSpec().GetFilename().IsEmpty() == false + if (GetWarningsOptimization() + && sc.module_sp + && !sc.module_sp->GetFileSpec().GetFilename().IsEmpty() && sc.function - && sc.function->GetIsOptimized() == true) + && sc.function->GetIsOptimized()) { PrintWarning (Process::Warnings::eWarningsOptimization, sc.module_sp.get(), "%s was compiled with optimization - stepping may behave oddly; variables may not be available.\n", sc.module_sp->GetFileSpec().GetFilename().GetCString()); } } +bool +Process::GetProcessInfo(ProcessInstanceInfo &info) +{ + info.Clear(); + + PlatformSP platform_sp = GetTarget().GetPlatform(); + if (! platform_sp) + return false; + + return platform_sp->GetProcessInfo(GetID(), info); +} + ThreadCollectionSP Process::GetHistoryThreads(lldb::addr_t addr) { @@ -6463,7 +6493,7 @@ Process::GetHistoryThreads(lldb::addr_t addr) const MemoryHistorySP &memory_history = MemoryHistory::FindPlugin(shared_from_this()); - if (! memory_history.get()) { + if (!memory_history) { return threads; } @@ -6521,13 +6551,13 @@ Process::AdvanceAddressToNextBranchInstruction (Address default_stop_addr, Addre { Target &target = GetTarget(); DisassemblerSP disassembler_sp; - InstructionList *insn_list = NULL; + InstructionList *insn_list = nullptr; Address retval = default_stop_addr; - if (target.GetUseFastStepping() == false) + if (!target.GetUseFastStepping()) return retval; - if (default_stop_addr.IsValid() == false) + if (!default_stop_addr.IsValid()) return retval; ExecutionContext exe_ctx (this); @@ -6540,10 +6570,10 @@ Process::AdvanceAddressToNextBranchInstruction (Address default_stop_addr, Addre exe_ctx, range_bounds, prefer_file_cache); - if (disassembler_sp.get()) + if (disassembler_sp) insn_list = &disassembler_sp->GetInstructionList(); - if (insn_list == NULL) + if (insn_list == nullptr) { return retval; } @@ -6569,11 +6599,38 @@ Process::AdvanceAddressToNextBranchInstruction (Address default_stop_addr, Addre } } - if (disassembler_sp.get()) + return retval; +} + +Error +Process::GetMemoryRegions (std::vector<lldb::MemoryRegionInfoSP>& region_list) +{ + + Error error; + + lldb::addr_t range_base = 0; + lldb::addr_t range_end = 0; + + region_list.clear(); + do { - // FIXME: The DisassemblerLLVMC has a reference cycle and won't go away if it has any active instructions. - disassembler_sp->GetInstructionList().Clear(); - } + lldb::MemoryRegionInfoSP region_info( new lldb_private::MemoryRegionInfo() ); + error = GetMemoryRegionInfo (range_end, *region_info); + // GetMemoryRegionInfo should only return an error if it is unimplemented. + if (error.Fail()) + { + region_list.clear(); + break; + } + + range_base = region_info->GetRange().GetRangeBase(); + range_end = region_info->GetRange().GetRangeEnd(); + if( region_info->GetMapped() == MemoryRegionInfo::eYes ) + { + region_list.push_back(region_info); + } + } while (range_end != LLDB_INVALID_ADDRESS); + + return error; - return retval; } |