21#include <unordered_map>
46#include "llvm/ADT/ScopeExit.h"
47#include "llvm/Support/Errno.h"
48#include "llvm/Support/Error.h"
49#include "llvm/Support/FileSystem.h"
50#include "llvm/Support/Threading.h"
52#include <linux/unistd.h>
53#include <sys/socket.h>
54#include <sys/syscall.h>
70#define HWCAP2_MTE (1 << 18)
81 static bool is_supported;
82 static llvm::once_flag flag;
84 llvm::call_once(flag, [] {
87 uint32_t source = 0x47424742;
90 struct iovec local, remote;
91 remote.iov_base = &source;
92 local.iov_base = &dest;
93 remote.iov_len = local.iov_len =
sizeof source;
98 is_supported = (res ==
sizeof(source) && source == dest);
101 "Detected kernel support for process_vm_readv syscall. "
102 "Fast memory reads enabled.");
105 "syscall process_vm_readv failed (error: {0}). Fast memory "
107 llvm::sys::StrError());
119 LLDB_LOG(log,
"setting STDIN to '{0}'", action->GetFileSpec());
121 LLDB_LOG(log,
"leaving STDIN as is");
124 LLDB_LOG(log,
"setting STDOUT to '{0}'", action->GetFileSpec());
126 LLDB_LOG(log,
"leaving STDOUT as is");
129 LLDB_LOG(log,
"setting STDERR to '{0}'", action->GetFileSpec());
131 LLDB_LOG(log,
"leaving STDERR as is");
136 LLDB_LOG(log,
"arg {0}: '{1}'", i, *args);
140 uint8_t *ptr = (uint8_t *)bytes;
142 for (uint32_t i = 0; i < loop_count; i++) {
155 case PTRACE_POKETEXT: {
160 case PTRACE_POKEDATA: {
165 case PTRACE_POKEUSER: {
180 case PTRACE_SETSIGINFO: {
197 "Size of long must be larger than ptrace word size");
204 int status = fcntl(fd, F_GETFL);
210 if (fcntl(fd, F_SETFL, status | flags) == -1) {
220 if (
auto E = ptrace_scope.takeError()) {
222 "error reading value of ptrace_scope: {0}");
226 return original_error;
230 switch (*ptrace_scope) {
233 llvm::consumeError(std::move(original_error));
234 return llvm::createStringError(
235 std::error_code(errno, std::generic_category()),
236 "The current value of ptrace_scope is %d, which can cause ptrace to "
237 "fail to attach to a running process. To fix this, run:\n"
238 "\tsudo sysctl -w kernel.yama.ptrace_scope=0\n"
239 "For more information, see: "
240 "https://www.kernel.org/doc/Documentation/security/Yama.txt.",
243 llvm::consumeError(std::move(original_error));
244 return llvm::createStringError(
245 std::error_code(errno, std::generic_category()),
246 "The current value of ptrace_scope is 3, which will cause ptrace to "
247 "fail to attach to a running process. This value cannot be changed "
248 "without rebooting.\n"
249 "For more information, see: "
250 "https://www.kernel.org/doc/Documentation/security/Yama.txt.");
253 return original_error;
265llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
278 LLDB_LOG(log,
"failed to launch process: {0}", status);
284 ::pid_t wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &wstatus, 0);
287 if (!WIFSTOPPED(wstatus)) {
288 LLDB_LOG(log,
"Could not sync with inferior process: wstatus={1}",
290 return llvm::make_error<StringError>(
"Could not sync with inferior process",
291 llvm::inconvertibleErrorCode());
293 LLDB_LOG(log,
"inferior started, now in stopped state");
297 LLDB_LOG(log,
"failed to set default ptrace options: {0}", status);
301 llvm::Expected<ArchSpec> arch_or =
304 return arch_or.takeError();
308 *arch_or, *
this, {pid}));
311llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
319 return tids_or.takeError();
320 ArrayRef<::pid_t> tids = *tids_or;
321 llvm::Expected<ArchSpec> arch_or =
324 return arch_or.takeError();
326 return std::unique_ptr<NativeProcessLinux>(
346static std::optional<std::pair<lldb::pid_t, WaitStatus>>
WaitPid() {
350 ::pid_t wait_pid = llvm::sys::RetryAfterSignal(
351 -1, ::waitpid, -1, &status, __WALL | __WNOTHREAD | WNOHANG);
356 if (wait_pid == -1) {
364 LLDB_LOG(log,
"waitpid(-1, &status, _) = {0}, status = {1}", wait_pid,
366 return std::make_pair(wait_pid, wait_status);
395 LLDB_LOG(log,
"Ignoring waitpid event {0} for pid {1}", status, pid);
410 "received clone event for tid {0}. tid not tracked yet, "
411 "waiting for it to appear...",
414 llvm::sys::RetryAfterSignal(-1, ::waitpid, tid, &status, __WALL);
421 "waitpid({0}, &status, __WALL) => {1} (errno: {2}, status = {3})",
430 llvm::ArrayRef<::pid_t> tids)
439 for (
const auto &tid : tids) {
457 for (Host::TidMap::iterator it = tids_to_attach.begin();
458 it != tids_to_attach.end();) {
459 if (it->second ==
false) {
468 it = tids_to_attach.erase(it);
480 llvm::sys::RetryAfterSignal(-1, ::waitpid, tid,
nullptr, __WALL);
486 if (errno == ESRCH) {
487 it = tids_to_attach.erase(it);
490 return llvm::errorCodeToError(
491 std::error_code(errno, std::generic_category()));
497 LLDB_LOG(log,
"adding tid = {0}", tid);
506 size_t tid_count = tids_to_attach.size();
508 return llvm::make_error<StringError>(
"No such process",
509 llvm::inconvertibleErrorCode());
511 std::vector<::pid_t> tids;
512 tids.reserve(tid_count);
513 for (
const auto &p : tids_to_attach)
514 tids.push_back(p.first);
515 return std::move(tids);
519 long ptrace_opts = 0;
523 ptrace_opts |= PTRACE_O_TRACEEXIT;
526 ptrace_opts |= PTRACE_O_TRACECLONE;
530 ptrace_opts |= PTRACE_O_TRACEEXEC;
533 ptrace_opts |= PTRACE_O_TRACEFORK;
536 ptrace_opts |= PTRACE_O_TRACEVFORK;
540 ptrace_opts |= PTRACE_O_TRACEVFORKDONE;
542 return PtraceWrapper(PTRACE_SETOPTIONS, pid,
nullptr, (
void *)ptrace_opts);
547 if (pid ==
GetID() &&
566 const bool is_main_thread = (thread.GetID() ==
GetID());
571 "got exit status({0}) , tid = {1} ({2} main thread), process "
573 status, thread.GetID(), is_main_thread ?
"is" :
"is not",
579 assert(!is_main_thread &&
"Main thread exits handled elsewhere");
587 if (info_err.Success()) {
594 if (info_err.GetError() == EINVAL) {
605 "received a group stop for pid {0} tid {1}. Transparent "
606 "handling of group stops not supported, resuming the "
608 GetID(), thread.GetID());
620 "GetSignalInfo({0}) failed: {1}, status = {2}, main_thread = "
621 "{3}. Expecting WIFEXITED soon.",
622 thread.GetID(), info_err, status, is_main_thread);
630 const bool is_main_thread = (thread.GetID() ==
GetID());
632 assert(info.si_signo ==
SIGTRAP &&
"Unexpected child signal!");
634 switch (info.si_code) {
635 case (
SIGTRAP | (PTRACE_EVENT_FORK << 8)):
636 case (
SIGTRAP | (PTRACE_EVENT_VFORK << 8)):
637 case (
SIGTRAP | (PTRACE_EVENT_CLONE << 8)): {
643 unsigned long event_message = 0;
646 "pid {0} received clone() event but GetEventMessage failed "
647 "so we don't know the new pid/tid",
657 case (
SIGTRAP | (PTRACE_EVENT_EXEC << 8)): {
658 LLDB_LOG(log,
"received exec event, code = {0}", info.si_code ^
SIGTRAP);
665 LLDB_LOG(log,
"exec received, stop tracking all but main thread");
667 llvm::erase_if(
m_threads, [&](std::unique_ptr<NativeThreadProtocol> &t) {
668 return t->GetID() !=
GetID();
674 main_thread->SetStoppedByExec();
688 case (
SIGTRAP | (PTRACE_EVENT_EXIT << 8)): {
694 unsigned long data = 0;
699 "received PTRACE_EVENT_EXIT, data = {0:x}, WIFEXITED={1}, "
700 "WIFSIGNALED={2}, pid = {3}, main_thread = {4}",
701 data, WIFEXITED(data), WIFSIGNALED(data), thread.GetID(),
716 if (is_main_thread) {
726 case (
SIGTRAP | (PTRACE_EVENT_VFORK_DONE << 8)): {
728 thread.SetStoppedByVForkDone();
742 Status error = thread.GetRegisterContext().GetWatchpointHitIndex(
743 wp_index, (uintptr_t)info.si_addr);
746 "received error while checking for watchpoint hits, pid = "
748 thread.GetID(),
error);
756 error = thread.GetRegisterContext().GetHardwareBreakHitIndex(
757 bp_index, (uintptr_t)info.si_addr);
759 LLDB_LOG(log,
"received error while checking for hardware "
760 "breakpoint hits, pid = {0}, error = {1}",
761 thread.GetID(),
error);
779 Status error = thread.GetRegisterContext().GetWatchpointHitIndex(
783 "received error while checking for watchpoint hits, pid = "
785 thread.GetID(),
error);
801 "received unknown SIGTRAP stop event ({0}, pid {1} tid {2}, resuming",
802 info.si_code,
GetID(), thread.GetID());
809 LLDB_LOG(log,
"received unknown SIGTRAP stop event ({0}, pid {1} tid {2}",
810 info.si_code,
GetID(), thread.GetID());
818 LLDB_LOG(log,
"received trace event, pid = {0}", thread.GetID());
821 thread.SetStoppedByTrace();
828 LLDB_LOG(log,
"received breakpoint event, pid = {0}", thread.GetID());
831 thread.SetStoppedByBreakpoint();
835 auto stepping_with_bp_it =
838 llvm::is_contained(stepping_with_bp_it->second, reg_ctx.
GetPC()))
839 thread.SetStoppedByTrace();
847 LLDB_LOG(log,
"received watchpoint event, pid = {0}, wp_index = {1}",
848 thread.GetID(), wp_index);
852 thread.SetStoppedByWatchpoint(wp_index);
861 const int signo = info.si_signo;
862 const bool is_from_llgs = info.si_pid == getpid();
877 "received signal {0} ({1}) with code {2}, (siginfo pid = {3}, "
878 "waitpid pid = {4})",
883 if (is_from_llgs && (info.si_code == SI_TKILL) && (signo ==
SIGSTOP)) {
885 LLDB_LOG(log,
"pid {0} tid {1}, thread stopped",
GetID(), thread.GetID());
894 const StateType thread_state = thread.GetState();
905 thread.SetStoppedBySignal(
SIGSTOP, &info);
907 thread.SetStoppedWithNoReason();
916 LLDB_LOG(log,
"failed to resume thread {0}: {1}", thread.GetID(),
921 "pid {0} tid {1}, thread was already marked as a stopped "
922 "state (state={2}), leaving stop signal as is",
923 GetID(), thread.GetID(), thread_state);
940 thread.SetStoppedBySignal(signo, &info);
949 LLDB_LOG(log,
"parent_tid={0}, child_pid={1}, event={2}", parent.
GetID(),
955 case PTRACE_EVENT_CLONE: {
961 if (tgid_ret != child_pid) {
963 assert(!tgid_ret || *tgid_ret ==
GetID());
974 case PTRACE_EVENT_FORK:
975 case PTRACE_EVENT_VFORK: {
976 bool is_vfork =
event == PTRACE_EVENT_VFORK;
985 m_delegate.NewSubprocess(
this, std::move(child_process));
990 child_process->Detach();
996 llvm_unreachable(
"unknown clone_info.event");
1003 if (
m_arch.IsMIPS() ||
m_arch.GetMachine() == llvm::Triple::arm ||
1004 m_arch.GetTriple().isRISCV() ||
m_arch.GetTriple().isLoongArch())
1017 if (software_single_step) {
1019 assert(thread &&
"thread list should not contain NULL threads");
1023 if (action ==
nullptr)
1036 assert(thread &&
"thread list should not contain NULL threads");
1041 if (action ==
nullptr) {
1042 LLDB_LOG(log,
"no action specified for pid {0} tid {1}",
GetID(),
1047 LLDB_LOG(log,
"processing resume action state {0} for pid {1} tid {2}",
1050 switch (action->
state) {
1054 const int signo = action->
signal;
1056 action->
state, signo);
1059 "NativeProcessLinux::%s: failed to resume thread "
1060 "for pid %" PRIu64
", tid %" PRIu64
", error = %s",
1061 __FUNCTION__,
GetID(), thread->GetID(),
error.AsCString());
1072 "NativeProcessLinux::%s (): unexpected state %s specified "
1073 "for pid %" PRIu64
", tid %" PRIu64,
1100 kill(
GetID(), SIGCONT);
1118 LLDB_LOG(log,
"sending signal {0} ({1}) to pid {1}", signo,
1121 if (kill(
GetID(), signo))
1135 LLDB_LOG(log,
"selecting running thread for interrupt target");
1139 const auto thread_state = thread->GetState();
1141 running_thread = thread.get();
1146 stopped_thread = thread.get();
1150 if (!running_thread && !stopped_thread) {
1151 Status error(
"found no running/stepping or live stopped threads as target "
1159 running_thread ? running_thread : stopped_thread;
1161 LLDB_LOG(log,
"pid {0} {1} tid {2} chosen for interrupt target",
GetID(),
1162 running_thread ?
"running" :
"stopped",
1163 deferred_signal_thread->
GetID());
1183 LLDB_LOG(log,
"ignored for PID {0} due to current state: {1}",
GetID(),
1237 "descending /proc/pid/maps entries detected, unexpected");
1255 range_info = proc_entry_info;
1281 LLDB_LOG(log,
"reusing {0} cached memory region entries",
1289 FileSpec file_spec(Info->GetName().GetCString());
1297 LLDB_LOG(log,
"failed to parse proc maps: {0}", Result);
1308 if (!BufferOrError) {
1310 return BufferOrError.getError();
1325 "failed to find any procfs maps entries, assuming no support "
1326 "for memory region metadata retrieval");
1330 LLDB_LOG(log,
"read {0} memory region entries from /proc/{1}/maps",
1340 LLDB_LOG(log,
"newBumpId={0}", newBumpId);
1341 LLDB_LOG(log,
"clearing {0} entries from memory region cache",
1346llvm::Expected<uint64_t>
1354 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1355 "No executable memory region found!");
1357 addr_t exe_addr = region_it->first.GetRange().GetRangeBase();
1368 return std::move(Err);
1369 auto restore_regs = llvm::make_scope_exit(
1372 llvm::SmallVector<uint8_t, 8> memory(syscall_data.
Insn.size());
1374 if (llvm::Error Err =
1375 ReadMemory(exe_addr, memory.data(), memory.size(), bytes_read)
1377 return std::move(Err);
1380 auto restore_mem = llvm::make_scope_exit(
1381 [&] {
WriteMemory(exe_addr, memory.data(), memory.size(), bytes_read); });
1383 if (llvm::Error Err = reg_ctx.
SetPC(exe_addr).
ToError())
1384 return std::move(Err);
1386 for (
const auto &zip : llvm::zip_first(args, syscall_data.
Args)) {
1387 if (llvm::Error Err =
1389 .WriteRegisterFromUnsigned(std::get<1>(zip), std::get<0>(zip))
1391 return std::move(Err);
1395 syscall_data.
Insn.size(), bytes_read)
1397 return std::move(Err);
1404 if (llvm::Error Err =
1406 return std::move(Err);
1409 ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, ::waitpid, thread.GetID(),
1411 if (wait_pid == -1) {
1412 return llvm::errorCodeToError(
1413 std::error_code(errno, std::generic_category()));
1415 assert((
unsigned)wait_pid == thread.GetID());
1420 uint64_t errno_threshold =
1421 (uint64_t(-1) >> (64 - 8 *
m_arch.GetAddressByteSize())) - 0x1000;
1422 if (result > errno_threshold) {
1423 return llvm::errorCodeToError(
1424 std::error_code(-result & 0xfff, std::generic_category()));
1430llvm::Expected<addr_t>
1433 std::optional<NativeRegisterContextLinux::MmapData> mmap_data =
1436 return llvm::make_error<UnimplementedError>();
1439 assert((permissions & (ePermissionsReadable | ePermissionsWritable |
1440 ePermissionsExecutable)) == permissions &&
1441 "Unknown permission!");
1442 if (permissions & ePermissionsReadable)
1444 if (permissions & ePermissionsWritable)
1446 if (permissions & ePermissionsExecutable)
1449 llvm::Expected<uint64_t> Result =
1458 std::optional<NativeRegisterContextLinux::MmapData> mmap_data =
1461 return llvm::make_error<UnimplementedError>();
1465 return llvm::createStringError(llvm::errc::invalid_argument,
1466 "Memory not allocated by the debugger.");
1468 llvm::Expected<uint64_t> Result =
1469 Syscall({mmap_data->SysMunmap, addr, it->second});
1471 return Result.takeError();
1474 return llvm::Error::success();
1479 std::vector<uint8_t> &tags) {
1480 llvm::Expected<NativeRegisterContextLinux::MemoryTaggingDetails> details =
1494 range = details->manager->ExpandToGranule(range);
1497 size_t num_tags = range.
GetByteSize() / details->manager->GetGranuleSize();
1498 tags.resize(num_tags * details->manager->GetTagSizeInBytes());
1500 struct iovec tags_iovec;
1501 uint8_t *dest = tags.data();
1507 tags_iovec.iov_base = dest;
1508 tags_iovec.iov_len = num_tags;
1512 reinterpret_cast<void *
>(read_addr),
static_cast<void *
>(&tags_iovec),
1521 size_t tags_read = tags_iovec.iov_len;
1522 assert(tags_read && (tags_read <= num_tags));
1524 dest += tags_read * details->manager->GetTagSizeInBytes();
1525 read_addr += details->manager->GetGranuleSize() * tags_read;
1526 num_tags -= tags_read;
1534 const std::vector<uint8_t> &tags) {
1535 llvm::Expected<NativeRegisterContextLinux::MemoryTaggingDetails> details =
1549 range = details->manager->ExpandToGranule(range);
1552 llvm::Expected<std::vector<lldb::addr_t>> unpacked_tags_or_err =
1553 details->manager->UnpackTagsData(tags);
1554 if (!unpacked_tags_or_err)
1557 llvm::Expected<std::vector<lldb::addr_t>> repeated_tags_or_err =
1558 details->manager->RepeatTagsForRange(*unpacked_tags_or_err, range);
1559 if (!repeated_tags_or_err)
1563 llvm::Expected<std::vector<uint8_t>> final_tag_data =
1564 details->manager->PackTags(*repeated_tags_or_err);
1565 if (!final_tag_data)
1568 struct iovec tags_vec;
1569 uint8_t *src = final_tag_data->data();
1572 size_t num_tags = repeated_tags_or_err->size();
1576 while (num_tags > 0) {
1577 tags_vec.iov_base = src;
1578 tags_vec.iov_len = num_tags;
1582 reinterpret_cast<void *
>(write_addr),
static_cast<void *
>(&tags_vec), 0,
1591 size_t tags_written = tags_vec.iov_len;
1592 assert(tags_written && (tags_written <= num_tags));
1594 src += tags_written * details->manager->GetTagSizeInBytes();
1595 write_addr += details->manager->GetGranuleSize() * tags_written;
1596 num_tags -= tags_written;
1624llvm::Expected<llvm::ArrayRef<uint8_t>>
1628 static const uint8_t g_arm_opcode[] = {0xf0, 0x01, 0xf0, 0xe7};
1629 static const uint8_t g_thumb_opcode[] = {0x01, 0xde};
1632 case llvm::Triple::arm:
1633 switch (size_hint) {
1635 return llvm::ArrayRef(g_thumb_opcode);
1637 return llvm::ArrayRef(g_arm_opcode);
1639 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1640 "Unrecognised trap opcode size hint!");
1648 size_t &bytes_read) {
1650 LLDB_LOG(log,
"addr = {0}, buf = {1}, size = {2}", addr, buf, size);
1657 struct iovec local_iov, remote_iov;
1658 local_iov.iov_base = buf;
1659 local_iov.iov_len = size;
1660 remote_iov.iov_base =
reinterpret_cast<void *
>(addr);
1661 remote_iov.iov_len = size;
1666 if (read_result < 0)
1669 bytes_read = read_result;
1672 "process_vm_readv({0}, [iovec({1}, {2})], [iovec({3:x}, {2})], 1, "
1675 error > 0 ? llvm::sys::StrError(errno) :
"sucesss");
1678 unsigned char *dst =
static_cast<unsigned char *
>(buf);
1682 for (; bytes_read < size; bytes_read += remainder) {
1685 reinterpret_cast<void *
>(addr + bytes_read),
nullptr, 0, &data);
1689 remainder = size - bytes_read;
1693 memcpy(dst + bytes_read, &data, remainder);
1699 size_t size,
size_t &bytes_written) {
1700 const unsigned char *src =
static_cast<const unsigned char *
>(buf);
1705 LLDB_LOG(log,
"addr = {0}, buf = {1}, size = {2}", addr, buf, size);
1707 for (bytes_written = 0; bytes_written < size; bytes_written += remainder) {
1708 remainder = size - bytes_written;
1712 unsigned long data = 0;
1715 LLDB_LOG(log,
"[{0:x}]:{1:x}", addr, data);
1721 unsigned char buff[8];
1727 memcpy(buff, src, remainder);
1729 size_t bytes_written_rec;
1734 LLDB_LOG(log,
"[{0:x}]:{1:x} ({2:x})", addr, *(
const unsigned long *)src,
1735 *(
unsigned long *)buff);
1745 return PtraceWrapper(PTRACE_GETSIGINFO, tid,
nullptr, siginfo);
1749 unsigned long *message) {
1750 return PtraceWrapper(PTRACE_GETEVENTMSG, tid,
nullptr, message);
1762 assert(thread &&
"thread list should not contain NULL threads");
1763 if (thread->GetID() == thread_id) {
1776 LLDB_LOG(log,
"tid: {0}", thread_id);
1778 auto it = llvm::find_if(
m_threads, [&](
const auto &thread_up) {
1779 return thread_up.get() == &thread;
1800 LLDB_LOG(log,
"Failed to trace a new thread with intel-pt, tid = {0}. {1}",
1801 tid,
error.AsCString());
1810 "Failed to stop a destroyed thread with intel-pt, tid = {0}. {1}",
1811 tid,
error.AsCString());
1818 LLDB_LOG(log,
"pid {0} adding thread with tid {1}",
GetID(), thread_id);
1821 "attempted to add a thread by id that already exists");
1827 m_threads.push_back(std::make_unique<NativeThreadLinux>(*
this, thread_id));
1832 if (tracing_error.
Fail()) {
1833 thread.SetStoppedByProcessorTrace(tracing_error.
AsCString());
1838 thread.SetStoppedBySignal(
SIGSTOP);
1849 FileSpec module_file_spec(module_path);
1854 if (it.second.GetFilename() == module_file_spec.
GetFilename()) {
1855 file_spec = it.second;
1860 "Module file (%s) not found in /proc/%" PRIu64
"/maps file!",
1873 if (it.second == file) {
1874 load_addr = it.first.GetRange().GetRangeBase();
1894 LLDB_LOG(log,
"tid: {0}", thread.GetID());
1903 "about to resume tid {0} per explicit request but we have a "
1904 "pending stop notification (tid {1}) that is actively "
1905 "waiting for this thread to stop. Valid sequence of events?",
1913 Status resume_result = thread.Resume(signo);
1916 return resume_result;
1919 Status step_result = thread.SingleStep(signo);
1925 LLDB_LOG(log,
"Unhandled state {0}.", state);
1926 llvm_unreachable(
"Unhandled state for resume");
1934 LLDB_LOG(log,
"about to process event: (triggering_tid: {0})",
1947 LLDB_LOG(log,
"event processing done");
1954 for (
const auto &thread_sp :
m_threads) {
1965 for (
auto &&bp_addr : thread_info.second) {
1968 LLDB_LOG(log,
"pid = {0} remove stepping breakpoint: {1}",
1969 thread_info.first,
error);
1982 LLDB_LOG(log,
"tid: {0}", thread.GetID());
1988 thread.RequestStop();
1995 void *data,
size_t data_size,
2007 *(
unsigned int *)addr, data);
2018 LLDB_LOG(log,
"ptrace({0}, {1}, {2}, {3}, {4})={5:x}", req, pid, addr, data,
2036 if (type ==
"intel-pt") {
2037 if (Expected<TraceIntelPTStartRequest> request =
2038 json::parse<TraceIntelPTStartRequest>(json_request,
2039 "TraceIntelPTStartRequest")) {
2042 return request.takeError();
2049 if (request.
type ==
"intel-pt")
2055 if (type ==
"intel-pt")
2062 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_LOGV(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()
#define DEBUG_PTRACE_MAXBYTES
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.
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
const ConstString & GetFilename() const
Filename string const get accessor.
void Clear()
Clears the object state.
void Resolve(llvm::SmallVectorImpl< char > &path)
Resolve path to make it canonical.
static FileSystem & Instance()
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 SetMapped(OptionalBool val)
void SetReadable(OptionalBool val)
void SetExecutable(OptionalBool val)
void SetWritable(OptionalBool val)
Range< lldb::addr_t, lldb::addr_t > TagRange
Abstract class that extends NativeProcessProtocol with ELF specific logic.
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)
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::unordered_map< lldb::addr_t, SoftwareBreakpoint > m_software_breakpoints
std::map< lldb::tid_t, std::vector< lldb::addr_t > > m_threads_stepping_with_breakpoint
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
PseudoTerminal & GetPTY()
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 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
void DoStopIDBumped(uint32_t newBumpId) 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...
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.
std::vector< std::pair< MemoryRegionInfo, FileSpec > > m_mem_region_cache
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 ReadMemory(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read) override
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 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.
Status WriteMemory(lldb::addr_t addr, const void *buf, size_t size, size_t &bytes_written) override
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.