| //===-- SBProcess.cpp -----------------------------------------------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "lldb/API/SBProcess.h" | |
| #include "lldb/Host/File.h" | |
| #include "lldb/Utility/Instrumentation.h" | |
| #include <cinttypes> | |
| #include "lldb/lldb-defines.h" | |
| #include "lldb/lldb-types.h" | |
| #include "lldb/Core/AddressRangeListImpl.h" | |
| #include "lldb/Core/Debugger.h" | |
| #include "lldb/Core/Module.h" | |
| #include "lldb/Core/PluginManager.h" | |
| #include "lldb/Core/StructuredDataImpl.h" | |
| #include "lldb/Host/StreamFile.h" | |
| #include "lldb/Target/MemoryRegionInfo.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" | |
| #include "lldb/Utility/AddressSpace.h" | |
| #include "lldb/Utility/Args.h" | |
| #include "lldb/Utility/LLDBLog.h" | |
| #include "lldb/Utility/ProcessInfo.h" | |
| #include "lldb/Utility/State.h" | |
| #include "lldb/Utility/Stream.h" | |
| #include "lldb/API/SBAddress.h" | |
| #include "lldb/API/SBBroadcaster.h" | |
| #include "lldb/API/SBCommandReturnObject.h" | |
| #include "lldb/API/SBDebugger.h" | |
| #include "lldb/API/SBEvent.h" | |
| #include "lldb/API/SBFile.h" | |
| #include "lldb/API/SBFileSpec.h" | |
| #include "lldb/API/SBMemoryRegionInfo.h" | |
| #include "lldb/API/SBMemoryRegionInfoList.h" | |
| #include "lldb/API/SBSaveCoreOptions.h" | |
| #include "lldb/API/SBScriptObject.h" | |
| #include "lldb/API/SBStream.h" | |
| #include "lldb/API/SBStringList.h" | |
| #include "lldb/API/SBStructuredData.h" | |
| #include "lldb/API/SBThread.h" | |
| #include "lldb/API/SBThreadCollection.h" | |
| #include "lldb/API/SBTrace.h" | |
| #include "lldb/API/SBUnixSignals.h" | |
| using namespace lldb; | |
| using namespace lldb_private; | |
| SBProcess::SBProcess() { LLDB_INSTRUMENT_VA(this); } | |
| // SBProcess constructor | |
| SBProcess::SBProcess(const SBProcess &rhs) : m_opaque_wp(rhs.m_opaque_wp) { | |
| LLDB_INSTRUMENT_VA(this, rhs); | |
| } | |
| SBProcess::SBProcess(const lldb::ProcessSP &process_sp) | |
| : m_opaque_wp(process_sp) { | |
| LLDB_INSTRUMENT_VA(this, process_sp); | |
| } | |
| const SBProcess &SBProcess::operator=(const SBProcess &rhs) { | |
| LLDB_INSTRUMENT_VA(this, rhs); | |
| if (this != &rhs) | |
| m_opaque_wp = rhs.m_opaque_wp; | |
| return *this; | |
| } | |
| // Destructor | |
| SBProcess::~SBProcess() = default; | |
| const char *SBProcess::GetBroadcasterClassName() { | |
| LLDB_INSTRUMENT(); | |
| return ConstString(Process::GetStaticBroadcasterClass()).AsCString(nullptr); | |
| } | |
| const char *SBProcess::GetPluginName() { | |
| LLDB_INSTRUMENT_VA(this); | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| return ConstString(process_sp->GetPluginName()).GetCString(); | |
| } | |
| return "<Unknown>"; | |
| } | |
| const char *SBProcess::GetShortPluginName() { | |
| LLDB_INSTRUMENT_VA(this); | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| return ConstString(process_sp->GetPluginName()).GetCString(); | |
| } | |
| return "<Unknown>"; | |
| } | |
| 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() { | |
| LLDB_INSTRUMENT_VA(this); | |
| m_opaque_wp.reset(); | |
| } | |
| bool SBProcess::IsValid() const { | |
| LLDB_INSTRUMENT_VA(this); | |
| return this->operator bool(); | |
| } | |
| SBProcess::operator bool() const { | |
| LLDB_INSTRUMENT_VA(this); | |
| 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) { | |
| LLDB_INSTRUMENT_VA(this, argv, envp, stdin_path, stdout_path, stderr_path, | |
| working_directory, launch_flags, stop_at_entry, error); | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| if (process_sp->GetState() == eStateConnected) { | |
| if (stop_at_entry) | |
| launch_flags |= eLaunchFlagStopAtEntry; | |
| ProcessLaunchInfo launch_info(FileSpec(stdin_path), FileSpec(stdout_path), | |
| FileSpec(stderr_path), | |
| FileSpec(working_directory), 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.GetEnvironment() = Environment(envp); | |
| error.SetError(process_sp->Launch(launch_info)); | |
| } else { | |
| error = Status::FromErrorString( | |
| "must be in eStateConnected to call RemoteLaunch"); | |
| } | |
| } else { | |
| error = Status::FromErrorString("unable to attach pid"); | |
| } | |
| return error.Success(); | |
| } | |
| bool SBProcess::RemoteAttachToProcessWithID(lldb::pid_t pid, | |
| lldb::SBError &error) { | |
| LLDB_INSTRUMENT_VA(this, pid, error); | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| if (process_sp->GetState() == eStateConnected) { | |
| ProcessAttachInfo attach_info; | |
| attach_info.SetProcessID(pid); | |
| error.SetError(process_sp->Attach(attach_info)); | |
| } else { | |
| error = Status::FromErrorString( | |
| "must be in eStateConnected to call RemoteAttachToProcessWithID"); | |
| } | |
| } else { | |
| error = Status::FromErrorString("unable to attach pid"); | |
| } | |
| return error.Success(); | |
| } | |
| uint32_t SBProcess::GetNumThreads() { | |
| LLDB_INSTRUMENT_VA(this); | |
| uint32_t num_threads = 0; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| Process::StopLocker stop_locker; | |
| if (stop_locker.TryLock(&process_sp->GetRunLock())) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| num_threads = process_sp->GetThreadList().GetSize(); | |
| } | |
| } | |
| return num_threads; | |
| } | |
| SBThread SBProcess::GetSelectedThread() const { | |
| LLDB_INSTRUMENT_VA(this); | |
| SBThread sb_thread; | |
| ThreadSP thread_sp; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| thread_sp = process_sp->GetThreadList().GetSelectedThread(); | |
| sb_thread.SetThread(thread_sp); | |
| } | |
| return sb_thread; | |
| } | |
| SBThread SBProcess::CreateOSPluginThread(lldb::tid_t tid, | |
| lldb::addr_t context) { | |
| LLDB_INSTRUMENT_VA(this, tid, context); | |
| SBThread sb_thread; | |
| ThreadSP thread_sp; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| thread_sp = process_sp->CreateOSPluginThread(tid, context); | |
| sb_thread.SetThread(thread_sp); | |
| } | |
| return sb_thread; | |
| } | |
| SBTarget SBProcess::GetTarget() const { | |
| LLDB_INSTRUMENT_VA(this); | |
| 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); | |
| } | |
| return sb_target; | |
| } | |
| size_t SBProcess::PutSTDIN(const char *src, size_t src_len) { | |
| LLDB_INSTRUMENT_VA(this, src, src_len); | |
| size_t ret_val = 0; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| Status error; | |
| ret_val = process_sp->PutSTDIN(src, src_len, error); | |
| } | |
| return ret_val; | |
| } | |
| size_t SBProcess::GetSTDOUT(char *dst, size_t dst_len) const { | |
| LLDB_INSTRUMENT_VA(this, dst, dst_len); | |
| size_t bytes_read = 0; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| Status error; | |
| bytes_read = process_sp->GetSTDOUT(dst, dst_len, error); | |
| } | |
| return bytes_read; | |
| } | |
| size_t SBProcess::GetSTDERR(char *dst, size_t dst_len) const { | |
| LLDB_INSTRUMENT_VA(this, dst, dst_len); | |
| size_t bytes_read = 0; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| Status error; | |
| bytes_read = process_sp->GetSTDERR(dst, dst_len, error); | |
| } | |
| return bytes_read; | |
| } | |
| size_t SBProcess::GetAsyncProfileData(char *dst, size_t dst_len) const { | |
| LLDB_INSTRUMENT_VA(this, dst, dst_len); | |
| size_t bytes_read = 0; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| Status error; | |
| bytes_read = process_sp->GetAsyncProfileData(dst, dst_len, error); | |
| } | |
| return bytes_read; | |
| } | |
| void SBProcess::ReportEventState(const SBEvent &event, SBFile out) const { | |
| LLDB_INSTRUMENT_VA(this, event, out); | |
| return ReportEventState(event, out.m_opaque_sp); | |
| } | |
| void SBProcess::ReportEventState(const SBEvent &event, FILE *out) const { | |
| LLDB_INSTRUMENT_VA(this, event, out); | |
| FileSP outfile = | |
| std::make_shared<NativeFile>(out, File::eOpenOptionWriteOnly, false); | |
| return ReportEventState(event, outfile); | |
| } | |
| void SBProcess::ReportEventState(const SBEvent &event, FileSP out) const { | |
| LLDB_INSTRUMENT_VA(this, event, out); | |
| if (!out || !out->IsValid()) | |
| return; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| StreamFile stream(out); | |
| const StateType event_state = SBProcess::GetStateFromEvent(event); | |
| stream.Printf("Process %" PRIu64 " %s\n", process_sp->GetID(), | |
| SBDebugger::StateAsCString(event_state)); | |
| } | |
| } | |
| void SBProcess::AppendEventStateReport(const SBEvent &event, | |
| SBCommandReturnObject &result) { | |
| LLDB_INSTRUMENT_VA(this, event, 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) { | |
| LLDB_INSTRUMENT_VA(this, thread); | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| return process_sp->GetThreadList().SetSelectedThreadByID( | |
| thread.GetThreadID()); | |
| } | |
| return false; | |
| } | |
| bool SBProcess::SetSelectedThreadByID(lldb::tid_t tid) { | |
| LLDB_INSTRUMENT_VA(this, tid); | |
| bool ret_val = false; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| ret_val = process_sp->GetThreadList().SetSelectedThreadByID(tid); | |
| } | |
| return ret_val; | |
| } | |
| bool SBProcess::SetSelectedThreadByIndexID(uint32_t index_id) { | |
| LLDB_INSTRUMENT_VA(this, index_id); | |
| bool ret_val = false; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| ret_val = process_sp->GetThreadList().SetSelectedThreadByIndexID(index_id); | |
| } | |
| return ret_val; | |
| } | |
| SBThread SBProcess::GetThreadAtIndex(size_t index) { | |
| LLDB_INSTRUMENT_VA(this, index); | |
| SBThread sb_thread; | |
| ThreadSP thread_sp; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| Process::StopLocker stop_locker; | |
| if (stop_locker.TryLock(&process_sp->GetRunLock())) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| thread_sp = process_sp->GetThreadList().GetThreadAtIndex(index, false); | |
| sb_thread.SetThread(thread_sp); | |
| } | |
| } | |
| return sb_thread; | |
| } | |
| uint32_t SBProcess::GetNumQueues() { | |
| LLDB_INSTRUMENT_VA(this); | |
| uint32_t num_queues = 0; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| Process::StopLocker stop_locker; | |
| if (stop_locker.TryLock(&process_sp->GetRunLock())) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| num_queues = process_sp->GetQueueList().GetSize(); | |
| } | |
| } | |
| return num_queues; | |
| } | |
| SBQueue SBProcess::GetQueueAtIndex(size_t index) { | |
| LLDB_INSTRUMENT_VA(this, index); | |
| SBQueue sb_queue; | |
| QueueSP queue_sp; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| Process::StopLocker stop_locker; | |
| if (stop_locker.TryLock(&process_sp->GetRunLock())) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| queue_sp = process_sp->GetQueueList().GetQueueAtIndex(index); | |
| sb_queue.SetQueue(queue_sp); | |
| } | |
| } | |
| return sb_queue; | |
| } | |
| uint32_t SBProcess::GetStopID(bool include_expression_stops) { | |
| LLDB_INSTRUMENT_VA(this, include_expression_stops); | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| if (include_expression_stops) | |
| return process_sp->GetStopID(); | |
| else | |
| return process_sp->GetLastNaturalStopID(); | |
| } | |
| return 0; | |
| } | |
| SBEvent SBProcess::GetStopEventForStopID(uint32_t stop_id) { | |
| LLDB_INSTRUMENT_VA(this, stop_id); | |
| SBEvent sb_event; | |
| EventSP event_sp; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| event_sp = process_sp->GetStopEventForStopID(stop_id); | |
| sb_event.reset(event_sp); | |
| } | |
| return sb_event; | |
| } | |
| void SBProcess::ForceScriptedState(StateType new_state) { | |
| LLDB_INSTRUMENT_VA(this, new_state); | |
| if (ProcessSP process_sp = GetSP()) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| process_sp->ForceScriptedState(new_state); | |
| } | |
| } | |
| StateType SBProcess::GetState() { | |
| LLDB_INSTRUMENT_VA(this); | |
| StateType ret_val = eStateInvalid; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| ret_val = process_sp->GetState(); | |
| } | |
| return ret_val; | |
| } | |
| int SBProcess::GetExitStatus() { | |
| LLDB_INSTRUMENT_VA(this); | |
| int exit_status = 0; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| exit_status = process_sp->GetExitStatus(); | |
| } | |
| return exit_status; | |
| } | |
| const char *SBProcess::GetExitDescription() { | |
| LLDB_INSTRUMENT_VA(this); | |
| ProcessSP process_sp(GetSP()); | |
| if (!process_sp) | |
| return nullptr; | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| return ConstString(process_sp->GetExitDescription()).GetCString(); | |
| } | |
| lldb::pid_t SBProcess::GetProcessID() { | |
| LLDB_INSTRUMENT_VA(this); | |
| lldb::pid_t ret_val = LLDB_INVALID_PROCESS_ID; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) | |
| ret_val = process_sp->GetID(); | |
| return ret_val; | |
| } | |
| uint32_t SBProcess::GetUniqueID() { | |
| LLDB_INSTRUMENT_VA(this); | |
| uint32_t ret_val = 0; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) | |
| ret_val = process_sp->GetUniqueID(); | |
| return ret_val; | |
| } | |
| ByteOrder SBProcess::GetByteOrder() const { | |
| LLDB_INSTRUMENT_VA(this); | |
| ByteOrder byteOrder = eByteOrderInvalid; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) | |
| byteOrder = process_sp->GetTarget().GetArchitecture().GetByteOrder(); | |
| return byteOrder; | |
| } | |
| uint32_t SBProcess::GetAddressByteSize() const { | |
| LLDB_INSTRUMENT_VA(this); | |
| uint32_t size = 0; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) | |
| size = process_sp->GetTarget().GetArchitecture().GetAddressByteSize(); | |
| return size; | |
| } | |
| SBError SBProcess::Continue() { | |
| LLDB_INSTRUMENT_VA(this); | |
| SBError sb_error; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| if (process_sp->GetTarget().GetDebugger().GetAsyncExecution()) | |
| sb_error.ref() = process_sp->Resume(); | |
| else | |
| sb_error.ref() = process_sp->ResumeSynchronous(nullptr); | |
| } else | |
| sb_error = Status::FromErrorString("SBProcess is invalid"); | |
| return sb_error; | |
| } | |
| SBError SBProcess::ContinueInDirection(RunDirection direction) { | |
| if (ProcessSP process_sp = GetSP()) { | |
| if (direction == RunDirection::eRunReverse && | |
| !process_sp->SupportsReverseDirection()) | |
| return Status::FromErrorStringWithFormatv( | |
| "{0} does not support reverse execution of processes", | |
| GetPluginName()); | |
| process_sp->SetBaseDirection(direction); | |
| } | |
| return Continue(); | |
| } | |
| SBError SBProcess::Destroy() { | |
| LLDB_INSTRUMENT_VA(this); | |
| SBError sb_error; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| sb_error.SetError(process_sp->Destroy(false)); | |
| } else | |
| sb_error = Status::FromErrorString("SBProcess is invalid"); | |
| return sb_error; | |
| } | |
| SBError SBProcess::Stop() { | |
| LLDB_INSTRUMENT_VA(this); | |
| SBError sb_error; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| sb_error.SetError(process_sp->Halt()); | |
| } else | |
| sb_error = Status::FromErrorString("SBProcess is invalid"); | |
| return sb_error; | |
| } | |
| SBError SBProcess::Kill() { | |
| LLDB_INSTRUMENT_VA(this); | |
| SBError sb_error; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| sb_error.SetError(process_sp->Destroy(true)); | |
| } else | |
| sb_error = Status::FromErrorString("SBProcess is invalid"); | |
| return sb_error; | |
| } | |
| SBError SBProcess::Detach() { | |
| LLDB_INSTRUMENT_VA(this); | |
| // FIXME: This should come from a process default. | |
| bool keep_stopped = false; | |
| return Detach(keep_stopped); | |
| } | |
| SBError SBProcess::Detach(bool keep_stopped) { | |
| LLDB_INSTRUMENT_VA(this, keep_stopped); | |
| SBError sb_error; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| sb_error.SetError(process_sp->Detach(keep_stopped)); | |
| } else | |
| sb_error = Status::FromErrorString("SBProcess is invalid"); | |
| return sb_error; | |
| } | |
| SBError SBProcess::Signal(int signo) { | |
| LLDB_INSTRUMENT_VA(this, signo); | |
| SBError sb_error; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| sb_error.SetError(process_sp->Signal(signo)); | |
| } else | |
| sb_error = Status::FromErrorString("SBProcess is invalid"); | |
| return sb_error; | |
| } | |
| SBUnixSignals SBProcess::GetUnixSignals() { | |
| LLDB_INSTRUMENT_VA(this); | |
| if (auto process_sp = GetSP()) | |
| return SBUnixSignals{process_sp}; | |
| return SBUnixSignals{}; | |
| } | |
| void SBProcess::SendAsyncInterrupt() { | |
| LLDB_INSTRUMENT_VA(this); | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| process_sp->SendAsyncInterrupt(); | |
| } | |
| } | |
| SBThread SBProcess::GetThreadByID(tid_t tid) { | |
| LLDB_INSTRUMENT_VA(this, 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()); | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| thread_sp = process_sp->GetThreadList().FindThreadByID(tid, can_update); | |
| sb_thread.SetThread(thread_sp); | |
| } | |
| return sb_thread; | |
| } | |
| SBThread SBProcess::GetThreadByIndexID(uint32_t index_id) { | |
| LLDB_INSTRUMENT_VA(this, 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()); | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| thread_sp = | |
| process_sp->GetThreadList().FindThreadByIndexID(index_id, can_update); | |
| sb_thread.SetThread(thread_sp); | |
| } | |
| return sb_thread; | |
| } | |
| StateType SBProcess::GetStateFromEvent(const SBEvent &event) { | |
| LLDB_INSTRUMENT_VA(event); | |
| StateType ret_val = Process::ProcessEventData::GetStateFromEvent(event.get()); | |
| return ret_val; | |
| } | |
| bool SBProcess::GetRestartedFromEvent(const SBEvent &event) { | |
| LLDB_INSTRUMENT_VA(event); | |
| bool ret_val = Process::ProcessEventData::GetRestartedFromEvent(event.get()); | |
| return ret_val; | |
| } | |
| size_t SBProcess::GetNumRestartedReasonsFromEvent(const lldb::SBEvent &event) { | |
| LLDB_INSTRUMENT_VA(event); | |
| return Process::ProcessEventData::GetNumRestartedReasons(event.get()); | |
| } | |
| const char * | |
| SBProcess::GetRestartedReasonAtIndexFromEvent(const lldb::SBEvent &event, | |
| size_t idx) { | |
| LLDB_INSTRUMENT_VA(event, idx); | |
| return ConstString(Process::ProcessEventData::GetRestartedReasonAtIndex( | |
| event.get(), idx)) | |
| .GetCString(); | |
| } | |
| SBProcess SBProcess::GetProcessFromEvent(const SBEvent &event) { | |
| LLDB_INSTRUMENT_VA(event); | |
| ProcessSP process_sp = | |
| Process::ProcessEventData::GetProcessFromEvent(event.get()); | |
| if (!process_sp) { | |
| // StructuredData events also know the process they come from. Try that. | |
| process_sp = EventDataStructuredData::GetProcessFromEvent(event.get()); | |
| } | |
| return SBProcess(process_sp); | |
| } | |
| bool SBProcess::GetInterruptedFromEvent(const SBEvent &event) { | |
| LLDB_INSTRUMENT_VA(event); | |
| return Process::ProcessEventData::GetInterruptedFromEvent(event.get()); | |
| } | |
| lldb::SBStructuredData | |
| SBProcess::GetStructuredDataFromEvent(const lldb::SBEvent &event) { | |
| LLDB_INSTRUMENT_VA(event); | |
| return SBStructuredData(event.GetSP()); | |
| } | |
| bool SBProcess::EventIsProcessEvent(const SBEvent &event) { | |
| LLDB_INSTRUMENT_VA(event); | |
| return Process::ProcessEventData::GetEventDataFromEvent(event.get()) != | |
| nullptr; | |
| } | |
| bool SBProcess::EventIsStructuredDataEvent(const lldb::SBEvent &event) { | |
| LLDB_INSTRUMENT_VA(event); | |
| EventSP event_sp = event.GetSP(); | |
| EventData *event_data = event_sp ? event_sp->GetData() : nullptr; | |
| return event_data && (event_data->GetFlavor() == | |
| EventDataStructuredData::GetFlavorString()); | |
| } | |
| SBBroadcaster SBProcess::GetBroadcaster() const { | |
| LLDB_INSTRUMENT_VA(this); | |
| ProcessSP process_sp(GetSP()); | |
| SBBroadcaster broadcaster(process_sp.get(), false); | |
| return broadcaster; | |
| } | |
| const char *SBProcess::GetBroadcasterClass() { | |
| LLDB_INSTRUMENT(); | |
| return ConstString(Process::GetStaticBroadcasterClass()).AsCString(nullptr); | |
| } | |
| lldb::SBAddressRangeList SBProcess::FindRangesInMemory( | |
| const void *buf, uint64_t size, const SBAddressRangeList &ranges, | |
| uint32_t alignment, uint32_t max_matches, SBError &error) { | |
| LLDB_INSTRUMENT_VA(this, buf, size, ranges, alignment, max_matches, error); | |
| lldb::SBAddressRangeList matches; | |
| ProcessSP process_sp(GetSP()); | |
| if (!process_sp) { | |
| error = Status::FromErrorString("SBProcess is invalid"); | |
| return matches; | |
| } | |
| Process::StopLocker stop_locker; | |
| if (!stop_locker.TryLock(&process_sp->GetRunLock())) { | |
| error = Status::FromErrorString("process is running"); | |
| return matches; | |
| } | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| matches.m_opaque_up->ref() = process_sp->FindRangesInMemory( | |
| reinterpret_cast<const uint8_t *>(buf), size, ranges.ref().ref(), | |
| alignment, max_matches, error.ref()); | |
| return matches; | |
| } | |
| lldb::addr_t SBProcess::FindInMemory(const void *buf, uint64_t size, | |
| const SBAddressRange &range, | |
| uint32_t alignment, SBError &error) { | |
| LLDB_INSTRUMENT_VA(this, buf, size, range, alignment, error); | |
| ProcessSP process_sp(GetSP()); | |
| if (!process_sp) { | |
| error = Status::FromErrorString("SBProcess is invalid"); | |
| return LLDB_INVALID_ADDRESS; | |
| } | |
| Process::StopLocker stop_locker; | |
| if (!stop_locker.TryLock(&process_sp->GetRunLock())) { | |
| error = Status::FromErrorString("process is running"); | |
| return LLDB_INVALID_ADDRESS; | |
| } | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| return process_sp->FindInMemory(reinterpret_cast<const uint8_t *>(buf), size, | |
| range.ref(), alignment, error.ref()); | |
| } | |
| size_t SBProcess::ReadMemory(addr_t addr, void *dst, size_t dst_len, | |
| SBError &sb_error) { | |
| LLDB_INSTRUMENT_VA(this, addr, dst, dst_len, sb_error); | |
| if (!dst) { | |
| sb_error = Status::FromErrorStringWithFormat( | |
| "no buffer provided to read %zu bytes into", dst_len); | |
| return 0; | |
| } | |
| size_t bytes_read = 0; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| Process::StopLocker stop_locker; | |
| if (stop_locker.TryLock(&process_sp->GetRunLock())) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| bytes_read = process_sp->ReadMemory(addr, dst, dst_len, sb_error.ref()); | |
| } else { | |
| sb_error = Status::FromErrorString("process is running"); | |
| } | |
| } else { | |
| sb_error = Status::FromErrorString("SBProcess is invalid"); | |
| } | |
| return bytes_read; | |
| } | |
| size_t SBProcess::ReadMemory(SBProcessAddress process_addr, void *dst, | |
| size_t dst_len, SBError &sb_error) { | |
| LLDB_INSTRUMENT_VA(this, process_addr, dst, dst_len, sb_error); | |
| if (!dst) { | |
| sb_error = Status::FromErrorStringWithFormat( | |
| "no buffer provided to read %zu bytes into", dst_len); | |
| return 0; | |
| } | |
| ProcessSP process_sp(GetSP()); | |
| if (!process_sp) { | |
| sb_error = Status::FromErrorString("SBProcess is invalid"); | |
| return 0; | |
| } | |
| Process::StopLocker stop_locker; | |
| if (!stop_locker.TryLock(&process_sp->GetRunLock())) { | |
| sb_error = Status::FromErrorString("process is running"); | |
| return 0; | |
| } | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| return process_sp->ReadMemory(process_addr.ref(), dst, dst_len, | |
| sb_error.ref()); | |
| } | |
| lldb::addr_space_t SBProcess::GetAddressSpaceID(const char *name, | |
| SBError &sb_error) { | |
| LLDB_INSTRUMENT_VA(this, name, sb_error); | |
| ProcessSP process_sp(GetSP()); | |
| if (!process_sp) { | |
| sb_error = Status::FromErrorString("SBProcess is invalid"); | |
| return LLDB_INVALID_ADDRESS_SPACE_ID; | |
| } | |
| if (!name || !name[0]) { | |
| sb_error = Status::FromErrorString("an address space name is required"); | |
| return LLDB_INVALID_ADDRESS_SPACE_ID; | |
| } | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| llvm::Expected<AddressSpaceInfo> info = process_sp->GetAddressSpaceInfo(name); | |
| if (!info) { | |
| sb_error = Status::FromError(info.takeError()); | |
| return LLDB_INVALID_ADDRESS_SPACE_ID; | |
| } | |
| sb_error.Clear(); | |
| return info->space_id; | |
| } | |
| size_t SBProcess::ReadCStringFromMemory(addr_t addr, void *buf, size_t size, | |
| lldb::SBError &sb_error) { | |
| LLDB_INSTRUMENT_VA(this, addr, buf, size, 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())) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| bytes_read = process_sp->ReadCStringFromMemory(addr, (char *)buf, size, | |
| sb_error.ref()); | |
| } else { | |
| sb_error = Status::FromErrorString("process is running"); | |
| } | |
| } else { | |
| sb_error = Status::FromErrorString("SBProcess is invalid"); | |
| } | |
| return bytes_read; | |
| } | |
| uint64_t SBProcess::ReadUnsignedFromMemory(addr_t addr, uint32_t byte_size, | |
| lldb::SBError &sb_error) { | |
| LLDB_INSTRUMENT_VA(this, addr, byte_size, sb_error); | |
| uint64_t value = 0; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| Process::StopLocker stop_locker; | |
| if (stop_locker.TryLock(&process_sp->GetRunLock())) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| value = process_sp->ReadUnsignedIntegerFromMemory(addr, byte_size, 0, | |
| sb_error.ref()); | |
| } else { | |
| sb_error = Status::FromErrorString("process is running"); | |
| } | |
| } else { | |
| sb_error = Status::FromErrorString("SBProcess is invalid"); | |
| } | |
| return value; | |
| } | |
| lldb::addr_t SBProcess::ReadPointerFromMemory(addr_t addr, | |
| lldb::SBError &sb_error) { | |
| LLDB_INSTRUMENT_VA(this, addr, 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())) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| if (llvm::Expected<lldb::addr_t> ptr_or_err = | |
| process_sp->ReadPointerFromMemory(addr)) | |
| ptr = *ptr_or_err; | |
| else | |
| sb_error = Status::FromError(ptr_or_err.takeError()); | |
| } else { | |
| sb_error = Status::FromErrorString("process is running"); | |
| } | |
| } else { | |
| sb_error = Status::FromErrorString("SBProcess is invalid"); | |
| } | |
| return ptr; | |
| } | |
| size_t SBProcess::WriteMemory(addr_t addr, const void *src, size_t src_len, | |
| SBError &sb_error) { | |
| LLDB_INSTRUMENT_VA(this, addr, src, src_len, sb_error); | |
| size_t bytes_written = 0; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| Process::StopLocker stop_locker; | |
| if (stop_locker.TryLock(&process_sp->GetRunLock())) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| bytes_written = | |
| process_sp->WriteMemory(addr, src, src_len, sb_error.ref()); | |
| } else { | |
| sb_error = Status::FromErrorString("process is running"); | |
| } | |
| } | |
| return bytes_written; | |
| } | |
| void SBProcess::GetStatus(SBStream &status) { | |
| LLDB_INSTRUMENT_VA(this, status); | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) | |
| process_sp->GetStatus(status.ref()); | |
| } | |
| bool SBProcess::GetDescription(SBStream &description) { | |
| LLDB_INSTRUMENT_VA(this, 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 = nullptr; | |
| if (exe_module) | |
| exe_name = ConstString(exe_module->GetFileSpec().GetFilename()) | |
| .AsCString(nullptr); | |
| 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; | |
| } | |
| SBStructuredData SBProcess::GetExtendedCrashInformation() { | |
| LLDB_INSTRUMENT_VA(this); | |
| SBStructuredData data; | |
| ProcessSP process_sp(GetSP()); | |
| if (!process_sp) | |
| return data; | |
| PlatformSP platform_sp = process_sp->GetTarget().GetPlatform(); | |
| if (!platform_sp) | |
| return data; | |
| auto expected_data = | |
| platform_sp->FetchExtendedCrashInformation(*process_sp.get()); | |
| if (!expected_data) { | |
| LLDB_LOG_ERROR(GetLog(LLDBLog::API), expected_data.takeError(), | |
| "FetchExtendedCrashInformation failed: {0}"); | |
| return data; | |
| } | |
| StructuredData::ObjectSP fetched_data = *expected_data; | |
| data.m_impl_up->SetObjectSP(fetched_data); | |
| return data; | |
| } | |
| uint32_t | |
| SBProcess::GetNumSupportedHardwareWatchpoints(lldb::SBError &sb_error) const { | |
| LLDB_INSTRUMENT_VA(this, sb_error); | |
| uint32_t num = 0; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| std::optional<uint32_t> actual_num = process_sp->GetWatchpointSlotCount(); | |
| if (actual_num) { | |
| num = *actual_num; | |
| } else { | |
| sb_error = | |
| Status::FromErrorString("Unable to determine number of watchpoints"); | |
| } | |
| } else { | |
| sb_error = Status::FromErrorString("SBProcess is invalid"); | |
| } | |
| return num; | |
| } | |
| uint32_t SBProcess::LoadImage(lldb::SBFileSpec &sb_remote_image_spec, | |
| lldb::SBError &sb_error) { | |
| LLDB_INSTRUMENT_VA(this, sb_remote_image_spec, sb_error); | |
| return LoadImage(SBFileSpec(), sb_remote_image_spec, sb_error); | |
| } | |
| uint32_t SBProcess::LoadImage(const lldb::SBFileSpec &sb_local_image_spec, | |
| const lldb::SBFileSpec &sb_remote_image_spec, | |
| lldb::SBError &sb_error) { | |
| LLDB_INSTRUMENT_VA(this, sb_local_image_spec, sb_remote_image_spec, sb_error); | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| Process::StopLocker stop_locker; | |
| if (stop_locker.TryLock(&process_sp->GetRunLock())) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| PlatformSP platform_sp = process_sp->GetTarget().GetPlatform(); | |
| return platform_sp->LoadImage(process_sp.get(), *sb_local_image_spec, | |
| *sb_remote_image_spec, sb_error.ref()); | |
| } else { | |
| sb_error = Status::FromErrorString("process is running"); | |
| } | |
| } else { | |
| sb_error = Status::FromErrorString("process is invalid"); | |
| } | |
| return LLDB_INVALID_IMAGE_TOKEN; | |
| } | |
| uint32_t SBProcess::LoadImageUsingPaths(const lldb::SBFileSpec &image_spec, | |
| SBStringList &paths, | |
| lldb::SBFileSpec &loaded_path, | |
| lldb::SBError &error) { | |
| LLDB_INSTRUMENT_VA(this, image_spec, paths, loaded_path, error); | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| Process::StopLocker stop_locker; | |
| if (stop_locker.TryLock(&process_sp->GetRunLock())) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| PlatformSP platform_sp = process_sp->GetTarget().GetPlatform(); | |
| size_t num_paths = paths.GetSize(); | |
| std::vector<std::string> paths_vec; | |
| paths_vec.reserve(num_paths); | |
| for (size_t i = 0; i < num_paths; i++) | |
| paths_vec.push_back(paths.GetStringAtIndex(i)); | |
| FileSpec loaded_spec; | |
| uint32_t token = platform_sp->LoadImageUsingPaths( | |
| process_sp.get(), *image_spec, paths_vec, error.ref(), &loaded_spec); | |
| if (token != LLDB_INVALID_IMAGE_TOKEN) | |
| loaded_path = loaded_spec; | |
| return token; | |
| } else { | |
| error = Status::FromErrorString("process is running"); | |
| } | |
| } else { | |
| error = Status::FromErrorString("process is invalid"); | |
| } | |
| return LLDB_INVALID_IMAGE_TOKEN; | |
| } | |
| lldb::SBError SBProcess::UnloadImage(uint32_t image_token) { | |
| LLDB_INSTRUMENT_VA(this, image_token); | |
| lldb::SBError sb_error; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| Process::StopLocker stop_locker; | |
| if (stop_locker.TryLock(&process_sp->GetRunLock())) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| PlatformSP platform_sp = process_sp->GetTarget().GetPlatform(); | |
| sb_error.SetError( | |
| platform_sp->UnloadImage(process_sp.get(), image_token)); | |
| } else { | |
| sb_error = Status::FromErrorString("process is running"); | |
| } | |
| } else | |
| sb_error = Status::FromErrorString("invalid process"); | |
| return sb_error; | |
| } | |
| lldb::SBError SBProcess::SendEventData(const char *event_data) { | |
| LLDB_INSTRUMENT_VA(this, event_data); | |
| lldb::SBError sb_error; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| Process::StopLocker stop_locker; | |
| if (stop_locker.TryLock(&process_sp->GetRunLock())) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| sb_error.SetError(process_sp->SendEventData(event_data)); | |
| } else { | |
| sb_error = Status::FromErrorString("process is running"); | |
| } | |
| } else | |
| sb_error = Status::FromErrorString("invalid process"); | |
| return sb_error; | |
| } | |
| uint32_t SBProcess::GetNumExtendedBacktraceTypes() { | |
| LLDB_INSTRUMENT_VA(this); | |
| 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) { | |
| LLDB_INSTRUMENT_VA(this, idx); | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp && process_sp->GetSystemRuntime()) { | |
| SystemRuntime *runtime = process_sp->GetSystemRuntime(); | |
| const std::vector<ConstString> &names = | |
| runtime->GetExtendedBacktraceTypes(); | |
| if (idx < names.size()) { | |
| return names[idx].AsCString(nullptr); | |
| } | |
| } | |
| return nullptr; | |
| } | |
| SBThreadCollection SBProcess::GetHistoryThreads(addr_t addr) { | |
| LLDB_INSTRUMENT_VA(this, addr); | |
| ProcessSP process_sp(GetSP()); | |
| SBThreadCollection threads; | |
| if (process_sp) { | |
| threads = SBThreadCollection(process_sp->GetHistoryThreads(addr)); | |
| } | |
| return threads; | |
| } | |
| bool SBProcess::IsInstrumentationRuntimePresent( | |
| InstrumentationRuntimeType type) { | |
| LLDB_INSTRUMENT_VA(this, type); | |
| ProcessSP process_sp(GetSP()); | |
| if (!process_sp) | |
| return false; | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| InstrumentationRuntimeSP runtime_sp = | |
| process_sp->GetInstrumentationRuntime(type); | |
| if (!runtime_sp.get()) | |
| return false; | |
| return runtime_sp->IsActive(); | |
| } | |
| lldb::SBError SBProcess::SaveCore(const char *file_name) { | |
| LLDB_INSTRUMENT_VA(this, file_name); | |
| SBSaveCoreOptions options; | |
| options.SetOutputFile(SBFileSpec(file_name)); | |
| options.SetStyle(SaveCoreStyle::eSaveCoreFull); | |
| return SaveCore(options); | |
| } | |
| lldb::SBError SBProcess::SaveCore(const char *file_name, | |
| const char *flavor, | |
| SaveCoreStyle core_style) { | |
| LLDB_INSTRUMENT_VA(this, file_name, flavor, core_style); | |
| SBSaveCoreOptions options; | |
| options.SetOutputFile(SBFileSpec(file_name)); | |
| options.SetStyle(core_style); | |
| SBError error = options.SetPluginName(flavor); | |
| if (error.Fail()) | |
| return error; | |
| return SaveCore(options); | |
| } | |
| lldb::SBError SBProcess::SaveCore(SBSaveCoreOptions &options) { | |
| LLDB_INSTRUMENT_VA(this, options); | |
| lldb::SBError error; | |
| ProcessSP process_sp(GetSP()); | |
| if (!process_sp) { | |
| error = Status::FromErrorString("SBProcess is invalid"); | |
| return error; | |
| } | |
| if (!options.GetProcess()) | |
| options.SetProcess(process_sp); | |
| if (options.GetProcess().GetSP() != process_sp) { | |
| error = Status::FromErrorString( | |
| "Save Core Options configured for a different process."); | |
| return error; | |
| } | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| if (process_sp->GetState() != eStateStopped) { | |
| error = Status::FromErrorString("the process is not stopped"); | |
| return error; | |
| } | |
| error.ref() = PluginManager::SaveCore(options.ref()); | |
| return error; | |
| } | |
| lldb::SBError | |
| SBProcess::GetMemoryRegionInfo(lldb::addr_t load_addr, | |
| SBMemoryRegionInfo &sb_region_info) { | |
| LLDB_INSTRUMENT_VA(this, load_addr, sb_region_info); | |
| lldb::SBError sb_error; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| Process::StopLocker stop_locker; | |
| if (stop_locker.TryLock(&process_sp->GetRunLock())) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| sb_error.ref() = | |
| process_sp->GetMemoryRegionInfo(load_addr, sb_region_info.ref()); | |
| } else { | |
| sb_error = Status::FromErrorString("process is running"); | |
| } | |
| } else { | |
| sb_error = Status::FromErrorString("SBProcess is invalid"); | |
| } | |
| return sb_error; | |
| } | |
| lldb::SBMemoryRegionInfoList SBProcess::GetMemoryRegions() { | |
| LLDB_INSTRUMENT_VA(this); | |
| lldb::SBMemoryRegionInfoList sb_region_list; | |
| ProcessSP process_sp(GetSP()); | |
| Process::StopLocker stop_locker; | |
| if (process_sp && stop_locker.TryLock(&process_sp->GetRunLock())) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| process_sp->GetMemoryRegions(sb_region_list.ref()); | |
| } | |
| return sb_region_list; | |
| } | |
| lldb::SBProcessInfo SBProcess::GetProcessInfo() { | |
| LLDB_INSTRUMENT_VA(this); | |
| lldb::SBProcessInfo sb_proc_info; | |
| ProcessSP process_sp(GetSP()); | |
| ProcessInstanceInfo proc_info; | |
| if (process_sp && process_sp->GetProcessInfo(proc_info)) { | |
| sb_proc_info.SetProcessInfo(proc_info); | |
| } | |
| return sb_proc_info; | |
| } | |
| lldb::SBFileSpec SBProcess::GetCoreFile() { | |
| LLDB_INSTRUMENT_VA(this); | |
| ProcessSP process_sp(GetSP()); | |
| FileSpec core_file; | |
| if (process_sp) { | |
| core_file = process_sp->GetCoreFile(); | |
| } | |
| return SBFileSpec(core_file); | |
| } | |
| bool SBProcess::IsLiveDebugSession() const { | |
| LLDB_INSTRUMENT_VA(this); | |
| ProcessSP process_sp(GetSP()); | |
| if (!process_sp) | |
| return false; | |
| return process_sp->IsLiveDebugSession(); | |
| } | |
| addr_t SBProcess::GetAddressMask(AddressMaskType type, | |
| AddressMaskRange addr_range) { | |
| LLDB_INSTRUMENT_VA(this, type, addr_range); | |
| if (ProcessSP process_sp = GetSP()) { | |
| switch (type) { | |
| case eAddressMaskTypeCode: | |
| if (addr_range == eAddressMaskRangeHigh) | |
| return process_sp->GetHighmemCodeAddressMask(); | |
| else | |
| return process_sp->GetCodeAddressMask(); | |
| case eAddressMaskTypeData: | |
| if (addr_range == eAddressMaskRangeHigh) | |
| return process_sp->GetHighmemDataAddressMask(); | |
| else | |
| return process_sp->GetDataAddressMask(); | |
| case eAddressMaskTypeAny: | |
| if (addr_range == eAddressMaskRangeHigh) | |
| return process_sp->GetHighmemDataAddressMask(); | |
| else | |
| return process_sp->GetDataAddressMask(); | |
| } | |
| } | |
| return LLDB_INVALID_ADDRESS_MASK; | |
| } | |
| void SBProcess::SetAddressMask(AddressMaskType type, addr_t mask, | |
| AddressMaskRange addr_range) { | |
| LLDB_INSTRUMENT_VA(this, type, mask, addr_range); | |
| if (ProcessSP process_sp = GetSP()) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| switch (type) { | |
| case eAddressMaskTypeCode: | |
| if (addr_range == eAddressMaskRangeAll) { | |
| process_sp->SetCodeAddressMask(mask); | |
| process_sp->SetHighmemCodeAddressMask(mask); | |
| } else if (addr_range == eAddressMaskRangeHigh) { | |
| process_sp->SetHighmemCodeAddressMask(mask); | |
| } else { | |
| process_sp->SetCodeAddressMask(mask); | |
| } | |
| break; | |
| case eAddressMaskTypeData: | |
| if (addr_range == eAddressMaskRangeAll) { | |
| process_sp->SetDataAddressMask(mask); | |
| process_sp->SetHighmemDataAddressMask(mask); | |
| } else if (addr_range == eAddressMaskRangeHigh) { | |
| process_sp->SetHighmemDataAddressMask(mask); | |
| } else { | |
| process_sp->SetDataAddressMask(mask); | |
| } | |
| break; | |
| case eAddressMaskTypeAll: | |
| if (addr_range == eAddressMaskRangeAll) { | |
| process_sp->SetCodeAddressMask(mask); | |
| process_sp->SetDataAddressMask(mask); | |
| process_sp->SetHighmemCodeAddressMask(mask); | |
| process_sp->SetHighmemDataAddressMask(mask); | |
| } else if (addr_range == eAddressMaskRangeHigh) { | |
| process_sp->SetHighmemCodeAddressMask(mask); | |
| process_sp->SetHighmemDataAddressMask(mask); | |
| } else { | |
| process_sp->SetCodeAddressMask(mask); | |
| process_sp->SetDataAddressMask(mask); | |
| } | |
| break; | |
| } | |
| process_sp->AddressMaskChangedCallback(); | |
| } | |
| } | |
| void SBProcess::SetAddressableBits(AddressMaskType type, uint32_t num_bits, | |
| AddressMaskRange addr_range) { | |
| LLDB_INSTRUMENT_VA(this, type, num_bits, addr_range); | |
| SetAddressMask(type, AddressableBits::AddressableBitToMask(num_bits), | |
| addr_range); | |
| } | |
| addr_t SBProcess::FixAddress(addr_t addr, AddressMaskType type) { | |
| LLDB_INSTRUMENT_VA(this, addr, type); | |
| if (ProcessSP process_sp = GetSP()) { | |
| if (type == eAddressMaskTypeAny) | |
| return process_sp->FixAnyAddress(addr); | |
| else if (type == eAddressMaskTypeData) | |
| return process_sp->FixDataAddress(addr); | |
| else if (type == eAddressMaskTypeCode) | |
| return process_sp->FixCodeAddress(addr); | |
| } | |
| return addr; | |
| } | |
| lldb::addr_t SBProcess::AllocateMemory(size_t size, uint32_t permissions, | |
| lldb::SBError &sb_error) { | |
| LLDB_INSTRUMENT_VA(this, size, permissions, sb_error); | |
| lldb::addr_t addr = LLDB_INVALID_ADDRESS; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| Process::StopLocker stop_locker; | |
| if (stop_locker.TryLock(&process_sp->GetRunLock())) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| addr = process_sp->AllocateMemory(size, permissions, sb_error.ref()); | |
| } else { | |
| sb_error = Status::FromErrorString("process is running"); | |
| } | |
| } else { | |
| sb_error = Status::FromErrorString("SBProcess is invalid"); | |
| } | |
| return addr; | |
| } | |
| lldb::SBError SBProcess::DeallocateMemory(lldb::addr_t ptr) { | |
| LLDB_INSTRUMENT_VA(this, ptr); | |
| lldb::SBError sb_error; | |
| ProcessSP process_sp(GetSP()); | |
| if (process_sp) { | |
| Process::StopLocker stop_locker; | |
| if (stop_locker.TryLock(&process_sp->GetRunLock())) { | |
| TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex(); | |
| std::lock_guard<TargetAPIMutex> guard(api_lock); | |
| Status error = process_sp->DeallocateMemory(ptr); | |
| sb_error.SetError(std::move(error)); | |
| } else { | |
| sb_error = Status::FromErrorString("process is running"); | |
| } | |
| } else { | |
| sb_error = Status::FromErrorString("SBProcess is invalid"); | |
| } | |
| return sb_error; | |
| } | |
| lldb::SBScriptObject SBProcess::GetScriptedImplementation() { | |
| LLDB_INSTRUMENT_VA(this); | |
| ProcessSP process_sp(GetSP()); | |
| return lldb::SBScriptObject((process_sp) ? process_sp->GetImplementation() | |
| : nullptr, | |
| eScriptLanguageDefault); | |
| } |