DebugServer2
Loading...
Searching...
No Matches
PTrace.h
1//
2// Copyright (c) 2014-present, Facebook, Inc.
3// All rights reserved.
4//
5// This source code is licensed under the University of Illinois/NCSA Open
6// Source License found in the LICENSE file in the root directory of this
7// source tree. An additional grant of patent rights can be found in the
8// PATENTS file in the same directory.
9//
10
11#pragma once
12
13#include "DebugServer2/Architecture/CPUState.h"
14#include "DebugServer2/Utils/Log.h"
15#include "DebugServer2/Utils/Stringify.h"
16
17#include <cerrno>
18#include <csignal>
19// clang-format off
20#include <sys/types.h>
21#include <sys/ptrace.h>
22// clang-format on
23
24namespace ds2 {
25namespace Host {
26namespace POSIX {
27
28class PTrace {
29public:
30 virtual ~PTrace() = default;
31
32public:
33 virtual ErrorCode wait(ProcessThreadId const &ptid, int *status = nullptr);
34
35public:
36 virtual ErrorCode traceMe(bool disableASLR);
37 virtual ErrorCode traceThat(ProcessId pid) = 0;
38
39public:
40 virtual ErrorCode attach(ProcessId pid);
41 virtual ErrorCode detach(ProcessId pid);
42
43public:
44 virtual ErrorCode kill(ProcessThreadId const &ptid, int signal) = 0;
45
46public:
47 virtual ErrorCode readString(ProcessThreadId const &ptid,
48 Address const &address, std::string &str,
49 size_t length, size_t *nread = nullptr) = 0;
50 virtual ErrorCode readMemory(ProcessThreadId const &ptid,
51 Address const &address, void *buffer,
52 size_t length, size_t *nread = nullptr) = 0;
53 virtual ErrorCode writeMemory(ProcessThreadId const &ptid,
54 Address const &address, void const *buffer,
55 size_t length, size_t *nwritten = nullptr) = 0;
56
57public:
58 virtual ErrorCode readCPUState(ProcessThreadId const &ptid,
59 ProcessInfo const &info,
60 Architecture::CPUState &state) = 0;
61 virtual ErrorCode writeCPUState(ProcessThreadId const &ptid,
62 ProcessInfo const &info,
63 Architecture::CPUState const &state) = 0;
64
65public:
66 virtual ErrorCode suspend(ProcessThreadId const &ptid);
67
68private:
69 ErrorCode doStepResume(bool stepping, ProcessThreadId const &ptid, int signal,
70 Address const &address);
71
72public:
73 virtual ErrorCode step(ProcessThreadId const &ptid, ProcessInfo const &pinfo,
74 int signal = 0, Address const &address = Address());
75 virtual ErrorCode resume(ProcessThreadId const &ptid,
76 ProcessInfo const &pinfo, int signal = 0,
77 Address const &address = Address());
78
79public:
80 virtual ErrorCode getSigInfo(ProcessThreadId const &ptid, siginfo_t &si) = 0;
81
82public:
83 virtual ErrorCode execute(ProcessThreadId const &ptid,
84 ProcessInfo const &pinfo, void const *code,
85 size_t length, uint64_t &result);
86
87#if defined(OS_LINUX)
88#if defined(ARCH_ARM) || defined(ARCH_ARM64)
89public:
90 virtual int getMaxHardwareBreakpoints(ProcessThreadId const &ptid) = 0;
91 virtual int getMaxHardwareWatchpoints(ProcessThreadId const &ptid) = 0;
92#endif
93
94#if defined(ARCH_ARM)
95public:
96 virtual int getMaxWatchpointSize(ProcessThreadId const &ptid) = 0;
97
98public:
99 virtual ErrorCode writeHardwareBreakpoint(ProcessThreadId const &ptid,
100 uint32_t addr, uint32_t ctrl,
101 size_t idx) = 0;
102 virtual ErrorCode writeHardwareWatchpoint(ProcessThreadId const &ptid,
103 uint32_t addr, uint32_t ctrl,
104 size_t idx) = 0;
105#endif // ARCH
106#endif // OS_LINUX
107
108protected:
109 template <typename CommandType, typename AddrType, typename DataType>
110 long wrapPtrace(CommandType request, pid_t pid, AddrType addr, DataType data,
111 int retries = 3) {
112#if defined(OS_LINUX)
113// The android toolchain declares ptrace() with an int command.
114#if defined(HAVE_ENUM_PTRACE_REQUEST)
115 typedef enum __ptrace_request PTraceRequestType;
116#else
117 typedef int PTraceRequestType;
118#endif
119 typedef void *PTraceAddrType;
120 typedef void *PTraceDataType;
121#elif defined(OS_FREEBSD) || defined(OS_DARWIN)
122 typedef int PTraceRequestType;
123 typedef caddr_t PTraceAddrType;
124 typedef int PTraceDataType;
125#endif
126 // ptrace return types vary across systems. Avoid truncating data.
127 decltype(ptrace((PTraceRequestType)0, 0, 0, 0)) ret = 0;
128
130
131 do {
132 if (ret < 0) {
133 retries--;
134 DS2LOG(Warning, "ptrace command %s on pid %d returned %s, retrying",
135 Stringify::PTraceCommand(request), pid, Stringify::Errno(errno));
136 }
137
138 // Clear errno so we can check it afterwards. Just checking the return
139 // value of ptrace won't work because PTRACE_PEEK* commands return the
140 // value read instead of 0 or -1.
141 errno = 0;
142
143 ret = ::ptrace(static_cast<PTraceRequestType>(request), pid,
144 (PTraceAddrType)(uintptr_t)addr,
145 (PTraceDataType)(uintptr_t)data);
146 } while (ret < 0 && (errno == EAGAIN || errno == EBUSY) && retries > 0);
147
148 if (errno != 0) {
149 DS2LOG(Debug, "ran ptrace command %s on pid %d, returned %s",
150 Stringify::PTraceCommand(request), pid, Stringify::Errno(errno));
151 }
152
153 return ret;
154 }
155
156 virtual ErrorCode ptidToPid(ProcessThreadId const &ptid, pid_t &pid);
157};
158} // namespace POSIX
159} // namespace Host
160} // namespace ds2
Definition Types.h:95
Definition PTrace.h:28
Definition Stringify.h:21
Definition Types.h:263
Definition Types.h:57