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(
1365 llvm::SmallVector<uint8_t, 8> memory(syscall_data.
Insn.size());
1367 if (llvm::Error Err =
1368 ReadMemory(exe_addr, memory.data(), memory.size(), bytes_read)
1370 return std::move(Err);
1373 llvm::scope_exit restore_mem([&] {
1374 DoWriteMemory(exe_addr, memory.data(), memory.size(), bytes_read);
1377 if (llvm::Error Err = reg_ctx.
SetPC(exe_addr).
ToError())
1378 return std::move(Err);
1380 for (
const auto &zip : llvm::zip_first(args, syscall_data.
Args)) {
1381 if (llvm::Error Err =
1383 .WriteRegisterFromUnsigned(std::get<1>(zip), std::get<0>(zip))
1385 return std::move(Err);
1389 syscall_data.
Insn.size(), bytes_read)
1391 return std::move(Err);
1398 if (llvm::Error Err =
1400 return std::move(Err);
1403 ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, ::waitpid, thread.GetID(),
1405 if (wait_pid == -1) {
1406 return llvm::errorCodeToError(
1407 std::error_code(errno, std::generic_category()));
1409 assert((
unsigned)wait_pid == thread.GetID());
1414 uint64_t errno_threshold =
1415 (uint64_t(-1) >> (64 - 8 *
m_arch.GetAddressByteSize())) - 0x1000;
1416 if (result > errno_threshold) {
1417 return llvm::errorCodeToError(
1418 std::error_code(-result & 0xfff, std::generic_category()));
1424llvm::Expected<addr_t>
1427 std::optional<NativeRegisterContextLinux::MmapData> mmap_data =
1430 return llvm::make_error<UnimplementedError>();
1433 assert((permissions & (ePermissionsReadable | ePermissionsWritable |
1434 ePermissionsExecutable)) == permissions &&
1435 "Unknown permission!");
1436 if (permissions & ePermissionsReadable)
1438 if (permissions & ePermissionsWritable)
1440 if (permissions & ePermissionsExecutable)
1443 llvm::Expected<uint64_t> Result =
1452 std::optional<NativeRegisterContextLinux::MmapData> mmap_data =
1455 return llvm::make_error<UnimplementedError>();
1459 return llvm::createStringError(llvm::errc::invalid_argument,
1460 "Memory not allocated by the debugger.");
1462 llvm::Expected<uint64_t> Result =
1463 Syscall({mmap_data->SysMunmap, addr, it->second});
1465 return Result.takeError();
1468 return llvm::Error::success();
1473 std::vector<uint8_t> &tags) {
1474 llvm::Expected<NativeRegisterContextLinux::MemoryTaggingDetails> details =
1488 range = details->manager->ExpandToGranule(range);
1491 size_t num_tags = range.
GetByteSize() / details->manager->GetGranuleSize();
1492 tags.resize(num_tags * details->manager->GetTagSizeInBytes());
1494 struct iovec tags_iovec;
1495 uint8_t *dest = tags.data();
1501 tags_iovec.iov_base = dest;
1502 tags_iovec.iov_len = num_tags;
1506 reinterpret_cast<void *
>(read_addr),
static_cast<void *
>(&tags_iovec),
1515 size_t tags_read = tags_iovec.iov_len;
1516 assert(tags_read && (tags_read <= num_tags));
1518 dest += tags_read * details->manager->GetTagSizeInBytes();
1519 read_addr += details->manager->GetGranuleSize() * tags_read;
1520 num_tags -= tags_read;
1528 const std::vector<uint8_t> &tags) {
1529 llvm::Expected<NativeRegisterContextLinux::MemoryTaggingDetails> details =
1543 range = details->manager->ExpandToGranule(range);
1546 llvm::Expected<std::vector<lldb::addr_t>> unpacked_tags_or_err =
1547 details->manager->UnpackTagsData(tags);
1548 if (!unpacked_tags_or_err)
1551 llvm::Expected<std::vector<lldb::addr_t>> repeated_tags_or_err =
1552 details->manager->RepeatTagsForRange(*unpacked_tags_or_err, range);
1553 if (!repeated_tags_or_err)
1557 llvm::Expected<std::vector<uint8_t>> final_tag_data =
1558 details->manager->PackTags(*repeated_tags_or_err);
1559 if (!final_tag_data)
1562 struct iovec tags_vec;
1563 uint8_t *src = final_tag_data->data();
1566 size_t num_tags = repeated_tags_or_err->size();
1570 while (num_tags > 0) {
1571 tags_vec.iov_base = src;
1572 tags_vec.iov_len = num_tags;
1576 reinterpret_cast<void *
>(write_addr),
static_cast<void *
>(&tags_vec), 0,
1585 size_t tags_written = tags_vec.iov_len;
1586 assert(tags_written && (tags_written <= num_tags));
1588 src += tags_written * details->manager->GetTagSizeInBytes();
1589 write_addr += details->manager->GetGranuleSize() * tags_written;
1590 num_tags -= tags_written;
1618llvm::Expected<llvm::ArrayRef<uint8_t>>
1622 static const uint8_t g_arm_opcode[] = {0xf0, 0x01, 0xf0, 0xe7};
1623 static const uint8_t g_thumb_opcode[] = {0x01, 0xde};
1626 case llvm::Triple::arm:
1627 switch (size_hint) {
1629 return llvm::ArrayRef(g_thumb_opcode);
1631 return llvm::ArrayRef(g_arm_opcode);
1633 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1634 "Unrecognised trap opcode size hint!");
1642 void *buf,
size_t size,
1643 size_t &bytes_read) {
1646 LLDB_LOG(log,
"addr = {0}, buf = {1}, size = {2}", addr, buf, size);
1653 struct iovec local_iov, remote_iov;
1654 local_iov.iov_base = buf;
1655 local_iov.iov_len = size;
1656 remote_iov.iov_base =
reinterpret_cast<void *
>(addr);
1657 remote_iov.iov_len = size;
1662 if (read_result < 0)
1665 bytes_read = read_result;
1668 "process_vm_readv({0}, [iovec({1}, {2})], [iovec({3:x}, {2})], 1, "
1671 error > 0 ? llvm::sys::StrError(errno) :
"sucesss");
1674 unsigned char *dst =
static_cast<unsigned char *
>(buf);
1678 for (; bytes_read < size; bytes_read += remainder) {
1681 reinterpret_cast<void *
>(addr + bytes_read),
nullptr, 0, &data);
1685 remainder = size - bytes_read;
1689 memcpy(dst + bytes_read, &data, remainder);
1695 size_t size,
size_t &bytes_written) {
1696 const unsigned char *src =
static_cast<const unsigned char *
>(buf);
1701 LLDB_LOG(log,
"addr = {0}, buf = {1}, size = {2}", addr, buf, size);
1703 for (bytes_written = 0; bytes_written < size; bytes_written += remainder) {
1704 remainder = size - bytes_written;
1708 unsigned long data = 0;
1711 LLDB_LOG(log,
"[{0:x}]:{1:x}", addr, data);
1717 unsigned char buff[8];
1723 memcpy(buff, src, remainder);
1725 size_t bytes_written_rec;
1730 LLDB_LOG(log,
"[{0:x}]:{1:x} ({2:x})", addr, *(
const unsigned long *)src,
1731 *(
unsigned long *)buff);
1741 return PtraceWrapper(PTRACE_GETSIGINFO, tid,
nullptr, siginfo);
1745 unsigned long *message) {
1746 return PtraceWrapper(PTRACE_GETEVENTMSG, tid,
nullptr, message);
1758 assert(thread &&
"thread list should not contain NULL threads");
1759 if (thread->GetID() == thread_id) {
1772 LLDB_LOG(log,
"tid: {0}", thread_id);
1774 auto it = llvm::find_if(
m_threads, [&](
const auto &thread_up) {
1775 return thread_up.get() == &thread;
1796 LLDB_LOG(log,
"Failed to trace a new thread with intel-pt, tid = {0}. {1}",
1797 tid,
error.AsCString());
1806 "Failed to stop a destroyed thread with intel-pt, tid = {0}. {1}",
1807 tid,
error.AsCString());
1814 LLDB_LOG(log,
"pid {0} adding thread with tid {1}",
GetID(), thread_id);
1817 "attempted to add a thread by id that already exists");
1823 m_threads.push_back(std::make_unique<NativeThreadLinux>(*
this, thread_id));
1828 if (tracing_error.
Fail()) {
1829 thread.SetStoppedByProcessorTrace(tracing_error.
AsCString());
1834 thread.SetStoppedBySignal(
SIGSTOP);
1845 FileSpec module_file_spec(module_path);
1850 if (it.second.GetFilename() == module_file_spec.
GetFilename()) {
1851 file_spec = it.second;
1856 "Module file ({0}) not found in /proc/{1}/maps file!",
1869 if (it.second == file) {
1870 load_addr = it.first.GetRange().GetRangeBase();
1890 LLDB_LOG(log,
"tid: {0}", thread.GetID());
1899 "about to resume tid {0} per explicit request but we have a "
1900 "pending stop notification (tid {1}) that is actively "
1901 "waiting for this thread to stop. Valid sequence of events?",
1909 Status resume_result = thread.Resume(signo);
1912 return resume_result;
1915 Status step_result = thread.SingleStep(signo);
1921 LLDB_LOG(log,
"Unhandled state {0}.", state);
1922 llvm_unreachable(
"Unhandled state for resume");
1930 LLDB_LOG(log,
"about to process event: (triggering_tid: {0})",
1943 LLDB_LOG(log,
"event processing done");
1950 for (
const auto &thread_sp :
m_threads) {
1963 LLDB_LOG(log,
"pid = {0} remove stepping breakpoint: {1}", bp_addr,
1977 LLDB_LOG(log,
"tid: {0}", thread.GetID());
1983 thread.RequestStop();
1990 void *data,
size_t data_size,
2002 *(
unsigned int *)addr, data);
2013 LLDB_LOG(log,
"ptrace({0}, {1}, {2}, {3}, {4})={5:x}", req, pid, addr, data,
2031 if (type ==
"intel-pt") {
2032 if (Expected<TraceIntelPTStartRequest> request =
2033 json::parse<TraceIntelPTStartRequest>(json_request,
2034 "TraceIntelPTStartRequest")) {
2037 return request.takeError();
2044 if (request.
type ==
"intel-pt")
2050 if (type ==
"intel-pt")
2057 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.