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::createStringError(
"Could not sync with inferior process");
292 LLDB_LOG(log,
"inferior started, now in stopped state");
296 LLDB_LOG(log,
"failed to set default ptrace options: {0}", status);
300 llvm::Expected<ArchSpec> arch_or =
303 return arch_or.takeError();
307 *arch_or, *
this, {pid}));
310llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
318 return tids_or.takeError();
319 ArrayRef<::pid_t> tids = *tids_or;
320 llvm::Expected<ArchSpec> arch_or =
323 return arch_or.takeError();
325 return std::unique_ptr<NativeProcessLinux>(
345static std::optional<std::pair<lldb::pid_t, WaitStatus>>
WaitPid() {
349 ::pid_t wait_pid = llvm::sys::RetryAfterSignal(
350 -1, ::waitpid, -1, &status, __WALL | __WNOTHREAD | WNOHANG);
355 if (wait_pid == -1) {
363 LLDB_LOG(log,
"waitpid(-1, &status, _) = {0}, status = {1}", wait_pid,
365 return std::make_pair(wait_pid, wait_status);
394 LLDB_LOG(log,
"Ignoring waitpid event {0} for pid {1}", status, pid);
409 "received clone event for tid {0}. tid not tracked yet, "
410 "waiting for it to appear...",
413 llvm::sys::RetryAfterSignal(-1, ::waitpid, tid, &status, __WALL);
420 "waitpid({0}, &status, __WALL) => {1} (errno: {2}, status = {3})",
429 llvm::ArrayRef<::pid_t> tids)
438 for (
const auto &tid : tids) {
456 for (Host::TidMap::iterator it = tids_to_attach.begin();
457 it != tids_to_attach.end();) {
458 if (it->second ==
false) {
467 it = tids_to_attach.erase(it);
479 llvm::sys::RetryAfterSignal(-1, ::waitpid, tid,
nullptr, __WALL);
485 if (errno == ESRCH) {
486 it = tids_to_attach.erase(it);
489 return llvm::errorCodeToError(
490 std::error_code(errno, std::generic_category()));
496 LLDB_LOG(log,
"adding tid = {0}", tid);
505 size_t tid_count = tids_to_attach.size();
507 return llvm::createStringError(
"No such process");
509 std::vector<::pid_t> tids;
510 tids.reserve(tid_count);
511 for (
const auto &p : tids_to_attach)
512 tids.push_back(p.first);
513 return std::move(tids);
517 long ptrace_opts = 0;
521 ptrace_opts |= PTRACE_O_TRACEEXIT;
524 ptrace_opts |= PTRACE_O_TRACECLONE;
528 ptrace_opts |= PTRACE_O_TRACEEXEC;
531 ptrace_opts |= PTRACE_O_TRACEFORK;
534 ptrace_opts |= PTRACE_O_TRACEVFORK;
538 ptrace_opts |= PTRACE_O_TRACEVFORKDONE;
540 return PtraceWrapper(PTRACE_SETOPTIONS, pid,
nullptr, (
void *)ptrace_opts);
545 if (pid ==
GetID() &&
564 const bool is_main_thread = (thread.GetID() ==
GetID());
569 "got exit status({0}) , tid = {1} ({2} main thread), process "
571 status, thread.GetID(), is_main_thread ?
"is" :
"is not",
577 assert(!is_main_thread &&
"Main thread exits handled elsewhere");
585 if (info_err.Success()) {
592 if (info_err.GetError() == EINVAL) {
603 "received a group stop for pid {0} tid {1}. Transparent "
604 "handling of group stops not supported, resuming the "
606 GetID(), thread.GetID());
618 "GetSignalInfo({0}) failed: {1}, status = {2}, main_thread = "
619 "{3}. Expecting WIFEXITED soon.",
620 thread.GetID(), info_err, status, is_main_thread);
628 const bool is_main_thread = (thread.GetID() ==
GetID());
630 assert(info.si_signo ==
SIGTRAP &&
"Unexpected child signal!");
632 switch (info.si_code) {
633 case (
SIGTRAP | (PTRACE_EVENT_FORK << 8)):
634 case (
SIGTRAP | (PTRACE_EVENT_VFORK << 8)):
635 case (
SIGTRAP | (PTRACE_EVENT_CLONE << 8)): {
641 unsigned long event_message = 0;
644 "pid {0} received clone() event but GetEventMessage failed "
645 "so we don't know the new pid/tid",
655 case (
SIGTRAP | (PTRACE_EVENT_EXEC << 8)): {
656 LLDB_LOG(log,
"received exec event, code = {0}", info.si_code ^
SIGTRAP);
663 LLDB_LOG(log,
"exec received, stop tracking all but main thread");
665 llvm::erase_if(
m_threads, [&](std::unique_ptr<NativeThreadProtocol> &t) {
666 return t->GetID() !=
GetID();
672 main_thread->SetStoppedByExec();
686 case (
SIGTRAP | (PTRACE_EVENT_EXIT << 8)): {
692 unsigned long data = 0;
697 "received PTRACE_EVENT_EXIT, data = {0:x}, WIFEXITED={1}, "
698 "WIFSIGNALED={2}, pid = {3}, main_thread = {4}",
699 data, WIFEXITED(data), WIFSIGNALED(data), thread.GetID(),
714 if (is_main_thread) {
724 case (
SIGTRAP | (PTRACE_EVENT_VFORK_DONE << 8)): {
726 thread.SetStoppedByVForkDone();
740 Status error = thread.GetRegisterContext().GetWatchpointHitIndex(
741 wp_index, (uintptr_t)info.si_addr);
744 "received error while checking for watchpoint hits, pid = "
746 thread.GetID(),
error);
754 error = thread.GetRegisterContext().GetHardwareBreakHitIndex(
755 bp_index, (uintptr_t)info.si_addr);
757 LLDB_LOG(log,
"received error while checking for hardware "
758 "breakpoint hits, pid = {0}, error = {1}",
759 thread.GetID(),
error);
779 "received unknown SIGTRAP stop event ({0}, pid {1} tid {2}, resuming",
780 info.si_code,
GetID(), thread.GetID());
787 LLDB_LOG(log,
"received unknown SIGTRAP stop event ({0}, pid {1} tid {2}",
788 info.si_code,
GetID(), thread.GetID());
796 LLDB_LOG(log,
"received trace event, pid = {0}", thread.GetID());
799 thread.SetStoppedByTrace();
806 LLDB_LOG(log,
"received breakpoint event, pid = {0}", thread.GetID());
809 thread.SetStoppedByBreakpoint();
813 auto stepping_with_bp_it =
816 llvm::is_contained(stepping_with_bp_it->second, reg_ctx.
GetPC()))
817 thread.SetStoppedByTrace();
825 LLDB_LOG(log,
"received watchpoint event, pid = {0}, wp_index = {1}",
826 thread.GetID(), wp_index);
830 thread.SetStoppedByWatchpoint(wp_index);
839 const int signo = info.si_signo;
840 const bool is_from_llgs = info.si_pid == getpid();
855 "received signal {0} ({1}) with code {2}, (siginfo pid = {3}, "
856 "waitpid pid = {4})",
861 if (is_from_llgs && (info.si_code == SI_TKILL) && (signo ==
SIGSTOP)) {
863 LLDB_LOG(log,
"pid {0} tid {1}, thread stopped",
GetID(), thread.GetID());
872 const StateType thread_state = thread.GetState();
883 thread.SetStoppedBySignal(
SIGSTOP, &info);
885 thread.SetStoppedWithNoReason();
894 LLDB_LOG(log,
"failed to resume thread {0}: {1}", thread.GetID(),
899 "pid {0} tid {1}, thread was already marked as a stopped "
900 "state (state={2}), leaving stop signal as is",
901 GetID(), thread.GetID(), thread_state);
918 thread.SetStoppedBySignal(signo, &info);
927 LLDB_LOG(log,
"parent_tid={0}, child_pid={1}, event={2}", parent.
GetID(),
933 case PTRACE_EVENT_CLONE: {
939 if (tgid_ret != child_pid) {
941 assert(!tgid_ret || *tgid_ret ==
GetID());
952 case PTRACE_EVENT_FORK:
953 case PTRACE_EVENT_VFORK: {
954 bool is_vfork =
event == PTRACE_EVENT_VFORK;
963 m_delegate.NewSubprocess(
this, std::move(child_process));
968 child_process->Detach();
974 llvm_unreachable(
"unknown clone_info.event");
981 if (
m_arch.GetMachine() == llvm::Triple::arm ||
982 m_arch.GetTriple().isRISCV() ||
m_arch.GetTriple().isLoongArch())
995 if (software_single_step) {
997 assert(thread &&
"thread list should not contain NULL threads");
1001 if (action ==
nullptr)
1014 assert(thread &&
"thread list should not contain NULL threads");
1019 if (action ==
nullptr) {
1020 LLDB_LOG(log,
"no action specified for pid {0} tid {1}",
GetID(),
1025 LLDB_LOG(log,
"processing resume action state {0} for pid {1} tid {2}",
1028 switch (action->
state) {
1032 const int signo = action->
signal;
1034 action->
state, signo);
1037 "NativeProcessLinux::%s: failed to resume thread "
1038 "for pid %" PRIu64
", tid %" PRIu64
", error = %s",
1039 __FUNCTION__,
GetID(), thread->GetID(),
error.AsCString());
1050 "NativeProcessLinux::%s (): unexpected state %s specified "
1051 "for pid %" PRIu64
", tid %" PRIu64,
1078 kill(
GetID(), SIGCONT);
1096 LLDB_LOG(log,
"sending signal {0} ({1}) to pid {1}", signo,
1099 if (kill(
GetID(), signo))
1113 LLDB_LOG(log,
"selecting running thread for interrupt target");
1117 const auto thread_state = thread->GetState();
1119 running_thread = thread.get();
1124 stopped_thread = thread.get();
1128 if (!running_thread && !stopped_thread) {
1129 Status error(
"found no running/stepping or live stopped threads as target "
1137 running_thread ? running_thread : stopped_thread;
1139 LLDB_LOG(log,
"pid {0} {1} tid {2} chosen for interrupt target",
GetID(),
1140 running_thread ?
"running" :
"stopped",
1141 deferred_signal_thread->
GetID());
1161 LLDB_LOG(log,
"ignored for PID {0} due to current state: {1}",
GetID(),
1215 "descending /proc/pid/maps entries detected, unexpected");
1233 range_info = proc_entry_info;
1259 LLDB_LOG(log,
"reusing {0} cached memory region entries",
1267 FileSpec file_spec(Info->GetName().GetCString());
1275 LLDB_LOG(log,
"failed to parse proc maps: {0}", Result);
1286 if (!BufferOrError) {
1288 return BufferOrError.getError();
1303 "failed to find any procfs maps entries, assuming no support "
1304 "for memory region metadata retrieval");
1308 LLDB_LOG(log,
"read {0} memory region entries from /proc/{1}/maps",
1318 LLDB_LOG(log,
"newBumpId={0}", newBumpId);
1319 LLDB_LOG(log,
"clearing {0} entries from memory region cache",
1324llvm::Expected<uint64_t>
1332 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1333 "No executable memory region found!");
1335 addr_t exe_addr = region_it->first.GetRange().GetRangeBase();
1346 return std::move(Err);
1347 llvm::scope_exit restore_regs(
1350 llvm::SmallVector<uint8_t, 8> memory(syscall_data.
Insn.size());
1352 if (llvm::Error Err =
1353 ReadMemory(exe_addr, memory.data(), memory.size(), bytes_read)
1355 return std::move(Err);
1358 llvm::scope_exit restore_mem(
1359 [&] {
WriteMemory(exe_addr, memory.data(), memory.size(), bytes_read); });
1361 if (llvm::Error Err = reg_ctx.
SetPC(exe_addr).
ToError())
1362 return std::move(Err);
1364 for (
const auto &zip : llvm::zip_first(args, syscall_data.
Args)) {
1365 if (llvm::Error Err =
1367 .WriteRegisterFromUnsigned(std::get<1>(zip), std::get<0>(zip))
1369 return std::move(Err);
1373 syscall_data.
Insn.size(), bytes_read)
1375 return std::move(Err);
1382 if (llvm::Error Err =
1384 return std::move(Err);
1387 ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, ::waitpid, thread.GetID(),
1389 if (wait_pid == -1) {
1390 return llvm::errorCodeToError(
1391 std::error_code(errno, std::generic_category()));
1393 assert((
unsigned)wait_pid == thread.GetID());
1398 uint64_t errno_threshold =
1399 (uint64_t(-1) >> (64 - 8 *
m_arch.GetAddressByteSize())) - 0x1000;
1400 if (result > errno_threshold) {
1401 return llvm::errorCodeToError(
1402 std::error_code(-result & 0xfff, std::generic_category()));
1408llvm::Expected<addr_t>
1411 std::optional<NativeRegisterContextLinux::MmapData> mmap_data =
1414 return llvm::make_error<UnimplementedError>();
1417 assert((permissions & (ePermissionsReadable | ePermissionsWritable |
1418 ePermissionsExecutable)) == permissions &&
1419 "Unknown permission!");
1420 if (permissions & ePermissionsReadable)
1422 if (permissions & ePermissionsWritable)
1424 if (permissions & ePermissionsExecutable)
1427 llvm::Expected<uint64_t> Result =
1436 std::optional<NativeRegisterContextLinux::MmapData> mmap_data =
1439 return llvm::make_error<UnimplementedError>();
1443 return llvm::createStringError(llvm::errc::invalid_argument,
1444 "Memory not allocated by the debugger.");
1446 llvm::Expected<uint64_t> Result =
1447 Syscall({mmap_data->SysMunmap, addr, it->second});
1449 return Result.takeError();
1452 return llvm::Error::success();
1457 std::vector<uint8_t> &tags) {
1458 llvm::Expected<NativeRegisterContextLinux::MemoryTaggingDetails> details =
1472 range = details->manager->ExpandToGranule(range);
1475 size_t num_tags = range.
GetByteSize() / details->manager->GetGranuleSize();
1476 tags.resize(num_tags * details->manager->GetTagSizeInBytes());
1478 struct iovec tags_iovec;
1479 uint8_t *dest = tags.data();
1485 tags_iovec.iov_base = dest;
1486 tags_iovec.iov_len = num_tags;
1490 reinterpret_cast<void *
>(read_addr),
static_cast<void *
>(&tags_iovec),
1499 size_t tags_read = tags_iovec.iov_len;
1500 assert(tags_read && (tags_read <= num_tags));
1502 dest += tags_read * details->manager->GetTagSizeInBytes();
1503 read_addr += details->manager->GetGranuleSize() * tags_read;
1504 num_tags -= tags_read;
1512 const std::vector<uint8_t> &tags) {
1513 llvm::Expected<NativeRegisterContextLinux::MemoryTaggingDetails> details =
1527 range = details->manager->ExpandToGranule(range);
1530 llvm::Expected<std::vector<lldb::addr_t>> unpacked_tags_or_err =
1531 details->manager->UnpackTagsData(tags);
1532 if (!unpacked_tags_or_err)
1535 llvm::Expected<std::vector<lldb::addr_t>> repeated_tags_or_err =
1536 details->manager->RepeatTagsForRange(*unpacked_tags_or_err, range);
1537 if (!repeated_tags_or_err)
1541 llvm::Expected<std::vector<uint8_t>> final_tag_data =
1542 details->manager->PackTags(*repeated_tags_or_err);
1543 if (!final_tag_data)
1546 struct iovec tags_vec;
1547 uint8_t *src = final_tag_data->data();
1550 size_t num_tags = repeated_tags_or_err->size();
1554 while (num_tags > 0) {
1555 tags_vec.iov_base = src;
1556 tags_vec.iov_len = num_tags;
1560 reinterpret_cast<void *
>(write_addr),
static_cast<void *
>(&tags_vec), 0,
1569 size_t tags_written = tags_vec.iov_len;
1570 assert(tags_written && (tags_written <= num_tags));
1572 src += tags_written * details->manager->GetTagSizeInBytes();
1573 write_addr += details->manager->GetGranuleSize() * tags_written;
1574 num_tags -= tags_written;
1602llvm::Expected<llvm::ArrayRef<uint8_t>>
1606 static const uint8_t g_arm_opcode[] = {0xf0, 0x01, 0xf0, 0xe7};
1607 static const uint8_t g_thumb_opcode[] = {0x01, 0xde};
1610 case llvm::Triple::arm:
1611 switch (size_hint) {
1613 return llvm::ArrayRef(g_thumb_opcode);
1615 return llvm::ArrayRef(g_arm_opcode);
1617 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1618 "Unrecognised trap opcode size hint!");
1626 size_t &bytes_read) {
1628 LLDB_LOG(log,
"addr = {0}, buf = {1}, size = {2}", addr, buf, size);
1635 struct iovec local_iov, remote_iov;
1636 local_iov.iov_base = buf;
1637 local_iov.iov_len = size;
1638 remote_iov.iov_base =
reinterpret_cast<void *
>(addr);
1639 remote_iov.iov_len = size;
1644 if (read_result < 0)
1647 bytes_read = read_result;
1650 "process_vm_readv({0}, [iovec({1}, {2})], [iovec({3:x}, {2})], 1, "
1653 error > 0 ? llvm::sys::StrError(errno) :
"sucesss");
1656 unsigned char *dst =
static_cast<unsigned char *
>(buf);
1660 for (; bytes_read < size; bytes_read += remainder) {
1663 reinterpret_cast<void *
>(addr + bytes_read),
nullptr, 0, &data);
1667 remainder = size - bytes_read;
1671 memcpy(dst + bytes_read, &data, remainder);
1677 size_t size,
size_t &bytes_written) {
1678 const unsigned char *src =
static_cast<const unsigned char *
>(buf);
1683 LLDB_LOG(log,
"addr = {0}, buf = {1}, size = {2}", addr, buf, size);
1685 for (bytes_written = 0; bytes_written < size; bytes_written += remainder) {
1686 remainder = size - bytes_written;
1690 unsigned long data = 0;
1693 LLDB_LOG(log,
"[{0:x}]:{1:x}", addr, data);
1699 unsigned char buff[8];
1705 memcpy(buff, src, remainder);
1707 size_t bytes_written_rec;
1712 LLDB_LOG(log,
"[{0:x}]:{1:x} ({2:x})", addr, *(
const unsigned long *)src,
1713 *(
unsigned long *)buff);
1723 return PtraceWrapper(PTRACE_GETSIGINFO, tid,
nullptr, siginfo);
1727 unsigned long *message) {
1728 return PtraceWrapper(PTRACE_GETEVENTMSG, tid,
nullptr, message);
1740 assert(thread &&
"thread list should not contain NULL threads");
1741 if (thread->GetID() == thread_id) {
1754 LLDB_LOG(log,
"tid: {0}", thread_id);
1756 auto it = llvm::find_if(
m_threads, [&](
const auto &thread_up) {
1757 return thread_up.get() == &thread;
1778 LLDB_LOG(log,
"Failed to trace a new thread with intel-pt, tid = {0}. {1}",
1779 tid,
error.AsCString());
1788 "Failed to stop a destroyed thread with intel-pt, tid = {0}. {1}",
1789 tid,
error.AsCString());
1796 LLDB_LOG(log,
"pid {0} adding thread with tid {1}",
GetID(), thread_id);
1799 "attempted to add a thread by id that already exists");
1805 m_threads.push_back(std::make_unique<NativeThreadLinux>(*
this, thread_id));
1810 if (tracing_error.
Fail()) {
1811 thread.SetStoppedByProcessorTrace(tracing_error.
AsCString());
1816 thread.SetStoppedBySignal(
SIGSTOP);
1827 FileSpec module_file_spec(module_path);
1832 if (it.second.GetFilename() == module_file_spec.
GetFilename()) {
1833 file_spec = it.second;
1838 "Module file (%s) not found in /proc/%" PRIu64
"/maps file!",
1851 if (it.second == file) {
1852 load_addr = it.first.GetRange().GetRangeBase();
1872 LLDB_LOG(log,
"tid: {0}", thread.GetID());
1881 "about to resume tid {0} per explicit request but we have a "
1882 "pending stop notification (tid {1}) that is actively "
1883 "waiting for this thread to stop. Valid sequence of events?",
1891 Status resume_result = thread.Resume(signo);
1894 return resume_result;
1897 Status step_result = thread.SingleStep(signo);
1903 LLDB_LOG(log,
"Unhandled state {0}.", state);
1904 llvm_unreachable(
"Unhandled state for resume");
1912 LLDB_LOG(log,
"about to process event: (triggering_tid: {0})",
1925 LLDB_LOG(log,
"event processing done");
1932 for (
const auto &thread_sp :
m_threads) {
1943 for (
auto &&bp_addr : thread_info.second) {
1946 LLDB_LOG(log,
"pid = {0} remove stepping breakpoint: {1}",
1947 thread_info.first,
error);
1960 LLDB_LOG(log,
"tid: {0}", thread.GetID());
1966 thread.RequestStop();
1973 void *data,
size_t data_size,
1985 *(
unsigned int *)addr, data);
1996 LLDB_LOG(log,
"ptrace({0}, {1}, {2}, {3}, {4})={5:x}", req, pid, addr, data,
2014 if (type ==
"intel-pt") {
2015 if (Expected<TraceIntelPTStartRequest> request =
2016 json::parse<TraceIntelPTStartRequest>(json_request,
2017 "TraceIntelPTStartRequest")) {
2020 return request.takeError();
2027 if (request.
type ==
"intel-pt")
2033 if (type ==
"intel-pt")
2040 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.
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 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
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.