xref: /llvm-project/lldb/tools/debugserver/source/RNBRemote.h (revision 4551f53523074cd4e2f93a6f79313ca2cdcc40d2)
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     query_thread_extra_info,                       // '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 
GetContinueThread()158   nub_thread_t GetContinueThread() const { return m_continue_thread; }
159 
SetContinueThread(nub_thread_t tid)160   void SetContinueThread(nub_thread_t tid) { m_continue_thread = tid; }
161 
GetCurrentThread()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 
SetCurrentThread(nub_thread_t tid)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 *header, const void *buf,
257                                      size_t buf_len, const char *footer);
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 
Context()265   RNBContext &Context() { return m_ctx; }
Comm()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 
IsPlatformPacketPacket284     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     }
PacketPacket294     Packet()
295         : type(invalid_packet), normal(NULL), async(NULL), abbrev(),
296           printable_name() {}
297 
PacketPacket298     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 
DispatchQueueOffsetsDispatchQueueOffsets330     DispatchQueueOffsets() { Clear(); }
331 
ClearDispatchQueueOffsets332     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 
IsValidDispatchQueueOffsets352     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 ExtractThreadIDFromThreadSuffix(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