33#include "llvm/ADT/ScopeExit.h"
34#include "llvm/Support/Errno.h"
35#include "llvm/Support/Error.h"
36#include "llvm/Support/FileSystem.h"
37#include "llvm/Support/Threading.h"
46#include <linux/unistd.h>
47#include <sys/ptrace.h>
48#include <sys/socket.h>
49#include <sys/syscall.h>
66#define HWCAP2_MTE (1 << 18)
70#define PTRACE_SETREGS 13
73#ifndef PTRACE_SETFPREGS
74#define PTRACE_SETFPREGS 15
77#ifndef PTRACE_GETREGSET
78#define PTRACE_GETREGSET 0x4204
81#ifndef PTRACE_SETREGSET
82#define PTRACE_SETREGSET 0x4205
100 static bool is_supported;
101 static llvm::once_flag flag;
103 llvm::call_once(flag, [] {
106 uint32_t source = 0x47424742;
109 struct iovec local, remote;
110 remote.iov_base = &source;
111 local.iov_base = &dest;
112 remote.iov_len = local.iov_len =
sizeof source;
117 is_supported = (res ==
sizeof(source) && source == dest);
120 "Detected kernel support for process_vm_readv syscall. "
121 "Fast memory reads enabled.");
124 "syscall process_vm_readv failed (error: {0}). Fast memory "
126 llvm::sys::StrError());
138 LLDB_LOG(log,
"setting STDIN to '{0}'", action->GetFileSpec());
140 LLDB_LOG(log,
"leaving STDIN as is");
143 LLDB_LOG(log,
"setting STDOUT to '{0}'", action->GetFileSpec());
145 LLDB_LOG(log,
"leaving STDOUT as is");
148 LLDB_LOG(log,
"setting STDERR to '{0}'", action->GetFileSpec());
150 LLDB_LOG(log,
"leaving STDERR as is");
155 LLDB_LOG(log,
"arg {0}: '{1}'", i, *args);
159 uint8_t *ptr = (uint8_t *)bytes;
160 constexpr uint32_t kDebugPTraceMaxBytes = 20;
161 const uint32_t loop_count = std::min<uint32_t>(kDebugPTraceMaxBytes, count);
162 for (uint32_t i = 0; i < loop_count; i++) {
175 case PTRACE_POKETEXT: {
180 case PTRACE_POKEDATA: {
185 case PTRACE_POKEUSER: {
200 case PTRACE_SETSIGINFO: {
217 "Size of long must be larger than ptrace word size");
224 int status = fcntl(fd, F_GETFL);
230 if (fcntl(fd, F_SETFL, status | flags) == -1) {
240 if (
auto E = ptrace_scope.takeError()) {
242 "error reading value of ptrace_scope: {0}");
246 return original_error;
250 switch (*ptrace_scope) {
253 llvm::consumeError(std::move(original_error));
254 return llvm::createStringError(
255 std::error_code(errno, std::generic_category()),
256 "The current value of ptrace_scope is %d, which can cause ptrace to "
257 "fail to attach to a running process. To fix this, run:\n"
258 "\tsudo sysctl -w kernel.yama.ptrace_scope=0\n"
259 "For more information, see: "
260 "https://www.kernel.org/doc/Documentation/security/Yama.txt.",
263 llvm::consumeError(std::move(original_error));
264 return llvm::createStringError(
265 std::error_code(errno, std::generic_category()),
266 "The current value of ptrace_scope is 3, which will cause ptrace to "
267 "fail to attach to a running process. This value cannot be changed "
268 "without rebooting.\n"
269 "For more information, see: "
270 "https://www.kernel.org/doc/Documentation/security/Yama.txt.");
273 return original_error;
285llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
298 LLDB_LOG(log,
"failed to launch process: {0}", status);
304 ::pid_t wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &wstatus, 0);
307 if (!WIFSTOPPED(wstatus)) {
308 LLDB_LOG(log,
"Could not sync with inferior process: wstatus={0}",
310 return llvm::createStringError(
"could not sync with inferior process");
312 LLDB_LOG(log,
"inferior started, now in stopped state");
316 LLDB_LOG(log,
"failed to set default ptrace options: {0}", status);
320 llvm::Expected<ArchSpec> arch_or =
323 return arch_or.takeError();
327 *arch_or, *
this, {pid}));
330llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
338 return tids_or.takeError();
339 ArrayRef<::pid_t> tids = *tids_or;
340 llvm::Expected<ArchSpec> arch_or =
343 return arch_or.takeError();
345 return std::unique_ptr<NativeProcessLinux>(
365static std::optional<std::pair<lldb::pid_t, WaitStatus>>
WaitPid() {
369 ::pid_t wait_pid = llvm::sys::RetryAfterSignal(
370 -1, ::waitpid, -1, &status, __WALL | __WNOTHREAD | WNOHANG);
375 if (wait_pid == -1) {
383 LLDB_LOG(log,
"waitpid(-1, &status, _) = {0}, status = {1}", wait_pid,
385 return std::make_pair(wait_pid, wait_status);
417 LLDB_LOG(log,
"Ignoring waitpid event {0} for pid {1}", status, pid);
432 "received clone event for tid {0}. tid not tracked yet, "
433 "waiting for it to appear...",
436 llvm::sys::RetryAfterSignal(-1, ::waitpid, tid, &status, __WALL);
443 "waitpid({0}, &status, __WALL) => {1} (errno: {2}, status = {3})",
452 llvm::ArrayRef<::pid_t> tids)
461 for (
const auto &tid : tids) {
479 for (Host::TidMap::iterator it = tids_to_attach.begin();
480 it != tids_to_attach.end();) {
481 if (it->second ==
false) {
490 it = tids_to_attach.erase(it);
502 llvm::sys::RetryAfterSignal(-1, ::waitpid, tid,
nullptr, __WALL);
508 if (errno == ESRCH) {
509 it = tids_to_attach.erase(it);
512 return llvm::errorCodeToError(
513 std::error_code(errno, std::generic_category()));
519 LLDB_LOG(log,
"adding tid = {0}", tid);
528 size_t tid_count = tids_to_attach.size();
530 return llvm::createStringError(
"no such process");
532 std::vector<::pid_t> tids;
533 tids.reserve(tid_count);
534 for (
const auto &p : tids_to_attach)
535 tids.push_back(p.first);
536 return std::move(tids);
540 long ptrace_opts = 0;
544 ptrace_opts |= PTRACE_O_TRACEEXIT;
547 ptrace_opts |= PTRACE_O_TRACECLONE;
551 ptrace_opts |= PTRACE_O_TRACEEXEC;
554 ptrace_opts |= PTRACE_O_TRACEFORK;
557 ptrace_opts |= PTRACE_O_TRACEVFORK;
561 ptrace_opts |= PTRACE_O_TRACEVFORKDONE;
563 return PtraceWrapper(PTRACE_SETOPTIONS, pid,
nullptr, (
void *)ptrace_opts);
568 if (pid ==
GetID() &&
587 const bool is_main_thread = (thread.GetID() ==
GetID());
592 "got exit status({0}) , tid = {1} ({2} main thread), process "
594 status, thread.GetID(), is_main_thread ?
"is" :
"is not",
600 assert(!is_main_thread &&
"Main thread exits handled elsewhere");
608 if (info_err.Success()) {
615 if (info_err.GetError() == EINVAL) {
626 "received a group stop for pid {0} tid {1}. Transparent "
627 "handling of group stops not supported, resuming the "
629 GetID(), thread.GetID());
641 "GetSignalInfo({0}) failed: {1}, status = {2}, main_thread = "
642 "{3}. Expecting WIFEXITED soon.",
643 thread.GetID(), info_err, status, is_main_thread);
651 const bool is_main_thread = (thread.GetID() ==
GetID());
653 assert(info.si_signo ==
SIGTRAP &&
"Unexpected child signal!");
655 switch (info.si_code) {
656 case (
SIGTRAP | (PTRACE_EVENT_FORK << 8)):
657 case (
SIGTRAP | (PTRACE_EVENT_VFORK << 8)):
658 case (
SIGTRAP | (PTRACE_EVENT_CLONE << 8)): {
664 unsigned long event_message = 0;
667 "pid {0} received clone() event but GetEventMessage failed "
668 "so we don't know the new pid/tid",
678 case (
SIGTRAP | (PTRACE_EVENT_EXEC << 8)): {
679 LLDB_LOG(log,
"received exec event, code = {0}", info.si_code ^
SIGTRAP);
686 LLDB_LOG(log,
"exec received, stop tracking all but main thread");
688 llvm::erase_if(
m_threads, [&](std::unique_ptr<NativeThreadProtocol> &t) {
689 return t->GetID() !=
GetID();
695 main_thread->SetStoppedByExec();
709 case (
SIGTRAP | (PTRACE_EVENT_EXIT << 8)): {
715 unsigned long data = 0;
720 "received PTRACE_EVENT_EXIT, data = {0:x}, WIFEXITED={1}, "
721 "WIFSIGNALED={2}, pid = {3}, main_thread = {4}",
722 data, WIFEXITED(data), WIFSIGNALED(data), thread.GetID(),
737 if (is_main_thread) {
747 case (
SIGTRAP | (PTRACE_EVENT_VFORK_DONE << 8)): {
749 thread.SetStoppedByVForkDone();
763 Status error = thread.GetRegisterContext().GetWatchpointHitIndex(
764 wp_index, (uintptr_t)info.si_addr);
767 "received error while checking for watchpoint hits, pid = "
769 thread.GetID(),
error);
777 error = thread.GetRegisterContext().GetHardwareBreakHitIndex(
778 bp_index, (uintptr_t)info.si_addr);
780 LLDB_LOG(log,
"received error while checking for hardware "
781 "breakpoint hits, pid = {0}, error = {1}",
782 thread.GetID(),
error);
802 "received unknown SIGTRAP stop event ({0}, pid {1} tid {2}, resuming",
803 info.si_code,
GetID(), thread.GetID());
810 LLDB_LOG(log,
"received unknown SIGTRAP stop event ({0}, pid {1} tid {2}",
811 info.si_code,
GetID(), thread.GetID());
819 LLDB_LOG(log,
"received trace event, pid = {0}", thread.GetID());
822 thread.SetStoppedByTrace();
829 LLDB_LOG(log,
"received breakpoint event, pid = {0}", thread.GetID());
832 thread.SetStoppedByBreakpoint();
836 auto stepping_with_bp_it =
839 llvm::is_contained(stepping_with_bp_it->second, reg_ctx.
GetPC()))
840 thread.SetStoppedByTrace();
848 LLDB_LOG(log,
"received watchpoint event, pid = {0}, wp_index = {1}",
849 thread.GetID(), wp_index);
853 thread.SetStoppedByWatchpoint(wp_index);
862 const int signo = info.si_signo;
863 const bool is_from_llgs = info.si_pid == getpid();
878 "received signal {0} ({1}) with code {2}, (siginfo pid = {3}, "
879 "waitpid pid = {4})",
884 if (is_from_llgs && (info.si_code == SI_TKILL) && (signo ==
SIGSTOP)) {
886 LLDB_LOG(log,
"pid {0} tid {1}, thread stopped",
GetID(), thread.GetID());
895 const StateType thread_state = thread.GetState();
906 thread.SetStoppedBySignal(
SIGSTOP, &info);
908 thread.SetStoppedWithNoReason();
917 LLDB_LOG(log,
"failed to resume thread {0}: {1}", thread.GetID(),
922 "pid {0} tid {1}, thread was already marked as a stopped "
923 "state (state={2}), leaving stop signal as is",
924 GetID(), thread.GetID(), thread_state);
941 thread.SetStoppedBySignal(signo, &info);
950 LLDB_LOG(log,
"parent_tid={0}, child_pid={1}, event={2}", parent.
GetID(),
956 case PTRACE_EVENT_CLONE: {
962 if (tgid_ret != child_pid) {
964 assert(!tgid_ret || *tgid_ret ==
GetID());
975 case PTRACE_EVENT_FORK:
976 case PTRACE_EVENT_VFORK: {
977 bool is_vfork =
event == PTRACE_EVENT_VFORK;
986 m_delegate.NewSubprocess(
this, std::move(child_process));
991 child_process->Detach();
997 llvm_unreachable(
"unknown clone_info.event");
1004 if (
m_arch.GetMachine() == llvm::Triple::arm ||
1005 m_arch.GetTriple().isRISCV() ||
m_arch.GetTriple().isLoongArch())
1018 if (software_single_step) {
1020 assert(thread &&
"thread list should not contain NULL threads");
1024 if (action ==
nullptr)
1037 assert(thread &&
"thread list should not contain NULL threads");
1042 if (action ==
nullptr) {
1043 LLDB_LOG(log,
"no action specified for pid {0} tid {1}",
GetID(),
1048 LLDB_LOG(log,
"processing resume action state {0} for pid {1} tid {2}",
1051 switch (action->
state) {
1055 const int signo = action->
signal;
1057 action->
state, signo);
1060 "NativeProcessLinux::%s: failed to resume thread "
1061 "for pid %" PRIu64
", tid %" PRIu64
", error = %s",
1062 __FUNCTION__,
GetID(), thread->GetID(),
error.AsCString());
1073 "NativeProcessLinux::%s (): unexpected state %s specified "
1074 "for pid %" PRIu64
", tid %" PRIu64,
1101 kill(
GetID(), SIGCONT);
1119 LLDB_LOG(log,
"sending signal {0} ({1}) to pid {2}", signo,
1122 if (kill(
GetID(), signo))
1136 LLDB_LOG(log,
"selecting running thread for interrupt target");
1140 const auto thread_state = thread->GetState();
1142 running_thread = thread.get();
1147 stopped_thread = thread.get();
1151 if (!running_thread && !stopped_thread) {
1152 Status error(
"found no running/stepping or live stopped threads as target "
1160 running_thread ? running_thread : stopped_thread;
1162 LLDB_LOG(log,
"pid {0} {1} tid {2} chosen for interrupt target",
GetID(),
1163 running_thread ?
"running" :
"stopped",
1164 deferred_signal_thread->
GetID());
1184 LLDB_LOG(log,
"ignored for PID {0} due to current state: {1}",
GetID(),
1238 "descending /proc/pid/maps entries detected, unexpected");
1256 range_info = proc_entry_info;
1282 LLDB_LOG(log,
"reusing {0} cached memory region entries",
1290 FileSpec file_spec(Info->GetName().GetCString());
1298 LLDB_LOG(log,
"failed to parse proc maps: {0}", Result);
1309 if (!BufferOrError) {
1311 return BufferOrError.getError();
1326 "failed to find any procfs maps entries, assuming no support "
1327 "for memory region metadata retrieval");
1331 LLDB_LOG(log,
"read {0} memory region entries from /proc/{1}/maps",
1339llvm::Expected<uint64_t>
1347 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1348 "No executable memory region found!");
1350 addr_t exe_addr = region_it->first.GetRange().GetRangeBase();
1361 return std::move(Err);
1362 llvm::scope_exit restore_regs(
1370 llvm::scope_exit restore_siginfo([&] {
1372 PtraceWrapper(PTRACE_SETSIGINFO, thread.GetID(),
nullptr, &siginfo);
1375 llvm::SmallVector<uint8_t, 8> memory(syscall_data.
Insn.size());
1377 if (llvm::Error Err =
1378 ReadMemory(exe_addr, memory.data(), memory.size(), bytes_read)
1380 return std::move(Err);
1383 llvm::scope_exit restore_mem([&] {
1384 DoWriteMemory(exe_addr, memory.data(), memory.size(), bytes_read);
1387 if (llvm::Error Err = reg_ctx.
SetPC(exe_addr).
ToError())
1388 return std::move(Err);
1390 for (
const auto &zip : llvm::zip_first(args, syscall_data.
Args)) {
1391 if (llvm::Error Err =
1393 .WriteRegisterFromUnsigned(std::get<1>(zip), std::get<0>(zip))
1395 return std::move(Err);
1399 syscall_data.
Insn.size(), bytes_read)
1401 return std::move(Err);
1408 if (llvm::Error Err =
1410 return std::move(Err);
1413 ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, ::waitpid, thread.GetID(),
1415 if (wait_pid == -1) {
1416 return llvm::errorCodeToError(
1417 std::error_code(errno, std::generic_category()));
1419 assert((
unsigned)wait_pid == thread.GetID());
1424 uint64_t errno_threshold =
1425 (uint64_t(-1) >> (64 - 8 *
m_arch.GetAddressByteSize())) - 0x1000;
1426 if (result > errno_threshold) {
1427 return llvm::errorCodeToError(
1428 std::error_code(-result & 0xfff, std::generic_category()));
1434llvm::Expected<addr_t>
1437 std::optional<NativeRegisterContextLinux::MmapData> mmap_data =
1440 return llvm::make_error<UnimplementedError>();
1443 assert((permissions & (ePermissionsReadable | ePermissionsWritable |
1444 ePermissionsExecutable)) == permissions &&
1445 "Unknown permission!");
1446 if (permissions & ePermissionsReadable)
1448 if (permissions & ePermissionsWritable)
1450 if (permissions & ePermissionsExecutable)
1453 llvm::Expected<uint64_t> Result =
1462 std::optional<NativeRegisterContextLinux::MmapData> mmap_data =
1465 return llvm::make_error<UnimplementedError>();
1469 return llvm::createStringError(llvm::errc::invalid_argument,
1470 "Memory not allocated by the debugger.");
1472 llvm::Expected<uint64_t> Result =
1473 Syscall({mmap_data->SysMunmap, addr, it->second});
1475 return Result.takeError();
1478 return llvm::Error::success();
1483 std::vector<uint8_t> &tags) {
1484 llvm::Expected<NativeRegisterContextLinux::MemoryTaggingDetails> details =
1498 range = details->manager->ExpandToGranule(range);
1501 size_t num_tags = range.
GetByteSize() / details->manager->GetGranuleSize();
1502 tags.resize(num_tags * details->manager->GetTagSizeInBytes());
1504 struct iovec tags_iovec;
1505 uint8_t *dest = tags.data();
1511 tags_iovec.iov_base = dest;
1512 tags_iovec.iov_len = num_tags;
1516 reinterpret_cast<void *
>(read_addr),
static_cast<void *
>(&tags_iovec),
1525 size_t tags_read = tags_iovec.iov_len;
1526 assert(tags_read && (tags_read <= num_tags));
1528 dest += tags_read * details->manager->GetTagSizeInBytes();
1529 read_addr += details->manager->GetGranuleSize() * tags_read;
1530 num_tags -= tags_read;
1538 const std::vector<uint8_t> &tags) {
1539 llvm::Expected<NativeRegisterContextLinux::MemoryTaggingDetails> details =
1553 range = details->manager->ExpandToGranule(range);
1556 llvm::Expected<std::vector<lldb::addr_t>> unpacked_tags_or_err =
1557 details->manager->UnpackTagsData(tags);
1558 if (!unpacked_tags_or_err)
1561 llvm::Expected<std::vector<lldb::addr_t>> repeated_tags_or_err =
1562 details->manager->RepeatTagsForRange(*unpacked_tags_or_err, range);
1563 if (!repeated_tags_or_err)
1567 llvm::Expected<std::vector<uint8_t>> final_tag_data =
1568 details->manager->PackTags(*repeated_tags_or_err);
1569 if (!final_tag_data)
1572 struct iovec tags_vec;
1573 uint8_t *src = final_tag_data->data();
1576 size_t num_tags = repeated_tags_or_err->size();
1580 while (num_tags > 0) {
1581 tags_vec.iov_base = src;
1582 tags_vec.iov_len = num_tags;
1586 reinterpret_cast<void *
>(write_addr),
static_cast<void *
>(&tags_vec), 0,
1595 size_t tags_written = tags_vec.iov_len;
1596 assert(tags_written && (tags_written <= num_tags));
1598 src += tags_written * details->manager->GetTagSizeInBytes();
1599 write_addr += details->manager->GetGranuleSize() * tags_written;
1600 num_tags -= tags_written;
1628llvm::Expected<llvm::ArrayRef<uint8_t>>
1632 static const uint8_t g_arm_opcode[] = {0xf0, 0x01, 0xf0, 0xe7};
1633 static const uint8_t g_thumb_opcode[] = {0x01, 0xde};
1636 case llvm::Triple::arm:
1637 switch (size_hint) {
1639 return llvm::ArrayRef(g_thumb_opcode);
1641 return llvm::ArrayRef(g_arm_opcode);
1643 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1644 "Unrecognised trap opcode size hint!");
1652 void *buf,
size_t size,
1653 size_t &bytes_read) {
1656 LLDB_LOG(log,
"addr = {0}, buf = {1}, size = {2}", addr, buf, size);
1663 struct iovec local_iov, remote_iov;
1664 local_iov.iov_base = buf;
1665 local_iov.iov_len = size;
1666 remote_iov.iov_base =
reinterpret_cast<void *
>(addr);
1667 remote_iov.iov_len = size;
1672 if (read_result < 0)
1675 bytes_read = read_result;
1678 "process_vm_readv({0}, [iovec({1}, {2})], [iovec({3:x}, {2})], 1, "
1681 error > 0 ? llvm::sys::StrError(errno) :
"sucesss");
1684 unsigned char *dst =
static_cast<unsigned char *
>(buf);
1688 for (; bytes_read < size; bytes_read += remainder) {
1691 reinterpret_cast<void *
>(addr + bytes_read),
nullptr, 0, &data);
1695 remainder = size - bytes_read;
1699 memcpy(dst + bytes_read, &data, remainder);
1705 size_t size,
size_t &bytes_written) {
1706 const unsigned char *src =
static_cast<const unsigned char *
>(buf);
1711 LLDB_LOG(log,
"addr = {0}, buf = {1}, size = {2}", addr, buf, size);
1713 for (bytes_written = 0; bytes_written < size; bytes_written += remainder) {
1714 remainder = size - bytes_written;
1718 unsigned long data = 0;
1721 LLDB_LOG(log,
"[{0:x}]:{1:x}", addr, data);
1727 unsigned char buff[8];
1733 memcpy(buff, src, remainder);
1735 size_t bytes_written_rec;
1740 LLDB_LOG(log,
"[{0:x}]:{1:x} ({2:x})", addr, *(
const unsigned long *)src,
1741 *(
unsigned long *)buff);
1751 return PtraceWrapper(PTRACE_GETSIGINFO, tid,
nullptr, siginfo);
1755 unsigned long *message) {
1756 return PtraceWrapper(PTRACE_GETEVENTMSG, tid,
nullptr, message);
1768 assert(thread &&
"thread list should not contain NULL threads");
1769 if (thread->GetID() == thread_id) {
1782 LLDB_LOG(log,
"tid: {0}", thread_id);
1784 auto it = llvm::find_if(
m_threads, [&](
const auto &thread_up) {
1785 return thread_up.get() == &thread;
1806 LLDB_LOG(log,
"Failed to trace a new thread with intel-pt, tid = {0}. {1}",
1807 tid,
error.AsCString());
1816 "Failed to stop a destroyed thread with intel-pt, tid = {0}. {1}",
1817 tid,
error.AsCString());
1824 LLDB_LOG(log,
"pid {0} adding thread with tid {1}",
GetID(), thread_id);
1827 "attempted to add a thread by id that already exists");
1833 m_threads.push_back(std::make_unique<NativeThreadLinux>(*
this, thread_id));
1838 if (tracing_error.
Fail()) {
1839 thread.SetStoppedByProcessorTrace(tracing_error.
AsCString());
1844 thread.SetStoppedBySignal(
SIGSTOP);
1855 FileSpec module_file_spec(module_path);
1860 if (it.second.GetFilename() == module_file_spec.
GetFilename()) {
1861 file_spec = it.second;
1866 "Module file ({0}) not found in /proc/{1}/maps file!",
1879 if (it.second == file) {
1880 load_addr = it.first.GetRange().GetRangeBase();
1900 LLDB_LOG(log,
"tid: {0}", thread.GetID());
1909 "about to resume tid {0} per explicit request but we have a "
1910 "pending stop notification (tid {1}) that is actively "
1911 "waiting for this thread to stop. Valid sequence of events?",
1919 Status resume_result = thread.Resume(signo);
1922 return resume_result;
1925 Status step_result = thread.SingleStep(signo);
1931 LLDB_LOG(log,
"Unhandled state {0}.", state);
1932 llvm_unreachable(
"Unhandled state for resume");
1940 LLDB_LOG(log,
"about to process event: (triggering_tid: {0})",
1953 LLDB_LOG(log,
"event processing done");
1960 for (
const auto &thread_sp :
m_threads) {
1973 LLDB_LOG(log,
"pid = {0} remove stepping breakpoint: {1}", bp_addr,
1987 LLDB_LOG(log,
"tid: {0}", thread.GetID());
1993 thread.RequestStop();
2000 void *data,
size_t data_size,
2012 *(
unsigned int *)addr, data);
2023 LLDB_LOG(log,
"ptrace({0}, {1}, {2}, {3}, {4})={5:x}", req, pid, addr, data,
2041 if (type ==
"intel-pt") {
2042 if (Expected<TraceIntelPTStartRequest> request =
2043 json::parse<TraceIntelPTStartRequest>(json_request,
2044 "TraceIntelPTStartRequest")) {
2047 return request.takeError();
2054 if (request.
type ==
"intel-pt")
2060 if (type ==
"intel-pt")
2067 if (request.
type ==
"intel-pt")
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
#define LLDB_LOG_ERROR(log, error,...)
#define LLDB_LOG_VERBOSE(log,...)
static std::optional< std::pair< lldb::pid_t, WaitStatus > > WaitPid()
static constexpr unsigned k_ptrace_word_size
static Status EnsureFDFlags(int fd, int flags)
static void MaybeLogLaunchInfo(const ProcessLaunchInfo &info)
static void PtraceDisplayBytes(int &req, void *data, size_t data_size)
static Status EnsureFDFlags(int fd, int flags)
static llvm::Error AddPtraceScopeNote(llvm::Error original_error)
static void DisplayBytes(StreamString &s, void *bytes, uint32_t count)
static bool ProcessVmReadvSupported()
ssize_t process_vm_readv(::pid_t pid, const struct iovec *local_iov, unsigned long liovcnt, const struct iovec *remote_iov, unsigned long riovcnt, unsigned long flags)
An architecture specification class.
const char ** GetConstArgumentVector() const
Gets the argument vector.
Represents a file descriptor action to be performed during process launch.
llvm::StringRef GetFilename() const
Filename string const get accessor.
void Clear()
Clears the object state.
static FileSystem & Instance()
void Resolve(llvm::SmallVectorImpl< char > &path, bool force_make_absolute=false)
Resolve path to make it canonical.
lldb::pid_t GetProcessId() const
static bool FindProcessThreads(const lldb::pid_t pid, TidMap &tids_to_attach)
std::map< lldb::pid_t, bool > TidMap
static const char * GetSignalAsCString(int signo)
SignalHandleUP RegisterSignal(int signo, const Callback &callback, Status &error)
void SetReadable(LazyBool val)
void SetMapped(LazyBool val)
void SetExecutable(LazyBool val)
void SetWritable(LazyBool val)
Range< lldb::addr_t, lldb::addr_t > TagRange
Abstract class that extends NativeProcessProtocol with ELF specific logic.
std::vector< std::pair< MemoryRegionInfo, FileSpec > > m_mem_region_cache
NativeProcessProtocol(lldb::pid_t pid, int terminal_fd, NativeDelegate &delegate)
void NotifyDidExec() override
Notify the delegate that an exec occurred.
virtual llvm::Expected< TraceSupportedResponse > TraceSupported()
Get the processor tracing type supported for this process.
virtual llvm::Expected< std::vector< uint8_t > > TraceGetBinaryData(const TraceGetBinaryDataRequest &request)
Get binary data given a trace technology and a data identifier.
lldb::pid_t GetID() const
virtual llvm::Error TraceStop(const TraceStopRequest &request)
Stop tracing a live process or its threads.
Status SetSoftwareBreakpoint(lldb::addr_t addr, uint32_t size_hint)
virtual llvm::Expected< llvm::json::Value > TraceGetState(llvm::StringRef type)
Get the current tracing state of the process and its threads.
lldb::StateType GetState() const
void SetState(lldb::StateType state, bool notify_delegates=true)
NativeThreadProtocol * GetThreadByID(lldb::tid_t tid)
NativeThreadProtocol * GetCurrentThread()
void SetCurrentThreadID(lldb::tid_t tid)
std::vector< std::unique_ptr< NativeThreadProtocol > > m_threads
llvm::DenseSet< int > m_signals_to_ignore
virtual bool SetExitStatus(WaitStatus status, bool bNotifyStateChange)
virtual Status RemoveBreakpoint(lldb::addr_t addr, bool hardware=false)
NativeDelegate & m_delegate
void FixupBreakpointPCAsNeeded(NativeThreadProtocol &thread)
lldb::tid_t GetCurrentThreadID() const
Extension
Extension flag constants, returned by Manager::GetSupportedExtensions() and passed to SetEnabledExten...
virtual Status SetHardwareBreakpoint(lldb::addr_t addr, size_t size)
std::map< lldb::addr_t, SoftwareBreakpoint > m_software_breakpoints
virtual llvm::Expected< llvm::ArrayRef< uint8_t > > GetSoftwareBreakpointTrapOpcode(size_t size_hint)
Extension m_enabled_extensions
virtual llvm::Error TraceStart(llvm::StringRef json_params, llvm::StringRef type)
Start tracing a process or its threads.
virtual Status RemoveHardwareBreakpoint(lldb::addr_t addr)
std::map< lldb::tid_t, std::vector< lldb::addr_t > > m_threads_stepping_with_breakpoint
std::set< lldb::addr_t > m_step_breakpoints
Status SetupSoftwareSingleStepping(NativeThreadProtocol &thread)
lldb::addr_t ReadRegisterAsUnsigned(uint32_t reg, lldb::addr_t fail_value)
virtual Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp)=0
lldb::addr_t GetPC(lldb::addr_t fail_value=LLDB_INVALID_ADDRESS)
virtual Status ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp)=0
Status SetPC(lldb::addr_t pc)
lldb::tid_t GetID() const
An address in a process, qualified by an address space.
lldb::addr_t GetValue() const
const FileAction * GetFileActionForFD(int fd) const
HostProcess LaunchProcess(const ProcessLaunchInfo &launch_info, Status &error) override
int ReleasePrimaryFileDescriptor()
Release the primary file descriptor.
const ResumeAction * GetActionForThread(lldb::tid_t tid, bool default_ok) const
static Status FromErrno()
Set the current error to errno.
Status Clone() const
Don't call this function in new code.
ValueType GetError() const
Access the error value.
llvm::Error ToError() const
FIXME: Replace all uses with takeError() instead.
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
static Status FromErrorString(const char *str)
bool Fail() const
Test for error condition.
const char * AsCString(const char *default_error_str="unknown error") const
Get the error string associated with the current error.
static Status static Status FromErrorStringWithFormatv(const char *format, Args &&...args)
static Status FromError(llvm::Error error)
Avoid using this in new code. Migrate APIs to llvm::Expected instead.
bool Success() const
Test for success condition.
const char * GetData() const
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
static bool IsSupported()
Manager(MainLoop &mainloop)
llvm::Expected< std::unique_ptr< NativeProcessProtocol > > Attach(lldb::pid_t pid, NativeDelegate &native_delegate) override
Attach to an existing process.
llvm::DenseSet<::pid_t > m_unowned_threads
MainLoop::SignalHandleUP m_sigchld_handle
llvm::SmallPtrSet< NativeProcessLinux *, 2 > m_processes
void AddProcess(NativeProcessLinux &process)
Extension GetSupportedExtensions() const override
Get the bitmask of extensions supported by this process plugin.
void CollectThread(::pid_t tid)
llvm::Expected< std::unique_ptr< NativeProcessProtocol > > Launch(ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate) override
Launch a process for debugging.
void MonitorBreakpoint(NativeThreadLinux &thread)
llvm::Expected< lldb::addr_t > AllocateMemory(size_t size, uint32_t permissions) override
llvm::Expected< std::vector< uint8_t > > TraceGetBinaryData(const TraceGetBinaryDataRequest &request) override
Get binary data given a trace technology and a data identifier.
NativeThreadLinux * GetThreadByID(lldb::tid_t id)
llvm::Error DeallocateMemory(lldb::addr_t addr) override
Status GetFileLoadAddress(const llvm::StringRef &file_name, lldb::addr_t &load_addr) override
Status NotifyTracersOfNewThread(lldb::tid_t tid)
Start tracing a new thread if process tracing is enabled.
const ArchSpec & GetArchitecture() const override
Status GetEventMessage(lldb::tid_t tid, unsigned long *message)
Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG) corresponding to the given thread ID...
Status DoWriteMemory(lldb::addr_t addr, const void *buf, size_t size, size_t &bytes_written) override
IntelPTCollector m_intel_pt_collector
Manages Intel PT process and thread traces.
llvm::Error TraceStart(llvm::StringRef json_request, llvm::StringRef type) override
Tracing These methods implement the jLLDBTrace packets.
lldb::tid_t m_pending_notification_tid
bool MonitorClone(NativeThreadLinux &parent, lldb::pid_t child_pid, int event)
void SignalIfAllThreadsStopped()
llvm::DenseMap< lldb::addr_t, lldb::addr_t > m_allocated_memory
Inferior memory (allocated by us) and its size.
Status Interrupt() override
Tells a process to interrupt all operations as if by a Ctrl-C.
void ThreadWasCreated(NativeThreadLinux &thread)
bool HasThreadNoLock(lldb::tid_t thread_id)
llvm::Expected< llvm::ArrayRef< uint8_t > > GetSoftwareBreakpointTrapOpcode(size_t size_hint) override
void NotifyTracersProcessWillResume() override
Notify tracers that the target process will resume.
void MonitorSIGTRAP(const siginfo_t &info, NativeThreadLinux &thread)
Status SetBreakpoint(lldb::addr_t addr, uint32_t size, bool hardware) override
llvm::Expected< TraceSupportedResponse > TraceSupported() override
Get the processor tracing type supported for this process.
void MonitorWatchpoint(NativeThreadLinux &thread, uint32_t wp_index)
bool TryHandleWaitStatus(lldb::pid_t pid, WaitStatus status)
llvm::Error TraceStop(const TraceStopRequest &request) override
Stop tracing a live process or its threads.
Status Resume(const ResumeActionList &resume_actions) override
llvm::Expected< llvm::json::Value > TraceGetState(llvm::StringRef type) override
Get the current tracing state of the process and its threads.
Status RemoveBreakpoint(lldb::addr_t addr, bool hardware=false) override
bool SupportHardwareSingleStepping() const
void StopTrackingThread(NativeThreadLinux &thread)
NativeProcessLinux(::pid_t pid, int terminal_fd, NativeDelegate &delegate, const ArchSpec &arch, Manager &manager, llvm::ArrayRef<::pid_t > tids)
Status ReadMemory(const ProcessAddress &addr, void *buf, size_t size, size_t &bytes_read) override
Plugins without address spaces should error on a non-default one.
Status NotifyTracersOfThreadDestroyed(lldb::tid_t tid)
Stop tracing threads upon a destroy event.
Status PopulateMemoryRegionCache()
void NotifyTracersProcessDidStop() override
Notify tracers that the target process just stopped.
static Status SetDefaultPtraceOpts(const lldb::pid_t)
void MonitorSignal(const siginfo_t &info, NativeThreadLinux &thread)
Status GetSignalInfo(lldb::tid_t tid, void *siginfo) const
Writes a siginfo_t structure corresponding to the given thread ID to the memory region pointed to by ...
Status WriteMemoryTags(int32_t type, lldb::addr_t addr, size_t len, const std::vector< uint8_t > &tags) override
size_t UpdateThreads() override
LazyBool m_supports_mem_region
Status ReadMemoryTags(int32_t type, lldb::addr_t addr, size_t len, std::vector< uint8_t > &tags) override
NativeThreadLinux * GetCurrentThread()
void MonitorTrace(NativeThreadLinux &thread)
void StopRunningThreads(lldb::tid_t triggering_tid)
Status ResumeThread(NativeThreadLinux &thread, lldb::StateType state, int signo)
Status GetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo &range_info) override
NativeThreadLinux & AddThread(lldb::tid_t thread_id, bool resume)
Create a new thread.
static llvm::Expected< std::vector<::pid_t > > Attach(::pid_t pid)
llvm::Expected< uint64_t > Syscall(llvm::ArrayRef< uint64_t > args)
Status Signal(int signo) override
Sends a process a UNIX signal signal.
Status GetLoadedModuleFileSpec(const char *module_path, FileSpec &file_spec) override
void MonitorCallback(NativeThreadLinux &thread, WaitStatus status)
static Status PtraceWrapper(int req, lldb::pid_t pid, void *addr=nullptr, void *data=nullptr, size_t data_size=0, long *result=nullptr)
}
virtual llvm::Expected< MemoryTaggingDetails > GetMemoryTaggingDetails(int32_t type)
Return architecture specific data needed to use memory tags, if they are supported.
virtual std::optional< MmapData > GetMmapData()
Return the architecture-specific data needed to make mmap syscalls, if they are supported.
static llvm::Expected< ArchSpec > DetermineArchitecture(lldb::tid_t tid)
virtual std::optional< SyscallData > GetSyscallData()
Return architecture-specific data needed to make inferior syscalls, if they are supported.
lldb::StateType GetState() override
NativeRegisterContextLinux & GetRegisterContext() override
void SetStoppedByFork(bool is_vfork, lldb::pid_t child_pid)
#define LLDB_INVALID_SIGNAL_NUMBER
#define LLDB_INVALID_THREAD_ID
#define LLDB_INVALID_INDEX32
#define UNUSED_IF_ASSERT_DISABLED(x)
#define LLDB_INVALID_ADDRESS
#define LLDB_INVALID_PROCESS_ID
llvm::Expected< int > GetPtraceScope()
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
std::optional< lldb::pid_t > getPIDForTID(lldb::pid_t tid)
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getProcFile(::pid_t pid, ::pid_t tid, const llvm::Twine &file)
bool StateIsStoppedState(lldb::StateType state, bool must_exist)
Check if a state represents a state where the process or thread is stopped.
bool StateIsRunningState(lldb::StateType state)
Check if a state represents a state where the process or thread is running.
const char * StateAsCString(lldb::StateType state)
Converts a StateType to a C string.
std::function< bool(llvm::Expected< MemoryRegionInfo >)> LinuxMapCallback
void ParseLinuxMapRegions(llvm::StringRef linux_map, LinuxMapCallback const &callback)
void ParseLinuxSMapRegions(llvm::StringRef linux_smap, LinuxMapCallback const &callback)
StateType
Process and Thread States.
@ eStateUnloaded
Process is object is valid, but not currently loaded.
@ eStateConnected
Process is connected to remote debug services, but not launched or attached to anything yet.
@ eStateDetached
Process has been detached and can't be examined.
@ eStateStopped
Process or thread is stopped and can be examined.
@ eStateSuspended
Process or thread is in a suspended state as far as the debugger is concerned while other processes o...
@ eStateRunning
Process or thread is running and can't be examined.
@ eStateLaunching
Process is in the process of launching.
@ eStateAttaching
Process is currently trying to attach.
@ eStateExited
Process has exited and can't be examined.
@ eStateStepping
Process or thread is in the process of stepping and can not be examined.
@ eStateCrashed
Process or thread has crashed and can be examined.
@ eErrorTypePOSIX
POSIX error codes.
std::shared_ptr< lldb_private::WritableDataBuffer > WritableDataBufferSP
bool Contains(BaseType r) const
BaseType GetRangeBase() const
void SetRangeEnd(BaseType end)
SizeType GetByteSize() const
void SetRangeBase(BaseType b)
Set the start value for the range, and keep the same size.
void SetByteSize(SizeType s)
jLLDBTraceGetBinaryData gdb-remote packet
std::string type
Tracing technology name, e.g. intel-pt, arm-coresight.
jLLDBTraceStop gdb-remote packet
std::string type
Tracing technology name, e.g. intel-pt, arm-coresight.
jLLDBTraceSupported gdb-remote packet
static WaitStatus Decode(int wstatus)
llvm::ArrayRef< uint8_t > Insn
The syscall instruction.
uint32_t Result
Register containing the syscall result.
llvm::ArrayRef< uint32_t > Args
Registers used for syscall arguments.