//===-- SBProcess.cpp -------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "lldb/API/SBProcess.h" // C Includes #include #include "lldb/lldb-defines.h" #include "lldb/lldb-types.h" #include "lldb/Interpreter/Args.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/State.h" #include "lldb/Core/Stream.h" #include "lldb/Core/StreamFile.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/SystemRuntime.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" // Project includes #include "lldb/API/SBBroadcaster.h" #include "lldb/API/SBCommandReturnObject.h" #include "lldb/API/SBDebugger.h" #include "lldb/API/SBEvent.h" #include "lldb/API/SBFileSpec.h" #include "lldb/API/SBThread.h" #include "lldb/API/SBThreadCollection.h" #include "lldb/API/SBStream.h" #include "lldb/API/SBStringList.h" #include "lldb/API/SBUnixSignals.h" using namespace lldb; using namespace lldb_private; SBProcess::SBProcess () : m_opaque_wp() { } //---------------------------------------------------------------------- // SBProcess constructor //---------------------------------------------------------------------- SBProcess::SBProcess (const SBProcess& rhs) : m_opaque_wp (rhs.m_opaque_wp) { } SBProcess::SBProcess (const lldb::ProcessSP &process_sp) : m_opaque_wp (process_sp) { } const SBProcess& SBProcess::operator = (const SBProcess& rhs) { if (this != &rhs) m_opaque_wp = rhs.m_opaque_wp; return *this; } //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- SBProcess::~SBProcess() { } const char * SBProcess::GetBroadcasterClassName () { return Process::GetStaticBroadcasterClass().AsCString(); } const char * SBProcess::GetPluginName () { ProcessSP process_sp(GetSP()); if (process_sp) { return process_sp->GetPluginName().GetCString(); } return ""; } const char * SBProcess::GetShortPluginName () { ProcessSP process_sp(GetSP()); if (process_sp) { return process_sp->GetPluginName().GetCString(); } return ""; } lldb::ProcessSP SBProcess::GetSP() const { return m_opaque_wp.lock(); } void SBProcess::SetSP (const ProcessSP &process_sp) { m_opaque_wp = process_sp; } void SBProcess::Clear () { m_opaque_wp.reset(); } bool SBProcess::IsValid() const { ProcessSP process_sp(m_opaque_wp.lock()); return ((bool) process_sp && process_sp->IsValid()); } bool SBProcess::RemoteLaunch (char const **argv, char const **envp, const char *stdin_path, const char *stdout_path, const char *stderr_path, const char *working_directory, uint32_t launch_flags, bool stop_at_entry, lldb::SBError& error) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) log->Printf ("SBProcess(%p)::RemoteLaunch (argv=%p, envp=%p, stdin=%s, stdout=%s, stderr=%s, working-dir=%s, launch_flags=0x%x, stop_at_entry=%i, &error (%p))...", static_cast(m_opaque_wp.lock().get()), static_cast(argv), static_cast(envp), stdin_path ? stdin_path : "NULL", stdout_path ? stdout_path : "NULL", stderr_path ? stderr_path : "NULL", working_directory ? working_directory : "NULL", launch_flags, stop_at_entry, static_cast(error.get())); ProcessSP process_sp(GetSP()); if (process_sp) { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); if (process_sp->GetState() == eStateConnected) { if (stop_at_entry) launch_flags |= eLaunchFlagStopAtEntry; ProcessLaunchInfo launch_info(FileSpec{stdin_path, false}, FileSpec{stdout_path, false}, FileSpec{stderr_path, false}, FileSpec{working_directory, false}, launch_flags); Module *exe_module = process_sp->GetTarget().GetExecutableModulePointer(); if (exe_module) launch_info.SetExecutableFile(exe_module->GetPlatformFileSpec(), true); if (argv) launch_info.GetArguments().AppendArguments (argv); if (envp) launch_info.GetEnvironmentEntries ().SetArguments (envp); error.SetError (process_sp->Launch (launch_info)); } else { error.SetErrorString ("must be in eStateConnected to call RemoteLaunch"); } } else { error.SetErrorString ("unable to attach pid"); } if (log) { SBStream sstr; error.GetDescription (sstr); log->Printf ("SBProcess(%p)::RemoteLaunch (...) => SBError (%p): %s", static_cast(process_sp.get()), static_cast(error.get()), sstr.GetData()); } return error.Success(); } bool SBProcess::RemoteAttachToProcessWithID (lldb::pid_t pid, lldb::SBError& error) { ProcessSP process_sp(GetSP()); if (process_sp) { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); if (process_sp->GetState() == eStateConnected) { ProcessAttachInfo attach_info; attach_info.SetProcessID (pid); error.SetError (process_sp->Attach (attach_info)); } else { error.SetErrorString ("must be in eStateConnected to call RemoteAttachToProcessWithID"); } } else { error.SetErrorString ("unable to attach pid"); } Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) { SBStream sstr; error.GetDescription (sstr); log->Printf ("SBProcess(%p)::RemoteAttachToProcessWithID (%" PRIu64 ") => SBError (%p): %s", static_cast(process_sp.get()), pid, static_cast(error.get()), sstr.GetData()); } return error.Success(); } uint32_t SBProcess::GetNumThreads () { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); uint32_t num_threads = 0; ProcessSP process_sp(GetSP()); if (process_sp) { Process::StopLocker stop_locker; const bool can_update = stop_locker.TryLock(&process_sp->GetRunLock()); Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); num_threads = process_sp->GetThreadList().GetSize(can_update); } if (log) log->Printf ("SBProcess(%p)::GetNumThreads () => %d", static_cast(process_sp.get()), num_threads); return num_threads; } SBThread SBProcess::GetSelectedThread () const { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); SBThread sb_thread; ThreadSP thread_sp; ProcessSP process_sp(GetSP()); if (process_sp) { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); thread_sp = process_sp->GetThreadList().GetSelectedThread(); sb_thread.SetThread (thread_sp); } if (log) log->Printf ("SBProcess(%p)::GetSelectedThread () => SBThread(%p)", static_cast(process_sp.get()), static_cast(thread_sp.get())); return sb_thread; } SBThread SBProcess::CreateOSPluginThread (lldb::tid_t tid, lldb::addr_t context) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); SBThread sb_thread; ThreadSP thread_sp; ProcessSP process_sp(GetSP()); if (process_sp) { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); thread_sp = process_sp->CreateOSPluginThread(tid, context); sb_thread.SetThread (thread_sp); } if (log) log->Printf ("SBProcess(%p)::CreateOSPluginThread (tid=0x%" PRIx64 ", context=0x%" PRIx64 ") => SBThread(%p)", static_cast(process_sp.get()), tid, context, static_cast(thread_sp.get())); return sb_thread; } SBTarget SBProcess::GetTarget() const { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); SBTarget sb_target; TargetSP target_sp; ProcessSP process_sp(GetSP()); if (process_sp) { target_sp = process_sp->GetTarget().shared_from_this(); sb_target.SetSP (target_sp); } if (log) log->Printf ("SBProcess(%p)::GetTarget () => SBTarget(%p)", static_cast(process_sp.get()), static_cast(target_sp.get())); return sb_target; } size_t SBProcess::PutSTDIN (const char *src, size_t src_len) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); size_t ret_val = 0; ProcessSP process_sp(GetSP()); if (process_sp) { Error error; ret_val = process_sp->PutSTDIN (src, src_len, error); } if (log) log->Printf("SBProcess(%p)::PutSTDIN (src=\"%s\", src_len=%" PRIu64 ") => %" PRIu64, static_cast(process_sp.get()), src, static_cast(src_len), static_cast(ret_val)); return ret_val; } size_t SBProcess::GetSTDOUT (char *dst, size_t dst_len) const { size_t bytes_read = 0; ProcessSP process_sp(GetSP()); if (process_sp) { Error error; bytes_read = process_sp->GetSTDOUT (dst, dst_len, error); } Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) log->Printf ("SBProcess(%p)::GetSTDOUT (dst=\"%.*s\", dst_len=%" PRIu64 ") => %" PRIu64, static_cast(process_sp.get()), static_cast(bytes_read), dst, static_cast(dst_len), static_cast(bytes_read)); return bytes_read; } size_t SBProcess::GetSTDERR (char *dst, size_t dst_len) const { size_t bytes_read = 0; ProcessSP process_sp(GetSP()); if (process_sp) { Error error; bytes_read = process_sp->GetSTDERR (dst, dst_len, error); } Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) log->Printf ("SBProcess(%p)::GetSTDERR (dst=\"%.*s\", dst_len=%" PRIu64 ") => %" PRIu64, static_cast(process_sp.get()), static_cast(bytes_read), dst, static_cast(dst_len), static_cast(bytes_read)); return bytes_read; } size_t SBProcess::GetAsyncProfileData(char *dst, size_t dst_len) const { size_t bytes_read = 0; ProcessSP process_sp(GetSP()); if (process_sp) { Error error; bytes_read = process_sp->GetAsyncProfileData (dst, dst_len, error); } Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) log->Printf ("SBProcess(%p)::GetProfileData (dst=\"%.*s\", dst_len=%" PRIu64 ") => %" PRIu64, static_cast(process_sp.get()), static_cast(bytes_read), dst, static_cast(dst_len), static_cast(bytes_read)); return bytes_read; } void SBProcess::ReportEventState (const SBEvent &event, FILE *out) const { if (out == NULL) return; ProcessSP process_sp(GetSP()); if (process_sp) { const StateType event_state = SBProcess::GetStateFromEvent (event); char message[1024]; int message_len = ::snprintf (message, sizeof (message), "Process %" PRIu64 " %s\n", process_sp->GetID(), SBDebugger::StateAsCString (event_state)); if (message_len > 0) ::fwrite (message, 1, message_len, out); } } void SBProcess::AppendEventStateReport (const SBEvent &event, SBCommandReturnObject &result) { ProcessSP process_sp(GetSP()); if (process_sp) { const StateType event_state = SBProcess::GetStateFromEvent (event); char message[1024]; ::snprintf (message, sizeof (message), "Process %" PRIu64 " %s\n", process_sp->GetID(), SBDebugger::StateAsCString (event_state)); result.AppendMessage (message); } } bool SBProcess::SetSelectedThread (const SBThread &thread) { ProcessSP process_sp(GetSP()); if (process_sp) { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); return process_sp->GetThreadList().SetSelectedThreadByID (thread.GetThreadID()); } return false; } bool SBProcess::SetSelectedThreadByID (lldb::tid_t tid) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); bool ret_val = false; ProcessSP process_sp(GetSP()); if (process_sp) { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); ret_val = process_sp->GetThreadList().SetSelectedThreadByID (tid); } if (log) log->Printf ("SBProcess(%p)::SetSelectedThreadByID (tid=0x%4.4" PRIx64 ") => %s", static_cast(process_sp.get()), tid, (ret_val ? "true" : "false")); return ret_val; } bool SBProcess::SetSelectedThreadByIndexID (uint32_t index_id) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); bool ret_val = false; ProcessSP process_sp(GetSP()); if (process_sp) { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); ret_val = process_sp->GetThreadList().SetSelectedThreadByIndexID (index_id); } if (log) log->Printf ("SBProcess(%p)::SetSelectedThreadByID (tid=0x%x) => %s", static_cast(process_sp.get()), index_id, (ret_val ? "true" : "false")); return ret_val; } SBThread SBProcess::GetThreadAtIndex (size_t index) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); SBThread sb_thread; ThreadSP thread_sp; ProcessSP process_sp(GetSP()); if (process_sp) { Process::StopLocker stop_locker; const bool can_update = stop_locker.TryLock(&process_sp->GetRunLock()); Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); thread_sp = process_sp->GetThreadList().GetThreadAtIndex(index, can_update); sb_thread.SetThread (thread_sp); } if (log) log->Printf ("SBProcess(%p)::GetThreadAtIndex (index=%d) => SBThread(%p)", static_cast(process_sp.get()), static_cast(index), static_cast(thread_sp.get())); return sb_thread; } uint32_t SBProcess::GetNumQueues () { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); uint32_t num_queues = 0; ProcessSP process_sp(GetSP()); if (process_sp) { Process::StopLocker stop_locker; Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); num_queues = process_sp->GetQueueList().GetSize(); } if (log) log->Printf ("SBProcess(%p)::GetNumQueues () => %d", static_cast(process_sp.get()), num_queues); return num_queues; } SBQueue SBProcess::GetQueueAtIndex (size_t index) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); SBQueue sb_queue; QueueSP queue_sp; ProcessSP process_sp(GetSP()); if (process_sp) { Process::StopLocker stop_locker; Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); queue_sp = process_sp->GetQueueList().GetQueueAtIndex(index); sb_queue.SetQueue (queue_sp); } if (log) log->Printf ("SBProcess(%p)::GetQueueAtIndex (index=%d) => SBQueue(%p)", static_cast(process_sp.get()), static_cast(index), static_cast(queue_sp.get())); return sb_queue; } uint32_t SBProcess::GetStopID(bool include_expression_stops) { ProcessSP process_sp(GetSP()); if (process_sp) { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); if (include_expression_stops) return process_sp->GetStopID(); else return process_sp->GetLastNaturalStopID(); } return 0; } SBEvent SBProcess::GetStopEventForStopID(uint32_t stop_id) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); SBEvent sb_event; EventSP event_sp; ProcessSP process_sp(GetSP()); if (process_sp) { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); event_sp = process_sp->GetStopEventForStopID(stop_id); sb_event.reset(event_sp); } if (log) log->Printf ("SBProcess(%p)::GetStopEventForStopID (stop_id=%" PRIu32 ") => SBEvent(%p)", static_cast(process_sp.get()), stop_id, static_cast(event_sp.get())); return sb_event; } StateType SBProcess::GetState () { StateType ret_val = eStateInvalid; ProcessSP process_sp(GetSP()); if (process_sp) { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); ret_val = process_sp->GetState(); } Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) log->Printf ("SBProcess(%p)::GetState () => %s", static_cast(process_sp.get()), lldb_private::StateAsCString (ret_val)); return ret_val; } int SBProcess::GetExitStatus () { int exit_status = 0; ProcessSP process_sp(GetSP()); if (process_sp) { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); exit_status = process_sp->GetExitStatus (); } Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) log->Printf ("SBProcess(%p)::GetExitStatus () => %i (0x%8.8x)", static_cast(process_sp.get()), exit_status, exit_status); return exit_status; } const char * SBProcess::GetExitDescription () { const char *exit_desc = NULL; ProcessSP process_sp(GetSP()); if (process_sp) { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); exit_desc = process_sp->GetExitDescription (); } Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) log->Printf ("SBProcess(%p)::GetExitDescription () => %s", static_cast(process_sp.get()), exit_desc); return exit_desc; } lldb::pid_t SBProcess::GetProcessID () { lldb::pid_t ret_val = LLDB_INVALID_PROCESS_ID; ProcessSP process_sp(GetSP()); if (process_sp) ret_val = process_sp->GetID(); Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) log->Printf ("SBProcess(%p)::GetProcessID () => %" PRIu64, static_cast(process_sp.get()), ret_val); return ret_val; } uint32_t SBProcess::GetUniqueID() { uint32_t ret_val = 0; ProcessSP process_sp(GetSP()); if (process_sp) ret_val = process_sp->GetUniqueID(); Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) log->Printf ("SBProcess(%p)::GetUniqueID () => %" PRIu32, static_cast(process_sp.get()), ret_val); return ret_val; } ByteOrder SBProcess::GetByteOrder () const { ByteOrder byteOrder = eByteOrderInvalid; ProcessSP process_sp(GetSP()); if (process_sp) byteOrder = process_sp->GetTarget().GetArchitecture().GetByteOrder(); Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) log->Printf ("SBProcess(%p)::GetByteOrder () => %d", static_cast(process_sp.get()), byteOrder); return byteOrder; } uint32_t SBProcess::GetAddressByteSize () const { uint32_t size = 0; ProcessSP process_sp(GetSP()); if (process_sp) size = process_sp->GetTarget().GetArchitecture().GetAddressByteSize(); Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) log->Printf ("SBProcess(%p)::GetAddressByteSize () => %d", static_cast(process_sp.get()), size); return size; } SBError SBProcess::Continue () { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); SBError sb_error; ProcessSP process_sp(GetSP()); if (log) log->Printf ("SBProcess(%p)::Continue ()...", static_cast(process_sp.get())); if (process_sp) { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); if (process_sp->GetTarget().GetDebugger().GetAsyncExecution ()) sb_error.ref() = process_sp->Resume (); else sb_error.ref() = process_sp->ResumeSynchronous (NULL); } else sb_error.SetErrorString ("SBProcess is invalid"); if (log) { SBStream sstr; sb_error.GetDescription (sstr); log->Printf ("SBProcess(%p)::Continue () => SBError (%p): %s", static_cast(process_sp.get()), static_cast(sb_error.get()), sstr.GetData()); } return sb_error; } SBError SBProcess::Destroy () { SBError sb_error; ProcessSP process_sp(GetSP()); if (process_sp) { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); sb_error.SetError(process_sp->Destroy(false)); } else sb_error.SetErrorString ("SBProcess is invalid"); Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) { SBStream sstr; sb_error.GetDescription (sstr); log->Printf ("SBProcess(%p)::Destroy () => SBError (%p): %s", static_cast(process_sp.get()), static_cast(sb_error.get()), sstr.GetData()); } return sb_error; } SBError SBProcess::Stop () { SBError sb_error; ProcessSP process_sp(GetSP()); if (process_sp) { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); sb_error.SetError (process_sp->Halt()); } else sb_error.SetErrorString ("SBProcess is invalid"); Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) { SBStream sstr; sb_error.GetDescription (sstr); log->Printf ("SBProcess(%p)::Stop () => SBError (%p): %s", static_cast(process_sp.get()), static_cast(sb_error.get()), sstr.GetData()); } return sb_error; } SBError SBProcess::Kill () { SBError sb_error; ProcessSP process_sp(GetSP()); if (process_sp) { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); sb_error.SetError (process_sp->Destroy(true)); } else sb_error.SetErrorString ("SBProcess is invalid"); Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) { SBStream sstr; sb_error.GetDescription (sstr); log->Printf ("SBProcess(%p)::Kill () => SBError (%p): %s", static_cast(process_sp.get()), static_cast(sb_error.get()), sstr.GetData()); } return sb_error; } SBError SBProcess::Detach () { // FIXME: This should come from a process default. bool keep_stopped = false; return Detach (keep_stopped); } SBError SBProcess::Detach (bool keep_stopped) { SBError sb_error; ProcessSP process_sp(GetSP()); if (process_sp) { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); sb_error.SetError (process_sp->Detach(keep_stopped)); } else sb_error.SetErrorString ("SBProcess is invalid"); return sb_error; } SBError SBProcess::Signal (int signo) { SBError sb_error; ProcessSP process_sp(GetSP()); if (process_sp) { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); sb_error.SetError (process_sp->Signal (signo)); } else sb_error.SetErrorString ("SBProcess is invalid"); Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) { SBStream sstr; sb_error.GetDescription (sstr); log->Printf ("SBProcess(%p)::Signal (signo=%i) => SBError (%p): %s", static_cast(process_sp.get()), signo, static_cast(sb_error.get()), sstr.GetData()); } return sb_error; } SBUnixSignals SBProcess::GetUnixSignals() { if (auto process_sp = GetSP()) return SBUnixSignals{process_sp}; return {}; } void SBProcess::SendAsyncInterrupt () { ProcessSP process_sp(GetSP()); if (process_sp) { process_sp->SendAsyncInterrupt (); } } SBThread SBProcess::GetThreadByID (tid_t tid) { SBThread sb_thread; ThreadSP thread_sp; ProcessSP process_sp(GetSP()); if (process_sp) { Process::StopLocker stop_locker; const bool can_update = stop_locker.TryLock(&process_sp->GetRunLock()); Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); thread_sp = process_sp->GetThreadList().FindThreadByID (tid, can_update); sb_thread.SetThread (thread_sp); } Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) log->Printf ("SBProcess(%p)::GetThreadByID (tid=0x%4.4" PRIx64 ") => SBThread (%p)", static_cast(process_sp.get()), tid, static_cast(thread_sp.get())); return sb_thread; } SBThread SBProcess::GetThreadByIndexID (uint32_t index_id) { SBThread sb_thread; ThreadSP thread_sp; ProcessSP process_sp(GetSP()); if (process_sp) { Process::StopLocker stop_locker; const bool can_update = stop_locker.TryLock(&process_sp->GetRunLock()); Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); thread_sp = process_sp->GetThreadList().FindThreadByIndexID (index_id, can_update); sb_thread.SetThread (thread_sp); } Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) log->Printf ("SBProcess(%p)::GetThreadByID (tid=0x%x) => SBThread (%p)", static_cast(process_sp.get()), index_id, static_cast(thread_sp.get())); return sb_thread; } StateType SBProcess::GetStateFromEvent (const SBEvent &event) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); StateType ret_val = Process::ProcessEventData::GetStateFromEvent (event.get()); if (log) log->Printf ("SBProcess::GetStateFromEvent (event.sp=%p) => %s", static_cast(event.get()), lldb_private::StateAsCString (ret_val)); return ret_val; } bool SBProcess::GetRestartedFromEvent (const SBEvent &event) { return Process::ProcessEventData::GetRestartedFromEvent (event.get()); } size_t SBProcess::GetNumRestartedReasonsFromEvent (const lldb::SBEvent &event) { return Process::ProcessEventData::GetNumRestartedReasons(event.get()); } const char * SBProcess::GetRestartedReasonAtIndexFromEvent (const lldb::SBEvent &event, size_t idx) { return Process::ProcessEventData::GetRestartedReasonAtIndex(event.get(), idx); } SBProcess SBProcess::GetProcessFromEvent (const SBEvent &event) { SBProcess process(Process::ProcessEventData::GetProcessFromEvent (event.get())); return process; } bool SBProcess::GetInterruptedFromEvent (const SBEvent &event) { return Process::ProcessEventData::GetInterruptedFromEvent(event.get()); } bool SBProcess::EventIsProcessEvent (const SBEvent &event) { return event.GetBroadcasterClass() == SBProcess::GetBroadcasterClass(); } SBBroadcaster SBProcess::GetBroadcaster () const { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); ProcessSP process_sp(GetSP()); SBBroadcaster broadcaster(process_sp.get(), false); if (log) log->Printf ("SBProcess(%p)::GetBroadcaster () => SBBroadcaster (%p)", static_cast(process_sp.get()), static_cast(broadcaster.get())); return broadcaster; } const char * SBProcess::GetBroadcasterClass () { return Process::GetStaticBroadcasterClass().AsCString(); } size_t SBProcess::ReadMemory (addr_t addr, void *dst, size_t dst_len, SBError &sb_error) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); size_t bytes_read = 0; ProcessSP process_sp(GetSP()); if (log) log->Printf ("SBProcess(%p)::ReadMemory (addr=0x%" PRIx64 ", dst=%p, dst_len=%" PRIu64 ", SBError (%p))...", static_cast(process_sp.get()), addr, static_cast(dst), static_cast(dst_len), static_cast(sb_error.get())); if (process_sp) { Process::StopLocker stop_locker; if (stop_locker.TryLock(&process_sp->GetRunLock())) { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); bytes_read = process_sp->ReadMemory (addr, dst, dst_len, sb_error.ref()); } else { if (log) log->Printf ("SBProcess(%p)::ReadMemory() => error: process is running", static_cast(process_sp.get())); sb_error.SetErrorString("process is running"); } } else { sb_error.SetErrorString ("SBProcess is invalid"); } if (log) { SBStream sstr; sb_error.GetDescription (sstr); log->Printf ("SBProcess(%p)::ReadMemory (addr=0x%" PRIx64 ", dst=%p, dst_len=%" PRIu64 ", SBError (%p): %s) => %" PRIu64, static_cast(process_sp.get()), addr, static_cast(dst), static_cast(dst_len), static_cast(sb_error.get()), sstr.GetData(), static_cast(bytes_read)); } return bytes_read; } size_t SBProcess::ReadCStringFromMemory (addr_t addr, void *buf, size_t size, lldb::SBError &sb_error) { size_t bytes_read = 0; ProcessSP process_sp(GetSP()); if (process_sp) { Process::StopLocker stop_locker; if (stop_locker.TryLock(&process_sp->GetRunLock())) { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); bytes_read = process_sp->ReadCStringFromMemory (addr, (char *)buf, size, sb_error.ref()); } else { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) log->Printf ("SBProcess(%p)::ReadCStringFromMemory() => error: process is running", static_cast(process_sp.get())); sb_error.SetErrorString("process is running"); } } else { sb_error.SetErrorString ("SBProcess is invalid"); } return bytes_read; } uint64_t SBProcess::ReadUnsignedFromMemory (addr_t addr, uint32_t byte_size, lldb::SBError &sb_error) { uint64_t value = 0; ProcessSP process_sp(GetSP()); if (process_sp) { Process::StopLocker stop_locker; if (stop_locker.TryLock(&process_sp->GetRunLock())) { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); value = process_sp->ReadUnsignedIntegerFromMemory (addr, byte_size, 0, sb_error.ref()); } else { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) log->Printf ("SBProcess(%p)::ReadUnsignedFromMemory() => error: process is running", static_cast(process_sp.get())); sb_error.SetErrorString("process is running"); } } else { sb_error.SetErrorString ("SBProcess is invalid"); } return value; } lldb::addr_t SBProcess::ReadPointerFromMemory (addr_t addr, lldb::SBError &sb_error) { lldb::addr_t ptr = LLDB_INVALID_ADDRESS; ProcessSP process_sp(GetSP()); if (process_sp) { Process::StopLocker stop_locker; if (stop_locker.TryLock(&process_sp->GetRunLock())) { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); ptr = process_sp->ReadPointerFromMemory (addr, sb_error.ref()); } else { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) log->Printf ("SBProcess(%p)::ReadPointerFromMemory() => error: process is running", static_cast(process_sp.get())); sb_error.SetErrorString("process is running"); } } else { sb_error.SetErrorString ("SBProcess is invalid"); } return ptr; } size_t SBProcess::WriteMemory (addr_t addr, const void *src, size_t src_len, SBError &sb_error) { size_t bytes_written = 0; Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); ProcessSP process_sp(GetSP()); if (log) log->Printf ("SBProcess(%p)::WriteMemory (addr=0x%" PRIx64 ", src=%p, src_len=%" PRIu64 ", SBError (%p))...", static_cast(process_sp.get()), addr, static_cast(src), static_cast(src_len), static_cast(sb_error.get())); if (process_sp) { Process::StopLocker stop_locker; if (stop_locker.TryLock(&process_sp->GetRunLock())) { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); bytes_written = process_sp->WriteMemory (addr, src, src_len, sb_error.ref()); } else { if (log) log->Printf ("SBProcess(%p)::WriteMemory() => error: process is running", static_cast(process_sp.get())); sb_error.SetErrorString("process is running"); } } if (log) { SBStream sstr; sb_error.GetDescription (sstr); log->Printf ("SBProcess(%p)::WriteMemory (addr=0x%" PRIx64 ", src=%p, src_len=%" PRIu64 ", SBError (%p): %s) => %" PRIu64, static_cast(process_sp.get()), addr, static_cast(src), static_cast(src_len), static_cast(sb_error.get()), sstr.GetData(), static_cast(bytes_written)); } return bytes_written; } bool SBProcess::GetDescription (SBStream &description) { Stream &strm = description.ref(); ProcessSP process_sp(GetSP()); if (process_sp) { char path[PATH_MAX]; GetTarget().GetExecutable().GetPath (path, sizeof(path)); Module *exe_module = process_sp->GetTarget().GetExecutableModulePointer(); const char *exe_name = NULL; if (exe_module) exe_name = exe_module->GetFileSpec().GetFilename().AsCString(); strm.Printf ("SBProcess: pid = %" PRIu64 ", state = %s, threads = %d%s%s", process_sp->GetID(), lldb_private::StateAsCString (GetState()), GetNumThreads(), exe_name ? ", executable = " : "", exe_name ? exe_name : ""); } else strm.PutCString ("No value"); return true; } uint32_t SBProcess::GetNumSupportedHardwareWatchpoints (lldb::SBError &sb_error) const { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); uint32_t num = 0; ProcessSP process_sp(GetSP()); if (process_sp) { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); sb_error.SetError(process_sp->GetWatchpointSupportInfo (num)); if (log) log->Printf ("SBProcess(%p)::GetNumSupportedHardwareWatchpoints () => %u", static_cast(process_sp.get()), num); } else { sb_error.SetErrorString ("SBProcess is invalid"); } return num; } uint32_t SBProcess::LoadImage (lldb::SBFileSpec &sb_image_spec, lldb::SBError &sb_error) { ProcessSP process_sp(GetSP()); if (process_sp) { Process::StopLocker stop_locker; if (stop_locker.TryLock(&process_sp->GetRunLock())) { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); return process_sp->LoadImage (*sb_image_spec, sb_error.ref()); } else { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) log->Printf ("SBProcess(%p)::LoadImage() => error: process is running", static_cast(process_sp.get())); sb_error.SetErrorString("process is running"); } } return LLDB_INVALID_IMAGE_TOKEN; } lldb::SBError SBProcess::UnloadImage (uint32_t image_token) { lldb::SBError sb_error; ProcessSP process_sp(GetSP()); if (process_sp) { Process::StopLocker stop_locker; if (stop_locker.TryLock(&process_sp->GetRunLock())) { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); sb_error.SetError (process_sp->UnloadImage (image_token)); } else { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) log->Printf ("SBProcess(%p)::UnloadImage() => error: process is running", static_cast(process_sp.get())); sb_error.SetErrorString("process is running"); } } else sb_error.SetErrorString("invalid process"); return sb_error; } lldb::SBError SBProcess::SendEventData (const char *event_data) { lldb::SBError sb_error; ProcessSP process_sp(GetSP()); if (process_sp) { Process::StopLocker stop_locker; if (stop_locker.TryLock(&process_sp->GetRunLock())) { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); sb_error.SetError (process_sp->SendEventData (event_data)); } else { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) log->Printf ("SBProcess(%p)::SendEventData() => error: process is running", static_cast(process_sp.get())); sb_error.SetErrorString("process is running"); } } else sb_error.SetErrorString("invalid process"); return sb_error; } uint32_t SBProcess::GetNumExtendedBacktraceTypes () { ProcessSP process_sp(GetSP()); if (process_sp && process_sp->GetSystemRuntime()) { SystemRuntime *runtime = process_sp->GetSystemRuntime(); return runtime->GetExtendedBacktraceTypes().size(); } return 0; } const char * SBProcess::GetExtendedBacktraceTypeAtIndex (uint32_t idx) { ProcessSP process_sp(GetSP()); if (process_sp && process_sp->GetSystemRuntime()) { SystemRuntime *runtime = process_sp->GetSystemRuntime(); const std::vector &names = runtime->GetExtendedBacktraceTypes(); if (idx < names.size()) { return names[idx].AsCString(); } else { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) log->Printf("SBProcess(%p)::GetExtendedBacktraceTypeAtIndex() => error: requested extended backtrace name out of bounds", static_cast(process_sp.get())); } } return NULL; } SBThreadCollection SBProcess::GetHistoryThreads (addr_t addr) { ProcessSP process_sp(GetSP()); SBThreadCollection threads; if (process_sp) { threads = SBThreadCollection(process_sp->GetHistoryThreads(addr)); } return threads; } bool SBProcess::IsInstrumentationRuntimePresent(InstrumentationRuntimeType type) { ProcessSP process_sp(GetSP()); if (! process_sp) return false; InstrumentationRuntimeSP runtime_sp = process_sp->GetInstrumentationRuntime(type); if (! runtime_sp.get()) return false; return runtime_sp->IsActive(); }