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/FreeBSD/NativeProcessFreeBSD.cpp45
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp2
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.cpp30
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.h3
-rw-r--r--lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp121
-rw-r--r--lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.h2
-rw-r--r--lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.cpp11
-rw-r--r--lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.h16
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp30
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp6
-rw-r--r--lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp20
-rw-r--r--lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.h32
-rw-r--r--lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.cpp111
-rw-r--r--lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h6
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp4
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp11
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h3
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp314
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h88
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp16
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterFallback.cpp86
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterFallback.h26
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp63
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h5
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp28
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h55
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp28
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h3
-rw-r--r--lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp70
-rw-r--r--lldb/source/Plugins/Process/scripted/ScriptedThread.cpp91
-rw-r--r--lldb/source/Plugins/Process/scripted/ScriptedThread.h12
31 files changed, 716 insertions, 622 deletions
diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp b/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp
index a62d3c1ba052..21c9ead0eca4 100644
--- a/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp
@@ -54,7 +54,7 @@ llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
NativeProcessFreeBSD::Factory::Launch(ProcessLaunchInfo &launch_info,
NativeDelegate &native_delegate,
MainLoop &mainloop) const {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ Log *log = GetLog(POSIXLog::Process);
Status status;
::pid_t pid = ProcessLauncherPosixFork()
@@ -108,7 +108,7 @@ llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
NativeProcessFreeBSD::Factory::Attach(
lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate,
MainLoop &mainloop) const {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ Log *log = GetLog(POSIXLog::Process);
LLDB_LOG(log, "pid = {0:x}", pid);
// Retrieve the architecture for the running process.
@@ -135,7 +135,8 @@ NativeProcessFreeBSD::Factory::GetSupportedExtensions() const {
Extension::savecore |
#endif
Extension::multiprocess | Extension::fork | Extension::vfork |
- Extension::pass_signals | Extension::auxv | Extension::libraries_svr4;
+ Extension::pass_signals | Extension::auxv | Extension::libraries_svr4 |
+ Extension::siginfo_read;
}
// Public Instance Methods
@@ -170,7 +171,7 @@ void NativeProcessFreeBSD::MonitorCallback(lldb::pid_t pid, int signal) {
}
void NativeProcessFreeBSD::MonitorExited(lldb::pid_t pid, WaitStatus status) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ Log *log = GetLog(POSIXLog::Process);
LLDB_LOG(log, "got exit signal({0}) , pid = {1}", status, pid);
@@ -193,7 +194,7 @@ void NativeProcessFreeBSD::MonitorSIGSTOP(lldb::pid_t pid) {
}
void NativeProcessFreeBSD::MonitorSIGTRAP(lldb::pid_t pid) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ Log *log = GetLog(POSIXLog::Process);
struct ptrace_lwpinfo info;
const auto siginfo_err = PtraceWrapper(PT_LWPINFO, pid, &info, sizeof(info));
@@ -254,6 +255,7 @@ void NativeProcessFreeBSD::MonitorSIGTRAP(lldb::pid_t pid) {
for (const auto &thread : m_threads)
static_cast<NativeThreadFreeBSD &>(*thread).SetStoppedByExec();
+ SetCurrentThreadID(m_threads.front()->GetID());
SetState(StateType::eStateStopped, true);
return;
}
@@ -312,6 +314,7 @@ void NativeProcessFreeBSD::MonitorSIGTRAP(lldb::pid_t pid) {
} else
thread->SetStoppedByBreakpoint();
FixupBreakpointPCAsNeeded(*thread);
+ SetCurrentThreadID(thread->GetID());
}
SetState(StateType::eStateStopped, true);
return;
@@ -333,11 +336,13 @@ void NativeProcessFreeBSD::MonitorSIGTRAP(lldb::pid_t pid) {
if (wp_index != LLDB_INVALID_INDEX32) {
regctx.ClearWatchpointHit(wp_index);
thread->SetStoppedByWatchpoint(wp_index);
+ SetCurrentThreadID(thread->GetID());
SetState(StateType::eStateStopped, true);
break;
}
thread->SetStoppedByTrace();
+ SetCurrentThreadID(thread->GetID());
}
SetState(StateType::eStateStopped, true);
@@ -352,7 +357,7 @@ void NativeProcessFreeBSD::MonitorSIGTRAP(lldb::pid_t pid) {
}
void NativeProcessFreeBSD::MonitorSignal(lldb::pid_t pid, int signal) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ Log *log = GetLog(POSIXLog::Process);
struct ptrace_lwpinfo info;
const auto siginfo_err = PtraceWrapper(PT_LWPINFO, pid, &info, sizeof(info));
@@ -370,9 +375,10 @@ void NativeProcessFreeBSD::MonitorSignal(lldb::pid_t pid, int signal) {
static_cast<NativeThreadFreeBSD &>(*abs_thread);
assert(info.pl_lwpid >= 0);
if (info.pl_lwpid == 0 ||
- static_cast<lldb::tid_t>(info.pl_lwpid) == thread.GetID())
+ static_cast<lldb::tid_t>(info.pl_lwpid) == thread.GetID()) {
thread.SetStoppedBySignal(info.pl_siginfo.si_signo, &info.pl_siginfo);
- else
+ SetCurrentThreadID(thread.GetID());
+ } else
thread.SetStoppedWithNoReason();
}
SetState(StateType::eStateStopped, true);
@@ -380,7 +386,7 @@ void NativeProcessFreeBSD::MonitorSignal(lldb::pid_t pid, int signal) {
Status NativeProcessFreeBSD::PtraceWrapper(int req, lldb::pid_t pid, void *addr,
int data, int *result) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
+ Log *log = GetLog(POSIXLog::Ptrace);
Status error;
int ret;
@@ -424,7 +430,7 @@ NativeProcessFreeBSD::GetSoftwareBreakpointTrapOpcode(size_t size_hint) {
}
Status NativeProcessFreeBSD::Resume(const ResumeActionList &resume_actions) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ Log *log = GetLog(POSIXLog::Process);
LLDB_LOG(log, "pid {0}", GetID());
Status ret;
@@ -521,7 +527,7 @@ Status NativeProcessFreeBSD::Signal(int signo) {
Status NativeProcessFreeBSD::Interrupt() { return Halt(); }
Status NativeProcessFreeBSD::Kill() {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ Log *log = GetLog(POSIXLog::Process);
LLDB_LOG(log, "pid {0}", GetID());
Status error;
@@ -608,7 +614,7 @@ Status NativeProcessFreeBSD::GetMemoryRegionInfo(lldb::addr_t load_addr,
}
Status NativeProcessFreeBSD::PopulateMemoryRegionCache() {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ Log *log = GetLog(POSIXLog::Process);
// If our cache is empty, pull the latest. There should always be at least
// one memory region if memory region handling is supported.
if (!m_mem_region_cache.empty()) {
@@ -735,7 +741,7 @@ NativeProcessFreeBSD::GetFileLoadAddress(const llvm::StringRef &file_name,
}
void NativeProcessFreeBSD::SigchldHandler() {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ Log *log = GetLog(POSIXLog::Process);
int status;
::pid_t wait_pid =
llvm::sys::RetryAfterSignal(-1, waitpid, GetID(), &status, WNOHANG);
@@ -780,7 +786,7 @@ bool NativeProcessFreeBSD::HasThreadNoLock(lldb::tid_t thread_id) {
}
NativeThreadFreeBSD &NativeProcessFreeBSD::AddThread(lldb::tid_t thread_id) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
+ Log *log = GetLog(POSIXLog::Thread);
LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id);
assert(thread_id > 0);
@@ -796,7 +802,7 @@ NativeThreadFreeBSD &NativeProcessFreeBSD::AddThread(lldb::tid_t thread_id) {
}
void NativeProcessFreeBSD::RemoveThread(lldb::tid_t thread_id) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
+ Log *log = GetLog(POSIXLog::Thread);
LLDB_LOG(log, "pid {0} removing thread with tid {1}", GetID(), thread_id);
assert(thread_id > 0);
@@ -809,6 +815,9 @@ void NativeProcessFreeBSD::RemoveThread(lldb::tid_t thread_id) {
break;
}
}
+
+ if (GetCurrentThreadID() == thread_id)
+ SetCurrentThreadID(m_threads.front()->GetID());
}
Status NativeProcessFreeBSD::Attach() {
@@ -845,7 +854,7 @@ Status NativeProcessFreeBSD::ReadMemory(lldb::addr_t addr, void *buf,
unsigned char *dst = static_cast<unsigned char *>(buf);
struct ptrace_io_desc io;
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY));
+ Log *log = GetLog(POSIXLog::Memory);
LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
bytes_read = 0;
@@ -873,7 +882,7 @@ Status NativeProcessFreeBSD::WriteMemory(lldb::addr_t addr, const void *buf,
Status error;
struct ptrace_io_desc io;
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY));
+ Log *log = GetLog(POSIXLog::Memory);
LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
bytes_written = 0;
@@ -953,7 +962,7 @@ bool NativeProcessFreeBSD::SupportHardwareSingleStepping() const {
void NativeProcessFreeBSD::MonitorClone(::pid_t child_pid, bool is_vfork,
NativeThreadFreeBSD &parent_thread) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ Log *log = GetLog(POSIXLog::Process);
LLDB_LOG(log, "fork, child_pid={0}", child_pid);
int status;
diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp
index 4578138a89b3..143d94069bc6 100644
--- a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp
@@ -227,7 +227,7 @@ llvm::Error NativeRegisterContextFreeBSD_arm64::CopyHardwareWatchpointsFrom(
llvm::Error NativeRegisterContextFreeBSD_arm64::ReadHardwareDebugInfo() {
#ifdef LLDB_HAS_FREEBSD_WATCHPOINT
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_REGISTERS));
+ Log *log = GetLog(POSIXLog::Registers);
// we're fully stateful, so no need to reread control registers ever
if (m_read_dbreg)
diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.cpp b/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.cpp
index 80b3527aebce..a75668f3b5c7 100644
--- a/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.cpp
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.cpp
@@ -75,7 +75,7 @@ Status NativeThreadFreeBSD::Suspend() {
void NativeThreadFreeBSD::SetStoppedBySignal(uint32_t signo,
const siginfo_t *info) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
+ Log *log = GetLog(POSIXLog::Thread);
LLDB_LOG(log, "tid = {0} in called with signal {1}", GetID(), signo);
SetStopped();
@@ -178,7 +178,7 @@ void NativeThreadFreeBSD::SetStepping() {
}
std::string NativeThreadFreeBSD::GetName() {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
+ Log *log = GetLog(POSIXLog::Thread);
std::vector<struct kinfo_proc> kp;
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID | KERN_PROC_INC_THREAD,
@@ -213,7 +213,7 @@ lldb::StateType NativeThreadFreeBSD::GetState() { return m_state; }
bool NativeThreadFreeBSD::GetStopReason(ThreadStopInfo &stop_info,
std::string &description) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
+ Log *log = GetLog(POSIXLog::Thread);
description.clear();
switch (m_state) {
@@ -313,3 +313,27 @@ NativeThreadFreeBSD::CopyWatchpointsFrom(NativeThreadFreeBSD &source) {
}
return s;
}
+
+llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
+NativeThreadFreeBSD::GetSiginfo() const {
+ Log *log = GetLog(POSIXLog::Process);
+
+ struct ptrace_lwpinfo info;
+ const auto siginfo_err = NativeProcessFreeBSD::PtraceWrapper(
+ PT_LWPINFO, GetID(), &info, sizeof(info));
+ if (siginfo_err.Fail()) {
+ LLDB_LOG(log, "PT_LWPINFO failed {0}", siginfo_err);
+ return siginfo_err.ToError();
+ }
+
+ if (info.pl_event != PL_EVENT_SIGNAL)
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "Thread not signaled");
+ if (!(info.pl_flags & PL_FLAG_SI))
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "No siginfo for thread");
+
+ return llvm::MemoryBuffer::getMemBufferCopy(
+ llvm::StringRef(reinterpret_cast<const char *>(&info.pl_siginfo),
+ sizeof(info.pl_siginfo)));
+}
diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.h b/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.h
index 3ec6daa409e4..6294a7a70963 100644
--- a/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.h
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.h
@@ -47,6 +47,9 @@ public:
Status RemoveHardwareBreakpoint(lldb::addr_t addr) override;
+ llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
+ GetSiginfo() const override;
+
private:
// Interface for friend classes
diff --git a/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp b/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp
index 339d33d25110..e3707365a9c3 100644
--- a/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp
+++ b/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp
@@ -137,12 +137,115 @@ bool ProcessFreeBSDKernel::DoUpdateThreadList(ThreadList &old_thread_list,
return false;
}
- const Symbol *pcb_sym =
- GetTarget().GetExecutableModule()->FindFirstSymbolWithNameAndType(
- ConstString("dumppcb"));
- ThreadSP thread_sp(new ThreadFreeBSDKernel(
- *this, 1, pcb_sym ? pcb_sym->GetFileAddress() : LLDB_INVALID_ADDRESS));
- new_thread_list.AddThread(thread_sp);
+ Status error;
+
+ // struct field offsets are written as symbols so that we don't have
+ // to figure them out ourselves
+ int32_t offset_p_list = ReadSignedIntegerFromMemory(
+ FindSymbol("proc_off_p_list"), 4, -1, error);
+ int32_t offset_p_pid =
+ ReadSignedIntegerFromMemory(FindSymbol("proc_off_p_pid"), 4, -1, error);
+ int32_t offset_p_threads = ReadSignedIntegerFromMemory(
+ FindSymbol("proc_off_p_threads"), 4, -1, error);
+ int32_t offset_p_comm = ReadSignedIntegerFromMemory(
+ FindSymbol("proc_off_p_comm"), 4, -1, error);
+
+ int32_t offset_td_tid = ReadSignedIntegerFromMemory(
+ FindSymbol("thread_off_td_tid"), 4, -1, error);
+ int32_t offset_td_plist = ReadSignedIntegerFromMemory(
+ FindSymbol("thread_off_td_plist"), 4, -1, error);
+ int32_t offset_td_pcb = ReadSignedIntegerFromMemory(
+ FindSymbol("thread_off_td_pcb"), 4, -1, error);
+ int32_t offset_td_oncpu = ReadSignedIntegerFromMemory(
+ FindSymbol("thread_off_td_oncpu"), 4, -1, error);
+ int32_t offset_td_name = ReadSignedIntegerFromMemory(
+ FindSymbol("thread_off_td_name"), 4, -1, error);
+
+ // fail if we were not able to read any of the offsets
+ if (offset_p_list == -1 || offset_p_pid == -1 || offset_p_threads == -1 ||
+ offset_p_comm == -1 || offset_td_tid == -1 || offset_td_plist == -1 ||
+ offset_td_pcb == -1 || offset_td_oncpu == -1 || offset_td_name == -1)
+ return false;
+
+ // dumptid contains the thread-id of the crashing thread
+ // dumppcb contains its PCB
+ int32_t dumptid =
+ ReadSignedIntegerFromMemory(FindSymbol("dumptid"), 4, -1, error);
+ lldb::addr_t dumppcb = FindSymbol("dumppcb");
+
+ // stoppcbs is an array of PCBs on all CPUs
+ // each element is of size pcb_size
+ int32_t pcbsize =
+ ReadSignedIntegerFromMemory(FindSymbol("pcb_size"), 4, -1, error);
+ lldb::addr_t stoppcbs = FindSymbol("stoppcbs");
+
+ // from FreeBSD sys/param.h
+ constexpr size_t fbsd_maxcomlen = 19;
+
+ // iterate through a linked list of all processes
+ // allproc is a pointer to the first list element, p_list field
+ // (found at offset_p_list) specifies the next element
+ for (lldb::addr_t proc =
+ ReadPointerFromMemory(FindSymbol("allproc"), error);
+ proc != 0 && proc != LLDB_INVALID_ADDRESS;
+ proc = ReadPointerFromMemory(proc + offset_p_list, error)) {
+ int32_t pid =
+ ReadSignedIntegerFromMemory(proc + offset_p_pid, 4, -1, error);
+ // process' command-line string
+ char comm[fbsd_maxcomlen + 1];
+ ReadCStringFromMemory(proc + offset_p_comm, comm, sizeof(comm), error);
+
+ // iterate through a linked list of all process' threads
+ // the initial thread is found in process' p_threads, subsequent
+ // elements are linked via td_plist field
+ for (lldb::addr_t td =
+ ReadPointerFromMemory(proc + offset_p_threads, error);
+ td != 0; td = ReadPointerFromMemory(td + offset_td_plist, error)) {
+ int32_t tid =
+ ReadSignedIntegerFromMemory(td + offset_td_tid, 4, -1, error);
+ lldb::addr_t pcb_addr =
+ ReadPointerFromMemory(td + offset_td_pcb, error);
+ // whether process was on CPU (-1 if not, otherwise CPU number)
+ int32_t oncpu =
+ ReadSignedIntegerFromMemory(td + offset_td_oncpu, 4, -2, error);
+ // thread name
+ char thread_name[fbsd_maxcomlen + 1];
+ ReadCStringFromMemory(td + offset_td_name, thread_name,
+ sizeof(thread_name), error);
+
+ // if we failed to read TID, ignore this thread
+ if (tid == -1)
+ continue;
+
+ std::string thread_desc = llvm::formatv("(pid {0}) {1}", pid, comm);
+ if (*thread_name && strcmp(thread_name, comm)) {
+ thread_desc += '/';
+ thread_desc += thread_name;
+ }
+
+ // roughly:
+ // 1. if the thread crashed, its PCB is going to be at "dumppcb"
+ // 2. if the thread was on CPU, its PCB is going to be on the CPU
+ // 3. otherwise, its PCB is in the thread struct
+ if (tid == dumptid) {
+ // NB: dumppcb can be LLDB_INVALID_ADDRESS if reading it failed
+ pcb_addr = dumppcb;
+ thread_desc += " (crashed)";
+ } else if (oncpu != -1) {
+ // if we managed to read stoppcbs and pcb_size, use them to find
+ // the correct PCB
+ if (stoppcbs != LLDB_INVALID_ADDRESS && pcbsize > 0)
+ pcb_addr = stoppcbs + oncpu * pcbsize;
+ else
+ pcb_addr = LLDB_INVALID_ADDRESS;
+ thread_desc += llvm::formatv(" (on CPU {0})", oncpu);
+ }
+
+ ThreadSP thread_sp{
+ new ThreadFreeBSDKernel(*this, tid, pcb_addr, thread_desc)};
+ new_thread_list.AddThread(thread_sp);
+ }
+ }
} else {
const uint32_t num_threads = old_thread_list.GetSize(false);
for (uint32_t i = 0; i < num_threads; ++i)
@@ -163,6 +266,12 @@ DynamicLoader *ProcessFreeBSDKernel::GetDynamicLoader() {
return m_dyld_up.get();
}
+lldb::addr_t ProcessFreeBSDKernel::FindSymbol(const char *name) {
+ ModuleSP mod_sp = GetTarget().GetExecutableModule();
+ const Symbol *sym = mod_sp->FindFirstSymbolWithNameAndType(ConstString(name));
+ return sym ? sym->GetLoadAddress(&GetTarget()) : LLDB_INVALID_ADDRESS;
+}
+
#if LLDB_ENABLE_FBSDVMCORE
ProcessFreeBSDKernelFVC::ProcessFreeBSDKernelFVC(lldb::TargetSP target_sp,
diff --git a/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.h b/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.h
index 558eec5403db..5bd463126307 100644
--- a/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.h
+++ b/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.h
@@ -46,6 +46,8 @@ public:
protected:
bool DoUpdateThreadList(lldb_private::ThreadList &old_thread_list,
lldb_private::ThreadList &new_thread_list) override;
+
+ lldb::addr_t FindSymbol(const char* name);
};
#endif // LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_PROCESSFREEBSDKERNEL_H
diff --git a/lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.cpp b/lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.cpp
index 124c65d587ff..8d304086a163 100644
--- a/lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.cpp
+++ b/lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.cpp
@@ -24,8 +24,10 @@ using namespace lldb;
using namespace lldb_private;
ThreadFreeBSDKernel::ThreadFreeBSDKernel(Process &process, lldb::tid_t tid,
- lldb::addr_t pcb_addr)
- : Thread(process, tid), m_pcb_addr(pcb_addr) {}
+ lldb::addr_t pcb_addr,
+ std::string thread_name)
+ : Thread(process, tid), m_thread_name(std::move(thread_name)),
+ m_pcb_addr(pcb_addr) {}
ThreadFreeBSDKernel::~ThreadFreeBSDKernel() {}
@@ -61,9 +63,8 @@ ThreadFreeBSDKernel::CreateRegisterContextForFrame(StackFrame *frame) {
m_pcb_addr);
break;
case llvm::Triple::x86:
- m_thread_reg_ctx_sp =
- std::make_shared<RegisterContextFreeBSDKernel_i386>(
- *this, new RegisterContextFreeBSD_i386(arch), m_pcb_addr);
+ m_thread_reg_ctx_sp = std::make_shared<RegisterContextFreeBSDKernel_i386>(
+ *this, new RegisterContextFreeBSD_i386(arch), m_pcb_addr);
break;
case llvm::Triple::x86_64:
m_thread_reg_ctx_sp =
diff --git a/lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.h b/lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.h
index 2842eba64e56..3bc019b63e68 100644
--- a/lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.h
+++ b/lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.h
@@ -14,7 +14,7 @@
class ThreadFreeBSDKernel : public lldb_private::Thread {
public:
ThreadFreeBSDKernel(lldb_private::Process &process, lldb::tid_t tid,
- lldb::addr_t pcb_addr);
+ lldb::addr_t pcb_addr, std::string thread_name);
~ThreadFreeBSDKernel() override;
@@ -25,10 +25,24 @@ public:
lldb::RegisterContextSP
CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override;
+ const char *GetName() override {
+ if (m_thread_name.empty())
+ return nullptr;
+ return m_thread_name.c_str();
+ }
+
+ void SetName(const char *name) override {
+ if (name && name[0])
+ m_thread_name.assign(name);
+ else
+ m_thread_name.clear();
+ }
+
protected:
bool CalculateStopInfo() override;
private:
+ std::string m_thread_name;
lldb::RegisterContextSP m_thread_reg_ctx_sp;
lldb::addr_t m_pcb_addr;
};
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
index 0420d00e39d6..182eefb7bee7 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
+++ b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
@@ -59,7 +59,7 @@ llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
NativeProcessNetBSD::Factory::Launch(ProcessLaunchInfo &launch_info,
NativeDelegate &native_delegate,
MainLoop &mainloop) const {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ Log *log = GetLog(POSIXLog::Process);
Status status;
::pid_t pid = ProcessLauncherPosixFork()
@@ -113,7 +113,7 @@ 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));
+ Log *log = GetLog(POSIXLog::Process);
LLDB_LOG(log, "pid = {0:x}", pid);
// Retrieve the architecture for the running process.
@@ -172,7 +172,7 @@ void NativeProcessNetBSD::MonitorCallback(lldb::pid_t pid, int signal) {
}
void NativeProcessNetBSD::MonitorExited(lldb::pid_t pid, WaitStatus status) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ Log *log = GetLog(POSIXLog::Process);
LLDB_LOG(log, "got exit signal({0}) , pid = {1}", status, pid);
@@ -207,7 +207,7 @@ void NativeProcessNetBSD::MonitorSIGSTOP(lldb::pid_t pid) {
}
void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ Log *log = GetLog(POSIXLog::Process);
ptrace_siginfo_t info;
const auto siginfo_err =
@@ -359,7 +359,7 @@ void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) {
}
void NativeProcessNetBSD::MonitorSignal(lldb::pid_t pid, int signal) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ Log *log = GetLog(POSIXLog::Process);
ptrace_siginfo_t info;
const auto siginfo_err =
@@ -383,7 +383,7 @@ void NativeProcessNetBSD::MonitorSignal(lldb::pid_t pid, int signal) {
Status NativeProcessNetBSD::PtraceWrapper(int req, lldb::pid_t pid, void *addr,
int data, int *result) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
+ Log *log = GetLog(POSIXLog::Ptrace);
Status error;
int ret;
@@ -459,7 +459,7 @@ static llvm::Expected<ptrace_siginfo_t> ComputeSignalInfo(
}
Status NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ Log *log = GetLog(POSIXLog::Process);
LLDB_LOG(log, "pid {0}", GetID());
Status ret;
@@ -562,7 +562,7 @@ Status NativeProcessNetBSD::Interrupt() {
}
Status NativeProcessNetBSD::Kill() {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ Log *log = GetLog(POSIXLog::Process);
LLDB_LOG(log, "pid {0}", GetID());
Status error;
@@ -654,7 +654,7 @@ Status NativeProcessNetBSD::GetMemoryRegionInfo(lldb::addr_t load_addr,
}
Status NativeProcessNetBSD::PopulateMemoryRegionCache() {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ Log *log = GetLog(POSIXLog::Process);
// If our cache is empty, pull the latest. There should always be at least
// one memory region if memory region handling is supported.
if (!m_mem_region_cache.empty()) {
@@ -772,7 +772,7 @@ Status NativeProcessNetBSD::GetFileLoadAddress(const llvm::StringRef &file_name,
}
void NativeProcessNetBSD::SigchldHandler() {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ Log *log = GetLog(POSIXLog::Process);
int status;
::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, waitpid, GetID(), &status,
WALLSIG | WNOHANG);
@@ -817,7 +817,7 @@ bool NativeProcessNetBSD::HasThreadNoLock(lldb::tid_t thread_id) {
}
NativeThreadNetBSD &NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
+ Log *log = GetLog(POSIXLog::Thread);
LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id);
assert(thread_id > 0);
@@ -833,7 +833,7 @@ NativeThreadNetBSD &NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) {
}
void NativeProcessNetBSD::RemoveThread(lldb::tid_t thread_id) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
+ Log *log = GetLog(POSIXLog::Thread);
LLDB_LOG(log, "pid {0} removing thread with tid {1}", GetID(), thread_id);
assert(thread_id > 0);
@@ -882,7 +882,7 @@ Status NativeProcessNetBSD::ReadMemory(lldb::addr_t addr, void *buf,
unsigned char *dst = static_cast<unsigned char *>(buf);
struct ptrace_io_desc io;
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY));
+ Log *log = GetLog(POSIXLog::Memory);
LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
bytes_read = 0;
@@ -910,7 +910,7 @@ Status NativeProcessNetBSD::WriteMemory(lldb::addr_t addr, const void *buf,
Status error;
struct ptrace_io_desc io;
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY));
+ Log *log = GetLog(POSIXLog::Memory);
LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
bytes_written = 0;
@@ -1013,7 +1013,7 @@ Status NativeProcessNetBSD::ReinitializeThreads() {
void NativeProcessNetBSD::MonitorClone(::pid_t child_pid, bool is_vfork,
NativeThreadNetBSD &parent_thread) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ Log *log = GetLog(POSIXLog::Process);
LLDB_LOG(log, "clone, child_pid={0}", child_pid);
int status;
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
index 400b89a5fddf..3e8cf9fd9f23 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
+++ b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
@@ -75,7 +75,7 @@ Status NativeThreadNetBSD::Suspend() {
void NativeThreadNetBSD::SetStoppedBySignal(uint32_t signo,
const siginfo_t *info) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
+ Log *log = GetLog(POSIXLog::Thread);
LLDB_LOG(log, "tid = {0} in called with signal {1}", GetID(), signo);
SetStopped();
@@ -178,7 +178,7 @@ void NativeThreadNetBSD::SetStepping() {
}
std::string NativeThreadNetBSD::GetName() {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
+ Log *log = GetLog(POSIXLog::Thread);
#ifdef PT_LWPSTATUS
struct ptrace_lwpstatus info = {};
@@ -225,7 +225,7 @@ lldb::StateType NativeThreadNetBSD::GetState() { return m_state; }
bool NativeThreadNetBSD::GetStopReason(ThreadStopInfo &stop_info,
std::string &description) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
+ Log *log = GetLog(POSIXLog::Thread);
description.clear();
switch (m_state) {
diff --git a/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp b/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp
index f4d0803b264a..7ad88aabc2c0 100644
--- a/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp
+++ b/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp
@@ -13,16 +13,20 @@
using namespace lldb_private;
static constexpr Log::Category g_categories[] = {
- {{"break"}, {"log breakpoints"}, POSIX_LOG_BREAKPOINTS},
- {{"memory"}, {"log memory reads and writes"}, POSIX_LOG_MEMORY},
- {{"process"}, {"log process events and activities"}, POSIX_LOG_PROCESS},
- {{"ptrace"}, {"log all calls to ptrace"}, POSIX_LOG_PTRACE},
- {{"registers"}, {"log register read/writes"}, POSIX_LOG_REGISTERS},
- {{"thread"}, {"log thread events and activities"}, POSIX_LOG_THREAD},
- {{"watch"}, {"log watchpoint related activities"}, POSIX_LOG_WATCHPOINTS},
+ {{"break"}, {"log breakpoints"}, POSIXLog::Breakpoints},
+ {{"memory"}, {"log memory reads and writes"}, POSIXLog::Memory},
+ {{"process"}, {"log process events and activities"}, POSIXLog::Process},
+ {{"ptrace"}, {"log all calls to ptrace"}, POSIXLog::Ptrace},
+ {{"registers"}, {"log register read/writes"}, POSIXLog::Registers},
+ {{"thread"}, {"log thread events and activities"}, POSIXLog::Thread},
+ {{"watch"}, {"log watchpoint related activities"}, POSIXLog::Watchpoints},
};
-Log::Channel ProcessPOSIXLog::g_channel(g_categories, POSIX_LOG_DEFAULT);
+static Log::Channel g_channel(g_categories, POSIXLog::Process);
+
+template <> Log::Channel &lldb_private::LogChannelFor<POSIXLog>() {
+ return g_channel;
+}
void ProcessPOSIXLog::Initialize() {
static llvm::once_flag g_once_flag;
diff --git a/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.h b/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.h
index c0147c43410f..7b8b6cdbf255 100644
--- a/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.h
+++ b/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.h
@@ -13,27 +13,25 @@
#include "lldb/Utility/Log.h"
-#define POSIX_LOG_PROCESS (1u << 1)
-#define POSIX_LOG_THREAD (1u << 2)
-#define POSIX_LOG_MEMORY (1u << 4) // Log memory reads/writes calls
-#define POSIX_LOG_PTRACE (1u << 5)
-#define POSIX_LOG_REGISTERS (1u << 6)
-#define POSIX_LOG_BREAKPOINTS (1u << 7)
-#define POSIX_LOG_WATCHPOINTS (1u << 8)
-#define POSIX_LOG_ALL (UINT32_MAX)
-#define POSIX_LOG_DEFAULT POSIX_LOG_PROCESS
-
namespace lldb_private {
-class ProcessPOSIXLog {
- static Log::Channel g_channel;
+enum class POSIXLog : Log::MaskType {
+ Breakpoints = Log::ChannelFlag<0>,
+ Memory = Log::ChannelFlag<1>,
+ Process = Log::ChannelFlag<2>,
+ Ptrace = Log::ChannelFlag<3>,
+ Registers = Log::ChannelFlag<4>,
+ Thread = Log::ChannelFlag<5>,
+ Watchpoints = Log::ChannelFlag<6>,
+ LLVM_MARK_AS_BITMASK_ENUM(Watchpoints)
+};
+
+class ProcessPOSIXLog {
public:
static void Initialize();
-
- static Log *GetLogIfAllCategoriesSet(uint32_t mask) {
- return g_channel.GetLogIfAll(mask);
- }
};
-}
+
+template <> Log::Channel &LogChannelFor<POSIXLog>();
+} // namespace lldb_private
#endif // liblldb_ProcessPOSIXLog_h_
diff --git a/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.cpp b/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.cpp
index d74b66b58afc..b71de4cadb18 100644
--- a/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.cpp
+++ b/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.cpp
@@ -7,6 +7,8 @@
//===----------------------------------------------------------------------===//
#include "MemoryTagManagerAArch64MTE.h"
+#include "llvm/Support/Error.h"
+#include <assert.h>
using namespace lldb_private;
@@ -20,7 +22,7 @@ MemoryTagManagerAArch64MTE::GetLogicalTag(lldb::addr_t addr) const {
}
lldb::addr_t
-MemoryTagManagerAArch64MTE::RemoveNonAddressBits(lldb::addr_t addr) const {
+MemoryTagManagerAArch64MTE::RemoveTagBits(lldb::addr_t addr) const {
// Here we're ignoring the whole top byte. If you've got MTE
// you must also have TBI (top byte ignore).
// The other 4 bits could contain other extension bits or
@@ -30,7 +32,7 @@ MemoryTagManagerAArch64MTE::RemoveNonAddressBits(lldb::addr_t addr) const {
ptrdiff_t MemoryTagManagerAArch64MTE::AddressDiff(lldb::addr_t addr1,
lldb::addr_t addr2) const {
- return RemoveNonAddressBits(addr1) - RemoveNonAddressBits(addr2);
+ return RemoveTagBits(addr1) - RemoveTagBits(addr2);
}
lldb::addr_t MemoryTagManagerAArch64MTE::GetGranuleSize() const {
@@ -66,6 +68,15 @@ MemoryTagManagerAArch64MTE::ExpandToGranule(TagRange range) const {
return TagRange(new_start, new_len);
}
+static llvm::Error MakeInvalidRangeErr(lldb::addr_t addr,
+ lldb::addr_t end_addr) {
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "End address (0x%" PRIx64
+ ") must be greater than the start address (0x%" PRIx64 ")",
+ end_addr, addr);
+}
+
llvm::Expected<MemoryTagManager::TagRange>
MemoryTagManagerAArch64MTE::MakeTaggedRange(
lldb::addr_t addr, lldb::addr_t end_addr,
@@ -74,17 +85,12 @@ MemoryTagManagerAArch64MTE::MakeTaggedRange(
// We must remove tags here otherwise an address with a higher
// tag value will always be > the other.
ptrdiff_t len = AddressDiff(end_addr, addr);
- if (len <= 0) {
- return llvm::createStringError(
- llvm::inconvertibleErrorCode(),
- "End address (0x%" PRIx64
- ") must be greater than the start address (0x%" PRIx64 ")",
- end_addr, addr);
- }
+ if (len <= 0)
+ return MakeInvalidRangeErr(addr, end_addr);
// Region addresses will not have memory tags. So when searching
// we must use an untagged address.
- MemoryRegionInfo::RangeType tag_range(RemoveNonAddressBits(addr), len);
+ MemoryRegionInfo::RangeType tag_range(RemoveTagBits(addr), len);
tag_range = ExpandToGranule(tag_range);
// Make a copy so we can use the original for errors and the final return.
@@ -123,6 +129,91 @@ MemoryTagManagerAArch64MTE::MakeTaggedRange(
return tag_range;
}
+llvm::Expected<std::vector<MemoryTagManager::TagRange>>
+MemoryTagManagerAArch64MTE::MakeTaggedRanges(
+ lldb::addr_t addr, lldb::addr_t end_addr,
+ const lldb_private::MemoryRegionInfos &memory_regions) const {
+ // First check that the range is not inverted.
+ // We must remove tags here otherwise an address with a higher
+ // tag value will always be > the other.
+ ptrdiff_t len = AddressDiff(end_addr, addr);
+ if (len <= 0)
+ return MakeInvalidRangeErr(addr, end_addr);
+
+ std::vector<MemoryTagManager::TagRange> tagged_ranges;
+ // No memory regions means no tagged memory at all
+ if (memory_regions.empty())
+ return tagged_ranges;
+
+ // For the logic to work regions must be in ascending order
+ // which is what you'd have if you used GetMemoryRegions.
+ assert(std::is_sorted(
+ memory_regions.begin(), memory_regions.end(),
+ [](const MemoryRegionInfo &lhs, const MemoryRegionInfo &rhs) {
+ return lhs.GetRange().GetRangeBase() < rhs.GetRange().GetRangeBase();
+ }));
+
+ // If we're debugging userspace in an OS like Linux that uses an MMU,
+ // the only reason we'd get overlapping regions is incorrect data.
+ // It is possible that won't hold for embedded with memory protection
+ // units (MPUs) that allow overlaps.
+ //
+ // For now we're going to assume the former, as there is no good way
+ // to handle overlaps. For example:
+ // < requested range >
+ // [-- region 1 --]
+ // [-- region 2--]
+ // Where the first region will reduce the requested range to nothing
+ // and exit early before it sees the overlap.
+ MemoryRegionInfos::const_iterator overlap = std::adjacent_find(
+ memory_regions.begin(), memory_regions.end(),
+ [](const MemoryRegionInfo &lhs, const MemoryRegionInfo &rhs) {
+ return rhs.GetRange().DoesIntersect(lhs.GetRange());
+ });
+ UNUSED_IF_ASSERT_DISABLED(overlap);
+ assert(overlap == memory_regions.end());
+
+ // Region addresses will not have memory tags so when searching
+ // we must use an untagged address.
+ MemoryRegionInfo::RangeType range(RemoveTagBits(addr), len);
+ range = ExpandToGranule(range);
+
+ // While there are regions to check and the range has non zero length
+ for (const MemoryRegionInfo &region : memory_regions) {
+ // If range we're checking has been reduced to zero length, exit early
+ if (!range.IsValid())
+ break;
+
+ // If the region doesn't overlap the range at all, ignore it.
+ if (!region.GetRange().DoesIntersect(range))
+ continue;
+
+ // If it's tagged record this sub-range.
+ // (assuming that it's already granule aligned)
+ if (region.GetMemoryTagged()) {
+ // The region found may extend outside the requested range.
+ // For example the first region might start before the range.
+ // We must only add what covers the requested range.
+ lldb::addr_t start =
+ std::max(range.GetRangeBase(), region.GetRange().GetRangeBase());
+ lldb::addr_t end =
+ std::min(range.GetRangeEnd(), region.GetRange().GetRangeEnd());
+ tagged_ranges.push_back(MemoryTagManager::TagRange(start, end - start));
+ }
+
+ // Move the range up to start at the end of the region.
+ lldb::addr_t old_end = range.GetRangeEnd();
+ // This "slides" the range so it moves the end as well.
+ range.SetRangeBase(region.GetRange().GetRangeEnd());
+ // So we set the end back to the original end address after sliding it up.
+ range.SetRangeEnd(old_end);
+ // (if the above were to try to set end < begin the range will just be set
+ // to 0 size)
+ }
+
+ return tagged_ranges;
+}
+
llvm::Expected<std::vector<lldb::addr_t>>
MemoryTagManagerAArch64MTE::UnpackTagsData(const std::vector<uint8_t> &tags,
size_t granules /*=0*/) const {
diff --git a/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h b/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h
index d4e8249da93f..7cda728b140f 100644
--- a/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h
+++ b/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h
@@ -27,7 +27,7 @@ public:
size_t GetTagSizeInBytes() const override;
lldb::addr_t GetLogicalTag(lldb::addr_t addr) const override;
- lldb::addr_t RemoveNonAddressBits(lldb::addr_t addr) const override;
+ lldb::addr_t RemoveTagBits(lldb::addr_t addr) const override;
ptrdiff_t AddressDiff(lldb::addr_t addr1, lldb::addr_t addr2) const override;
TagRange ExpandToGranule(TagRange range) const override;
@@ -36,6 +36,10 @@ public:
lldb::addr_t addr, lldb::addr_t end_addr,
const lldb_private::MemoryRegionInfos &memory_regions) const override;
+ llvm::Expected<std::vector<TagRange>> MakeTaggedRanges(
+ lldb::addr_t addr, lldb::addr_t end_addr,
+ const lldb_private::MemoryRegionInfos &memory_regions) const override;
+
llvm::Expected<std::vector<lldb::addr_t>>
UnpackTagsData(const std::vector<uint8_t> &tags,
size_t granules = 0) const override;
diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
index 6c130be7b741..d6c4a8687ec5 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
@@ -178,10 +178,10 @@ static const lldb_private::RegisterSet g_reg_sets_arm64[k_num_register_sets] = {
g_sve_regnums_arm64}};
static const lldb_private::RegisterSet g_reg_set_pauth_arm64 = {
- "Pointer Authentication Registers", "pauth", k_num_pauth_register, NULL};
+ "Pointer Authentication Registers", "pauth", k_num_pauth_register, nullptr};
static const lldb_private::RegisterSet g_reg_set_mte_arm64 = {
- "MTE Control Register", "mte", k_num_mte_register, NULL};
+ "MTE Control Register", "mte", k_num_mte_register, nullptr};
RegisterInfoPOSIX_arm64::RegisterInfoPOSIX_arm64(
const lldb_private::ArchSpec &target_arch, lldb_private::Flags opt_regsets)
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index b5b105351de5..f6526d03863b 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -173,6 +173,13 @@ bool GDBRemoteCommunicationClient::GetQXferMemoryMapReadSupported() {
return m_supports_qXfer_memory_map_read == eLazyBoolYes;
}
+bool GDBRemoteCommunicationClient::GetQXferSigInfoReadSupported() {
+ if (m_supports_qXfer_siginfo_read == eLazyBoolCalculate) {
+ GetRemoteQSupported();
+ }
+ return m_supports_qXfer_siginfo_read == eLazyBoolYes;
+}
+
uint64_t GDBRemoteCommunicationClient::GetRemoteMaxPacketSize() {
if (m_max_packet_size == 0) {
GetRemoteQSupported();
@@ -273,6 +280,7 @@ void GDBRemoteCommunicationClient::ResetDiscoverableSettings(bool did_exec) {
m_supports_qXfer_libraries_svr4_read = eLazyBoolCalculate;
m_supports_qXfer_features_read = eLazyBoolCalculate;
m_supports_qXfer_memory_map_read = eLazyBoolCalculate;
+ m_supports_qXfer_siginfo_read = eLazyBoolCalculate;
m_supports_augmented_libraries_svr4_read = eLazyBoolCalculate;
m_uses_native_signals = eLazyBoolCalculate;
m_supports_qProcessInfoPID = true;
@@ -320,6 +328,7 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() {
m_supports_augmented_libraries_svr4_read = eLazyBoolNo;
m_supports_qXfer_features_read = eLazyBoolNo;
m_supports_qXfer_memory_map_read = eLazyBoolNo;
+ m_supports_qXfer_siginfo_read = eLazyBoolNo;
m_supports_multiprocess = eLazyBoolNo;
m_supports_qEcho = eLazyBoolNo;
m_supports_QPassSignals = eLazyBoolNo;
@@ -362,6 +371,8 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() {
m_supports_qXfer_features_read = eLazyBoolYes;
else if (x == "qXfer:memory-map:read+")
m_supports_qXfer_memory_map_read = eLazyBoolYes;
+ else if (x == "qXfer:siginfo:read+")
+ m_supports_qXfer_siginfo_read = eLazyBoolYes;
else if (x == "qEcho")
m_supports_qEcho = eLazyBoolYes;
else if (x == "QPassSignals+")
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index c69c33bb1c15..58ed22187747 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -337,6 +337,8 @@ public:
bool GetQXferMemoryMapReadSupported();
+ bool GetQXferSigInfoReadSupported();
+
LazyBool SupportsAllocDeallocMemory() // const
{
// Uncomment this to have lldb pretend the debug server doesn't respond to
@@ -551,6 +553,7 @@ protected:
LazyBool m_supports_qXfer_libraries_svr4_read = eLazyBoolCalculate;
LazyBool m_supports_qXfer_features_read = eLazyBoolCalculate;
LazyBool m_supports_qXfer_memory_map_read = eLazyBoolCalculate;
+ LazyBool m_supports_qXfer_siginfo_read = eLazyBoolCalculate;
LazyBool m_supports_augmented_libraries_svr4_read = eLazyBoolCalculate;
LazyBool m_supports_jThreadExtendedInfo = eLazyBoolCalculate;
LazyBool m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolCalculate;
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp
deleted file mode 100644
index c91d7cb5ac30..000000000000
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp
+++ /dev/null
@@ -1,314 +0,0 @@
-//===-- GDBRemoteCommunicationReplayServer.cpp ----------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include <cerrno>
-
-#include "lldb/Host/Config.h"
-#include "llvm/ADT/ScopeExit.h"
-
-#include "GDBRemoteCommunicationReplayServer.h"
-#include "ProcessGDBRemoteLog.h"
-
-// C Includes
-// C++ Includes
-#include <cstring>
-
-// Project includes
-#include "lldb/Host/ThreadLauncher.h"
-#include "lldb/Utility/ConstString.h"
-#include "lldb/Utility/Event.h"
-#include "lldb/Utility/FileSpec.h"
-#include "lldb/Utility/StreamString.h"
-#include "lldb/Utility/StringExtractorGDBRemote.h"
-
-using namespace llvm;
-using namespace lldb;
-using namespace lldb_private;
-using namespace lldb_private::process_gdb_remote;
-
-/// Check if the given expected packet matches the actual packet.
-static bool unexpected(llvm::StringRef expected, llvm::StringRef actual) {
- // The 'expected' string contains the raw data, including the leading $ and
- // trailing checksum. The 'actual' string contains only the packet's content.
- if (expected.contains(actual))
- return false;
- // Contains a PID which might be different.
- if (expected.contains("vAttach"))
- return false;
- // Contains a ascii-hex-path.
- if (expected.contains("QSetSTD"))
- return false;
- // Contains environment values.
- if (expected.contains("QEnvironment"))
- return false;
-
- return true;
-}
-
-/// Check if we should reply to the given packet.
-static bool skip(llvm::StringRef data) {
- assert(!data.empty() && "Empty packet?");
-
- // We've already acknowledge the '+' packet so we're done here.
- if (data == "+")
- return true;
-
- /// Don't 't reply to ^C. We need this because of stop reply packets, which
- /// are only returned when the target halts. Reproducers synchronize these
- /// 'asynchronous' replies, by recording them as a regular replies to the
- /// previous packet (e.g. vCont). As a result, we should ignore real
- /// asynchronous requests.
- if (data.data()[0] == 0x03)
- return true;
-
- return false;
-}
-
-GDBRemoteCommunicationReplayServer::GDBRemoteCommunicationReplayServer()
- : GDBRemoteCommunication("gdb-replay", "gdb-replay.rx_packet"),
- m_async_broadcaster(nullptr, "lldb.gdb-replay.async-broadcaster"),
- m_async_listener_sp(
- Listener::MakeListener("lldb.gdb-replay.async-listener")),
- m_async_thread_state_mutex() {
- m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue,
- "async thread continue");
- m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit,
- "async thread should exit");
-
- const uint32_t async_event_mask =
- eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit;
- m_async_listener_sp->StartListeningForEvents(&m_async_broadcaster,
- async_event_mask);
-}
-
-GDBRemoteCommunicationReplayServer::~GDBRemoteCommunicationReplayServer() {
- StopAsyncThread();
-}
-
-GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationReplayServer::GetPacketAndSendResponse(
- Timeout<std::micro> timeout, Status &error, bool &interrupt, bool &quit) {
- std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex);
-
- StringExtractorGDBRemote packet;
- PacketResult packet_result = WaitForPacketNoLock(packet, timeout, false);
-
- if (packet_result != PacketResult::Success) {
- if (!IsConnected()) {
- error.SetErrorString("lost connection");
- quit = true;
- } else {
- error.SetErrorString("timeout");
- }
- return packet_result;
- }
-
- m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue);
-
- // Check if we should reply to this packet.
- if (skip(packet.GetStringRef()))
- return PacketResult::Success;
-
- // This completes the handshake. Since m_send_acks was true, we can unset it
- // already.
- if (packet.GetStringRef() == "QStartNoAckMode")
- m_send_acks = false;
-
- // A QEnvironment packet is sent for every environment variable. If the
- // number of environment variables is different during replay, the replies
- // become out of sync.
- if (packet.GetStringRef().find("QEnvironment") == 0)
- return SendRawPacketNoLock("$OK#9a");
-
- Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
- while (!m_packet_history.empty()) {
- // Pop last packet from the history.
- GDBRemotePacket entry = m_packet_history.back();
- m_packet_history.pop_back();
-
- // Decode run-length encoding.
- const std::string expanded_data =
- GDBRemoteCommunication::ExpandRLE(entry.packet.data);
-
- // We've handled the handshake implicitly before. Skip the packet and move
- // on.
- if (entry.packet.data == "+")
- continue;
-
- if (entry.type == GDBRemotePacket::ePacketTypeSend) {
- if (unexpected(expanded_data, packet.GetStringRef())) {
- LLDB_LOG(log,
- "GDBRemoteCommunicationReplayServer expected packet: '{0}'",
- expanded_data);
- LLDB_LOG(log, "GDBRemoteCommunicationReplayServer actual packet: '{0}'",
- packet.GetStringRef());
-#ifndef NDEBUG
- // This behaves like a regular assert, but prints the expected and
- // received packet before aborting.
- printf("Reproducer expected packet: '%s'\n", expanded_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;
- }
-
- // Ignore QEnvironment packets as they're handled earlier.
- if (expanded_data.find("QEnvironment") == 1) {
- assert(m_packet_history.back().type ==
- GDBRemotePacket::ePacketTypeRecv);
- m_packet_history.pop_back();
- }
-
- continue;
- }
-
- if (entry.type == GDBRemotePacket::ePacketTypeInvalid) {
- LLDB_LOG(
- log,
- "GDBRemoteCommunicationReplayServer skipped invalid packet: '{0}'",
- packet.GetStringRef());
- continue;
- }
-
- LLDB_LOG(log,
- "GDBRemoteCommunicationReplayServer replied to '{0}' with '{1}'",
- packet.GetStringRef(), entry.packet.data);
- return SendRawPacketNoLock(entry.packet.data);
- }
-
- quit = true;
-
- return packet_result;
-}
-
-llvm::Error
-GDBRemoteCommunicationReplayServer::LoadReplayHistory(const FileSpec &path) {
- auto error_or_file = MemoryBuffer::getFile(path.GetPath());
- if (auto err = error_or_file.getError())
- return errorCodeToError(err);
-
- yaml::Input yin((*error_or_file)->getBuffer());
- yin >> m_packet_history;
-
- if (auto err = yin.error())
- return errorCodeToError(err);
-
- // We want to manipulate the vector like a stack so we need to reverse the
- // order of the packets to have the oldest on at the back.
- std::reverse(m_packet_history.begin(), m_packet_history.end());
-
- return Error::success();
-}
-
-bool GDBRemoteCommunicationReplayServer::StartAsyncThread() {
- std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex);
- if (!m_async_thread.IsJoinable()) {
- // Create a thread that watches our internal state and controls which
- // events make it to clients (into the DCProcess event queue).
- llvm::Expected<HostThread> async_thread = ThreadLauncher::LaunchThread(
- "<lldb.gdb-replay.async>",
- GDBRemoteCommunicationReplayServer::AsyncThread, this);
- if (!async_thread) {
- LLDB_LOG_ERROR(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST),
- async_thread.takeError(),
- "failed to launch host thread: {}");
- return false;
- }
- m_async_thread = *async_thread;
- }
-
- // Wait for handshake.
- m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue);
-
- return m_async_thread.IsJoinable();
-}
-
-void GDBRemoteCommunicationReplayServer::StopAsyncThread() {
- std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex);
-
- if (!m_async_thread.IsJoinable())
- return;
-
- // Request thread to stop.
- m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncThreadShouldExit);
-
- // Disconnect client.
- Disconnect();
-
- // Stop the thread.
- m_async_thread.Join(nullptr);
- m_async_thread.Reset();
-}
-
-void GDBRemoteCommunicationReplayServer::ReceivePacket(
- GDBRemoteCommunicationReplayServer &server, bool &done) {
- Status error;
- bool interrupt;
- auto packet_result = server.GetPacketAndSendResponse(std::chrono::seconds(1),
- error, interrupt, done);
- if (packet_result != GDBRemoteCommunication::PacketResult::Success &&
- packet_result !=
- GDBRemoteCommunication::PacketResult::ErrorReplyTimeout) {
- done = true;
- } else {
- server.m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue);
- }
-}
-
-thread_result_t GDBRemoteCommunicationReplayServer::AsyncThread(void *arg) {
- GDBRemoteCommunicationReplayServer *server =
- (GDBRemoteCommunicationReplayServer *)arg;
- auto D = make_scope_exit([&]() { server->Disconnect(); });
- EventSP event_sp;
- bool done = false;
- while (!done) {
- if (server->m_async_listener_sp->GetEvent(event_sp, llvm::None)) {
- const uint32_t event_type = event_sp->GetType();
- if (event_sp->BroadcasterIs(&server->m_async_broadcaster)) {
- switch (event_type) {
- case eBroadcastBitAsyncContinue:
- ReceivePacket(*server, done);
- if (done)
- return {};
- break;
- case eBroadcastBitAsyncThreadShouldExit:
- default:
- return {};
- }
- }
- }
- }
-
- return {};
-}
-
-Status GDBRemoteCommunicationReplayServer::Connect(
- process_gdb_remote::GDBRemoteCommunicationClient &client) {
- repro::Loader *loader = repro::Reproducer::Instance().GetLoader();
- if (!loader)
- return Status("No loader provided.");
-
- static std::unique_ptr<repro::MultiLoader<repro::GDBRemoteProvider>>
- multi_loader = repro::MultiLoader<repro::GDBRemoteProvider>::Create(
- repro::Reproducer::Instance().GetLoader());
- 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.");
-
- if (auto error = LoadReplayHistory(FileSpec(*history_file)))
- return Status("Unable to load replay history");
-
- if (auto error = GDBRemoteCommunication::ConnectLocally(client, *this))
- return Status("Unable to connect to replay server");
-
- return {};
-}
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h
deleted file mode 100644
index 2f8770d0accf..000000000000
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h
+++ /dev/null
@@ -1,88 +0,0 @@
-//===-- GDBRemoteCommunicationReplayServer.h --------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONREPLAYSERVER_H
-#define LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONREPLAYSERVER_H
-
-// Other libraries and framework includes
-#include "GDBRemoteCommunication.h"
-#include "GDBRemoteCommunicationClient.h"
-#include "GDBRemoteCommunicationHistory.h"
-
-// Project includes
-#include "lldb/Host/HostThread.h"
-#include "lldb/Utility/Broadcaster.h"
-#include "lldb/lldb-private-forward.h"
-#include "llvm/Support/Error.h"
-
-// C Includes
-// C++ Includes
-#include <functional>
-#include <map>
-#include <thread>
-
-class StringExtractorGDBRemote;
-
-namespace lldb_private {
-namespace process_gdb_remote {
-
-class ProcessGDBRemote;
-
-/// Dummy GDB server that replays packets from the GDB Remote Communication
-/// history. This is used to replay GDB packets.
-class GDBRemoteCommunicationReplayServer : public GDBRemoteCommunication {
-public:
- GDBRemoteCommunicationReplayServer();
-
- ~GDBRemoteCommunicationReplayServer() override;
-
- PacketResult GetPacketAndSendResponse(Timeout<std::micro> timeout,
- Status &error, bool &interrupt,
- bool &quit);
-
- bool HandshakeWithClient() { return GetAck() == PacketResult::Success; }
-
- llvm::Error LoadReplayHistory(const FileSpec &path);
-
- bool StartAsyncThread();
- void StopAsyncThread();
-
- Status Connect(process_gdb_remote::GDBRemoteCommunicationClient &client);
-
-protected:
- enum {
- eBroadcastBitAsyncContinue = (1 << 0),
- eBroadcastBitAsyncThreadShouldExit = (1 << 1),
- };
-
- static void ReceivePacket(GDBRemoteCommunicationReplayServer &server,
- bool &done);
- static lldb::thread_result_t AsyncThread(void *arg);
-
- /// Replay history with the oldest packet at the end.
- std::vector<GDBRemotePacket> m_packet_history;
-
- /// Server thread.
- Broadcaster m_async_broadcaster;
- lldb::ListenerSP m_async_listener_sp;
- HostThread m_async_thread;
- std::recursive_mutex m_async_thread_state_mutex;
-
- bool m_skip_acks = false;
-
-private:
- GDBRemoteCommunicationReplayServer(
- const GDBRemoteCommunicationReplayServer &) = delete;
- const GDBRemoteCommunicationReplayServer &
- operator=(const GDBRemoteCommunicationReplayServer &) = delete;
-};
-
-} // namespace process_gdb_remote
-} // namespace lldb_private
-
-#endif // LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONREPLAYSERVER_H
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index 30f14a52dfb5..123a8198a89b 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -1086,7 +1086,7 @@ void GDBRemoteCommunicationServerLLGS::NewSubprocess(
}
void GDBRemoteCommunicationServerLLGS::DataAvailableCallback() {
- Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_COMM));
+ Log *log = GetLog(GDBRLog::Comm);
bool interrupt = false;
bool done = false;
@@ -2920,6 +2920,18 @@ GDBRemoteCommunicationServerLLGS::ReadXferObject(llvm::StringRef object,
return std::move(*buffer_or_error);
}
+ if (object == "siginfo") {
+ NativeThreadProtocol *thread = m_current_process->GetCurrentThread();
+ if (!thread)
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "no current thread");
+
+ auto buffer_or_error = thread->GetSiginfo();
+ if (!buffer_or_error)
+ return buffer_or_error.takeError();
+ return std::move(*buffer_or_error);
+ }
+
if (object == "libraries-svr4") {
auto library_list = m_current_process->GetLoadedSVR4Libraries();
if (!library_list)
@@ -3838,6 +3850,8 @@ std::vector<std::string> GDBRemoteCommunicationServerLLGS::HandleFeatures(
ret.push_back("qXfer:auxv:read+");
if (bool(plugin_features & Extension::libraries_svr4))
ret.push_back("qXfer:libraries-svr4:read+");
+ if (bool(plugin_features & Extension::siginfo_read))
+ ret.push_back("qXfer:siginfo:read+");
if (bool(plugin_features & Extension::memory_tagging))
ret.push_back("memory-tagging+");
if (bool(plugin_features & Extension::savecore))
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterFallback.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterFallback.cpp
new file mode 100644
index 000000000000..b391edced695
--- /dev/null
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterFallback.cpp
@@ -0,0 +1,86 @@
+//===-- GDBRemoteRegisterFallback.cpp -------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "GDBRemoteRegisterFallback.h"
+
+namespace lldb_private {
+namespace process_gdb_remote {
+
+#define REG(name, size) \
+ DynamicRegisterInfo::Register { \
+ ConstString(#name), empty_alt_name, reg_set, size, LLDB_INVALID_INDEX32, \
+ lldb::eEncodingUint, lldb::eFormatHex, LLDB_INVALID_REGNUM, \
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, {}, {} \
+ }
+#define R64(name) REG(name, 8)
+#define R32(name) REG(name, 4)
+
+static std::vector<DynamicRegisterInfo::Register> GetRegisters_aarch64() {
+ ConstString empty_alt_name;
+ ConstString reg_set{"general purpose registers"};
+
+ std::vector<DynamicRegisterInfo::Register> registers{
+ R64(x0), R64(x1), R64(x2), R64(x3), R64(x4), R64(x5), R64(x6),
+ R64(x7), R64(x8), R64(x9), R64(x10), R64(x11), R64(x12), R64(x13),
+ R64(x14), R64(x15), R64(x16), R64(x17), R64(x18), R64(x19), R64(x20),
+ R64(x21), R64(x22), R64(x23), R64(x24), R64(x25), R64(x26), R64(x27),
+ R64(x28), R64(x29), R64(x30), R64(sp), R64(pc), R32(cpsr),
+ };
+
+ return registers;
+}
+
+static std::vector<DynamicRegisterInfo::Register> GetRegisters_x86() {
+ ConstString empty_alt_name;
+ ConstString reg_set{"general purpose registers"};
+
+ std::vector<DynamicRegisterInfo::Register> registers{
+ R32(eax), R32(ecx), R32(edx), R32(ebx), R32(esp), R32(ebp),
+ R32(esi), R32(edi), R32(eip), R32(eflags), R32(cs), R32(ss),
+ R32(ds), R32(es), R32(fs), R32(gs),
+ };
+
+ return registers;
+}
+
+static std::vector<DynamicRegisterInfo::Register> GetRegisters_x86_64() {
+ ConstString empty_alt_name;
+ ConstString reg_set{"general purpose registers"};
+
+ std::vector<DynamicRegisterInfo::Register> registers{
+ R64(rax), R64(rbx), R64(rcx), R64(rdx), R64(rsi), R64(rdi),
+ R64(rbp), R64(rsp), R64(r8), R64(r9), R64(r10), R64(r11),
+ R64(r12), R64(r13), R64(r14), R64(r15), R64(rip), R32(eflags),
+ R32(cs), R32(ss), R32(ds), R32(es), R32(fs), R32(gs),
+ };
+
+ return registers;
+}
+
+#undef R32
+#undef R64
+#undef REG
+
+std::vector<DynamicRegisterInfo::Register>
+GetFallbackRegisters(const ArchSpec &arch_to_use) {
+ switch (arch_to_use.GetMachine()) {
+ case llvm::Triple::aarch64:
+ return GetRegisters_aarch64();
+ case llvm::Triple::x86:
+ return GetRegisters_x86();
+ case llvm::Triple::x86_64:
+ return GetRegisters_x86_64();
+ default:
+ break;
+ }
+
+ return {};
+}
+
+} // namespace process_gdb_remote
+} // namespace lldb_private
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterFallback.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterFallback.h
new file mode 100644
index 000000000000..82e03c6b9b1c
--- /dev/null
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterFallback.h
@@ -0,0 +1,26 @@
+//===-- GDBRemoteRegisterFallback.h -----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTEREGISTERFALLBACK_H
+#define LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTEREGISTERFALLBACK_H
+
+#include <vector>
+
+#include "lldb/Target/DynamicRegisterInfo.h"
+#include "lldb/Utility/ArchSpec.h"
+
+namespace lldb_private {
+namespace process_gdb_remote {
+
+std::vector<DynamicRegisterInfo::Register>
+GetFallbackRegisters(const ArchSpec &arch_to_use);
+
+} // namespace process_gdb_remote
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTEREGISTERFALLBACK_H
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 93fe36c0d9d6..d8ad0b4e4e4b 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -23,13 +23,6 @@
#include <ctime>
#include <sys/types.h>
-#include <algorithm>
-#include <csignal>
-#include <map>
-#include <memory>
-#include <mutex>
-#include <sstream>
-
#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
@@ -70,8 +63,16 @@
#include "lldb/Utility/State.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/Timer.h"
+#include <algorithm>
+#include <csignal>
+#include <map>
+#include <memory>
+#include <mutex>
+#include <sstream>
+#include <thread>
#include "GDBRemoteRegisterContext.h"
+#include "GDBRemoteRegisterFallback.h"
#include "Plugins/Platform/MacOSX/PlatformRemoteiOS.h"
#include "Plugins/Process/Utility/GDBRemoteSignals.h"
#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
@@ -253,9 +254,8 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp,
m_addr_to_mmap_size(), m_thread_create_bp_sp(),
m_waiting_for_attach(false), m_destroy_tried_resuming(false),
m_command_sp(), m_breakpoint_pc_offset(0),
- m_initial_tid(LLDB_INVALID_THREAD_ID), m_replay_mode(false),
- m_allow_flash_writes(false), m_erased_flash_ranges(),
- m_vfork_in_progress(false) {
+ m_initial_tid(LLDB_INVALID_THREAD_ID), m_allow_flash_writes(false),
+ m_erased_flash_ranges(), m_vfork_in_progress(false) {
m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit,
"async thread should exit");
m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue,
@@ -395,6 +395,7 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) {
// 2 - If the target definition doesn't have any of the info from the
// target.xml (registers) then proceed to read the target.xml.
// 3 - Fall back on the qRegisterInfo packets.
+ // 4 - Use hardcoded defaults if available.
FileSpec target_definition_fspec =
GetGlobalPluginProperties().GetTargetDefinitionFile();
@@ -508,6 +509,9 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) {
}
}
+ if (registers.empty())
+ registers = GetFallbackRegisters(arch_to_use);
+
AddRemoteRegisters(registers, arch_to_use);
}
@@ -525,7 +529,7 @@ Status ProcessGDBRemote::WillAttachToProcessWithName(const char *process_name,
}
Status ProcessGDBRemote::DoConnectRemote(llvm::StringRef remote_url) {
- Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ Log *log = GetLog(GDBRLog::Process);
Status error(WillLaunchOrAttach());
if (error.Fail())
@@ -602,8 +606,7 @@ Status ProcessGDBRemote::DoConnectRemote(llvm::StringRef remote_url) {
ReadModuleFromMemory(FileSpec(namebuf), standalone_value);
}
- Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(
- LIBLLDB_LOG_DYNAMIC_LOADER));
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
if (module_sp.get()) {
target.GetImages().AppendIfNeeded(module_sp, false);
@@ -3316,24 +3319,6 @@ Status ProcessGDBRemote::DoSignal(int signo) {
return error;
}
-Status ProcessGDBRemote::ConnectToReplayServer() {
- Status status = m_gdb_replay_server.Connect(m_gdb_comm);
- if (status.Fail())
- return status;
-
- // Enable replay mode.
- m_replay_mode = true;
-
- // Start server thread.
- m_gdb_replay_server.StartAsyncThread();
-
- // Start client thread.
- StartAsyncThread();
-
- // Do the usual setup.
- return ConnectToDebugserver("");
-}
-
Status
ProcessGDBRemote::EstablishConnectionIfNeeded(const ProcessInfo &process_info) {
// Make sure we aren't already connected?
@@ -4370,9 +4355,9 @@ bool ProcessGDBRemote::GetGDBServerRegisterInfoXMLAndProcess(
} else if (name == "osabi") {
node.GetElementText(target_info.osabi);
} else if (name == "xi:include" || name == "include") {
- llvm::StringRef href = node.GetAttributeValue("href");
+ std::string href = node.GetAttributeValue("href");
if (!href.empty())
- target_info.includes.push_back(href.str());
+ target_info.includes.push_back(href);
} else if (name == "feature") {
feature_nodes.push_back(node);
} else if (name == "groups") {
@@ -4411,9 +4396,9 @@ bool ProcessGDBRemote::GetGDBServerRegisterInfoXMLAndProcess(
const XMLNode &node) -> bool {
llvm::StringRef name = node.GetName();
if (name == "xi:include" || name == "include") {
- llvm::StringRef href = node.GetAttributeValue("href");
+ std::string href = node.GetAttributeValue("href");
if (!href.empty())
- target_info.includes.push_back(href.str());
+ target_info.includes.push_back(href);
}
return true;
});
@@ -4549,7 +4534,7 @@ llvm::Expected<LoadedModuleInfoList> ProcessGDBRemote::GetLoadedModuleList() {
"Error finding library-list-svr4 xml element");
// main link map structure
- llvm::StringRef main_lm = root_element.GetAttributeValue("main-lm");
+ std::string main_lm = root_element.GetAttributeValue("main-lm");
// FIXME: we're silently ignoring invalid data here
if (!main_lm.empty())
llvm::to_integer(main_lm, list.m_link_map);
@@ -4637,15 +4622,15 @@ llvm::Expected<LoadedModuleInfoList> ProcessGDBRemote::GetLoadedModuleList() {
"library", [log, &list](const XMLNode &library) -> bool {
LoadedModuleInfoList::LoadedModuleInfo module;
- llvm::StringRef name = library.GetAttributeValue("name");
- module.set_name(name.str());
+ std::string name = library.GetAttributeValue("name");
+ module.set_name(name);
// The base address of a given library will be the address of its
// first section. Most remotes send only one section for Windows
// targets for example.
const XMLNode &section =
library.FindFirstChildElementWithName("section");
- llvm::StringRef address = section.GetAttributeValue("address");
+ std::string address = section.GetAttributeValue("address");
uint64_t address_value = LLDB_INVALID_ADDRESS;
llvm::to_integer(address, address_value);
module.set_base(address_value);
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 488336b8c1b8..bdf130e3ec11 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -34,7 +34,6 @@
#include "lldb/lldb-private-forward.h"
#include "GDBRemoteCommunicationClient.h"
-#include "GDBRemoteCommunicationReplayServer.h"
#include "GDBRemoteRegisterContext.h"
#include "llvm/ADT/DenseMap.h"
@@ -251,7 +250,6 @@ protected:
};
GDBRemoteCommunicationClient m_gdb_comm;
- GDBRemoteCommunicationReplayServer m_gdb_replay_server;
std::atomic<lldb::pid_t> m_debugserver_pid;
llvm::Optional<StringExtractorGDBRemote> m_last_stop_packet;
@@ -292,7 +290,6 @@ protected:
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;
using FlashRangeVector = lldb_private::RangeVector<lldb::addr_t, size_t>;
using FlashRange = FlashRangeVector::Entry;
@@ -320,8 +317,6 @@ protected:
bool DoUpdateThreadList(ThreadList &old_thread_list,
ThreadList &new_thread_list) override;
- Status ConnectToReplayServer();
-
Status EstablishConnectionIfNeeded(const ProcessInfo &process_info);
Status LaunchAndConnectToDebugserver(const ProcessInfo &process_info);
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp
index 40990ef66494..3322f6b8048a 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp
@@ -15,25 +15,29 @@ using namespace lldb_private;
using namespace lldb_private::process_gdb_remote;
static constexpr Log::Category g_categories[] = {
- {{"async"}, {"log asynchronous activity"}, GDBR_LOG_ASYNC},
- {{"break"}, {"log breakpoints"}, GDBR_LOG_BREAKPOINTS},
- {{"comm"}, {"log communication activity"}, GDBR_LOG_COMM},
- {{"packets"}, {"log gdb remote packets"}, GDBR_LOG_PACKETS},
- {{"memory"}, {"log memory reads and writes"}, GDBR_LOG_MEMORY},
+ {{"async"}, {"log asynchronous activity"}, GDBRLog::Async},
+ {{"break"}, {"log breakpoints"}, GDBRLog::Breakpoints},
+ {{"comm"}, {"log communication activity"}, GDBRLog::Comm},
+ {{"packets"}, {"log gdb remote packets"}, GDBRLog::Packets},
+ {{"memory"}, {"log memory reads and writes"}, GDBRLog::Memory},
{{"data-short"},
{"log memory bytes for memory reads and writes for short transactions "
"only"},
- GDBR_LOG_MEMORY_DATA_SHORT},
+ GDBRLog::MemoryDataShort},
{{"data-long"},
{"log memory bytes for memory reads and writes for all transactions"},
- GDBR_LOG_MEMORY_DATA_LONG},
- {{"process"}, {"log process events and activities"}, GDBR_LOG_PROCESS},
- {{"step"}, {"log step related activities"}, GDBR_LOG_STEP},
- {{"thread"}, {"log thread events and activities"}, GDBR_LOG_THREAD},
- {{"watch"}, {"log watchpoint related activities"}, GDBR_LOG_WATCHPOINTS},
+ GDBRLog::MemoryDataLong},
+ {{"process"}, {"log process events and activities"}, GDBRLog::Process},
+ {{"step"}, {"log step related activities"}, GDBRLog::Step},
+ {{"thread"}, {"log thread events and activities"}, GDBRLog::Thread},
+ {{"watch"}, {"log watchpoint related activities"}, GDBRLog::Watchpoints},
};
-Log::Channel ProcessGDBRemoteLog::g_channel(g_categories, GDBR_LOG_DEFAULT);
+static Log::Channel g_channel(g_categories, GDBRLog::Packets);
+
+template <> Log::Channel &lldb_private::LogChannelFor<GDBRLog>() {
+ return g_channel;
+}
void ProcessGDBRemoteLog::Initialize() {
static llvm::once_flag g_once_flag;
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h
index bd3e993cf72a..44e390ec8cad 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h
@@ -11,35 +11,52 @@
#include "lldb/Utility/Log.h"
-#define GDBR_LOG_PROCESS (1u << 1)
-#define GDBR_LOG_THREAD (1u << 2)
-#define GDBR_LOG_PACKETS (1u << 3)
-#define GDBR_LOG_MEMORY (1u << 4) // Log memory reads/writes calls
-#define GDBR_LOG_MEMORY_DATA_SHORT \
- (1u << 5) // Log short memory reads/writes bytes
-#define GDBR_LOG_MEMORY_DATA_LONG (1u << 6) // Log all memory reads/writes bytes
-#define GDBR_LOG_BREAKPOINTS (1u << 7)
-#define GDBR_LOG_WATCHPOINTS (1u << 8)
-#define GDBR_LOG_STEP (1u << 9)
-#define GDBR_LOG_COMM (1u << 10)
-#define GDBR_LOG_ASYNC (1u << 11)
-#define GDBR_LOG_ALL (UINT32_MAX)
-#define GDBR_LOG_DEFAULT GDBR_LOG_PACKETS
-
namespace lldb_private {
namespace process_gdb_remote {
-class ProcessGDBRemoteLog {
- static Log::Channel g_channel;
+enum class GDBRLog : Log::MaskType {
+ Async = Log::ChannelFlag<0>,
+ Breakpoints = Log::ChannelFlag<1>,
+ Comm = Log::ChannelFlag<2>,
+ Memory = Log::ChannelFlag<3>, // Log memory reads/writes calls
+ MemoryDataLong = Log::ChannelFlag<4>, // Log all memory reads/writes bytes
+ MemoryDataShort = Log::ChannelFlag<5>, // Log short memory reads/writes bytes
+ Packets = Log::ChannelFlag<6>,
+ Process = Log::ChannelFlag<7>,
+ Step = Log::ChannelFlag<8>,
+ Thread = Log::ChannelFlag<9>,
+ Watchpoints = Log::ChannelFlag<10>,
+ LLVM_MARK_AS_BITMASK_ENUM(Watchpoints)
+};
+#define GDBR_LOG_PROCESS ::lldb_private::process_gdb_remote::GDBRLog::Process
+#define GDBR_LOG_THREAD ::lldb_private::process_gdb_remote::GDBRLog::Thread
+#define GDBR_LOG_PACKETS ::lldb_private::process_gdb_remote::GDBRLog::Packets
+#define GDBR_LOG_MEMORY ::lldb_private::process_gdb_remote::GDBRLog::Memory
+#define GDBR_LOG_MEMORY_DATA_SHORT \
+ ::lldb_private::process_gdb_remote::GDBRLog::MemoryDataShort
+#define GDBR_LOG_MEMORY_DATA_LONG \
+ ::lldb_private::process_gdb_remote::GDBRLog::MemoryDataLong
+#define GDBR_LOG_BREAKPOINTS \
+ ::lldb_private::process_gdb_remote::GDBRLog::Breakpoints
+#define GDBR_LOG_WATCHPOINTS \
+ ::lldb_private::process_gdb_remote::GDBRLog::Watchpoints
+#define GDBR_LOG_STEP ::lldb_private::process_gdb_remote::GDBRLog::Step
+#define GDBR_LOG_COMM ::lldb_private::process_gdb_remote::GDBRLog::Comm
+#define GDBR_LOG_ASYNC ::lldb_private::process_gdb_remote::GDBRLog::Async
+
+class ProcessGDBRemoteLog {
public:
static void Initialize();
- static Log *GetLogIfAllCategoriesSet(uint32_t mask) { return g_channel.GetLogIfAll(mask); }
- static Log *GetLogIfAnyCategoryIsSet(uint32_t mask) { return g_channel.GetLogIfAny(mask); }
+ static Log *GetLogIfAllCategoriesSet(GDBRLog mask) { return GetLog(mask); }
+ static Log *GetLogIfAnyCategoryIsSet(GDBRLog mask) { return GetLog(mask); }
};
} // namespace process_gdb_remote
+
+template <> Log::Channel &LogChannelFor<process_gdb_remote::GDBRLog>();
+
} // namespace lldb_private
#endif // LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_PROCESSGDBREMOTELOG_H
diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
index 2a9896e41085..3d23c074c1be 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -39,7 +39,7 @@ ThreadGDBRemote::ThreadGDBRemote(Process &process, lldb::tid_t tid)
m_dispatch_queue_t(LLDB_INVALID_ADDRESS), m_queue_kind(eQueueKindUnknown),
m_queue_serial_number(LLDB_INVALID_QUEUE_ID),
m_associated_with_libdispatch_queue(eLazyBoolCalculate) {
- Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_THREAD));
+ Log *log = GetLog(GDBRLog::Thread);
LLDB_LOG(log, "this = {0}, pid = {1}, tid = {2}", this, process.GetID(),
GetID());
// At this point we can clone reg_info for architectures supporting
@@ -54,7 +54,7 @@ ThreadGDBRemote::ThreadGDBRemote(Process &process, lldb::tid_t tid)
ThreadGDBRemote::~ThreadGDBRemote() {
ProcessSP process_sp(GetProcess());
- Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_THREAD));
+ Log *log = GetLog(GDBRLog::Thread);
LLDB_LOG(log, "this = {0}, pid = {1}, tid = {2}", this,
process_sp ? process_sp->GetID() : LLDB_INVALID_PROCESS_ID, GetID());
DestroyThread();
@@ -222,7 +222,7 @@ void ThreadGDBRemote::SetAssociatedWithLibdispatchQueue(
StructuredData::ObjectSP ThreadGDBRemote::FetchThreadExtendedInfo() {
StructuredData::ObjectSP object_sp;
const lldb::user_id_t tid = GetProtocolID();
- Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_THREAD));
+ Log *log = GetLog(GDBRLog::Thread);
LLDB_LOGF(log, "Fetching extended information for thread %4.4" PRIx64, tid);
ProcessSP process_sp(GetProcess());
if (process_sp) {
@@ -236,7 +236,7 @@ StructuredData::ObjectSP ThreadGDBRemote::FetchThreadExtendedInfo() {
void ThreadGDBRemote::WillResume(StateType resume_state) {
int signo = GetResumeSignal();
const lldb::user_id_t tid = GetProtocolID();
- Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_THREAD));
+ Log *log = GetLog(GDBRLog::Thread);
LLDB_LOGF(log, "Resuming thread: %4.4" PRIx64 " with state: %s.", tid,
StateAsCString(resume_state));
@@ -346,3 +346,23 @@ bool ThreadGDBRemote::CalculateStopInfo() {
->CalculateThreadStopInfo(this);
return false;
}
+
+llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
+ThreadGDBRemote::GetSiginfo(size_t max_size) const {
+ ProcessSP process_sp(GetProcess());
+ if (!process_sp)
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "no process");
+ ProcessGDBRemote *gdb_process =
+ static_cast<ProcessGDBRemote *>(process_sp.get());
+ if (!gdb_process->m_gdb_comm.GetQXferSigInfoReadSupported())
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "qXfer:siginfo:read not supported");
+
+ llvm::Expected<std::string> response =
+ gdb_process->m_gdb_comm.ReadExtFeature("siginfo", "");
+ if (!response)
+ return response.takeError();
+
+ return llvm::MemoryBuffer::getMemBufferCopy(response.get());
+}
diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
index b7d75021c062..fb83c74fd2c5 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
+++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
@@ -90,6 +90,9 @@ public:
StructuredData::ObjectSP FetchThreadExtendedInfo() override;
+ llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
+ GetSiginfo(size_t max_size) const override;
+
protected:
friend class ProcessGDBRemote;
diff --git a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
index cb21a3e7e65f..5eb7cb0e6a5c 100644
--- a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
+++ b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
@@ -164,9 +164,6 @@ Status ScriptedProcess::DoLaunch(Module *exe_module,
SetPrivateState(eStateStopped);
- UpdateThreadListIfNeeded();
- GetThreadList();
-
return {};
}
@@ -225,8 +222,8 @@ bool ScriptedProcess::IsAlive() {
size_t ScriptedProcess::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
Status &error) {
if (!m_interpreter)
- return GetInterface().ErrorWithMessage<size_t>(LLVM_PRETTY_FUNCTION,
- "No interpreter.", error);
+ return ScriptedInterface::ErrorWithMessage<size_t>(
+ LLVM_PRETTY_FUNCTION, "No interpreter.", error);
lldb::DataExtractorSP data_extractor_sp =
GetInterface().ReadMemoryAtAddress(addr, size, error);
@@ -238,7 +235,7 @@ size_t ScriptedProcess::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
0, data_extractor_sp->GetByteSize(), buf, size, GetByteOrder());
if (!bytes_copied || bytes_copied == LLDB_INVALID_OFFSET)
- return GetInterface().ErrorWithMessage<size_t>(
+ return ScriptedInterface::ErrorWithMessage<size_t>(
LLVM_PRETTY_FUNCTION, "Failed to copy read memory to buffer.", error);
return size;
@@ -296,7 +293,7 @@ bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list,
ScriptLanguage language = m_interpreter->GetLanguage();
if (language != eScriptLanguagePython)
- return GetInterface().ErrorWithMessage<bool>(
+ return ScriptedInterface::ErrorWithMessage<bool>(
LLVM_PRETTY_FUNCTION,
llvm::Twine("ScriptInterpreter language (" +
llvm::Twine(m_interpreter->LanguageToString(language)) +
@@ -304,19 +301,57 @@ bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list,
.str(),
error);
- lldb::ThreadSP thread_sp;
- thread_sp = std::make_shared<ScriptedThread>(*this, error);
+ StructuredData::DictionarySP thread_info_sp = GetInterface().GetThreadsInfo();
+
+ if (!thread_info_sp)
+ return ScriptedInterface::ErrorWithMessage<bool>(
+ LLVM_PRETTY_FUNCTION,
+ "Couldn't fetch thread list from Scripted Process.", error);
+
+ auto create_scripted_thread =
+ [this, &old_thread_list, &error,
+ &new_thread_list](ConstString key, StructuredData::Object *val) -> bool {
+ if (!val)
+ return ScriptedInterface::ErrorWithMessage<bool>(
+ LLVM_PRETTY_FUNCTION, "Invalid thread info object", error);
+
+ lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
+ if (!llvm::to_integer(key.AsCString(), tid))
+ return ScriptedInterface::ErrorWithMessage<bool>(
+ LLVM_PRETTY_FUNCTION, "Invalid thread id", error);
+
+ if (ThreadSP thread_sp =
+ old_thread_list.FindThreadByID(tid, false /*=can_update*/)) {
+ // If the thread was already in the old_thread_list,
+ // just add it back to the new_thread_list.
+ new_thread_list.AddThread(thread_sp);
+ return true;
+ }
+
+ auto thread_or_error = ScriptedThread::Create(*this, val->GetAsGeneric());
+
+ if (!thread_or_error)
+ return ScriptedInterface::ErrorWithMessage<bool>(
+ LLVM_PRETTY_FUNCTION, toString(thread_or_error.takeError()), error);
+
+ ThreadSP thread_sp = thread_or_error.get();
+ lldbassert(thread_sp && "Couldn't initialize scripted thread.");
+
+ RegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext();
+ if (!reg_ctx_sp)
+ return ScriptedInterface::ErrorWithMessage<bool>(
+ LLVM_PRETTY_FUNCTION,
+ llvm::Twine("Invalid Register Context for thread " +
+ llvm::Twine(key.AsCString()))
+ .str(),
+ error);
- if (!thread_sp || error.Fail())
- return GetInterface().ErrorWithMessage<bool>(LLVM_PRETTY_FUNCTION,
- error.AsCString(), error);
+ new_thread_list.AddThread(thread_sp);
- RegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext();
- if (!reg_ctx_sp)
- return GetInterface().ErrorWithMessage<bool>(
- LLVM_PRETTY_FUNCTION, "Invalid Register Context", error);
+ return true;
+ };
- new_thread_list.AddThread(thread_sp);
+ thread_info_sp->ForEach(create_scripted_thread);
return new_thread_list.GetSize(false) > 0;
}
@@ -324,7 +359,6 @@ bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list,
void ScriptedProcess::RefreshStateAfterStop() {
// Let all threads recover from stopping and do any clean up based on the
// previous thread state (if any).
- m_thread_list.RefreshStateAfterStop();
}
bool ScriptedProcess::GetProcessInfo(ProcessInstanceInfo &info) {
diff --git a/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp b/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp
index 959b8c581885..b6cbb62fd6e6 100644
--- a/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp
+++ b/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp
@@ -28,44 +28,60 @@ void ScriptedThread::CheckInterpreterAndScriptObject() const {
lldbassert(GetInterface() && "Invalid Scripted Thread Interface.");
}
-ScriptedThread::ScriptedThread(ScriptedProcess &process, Status &error)
- : Thread(process, LLDB_INVALID_THREAD_ID), m_scripted_process(process) {
- if (!process.IsValid()) {
- error.SetErrorString("Invalid scripted process");
- return;
- }
+llvm::Expected<std::shared_ptr<ScriptedThread>>
+ScriptedThread::Create(ScriptedProcess &process,
+ StructuredData::Generic *script_object) {
+ if (!process.IsValid())
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "Invalid scripted process.");
process.CheckInterpreterAndScriptObject();
- auto scripted_thread_interface = GetInterface();
- if (!scripted_thread_interface) {
- error.SetErrorString("Failed to get scripted thread interface.");
- return;
- }
-
- llvm::Optional<std::string> class_name =
- process.GetInterface().GetScriptedThreadPluginName();
- if (!class_name || class_name->empty()) {
- error.SetErrorString("Failed to get scripted thread class name.");
- return;
+ auto scripted_thread_interface =
+ process.GetInterface().CreateScriptedThreadInterface();
+ if (!scripted_thread_interface)
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "Failed to create scripted thread interface.");
+
+ llvm::StringRef thread_class_name;
+ if (!script_object) {
+ llvm::Optional<std::string> class_name =
+ process.GetInterface().GetScriptedThreadPluginName();
+ if (!class_name || class_name->empty())
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "Failed to get scripted thread class name.");
+ thread_class_name = *class_name;
}
ExecutionContext exe_ctx(process);
-
- StructuredData::GenericSP object_sp =
+ StructuredData::GenericSP owned_script_object_sp =
scripted_thread_interface->CreatePluginObject(
- class_name->c_str(), exe_ctx,
- process.m_scripted_process_info.GetArgsSP());
- if (!object_sp || !object_sp->IsValid()) {
- error.SetErrorString("Failed to create valid script object");
- return;
- }
+ thread_class_name, exe_ctx,
+ process.m_scripted_process_info.GetArgsSP(), script_object);
- m_script_object_sp = object_sp;
+ if (!owned_script_object_sp)
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "Failed to create script object.");
+ if (!owned_script_object_sp->IsValid())
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "Created script object is invalid.");
- SetID(scripted_thread_interface->GetThreadID());
+ lldb::tid_t tid = scripted_thread_interface->GetThreadID();
+
+ return std::make_shared<ScriptedThread>(process, scripted_thread_interface,
+ tid, owned_script_object_sp);
}
+ScriptedThread::ScriptedThread(ScriptedProcess &process,
+ ScriptedThreadInterfaceSP interface_sp,
+ lldb::tid_t tid,
+ StructuredData::GenericSP script_object_sp)
+ : Thread(process, tid), m_scripted_process(process),
+ m_scripted_thread_interface_sp(interface_sp),
+ m_script_object_sp(script_object_sp) {}
+
ScriptedThread::~ScriptedThread() { DestroyThread(); }
const char *ScriptedThread::GetName() {
@@ -137,6 +153,11 @@ bool ScriptedThread::CalculateStopInfo() {
StructuredData::DictionarySP dict_sp = GetInterface()->GetStopReason();
Status error;
+ if (!dict_sp)
+ return GetInterface()->ErrorWithMessage<bool>(
+ LLVM_PRETTY_FUNCTION, "Failed to get scripted thread stop info.", error,
+ LIBLLDB_LOG_THREAD);
+
lldb::StopInfoSP stop_info_sp;
lldb::StopReason stop_reason_type;
@@ -150,12 +171,12 @@ bool ScriptedThread::CalculateStopInfo() {
if (!dict_sp->GetValueForKeyAsDictionary("data", data_dict))
return GetInterface()->ErrorWithMessage<bool>(
LLVM_PRETTY_FUNCTION,
- "Couldn't find value for key 'type' in stop reason dictionary.", error,
+ "Couldn't find value for key 'data' in stop reason dictionary.", error,
LIBLLDB_LOG_THREAD);
switch (stop_reason_type) {
case lldb::eStopReasonNone:
- break;
+ return true;
case lldb::eStopReasonBreakpoint: {
lldb::break_id_t break_id;
data_dict->GetValueForKeyAsInteger("break_id", break_id,
@@ -172,6 +193,13 @@ bool ScriptedThread::CalculateStopInfo() {
stop_info_sp =
StopInfo::CreateStopReasonWithSignal(*this, signal, description.data());
} break;
+ case lldb::eStopReasonException: {
+ llvm::StringRef description;
+ data_dict->GetValueForKeyAsString("desc", description);
+
+ stop_info_sp =
+ StopInfo::CreateStopReasonWithException(*this, description.data());
+ } break;
default:
return GetInterface()->ErrorWithMessage<bool>(
LLVM_PRETTY_FUNCTION,
@@ -181,6 +209,9 @@ bool ScriptedThread::CalculateStopInfo() {
error, LIBLLDB_LOG_THREAD);
}
+ if (!stop_info_sp)
+ return false;
+
SetStopInfo(stop_info_sp);
return true;
}
@@ -190,7 +221,7 @@ void ScriptedThread::RefreshStateAfterStop() {
}
lldb::ScriptedThreadInterfaceSP ScriptedThread::GetInterface() const {
- return m_scripted_process.GetInterface().GetScriptedThreadInterface();
+ return m_scripted_thread_interface_sp;
}
std::shared_ptr<DynamicRegisterInfo> ScriptedThread::GetDynamicRegisterInfo() {
diff --git a/lldb/source/Plugins/Process/scripted/ScriptedThread.h b/lldb/source/Plugins/Process/scripted/ScriptedThread.h
index cdcd543702a4..8d8a7c2a3df9 100644
--- a/lldb/source/Plugins/Process/scripted/ScriptedThread.h
+++ b/lldb/source/Plugins/Process/scripted/ScriptedThread.h
@@ -25,11 +25,18 @@ class ScriptedProcess;
namespace lldb_private {
class ScriptedThread : public lldb_private::Thread {
+
public:
- ScriptedThread(ScriptedProcess &process, Status &error);
+ ScriptedThread(ScriptedProcess &process,
+ lldb::ScriptedThreadInterfaceSP interface_sp, lldb::tid_t tid,
+ StructuredData::GenericSP script_object_sp = nullptr);
~ScriptedThread() override;
+ static llvm::Expected<std::shared_ptr<ScriptedThread>>
+ Create(ScriptedProcess &process,
+ StructuredData::Generic *script_object = nullptr);
+
lldb::RegisterContextSP GetRegisterContext() override;
lldb::RegisterContextSP
@@ -59,8 +66,9 @@ private:
std::shared_ptr<DynamicRegisterInfo> GetDynamicRegisterInfo();
const ScriptedProcess &m_scripted_process;
+ lldb::ScriptedThreadInterfaceSP m_scripted_thread_interface_sp = nullptr;
+ lldb_private::StructuredData::GenericSP m_script_object_sp = nullptr;
std::shared_ptr<DynamicRegisterInfo> m_register_info_sp = nullptr;
- lldb_private::StructuredData::ObjectSP m_script_object_sp = nullptr;
};
} // namespace lldb_private