Remove shared pointer from NativeProcessProtocol

Summary:
The usage of shared_from_this forces us to separate construction and
initialization phases, because shared_from_this() is not available in
the constructor (or destructor). The shared semantics are not necessary,
as we always have a clear owner of the native process class
(GDBRemoteCommunicationServerLLDB object). Even if we need shared
semantics in the future (which I think we should strongly avoid),
reverting this will not be necessary -- the owners can still easily
store the native process object in a shared pointer if they really want
to -- this just prevents the knowledge of that from leaking into the
class implementation.

After this a NativeThread object will hold a reference to the parent
process (instead of a weak_ptr) -- having a process instance always
available allows us to simplify some logic in this class (some of it was
already simplified because we were asserting that the process is
available, but this makes it obvious).

Reviewers: krytarowski, eugene, zturner

Subscribers: lldb-commits

Differential Revision: https://reviews.llvm.org/D35123

llvm-svn: 308282
This commit is contained in:
Pavel Labath 2017-07-18 09:24:48 +00:00
parent 095ec3da81
commit 82abefa4b1
18 changed files with 299 additions and 468 deletions

View File

@ -33,8 +33,7 @@ class ResumeActionList;
//------------------------------------------------------------------
// NativeProcessProtocol
//------------------------------------------------------------------
class NativeProcessProtocol
: public std::enable_shared_from_this<NativeProcessProtocol> {
class NativeProcessProtocol {
friend class SoftwareBreakpoint;
public:
@ -268,7 +267,7 @@ public:
/// A NativeProcessProtocol shared pointer if the operation succeeded or
/// an error object if it failed.
//------------------------------------------------------------------
virtual llvm::Expected<NativeProcessProtocolSP>
virtual llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
Launch(ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate,
MainLoop &mainloop) const = 0;
@ -292,7 +291,7 @@ public:
/// A NativeProcessProtocol shared pointer if the operation succeeded or
/// an error object if it failed.
//------------------------------------------------------------------
virtual llvm::Expected<NativeProcessProtocolSP>
virtual llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
Attach(lldb::pid_t pid, NativeDelegate &native_delegate,
MainLoop &mainloop) const = 0;
};

View File

@ -23,7 +23,7 @@ namespace lldb_private {
class NativeThreadProtocol
: public std::enable_shared_from_this<NativeThreadProtocol> {
public:
NativeThreadProtocol(NativeProcessProtocol *process, lldb::tid_t tid);
NativeThreadProtocol(NativeProcessProtocol &process, lldb::tid_t tid);
virtual ~NativeThreadProtocol() {}
@ -46,7 +46,7 @@ public:
lldb::tid_t GetID() const { return m_tid; }
NativeProcessProtocolSP GetProcess();
NativeProcessProtocol &GetProcess() { return m_process; }
// ---------------------------------------------------------------------
// Thread-specific watchpoints
@ -64,7 +64,7 @@ public:
virtual Status RemoveHardwareBreakpoint(lldb::addr_t addr) = 0;
protected:
NativeProcessProtocolWP m_process_wp;
NativeProcessProtocol &m_process;
lldb::tid_t m_tid;
};
}

View File

@ -30,10 +30,6 @@ class UnixSignals;
// SP/WP decls.
// ---------------------------------------------------------------
typedef std::shared_ptr<NativeBreakpoint> NativeBreakpointSP;
typedef std::shared_ptr<lldb_private::NativeProcessProtocol>
NativeProcessProtocolSP;
typedef std::weak_ptr<lldb_private::NativeProcessProtocol>
NativeProcessProtocolWP;
typedef std::shared_ptr<lldb_private::NativeRegisterContext>
NativeRegisterContextSP;
typedef std::shared_ptr<lldb_private::NativeThreadProtocol>

View File

@ -345,17 +345,12 @@ Status NativeRegisterContext::ReadRegisterValueFromMemory(
return error;
}
NativeProcessProtocolSP process_sp(m_thread.GetProcess());
if (!process_sp) {
error.SetErrorString("invalid process");
return error;
}
NativeProcessProtocol &process = m_thread.GetProcess();
uint8_t src[RegisterValue::kMaxRegisterByteSize];
// Read the memory
size_t bytes_read;
error = process_sp->ReadMemory(src_addr, src, src_len, bytes_read);
error = process.ReadMemory(src_addr, src, src_len, bytes_read);
if (error.Fail())
return error;
@ -374,7 +369,7 @@ Status NativeRegisterContext::ReadRegisterValueFromMemory(
// order of the memory data doesn't match the process. For now we are assuming
// they are the same.
lldb::ByteOrder byte_order;
if (!process_sp->GetByteOrder(byte_order)) {
if (process.GetByteOrder(byte_order)) {
error.SetErrorString("NativeProcessProtocol::GetByteOrder () failed");
return error;
}
@ -392,41 +387,37 @@ Status NativeRegisterContext::WriteRegisterValueToMemory(
Status error;
NativeProcessProtocolSP process_sp(m_thread.GetProcess());
if (process_sp) {
NativeProcessProtocol &process = m_thread.GetProcess();
// TODO: we might need to add a parameter to this function in case the byte
// order of the memory data doesn't match the process. For now we are
// assuming
// they are the same.
lldb::ByteOrder byte_order;
if (!process_sp->GetByteOrder(byte_order))
return Status("NativeProcessProtocol::GetByteOrder () failed");
// TODO: we might need to add a parameter to this function in case the byte
// order of the memory data doesn't match the process. For now we are
// assuming
// they are the same.
lldb::ByteOrder byte_order;
if (!process.GetByteOrder(byte_order))
return Status("NativeProcessProtocol::GetByteOrder () failed");
const size_t bytes_copied =
reg_value.GetAsMemoryData(reg_info, dst, dst_len, byte_order, error);
const size_t bytes_copied =
reg_value.GetAsMemoryData(reg_info, dst, dst_len, byte_order, error);
if (error.Success()) {
if (bytes_copied == 0) {
error.SetErrorString("byte copy failed.");
} else {
size_t bytes_written;
error =
process_sp->WriteMemory(dst_addr, dst, bytes_copied, bytes_written);
if (error.Fail())
return error;
if (error.Success()) {
if (bytes_copied == 0) {
error.SetErrorString("byte copy failed.");
} else {
size_t bytes_written;
error = process.WriteMemory(dst_addr, dst, bytes_copied, bytes_written);
if (error.Fail())
return error;
if (bytes_written != bytes_copied) {
// This might happen if we read _some_ bytes but not all
error.SetErrorStringWithFormat("only wrote %" PRIu64 " of %" PRIu64
" bytes",
static_cast<uint64_t>(bytes_written),
static_cast<uint64_t>(bytes_copied));
}
if (bytes_written != bytes_copied) {
// This might happen if we read _some_ bytes but not all
error.SetErrorStringWithFormat("only wrote %" PRIu64 " of %" PRIu64
" bytes",
static_cast<uint64_t>(bytes_written),
static_cast<uint64_t>(bytes_copied));
}
}
} else
error.SetErrorString("invalid process");
}
return error;
}

View File

@ -16,9 +16,9 @@
using namespace lldb;
using namespace lldb_private;
NativeThreadProtocol::NativeThreadProtocol(NativeProcessProtocol *process,
NativeThreadProtocol::NativeThreadProtocol(NativeProcessProtocol &process,
lldb::tid_t tid)
: m_process_wp(process->shared_from_this()), m_tid(tid) {}
: m_process(process), m_tid(tid) {}
Status NativeThreadProtocol::ReadRegister(uint32_t reg,
RegisterValue &reg_value) {
@ -62,7 +62,3 @@ Status NativeThreadProtocol::RestoreAllRegisters(lldb::DataBufferSP &data_sp) {
return Status("no register context");
return register_context_sp->ReadAllRegisterValues(data_sp);
}
NativeProcessProtocolSP NativeThreadProtocol::GetProcess() {
return m_process_wp.lock();
}

View File

@ -214,7 +214,7 @@ static Status EnsureFDFlags(int fd, int flags) {
// Public Static Methods
// -----------------------------------------------------------------------------
llvm::Expected<NativeProcessProtocolSP>
llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
NativeProcessLinux::Factory::Launch(ProcessLaunchInfo &launch_info,
NativeDelegate &native_delegate,
MainLoop &mainloop) const {
@ -259,14 +259,13 @@ NativeProcessLinux::Factory::Launch(ProcessLaunchInfo &launch_info,
return status.ToError();
}
std::shared_ptr<NativeProcessLinux> process_sp(new NativeProcessLinux(
return std::unique_ptr<NativeProcessLinux>(new NativeProcessLinux(
pid, launch_info.GetPTY().ReleaseMasterFileDescriptor(), native_delegate,
arch, mainloop));
process_sp->InitializeThreads({pid});
return process_sp;
arch, mainloop, {pid}));
}
llvm::Expected<NativeProcessProtocolSP> NativeProcessLinux::Factory::Attach(
llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
NativeProcessLinux::Factory::Attach(
lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate,
MainLoop &mainloop) const {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
@ -282,10 +281,8 @@ llvm::Expected<NativeProcessProtocolSP> NativeProcessLinux::Factory::Attach(
if (!tids_or)
return tids_or.takeError();
std::shared_ptr<NativeProcessLinux> process_sp(
new NativeProcessLinux(pid, -1, native_delegate, arch, mainloop));
process_sp->InitializeThreads(*tids_or);
return process_sp;
return std::unique_ptr<NativeProcessLinux>(new NativeProcessLinux(
pid, -1, native_delegate, arch, mainloop, *tids_or));
}
// -----------------------------------------------------------------------------
@ -294,7 +291,8 @@ llvm::Expected<NativeProcessProtocolSP> NativeProcessLinux::Factory::Attach(
NativeProcessLinux::NativeProcessLinux(::pid_t pid, int terminal_fd,
NativeDelegate &delegate,
const ArchSpec &arch, MainLoop &mainloop)
const ArchSpec &arch, MainLoop &mainloop,
llvm::ArrayRef<::pid_t> tids)
: NativeProcessProtocol(pid, terminal_fd, delegate), m_arch(arch) {
if (m_terminal_fd != -1) {
Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK);
@ -305,9 +303,7 @@ NativeProcessLinux::NativeProcessLinux(::pid_t pid, int terminal_fd,
m_sigchld_handle = mainloop.RegisterSignal(
SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, status);
assert(m_sigchld_handle && status.Success());
}
void NativeProcessLinux::InitializeThreads(llvm::ArrayRef<::pid_t> tids) {
for (const auto &tid : tids) {
NativeThreadLinuxSP thread_sp = AddThread(tid);
assert(thread_sp && "AddThread() returned a nullptr thread");
@ -2009,7 +2005,7 @@ NativeThreadLinuxSP NativeProcessLinux::AddThread(lldb::tid_t thread_id) {
if (m_threads.empty())
SetCurrentThreadID(thread_id);
auto thread_sp = std::make_shared<NativeThreadLinux>(this, thread_id);
auto thread_sp = std::make_shared<NativeThreadLinux>(*this, thread_id);
m_threads.push_back(thread_sp);
if (m_pt_proces_trace_id != LLDB_INVALID_UID) {

View File

@ -42,11 +42,11 @@ class NativeProcessLinux : public NativeProcessProtocol {
public:
class Factory : public NativeProcessProtocol::Factory {
public:
llvm::Expected<NativeProcessProtocolSP>
llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
Launch(ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate,
MainLoop &mainloop) const override;
llvm::Expected<NativeProcessProtocolSP>
llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
Attach(lldb::pid_t pid, NativeDelegate &native_delegate,
MainLoop &mainloop) const override;
};
@ -160,15 +160,14 @@ private:
// Private Instance Methods
// ---------------------------------------------------------------------
NativeProcessLinux(::pid_t pid, int terminal_fd, NativeDelegate &delegate,
const ArchSpec &arch, MainLoop &mainloop);
const ArchSpec &arch, MainLoop &mainloop,
llvm::ArrayRef<::pid_t> tids);
// Returns a list of process threads that we have attached to.
static llvm::Expected<std::vector<::pid_t>> Attach(::pid_t pid);
static Status SetDefaultPtraceOpts(const lldb::pid_t);
void InitializeThreads(llvm::ArrayRef<::pid_t> tids);
void MonitorCallback(lldb::pid_t pid, bool exited, WaitStatus status);
void WaitForNewThread(::pid_t tid);

View File

@ -30,11 +30,7 @@ lldb::ByteOrder NativeRegisterContextLinux::GetByteOrder() const {
// read.
lldb::ByteOrder byte_order = lldb::eByteOrderInvalid;
NativeProcessProtocolSP process_sp(m_thread.GetProcess());
if (!process_sp)
return byte_order;
if (!process_sp->GetByteOrder(byte_order)) {
if (!m_thread.GetProcess().GetByteOrder(byte_order)) {
// FIXME log here
}

View File

@ -85,7 +85,7 @@ void LogThreadStopInfo(Log &log, const ThreadStopInfo &stop_info,
}
}
NativeThreadLinux::NativeThreadLinux(NativeProcessLinux *process,
NativeThreadLinux::NativeThreadLinux(NativeProcessLinux &process,
lldb::tid_t tid)
: NativeThreadProtocol(process, tid), m_state(StateType::eStateInvalid),
m_stop_info(), m_reg_context_sp(), m_stop_description() {}
@ -144,12 +144,8 @@ NativeRegisterContextSP NativeThreadLinux::GetRegisterContext() {
if (m_reg_context_sp)
return m_reg_context_sp;
NativeProcessProtocolSP m_process_sp = m_process_wp.lock();
if (!m_process_sp)
return NativeRegisterContextSP();
ArchSpec target_arch;
if (!m_process_sp->GetArchitecture(target_arch))
if (!m_process.GetArchitecture(target_arch))
return NativeRegisterContextSP();
const uint32_t concrete_frame_idx = 0;
@ -460,20 +456,10 @@ void NativeThreadLinux::MaybeLogStateChange(lldb::StateType new_state) {
if (new_state == old_state)
return;
NativeProcessProtocolSP m_process_sp = m_process_wp.lock();
lldb::pid_t pid =
m_process_sp ? m_process_sp->GetID() : LLDB_INVALID_PROCESS_ID;
// Log it.
log->Printf("NativeThreadLinux: thread (pid=%" PRIu64 ", tid=%" PRIu64
") changing from state %s to %s",
pid, GetID(), StateAsCString(old_state),
StateAsCString(new_state));
LLDB_LOG(log, "pid={0}, tid={1}: changing from state {2} to {3}",
m_process.GetID(), GetID(), old_state, new_state);
}
NativeProcessLinux &NativeThreadLinux::GetProcess() {
auto process_sp = std::static_pointer_cast<NativeProcessLinux>(
NativeThreadProtocol::GetProcess());
assert(process_sp);
return *process_sp;
return static_cast<NativeProcessLinux &>(m_process);
}

View File

@ -27,7 +27,7 @@ class NativeThreadLinux : public NativeThreadProtocol {
friend class NativeProcessLinux;
public:
NativeThreadLinux(NativeProcessLinux *process, lldb::tid_t tid);
NativeThreadLinux(NativeProcessLinux &process, lldb::tid_t tid);
// ---------------------------------------------------------------------
// NativeThreadProtocol Interface

View File

@ -64,7 +64,7 @@ static Status EnsureFDFlags(int fd, int flags) {
// Public Static Methods
// -----------------------------------------------------------------------------
llvm::Expected<NativeProcessProtocolSP>
llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
NativeProcessNetBSD::Factory::Launch(ProcessLaunchInfo &launch_info,
NativeDelegate &native_delegate,
MainLoop &mainloop) const {
@ -101,24 +101,25 @@ NativeProcessNetBSD::Factory::Launch(ProcessLaunchInfo &launch_info,
LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid,
arch.GetArchitectureName());
std::shared_ptr<NativeProcessNetBSD> process_sp(new NativeProcessNetBSD(
std::unique_ptr<NativeProcessNetBSD> process_up(new NativeProcessNetBSD(
pid, launch_info.GetPTY().ReleaseMasterFileDescriptor(), native_delegate,
arch, mainloop));
status = process_sp->ReinitializeThreads();
status = process_up->ReinitializeThreads();
if (status.Fail())
return status.ToError();
for (const auto &thread_sp : process_sp->m_threads) {
for (const auto &thread_sp : process_up->m_threads) {
static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal(
SIGSTOP);
}
process_sp->SetState(StateType::eStateStopped);
process_up->SetState(StateType::eStateStopped);
return process_sp;
return std::move(process_up);
}
llvm::Expected<NativeProcessProtocolSP> NativeProcessNetBSD::Factory::Attach(
llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
NativeProcessNetBSD::Factory::Attach(
lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate,
MainLoop &mainloop) const {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
@ -130,14 +131,14 @@ llvm::Expected<NativeProcessProtocolSP> NativeProcessNetBSD::Factory::Attach(
if (!status.Success())
return status.ToError();
std::shared_ptr<NativeProcessNetBSD> process_sp(
std::unique_ptr<NativeProcessNetBSD> process_up(
new NativeProcessNetBSD(pid, -1, native_delegate, arch, mainloop));
status = process_sp->Attach();
status = process_up->Attach();
if (!status.Success())
return status.ToError();
return process_sp;
return std::move(process_up);
}
// -----------------------------------------------------------------------------
@ -787,7 +788,7 @@ NativeThreadNetBSDSP NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) {
if (m_threads.empty())
SetCurrentThreadID(thread_id);
auto thread_sp = std::make_shared<NativeThreadNetBSD>(this, thread_id);
auto thread_sp = std::make_shared<NativeThreadNetBSD>(*this, thread_id);
m_threads.push_back(thread_sp);
return thread_sp;
}

View File

@ -34,11 +34,11 @@ class NativeProcessNetBSD : public NativeProcessProtocol {
public:
class Factory : public NativeProcessProtocol::Factory {
public:
llvm::Expected<NativeProcessProtocolSP>
llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
Launch(ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate,
MainLoop &mainloop) const override;
llvm::Expected<NativeProcessProtocolSP>
llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
Attach(lldb::pid_t pid, NativeDelegate &native_delegate,
MainLoop &mainloop) const override;
};

View File

@ -104,15 +104,9 @@ Status NativeRegisterContextNetBSD::DoWriteDBR(void *buf) {
}
NativeProcessNetBSD &NativeRegisterContextNetBSD::GetProcess() {
auto process_sp =
std::static_pointer_cast<NativeProcessNetBSD>(m_thread.GetProcess());
assert(process_sp);
return *process_sp;
return static_cast<NativeProcessNetBSD &>(m_thread.GetProcess());
}
::pid_t NativeRegisterContextNetBSD::GetProcessPid() {
NativeProcessNetBSD &process = GetProcess();
lldb::pid_t pid = process.GetID();
return pid;
return GetProcess().GetID();
}

View File

@ -24,7 +24,7 @@ using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_netbsd;
NativeThreadNetBSD::NativeThreadNetBSD(NativeProcessNetBSD *process,
NativeThreadNetBSD::NativeThreadNetBSD(NativeProcessNetBSD &process,
lldb::tid_t tid)
: NativeThreadProtocol(process, tid), m_state(StateType::eStateInvalid),
m_stop_info(), m_reg_context_sp(), m_stop_description() {}
@ -144,12 +144,8 @@ NativeRegisterContextSP NativeThreadNetBSD::GetRegisterContext() {
if (m_reg_context_sp)
return m_reg_context_sp;
NativeProcessProtocolSP m_process_sp = m_process_wp.lock();
if (!m_process_sp)
return NativeRegisterContextSP();
ArchSpec target_arch;
if (!m_process_sp->GetArchitecture(target_arch))
if (!m_process.GetArchitecture(target_arch))
return NativeRegisterContextSP();
const uint32_t concrete_frame_idx = 0;

View File

@ -24,7 +24,7 @@ class NativeThreadNetBSD : public NativeThreadProtocol {
friend class NativeProcessNetBSD;
public:
NativeThreadNetBSD(NativeProcessNetBSD *process, lldb::tid_t tid);
NativeThreadNetBSD(NativeProcessNetBSD &process, lldb::tid_t tid);
// ---------------------------------------------------------------------
// NativeThreadProtocol Interface

View File

@ -114,7 +114,7 @@ protected:
lldb::tid_t m_current_tid = LLDB_INVALID_THREAD_ID;
lldb::tid_t m_continue_tid = LLDB_INVALID_THREAD_ID;
std::recursive_mutex m_debugged_process_mutex;
NativeProcessProtocolSP m_debugged_process_sp;
std::unique_ptr<NativeProcessProtocol> m_debugged_process_up;
Communication m_stdio_communication;
MainLoop::ReadHandleUP m_stdio_handle_up;

View File

@ -67,13 +67,13 @@ typedef process_netbsd::NativeProcessNetBSD::Factory NativeProcessFactory;
// Dummy implementation to make sure the code compiles
class NativeProcessFactory : public NativeProcessProtocol::Factory {
public:
llvm::Expected<NativeProcessProtocolSP>
llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
Launch(ProcessLaunchInfo &launch_info,
NativeProcessProtocol::NativeDelegate &delegate,
MainLoop &mainloop) const override {
llvm_unreachable("Not implemented");
}
llvm::Expected<NativeProcessProtocolSP>
llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
Attach(lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &delegate,
MainLoop &mainloop) const override {
llvm_unreachable("Not implemented");