ErrorCode PTrace::readBytes(ProcessThreadId const &ptid, Address const &address, void *buffer, size_t length, size_t *count, bool nullTerm) { pid_t pid; CHK(ptidToPid(ptid, pid)); bool foundNull = false; size_t nread = 0; uintptr_t base = address; uintptr_t *words = (uintptr_t *)buffer; if (length == 0 || buffer == nullptr) { if (count != nullptr) { *count = 0; } return kSuccess; } while (length > 0) { union { uintptr_t word; uint8_t bytes[sizeof(uintptr_t)]; } data; size_t ncopy = std::min(length, sizeof(uintptr_t)); errno = 0; if (ncopy < sizeof(uintptr_t)) { data.word = wrapPtrace(PTRACE_PEEKDATA, pid, base + nread, nullptr); if (errno == 0) { std::memcpy(words, data.bytes, ncopy); } } else { *words = wrapPtrace(PTRACE_PEEKDATA, pid, base + nread, nullptr); } if (errno != 0) break; if (nullTerm && strnlen((char *)words, ncopy) < ncopy) { foundNull = true; break; } length -= ncopy; nread += ncopy; words++; } if (count != nullptr) { *count = nread; } if (errno != 0) return Platform::TranslateError(); if (nullTerm && !foundNull) return kErrorNameTooLong; return kSuccess; }
ErrorCode PTrace::writeMemory(ProcessThreadId const &ptid, Address const &address, void const *buffer, size_t length, size_t *count) { pid_t pid; CHK(ptidToPid(ptid, pid)); uintptr_t base = address; struct ptrace_io_desc desc; if (length == 0 || buffer == nullptr) { if (count != nullptr) *count = 0; return kSuccess; } desc.piod_op = PIOD_WRITE_D; desc.piod_offs = (void *)base; desc.piod_addr = (void *)buffer; desc.piod_len = length; if (wrapPtrace(PT_IO, pid, &desc, nullptr) < 0) return Platform::TranslateError(); if (count != nullptr) *count = desc.piod_len; return kSuccess; }
ErrorCode PTrace::getSigInfo(ProcessThreadId const &ptid, siginfo_t &si) { pid_t pid; CHK(ptidToPid(ptid, pid)); if (wrapPtrace(PTRACE_GETSIGINFO, pid, nullptr, &si) < 0) return Platform::TranslateError(); return kSuccess; }
ErrorCode PTrace::getLwpInfo(ProcessThreadId const &ptid, struct ptrace_lwpinfo *lwpinfo) { pid_t pid; CHK(ptidToPid(ptid, pid)); if (wrapPtrace(PT_LWPINFO, pid, lwpinfo, sizeof(struct ptrace_lwpinfo)) < 0) return Platform::TranslateError(); return kSuccess; }
ErrorCode PTrace::getSigInfo(ProcessThreadId const &ptid, siginfo_t &si) { struct ptrace_lwpinfo lwpinfo; pid_t pid; CHK(ptidToPid(ptid, pid)); if (wrapPtrace(PT_LWPINFO, pid, &lwpinfo, sizeof lwpinfo) < 0) return Platform::TranslateError(); si = lwpinfo.pl_siginfo; return kSuccess; }
ErrorCode PTrace::writeMemory(ProcessThreadId const &ptid, Address const &address, void const *buffer, size_t length, size_t *count) { pid_t pid; CHK(ptidToPid(ptid, pid)); size_t nwritten = 0; uintptr_t base = address; uintptr_t const *words = (uintptr_t const *)buffer; if (length == 0 || buffer == nullptr) { if (count != nullptr) { *count = 0; } return kSuccess; } while (length > 0) { union { uintptr_t word; uint8_t bytes[sizeof(uintptr_t)]; } data; size_t ncopy = std::min(length, sizeof(uintptr_t)); errno = 0; if (ncopy < sizeof(uintptr_t)) { data.word = wrapPtrace(PTRACE_PEEKDATA, pid, base + nwritten, nullptr); if (errno == 0) { std::memcpy(data.bytes, words, ncopy); wrapPtrace(PTRACE_POKEDATA, pid, base + nwritten, data.word); } } else { wrapPtrace(PTRACE_POKEDATA, pid, base + nwritten, *words); } if (errno != 0) break; length -= ncopy; nwritten += ncopy; words++; } if (errno != 0) return Platform::TranslateError(); if (count != nullptr) { *count = nwritten; } return kSuccess; }
ErrorCode PTrace::wait(ProcessThreadId const &ptid, int *status) { pid_t pid; CHK(ptidToPid(ptid, pid)); int stat; pid_t ret; ret = waitpid(pid, &stat, __WALL); if (ret < 0) return kErrorProcessNotFound; DS2ASSERT(ret == pid); if (status != nullptr) { *status = stat; } return kSuccess; }