aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/Process
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/Process')
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp333
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h3
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp2
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h7
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp138
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h7
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp108
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h13
-rw-r--r--lldb/source/Plugins/Process/POSIX/CrashReason.cpp8
-rw-r--r--lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp2
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp11
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp6
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp6
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp6
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64.h7
-rw-r--r--lldb/source/Plugins/Process/Utility/lldb-x86-register-enums.h5
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp10
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h6
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp31
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h6
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp8
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h8
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp15
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp4
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp14
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp23
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h3
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp106
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h1
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td4
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp9
-rw-r--r--lldb/source/Plugins/Process/minidump/MinidumpParser.cpp73
-rw-r--r--lldb/source/Plugins/Process/minidump/MinidumpParser.h10
-rw-r--r--lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp79
-rw-r--r--lldb/source/Plugins/Process/minidump/ProcessMinidump.h3
35 files changed, 737 insertions, 338 deletions
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
index 8b6f9fbc33c3..4313d27e11e9 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
+++ b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
@@ -8,8 +8,7 @@
#include "NativeProcessNetBSD.h"
-
-
+#include "Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h"
#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
#include "lldb/Host/HostProcess.h"
#include "lldb/Host/common/NativeRegisterContext.h"
@@ -99,6 +98,17 @@ NativeProcessNetBSD::Factory::Launch(ProcessLaunchInfo &launch_info,
pid, launch_info.GetPTY().ReleaseMasterFileDescriptor(), native_delegate,
Info.GetArchitecture(), mainloop));
+ // Enable event reporting
+ ptrace_event_t events;
+ status = PtraceWrapper(PT_GET_EVENT_MASK, pid, &events, sizeof(events));
+ if (status.Fail())
+ return status.ToError();
+ // TODO: PTRACE_FORK | PTRACE_VFORK | PTRACE_POSIX_SPAWN?
+ events.pe_set_event |= PTRACE_LWP_CREATE | PTRACE_LWP_EXIT;
+ status = PtraceWrapper(PT_SET_EVENT_MASK, pid, &events, sizeof(events));
+ if (status.Fail())
+ return status.ToError();
+
status = process_up->ReinitializeThreads();
if (status.Fail())
return status.ToError();
@@ -211,17 +221,32 @@ void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) {
return;
}
+ NativeThreadNetBSD* thread = nullptr;
+ if (info.psi_lwpid > 0) {
+ for (const auto &t : m_threads) {
+ if (t->GetID() == static_cast<lldb::tid_t>(info.psi_lwpid)) {
+ thread = static_cast<NativeThreadNetBSD *>(t.get());
+ break;
+ }
+ static_cast<NativeThreadNetBSD *>(t.get())->SetStoppedWithNoReason();
+ }
+ if (!thread)
+ LLDB_LOG(log,
+ "thread not found in m_threads, pid = {0}, LWP = {1}", pid,
+ info.psi_lwpid);
+ }
+
switch (info.psi_siginfo.si_code) {
case TRAP_BRKPT:
- for (const auto &thread : m_threads) {
- static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByBreakpoint();
- FixupBreakpointPCAsNeeded(static_cast<NativeThreadNetBSD &>(*thread));
+ if (thread) {
+ thread->SetStoppedByBreakpoint();
+ FixupBreakpointPCAsNeeded(*thread);
}
SetState(StateType::eStateStopped, true);
break;
case TRAP_TRACE:
- for (const auto &thread : m_threads)
- static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByTrace();
+ if (thread)
+ thread->SetStoppedByTrace();
SetState(StateType::eStateStopped, true);
break;
case TRAP_EXEC: {
@@ -238,54 +263,66 @@ void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) {
static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByExec();
SetState(StateType::eStateStopped, true);
} break;
- case TRAP_DBREG: {
- // Find the thread.
- NativeThreadNetBSD* thread = nullptr;
- for (const auto &t : m_threads) {
- if (t->GetID() == info.psi_lwpid) {
- thread = static_cast<NativeThreadNetBSD *>(t.get());
+ case TRAP_LWP: {
+ ptrace_state_t pst;
+ Status error = PtraceWrapper(PT_GET_PROCESS_STATE, pid, &pst, sizeof(pst));
+ if (error.Fail()) {
+ SetState(StateType::eStateInvalid);
+ return;
+ }
+
+ switch (pst.pe_report_event) {
+ case PTRACE_LWP_CREATE: {
+ LLDB_LOG(log,
+ "monitoring new thread, pid = {0}, LWP = {1}", pid,
+ pst.pe_lwp);
+ NativeThreadNetBSD& t = AddThread(pst.pe_lwp);
+ error = t.CopyWatchpointsFrom(
+ static_cast<NativeThreadNetBSD &>(*GetCurrentThread()));
+ if (error.Fail()) {
+ LLDB_LOG(log,
+ "failed to copy watchpoints to new thread {0}: {1}",
+ pst.pe_lwp, error);
+ SetState(StateType::eStateInvalid);
+ return;
+ }
+ } break;
+ case PTRACE_LWP_EXIT:
+ LLDB_LOG(log,
+ "removing exited thread, pid = {0}, LWP = {1}", pid,
+ pst.pe_lwp);
+ RemoveThread(pst.pe_lwp);
break;
- }
}
- if (!thread) {
- LLDB_LOG(log,
- "thread not found in m_threads, pid = {0}, LWP = {1}",
- GetID(), info.psi_lwpid);
- break;
+
+ error = PtraceWrapper(PT_CONTINUE, pid, reinterpret_cast<void*>(1), 0);
+ if (error.Fail()) {
+ SetState(StateType::eStateInvalid);
+ return;
}
+ } break;
+ case TRAP_DBREG: {
+ if (!thread)
+ break;
- // If a watchpoint was hit, report it
+ auto &regctx = static_cast<NativeRegisterContextNetBSD &>(
+ thread->GetRegisterContext());
uint32_t wp_index = LLDB_INVALID_INDEX32;
- Status error = thread->GetRegisterContext().GetWatchpointHitIndex(
- wp_index, (uintptr_t)info.psi_siginfo.si_addr);
+ Status error = regctx.GetWatchpointHitIndex(wp_index,
+ (uintptr_t)info.psi_siginfo.si_addr);
if (error.Fail())
LLDB_LOG(log,
"received error while checking for watchpoint hits, pid = "
- "{0}, LWP = {1}, error = {2}",
- GetID(), info.psi_lwpid, error);
+ "{0}, LWP = {1}, error = {2}", pid, info.psi_lwpid, error);
if (wp_index != LLDB_INVALID_INDEX32) {
- for (const auto &thread : m_threads)
- static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByWatchpoint(
- wp_index);
+ thread->SetStoppedByWatchpoint(wp_index);
+ regctx.ClearWatchpointHit(wp_index);
SetState(StateType::eStateStopped, true);
break;
}
- // If a breakpoint was hit, report it
- uint32_t bp_index = LLDB_INVALID_INDEX32;
- error = thread->GetRegisterContext().GetHardwareBreakHitIndex(
- bp_index, (uintptr_t)info.psi_siginfo.si_addr);
- if (error.Fail())
- LLDB_LOG(log,
- "received error while checking for hardware "
- "breakpoint hits, pid = {0}, LWP = {1}, error = {2}",
- GetID(), info.psi_lwpid, error);
- if (bp_index != LLDB_INVALID_INDEX32) {
- for (const auto &thread : m_threads)
- static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByBreakpoint();
- SetState(StateType::eStateStopped, true);
- break;
- }
+ thread->SetStoppedByTrace();
+ SetState(StateType::eStateStopped, true);
} break;
}
}
@@ -295,9 +332,14 @@ void NativeProcessNetBSD::MonitorSignal(lldb::pid_t pid, int signal) {
const auto siginfo_err =
PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));
- for (const auto &thread : m_threads) {
- static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(
- info.psi_siginfo.si_signo, &info.psi_siginfo);
+ for (const auto &abs_thread : m_threads) {
+ NativeThreadNetBSD &thread = static_cast<NativeThreadNetBSD &>(*abs_thread);
+ assert(info.psi_lwpid >= 0);
+ if (info.psi_lwpid == 0 ||
+ static_cast<lldb::tid_t>(info.psi_lwpid) == thread.GetID())
+ thread.SetStoppedBySignal(info.psi_siginfo.si_signo, &info.psi_siginfo);
+ else
+ thread.SetStoppedWithNoReason();
}
SetState(StateType::eStateStopped, true);
}
@@ -325,68 +367,137 @@ Status NativeProcessNetBSD::PtraceWrapper(int req, lldb::pid_t pid, void *addr,
return error;
}
+static llvm::Expected<ptrace_siginfo_t> ComputeSignalInfo(
+ const std::vector<std::unique_ptr<NativeThreadProtocol>> &threads,
+ const ResumeActionList &resume_actions) {
+ // We need to account for three possible scenarios:
+ // 1. no signal being sent.
+ // 2. a signal being sent to one thread.
+ // 3. a signal being sent to the whole process.
+
+ // Count signaled threads. While at it, determine which signal is being sent
+ // and ensure there's only one.
+ size_t signaled_threads = 0;
+ int signal = LLDB_INVALID_SIGNAL_NUMBER;
+ lldb::tid_t signaled_lwp;
+ for (const auto &thread : threads) {
+ assert(thread && "thread list should not contain NULL threads");
+ const ResumeAction *action =
+ resume_actions.GetActionForThread(thread->GetID(), true);
+ if (action) {
+ if (action->signal != LLDB_INVALID_SIGNAL_NUMBER) {
+ signaled_threads++;
+ if (action->signal != signal) {
+ if (signal != LLDB_INVALID_SIGNAL_NUMBER)
+ return Status("NetBSD does not support passing multiple signals "
+ "simultaneously")
+ .ToError();
+ signal = action->signal;
+ signaled_lwp = thread->GetID();
+ }
+ }
+ }
+ }
+
+ if (signaled_threads == 0) {
+ ptrace_siginfo_t siginfo;
+ siginfo.psi_siginfo.si_signo = LLDB_INVALID_SIGNAL_NUMBER;
+ return siginfo;
+ }
+
+ if (signaled_threads > 1 && signaled_threads < threads.size())
+ return Status("NetBSD does not support passing signal to 1<i<all threads")
+ .ToError();
+
+ ptrace_siginfo_t siginfo;
+ siginfo.psi_siginfo.si_signo = signal;
+ siginfo.psi_siginfo.si_code = SI_USER;
+ siginfo.psi_siginfo.si_pid = getpid();
+ siginfo.psi_siginfo.si_uid = getuid();
+ if (signaled_threads == 1)
+ siginfo.psi_lwpid = signaled_lwp;
+ else // signal for the whole process
+ siginfo.psi_lwpid = 0;
+ return siginfo;
+}
+
Status NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
LLDB_LOG(log, "pid {0}", GetID());
- const auto &thread = m_threads[0];
- const ResumeAction *const action =
- resume_actions.GetActionForThread(thread->GetID(), true);
+ Status ret;
- if (action == nullptr) {
- LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(),
- thread->GetID());
- return Status();
- }
+ Expected<ptrace_siginfo_t> siginfo =
+ ComputeSignalInfo(m_threads, resume_actions);
+ if (!siginfo)
+ return Status(siginfo.takeError());
- Status error;
- int signal =
- action->signal != LLDB_INVALID_SIGNAL_NUMBER ? action->signal : 0;
-
- switch (action->state) {
- case eStateRunning: {
- // Run the thread, possibly feeding it the signal.
- error = NativeProcessNetBSD::PtraceWrapper(PT_CONTINUE, GetID(), (void *)1,
- signal);
- if (!error.Success())
- return error;
- for (const auto &thread : m_threads)
- static_cast<NativeThreadNetBSD &>(*thread).SetRunning();
- SetState(eStateRunning, true);
- break;
- }
- case eStateStepping:
- // Run the thread, possibly feeding it the signal.
- error = NativeProcessNetBSD::PtraceWrapper(PT_STEP, GetID(), (void *)1,
- signal);
- if (!error.Success())
- return error;
- for (const auto &thread : m_threads)
- static_cast<NativeThreadNetBSD &>(*thread).SetStepping();
- SetState(eStateStepping, true);
- break;
+ for (const auto &abs_thread : m_threads) {
+ assert(abs_thread && "thread list should not contain NULL threads");
+ NativeThreadNetBSD &thread = static_cast<NativeThreadNetBSD &>(*abs_thread);
- case eStateSuspended:
- case eStateStopped:
- llvm_unreachable("Unexpected state");
+ const ResumeAction *action =
+ resume_actions.GetActionForThread(thread.GetID(), true);
+ // we need to explicit issue suspend requests, so it is simpler to map it
+ // into proper action
+ ResumeAction suspend_action{thread.GetID(), eStateSuspended,
+ LLDB_INVALID_SIGNAL_NUMBER};
- default:
- return Status("NativeProcessNetBSD::%s (): unexpected state %s specified "
- "for pid %" PRIu64 ", tid %" PRIu64,
- __FUNCTION__, StateAsCString(action->state), GetID(),
- thread->GetID());
+ if (action == nullptr) {
+ LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(),
+ thread.GetID());
+ action = &suspend_action;
+ }
+
+ LLDB_LOG(
+ log,
+ "processing resume action state {0} signal {1} for pid {2} tid {3}",
+ action->state, action->signal, GetID(), thread.GetID());
+
+ switch (action->state) {
+ case eStateRunning:
+ ret = thread.Resume();
+ break;
+ case eStateStepping:
+ ret = thread.SingleStep();
+ break;
+ case eStateSuspended:
+ case eStateStopped:
+ if (action->signal != LLDB_INVALID_SIGNAL_NUMBER)
+ return Status("Passing signal to suspended thread unsupported");
+
+ ret = thread.Suspend();
+ break;
+
+ default:
+ return Status("NativeProcessNetBSD::%s (): unexpected state %s specified "
+ "for pid %" PRIu64 ", tid %" PRIu64,
+ __FUNCTION__, StateAsCString(action->state), GetID(),
+ thread.GetID());
+ }
+
+ if (!ret.Success())
+ return ret;
}
- return Status();
+ int signal = 0;
+ if (siginfo->psi_siginfo.si_signo != LLDB_INVALID_SIGNAL_NUMBER) {
+ ret = PtraceWrapper(PT_SET_SIGINFO, GetID(), &siginfo.get(),
+ sizeof(*siginfo));
+ if (!ret.Success())
+ return ret;
+ signal = siginfo->psi_siginfo.si_signo;
+ }
+
+ ret = PtraceWrapper(PT_CONTINUE, GetID(), reinterpret_cast<void *>(1),
+ signal);
+ if (ret.Success())
+ SetState(eStateRunning, true);
+ return ret;
}
Status NativeProcessNetBSD::Halt() {
- Status error;
-
- if (kill(GetID(), SIGSTOP) != 0)
- error.SetErrorToErrno();
-
- return error;
+ return PtraceWrapper(PT_STOP, GetID());
}
Status NativeProcessNetBSD::Detach() {
@@ -411,6 +522,10 @@ Status NativeProcessNetBSD::Signal(int signo) {
return error;
}
+Status NativeProcessNetBSD::Interrupt() {
+ return PtraceWrapper(PT_STOP, GetID());
+}
+
Status NativeProcessNetBSD::Kill() {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
LLDB_LOG(log, "pid {0}", GetID());
@@ -650,10 +765,10 @@ bool NativeProcessNetBSD::HasThreadNoLock(lldb::tid_t thread_id) {
}
NativeThreadNetBSD &NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) {
-
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id);
+ assert(thread_id > 0);
assert(!HasThreadNoLock(thread_id) &&
"attempted to add a thread by id that already exists");
@@ -665,6 +780,22 @@ NativeThreadNetBSD &NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) {
return static_cast<NativeThreadNetBSD &>(*m_threads.back());
}
+void NativeProcessNetBSD::RemoveThread(lldb::tid_t thread_id) {
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
+ LLDB_LOG(log, "pid {0} removing thread with tid {1}", GetID(), thread_id);
+
+ assert(thread_id > 0);
+ assert(HasThreadNoLock(thread_id) &&
+ "attempted to remove a thread that does not exist");
+
+ for (auto it = m_threads.begin(); it != m_threads.end(); ++it) {
+ if ((*it)->GetID() == thread_id) {
+ m_threads.erase(it);
+ break;
+ }
+ }
+}
+
Status NativeProcessNetBSD::Attach() {
// Attach to the requested process.
// An attach will cause the thread to stop with a SIGSTOP.
@@ -783,15 +914,23 @@ Status NativeProcessNetBSD::ReinitializeThreads() {
m_threads.clear();
// Initialize new thread
+#ifdef PT_LWPSTATUS
+ struct ptrace_lwpstatus info = {};
+ int op = PT_LWPNEXT;
+#else
struct ptrace_lwpinfo info = {};
- Status error = PtraceWrapper(PT_LWPINFO, GetID(), &info, sizeof(info));
+ int op = PT_LWPINFO;
+#endif
+
+ Status error = PtraceWrapper(op, GetID(), &info, sizeof(info));
+
if (error.Fail()) {
return error;
}
// Reinitialize from scratch threads and register them in process
while (info.pl_lwpid != 0) {
AddThread(info.pl_lwpid);
- error = PtraceWrapper(PT_LWPINFO, GetID(), &info, sizeof(info));
+ error = PtraceWrapper(op, GetID(), &info, sizeof(info));
if (error.Fail()) {
return error;
}
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
index 4e7f0a1c13ab..6a06773f40a8 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
+++ b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
@@ -47,6 +47,8 @@ public:
Status Signal(int signo) override;
+ Status Interrupt() override;
+
Status Kill() override;
Status GetMemoryRegionInfo(lldb::addr_t load_addr,
@@ -98,6 +100,7 @@ private:
bool HasThreadNoLock(lldb::tid_t thread_id);
NativeThreadNetBSD &AddThread(lldb::tid_t thread_id);
+ void RemoveThread(lldb::tid_t thread_id);
void MonitorCallback(lldb::pid_t pid, int signal);
void MonitorExited(lldb::pid_t pid, WaitStatus status);
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp
index 3a9caaad74c8..a8afa0b20305 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp
+++ b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp
@@ -8,6 +8,8 @@
#include "NativeRegisterContextNetBSD.h"
+#include "Plugins/Process/NetBSD/NativeProcessNetBSD.h"
+
#include "lldb/Host/common/NativeProcessProtocol.h"
using namespace lldb_private;
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h
index f5dd0c33b677..13e023d856d2 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h
+++ b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h
@@ -11,12 +11,13 @@
#include "lldb/Host/common/NativeThreadProtocol.h"
-#include "Plugins/Process/NetBSD/NativeProcessNetBSD.h"
#include "Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h"
namespace lldb_private {
namespace process_netbsd {
+class NativeProcessNetBSD;
+
class NativeRegisterContextNetBSD : public NativeRegisterContextRegisterInfo {
public:
NativeRegisterContextNetBSD(NativeThreadProtocol &native_thread,
@@ -30,6 +31,10 @@ public:
static NativeRegisterContextNetBSD *
CreateHostNativeRegisterContextNetBSD(const ArchSpec &target_arch,
NativeThreadProtocol &native_thread);
+ virtual Status
+ CopyHardwareWatchpointsFrom(NativeRegisterContextNetBSD &source) = 0;
+
+ virtual Status ClearWatchpointHit(uint32_t wp_index) = 0;
protected:
Status DoRegisterSet(int req, void *buf);
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
index 6cc2810fa235..05a35401da46 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
+++ b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
@@ -84,13 +84,71 @@ static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) -
k_num_gpr_registers_x86_64,
"g_gpr_regnums_x86_64 has wrong number of register infos");
+// x86 64-bit floating point registers.
+static const uint32_t g_fpu_regnums_x86_64[] = {
+ lldb_fctrl_x86_64, lldb_fstat_x86_64, lldb_ftag_x86_64,
+ lldb_fop_x86_64, lldb_fiseg_x86_64, lldb_fioff_x86_64,
+ lldb_foseg_x86_64, lldb_fooff_x86_64, lldb_mxcsr_x86_64,
+ lldb_mxcsrmask_x86_64, lldb_st0_x86_64, lldb_st1_x86_64,
+ lldb_st2_x86_64, lldb_st3_x86_64, lldb_st4_x86_64,
+ lldb_st5_x86_64, lldb_st6_x86_64, lldb_st7_x86_64,
+ lldb_mm0_x86_64, lldb_mm1_x86_64, lldb_mm2_x86_64,
+ lldb_mm3_x86_64, lldb_mm4_x86_64, lldb_mm5_x86_64,
+ lldb_mm6_x86_64, lldb_mm7_x86_64, lldb_xmm0_x86_64,
+ lldb_xmm1_x86_64, lldb_xmm2_x86_64, lldb_xmm3_x86_64,
+ lldb_xmm4_x86_64, lldb_xmm5_x86_64, lldb_xmm6_x86_64,
+ lldb_xmm7_x86_64, lldb_xmm8_x86_64, lldb_xmm9_x86_64,
+ lldb_xmm10_x86_64, lldb_xmm11_x86_64, lldb_xmm12_x86_64,
+ lldb_xmm13_x86_64, lldb_xmm14_x86_64, lldb_xmm15_x86_64,
+ LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+static_assert((sizeof(g_fpu_regnums_x86_64) / sizeof(g_fpu_regnums_x86_64[0])) -
+ 1 ==
+ k_num_fpr_registers_x86_64,
+ "g_fpu_regnums_x86_64 has wrong number of register infos");
+
+// x86 64-bit registers available via XState.
+static const uint32_t g_xstate_regnums_x86_64[] = {
+ lldb_ymm0_x86_64, lldb_ymm1_x86_64, lldb_ymm2_x86_64, lldb_ymm3_x86_64,
+ lldb_ymm4_x86_64, lldb_ymm5_x86_64, lldb_ymm6_x86_64, lldb_ymm7_x86_64,
+ lldb_ymm8_x86_64, lldb_ymm9_x86_64, lldb_ymm10_x86_64, lldb_ymm11_x86_64,
+ lldb_ymm12_x86_64, lldb_ymm13_x86_64, lldb_ymm14_x86_64, lldb_ymm15_x86_64,
+ // Note: we currently do not provide them but this is needed to avoid
+ // unnamed groups in SBFrame::GetRegisterContext().
+ lldb_bnd0_x86_64, lldb_bnd1_x86_64, lldb_bnd2_x86_64,
+ lldb_bnd3_x86_64, lldb_bndcfgu_x86_64, lldb_bndstatus_x86_64,
+ LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+static_assert((sizeof(g_xstate_regnums_x86_64) / sizeof(g_xstate_regnums_x86_64[0])) -
+ 1 ==
+ k_num_avx_registers_x86_64 + k_num_mpx_registers_x86_64,
+ "g_xstate_regnums_x86_64 has wrong number of register infos");
+
+// x86 debug registers.
+static const uint32_t g_dbr_regnums_x86_64[] = {
+ lldb_dr0_x86_64, lldb_dr1_x86_64, lldb_dr2_x86_64, lldb_dr3_x86_64,
+ lldb_dr4_x86_64, lldb_dr5_x86_64, lldb_dr6_x86_64, lldb_dr7_x86_64,
+ LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+static_assert((sizeof(g_dbr_regnums_x86_64) / sizeof(g_dbr_regnums_x86_64[0])) -
+ 1 ==
+ k_num_dbr_registers_x86_64,
+ "g_dbr_regnums_x86_64 has wrong number of register infos");
+
// Number of register sets provided by this context.
-enum { k_num_extended_register_sets = 2, k_num_register_sets = 4 };
+enum { k_num_register_sets = 4 };
// Register sets for x86 64-bit.
static const RegisterSet g_reg_sets_x86_64[k_num_register_sets] = {
{"General Purpose Registers", "gpr", k_num_gpr_registers_x86_64,
g_gpr_regnums_x86_64},
+ {"Floating Point Registers", "fpu", k_num_fpr_registers_x86_64,
+ g_fpu_regnums_x86_64},
+ {"Extended State Registers", "xstate",
+ k_num_avx_registers_x86_64 + k_num_mpx_registers_x86_64,
+ g_xstate_regnums_x86_64},
+ {"Debug Registers", "dbr", k_num_dbr_registers_x86_64,
+ g_dbr_regnums_x86_64},
};
#define REG_CONTEXT_SIZE (GetRegisterInfoInterface().GetGPRSize())
@@ -667,11 +725,6 @@ Status NativeRegisterContextNetBSD_x86_64::ReadAllRegisterValues(
::memcpy(dst, &m_gpr_x86_64, GetRegisterInfoInterface().GetGPRSize());
dst += GetRegisterInfoInterface().GetGPRSize();
- RegisterValue value((uint64_t)-1);
- const RegisterInfo *reg_info =
- GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_eax");
- if (reg_info == nullptr)
- reg_info = GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_rax");
return error;
}
@@ -795,10 +848,10 @@ Status NativeRegisterContextNetBSD_x86_64::SetHardwareWatchpointWithIndex(
if (!is_vacant)
return Status("Watchpoint index not vacant");
- RegisterValue reg_value;
const RegisterInfo *const reg_info_dr7 =
GetRegisterInfoAtIndex(lldb_dr7_x86_64);
- error = ReadRegister(reg_info_dr7, reg_value);
+ RegisterValue dr7_value;
+ error = ReadRegister(reg_info_dr7, dr7_value);
if (error.Fail())
return error;
@@ -816,16 +869,28 @@ Status NativeRegisterContextNetBSD_x86_64::SetHardwareWatchpointWithIndex(
uint64_t bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
- uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
+ uint64_t control_bits = dr7_value.GetAsUInt64() & ~bit_mask;
control_bits |= enable_bit | rw_bits | size_bits;
const RegisterInfo *const reg_info_drN =
GetRegisterInfoAtIndex(lldb_dr0_x86_64 + wp_index);
- error = WriteRegister(reg_info_drN, RegisterValue(addr));
+ RegisterValue drN_value;
+ error = ReadRegister(reg_info_drN, drN_value);
if (error.Fail())
return error;
+ // clear dr6 if address or bits changed (i.e. we're not reenabling the same
+ // watchpoint)
+ if (drN_value.GetAsUInt64() != addr ||
+ (dr7_value.GetAsUInt64() & bit_mask) != (rw_bits | size_bits)) {
+ ClearWatchpointHit(wp_index);
+
+ error = WriteRegister(reg_info_drN, RegisterValue(addr));
+ if (error.Fail())
+ return error;
+ }
+
error = WriteRegister(reg_info_dr7, RegisterValue(control_bits));
if (error.Fail())
return error;
@@ -839,32 +904,36 @@ bool NativeRegisterContextNetBSD_x86_64::ClearHardwareWatchpoint(
if (wp_index >= NumSupportedHardwareWatchpoints())
return false;
+ // for watchpoints 0, 1, 2, or 3, respectively, clear bits 0-1, 2-3, 4-5
+ // or 6-7 of the debug control register (DR7)
+ const RegisterInfo *const reg_info_dr7 =
+ GetRegisterInfoAtIndex(lldb_dr7_x86_64);
RegisterValue reg_value;
+ Status error = ReadRegister(reg_info_dr7, reg_value);
+ if (error.Fail())
+ return false;
+ uint64_t bit_mask = 0x3 << (2 * wp_index);
+ uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
- // for watchpoints 0, 1, 2, or 3, respectively, clear bits 0, 1, 2, or 3 of
+ return WriteRegister(reg_info_dr7, RegisterValue(control_bits)).Success();
+}
+
+Status NativeRegisterContextNetBSD_x86_64::ClearWatchpointHit(uint32_t wp_index) {
+ if (wp_index >= NumSupportedHardwareWatchpoints())
+ return Status("Watchpoint index out of range");
+
+ // for watchpoints 0, 1, 2, or 3, respectively, check bits 0, 1, 2, or 3 of
// the debug status register (DR6)
const RegisterInfo *const reg_info_dr6 =
GetRegisterInfoAtIndex(lldb_dr6_x86_64);
+ RegisterValue reg_value;
Status error = ReadRegister(reg_info_dr6, reg_value);
if (error.Fail())
- return false;
+ return error;
+
uint64_t bit_mask = 1 << wp_index;
uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask;
- error = WriteRegister(reg_info_dr6, RegisterValue(status_bits));
- if (error.Fail())
- return false;
-
- // for watchpoints 0, 1, 2, or 3, respectively, clear bits {0-1,16-19},
- // {2-3,20-23}, {4-5,24-27}, or {6-7,28-31} of the debug control register
- // (DR7)
- const RegisterInfo *const reg_info_dr7 =
- GetRegisterInfoAtIndex(lldb_dr7_x86_64);
- error = ReadRegister(reg_info_dr7, reg_value);
- if (error.Fail())
- return false;
- bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
- uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
- return WriteRegister(reg_info_dr7, RegisterValue(control_bits)).Success();
+ return WriteRegister(reg_info_dr6, RegisterValue(status_bits));
}
Status NativeRegisterContextNetBSD_x86_64::ClearAllHardwareWatchpoints() {
@@ -930,4 +999,19 @@ uint32_t NativeRegisterContextNetBSD_x86_64::NumSupportedHardwareWatchpoints() {
return 4;
}
+Status NativeRegisterContextNetBSD_x86_64::CopyHardwareWatchpointsFrom(
+ NativeRegisterContextNetBSD &source) {
+ auto &r_source = static_cast<NativeRegisterContextNetBSD_x86_64&>(source);
+ Status res = r_source.ReadRegisterSet(DBRegSet);
+ if (!res.Fail()) {
+ // copy dbregs only if any watchpoints were set
+ if ((r_source.m_dbr_x86_64.dr[7] & 0xFF) == 0)
+ return res;
+
+ m_dbr_x86_64 = r_source.m_dbr_x86_64;
+ res = WriteRegisterSet(DBRegSet);
+ }
+ return res;
+}
+
#endif // defined(__x86_64__)
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h
index 0fed16542a95..54b8a806267f 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h
+++ b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h
@@ -58,6 +58,8 @@ public:
bool ClearHardwareWatchpoint(uint32_t wp_index) override;
+ Status ClearWatchpointHit(uint32_t wp_index) override;
+
Status ClearAllHardwareWatchpoints() override;
Status SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size,
@@ -71,9 +73,12 @@ public:
uint32_t NumSupportedHardwareWatchpoints() override;
+ Status
+ CopyHardwareWatchpointsFrom(NativeRegisterContextNetBSD &source) override;
+
private:
// Private member types.
- enum { GPRegSet, FPRegSet, DBRegSet, XStateRegSet };
+ enum { GPRegSet, FPRegSet, XStateRegSet, DBRegSet };
// Private member variables.
struct reg m_gpr_x86_64;
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
index e25975c93446..dd2745d9330e 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
+++ b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
@@ -16,9 +16,20 @@
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/State.h"
+#include "llvm/Support/Errno.h"
+
+// clang-format off
+#include <sys/types.h>
+#include <sys/ptrace.h>
+// clang-format on
#include <sstream>
+// clang-format off
+#include <sys/types.h>
+#include <sys/sysctl.h>
+// clang-format on
+
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_netbsd;
@@ -30,6 +41,38 @@ NativeThreadNetBSD::NativeThreadNetBSD(NativeProcessNetBSD &process,
NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD(process.GetArchitecture(), *this)
), m_stop_description() {}
+Status NativeThreadNetBSD::Resume() {
+ Status ret = NativeProcessNetBSD::PtraceWrapper(PT_RESUME, m_process.GetID(),
+ nullptr, GetID());
+ if (!ret.Success())
+ return ret;
+ ret = NativeProcessNetBSD::PtraceWrapper(PT_CLEARSTEP, m_process.GetID(),
+ nullptr, GetID());
+ if (ret.Success())
+ SetRunning();
+ return ret;
+}
+
+Status NativeThreadNetBSD::SingleStep() {
+ Status ret = NativeProcessNetBSD::PtraceWrapper(PT_RESUME, m_process.GetID(),
+ nullptr, GetID());
+ if (!ret.Success())
+ return ret;
+ ret = NativeProcessNetBSD::PtraceWrapper(PT_SETSTEP, m_process.GetID(),
+ nullptr, GetID());
+ if (ret.Success())
+ SetStepping();
+ return ret;
+}
+
+Status NativeThreadNetBSD::Suspend() {
+ Status ret = NativeProcessNetBSD::PtraceWrapper(PT_SUSPEND, m_process.GetID(),
+ nullptr, GetID());
+ if (ret.Success())
+ SetStopped();
+ return ret;
+}
+
void NativeThreadNetBSD::SetStoppedBySignal(uint32_t signo,
const siginfo_t *info) {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
@@ -89,6 +132,13 @@ void NativeThreadNetBSD::SetStoppedByWatchpoint(uint32_t wp_index) {
m_stop_info.details.signal.signo = SIGTRAP;
}
+void NativeThreadNetBSD::SetStoppedWithNoReason() {
+ SetStopped();
+
+ m_stop_info.reason = StopReason::eStopReasonNone;
+ m_stop_info.details.signal.signo = 0;
+}
+
void NativeThreadNetBSD::SetStopped() {
const StateType new_state = StateType::eStateStopped;
m_state = new_state;
@@ -105,7 +155,49 @@ void NativeThreadNetBSD::SetStepping() {
m_stop_info.reason = StopReason::eStopReasonNone;
}
-std::string NativeThreadNetBSD::GetName() { return std::string(""); }
+std::string NativeThreadNetBSD::GetName() {
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
+
+#ifdef PT_LWPSTATUS
+ struct ptrace_lwpstatus info = {};
+ info.pl_lwpid = m_tid;
+ Status error = NativeProcessNetBSD::PtraceWrapper(
+ PT_LWPSTATUS, static_cast<int>(m_process.GetID()), &info, sizeof(info));
+ if (error.Fail()) {
+ return "";
+ }
+ return info.pl_name;
+#else
+ std::vector<struct kinfo_lwp> infos;
+ int mib[5] = {CTL_KERN, KERN_LWP, static_cast<int>(m_process.GetID()),
+ sizeof(struct kinfo_lwp), 0};
+ size_t size;
+
+ if (::sysctl(mib, 5, nullptr, &size, nullptr, 0) == -1 || size == 0) {
+ LLDB_LOG(log, "sysctl() for LWP info size failed: {0}",
+ llvm::sys::StrError());
+ return "";
+ }
+
+ mib[4] = size / sizeof(size_t);
+ infos.resize(size / sizeof(struct kinfo_lwp));
+
+ if (sysctl(mib, 5, infos.data(), &size, NULL, 0) == -1 || size == 0) {
+ LLDB_LOG(log, "sysctl() for LWP info failed: {0}", llvm::sys::StrError());
+ return "";
+ }
+
+ size_t nlwps = size / sizeof(struct kinfo_lwp);
+ for (size_t i = 0; i < nlwps; i++) {
+ if (static_cast<lldb::tid_t>(infos[i].l_lid) == m_tid) {
+ return infos[i].l_name;
+ }
+ }
+
+ LLDB_LOG(log, "unable to find lwp {0} in LWP infos", m_tid);
+ return "";
+#endif
+}
lldb::StateType NativeThreadNetBSD::GetState() { return m_state; }
@@ -140,9 +232,9 @@ bool NativeThreadNetBSD::GetStopReason(ThreadStopInfo &stop_info,
llvm_unreachable("unhandled StateType!");
}
-NativeRegisterContext& NativeThreadNetBSD::GetRegisterContext() {
+NativeRegisterContextNetBSD &NativeThreadNetBSD::GetRegisterContext() {
assert(m_reg_context_up);
-return *m_reg_context_up;
+ return *m_reg_context_up;
}
Status NativeThreadNetBSD::SetWatchpoint(lldb::addr_t addr, size_t size,
@@ -203,3 +295,13 @@ Status NativeThreadNetBSD::RemoveHardwareBreakpoint(lldb::addr_t addr) {
return Status("Clearing hardware breakpoint failed.");
}
+
+Status NativeThreadNetBSD::CopyWatchpointsFrom(NativeThreadNetBSD &source) {
+ Status s = GetRegisterContext().CopyHardwareWatchpointsFrom(
+ source.GetRegisterContext());
+ if (!s.Fail()) {
+ m_watchpoint_index_map = source.m_watchpoint_index_map;
+ m_hw_break_index_map = source.m_hw_break_index_map;
+ }
+ return s;
+}
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h
index 015d8995db34..89b61ef86722 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h
+++ b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h
@@ -11,6 +11,8 @@
#include "lldb/Host/common/NativeThreadProtocol.h"
+#include "Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h"
+
#include <csignal>
#include <map>
#include <string>
@@ -34,7 +36,7 @@ public:
bool GetStopReason(ThreadStopInfo &stop_info,
std::string &description) override;
- NativeRegisterContext& GetRegisterContext() override;
+ NativeRegisterContextNetBSD &GetRegisterContext() override;
Status SetWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags,
bool hardware) override;
@@ -48,19 +50,26 @@ public:
private:
// Interface for friend classes
+ Status Resume();
+ Status SingleStep();
+ Status Suspend();
+
void SetStoppedBySignal(uint32_t signo, const siginfo_t *info = nullptr);
void SetStoppedByBreakpoint();
void SetStoppedByTrace();
void SetStoppedByExec();
void SetStoppedByWatchpoint(uint32_t wp_index);
+ void SetStoppedWithNoReason();
void SetStopped();
void SetRunning();
void SetStepping();
+ Status CopyWatchpointsFrom(NativeThreadNetBSD& source);
+
// Member Variables
lldb::StateType m_state;
ThreadStopInfo m_stop_info;
- std::unique_ptr<NativeRegisterContext> m_reg_context_up;
+ std::unique_ptr<NativeRegisterContextNetBSD> m_reg_context_up;
std::string m_stop_description;
using WatchpointIndexMap = std::map<lldb::addr_t, uint32_t>;
WatchpointIndexMap m_watchpoint_index_map;
diff --git a/lldb/source/Plugins/Process/POSIX/CrashReason.cpp b/lldb/source/Plugins/Process/POSIX/CrashReason.cpp
index 9678e48436e7..b872269fdfe1 100644
--- a/lldb/source/Plugins/Process/POSIX/CrashReason.cpp
+++ b/lldb/source/Plugins/Process/POSIX/CrashReason.cpp
@@ -136,15 +136,15 @@ std::string GetCrashReasonString(CrashReason reason, const siginfo_t &info) {
#if defined(si_lower) && defined(si_upper)
if (reason == CrashReason::eBoundViolation) {
str = "signal SIGSEGV";
- AppendBounds(str, reinterpret_cast<lldb::addr_t>(info.si_lower),
- reinterpret_cast<lldb::addr_t>(info.si_upper),
- reinterpret_cast<lldb::addr_t>(info.si_addr));
+ AppendBounds(str, reinterpret_cast<uintptr_t>(info.si_lower),
+ reinterpret_cast<uintptr_t>(info.si_upper),
+ reinterpret_cast<uintptr_t>(info.si_addr));
return str;
}
#endif
return GetCrashReasonString(reason,
- reinterpret_cast<lldb::addr_t>(info.si_addr));
+ reinterpret_cast<uintptr_t>(info.si_addr));
}
std::string GetCrashReasonString(CrashReason reason, lldb::addr_t fault_addr) {
diff --git a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
index 2ccbeacc4960..ee939b01d350 100644
--- a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
+++ b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
@@ -20,7 +20,7 @@
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
-#ifndef LLDB_DISABLE_POSIX
+#if LLDB_ENABLE_POSIX
#include <sys/mman.h>
#else
// define them
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
index 4ca33c248c6f..173e66904151 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
@@ -21,12 +21,6 @@
#include <memory>
-// Support building against older versions of LLVM, this macro was added
-// recently.
-#ifndef LLVM_EXTENSION
-#define LLVM_EXTENSION
-#endif
-
#include "Utility/ARM_DWARF_Registers.h"
#include "Utility/ARM_ehframe_Registers.h"
@@ -1146,10 +1140,11 @@ bool RegisterContextDarwin_arm::ReadRegister(const RegisterInfo *reg_info,
case gpr_sp:
case gpr_lr:
case gpr_pc:
- case gpr_cpsr:
value.SetUInt32(gpr.r[reg - gpr_r0]);
break;
-
+ case gpr_cpsr:
+ value.SetUInt32(gpr.cpsr);
+ break;
case fpu_s0:
case fpu_s1:
case fpu_s2:
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
index b3ec24d8905d..fa5197cd6bf4 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
@@ -30,12 +30,6 @@
#include <sys/sysctl.h>
#endif
-// Support building against older versions of LLVM, this macro was added
-// recently.
-#ifndef LLVM_EXTENSION
-#define LLVM_EXTENSION
-#endif
-
#include "Utility/ARM64_DWARF_Registers.h"
using namespace lldb;
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
index 873713fd8373..959b04700b17 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
@@ -19,12 +19,6 @@
#include <memory>
-// Support building against older versions of LLVM, this macro was added
-// recently.
-#ifndef LLVM_EXTENSION
-#define LLVM_EXTENSION
-#endif
-
#include "RegisterContextDarwin_i386.h"
using namespace lldb;
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
index 47758ce85eb2..22088a7d6448 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
@@ -21,12 +21,6 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Compiler.h"
-// Support building against older versions of LLVM, this macro was added
-// recently.
-#ifndef LLVM_EXTENSION
-#define LLVM_EXTENSION
-#endif
-
#include "RegisterContextDarwin_x86_64.h"
using namespace lldb;
diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64.h b/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64.h
index 4a3b3c73fd6b..af3027afa73c 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64.h
@@ -25,15 +25,18 @@
LLVM_EXTENSION offsetof(FPR, xsave) + \
LLVM_EXTENSION offsetof(XSAVE, ymmh[0]) + (32 * reg_index))
+// Guarantees BNDR/BNDC offsets do not overlap with YMM offsets.
+#define GDB_REMOTE_OFFSET 128
+
#define BNDR_OFFSET(reg_index) \
(LLVM_EXTENSION offsetof(UserArea, fpr) + \
LLVM_EXTENSION offsetof(FPR, xsave) + \
- LLVM_EXTENSION offsetof(XSAVE, mpxr[reg_index]))
+ LLVM_EXTENSION offsetof(XSAVE, mpxr[reg_index]) + GDB_REMOTE_OFFSET)
#define BNDC_OFFSET(reg_index) \
(LLVM_EXTENSION offsetof(UserArea, fpr) + \
LLVM_EXTENSION offsetof(FPR, xsave) + \
- LLVM_EXTENSION offsetof(XSAVE, mpxc[reg_index]))
+ LLVM_EXTENSION offsetof(XSAVE, mpxc[reg_index]) + GDB_REMOTE_OFFSET)
#ifdef DECLARE_REGISTER_INFOS_X86_64_STRUCT
diff --git a/lldb/source/Plugins/Process/Utility/lldb-x86-register-enums.h b/lldb/source/Plugins/Process/Utility/lldb-x86-register-enums.h
index 0d2149c83573..bfdd586d9ded 100644
--- a/lldb/source/Plugins/Process/Utility/lldb-x86-register-enums.h
+++ b/lldb/source/Plugins/Process/Utility/lldb-x86-register-enums.h
@@ -294,7 +294,8 @@ enum {
lldb_bndstatus_x86_64,
k_last_mpxc_x86_64 = lldb_bndstatus_x86_64,
- lldb_dr0_x86_64,
+ k_first_dbr_x86_64,
+ lldb_dr0_x86_64 = k_first_dbr_x86_64,
lldb_dr1_x86_64,
lldb_dr2_x86_64,
lldb_dr3_x86_64,
@@ -302,6 +303,7 @@ enum {
lldb_dr5_x86_64,
lldb_dr6_x86_64,
lldb_dr7_x86_64,
+ k_last_dbr_x86_64 = lldb_dr7_x86_64,
k_num_registers_x86_64,
k_num_gpr_registers_x86_64 = k_last_gpr_x86_64 - k_first_gpr_x86_64 + 1,
@@ -312,6 +314,7 @@ enum {
k_num_fpr_registers_x86_64 +
k_num_avx_registers_x86_64 +
k_num_mpx_registers_x86_64,
+ k_num_dbr_registers_x86_64 = k_last_dbr_x86_64 - k_first_dbr_x86_64 + 1,
};
}
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 144ae103faa4..7cea013eea7f 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -31,6 +31,7 @@
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegularExpression.h"
+#include "lldb/Utility/Reproducer.h"
#include "lldb/Utility/StreamString.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ScopedPrinter.h"
@@ -49,7 +50,7 @@
#include <compression.h>
#endif
-#if defined(HAVE_LIBZ)
+#if LLVM_ENABLE_ZLIB
#include <zlib.h>
#endif
@@ -581,7 +582,7 @@ bool GDBRemoteCommunication::DecompressPacket() {
}
#endif
-#if defined(HAVE_LIBZ)
+#if LLVM_ENABLE_ZLIB
if (decompressed_bytes == 0 && decompressed_bufsize != ULONG_MAX &&
decompressed_buffer != nullptr &&
m_compression_type == CompressionType::ZlibDeflate) {
@@ -1243,8 +1244,9 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
void GDBRemoteCommunication::DumpHistory(Stream &strm) { m_history.Dump(strm); }
-void GDBRemoteCommunication::SetHistoryStream(llvm::raw_ostream *strm) {
- m_history.SetStream(strm);
+void GDBRemoteCommunication::SetPacketRecorder(
+ repro::PacketRecorder *recorder) {
+ m_history.SetRecorder(recorder);
}
llvm::Error
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
index bb777a5c26a7..0b670018bd69 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
@@ -27,6 +27,9 @@
#include "lldb/lldb-public.h"
namespace lldb_private {
+namespace repro {
+class PacketRecorder;
+}
namespace process_gdb_remote {
enum GDBStoppointType {
@@ -133,7 +136,8 @@ public:
// fork/exec to avoid having to connect/accept
void DumpHistory(Stream &strm);
- void SetHistoryStream(llvm::raw_ostream *strm);
+
+ void SetPacketRecorder(repro::PacketRecorder *recorder);
static llvm::Error ConnectLocally(GDBRemoteCommunication &client,
GDBRemoteCommunication &server);
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index feb9f0589cee..b2f1ee527e8b 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -543,21 +543,24 @@ GDBRemoteCommunicationClient::SendThreadSpecificPacketAndWaitForResponse(
//
// Takes a valid thread ID because p needs to apply to a thread.
bool GDBRemoteCommunicationClient::GetpPacketSupported(lldb::tid_t tid) {
- if (m_supports_p == eLazyBoolCalculate) {
- m_supports_p = eLazyBoolNo;
- StreamString payload;
- payload.PutCString("p0");
- StringExtractorGDBRemote response;
- if (SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload),
- response, false) ==
- PacketResult::Success &&
- response.IsNormalResponse()) {
- m_supports_p = eLazyBoolYes;
- }
- }
+ if (m_supports_p == eLazyBoolCalculate)
+ m_supports_p = GetThreadPacketSupported(tid, "p0");
return m_supports_p;
}
+LazyBool GDBRemoteCommunicationClient::GetThreadPacketSupported(
+ lldb::tid_t tid, llvm::StringRef packetStr) {
+ StreamString payload;
+ payload.PutCString(packetStr);
+ StringExtractorGDBRemote response;
+ if (SendThreadSpecificPacketAndWaitForResponse(
+ tid, std::move(payload), response, false) == PacketResult::Success &&
+ response.IsNormalResponse()) {
+ return eLazyBoolYes;
+ }
+ return eLazyBoolNo;
+}
+
StructuredData::ObjectSP GDBRemoteCommunicationClient::GetThreadsInfo() {
// Get information on all threads at one using the "jThreadsInfo" packet
StructuredData::ObjectSP object_sp;
@@ -1042,7 +1045,7 @@ void GDBRemoteCommunicationClient::MaybeEnableCompression(
}
#endif
-#if defined(HAVE_LIBZ)
+#if LLVM_ENABLE_ZLIB
if (avail_type == CompressionType::None) {
for (auto compression : supported_compressions) {
if (compression == "zlib-deflate") {
@@ -3737,7 +3740,7 @@ bool GDBRemoteCommunicationClient::ReadExtFeature(
case ('m'):
if (str.length() > 1)
output << &str[1];
- offset += size;
+ offset += str.length() - 1;
break;
// unknown chunk
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index 574cd0fd70c5..11fd40bce44f 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -89,7 +89,7 @@ public:
/// Sends a GDB remote protocol 'A' packet that delivers program
/// arguments to the remote server.
///
- /// \param[in] argv
+ /// \param[in] launch_info
/// A NULL terminated array of const C strings to use as the
/// arguments.
///
@@ -155,7 +155,7 @@ public:
/// Sets the path to use for stdin/out/err for a process
/// that will be launched with the 'A' packet.
///
- /// \param[in] path
+ /// \param[in] file_spec
/// The path to use for stdin/out/err
///
/// \return
@@ -596,6 +596,8 @@ protected:
Status GetQXferMemoryMapRegionInfo(lldb::addr_t addr,
MemoryRegionInfo &region);
+ LazyBool GetThreadPacketSupported(lldb::tid_t tid, llvm::StringRef packetStr);
+
private:
DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunicationClient);
};
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp
index d2cc32f63f20..9e5646985f87 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp
@@ -40,8 +40,8 @@ void GDBRemoteCommunicationHistory::AddPacket(char packet_char,
m_packets[idx].bytes_transmitted = bytes_transmitted;
m_packets[idx].packet_idx = m_total_packet_count;
m_packets[idx].tid = llvm::get_threadid();
- if (m_stream)
- m_packets[idx].Serialize(*m_stream);
+ if (m_recorder)
+ m_recorder->Record(m_packets[idx]);
}
void GDBRemoteCommunicationHistory::AddPacket(const std::string &src,
@@ -58,8 +58,8 @@ void GDBRemoteCommunicationHistory::AddPacket(const std::string &src,
m_packets[idx].bytes_transmitted = bytes_transmitted;
m_packets[idx].packet_idx = m_total_packet_count;
m_packets[idx].tid = llvm::get_threadid();
- if (m_stream)
- m_packets[idx].Serialize(*m_stream);
+ if (m_recorder)
+ m_recorder->Record(m_packets[idx]);
}
void GDBRemoteCommunicationHistory::Dump(Stream &strm) const {
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h
index c006fbd34a4b..ee265ef86dff 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h
@@ -13,11 +13,15 @@
#include <vector>
#include "lldb/Utility/GDBRemote.h"
+#include "lldb/Utility/Reproducer.h"
#include "lldb/lldb-public.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"
namespace lldb_private {
+namespace repro {
+class PacketRecorder;
+}
namespace process_gdb_remote {
/// The history keeps a circular buffer of GDB remote packets. The history is
@@ -41,7 +45,7 @@ public:
void Dump(Log *log) const;
bool DidDumpToLog() const { return m_dumped_to_log; }
- void SetStream(llvm::raw_ostream *strm) { m_stream = strm; }
+ void SetRecorder(repro::PacketRecorder *recorder) { m_recorder = recorder; }
private:
uint32_t GetFirstSavedPacketIndex() const {
@@ -73,7 +77,7 @@ private:
uint32_t m_curr_idx;
uint32_t m_total_packet_count;
mutable bool m_dumped_to_log;
- llvm::raw_ostream *m_stream = nullptr;
+ repro::PacketRecorder *m_recorder = nullptr;
};
} // namespace process_gdb_remote
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp
index 2d26c550dc76..15c73e78bd44 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp
@@ -143,7 +143,14 @@ GDBRemoteCommunicationReplayServer::GetPacketAndSendResponse(
entry.packet.data);
LLDB_LOG(log, "GDBRemoteCommunicationReplayServer actual packet: '{0}'",
packet.GetStringRef());
- assert(false && "Encountered unexpected packet during replay");
+#ifndef NDEBUG
+ // This behaves like a regular assert, but prints the expected and
+ // received packet before aborting.
+ printf("Reproducer expected packet: '%s'\n", entry.packet.data.c_str());
+ printf("Reproducer received packet: '%s'\n",
+ packet.GetStringRef().data());
+ llvm::report_fatal_error("Encountered unexpected packet during replay");
+#endif
return PacketResult::ErrorSendFailed;
}
@@ -204,9 +211,9 @@ bool GDBRemoteCommunicationReplayServer::StartAsyncThread() {
"<lldb.gdb-replay.async>",
GDBRemoteCommunicationReplayServer::AsyncThread, this);
if (!async_thread) {
- LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST),
- "failed to launch host thread: {}",
- llvm::toString(async_thread.takeError()));
+ LLDB_LOG_ERROR(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST),
+ async_thread.takeError(),
+ "failed to launch host thread: {}");
return false;
}
m_async_thread = *async_thread;
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
index 37980d914dc2..4b5fc0774a6d 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
@@ -429,7 +429,7 @@ GDBRemoteCommunicationServerCommon::Handle_qsProcessInfo(
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerCommon::Handle_qUserName(
StringExtractorGDBRemote &packet) {
-#if !defined(LLDB_DISABLE_POSIX)
+#if LLDB_ENABLE_POSIX
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
LLDB_LOGF(log, "GDBRemoteCommunicationServerCommon::%s begin", __FUNCTION__);
@@ -452,7 +452,7 @@ GDBRemoteCommunicationServerCommon::Handle_qUserName(
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerCommon::Handle_qGroupName(
StringExtractorGDBRemote &packet) {
-#if !defined(LLDB_DISABLE_POSIX)
+#if LLDB_ENABLE_POSIX
// Packet format: "qGroupName:%i" where %i is the gid
packet.SetFilePos(::strlen("qGroupName:"));
uint32_t gid = packet.GetU32(UINT32_MAX);
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index ad1a39b57969..f33f0ee66304 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -669,9 +669,9 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
response.PutStringAsRawHex8(unescaped_response.GetData());
response.PutChar(';');
} else {
- LLDB_LOG(log, "failed to prepare a jstopinfo field for pid {0}:",
- m_debugged_process_up->GetID(),
- llvm::toString(threads_info.takeError()));
+ LLDB_LOG_ERROR(log, threads_info.takeError(),
+ "failed to prepare a jstopinfo field for pid {1}: {0}",
+ m_debugged_process_up->GetID());
}
}
@@ -2013,7 +2013,7 @@ GDBRemoteCommunicationServerLLGS::Handle_p(StringExtractorGDBRemote &packet) {
}
const uint8_t *const data =
- reinterpret_cast<const uint8_t *>(reg_value.GetBytes());
+ static_cast<const uint8_t *>(reg_value.GetBytes());
if (!data) {
LLDB_LOGF(log,
"GDBRemoteCommunicationServerLLGS::%s failed to get data "
@@ -3087,9 +3087,9 @@ GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo(
llvm::Expected<json::Value> threads_info = GetJSONThreadsInfo(
*m_debugged_process_up, threads_with_valid_stop_info_only);
if (!threads_info) {
- LLDB_LOG(log, "failed to prepare a packet for pid {0}: {1}",
- m_debugged_process_up->GetID(),
- llvm::toString(threads_info.takeError()));
+ LLDB_LOG_ERROR(log, threads_info.takeError(),
+ "failed to prepare a packet for pid {1}: {0}",
+ m_debugged_process_up->GetID());
return SendErrorResponse(52);
}
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
index c06c9527708e..ec1a54afd727 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -31,9 +31,11 @@ using namespace lldb_private::process_gdb_remote;
// GDBRemoteRegisterContext constructor
GDBRemoteRegisterContext::GDBRemoteRegisterContext(
ThreadGDBRemote &thread, uint32_t concrete_frame_idx,
- GDBRemoteDynamicRegisterInfo &reg_info, bool read_all_at_once)
+ GDBRemoteDynamicRegisterInfo &reg_info, bool read_all_at_once,
+ bool write_all_at_once)
: RegisterContext(thread, concrete_frame_idx), m_reg_info(reg_info),
- m_reg_valid(), m_reg_data(), m_read_all_at_once(read_all_at_once) {
+ m_reg_valid(), m_reg_data(), m_read_all_at_once(read_all_at_once),
+ m_write_all_at_once(write_all_at_once) {
// Resize our vector of bools to contain one bool for every register. We will
// use these boolean values to know when a register value is valid in
// m_reg_data.
@@ -87,6 +89,9 @@ bool GDBRemoteRegisterContext::ReadRegister(const RegisterInfo *reg_info,
RegisterValue &value) {
// Read the register
if (ReadRegisterBytes(reg_info, m_reg_data)) {
+ const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+ if (m_reg_valid[reg] == false)
+ return false;
const bool partial_data_ok = false;
Status error(value.SetValueFromData(
reg_info, m_reg_data, reg_info->byte_offset, partial_data_ok));
@@ -203,6 +208,18 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info,
if (buffer_sp->GetByteSize() >= m_reg_data.GetByteSize()) {
SetAllRegisterValid(true);
return true;
+ } else if (buffer_sp->GetByteSize() > 0) {
+ const int regcount = m_reg_info.GetNumRegisters();
+ for (int i = 0; i < regcount; i++) {
+ struct RegisterInfo *reginfo = m_reg_info.GetRegisterInfoAtIndex(i);
+ if (reginfo->byte_offset + reginfo->byte_size
+ <= buffer_sp->GetByteSize()) {
+ m_reg_valid[i] = true;
+ } else {
+ m_reg_valid[i] = false;
+ }
+ }
+ return true;
} else {
Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_THREAD |
GDBR_LOG_PACKETS));
@@ -333,7 +350,7 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info,
{
GDBRemoteClientBase::Lock lock(gdb_comm, false);
if (lock) {
- if (m_read_all_at_once) {
+ if (m_write_all_at_once) {
// Invalidate all register values
InvalidateIfNeeded(true);
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
index 25e9b716f8cb..b42c87b5991b 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
@@ -41,7 +41,7 @@ class GDBRemoteRegisterContext : public RegisterContext {
public:
GDBRemoteRegisterContext(ThreadGDBRemote &thread, uint32_t concrete_frame_idx,
GDBRemoteDynamicRegisterInfo &reg_info,
- bool read_all_at_once);
+ bool read_all_at_once, bool write_all_at_once);
~GDBRemoteRegisterContext() override;
@@ -114,6 +114,7 @@ protected:
std::vector<bool> m_reg_valid;
DataExtractor m_reg_data;
bool m_read_all_at_once;
+ bool m_write_all_at_once;
private:
// Helper function for ReadRegisterBytes().
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index f1762abc55f8..a49db5d9a934 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -10,7 +10,7 @@
#include <errno.h>
#include <stdlib.h>
-#ifndef LLDB_DISABLE_POSIX
+#if LLDB_ENABLE_POSIX
#include <netinet/in.h>
#include <sys/mman.h>
#include <sys/socket.h>
@@ -154,6 +154,11 @@ public:
nullptr, idx,
g_processgdbremote_properties[idx].default_uint_value != 0);
}
+
+ bool GetUseGPacketForReading() const {
+ const uint32_t idx = ePropertyUseGPacketForReading;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
+ }
};
typedef std::shared_ptr<PluginProperties> ProcessKDPPropertiesSP;
@@ -274,12 +279,9 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp,
"async thread did exit");
if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator()) {
- repro::ProcessGDBRemoteProvider &provider =
- g->GetOrCreate<repro::ProcessGDBRemoteProvider>();
- // Set the history stream to the stream owned by the provider.
- m_gdb_comm.SetHistoryStream(provider.GetHistoryStream());
- // Make sure to clear the stream again when we're finished.
- provider.SetCallback([&]() { m_gdb_comm.SetHistoryStream(nullptr); });
+ repro::GDBRemoteProvider &provider =
+ g->GetOrCreate<repro::GDBRemoteProvider>();
+ m_gdb_comm.SetPacketRecorder(provider.GetNewPacketRecorder());
}
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_ASYNC));
@@ -309,6 +311,9 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp,
GetGlobalPluginProperties()->GetPacketTimeout();
if (timeout_seconds > 0)
m_gdb_comm.SetPacketTimeout(std::chrono::seconds(timeout_seconds));
+
+ m_use_g_packet_for_reading =
+ GetGlobalPluginProperties()->GetUseGPacketForReading();
}
// Destructor
@@ -380,36 +385,6 @@ bool ProcessGDBRemote::ParsePythonTargetDefinition(
return false;
}
-// If the remote stub didn't give us eh_frame or DWARF register numbers for a
-// register, see if the ABI can provide them.
-// DWARF and eh_frame register numbers are defined as a part of the ABI.
-static void AugmentRegisterInfoViaABI(RegisterInfo &reg_info,
- ConstString reg_name, ABISP abi_sp) {
- if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM ||
- reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM) {
- if (abi_sp) {
- RegisterInfo abi_reg_info;
- if (abi_sp->GetRegisterInfoByName(reg_name, abi_reg_info)) {
- if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM &&
- abi_reg_info.kinds[eRegisterKindEHFrame] != LLDB_INVALID_REGNUM) {
- reg_info.kinds[eRegisterKindEHFrame] =
- abi_reg_info.kinds[eRegisterKindEHFrame];
- }
- if (reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM &&
- abi_reg_info.kinds[eRegisterKindDWARF] != LLDB_INVALID_REGNUM) {
- reg_info.kinds[eRegisterKindDWARF] =
- abi_reg_info.kinds[eRegisterKindDWARF];
- }
- if (reg_info.kinds[eRegisterKindGeneric] == LLDB_INVALID_REGNUM &&
- abi_reg_info.kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM) {
- reg_info.kinds[eRegisterKindGeneric] =
- abi_reg_info.kinds[eRegisterKindGeneric];
- }
- }
- }
- }
-}
-
static size_t SplitCommaSeparatedRegisterNumberString(
const llvm::StringRef &comma_separated_regiter_numbers,
std::vector<uint32_t> &regnums, int base) {
@@ -607,12 +582,12 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) {
reg_info.invalidate_regs = invalidate_regs.data();
}
+ reg_info.name = reg_name.AsCString();
// We have to make a temporary ABI here, and not use the GetABI because
// this code gets called in DidAttach, when the target architecture
// (and consequently the ABI we'll get from the process) may be wrong.
- ABISP abi_to_use = ABI::FindPlugin(shared_from_this(), arch_to_use);
-
- AugmentRegisterInfoViaABI(reg_info, reg_name, abi_to_use);
+ if (ABISP abi_sp = ABI::FindPlugin(shared_from_this(), arch_to_use))
+ abi_sp->AugmentRegisterInfo(reg_info);
m_register_info.AddRegister(reg_info, reg_name, alt_name, set_name);
} else {
@@ -2374,21 +2349,22 @@ void ProcessGDBRemote::RefreshStateAfterStop() {
m_thread_ids.clear();
m_thread_pcs.clear();
+
// Set the thread stop info. It might have a "threads" key whose value is a
// list of all thread IDs in the current process, so m_thread_ids might get
// set.
+ // Check to see if SetThreadStopInfo() filled in m_thread_ids?
+ if (m_thread_ids.empty()) {
+ // No, we need to fetch the thread list manually
+ UpdateThreadIDList();
+ }
+
+ // We might set some stop info's so make sure the thread list is up to
+ // date before we do that or we might overwrite what was computed here.
+ UpdateThreadListIfNeeded();
// Scope for the lock
{
- // Check to see if SetThreadStopInfo() filled in m_thread_ids?
- if (m_thread_ids.empty()) {
- // No, we need to fetch the thread list manually
- UpdateThreadIDList();
- }
- // We might set some stop info's so make sure the thread list is up to
- // date before we do that or we might overwrite what was computed here.
- UpdateThreadListIfNeeded();
-
// Lock the thread stack while we access it
std::lock_guard<std::recursive_mutex> guard(m_last_stop_packet_mutex);
// Get the number of stop packets on the stack
@@ -3384,17 +3360,20 @@ Status ProcessGDBRemote::ConnectToReplayServer(repro::Loader *loader) {
if (!loader)
return Status("No loader provided.");
- // Construct replay history path.
- FileSpec history_file =
- loader->GetFile<repro::ProcessGDBRemoteProvider::Info>();
- if (!history_file)
- return Status("No provider for gdb-remote.");
+ static std::unique_ptr<repro::MultiLoader<repro::GDBRemoteProvider>>
+ multi_loader = repro::MultiLoader<repro::GDBRemoteProvider>::Create(
+ repro::Reproducer::Instance().GetLoader());
- // Enable replay mode.
- m_replay_mode = true;
+ if (!multi_loader)
+ return Status("No gdb remote provider found.");
+
+ llvm::Optional<std::string> history_file = multi_loader->GetNextFile();
+ if (!history_file)
+ return Status("No gdb remote packet log found.");
// Load replay history.
- if (auto error = m_gdb_replay_server.LoadReplayHistory(history_file))
+ if (auto error =
+ m_gdb_replay_server.LoadReplayHistory(FileSpec(*history_file)))
return Status("Unable to load replay history");
// Make a local connection.
@@ -3402,6 +3381,9 @@ Status ProcessGDBRemote::ConnectToReplayServer(repro::Loader *loader) {
m_gdb_replay_server))
return Status("Unable to connect to replay server");
+ // Enable replay mode.
+ m_replay_mode = true;
+
// Start server thread.
m_gdb_replay_server.StartAsyncThread();
@@ -3627,9 +3609,9 @@ bool ProcessGDBRemote::StartAsyncThread() {
llvm::Expected<HostThread> async_thread = ThreadLauncher::LaunchThread(
"<lldb.process.gdb-remote.async>", ProcessGDBRemote::AsyncThread, this);
if (!async_thread) {
- LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST),
- "failed to launch host thread: {}",
- llvm::toString(async_thread.takeError()));
+ LLDB_LOG_ERROR(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST),
+ async_thread.takeError(),
+ "failed to launch host thread: {}");
return false;
}
m_async_thread = *async_thread;
@@ -4475,7 +4457,9 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info,
}
++cur_reg_num;
- AugmentRegisterInfoViaABI(reg_info, reg_name, abi_sp);
+ reg_info.name = reg_name.AsCString();
+ if (abi_sp)
+ abi_sp->AugmentRegisterInfo(reg_info);
dyn_reg_info.AddRegister(reg_info, reg_name, alt_name, set_name);
return true; // Keep iterating through all "reg" elements
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 0e3e3b39d9c8..9ea3940103b6 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -284,6 +284,7 @@ protected:
lldb::CommandObjectSP m_command_sp;
int64_t m_breakpoint_pc_offset;
lldb::tid_t m_initial_tid; // The initial thread ID, given by stub on attach
+ bool m_use_g_packet_for_reading;
bool m_replay_mode;
bool m_allow_flash_writes;
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td
index 16e7723e3061..9cbe3d40ca2c 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td
@@ -13,4 +13,8 @@ let Definition = "processgdbremote" in {
Global,
DefaultFalse,
Desc<"If true, the libraries-svr4 feature will be used to get a hold of the process's loaded modules.">;
+ def UseGPacketForReading: Property<"use-g-packet-for-reading", "Boolean">,
+ Global,
+ DefaultFalse,
+ Desc<"Specify if the server should use 'g' packets to read registers.">;
}
diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
index 8a6a58c55450..9da481979f73 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -301,13 +301,14 @@ ThreadGDBRemote::CreateRegisterContextForFrame(StackFrame *frame) {
if (process_sp) {
ProcessGDBRemote *gdb_process =
static_cast<ProcessGDBRemote *>(process_sp.get());
- // read_all_registers_at_once will be true if 'p' packet is not
- // supported.
+ bool pSupported =
+ gdb_process->GetGDBRemote().GetpPacketSupported(GetID());
bool read_all_registers_at_once =
- !gdb_process->GetGDBRemote().GetpPacketSupported(GetID());
+ !pSupported || gdb_process->m_use_g_packet_for_reading;
+ bool write_all_registers_at_once = !pSupported;
reg_ctx_sp = std::make_shared<GDBRemoteRegisterContext>(
*this, concrete_frame_idx, gdb_process->m_register_info,
- read_all_registers_at_once);
+ read_all_registers_at_once, write_all_registers_at_once);
}
} else {
Unwind *unwinder = GetUnwinder();
diff --git a/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp b/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp
index 70933f91fe51..3c0e1cb49d1d 100644
--- a/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp
+++ b/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp
@@ -174,6 +174,7 @@ ArchSpec MinidumpParser::GetArchitecture() {
triple.setArch(llvm::Triple::ArchType::arm);
break;
case ProcessorArchitecture::ARM64:
+ case ProcessorArchitecture::BP_ARM64:
triple.setArch(llvm::Triple::ArchType::aarch64);
break;
default:
@@ -518,58 +519,26 @@ CreateRegionsCacheFromMemory64List(MinidumpParser &parser,
return !regions.empty();
}
-MemoryRegionInfo
-MinidumpParser::FindMemoryRegion(lldb::addr_t load_addr) const {
- auto begin = m_regions.begin();
- auto end = m_regions.end();
- auto pos = std::lower_bound(begin, end, load_addr);
- if (pos != end && pos->GetRange().Contains(load_addr))
- return *pos;
-
- MemoryRegionInfo region;
- if (pos == begin)
- region.GetRange().SetRangeBase(0);
- else {
- auto prev = pos - 1;
- if (prev->GetRange().Contains(load_addr))
- return *prev;
- region.GetRange().SetRangeBase(prev->GetRange().GetRangeEnd());
- }
- if (pos == end)
- region.GetRange().SetRangeEnd(UINT64_MAX);
- else
- region.GetRange().SetRangeEnd(pos->GetRange().GetRangeBase());
- region.SetReadable(MemoryRegionInfo::eNo);
- region.SetWritable(MemoryRegionInfo::eNo);
- region.SetExecutable(MemoryRegionInfo::eNo);
- region.SetMapped(MemoryRegionInfo::eNo);
- return region;
-}
-
-MemoryRegionInfo
-MinidumpParser::GetMemoryRegionInfo(lldb::addr_t load_addr) {
- if (!m_parsed_regions)
- GetMemoryRegions();
- return FindMemoryRegion(load_addr);
-}
-
-const MemoryRegionInfos &MinidumpParser::GetMemoryRegions() {
- if (!m_parsed_regions) {
- m_parsed_regions = true;
- // We haven't cached our memory regions yet we will create the region cache
- // once. We create the region cache using the best source. We start with
- // the linux maps since they are the most complete and have names for the
- // regions. Next we try the MemoryInfoList since it has
- // read/write/execute/map data, and then fall back to the MemoryList and
- // Memory64List to just get a list of the memory that is mapped in this
- // core file
- if (!CreateRegionsCacheFromLinuxMaps(*this, m_regions))
- if (!CreateRegionsCacheFromMemoryInfoList(*this, m_regions))
- if (!CreateRegionsCacheFromMemoryList(*this, m_regions))
- CreateRegionsCacheFromMemory64List(*this, m_regions);
- llvm::sort(m_regions.begin(), m_regions.end());
- }
- return m_regions;
+std::pair<MemoryRegionInfos, bool> MinidumpParser::BuildMemoryRegions() {
+ // We create the region cache using the best source. We start with
+ // the linux maps since they are the most complete and have names for the
+ // regions. Next we try the MemoryInfoList since it has
+ // read/write/execute/map data, and then fall back to the MemoryList and
+ // Memory64List to just get a list of the memory that is mapped in this
+ // core file
+ MemoryRegionInfos result;
+ const auto &return_sorted = [&](bool is_complete) {
+ llvm::sort(result);
+ return std::make_pair(std::move(result), is_complete);
+ };
+ if (CreateRegionsCacheFromLinuxMaps(*this, result))
+ return return_sorted(true);
+ if (CreateRegionsCacheFromMemoryInfoList(*this, result))
+ return return_sorted(true);
+ if (CreateRegionsCacheFromMemoryList(*this, result))
+ return return_sorted(false);
+ CreateRegionsCacheFromMemory64List(*this, result);
+ return return_sorted(false);
}
#define ENUM_TO_CSTR(ST) \
diff --git a/lldb/source/Plugins/Process/minidump/MinidumpParser.h b/lldb/source/Plugins/Process/minidump/MinidumpParser.h
index d206fe6c9a00..4bcb2b47d45a 100644
--- a/lldb/source/Plugins/Process/minidump/MinidumpParser.h
+++ b/lldb/source/Plugins/Process/minidump/MinidumpParser.h
@@ -88,9 +88,9 @@ public:
llvm::ArrayRef<uint8_t> GetMemory(lldb::addr_t addr, size_t size);
- MemoryRegionInfo GetMemoryRegionInfo(lldb::addr_t load_addr);
-
- const MemoryRegionInfos &GetMemoryRegions();
+ /// Returns a list of memory regions and a flag indicating whether the list is
+ /// complete (includes all regions mapped into the process memory).
+ std::pair<MemoryRegionInfos, bool> BuildMemoryRegions();
static llvm::StringRef GetStreamTypeAsString(StreamType stream_type);
@@ -100,14 +100,10 @@ private:
MinidumpParser(lldb::DataBufferSP data_sp,
std::unique_ptr<llvm::object::MinidumpFile> file);
- MemoryRegionInfo FindMemoryRegion(lldb::addr_t load_addr) const;
-
private:
lldb::DataBufferSP m_data_sp;
std::unique_ptr<llvm::object::MinidumpFile> m_file;
ArchSpec m_arch;
- MemoryRegionInfos m_regions;
- bool m_parsed_regions = false;
};
} // end namespace minidump
diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
index e30a3c82a887..5c090dc6e12f 100644
--- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
+++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
@@ -334,15 +334,84 @@ ArchSpec ProcessMinidump::GetArchitecture() {
return ArchSpec(triple);
}
+static MemoryRegionInfo GetMemoryRegionInfo(const MemoryRegionInfos &regions,
+ lldb::addr_t load_addr) {
+ MemoryRegionInfo region;
+ auto pos = llvm::upper_bound(regions, load_addr);
+ if (pos != regions.begin() &&
+ std::prev(pos)->GetRange().Contains(load_addr)) {
+ return *std::prev(pos);
+ }
+
+ if (pos == regions.begin())
+ region.GetRange().SetRangeBase(0);
+ else
+ region.GetRange().SetRangeBase(std::prev(pos)->GetRange().GetRangeEnd());
+
+ if (pos == regions.end())
+ region.GetRange().SetRangeEnd(UINT64_MAX);
+ else
+ region.GetRange().SetRangeEnd(pos->GetRange().GetRangeBase());
+
+ region.SetReadable(MemoryRegionInfo::eNo);
+ region.SetWritable(MemoryRegionInfo::eNo);
+ region.SetExecutable(MemoryRegionInfo::eNo);
+ region.SetMapped(MemoryRegionInfo::eNo);
+ return region;
+}
+
+void ProcessMinidump::BuildMemoryRegions() {
+ if (m_memory_regions)
+ return;
+ m_memory_regions.emplace();
+ bool is_complete;
+ std::tie(*m_memory_regions, is_complete) =
+ m_minidump_parser->BuildMemoryRegions();
+
+ if (is_complete)
+ return;
+
+ MemoryRegionInfos to_add;
+ ModuleList &modules = GetTarget().GetImages();
+ SectionLoadList &load_list = GetTarget().GetSectionLoadList();
+ modules.ForEach([&](const ModuleSP &module_sp) {
+ SectionList *sections = module_sp->GetSectionList();
+ for (size_t i = 0; i < sections->GetSize(); ++i) {
+ SectionSP section_sp = sections->GetSectionAtIndex(i);
+ addr_t load_addr = load_list.GetSectionLoadAddress(section_sp);
+ if (load_addr == LLDB_INVALID_ADDRESS)
+ continue;
+ MemoryRegionInfo::RangeType section_range(load_addr,
+ section_sp->GetByteSize());
+ MemoryRegionInfo region =
+ ::GetMemoryRegionInfo(*m_memory_regions, load_addr);
+ if (region.GetMapped() != MemoryRegionInfo::eYes &&
+ region.GetRange().GetRangeBase() <= section_range.GetRangeBase() &&
+ section_range.GetRangeEnd() <= region.GetRange().GetRangeEnd()) {
+ to_add.emplace_back();
+ to_add.back().GetRange() = section_range;
+ to_add.back().SetLLDBPermissions(section_sp->GetPermissions());
+ to_add.back().SetMapped(MemoryRegionInfo::eYes);
+ to_add.back().SetName(module_sp->GetFileSpec().GetPath().c_str());
+ }
+ }
+ return true;
+ });
+ m_memory_regions->insert(m_memory_regions->end(), to_add.begin(),
+ to_add.end());
+ llvm::sort(*m_memory_regions);
+}
+
Status ProcessMinidump::GetMemoryRegionInfo(lldb::addr_t load_addr,
- MemoryRegionInfo &range_info) {
- range_info = m_minidump_parser->GetMemoryRegionInfo(load_addr);
+ MemoryRegionInfo &region) {
+ BuildMemoryRegions();
+ region = ::GetMemoryRegionInfo(*m_memory_regions, load_addr);
return Status();
}
-Status ProcessMinidump::GetMemoryRegions(
- lldb_private::MemoryRegionInfos &region_list) {
- region_list = m_minidump_parser->GetMemoryRegions();
+Status ProcessMinidump::GetMemoryRegions(MemoryRegionInfos &region_list) {
+ BuildMemoryRegions();
+ region_list = *m_memory_regions;
return Status();
}
diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.h b/lldb/source/Plugins/Process/minidump/ProcessMinidump.h
index 22dc24af7c0e..750164cf8aaf 100644
--- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.h
+++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.h
@@ -111,6 +111,9 @@ private:
const minidump::ExceptionStream *m_active_exception;
lldb::CommandObjectSP m_command_sp;
bool m_is_wow64;
+ llvm::Optional<MemoryRegionInfos> m_memory_regions;
+
+ void BuildMemoryRegions();
};
} // namespace minidump