1 | |
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 | // Created by Greg Clayton on 12/12/07. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef LLDB_TOOLS_DEBUGSERVER_SOURCE_RNBREMOTE_H |
14 | #define LLDB_TOOLS_DEBUGSERVER_SOURCE_RNBREMOTE_H |
15 | |
16 | #include "DNB.h" |
17 | #include "PThreadMutex.h" |
18 | #include "RNBContext.h" |
19 | #include "RNBDefs.h" |
20 | #include "RNBSocket.h" |
21 | #include <deque> |
22 | #include <map> |
23 | #include <string> |
24 | #include <vector> |
25 | |
26 | class RNBSocket; |
27 | class RNBContext; |
28 | class PThreadEvents; |
29 | |
30 | enum event_loop_mode { debug_nub, gdb_remote_protocol, done }; |
31 | |
32 | enum class compression_types { zlib_deflate, lz4, lzma, lzfse, none }; |
33 | |
34 | class RNBRemote { |
35 | public: |
36 | // clang-format off |
37 | enum PacketEnum { |
38 | invalid_packet = 0, |
39 | ack, // '+' |
40 | nack, // '-' |
41 | halt, // ^C (async halt) |
42 | use_extended_mode, // '!' |
43 | why_halted, // '?' |
44 | set_argv, // 'A' |
45 | set_bp, // 'B' |
46 | cont, // 'c' |
47 | continue_with_sig, // 'C' |
48 | detach, // 'D' |
49 | read_general_regs, // 'g' |
50 | write_general_regs, // 'G' |
51 | set_thread, // 'H' |
52 | step_inferior_one_cycle, // 'i' |
53 | signal_and_step_inf_one_cycle, // 'I' |
54 | kill, // 'k' |
55 | read_memory, // 'm' |
56 | write_memory, // 'M' |
57 | read_register, // 'p' |
58 | write_register, // 'P' |
59 | restart, // 'R' |
60 | single_step, // 's' |
61 | single_step_with_sig, // 'S' |
62 | search_mem_backwards, // 't' |
63 | thread_alive_p, // 'T' |
64 | vattach, // 'vAttach;pid' |
65 | vattachwait, // 'vAttachWait:XX...' where XX is one or more hex encoded |
66 | // process name ASCII bytes |
67 | vattachorwait, // 'vAttachOrWait:XX...' where XX is one or more hex encoded |
68 | // process name ASCII bytes |
69 | vattachname, // 'vAttachName:XX...' where XX is one or more hex encoded |
70 | // process name ASCII bytes |
71 | vcont, // 'vCont' |
72 | vcont_list_actions, // 'vCont?' |
73 | read_data_from_memory, // 'x' |
74 | write_data_to_memory, // 'X' |
75 | insert_mem_bp, // 'Z0' |
76 | remove_mem_bp, // 'z0' |
77 | insert_hardware_bp, // 'Z1' |
78 | remove_hardware_bp, // 'z1' |
79 | insert_write_watch_bp, // 'Z2' |
80 | remove_write_watch_bp, // 'z2' |
81 | insert_read_watch_bp, // 'Z3' |
82 | remove_read_watch_bp, // 'z3' |
83 | insert_access_watch_bp, // 'Z4' |
84 | remove_access_watch_bp, // 'z4' |
85 | |
86 | query_monitor, // 'qRcmd' |
87 | query_current_thread_id, // 'qC' |
88 | query_get_pid, // 'qGetPid' |
89 | query_echo, // 'qEcho' |
90 | query_thread_ids_first, // 'qfThreadInfo' |
91 | query_thread_ids_subsequent, // 'qsThreadInfo' |
92 | , // 'qThreadExtraInfo' |
93 | query_thread_stop_info, // 'qThreadStopInfo' |
94 | query_image_offsets, // 'qOffsets' |
95 | query_symbol_lookup, // 'qSymbol' |
96 | query_launch_success, // 'qLaunchSuccess' |
97 | query_register_info, // 'qRegisterInfo' |
98 | query_shlib_notify_info_addr, // 'qShlibInfoAddr' |
99 | query_step_packet_supported, // 'qStepPacketSupported' |
100 | query_supported_features, // 'qSupported' |
101 | query_vattachorwait_supported, // 'qVAttachOrWaitSupported' |
102 | query_sync_thread_state_supported, // 'QSyncThreadState' |
103 | query_host_info, // 'qHostInfo' |
104 | query_gdb_server_version, // 'qGDBServerVersion' |
105 | query_process_info, // 'qProcessInfo' |
106 | json_query_thread_extended_info, // 'jThreadExtendedInfo' |
107 | json_query_get_loaded_dynamic_libraries_infos, // 'jGetLoadedDynamicLibrariesInfos' |
108 | json_query_threads_info, // 'jThreadsInfo' |
109 | json_query_get_shared_cache_info, // 'jGetSharedCacheInfo' |
110 | pass_signals_to_inferior, // 'QPassSignals' |
111 | start_noack_mode, // 'QStartNoAckMode' |
112 | prefix_reg_packets_with_tid, // 'QPrefixRegisterPacketsWithThreadID |
113 | set_logging_mode, // 'QSetLogging:' |
114 | set_ignored_exceptions, // 'QSetIgnoredExceptions' |
115 | set_max_packet_size, // 'QSetMaxPacketSize:' |
116 | set_max_payload_size, // 'QSetMaxPayloadSize:' |
117 | set_environment_variable, // 'QEnvironment:' |
118 | set_environment_variable_hex, // 'QEnvironmentHexEncoded:' |
119 | set_launch_arch, // 'QLaunchArch:' |
120 | set_disable_aslr, // 'QSetDisableASLR:' |
121 | set_stdin, // 'QSetSTDIN:' |
122 | set_stdout, // 'QSetSTDOUT:' |
123 | set_stderr, // 'QSetSTDERR:' |
124 | set_working_dir, // 'QSetWorkingDir:' |
125 | set_list_threads_in_stop_reply, // 'QListThreadsInStopReply:' |
126 | sync_thread_state, // 'QSyncThreadState:' |
127 | memory_region_info, // 'qMemoryRegionInfo:' |
128 | get_profile_data, // 'qGetProfileData' |
129 | set_enable_profiling, // 'QSetEnableAsyncProfiling' |
130 | enable_compression, // 'QEnableCompression:' |
131 | watchpoint_support_info, // 'qWatchpointSupportInfo:' |
132 | allocate_memory, // '_M' |
133 | deallocate_memory, // '_m' |
134 | set_process_event, // 'QSetProcessEvent:' |
135 | save_register_state, // '_g' |
136 | restore_register_state, // '_G' |
137 | speed_test, // 'qSpeedTest:' |
138 | set_detach_on_error, // 'QSetDetachOnError:' |
139 | query_transfer, // 'qXfer:' |
140 | json_query_dyld_process_state, // 'jGetDyldProcessState' |
141 | enable_error_strings, // 'QEnableErrorStrings' |
142 | unknown_type |
143 | }; |
144 | // clang-format on |
145 | |
146 | typedef rnb_err_t (RNBRemote::*HandlePacketCallback)(const char *p); |
147 | |
148 | RNBRemote(); |
149 | ~RNBRemote(); |
150 | |
151 | void Initialize(); |
152 | |
153 | bool InitializeRegisters(bool force = false); |
154 | |
155 | rnb_err_t HandleAsyncPacket(PacketEnum *type = NULL); |
156 | rnb_err_t HandleReceivedPacket(PacketEnum *type = NULL); |
157 | |
158 | nub_thread_t GetContinueThread() const { return m_continue_thread; } |
159 | |
160 | void SetContinueThread(nub_thread_t tid) { m_continue_thread = tid; } |
161 | |
162 | nub_thread_t GetCurrentThread() const { |
163 | if (m_thread == 0 || m_thread == (nub_thread_t)-1) |
164 | return DNBProcessGetCurrentThread(m_ctx.ProcessID()); |
165 | return m_thread; |
166 | } |
167 | |
168 | void SetCurrentThread(nub_thread_t tid) { |
169 | DNBProcessSetCurrentThread(m_ctx.ProcessID(), tid); |
170 | m_thread = tid; |
171 | } |
172 | |
173 | static void *ThreadFunctionReadRemoteData(void *arg); |
174 | void StartReadRemoteDataThread(); |
175 | void StopReadRemoteDataThread(); |
176 | |
177 | void NotifyThatProcessStopped(void); |
178 | |
179 | rnb_err_t HandlePacket_A(const char *p); |
180 | rnb_err_t HandlePacket_H(const char *p); |
181 | rnb_err_t HandlePacket_qC(const char *p); |
182 | rnb_err_t HandlePacket_qRcmd(const char *p); |
183 | rnb_err_t HandlePacket_qGetPid(const char *p); |
184 | rnb_err_t HandlePacket_qEcho(const char *p); |
185 | rnb_err_t HandlePacket_qLaunchSuccess(const char *p); |
186 | rnb_err_t HandlePacket_qRegisterInfo(const char *p); |
187 | rnb_err_t HandlePacket_qShlibInfoAddr(const char *p); |
188 | rnb_err_t HandlePacket_qStepPacketSupported(const char *p); |
189 | rnb_err_t HandlePacket_qVAttachOrWaitSupported(const char *p); |
190 | rnb_err_t HandlePacket_qSyncThreadStateSupported(const char *p); |
191 | rnb_err_t HandlePacket_qThreadInfo(const char *p); |
192 | rnb_err_t HandlePacket_jThreadExtendedInfo(const char *p); |
193 | rnb_err_t HandlePacket_jGetLoadedDynamicLibrariesInfos(const char *p); |
194 | rnb_err_t HandlePacket_jThreadsInfo(const char *p); |
195 | rnb_err_t HandlePacket_jGetSharedCacheInfo(const char *p); |
196 | rnb_err_t HandlePacket_qThreadExtraInfo(const char *p); |
197 | rnb_err_t HandlePacket_qThreadStopInfo(const char *p); |
198 | rnb_err_t HandlePacket_qHostInfo(const char *p); |
199 | rnb_err_t HandlePacket_qGDBServerVersion(const char *p); |
200 | rnb_err_t HandlePacket_qProcessInfo(const char *p); |
201 | rnb_err_t HandlePacket_qSymbol(const char *p); |
202 | rnb_err_t HandlePacket_QEnableErrorStrings(const char *p); |
203 | rnb_err_t HandlePacket_QStartNoAckMode(const char *p); |
204 | rnb_err_t HandlePacket_QThreadSuffixSupported(const char *p); |
205 | rnb_err_t HandlePacket_QSetLogging(const char *p); |
206 | rnb_err_t HandlePacket_QSetIgnoredExceptions(const char *p); |
207 | rnb_err_t HandlePacket_QSetDisableASLR(const char *p); |
208 | rnb_err_t HandlePacket_QSetSTDIO(const char *p); |
209 | rnb_err_t HandlePacket_QSetWorkingDir(const char *p); |
210 | rnb_err_t HandlePacket_QSetMaxPayloadSize(const char *p); |
211 | rnb_err_t HandlePacket_QSetMaxPacketSize(const char *p); |
212 | rnb_err_t HandlePacket_QEnvironment(const char *p); |
213 | rnb_err_t HandlePacket_QEnvironmentHexEncoded(const char *p); |
214 | rnb_err_t HandlePacket_QLaunchArch(const char *p); |
215 | rnb_err_t HandlePacket_QListThreadsInStopReply(const char *p); |
216 | rnb_err_t HandlePacket_QSyncThreadState(const char *p); |
217 | rnb_err_t HandlePacket_QPrefixRegisterPacketsWithThreadID(const char *p); |
218 | rnb_err_t HandlePacket_QSetProcessEvent(const char *p); |
219 | rnb_err_t HandlePacket_last_signal(const char *p); |
220 | rnb_err_t HandlePacket_m(const char *p); |
221 | rnb_err_t HandlePacket_M(const char *p); |
222 | rnb_err_t HandlePacket_x(const char *p); |
223 | rnb_err_t HandlePacket_X(const char *p); |
224 | rnb_err_t HandlePacket_g(const char *p); |
225 | rnb_err_t HandlePacket_G(const char *p); |
226 | rnb_err_t HandlePacket_z(const char *p); |
227 | rnb_err_t HandlePacket_T(const char *p); |
228 | rnb_err_t HandlePacket_p(const char *p); |
229 | rnb_err_t HandlePacket_P(const char *p); |
230 | rnb_err_t HandlePacket_c(const char *p); |
231 | rnb_err_t HandlePacket_C(const char *p); |
232 | rnb_err_t HandlePacket_D(const char *p); |
233 | rnb_err_t HandlePacket_k(const char *p); |
234 | rnb_err_t HandlePacket_s(const char *p); |
235 | rnb_err_t HandlePacket_S(const char *p); |
236 | rnb_err_t HandlePacket_qSupported(const char *p); |
237 | rnb_err_t HandlePacket_v(const char *p); |
238 | rnb_err_t HandlePacket_UNIMPLEMENTED(const char *p); |
239 | rnb_err_t HandlePacket_ILLFORMED(const char *file, int line, const char *p, |
240 | const char *description); |
241 | rnb_err_t HandlePacket_AllocateMemory(const char *p); |
242 | rnb_err_t HandlePacket_DeallocateMemory(const char *p); |
243 | rnb_err_t HandlePacket_SaveRegisterState(const char *p); |
244 | rnb_err_t HandlePacket_RestoreRegisterState(const char *p); |
245 | rnb_err_t HandlePacket_MemoryRegionInfo(const char *p); |
246 | rnb_err_t HandlePacket_GetProfileData(const char *p); |
247 | rnb_err_t HandlePacket_SetEnableAsyncProfiling(const char *p); |
248 | rnb_err_t HandlePacket_QEnableCompression(const char *p); |
249 | rnb_err_t HandlePacket_WatchpointSupportInfo(const char *p); |
250 | rnb_err_t HandlePacket_qSpeedTest(const char *p); |
251 | rnb_err_t HandlePacket_qXfer(const char *p); |
252 | rnb_err_t HandlePacket_stop_process(const char *p); |
253 | rnb_err_t HandlePacket_QSetDetachOnError(const char *p); |
254 | rnb_err_t HandlePacket_jGetDyldProcessState(const char *p); |
255 | rnb_err_t SendStopReplyPacketForThread(nub_thread_t tid); |
256 | rnb_err_t SendHexEncodedBytePacket(const char *, const void *buf, |
257 | size_t buf_len, const char *); |
258 | rnb_err_t SendSTDOUTPacket(char *buf, nub_size_t buf_size); |
259 | rnb_err_t SendSTDERRPacket(char *buf, nub_size_t buf_size); |
260 | void FlushSTDIO(); |
261 | void SendAsyncProfileData(); |
262 | rnb_err_t SendAsyncProfileDataPacket(char *buf, nub_size_t buf_size); |
263 | rnb_err_t SendAsyncJSONPacket(const JSONGenerator::Dictionary &dictionary); |
264 | |
265 | RNBContext &Context() { return m_ctx; } |
266 | RNBSocket &Comm() { return m_comm; } |
267 | |
268 | private: |
269 | RNBRemote(const RNBRemote &) = delete; |
270 | |
271 | protected: |
272 | rnb_err_t GetCommData(); |
273 | void CommDataReceived(const std::string &data); |
274 | struct Packet { |
275 | typedef std::vector<Packet> collection; |
276 | typedef collection::iterator iterator; |
277 | typedef collection::const_iterator const_iterator; |
278 | PacketEnum type; |
279 | HandlePacketCallback normal; // Function to call when inferior is halted |
280 | HandlePacketCallback async; // Function to call when inferior is running |
281 | std::string abbrev; |
282 | std::string printable_name; |
283 | |
284 | bool IsPlatformPacket() const { |
285 | switch (type) { |
286 | case set_logging_mode: |
287 | case query_host_info: |
288 | return true; |
289 | default: |
290 | break; |
291 | } |
292 | return false; |
293 | } |
294 | Packet() |
295 | : type(invalid_packet), normal(NULL), async(NULL), abbrev(), |
296 | printable_name() {} |
297 | |
298 | Packet(PacketEnum in_type, HandlePacketCallback in_normal, |
299 | HandlePacketCallback in_async, const char *in_abbrev, |
300 | const char *in_printable_name) |
301 | : type(in_type), normal(in_normal), async(in_async), abbrev(in_abbrev), |
302 | printable_name(in_printable_name) {} |
303 | }; |
304 | |
305 | struct DispatchQueueOffsets { |
306 | uint16_t dqo_version; |
307 | uint16_t dqo_label; |
308 | uint16_t dqo_label_size; |
309 | uint16_t dqo_flags; |
310 | uint16_t dqo_flags_size; |
311 | uint16_t dqo_serialnum; |
312 | uint16_t dqo_serialnum_size; |
313 | uint16_t dqo_width; |
314 | uint16_t dqo_width_size; |
315 | uint16_t dqo_running; |
316 | uint16_t dqo_running_size; |
317 | uint16_t dqo_suspend_cnt; // version 5 and later, starting with Mac OS X |
318 | // 10.10/iOS 8 |
319 | uint16_t dqo_suspend_cnt_size; // version 5 and later, starting with Mac OS |
320 | // X 10.10/iOS 8 |
321 | uint16_t dqo_target_queue; // version 5 and later, starting with Mac OS X |
322 | // 10.10/iOS 8 |
323 | uint16_t dqo_target_queue_size; // version 5 and later, starting with Mac OS |
324 | // X 10.10/iOS 8 |
325 | uint16_t |
326 | dqo_priority; // version 5 and later, starting with Mac OS X 10.10/iOS 8 |
327 | uint16_t dqo_priority_size; // version 5 and later, starting with Mac OS X |
328 | // 10.10/iOS 8 |
329 | |
330 | DispatchQueueOffsets() { Clear(); } |
331 | |
332 | void Clear() { |
333 | dqo_version = UINT16_MAX; |
334 | dqo_label = UINT16_MAX; |
335 | dqo_label_size = UINT16_MAX; |
336 | dqo_flags = UINT16_MAX; |
337 | dqo_flags_size = UINT16_MAX; |
338 | dqo_serialnum = UINT16_MAX; |
339 | dqo_serialnum_size = UINT16_MAX; |
340 | dqo_width = UINT16_MAX; |
341 | dqo_width_size = UINT16_MAX; |
342 | dqo_running = UINT16_MAX; |
343 | dqo_running_size = UINT16_MAX; |
344 | dqo_suspend_cnt = UINT16_MAX; |
345 | dqo_suspend_cnt_size = UINT16_MAX; |
346 | dqo_target_queue = UINT16_MAX; |
347 | dqo_target_queue_size = UINT16_MAX; |
348 | dqo_priority = UINT16_MAX; |
349 | dqo_priority_size = UINT16_MAX; |
350 | } |
351 | |
352 | bool IsValid() const { return dqo_version != UINT16_MAX; } |
353 | |
354 | void GetThreadQueueInfo(nub_process_t pid, nub_addr_t dispatch_qaddr, |
355 | nub_addr_t &dispatch_queue_t, |
356 | std::string &queue_name, uint64_t &queue_width, |
357 | uint64_t &queue_serialnum) const; |
358 | }; |
359 | |
360 | rnb_err_t GetPacket(std::string &packet_data, RNBRemote::Packet &packet_info, |
361 | bool wait); |
362 | rnb_err_t SendPacket(const std::string &); |
363 | rnb_err_t SendErrorPacket(std::string errcode, |
364 | const std::string &errmsg = "" ); |
365 | std::string CompressString(const std::string &); |
366 | |
367 | void CreatePacketTable(); |
368 | rnb_err_t GetPacketPayload(std::string &); |
369 | |
370 | nub_thread_t (const char *p); |
371 | |
372 | void EnableCompressionNextSendPacket(compression_types); |
373 | |
374 | compression_types GetCompressionType(); |
375 | |
376 | const DispatchQueueOffsets *GetDispatchQueueOffsets(); |
377 | |
378 | JSONGenerator::ObjectSP |
379 | GetJSONThreadsInfo(bool threads_with_valid_stop_info_only); |
380 | |
381 | RNBContext m_ctx; // process context |
382 | RNBSocket m_comm; // communication port |
383 | std::string m_arch; |
384 | nub_thread_t m_continue_thread; // thread to continue; 0 for any, -1 for all |
385 | nub_thread_t m_thread; // thread for other ops; 0 for any, -1 for all |
386 | PThreadMutex m_mutex; // Mutex that protects |
387 | DispatchQueueOffsets m_dispatch_queue_offsets; |
388 | nub_addr_t m_dispatch_queue_offsets_addr; |
389 | uint32_t m_qSymbol_index; |
390 | uint32_t m_packets_recvd; |
391 | Packet::collection m_packets; |
392 | std::deque<std::string> m_rx_packets; |
393 | std::string m_rx_partial_data; // For packets that may come in more than one |
394 | // batch, anything left over can be left here |
395 | pthread_t m_rx_pthread; |
396 | uint32_t |
397 | m_max_payload_size; // the maximum sized payload we should send to gdb |
398 | bool m_extended_mode; // are we in extended mode? |
399 | bool m_noack_mode; // are we in no-ack mode? |
400 | bool m_thread_suffix_supported; // Set to true if the 'p', 'P', 'g', and 'G' |
401 | // packets should be prefixed with the thread |
402 | // ID and colon: |
403 | // "$pRR;thread:TTTT;" instead of "$pRR" |
404 | // "$PRR=VVVVVVVV;thread:TTTT;" instead of "$PRR=VVVVVVVV" |
405 | // "$g;thread:TTTT" instead of "$g" |
406 | // "$GVVVVVVVVVVVVVV;thread:TTTT;#00 instead of "$GVVVVVVVVVVVVVV" |
407 | bool m_list_threads_in_stop_reply; |
408 | |
409 | size_t m_compression_minsize; // only packets larger than this size will be |
410 | // compressed |
411 | bool m_enable_compression_next_send_packet; |
412 | |
413 | compression_types m_compression_mode; |
414 | |
415 | bool m_enable_error_strings; // Whether we can append asciihex error strings |
416 | // after Exx error replies |
417 | }; |
418 | |
419 | /* We translate the /usr/include/mach/exception_types.h exception types |
420 | (e.g. EXC_BAD_ACCESS) to the fake BSD signal numbers that gdb uses |
421 | in include/gdb/signals.h (e.g. TARGET_EXC_BAD_ACCESS). These hard |
422 | coded values for TARGET_EXC_BAD_ACCESS et al must match the gdb |
423 | values in its include/gdb/signals.h. */ |
424 | |
425 | #define TARGET_EXC_BAD_ACCESS 0x91 |
426 | #define TARGET_EXC_BAD_INSTRUCTION 0x92 |
427 | #define TARGET_EXC_ARITHMETIC 0x93 |
428 | #define TARGET_EXC_EMULATION 0x94 |
429 | #define TARGET_EXC_SOFTWARE 0x95 |
430 | #define TARGET_EXC_BREAKPOINT 0x96 |
431 | |
432 | /* Generally speaking, you can't assume gdb can receive more than 399 bytes |
433 | at a time with a random gdb. This bufsize constant is only specifying |
434 | how many bytes gdb can *receive* from debugserver -- it tells us nothing |
435 | about how many bytes gdb might try to send in a single packet. */ |
436 | #define DEFAULT_GDB_REMOTE_PROTOCOL_BUFSIZE 399 |
437 | |
438 | #endif // LLDB_TOOLS_DEBUGSERVER_SOURCE_RNBREMOTE_H |
439 | |