1 | //===-- CommunicationKDP.h --------------------------------------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #ifndef LLDB_SOURCE_PLUGINS_PROCESS_MACOSX_KERNEL_COMMUNICATIONKDP_H |
10 | #define LLDB_SOURCE_PLUGINS_PROCESS_MACOSX_KERNEL_COMMUNICATIONKDP_H |
11 | |
12 | #include <list> |
13 | #include <mutex> |
14 | #include <string> |
15 | |
16 | #include "lldb/Core/Communication.h" |
17 | #include "lldb/Utility/Listener.h" |
18 | #include "lldb/Utility/Predicate.h" |
19 | #include "lldb/Utility/StreamBuffer.h" |
20 | #include "lldb/lldb-private.h" |
21 | |
22 | class CommunicationKDP : public lldb_private::Communication { |
23 | public: |
24 | const static uint32_t kMaxPacketSize = 1200; |
25 | const static uint32_t kMaxDataSize = 1024; |
26 | typedef lldb_private::StreamBuffer<4096> PacketStreamType; |
27 | enum CommandType { |
28 | KDP_CONNECT = 0u, |
29 | KDP_DISCONNECT, |
30 | KDP_HOSTINFO, |
31 | KDP_VERSION, |
32 | KDP_MAXBYTES, |
33 | KDP_READMEM, |
34 | KDP_WRITEMEM, |
35 | KDP_READREGS, |
36 | KDP_WRITEREGS, |
37 | KDP_LOAD, |
38 | KDP_IMAGEPATH, |
39 | KDP_SUSPEND, |
40 | KDP_RESUMECPUS, |
41 | KDP_EXCEPTION, |
42 | KDP_TERMINATION, |
43 | KDP_BREAKPOINT_SET, |
44 | KDP_BREAKPOINT_REMOVE, |
45 | KDP_REGIONS, |
46 | KDP_REATTACH, |
47 | KDP_HOSTREBOOT, |
48 | KDP_READMEM64, |
49 | KDP_WRITEMEM64, |
50 | KDP_BREAKPOINT_SET64, |
51 | KDP_BREAKPOINT_REMOVE64, |
52 | KDP_KERNELVERSION, |
53 | KDP_READPHYSMEM64, |
54 | KDP_WRITEPHYSMEM64, |
55 | KDP_READIOPORT, |
56 | KDP_WRITEIOPORT, |
57 | KDP_READMSR64, |
58 | KDP_WRITEMSR64, |
59 | KDP_DUMPINFO |
60 | }; |
61 | |
62 | enum { KDP_FEATURE_BP = (1u << 0) }; |
63 | |
64 | enum KDPError { |
65 | KDP_PROTERR_SUCCESS = 0, |
66 | KDP_PROTERR_ALREADY_CONNECTED, |
67 | KDP_PROTERR_BAD_NBYTES, |
68 | KDP_PROTERR_BADFLAVOR |
69 | }; |
70 | |
71 | enum PacketType { |
72 | ePacketTypeRequest = 0x00u, |
73 | ePacketTypeReply = 0x80u, |
74 | ePacketTypeMask = 0x80u, |
75 | eCommandTypeMask = 0x7fu |
76 | }; |
77 | // Constructors and Destructors |
78 | CommunicationKDP(const char *comm_name); |
79 | |
80 | ~CommunicationKDP() override; |
81 | |
82 | bool SendRequestPacket(const PacketStreamType &request_packet); |
83 | |
84 | // Wait for a packet within 'nsec' seconds |
85 | size_t |
86 | (lldb_private::DataExtractor &response, |
87 | uint32_t usec); |
88 | |
89 | bool GetSequenceMutex(std::unique_lock<std::recursive_mutex> &lock); |
90 | |
91 | bool (const uint8_t *src, size_t src_len, |
92 | lldb_private::DataExtractor &packet); |
93 | bool IsRunning() const { return m_is_running.GetValue(); } |
94 | |
95 | // Set the global packet timeout. |
96 | // |
97 | // For clients, this is the timeout that gets used when sending |
98 | // packets and waiting for responses. For servers, this might not |
99 | // get used, and if it doesn't this should be moved to the |
100 | // CommunicationKDPClient. |
101 | std::chrono::seconds SetPacketTimeout(std::chrono::seconds packet_timeout) { |
102 | const auto old_packet_timeout = m_packet_timeout; |
103 | m_packet_timeout = packet_timeout; |
104 | return old_packet_timeout; |
105 | } |
106 | |
107 | std::chrono::seconds GetPacketTimeout() const { return m_packet_timeout; } |
108 | |
109 | // Public Request Packets |
110 | bool SendRequestConnect(uint16_t reply_port, uint16_t exc_port, |
111 | const char *greeting); |
112 | |
113 | bool SendRequestReattach(uint16_t reply_port); |
114 | |
115 | bool SendRequestDisconnect(); |
116 | |
117 | uint32_t SendRequestReadMemory(lldb::addr_t addr, void *dst, |
118 | uint32_t dst_size, |
119 | lldb_private::Status &error); |
120 | |
121 | uint32_t SendRequestWriteMemory(lldb::addr_t addr, const void *src, |
122 | uint32_t src_len, |
123 | lldb_private::Status &error); |
124 | |
125 | bool (uint8_t command_byte, const void *src, uint32_t src_len, |
126 | lldb_private::DataExtractor &reply, |
127 | lldb_private::Status &error); |
128 | |
129 | uint32_t SendRequestReadRegisters(uint32_t cpu, uint32_t flavor, void *dst, |
130 | uint32_t dst_size, |
131 | lldb_private::Status &error); |
132 | |
133 | uint32_t SendRequestWriteRegisters(uint32_t cpu, uint32_t flavor, |
134 | const void *src, uint32_t src_size, |
135 | lldb_private::Status &error); |
136 | |
137 | const char *GetKernelVersion(); |
138 | |
139 | // Disable KDP_IMAGEPATH for now, it seems to hang the KDP connection... |
140 | // const char * |
141 | // GetImagePath (); |
142 | |
143 | uint32_t GetVersion(); |
144 | |
145 | uint32_t GetFeatureFlags(); |
146 | |
147 | bool LocalBreakpointsAreSupported() { |
148 | return (GetFeatureFlags() & KDP_FEATURE_BP) != 0; |
149 | } |
150 | |
151 | uint32_t GetCPUMask(); |
152 | |
153 | uint32_t GetCPUType(); |
154 | |
155 | uint32_t GetCPUSubtype(); |
156 | |
157 | lldb_private::UUID GetUUID(); |
158 | |
159 | bool RemoteIsEFI(); |
160 | |
161 | bool RemoteIsDarwinKernel(); |
162 | |
163 | lldb::addr_t GetLoadAddress(); |
164 | |
165 | bool SendRequestResume(); |
166 | |
167 | bool SendRequestSuspend(); |
168 | |
169 | bool SendRequestBreakpoint(bool set, lldb::addr_t addr); |
170 | |
171 | protected: |
172 | bool SendRequestPacketNoLock(const PacketStreamType &request_packet); |
173 | |
174 | size_t ( |
175 | lldb_private::DataExtractor &response, uint32_t timeout_usec); |
176 | |
177 | bool WaitForNotRunningPrivate(const std::chrono::microseconds &timeout); |
178 | |
179 | void MakeRequestPacketHeader(CommandType request_type, |
180 | PacketStreamType &request_packet, |
181 | uint16_t request_length); |
182 | |
183 | // Protected Request Packets (use public accessors which will cache |
184 | // results. |
185 | bool SendRequestVersion(); |
186 | |
187 | bool SendRequestHostInfo(); |
188 | |
189 | bool SendRequestKernelVersion(); |
190 | |
191 | // Disable KDP_IMAGEPATH for now, it seems to hang the KDP connection... |
192 | // bool |
193 | // SendRequestImagePath (); |
194 | |
195 | void DumpPacket(lldb_private::Stream &s, const void *data, uint32_t data_len); |
196 | |
197 | void (lldb_private::Stream &s, |
198 | const lldb_private::DataExtractor &); |
199 | |
200 | bool VersionIsValid() const { return m_kdp_version_version != 0; } |
201 | |
202 | bool HostInfoIsValid() const { return m_kdp_hostinfo_cpu_type != 0; } |
203 | |
204 | bool (uint8_t first_packet_byte) const { |
205 | // TODO: handle big endian... |
206 | return (first_packet_byte & ePacketTypeMask) != 0; |
207 | } |
208 | |
209 | CommandType ExtractCommand(uint8_t first_packet_byte) const { |
210 | // TODO: handle big endian... |
211 | return (CommandType)(first_packet_byte & eCommandTypeMask); |
212 | } |
213 | |
214 | static const char *GetCommandAsCString(uint8_t command); |
215 | |
216 | void ClearKDPSettings(); |
217 | |
218 | bool SendRequestAndGetReply(const CommandType command, |
219 | const PacketStreamType &request_packet, |
220 | lldb_private::DataExtractor &reply_packet); |
221 | // Classes that inherit from CommunicationKDP can see and modify these |
222 | uint32_t m_addr_byte_size; |
223 | lldb::ByteOrder m_byte_order; |
224 | std::string m_bytes; |
225 | std::recursive_mutex m_bytes_mutex; |
226 | std::chrono::seconds m_packet_timeout; |
227 | std::recursive_mutex m_sequence_mutex; // Restrict access to sending/receiving |
228 | // packets to a single thread at a time |
229 | lldb_private::Predicate<bool> m_is_running; |
230 | uint32_t m_session_key; |
231 | uint8_t m_request_sequence_id; |
232 | uint8_t m_exception_sequence_id; |
233 | uint32_t m_kdp_version_version; |
234 | uint32_t m_kdp_version_feature; |
235 | uint32_t m_kdp_hostinfo_cpu_mask; |
236 | uint32_t m_kdp_hostinfo_cpu_type; |
237 | uint32_t m_kdp_hostinfo_cpu_subtype; |
238 | std::string m_kernel_version; |
239 | // std::string m_image_path; // Disable KDP_IMAGEPATH for now, it seems to |
240 | // hang the KDP connection... |
241 | lldb::addr_t m_last_read_memory_addr; // Last memory read address for logging |
242 | private: |
243 | // For CommunicationKDP only |
244 | CommunicationKDP(const CommunicationKDP &) = delete; |
245 | const CommunicationKDP &operator=(const CommunicationKDP &) = delete; |
246 | }; |
247 | |
248 | #endif // LLDB_SOURCE_PLUGINS_PROCESS_MACOSX_KERNEL_COMMUNICATIONKDP_H |
249 | |