diff options
Diffstat (limited to 'source/Target/Process.cpp')
| -rw-r--r-- | source/Target/Process.cpp | 1033 | 
1 files changed, 490 insertions, 543 deletions
diff --git a/source/Target/Process.cpp b/source/Target/Process.cpp index 3abae4fce5b1..6bc9f2b0c9d8 100644 --- a/source/Target/Process.cpp +++ b/source/Target/Process.cpp @@ -7,6 +7,10 @@  //  //===----------------------------------------------------------------------===// +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes  #include "lldb/Target/Process.h"  #include "lldb/Breakpoint/StoppointCallbackContext.h"  #include "lldb/Breakpoint/BreakpointLocation.h" @@ -18,9 +22,10 @@  #include "lldb/Core/PluginManager.h"  #include "lldb/Core/State.h"  #include "lldb/Core/StreamFile.h" -#include "lldb/Expression/ClangUserExpression.h" +#include "lldb/Expression/UserExpression.h"  #include "lldb/Expression/IRDynamicChecks.h"  #include "lldb/Host/ConnectionFileDescriptor.h" +#include "lldb/Host/FileSystem.h"  #include "lldb/Host/Host.h"  #include "lldb/Host/HostInfo.h"  #include "lldb/Host/Pipe.h" @@ -28,6 +33,7 @@  #include "lldb/Host/ThreadLauncher.h"  #include "lldb/Interpreter/CommandInterpreter.h"  #include "lldb/Interpreter/OptionValueProperties.h" +#include "lldb/Symbol/Function.h"  #include "lldb/Symbol/Symbol.h"  #include "lldb/Target/ABI.h"  #include "lldb/Target/DynamicLoader.h" @@ -56,7 +62,6 @@  using namespace lldb;  using namespace lldb_private; -  // Comment out line below to disable memory caching, overriding the process setting  // target.process.disable-memory-cache  #define ENABLE_MEMORY_CACHING @@ -83,8 +88,8 @@ public:      {      } -    virtual const Property * -    GetPropertyAtIndex (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const +    const Property * +    GetPropertyAtIndex(const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const override      {          // When getting the value for a key from the process options, we will always          // try and grab the setting from the current process if there is one. Else we just @@ -115,6 +120,7 @@ g_properties[] =      { "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  }  }; @@ -126,7 +132,8 @@ enum {      ePropertyPythonOSPluginPath,      ePropertyStopOnSharedLibraryEvents,      ePropertyDetachKeepsStopped, -    ePropertyMemCacheLineSize +    ePropertyMemCacheLineSize, +    ePropertyWarningOptimization  };  ProcessProperties::ProcessProperties (lldb_private::Process *process) : @@ -150,9 +157,7 @@ ProcessProperties::ProcessProperties (lldb_private::Process *process) :      }  } -ProcessProperties::~ProcessProperties() -{ -} +ProcessProperties::~ProcessProperties() = default;  void  ProcessProperties::OptionValueChangedCallback (void *baton, OptionValue *option_value) @@ -206,7 +211,6 @@ ProcessProperties::SetPythonOSPluginPath (const FileSpec &file)      m_collection_sp->SetPropertyAtIndexAsFileSpec(NULL, idx, file);  } -  bool  ProcessProperties::GetIgnoreBreakpointsInExpressions () const  { @@ -263,6 +267,13 @@ ProcessProperties::SetDetachKeepsStopped (bool stop)      m_collection_sp->SetPropertyAtIndexAsBoolean(NULL, 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); +} +  void  ProcessInstanceInfo::Dump (Stream &s, Platform *platform) const  { @@ -306,8 +317,12 @@ ProcessInstanceInfo::Dump (Stream &s, Platform *platform) const          }      } -    if (m_arch.IsValid())                        -        s.Printf ("   arch = %s\n", m_arch.GetTriple().str().c_str()); +    if (m_arch.IsValid()) +    { +        s.Printf ("   arch = "); +        m_arch.DumpTriple(s); +        s.EOL(); +    }      if (m_uid != UINT32_MAX)      { @@ -360,7 +375,10 @@ ProcessInstanceInfo::DumpAsTableRow (Stream &s, Platform *platform, bool show_ar          const char *cstr;          s.Printf ("%-6" PRIu64 " %-6" PRIu64 " ", m_pid, m_parent_pid); -     +        StreamString arch_strm; +        if (m_arch.IsValid()) +            m_arch.DumpTriple(arch_strm); +          if (verbose)          {              cstr = platform->GetUserName (m_uid); @@ -386,13 +404,14 @@ ProcessInstanceInfo::DumpAsTableRow (Stream &s, Platform *platform, bool show_ar                  s.Printf ("%-10s ", cstr);              else                  s.Printf ("%-10u ", m_egid); -            s.Printf ("%-24s ", m_arch.IsValid() ? m_arch.GetTriple().str().c_str() : ""); + +            s.Printf ("%-24s ", arch_strm.GetString().c_str());          }          else          {              s.Printf ("%-10s %-24s ",                        platform->GetUserName (m_euid), -                      m_arch.IsValid() ? m_arch.GetTriple().str().c_str() : ""); +                      arch_strm.GetString().c_str());          }          if (verbose || show_args) @@ -460,7 +479,7 @@ ProcessLaunchCommandOptions::SetOptionValue (uint32_t option_idx, const char *op          case 'n':   // Disable STDIO          {              FileAction action; -            const FileSpec dev_null{"/dev/null", false}; +            const FileSpec dev_null{FileSystem::DEV_NULL, false};              if (action.Open(STDIN_FILENO, dev_null, true, false))                  launch_info.AppendFileAction (action);              if (action.Open(STDOUT_FILENO, dev_null, false, true)) @@ -545,8 +564,6 @@ ProcessLaunchCommandOptions::g_option_table[] =  { 0               , false, NULL,             0,  0,                 NULL, NULL, 0, eArgTypeNone,    NULL }  }; - -  bool  ProcessInstanceInfoMatch::NameMatches (const char *process_name) const  { @@ -626,7 +643,6 @@ ProcessInstanceInfoMatch::MatchAllProcesses () const          return false;      return true; -  }  void @@ -638,7 +654,7 @@ ProcessInstanceInfoMatch::Clear()  }  ProcessSP -Process::FindPlugin (Target &target, const char *plugin_name, Listener &listener, const FileSpec *crash_file_path) +Process::FindPlugin (lldb::TargetSP target_sp, const char *plugin_name, Listener &listener, const FileSpec *crash_file_path)  {      static uint32_t g_process_unique_id = 0; @@ -650,10 +666,10 @@ Process::FindPlugin (Target &target, const char *plugin_name, Listener &listener          create_callback  = PluginManager::GetProcessCreateCallbackForPluginName (const_plugin_name);          if (create_callback)          { -            process_sp = create_callback(target, listener, crash_file_path); +            process_sp = create_callback(target_sp, listener, crash_file_path);              if (process_sp)              { -                if (process_sp->CanDebug(target, true)) +                if (process_sp->CanDebug(target_sp, true))                  {                      process_sp->m_process_unique_id = ++g_process_unique_id;                  } @@ -666,10 +682,10 @@ Process::FindPlugin (Target &target, const char *plugin_name, Listener &listener      {          for (uint32_t idx = 0; (create_callback = PluginManager::GetProcessCreateCallbackAtIndex(idx)) != NULL; ++idx)          { -            process_sp = create_callback(target, listener, crash_file_path); +            process_sp = create_callback(target_sp, listener, crash_file_path);              if (process_sp)              { -                if (process_sp->CanDebug(target, false)) +                if (process_sp->CanDebug(target_sp, false))                  {                      process_sp->m_process_unique_id = ++g_process_unique_id;                      break; @@ -689,21 +705,18 @@ Process::GetStaticBroadcasterClass ()      return class_name;  } -//---------------------------------------------------------------------- -// Process constructor -//---------------------------------------------------------------------- -Process::Process(Target &target, Listener &listener) : -    Process(target, listener, UnixSignals::Create(HostInfo::GetArchitecture())) +Process::Process(lldb::TargetSP target_sp, Listener &listener) : +    Process(target_sp, listener, UnixSignals::Create(HostInfo::GetArchitecture()))  {      // This constructor just delegates to the full Process constructor,      // defaulting to using the Host's UnixSignals.  } -Process::Process(Target &target, Listener &listener, const UnixSignalsSP &unix_signals_sp) : +Process::Process(lldb::TargetSP target_sp, Listener &listener, const UnixSignalsSP &unix_signals_sp) :      ProcessProperties (this),      UserID (LLDB_INVALID_PROCESS_ID), -    Broadcaster (&(target.GetDebugger()), Process::GetStaticBroadcasterClass().AsCString()), -    m_target (target), +    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"), @@ -746,7 +759,6 @@ Process::Process(Target &target, Listener &listener, const UnixSignalsSP &unix_s      m_next_event_action_ap(),      m_public_run_lock (),      m_private_run_lock (), -    m_currently_handling_event(false),      m_stop_info_override_callback (NULL),      m_finalizing (false),      m_finalize_called (false), @@ -755,6 +767,7 @@ Process::Process(Target &target, Listener &listener, const UnixSignalsSP &unix_s      m_last_broadcast_state (eStateInvalid),      m_destroy_in_process (false),      m_can_interpret_function_calls(false), +    m_warnings_issued (),      m_can_jit(eCanJITDontKnow)  {      CheckInWithManager (); @@ -793,11 +806,15 @@ Process::Process(Target &target, Listener &listener, const UnixSignalsSP &unix_s                                                       eBroadcastInternalStateControlResume);      // We need something valid here, even if just the default UnixSignalsSP.      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(); +    uint32_t platform_cache_line_size = target_sp->GetPlatform()->GetDefaultMemoryCacheLineSize(); +    if (! value_sp->OptionWasSet() && platform_cache_line_size != 0) +        value_sp->SetUInt64Value(platform_cache_line_size);  } -//---------------------------------------------------------------------- -// Destructor -//----------------------------------------------------------------------  Process::~Process()  {      Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); @@ -974,7 +991,8 @@ Process::WaitForProcessToStop (const TimeValue *timeout,                                 EventSP *event_sp_ptr,                                 bool wait_always,                                 Listener *hijack_listener, -                               Stream *stream) +                               Stream *stream, +                               bool use_run_lock)  {      // 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 @@ -1001,7 +1019,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) +        if (hijack_listener && use_run_lock)              m_public_run_lock.SetStopped();          return state;      } @@ -1024,7 +1042,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) +            if (hijack_listener && use_run_lock)                  m_public_run_lock.SetStopped();              return state;          case eStateStopped: @@ -1034,7 +1052,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) +                if (hijack_listener && use_run_lock)                      m_public_run_lock.SetStopped();                  return state;              } @@ -1247,14 +1265,10 @@ Process::HandleProcessStateChangedEvent (const EventSP &event_sp,      return true;  } -  StateType -Process::WaitForState -( -    const TimeValue *timeout, -    const StateType *match_states, -    const uint32_t num_match_states -) +Process::WaitForState(const TimeValue *timeout, +                      const StateType *match_states, +                      const uint32_t num_match_states)  {      EventSP event_sp;      uint32_t i; @@ -1294,23 +1308,6 @@ Process::RestoreProcessEvents ()      RestoreBroadcaster();  } -bool -Process::HijackPrivateProcessEvents (Listener *listener) -{ -    if (listener != NULL) -    { -        return m_private_state_broadcaster.HijackBroadcaster(listener, eBroadcastBitStateChanged | eBroadcastBitInterrupt); -    } -    else -        return false; -} - -void -Process::RestorePrivateProcessEvents () -{ -    m_private_state_broadcaster.RestoreBroadcaster(); -} -  StateType  Process::WaitForStateChangedEvents (const TimeValue *timeout, EventSP &event_sp, Listener *hijack_listener)  { @@ -1429,7 +1426,6 @@ Process::GetExitStatus ()      return -1;  } -  const char *  Process::GetExitDescription ()  { @@ -1468,12 +1464,7 @@ Process::SetExitStatus (int status, const char *cstr)      else          m_exit_string.clear(); -    // When we exit, we no longer need to the communication channel -    m_stdio_communication.Disconnect(); -    m_stdio_communication.StopReadThread(); -    m_stdin_forward = false; - -    // And we don't need the input reader anymore as well +    // When we exit, we don't need the input reader anymore      if (m_process_input_reader)      {          m_process_input_reader->SetIsDone(true); @@ -1493,6 +1484,29 @@ Process::SetExitStatus (int status, const char *cstr)      return true;  } +bool +Process::IsAlive () +{ +    switch (m_private_state.GetValue()) +    { +        case eStateInvalid: +        case eStateUnloaded: +        case eStateDetached: +        case eStateExited: +            return false; + +        case eStateConnected: +        case eStateAttaching: +        case eStateLaunching: +        case eStateStopped: +        case eStateRunning: +        case eStateStepping: +        case eStateCrashed: +        case eStateSuspended: +            return true; +    } +} +  // This static callback can be used to watch for local child processes on  // the current host. The child process exits, the process will be  // found in the global target list (we want to be completely sure that the @@ -1534,7 +1548,6 @@ Process::SetProcessExitStatus (void *callback_baton,      return false;  } -  void  Process::UpdateThreadListIfNeeded ()  { @@ -1558,41 +1571,38 @@ Process::UpdateThreadListIfNeeded ()                  // Don't call into the OperatingSystem to update the thread list if we are shutting down, since                  // that may call back into the SBAPI's, requiring the API lock which is already held by whoever is                  // shutting us down, causing a deadlock. -                if (!m_destroy_in_process) +                OperatingSystem *os = GetOperatingSystem (); +                if (os && !m_destroy_in_process)                  { -                    OperatingSystem *os = GetOperatingSystem (); -                    if (os) -                    { -                        // 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) -                            old_thread_list.GetThreadAtIndex(i, false)->ClearBackingThread(); - -                        // Turn off dynamic types to ensure we don't run any expressions. Objective C -                        // can run an expression to determine if a SBValue is a dynamic type or not -                        // and we need to avoid this. OperatingSystem plug-ins can't run expressions -                        // that require running code... - -                        Target &target = GetTarget(); -                        const lldb::DynamicValueType saved_prefer_dynamic = target.GetPreferDynamicValue (); -                        if (saved_prefer_dynamic != lldb::eNoDynamicValues) -                            target.SetPreferDynamicValue(lldb::eNoDynamicValues); - -                        // Now let the OperatingSystem plug-in update the thread list - -                        os->UpdateThreadList (old_thread_list,  // Old list full of threads created by OS plug-in -                                              real_thread_list, // The actual thread list full of threads created by each lldb_private::Process subclass -                                              new_thread_list); // The new thread list that we will show to the user that gets filled in - -                        if (saved_prefer_dynamic != lldb::eNoDynamicValues) -                            target.SetPreferDynamicValue(saved_prefer_dynamic); -                    } -                    else -                    { -                        // No OS plug-in, the new thread list is the same as the real thread list -                        new_thread_list = real_thread_list; -                    } +                    // 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) +                        old_thread_list.GetThreadAtIndex(i, false)->ClearBackingThread(); + +                    // Turn off dynamic types to ensure we don't run any expressions. Objective C +                    // can run an expression to determine if a SBValue is a dynamic type or not +                    // and we need to avoid this. OperatingSystem plug-ins can't run expressions +                    // that require running code... + +                    Target &target = GetTarget(); +                    const lldb::DynamicValueType saved_prefer_dynamic = target.GetPreferDynamicValue (); +                    if (saved_prefer_dynamic != lldb::eNoDynamicValues) +                        target.SetPreferDynamicValue(lldb::eNoDynamicValues); + +                    // Now let the OperatingSystem plug-in update the thread list + +                    os->UpdateThreadList (old_thread_list,  // Old list full of threads created by OS plug-in +                                          real_thread_list, // The actual thread list full of threads created by each lldb_private::Process subclass +                                          new_thread_list); // The new thread list that we will show to the user that gets filled in + +                    if (saved_prefer_dynamic != lldb::eNoDynamicValues) +                        target.SetPreferDynamicValue(saved_prefer_dynamic); +                } +                else +                { +                    // No OS plug-in, the new thread list is the same as the real thread list +                    new_thread_list = real_thread_list;                  }                  m_thread_list_real.Update(real_thread_list); @@ -1648,15 +1658,7 @@ Process::GetNextThreadIndexID (uint64_t thread_id)  bool  Process::HasAssignedIndexIDToThread(uint64_t thread_id)  { -    std::map<uint64_t, uint32_t>::iterator iterator = m_thread_id_to_index_id_map.find(thread_id); -    if (iterator == m_thread_id_to_index_id_map.end()) -    { -        return false; -    } -    else -    { -        return true; -    } +    return (m_thread_id_to_index_id_map.find(thread_id) != m_thread_id_to_index_id_map.end());  }  uint32_t @@ -1866,225 +1868,11 @@ Process::GetImageInfoAddress()      return LLDB_INVALID_ADDRESS;  } -//---------------------------------------------------------------------- -// LoadImage -// -// This function provides a default implementation that works for most -// unix variants. Any Process subclasses that need to do shared library -// loading differently should override LoadImage and UnloadImage and -// do what is needed. -//---------------------------------------------------------------------- -uint32_t -Process::LoadImage (const FileSpec &image_spec, Error &error) -{ -    if (m_finalizing) -    { -        error.SetErrorString("process is tearing itself down"); -        return LLDB_INVALID_IMAGE_TOKEN; -    } - -    char path[PATH_MAX]; -    image_spec.GetPath(path, sizeof(path)); - -    DynamicLoader *loader = GetDynamicLoader(); -    if (loader) -    { -        error = loader->CanLoadImage(); -        if (error.Fail()) -            return LLDB_INVALID_IMAGE_TOKEN; -    } -     -    if (error.Success()) -    { -        ThreadSP thread_sp(GetThreadList ().GetSelectedThread()); -         -        if (thread_sp) -        { -            StackFrameSP frame_sp (thread_sp->GetStackFrameAtIndex (0)); -             -            if (frame_sp) -            { -                ExecutionContext exe_ctx; -                frame_sp->CalculateExecutionContext (exe_ctx); -                EvaluateExpressionOptions expr_options; -                expr_options.SetUnwindOnError(true); -                expr_options.SetIgnoreBreakpoints(true); -                expr_options.SetExecutionPolicy(eExecutionPolicyAlways); -                expr_options.SetResultIsInternal(true); -                 -                StreamString expr; -                expr.Printf(R"( -                               struct __lldb_dlopen_result { void *image_ptr; const char *error_str; } the_result; -                               the_result.image_ptr = dlopen ("%s", 2); -                               if (the_result.image_ptr == (void *) 0x0) -                               { -                                   the_result.error_str = dlerror(); -                               } -                               else -                               { -                                   the_result.error_str = (const char *) 0x0; -                               } -                               the_result; -                              )", -                              path); -                const char *prefix = R"( -                                        extern "C" void* dlopen (const char *path, int mode); -                                        extern "C" const char *dlerror (void); -                                        )"; -                lldb::ValueObjectSP result_valobj_sp; -                Error expr_error; -                ClangUserExpression::Evaluate (exe_ctx, -                                               expr_options, -                                               expr.GetData(), -                                               prefix, -                                               result_valobj_sp, -                                               expr_error); -                if (expr_error.Success()) -                { -                    error = result_valobj_sp->GetError(); -                    if (error.Success()) -                    { -                        Scalar scalar; -                        ValueObjectSP image_ptr_sp = result_valobj_sp->GetChildAtIndex(0, true); -                        if (image_ptr_sp && image_ptr_sp->ResolveValue (scalar)) -                        { -                            addr_t image_ptr = scalar.ULongLong(LLDB_INVALID_ADDRESS); -                            if (image_ptr != 0 && image_ptr != LLDB_INVALID_ADDRESS) -                            { -                                uint32_t image_token = m_image_tokens.size(); -                                m_image_tokens.push_back (image_ptr); -                                return image_token; -                            } -                            else if (image_ptr == 0) -                            { -                                ValueObjectSP error_str_sp = result_valobj_sp->GetChildAtIndex(1, true); -                                if (error_str_sp) -                                { -                                    if (error_str_sp->IsCStringContainer(true)) -                                    { -                                        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", buffer_sp->GetBytes()); -                                        } -                                        else -                                        { -                                            error.Clear(); -                                            error.SetErrorStringWithFormat("dlopen failed for unknown reasons."); -                                        } -                                    } -                                } -                            } -                        } -                    } -                } -                else -                    error = expr_error; -            } -        } -    } -    if (!error.AsCString()) -        error.SetErrorStringWithFormat("unable to load '%s'", path); -    return LLDB_INVALID_IMAGE_TOKEN; -} - -//---------------------------------------------------------------------- -// UnloadImage -// -// This function provides a default implementation that works for most -// unix variants. Any Process subclasses that need to do shared library -// loading differently should override LoadImage and UnloadImage and -// do what is needed. -//---------------------------------------------------------------------- -Error -Process::UnloadImage (uint32_t image_token) -{ -    Error error; - -    if (m_finalizing) -    { -        error.SetErrorString("process is tearing itself down"); -        return error; -    } - -    if (image_token < m_image_tokens.size()) -    { -        const addr_t image_addr = m_image_tokens[image_token]; -        if (image_addr == LLDB_INVALID_ADDRESS) -        { -            error.SetErrorString("image already unloaded"); -        } -        else -        { -            DynamicLoader *loader = GetDynamicLoader(); -            if (loader) -                error = loader->CanLoadImage(); -             -            if (error.Success()) -            { -                ThreadSP thread_sp(GetThreadList ().GetSelectedThread()); -                 -                if (thread_sp) -                { -                    StackFrameSP frame_sp (thread_sp->GetStackFrameAtIndex (0)); -                     -                    if (frame_sp) -                    { -                        ExecutionContext exe_ctx; -                        frame_sp->CalculateExecutionContext (exe_ctx); -                        EvaluateExpressionOptions expr_options; -                        expr_options.SetUnwindOnError(true); -                        expr_options.SetIgnoreBreakpoints(true); -                        expr_options.SetExecutionPolicy(eExecutionPolicyAlways); -                        StreamString expr; -                        expr.Printf("dlclose ((void *)0x%" PRIx64 ")", image_addr); -                        const char *prefix = "extern \"C\" int dlclose(void* handle);\n"; -                        lldb::ValueObjectSP result_valobj_sp; -                        Error expr_error; -                        ClangUserExpression::Evaluate (exe_ctx, -                                                       expr_options, -                                                       expr.GetData(), -                                                       prefix, -                                                       result_valobj_sp, -                                                       expr_error); -                        if (result_valobj_sp->GetError().Success()) -                        { -                            Scalar scalar; -                            if (result_valobj_sp->ResolveValue (scalar)) -                            { -                                if (scalar.UInt(1)) -                                { -                                    error.SetErrorStringWithFormat("expression failed: \"%s\"", expr.GetData()); -                                } -                                else -                                { -                                    m_image_tokens[image_token] = LLDB_INVALID_ADDRESS; -                                } -                            } -                        } -                        else -                        { -                            error = result_valobj_sp->GetError(); -                        } -                    } -                } -            } -        } -    } -    else -    { -        error.SetErrorString("invalid image token"); -    } -    return error; -} -  const lldb::ABISP &  Process::GetABI()  {      if (!m_abi_sp) -        m_abi_sp = ABI::FindPlugin(m_target.GetArchitecture()); +        m_abi_sp = ABI::FindPlugin(GetTarget().GetArchitecture());      return m_abi_sp;  } @@ -2167,7 +1955,6 @@ Process::GetBreakpointSiteList() const      return m_breakpoint_site_list;  } -  void  Process::DisableAllBreakpointSites ()  { @@ -2264,22 +2051,22 @@ Process::CreateBreakpointSite (const BreakpointLocationSP &owner, bool use_hardw              load_addr = ResolveIndirectFunction (&symbol_address, error);              if (!error.Success() && show_error)              { -                m_target.GetDebugger().GetErrorFile()->Printf ("warning: failed to resolve indirect function at 0x%" PRIx64 " for breakpoint %i.%i: %s\n", -                                                               symbol->GetLoadAddress(&m_target), -                                                               owner->GetBreakpoint().GetID(), -                                                               owner->GetID(), -                                                               error.AsCString() ? error.AsCString() : "unknown error"); +                GetTarget().GetDebugger().GetErrorFile()->Printf ("warning: failed to resolve indirect function at 0x%" PRIx64 " for breakpoint %i.%i: %s\n", +                                                                   symbol->GetLoadAddress(&GetTarget()), +                                                                   owner->GetBreakpoint().GetID(), +                                                                   owner->GetID(), +                                                                   error.AsCString() ? error.AsCString() : "unknown error");                  return LLDB_INVALID_BREAK_ID;              }              Address resolved_address(load_addr); -            load_addr = resolved_address.GetOpcodeLoadAddress (&m_target); +            load_addr = resolved_address.GetOpcodeLoadAddress (&GetTarget());              owner->SetIsIndirect(true);          }          else -            load_addr = owner->GetAddress().GetOpcodeLoadAddress (&m_target); +            load_addr = owner->GetAddress().GetOpcodeLoadAddress (&GetTarget());      }      else -        load_addr = owner->GetAddress().GetOpcodeLoadAddress (&m_target); +        load_addr = owner->GetAddress().GetOpcodeLoadAddress (&GetTarget());      if (load_addr != LLDB_INVALID_ADDRESS)      { @@ -2312,11 +2099,11 @@ Process::CreateBreakpointSite (const BreakpointLocationSP &owner, bool use_hardw                      if (show_error)                      {                          // Report error for setting breakpoint... -                        m_target.GetDebugger().GetErrorFile()->Printf ("warning: failed to set breakpoint site at 0x%" PRIx64 " for breakpoint %i.%i: %s\n", -                                                                       load_addr, -                                                                       owner->GetBreakpoint().GetID(), -                                                                       owner->GetID(), -                                                                       error.AsCString() ? error.AsCString() : "unknown error"); +                        GetTarget().GetDebugger().GetErrorFile()->Printf ("warning: failed to set breakpoint site at 0x%" PRIx64 " for breakpoint %i.%i: %s\n", +                                                                           load_addr, +                                                                           owner->GetBreakpoint().GetID(), +                                                                           owner->GetID(), +                                                                           error.AsCString() ? error.AsCString() : "unknown error");                      }                  }              } @@ -2324,7 +2111,6 @@ Process::CreateBreakpointSite (const BreakpointLocationSP &owner, bool use_hardw      }      // We failed to enable the breakpoint      return LLDB_INVALID_BREAK_ID; -  }  void @@ -2340,7 +2126,6 @@ Process::RemoveOwnerFromBreakpointSite (lldb::user_id_t owner_id, lldb::user_id_      }  } -  size_t  Process::RemoveBreakpointOpcodesFromBuffer (addr_t bp_addr, size_t size, uint8_t *buf) const  { @@ -2369,14 +2154,12 @@ Process::RemoveBreakpointOpcodesFromBuffer (addr_t bp_addr, size_t size, uint8_t      return bytes_removed;  } - -  size_t  Process::GetSoftwareBreakpointTrapOpcode (BreakpointSite* bp_site)  { -    PlatformSP platform_sp (m_target.GetPlatform()); +    PlatformSP platform_sp (GetTarget().GetPlatform());      if (platform_sp) -        return platform_sp->GetSoftwareBreakpointTrapOpcode (m_target, bp_site); +        return platform_sp->GetSoftwareBreakpointTrapOpcode (GetTarget(), bp_site);      return 0;  } @@ -2550,7 +2333,6 @@ Process::DisableSoftwareBreakpoint (BreakpointSite *bp_site)                       (uint64_t)bp_addr,                       error.AsCString());      return error; -  }  // Uncomment to verify memory caching works after making changes to caching code @@ -2622,7 +2404,6 @@ Process::ReadCStringFromMemory (addr_t addr, std::string &out_str, Error &error)      return out_str.size();  } -  size_t  Process::ReadStringFromMemory (addr_t addr, char *dst, size_t max_bytes, Error &error,                                  size_t type_width) @@ -2772,7 +2553,6 @@ Process::ReadPointerFromMemory (lldb::addr_t vm_addr, Error &error)      return LLDB_INVALID_ADDRESS;  } -  bool  Process::WritePointerToMemory (lldb::addr_t vm_addr,                                  lldb::addr_t ptr_value,  @@ -2843,6 +2623,7 @@ Process::WriteMemory (addr_t addr, const void *buf, size_t size, Error &error)                      size_t intersect_size;                      size_t opcode_offset;                      const bool intersects = bp->IntersectsRange(addr, size, &intersect_addr, &intersect_size, &opcode_offset); +                    UNUSED_IF_ASSERT_DISABLED(intersects);                      assert(intersects);                      assert(addr <= intersect_addr && intersect_addr < addr + size);                      assert(addr < intersect_addr + intersect_size && intersect_addr + intersect_size <= addr + size); @@ -2975,6 +2756,18 @@ Process::AllocateMemory(size_t size, uint32_t permissions, Error &error)  #endif  } +addr_t +Process::CallocateMemory(size_t size, uint32_t permissions, Error &error) +{ +    addr_t return_addr = AllocateMemory(size, permissions, error); +    if (error.Success()) +    { +        std::string buffer(size, 0); +        WriteMemory(return_addr, buffer.c_str(), size, error); +    } +    return return_addr; +} +  bool  Process::CanJIT ()  { @@ -3042,12 +2835,16 @@ Process::DeallocateMemory (addr_t ptr)      return error;  } -  ModuleSP  Process::ReadModuleFromMemory (const FileSpec& file_spec,                                  lldb::addr_t header_addr,                                 size_t size_to_read)  { +    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); +    if (log) +    { +        log->Printf ("Process::ReadModuleFromMemory reading %s binary from memory", file_spec.GetPath().c_str()); +    }      ModuleSP module_sp (new Module (file_spec, ArchSpec()));      if (module_sp)      { @@ -3148,7 +2945,7 @@ Process::Launch (ProcessLaunchInfo &launch_info)      m_process_input_reader.reset();      m_stop_info_override_callback = NULL; -    Module *exe_module = m_target.GetExecutableModulePointer(); +    Module *exe_module = GetTarget().GetExecutableModulePointer();      if (exe_module)      {          char local_exec_file_path[PATH_MAX]; @@ -3214,7 +3011,6 @@ Process::Launch (ProcessLaunchInfo &launch_info)                      }                      else if (state == eStateStopped || state == eStateCrashed)                      { -                          DidLaunch ();                          DynamicLoader *dyld = GetDynamicLoader (); @@ -3264,7 +3060,6 @@ Process::Launch (ProcessLaunchInfo &launch_info)      return error;  } -  Error  Process::LoadCore ()  { @@ -3495,7 +3290,7 @@ Process::Attach (ProcessAttachInfo &attach_info)              else              {                  ProcessInstanceInfoList process_infos; -                PlatformSP platform_sp (m_target.GetPlatform ()); +                PlatformSP platform_sp (GetTarget().GetPlatform ());                  if (platform_sp)                  { @@ -3597,7 +3392,7 @@ Process::CompleteAttach ()      if (process_arch.IsValid())      { -        m_target.SetArchitecture(process_arch); +        GetTarget().SetArchitecture(process_arch);          if (log)          {              const char *triple_str = process_arch.GetTriple().getTriple().c_str (); @@ -3609,19 +3404,19 @@ 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 (m_target.GetPlatform ()); +    PlatformSP platform_sp (GetTarget().GetPlatform ());      assert (platform_sp.get());      if (platform_sp)      { -        const ArchSpec &target_arch = m_target.GetArchitecture(); +        const ArchSpec &target_arch = GetTarget().GetArchitecture();          if (target_arch.IsValid() && !platform_sp->IsCompatibleArchitecture (target_arch, false, NULL))          {              ArchSpec platform_arch;              platform_sp = platform_sp->GetPlatformForArchitecture (target_arch, &platform_arch);              if (platform_sp)              { -                m_target.SetPlatform (platform_sp); -                m_target.SetArchitecture(platform_arch); +                GetTarget().SetPlatform (platform_sp); +                GetTarget().SetArchitecture(platform_arch);                  if (log)                      log->Printf ("Process::%s switching platform to %s and architecture to %s based on info from attach", __FUNCTION__, platform_sp->GetName().AsCString (""), platform_arch.GetTriple().getTriple().c_str ());              } @@ -3631,9 +3426,9 @@ Process::CompleteAttach ()              ProcessInstanceInfo process_info;              platform_sp->GetProcessInfo (GetID(), process_info);              const ArchSpec &process_arch = process_info.GetArchitecture(); -            if (process_arch.IsValid() && !m_target.GetArchitecture().IsExactMatch(process_arch)) +            if (process_arch.IsValid() && !GetTarget().GetArchitecture().IsExactMatch(process_arch))              { -                m_target.SetArchitecture (process_arch); +                GetTarget().SetArchitecture (process_arch);                  if (log)                      log->Printf ("Process::%s switching architecture to %s based on info the platform retrieved for pid %" PRIu64, __FUNCTION__, process_arch.GetTriple().getTriple().c_str (), GetID ());              } @@ -3648,7 +3443,7 @@ Process::CompleteAttach ()          dyld->DidAttach();          if (log)          { -            ModuleSP exe_module_sp = m_target.GetExecutableModule (); +            ModuleSP exe_module_sp = GetTarget().GetExecutableModule ();              log->Printf ("Process::%s after DynamicLoader::DidAttach(), target executable is %s (using %s plugin)",                           __FUNCTION__,                           exe_module_sp ? exe_module_sp->GetFileSpec().GetPath().c_str () : "<none>", @@ -3664,7 +3459,7 @@ Process::CompleteAttach ()          system_runtime->DidAttach();          if (log)          { -            ModuleSP exe_module_sp = m_target.GetExecutableModule (); +            ModuleSP exe_module_sp = GetTarget().GetExecutableModule ();              log->Printf ("Process::%s after SystemRuntime::DidAttach(), target executable is %s (using %s plugin)",                           __FUNCTION__,                           exe_module_sp ? exe_module_sp->GetFileSpec().GetPath().c_str () : "<none>", @@ -3674,7 +3469,7 @@ Process::CompleteAttach ()      m_os_ap.reset (OperatingSystem::FindPlugin (this, NULL));      // Figure out which one is the executable, and set that in our target: -    const ModuleList &target_modules = m_target.GetImages(); +    const ModuleList &target_modules = GetTarget().GetImages();      Mutex::Locker modules_locker(target_modules.GetMutex());      size_t num_modules = target_modules.GetSize();      ModuleSP new_executable_module_sp; @@ -3684,17 +3479,17 @@ Process::CompleteAttach ()          ModuleSP module_sp (target_modules.GetModuleAtIndexUnlocked (i));          if (module_sp && module_sp->IsExecutable())          { -            if (m_target.GetExecutableModulePointer() != module_sp.get()) +            if (GetTarget().GetExecutableModulePointer() != module_sp.get())                  new_executable_module_sp = module_sp;              break;          }      }      if (new_executable_module_sp)      { -        m_target.SetExecutableModule (new_executable_module_sp, false); +        GetTarget().SetExecutableModule (new_executable_module_sp, false);          if (log)          { -            ModuleSP exe_module_sp = m_target.GetExecutableModule (); +            ModuleSP exe_module_sp = GetTarget().GetExecutableModule ();              log->Printf ("Process::%s after looping through modules, target executable is %s",                           __FUNCTION__,                           exe_module_sp ? exe_module_sp->GetFileSpec().GetPath().c_str () : "<none>"); @@ -3742,7 +3537,6 @@ Process::ConnectRemote (Stream *strm, const char *remote_url)      return error;  } -  Error  Process::PrivateResume ()  { @@ -3803,150 +3597,99 @@ Process::PrivateResume ()  }  Error -Process::Halt (bool clear_thread_plans) +Process::Halt (bool clear_thread_plans, bool use_run_lock)  { +    if (! StateIsRunningState(m_public_state.GetValue())) +        return Error("Process is not running."); +      // Don't clear the m_clear_thread_plans_on_stop, only set it to true if      // in case it was already set and some thread plan logic calls halt on its      // own.      m_clear_thread_plans_on_stop |= clear_thread_plans; -    // First make sure we aren't in the middle of handling an event, or we might restart.  This is pretty weak, since -    // we could just straightaway get another event.  It just narrows the window... -    m_currently_handling_event.WaitForValueEqualTo(false); - -     -    // Pause our private state thread so we can ensure no one else eats -    // the stop event out from under us.      Listener halt_listener ("lldb.process.halt_listener"); -    HijackPrivateProcessEvents(&halt_listener); +    HijackProcessEvents(&halt_listener);      EventSP event_sp; -    Error error (WillHalt()); -    bool restored_process_events = false; -    if (error.Success()) +    SendAsyncInterrupt(); + +    if (m_public_state.GetValue() == eStateAttaching)      { -         -        bool caused_stop = false; -         -        // Ask the process subclass to actually halt our process -        error = DoHalt(caused_stop); -        if (error.Success()) -        { -            if (m_public_state.GetValue() == eStateAttaching) -            { -                // Don't hijack and eat the eStateExited as the code that was doing -                // the attach will be waiting for this event... -                RestorePrivateProcessEvents(); -                restored_process_events = true; -                SetExitStatus(SIGKILL, "Cancelled async attach."); -                Destroy (false); -            } -            else -            { -                // If "caused_stop" is true, then DoHalt stopped the process. If -                // "caused_stop" is false, the process was already stopped. -                // If the DoHalt caused the process to stop, then we want to catch -                // this event and set the interrupted bool to true before we pass -                // this along so clients know that the process was interrupted by -                // a halt command. -                if (caused_stop) -                { -                    // Wait for 1 second for the process to stop. -                    TimeValue timeout_time; -                    timeout_time = TimeValue::Now(); -                    timeout_time.OffsetWithSeconds(10); -                    bool got_event = halt_listener.WaitForEvent (&timeout_time, event_sp); -                    StateType state = ProcessEventData::GetStateFromEvent(event_sp.get()); -                     -                    if (!got_event || state == eStateInvalid) -                    { -                        // We timeout out and didn't get a stop event... -                        error.SetErrorStringWithFormat ("Halt timed out. State = %s", StateAsCString(GetState())); -                    } -                    else -                    { -                        if (StateIsStoppedState (state, false)) -                        { -                            // We caused the process to interrupt itself, so mark this -                            // as such in the stop event so clients can tell an interrupted -                            // process from a natural stop -                            ProcessEventData::SetInterruptedInEvent (event_sp.get(), true); -                        } -                        else -                        { -                            Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); -                            if (log) -                                log->Printf("Process::Halt() failed to stop, state is: %s", StateAsCString(state)); -                            error.SetErrorString ("Did not get stopped event after halt."); -                        } -                    } -                } -                DidHalt(); -            } -        } +        // Don't hijack and eat the eStateExited as the code that was doing +        // the attach will be waiting for this event... +        RestoreProcessEvents(); +        SetExitStatus(SIGKILL, "Cancelled async attach."); +        Destroy (false); +        return Error();      } -    // Resume our private state thread before we post the event (if any) -    if (!restored_process_events) -        RestorePrivateProcessEvents(); -    // Post any event we might have consumed. If all goes well, we will have -    // stopped the process, intercepted the event and set the interrupted -    // bool in the event.  Post it to the private event queue and that will end up -    // correctly setting the state. -    if (event_sp) -        m_private_state_broadcaster.BroadcastEvent(event_sp); +    // Wait for 10 second for the process to stop. +    TimeValue timeout_time; +    timeout_time = TimeValue::Now(); +    timeout_time.OffsetWithSeconds(10); +    StateType state = WaitForProcessToStop(&timeout_time, &event_sp, true, &halt_listener, +                                           nullptr, use_run_lock); +    RestoreProcessEvents(); -    return error; +    if (state == eStateInvalid || ! event_sp) +    { +        // We timed out and didn't get a stop event... +        return Error("Halt timed out. State = %s", StateAsCString(GetState())); +    } + +    BroadcastEvent(event_sp); + +    return Error();  }  Error -Process::HaltForDestroyOrDetach(lldb::EventSP &exit_event_sp) +Process::StopForDestroyOrDetach(lldb::EventSP &exit_event_sp)  {      Error error;      if (m_public_state.GetValue() == eStateRunning)      {          Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));          if (log) -            log->Printf("Process::Destroy() About to halt."); -        error = Halt(); -        if (error.Success()) +            log->Printf("Process::%s() About to stop.", __FUNCTION__); + +        ListenerSP listener_sp (new Listener("lldb.Process.StopForDestroyOrDetach.hijack")); +        HijackProcessEvents(listener_sp.get()); + +        SendAsyncInterrupt(); + +        // Consume the interrupt event. +        TimeValue timeout (TimeValue::Now()); +        timeout.OffsetWithSeconds(10); + +        StateType state = WaitForProcessToStop (&timeout, &exit_event_sp, true, listener_sp.get()); + +        RestoreProcessEvents(); + +        // If the process exited while we were waiting for it to stop, put the exited event into +        // the shared pointer passed in and return.  Our caller doesn't need to do anything else, since +        // they don't have a process anymore... + +        if (state == eStateExited || m_private_state.GetValue() == eStateExited)          { -            // Consume the halt event. -            TimeValue timeout (TimeValue::Now()); -            timeout.OffsetWithSeconds(1); -            StateType state = WaitForProcessToStop (&timeout, &exit_event_sp); -             -            // If the process exited while we were waiting for it to stop, put the exited event into -            // the shared pointer passed in and return.  Our caller doesn't need to do anything else, since -            // they don't have a process anymore... -             -            if (state == eStateExited || m_private_state.GetValue() == eStateExited) -            { -                if (log) -                    log->Printf("Process::HaltForDestroyOrDetach() Process exited while waiting to Halt."); -                return error; -            } -            else -                exit_event_sp.reset(); // It is ok to consume any non-exit stop events -     -            if (state != eStateStopped) -            { -                if (log) -                    log->Printf("Process::HaltForDestroyOrDetach() Halt failed to stop, state is: %s", StateAsCString(state)); -                // If we really couldn't stop the process then we should just error out here, but if the -                // lower levels just bobbled sending the event and we really are stopped, then continue on. -                StateType private_state = m_private_state.GetValue(); -                if (private_state != eStateStopped) -                { -                    return error; -                } -            } +            if (log) +                log->Printf("Process::%s() Process exited while waiting to stop.", __FUNCTION__); +            return error;          }          else +            exit_event_sp.reset(); // It is ok to consume any non-exit stop events + +        if (state != eStateStopped)          {              if (log) -                log->Printf("Process::HaltForDestroyOrDetach() Halt got error: %s", error.AsCString()); +                log->Printf("Process::%s() failed to stop, state is: %s", __FUNCTION__, StateAsCString(state)); +            // If we really couldn't stop the process then we should just error out here, but if the +            // lower levels just bobbled sending the event and we really are stopped, then continue on. +            StateType private_state = m_private_state.GetValue(); +            if (private_state != eStateStopped) +            { +                return error; +            }          }      }      return error; @@ -3965,7 +3708,7 @@ Process::Detach (bool keep_stopped)      {          if (DetachRequiresHalt())          { -            error = HaltForDestroyOrDetach (exit_event_sp); +            error = StopForDestroyOrDetach (exit_event_sp);              if (!error.Success())              {                  m_destroy_in_process = false; @@ -4016,7 +3759,7 @@ Process::Detach (bool keep_stopped)  Error  Process::Destroy (bool force_kill)  { -     +      // Tell ourselves we are in the process of destroying the process, so that we don't do any unnecessary work      // that might hinder the destruction.  Remember to set this back to false when we are done.  That way if the attempt      // failed and the process stays around for some reason it won't be in a confused state. @@ -4039,7 +3782,7 @@ Process::Destroy (bool force_kill)          EventSP exit_event_sp;          if (DestroyRequiresHalt())          { -            error = HaltForDestroyOrDetach(exit_event_sp); +            error = StopForDestroyOrDetach(exit_event_sp);          }          if (m_public_state.GetValue() != eStateRunning) @@ -4103,7 +3846,7 @@ Process::Signal (int signal)  }  void -Process::SetUnixSignals (const UnixSignalsSP &signals_sp) +Process::SetUnixSignals(UnixSignalsSP &&signals_sp)  {      assert (signals_sp && "null signals_sp");      m_unix_signals_sp = signals_sp; @@ -4119,16 +3862,15 @@ Process::GetUnixSignals ()  lldb::ByteOrder  Process::GetByteOrder () const  { -    return m_target.GetArchitecture().GetByteOrder(); +    return GetTarget().GetArchitecture().GetByteOrder();  }  uint32_t  Process::GetAddressByteSize () const  { -    return m_target.GetArchitecture().GetAddressByteSize(); +    return GetTarget().GetArchitecture().GetAddressByteSize();  } -  bool  Process::ShouldBroadcastEvent (Event *event_ptr)  { @@ -4142,6 +3884,10 @@ Process::ShouldBroadcastEvent (Event *event_ptr)          case eStateExited:          case eStateUnloaded:              m_stdio_communication.SynchronizeWithReadThread(); +            m_stdio_communication.Disconnect(); +            m_stdio_communication.StopReadThread(); +            m_stdin_forward = false; +              // fall-through          case eStateConnected:          case eStateAttaching: @@ -4258,7 +4004,6 @@ Process::ShouldBroadcastEvent (Event *event_ptr)                          ProcessEventData::SetRestartedInEvent(event_ptr, true);                          PrivateResume ();                      } -                  }                  else                  { @@ -4291,7 +4036,6 @@ Process::ShouldBroadcastEvent (Event *event_ptr)      return return_value;  } -  bool  Process::StartPrivateStateThread (bool is_secondary_thread)  { @@ -4326,7 +4070,7 @@ 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); +    m_private_state_thread = ThreadLauncher::LaunchThread(thread_name, Process::PrivateStateThread, (void *) &args, NULL, 8 * 1024 * 1024);      if (m_private_state_thread.IsJoinable())      {          ResumePrivateStateThread(); @@ -4432,8 +4176,6 @@ Process::HandlePrivateEvent (EventSP &event_sp)      Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));      m_resume_requested = false; -    m_currently_handling_event.SetValue(true, eBroadcastNever); -          const StateType new_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());      // First check to see if anybody wants a shot at this event: @@ -4460,7 +4202,6 @@ Process::HandlePrivateEvent (EventSP &event_sp)                  {                      // FIXME: should cons up an exited event, and discard this one.                      SetExitStatus(0, m_next_event_action_ap->GetExitString()); -                    m_currently_handling_event.SetValue(false, eBroadcastAlways);                      SetNextEventAction(NULL);                      return;                  } @@ -4532,7 +4273,7 @@ Process::HandlePrivateEvent (EventSP &event_sp)                  // events) and we do need the IO handler to be pushed and popped                  // correctly. -                if (is_hijacked || m_target.GetDebugger().IsHandlingEvents() == false) +                if (is_hijacked || GetTarget().GetDebugger().IsHandlingEvents() == false)                      PopProcessIOHandler ();              }          } @@ -4550,7 +4291,22 @@ Process::HandlePrivateEvent (EventSP &event_sp)                           StateAsCString (GetState ()));          }      } -    m_currently_handling_event.SetValue(false, eBroadcastAlways); +} + +Error +Process::HaltPrivate() +{ +    EventSP event_sp; +    Error error (WillHalt()); +    if (error.Fail()) +        return error; + +    // Ask the process subclass to actually halt our process +    bool caused_stop; +    error = DoHalt(caused_stop); + +    DidHalt(); +    return error;  }  thread_result_t @@ -4573,6 +4329,7 @@ Process::RunPrivateStateThread (bool is_secondary_thread)                       __FUNCTION__, static_cast<void*>(this), GetID());      bool exit_now = false; +    bool interrupt_requested = false;      while (!exit_now)      {          EventSP event_sp; @@ -4612,13 +4369,32 @@ Process::RunPrivateStateThread (bool is_secondary_thread)                                   GetID());                  BroadcastEvent (eBroadcastBitInterrupt, NULL);              } -            else +            else if(StateIsRunningState(m_last_broadcast_state))              {                  if (log)                      log->Printf ("Process::%s (arg = %p, pid = %" PRIu64 ") woke up with an interrupt - Halting.",                                   __FUNCTION__, static_cast<void*>(this),                                   GetID()); -                Halt(); +                Error error = HaltPrivate(); +                if (error.Fail() && log) +                    log->Printf ("Process::%s (arg = %p, pid = %" PRIu64 ") failed to halt the process: %s", +                                 __FUNCTION__, static_cast<void*>(this), +                                 GetID(), error.AsCString()); +                // Halt should generate a stopped event. Make a note of the fact that we were +                // doing the interrupt, so we can set the interrupted flag after we receive the +                // event. We deliberately set this to true even if HaltPrivate failed, so that we +                // can interrupt on the next natural stop. +                interrupt_requested = true; +            } +            else +            { +                // This can happen when someone (e.g. Process::Halt) sees that we are running and +                // sends an interrupt request, but the process actually stops before we receive +                // it. In that case, we can just ignore the request. We use +                // m_last_broadcast_state, because the Stopped event may not have been popped of +                // the event queue yet, which is when the public state gets updated. +                if (log) +                    log->Printf("Process::%s ignoring interrupt as we have already stopped.", __FUNCTION__);              }              continue;          } @@ -4633,6 +4409,23 @@ Process::RunPrivateStateThread (bool is_secondary_thread)                  m_clear_thread_plans_on_stop = false;                  m_thread_list.DiscardThreadPlans();              } + +            if (interrupt_requested) +            { +                if (StateIsStoppedState (internal_state, true)) +                { +                    // We requested the interrupt, so mark this as such in the stop event so +                    // clients can tell an interrupted process from a natural stop +                    ProcessEventData::SetInterruptedInEvent (event_sp.get(), true); +                    interrupt_requested = false; +                } +                else if (log) +                { +                    log->Printf("Process::%s interrupt_requested, but a non-stopped state '%s' received.", +                            __FUNCTION__, StateAsCString(internal_state)); +                } +            } +              HandlePrivateEvent (event_sp);          } @@ -4690,9 +4483,7 @@ Process::ProcessEventData::ProcessEventData (const ProcessSP &process_sp, StateT          m_process_wp = process_sp;  } -Process::ProcessEventData::~ProcessEventData() -{ -} +Process::ProcessEventData::~ProcessEventData() = default;  const ConstString &  Process::ProcessEventData::GetFlavorString () @@ -4734,7 +4525,12 @@ Process::ProcessEventData::DoOnRemoval (Event *event_ptr)      // If we're stopped and haven't restarted, then do the StopInfo actions here:      if (m_state == eStateStopped && ! m_restarted) -    {         +    { +        // Let process subclasses know we are about to do a public stop and +        // do anything they might need to in order to speed up register and +        // memory accesses. +        process_sp->WillPublicStop(); +          ThreadList &curr_thread_list = process_sp->GetThreadList();          uint32_t num_threads = curr_thread_list.GetSize();          uint32_t idx; @@ -4818,7 +4614,6 @@ Process::ProcessEventData::DoOnRemoval (Event *event_ptr)                      still_should_stop = this_thread_wants_to_stop;              }          } -          if (!GetRestarted())          { @@ -4967,13 +4762,13 @@ Process::ProcessEventData::SetUpdateStateOnRemoval (Event *event_ptr)  lldb::TargetSP  Process::CalculateTarget ()  { -    return m_target.shared_from_this(); +    return m_target_sp.lock();  }  void  Process::CalculateExecutionContext (ExecutionContext &exe_ctx)  { -    exe_ctx.SetTargetPtr (&m_target); +    exe_ctx.SetTargetPtr (&GetTarget());      exe_ctx.SetProcessPtr (this);      exe_ctx.SetThreadPtr(NULL);      exe_ctx.SetFramePtr (NULL); @@ -5052,7 +4847,6 @@ Process::GetAsyncProfileData (char *buf, size_t buf_size, Error &error)      return bytes_available;  } -  //------------------------------------------------------------------  // Process STDIO  //------------------------------------------------------------------ @@ -5084,7 +4878,6 @@ Process::GetSTDOUT (char *buf, size_t buf_size, Error &error)      return bytes_available;  } -  size_t  Process::GetSTDERR (char *buf, size_t buf_size, Error &error)  { @@ -5135,12 +4928,8 @@ public:          m_read_file.SetDescriptor(GetInputFD(), false);      } -    virtual -    ~IOHandlerProcessSTDIO () -    { -         -    } -     +    ~IOHandlerProcessSTDIO() override = default; +      // Each IOHandler gets to run until it is done. It should read data      // from the "in" and place output into "out" and "err and return      // when done. @@ -5207,7 +4996,7 @@ public:                                  break;                              case 'i':                                  if (StateIsRunningState(m_process->GetState())) -                                    m_process->Halt(); +                                    m_process->SendAsyncInterrupt();                                  break;                          }                      } @@ -5232,8 +5021,8 @@ public:          // Do only things that are safe to do in an interrupt context (like in          // a SIGINT handler), like write 1 byte to a file descriptor. This will          // interrupt the IOHandlerProcessSTDIO::Run() and we can look at the byte -        // that was written to the pipe and then call m_process->Halt() from a -        // much safer location in code. +        // that was written to the pipe and then call m_process->SendAsyncInterrupt() +        // from a much safer location in code.          if (m_active)          {              char ch = 'i'; // Send 'i' for interrupt @@ -5263,7 +5052,6 @@ public:      void      GotEOF() override      { -              }  protected: @@ -5301,7 +5089,7 @@ Process::ProcessIOHandlerIsActive ()  {      IOHandlerSP io_handler_sp (m_process_input_reader);      if (io_handler_sp) -        return m_target.GetDebugger().IsTopIOHandler (io_handler_sp); +        return GetTarget().GetDebugger().IsTopIOHandler (io_handler_sp);      return false;  }  bool @@ -5315,7 +5103,7 @@ Process::PushProcessIOHandler ()              log->Printf("Process::%s pushing IO handler", __FUNCTION__);          io_handler_sp->SetIsDone(false); -        m_target.GetDebugger().PushIOHandler (io_handler_sp); +        GetTarget().GetDebugger().PushIOHandler (io_handler_sp);          return true;      }      return false; @@ -5326,7 +5114,7 @@ Process::PopProcessIOHandler ()  {      IOHandlerSP io_handler_sp (m_process_input_reader);      if (io_handler_sp) -        return m_target.GetDebugger().PopIOHandler (io_handler_sp); +        return GetTarget().GetDebugger().PopIOHandler (io_handler_sp);      return false;  } @@ -5343,6 +5131,54 @@ Process::SettingsTerminate ()      Thread::SettingsTerminate ();  } +namespace +{ +    // RestorePlanState is used to record the "is private", "is master" and "okay to discard" fields of +    // the plan we are running, and reset it on Clean or on destruction. +    // It will only reset the state once, so you can call Clean and then monkey with the state and it +    // won't get reset on you again. +     +    class RestorePlanState +    { +    public: +        RestorePlanState (lldb::ThreadPlanSP thread_plan_sp) : +            m_thread_plan_sp(thread_plan_sp), +            m_already_reset(false) +        { +            if (m_thread_plan_sp) +            { +                m_private = m_thread_plan_sp->GetPrivate(); +                m_is_master = m_thread_plan_sp->IsMasterPlan(); +                m_okay_to_discard = m_thread_plan_sp->OkayToDiscard(); +            } +        } +         +        ~RestorePlanState() +        { +            Clean(); +        } +         +        void +        Clean () +        { +            if (!m_already_reset && m_thread_plan_sp) +            { +                m_already_reset = true; +                m_thread_plan_sp->SetPrivate(m_private); +                m_thread_plan_sp->SetIsMasterPlan (m_is_master); +                m_thread_plan_sp->SetOkayToDiscard(m_okay_to_discard); +            } +        } + +    private: +        lldb::ThreadPlanSP m_thread_plan_sp; +        bool m_already_reset; +        bool m_private; +        bool m_is_master; +        bool m_okay_to_discard; +    }; +} // anonymous namespace +  ExpressionResults  Process::RunThreadPlan (ExecutionContext &exe_ctx,                          lldb::ThreadPlanSP &thread_plan_sp, @@ -5376,12 +5212,22 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,          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.      // For that to be true the plan can't be private - since private plans suppress themselves in the      // GetCompletedPlan call.  -    bool orig_plan_private = thread_plan_sp->GetPrivate();      thread_plan_sp->SetPrivate(false); +     +    // The plans run with RunThreadPlan also need to be terminal master plans or when they are done we will end +    // up asking the plan above us whether we should stop, which may give the wrong answer. +     +    thread_plan_sp->SetIsMasterPlan (true); +    thread_plan_sp->SetOkayToDiscard(false);      if (m_private_state.GetValue() != eStateStopped)      { @@ -5553,7 +5399,6 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,                  }                  one_thread_timeout_usec = computed_one_thread_timeout;                  all_threads_timeout_usec = timeout_usec - one_thread_timeout_usec; -                              }          } @@ -5595,8 +5440,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,  #endif          TimeValue one_thread_timeout;          TimeValue final_timeout; -         -         +          while (1)          {              // We usually want to resume the process if we get to the top of the loop. @@ -5664,7 +5508,9 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,                      {                          // This is probably an overabundance of caution, I don't think I should ever get a stopped & restarted                          // event here.  But if I do, the best thing is to Halt and then get out of here. -                        Halt(); +                        const bool clear_thread_plans = false; +                        const bool use_run_lock = false; +                        Halt(clear_thread_plans, use_run_lock);                      }                      errors.Printf("Didn't get running event after initial resume, got %s instead.", @@ -5758,7 +5604,9 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,                      bool keep_going = false;                      if (event_sp->GetType() == eBroadcastBitInterrupt)                      { -                        Halt(); +                        const bool clear_thread_plans = false; +                        const bool use_run_lock = false; +                        Halt(clear_thread_plans, use_run_lock);                          return_value = eExpressionInterrupted;                          errors.Printf ("Execution halted by user interrupt.");                          if (log) @@ -5796,7 +5644,6 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,                                         keep_going = true;                                         do_resume = false;                                         handle_running_event = true; -                                      }                                      else                                      { @@ -5811,10 +5658,10 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,                                          {                                              if (log)                                                  log->PutCString ("Process::RunThreadPlan(): execution completed successfully."); -                                            // Now mark this plan as private so it doesn't get reported as the stop reason -                                            // after this point.   -                                            if (thread_plan_sp) -                                                thread_plan_sp->SetPrivate (orig_plan_private); +                                             +                                            // Restore the plan state so it will get reported as intended when we are done. +                                            thread_plan_restorer.Clean(); +                                                                                          return_value = eExpressionCompleted;                                          }                                          else @@ -5827,6 +5674,13 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,                                                  return_value = eExpressionHitBreakpoint;                                                  if (!options.DoesIgnoreBreakpoints())                                                  { +                                                    // Restore the plan state and then force Private to false.  We are +                                                    // going to stop because of this plan so we need it to become a public +                                                    // plan or it won't report correctly when we continue to its termination +                                                    // later on. +                                                    thread_plan_restorer.Clean(); +                                                    if (thread_plan_sp) +                                                        thread_plan_sp->SetPrivate(false);                                                      event_to_broadcast_sp = event_sp;                                                  }                                              } @@ -5929,7 +5783,9 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,                      {                          if (log)                              log->Printf ("Process::RunThreadPlan(): Running Halt."); -                        halt_error = Halt(); +                        const bool clear_thread_plans = false; +                        const bool use_run_lock = false; +                        Halt(clear_thread_plans, use_run_lock);                      }                      if (halt_error.Success())                      { @@ -6045,6 +5901,19 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,                  m_public_state.SetValueNoLock(old_state);          } +        if (return_value != eExpressionCompleted && log) +        { +            // Print a backtrace into the log so we can figure out where we are: +            StreamString s; +            s.PutCString("Thread state after unsuccessful completion: \n"); +            thread->GetStackFrameStatus (s, +                                         0, +                                         UINT32_MAX, +                                         true, +                                         UINT32_MAX); +            log->PutCString(s.GetData()); + +        }          // Restore the thread state if we are going to discard the plan execution.  There are three cases where this          // could happen:          // 1) The execution successfully completed @@ -6133,7 +6002,8 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,                              else                                  ts.Printf("[ip unknown] "); -                            lldb::StopInfoSP stop_info_sp = thread->GetStopInfo(); +                            // Show the private stop info here, the public stop info will be from the last natural stop. +                            lldb::StopInfoSP stop_info_sp = thread->GetPrivateStopInfo();                              if (stop_info_sp)                              {                                  const char *stop_desc = stop_info_sp->GetDescription(); @@ -6159,7 +6029,6 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,                      log->Printf ("Process::RunThreadPlan: ExecutionInterrupted - discarding thread plans up to %p.",                                   static_cast<void*>(thread_plan_sp.get()));                  thread->DiscardThreadPlansUpToPlan (thread_plan_sp); -                thread_plan_sp->SetPrivate (orig_plan_private);              }              else              { @@ -6176,7 +6045,6 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,              if (options.DoesUnwindOnError())              {                  thread->DiscardThreadPlansUpToPlan (thread_plan_sp); -                thread_plan_sp->SetPrivate (orig_plan_private);              }          }          else @@ -6202,7 +6070,6 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,                      if (log)                          log->PutCString("Process::RunThreadPlan(): discarding thread plan 'cause unwind_on_error is set.");                      thread->DiscardThreadPlansUpToPlan (thread_plan_sp); -                    thread_plan_sp->SetPrivate (orig_plan_private);                  }              }          } @@ -6360,7 +6227,6 @@ Process::GetThreadStatus (Stream &strm,              Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS));              if (log)                  log->Printf("Process::GetThreadStatus - thread 0x" PRIu64 " vanished while running Thread::GetStatus."); -                      }      }      return num_thread_infos_dumped; @@ -6529,6 +6395,65 @@ Process::ModulesDidLoad (ModuleList &module_list)          if (language_runtime_sp)              language_runtime_sp->ModulesDidLoad(module_list);      } + +    LoadOperatingSystemPlugin(false); +} + +void +Process::PrintWarning (uint64_t warning_type, const void *repeat_key, const char *fmt, ...) +{ +    bool print_warning = true; + +    StreamSP stream_sp = GetTarget().GetDebugger().GetAsyncOutputStream(); +    if (stream_sp.get() == nullptr) +        return; +    if (warning_type == eWarningsOptimization +        && GetWarningsOptimization() == false) +    { +        return; +    } + +    if (repeat_key != nullptr) +    { +        WarningsCollection::iterator it = m_warnings_issued.find (warning_type); +        if (it == m_warnings_issued.end()) +        { +            m_warnings_issued[warning_type] = WarningsPointerSet(); +            m_warnings_issued[warning_type].insert (repeat_key); +        } +        else +        { +            if (it->second.find (repeat_key) != it->second.end()) +            { +                print_warning = false; +            } +            else +            { +                it->second.insert (repeat_key); +            } +        } +    } + +    if (print_warning) +    { +        va_list args; +        va_start (args, fmt); +        stream_sp->PrintfVarArg (fmt, args); +        va_end (args); +    } +} + +void +Process::PrintWarningOptimization (const SymbolContext &sc) +{ +    if (GetWarningsOptimization() == true +        && sc.module_sp.get()  +        && sc.module_sp->GetFileSpec().GetFilename().IsEmpty() == false +        && sc.function +        && sc.function->GetIsOptimized() == true) +    { +        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()); +    }  }  ThreadCollectionSP @@ -6568,3 +6493,25 @@ Process::GetModuleSpec(const FileSpec& module_file_spec,      module_spec.Clear();      return false;  } + +size_t +Process::AddImageToken(lldb::addr_t image_ptr) +{ +    m_image_tokens.push_back(image_ptr); +    return m_image_tokens.size() - 1; +} + +lldb::addr_t +Process::GetImagePtrFromToken(size_t token) const +{ +    if (token < m_image_tokens.size()) +        return m_image_tokens[token]; +    return LLDB_INVALID_IMAGE_TOKEN; +} + +void +Process::ResetImageToken(size_t token) +{ +    if (token < m_image_tokens.size()) +        m_image_tokens[token] = LLDB_INVALID_IMAGE_TOKEN; +}  | 
