//===-- ThreadMemory.h ------------------------------------------*- C++ -*-===// // // 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 // //===----------------------------------------------------------------------===// #ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_THREADMEMORY_H #define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_THREADMEMORY_H #include #include "lldb/Target/Thread.h" /// A memory thread with its own ID, optionally backed by a real thread. /// Most methods of this class dispatch to the real thread if it is not null. /// Notable exceptions are the methods calculating the StopInfo and /// RegisterContext of the thread, those may query the OS plugin that created /// the thread. class ThreadMemory : public lldb_private::Thread { public: ThreadMemory(lldb_private::Process &process, lldb::tid_t tid, lldb::addr_t register_data_addr) : Thread(process, tid), m_register_data_addr(register_data_addr) {} ~ThreadMemory() override; lldb::RegisterContextSP GetRegisterContext() override; lldb::RegisterContextSP CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; bool CalculateStopInfo() override; const char *GetInfo() override { if (m_backing_thread_sp) return m_backing_thread_sp->GetInfo(); return nullptr; } const char *GetName() override { if (m_backing_thread_sp) return m_backing_thread_sp->GetName(); return nullptr; } const char *GetQueueName() override { if (m_backing_thread_sp) return m_backing_thread_sp->GetQueueName(); return nullptr; } void WillResume(lldb::StateType resume_state) override; void SetQueueName(const char *name) override { if (m_backing_thread_sp) m_backing_thread_sp->SetQueueName(name); } lldb::queue_id_t GetQueueID() override { if (m_backing_thread_sp) return m_backing_thread_sp->GetQueueID(); return LLDB_INVALID_QUEUE_ID; } void SetQueueID(lldb::queue_id_t new_val) override { if (m_backing_thread_sp) m_backing_thread_sp->SetQueueID(new_val); } lldb::QueueKind GetQueueKind() override { if (m_backing_thread_sp) return m_backing_thread_sp->GetQueueKind(); return lldb::eQueueKindUnknown; } void SetQueueKind(lldb::QueueKind kind) override { if (m_backing_thread_sp) m_backing_thread_sp->SetQueueKind(kind); } lldb::QueueSP GetQueue() override { if (m_backing_thread_sp) return m_backing_thread_sp->GetQueue(); return lldb::QueueSP(); } lldb::addr_t GetQueueLibdispatchQueueAddress() override { if (m_backing_thread_sp) return m_backing_thread_sp->GetQueueLibdispatchQueueAddress(); return LLDB_INVALID_ADDRESS; } void SetQueueLibdispatchQueueAddress(lldb::addr_t dispatch_queue_t) override { if (m_backing_thread_sp) m_backing_thread_sp->SetQueueLibdispatchQueueAddress(dispatch_queue_t); } lldb_private::LazyBool GetAssociatedWithLibdispatchQueue() override { if (m_backing_thread_sp) return m_backing_thread_sp->GetAssociatedWithLibdispatchQueue(); return lldb_private::eLazyBoolNo; } void SetAssociatedWithLibdispatchQueue( lldb_private::LazyBool associated_with_libdispatch_queue) override { if (m_backing_thread_sp) m_backing_thread_sp->SetAssociatedWithLibdispatchQueue( associated_with_libdispatch_queue); } bool ThreadHasQueueInformation() const override { if (m_backing_thread_sp) return m_backing_thread_sp->ThreadHasQueueInformation(); return false; } void DidResume() override { if (m_backing_thread_sp) m_backing_thread_sp->DidResume(); } lldb::user_id_t GetProtocolID() const override { if (m_backing_thread_sp) return m_backing_thread_sp->GetProtocolID(); return Thread::GetProtocolID(); } void RefreshStateAfterStop() override; void ClearStackFrames() override; void ClearBackingThread() override { if (m_backing_thread_sp) m_backing_thread_sp->ClearBackedThread(); m_backing_thread_sp.reset(); } bool SetBackingThread(const lldb::ThreadSP &thread_sp) override { m_backing_thread_sp = thread_sp; thread_sp->SetBackedThread(*this); return thread_sp.get(); } lldb::ThreadSP GetBackingThread() const override { return m_backing_thread_sp; } bool IsOperatingSystemPluginThread() const override { return true; } private: lldb::addr_t m_register_data_addr; lldb::ThreadSP m_backing_thread_sp; ThreadMemory(const ThreadMemory &) = delete; const ThreadMemory &operator=(const ThreadMemory &) = delete; }; /// A ThreadMemory that optionally overrides the thread name. class ThreadMemoryProvidingName : public ThreadMemory { public: ThreadMemoryProvidingName(lldb_private::Process &process, lldb::tid_t tid, lldb::addr_t register_data_addr, llvm::StringRef name) : ThreadMemory(process, tid, register_data_addr), m_name(name) {} const char *GetName() override { if (!m_name.empty()) return m_name.c_str(); return ThreadMemory::GetName(); } ~ThreadMemoryProvidingName() override = default; private: std::string m_name; }; /// A ThreadMemoryProvidingName that optionally overrides queue information. class ThreadMemoryProvidingNameAndQueue : public ThreadMemoryProvidingName { public: ThreadMemoryProvidingNameAndQueue( lldb_private::Process &process, lldb::tid_t tid, const lldb::ValueObjectSP &thread_info_valobj_sp); ThreadMemoryProvidingNameAndQueue(lldb_private::Process &process, lldb::tid_t tid, llvm::StringRef name, llvm::StringRef queue, lldb::addr_t register_data_addr); ~ThreadMemoryProvidingNameAndQueue() override = default; const char *GetQueueName() override { if (!m_queue.empty()) return m_queue.c_str(); return ThreadMemory::GetQueueName(); } /// TODO: this method should take into account the queue override. void SetQueueName(const char *name) override { Thread::SetQueueName(name); } /// TODO: this method should take into account the queue override. lldb::queue_id_t GetQueueID() override { return Thread::GetQueueID(); } /// TODO: this method should take into account the queue override. void SetQueueID(lldb::queue_id_t new_val) override { Thread::SetQueueID(new_val); } /// TODO: this method should take into account the queue override. lldb::QueueKind GetQueueKind() override { return Thread::GetQueueKind(); } /// TODO: this method should take into account the queue override. void SetQueueKind(lldb::QueueKind kind) override { Thread::SetQueueKind(kind); } /// TODO: this method should take into account the queue override. lldb::QueueSP GetQueue() override { return Thread::GetQueue(); } /// TODO: this method should take into account the queue override. lldb::addr_t GetQueueLibdispatchQueueAddress() override { return Thread::GetQueueLibdispatchQueueAddress(); } /// TODO: this method should take into account the queue override. void SetQueueLibdispatchQueueAddress(lldb::addr_t dispatch_queue_t) override { Thread::SetQueueLibdispatchQueueAddress(dispatch_queue_t); } /// TODO: this method should take into account the queue override. bool ThreadHasQueueInformation() const override { return Thread::ThreadHasQueueInformation(); } /// TODO: this method should take into account the queue override. lldb_private::LazyBool GetAssociatedWithLibdispatchQueue() override { return Thread::GetAssociatedWithLibdispatchQueue(); } /// TODO: this method should take into account the queue override. void SetAssociatedWithLibdispatchQueue( lldb_private::LazyBool associated_with_libdispatch_queue) override { Thread::SetAssociatedWithLibdispatchQueue( associated_with_libdispatch_queue); } lldb::ValueObjectSP &GetValueObject() { return m_thread_info_valobj_sp; } protected: lldb::ValueObjectSP m_thread_info_valobj_sp; std::string m_queue; private: ThreadMemoryProvidingNameAndQueue(const ThreadMemoryProvidingNameAndQueue &) = delete; const ThreadMemoryProvidingNameAndQueue & operator=(const ThreadMemoryProvidingNameAndQueue &) = delete; }; #endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_THREADMEMORY_H