1 //===-- RNBRemote.cpp -------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  Created by Greg Clayton on 12/12/07.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "RNBRemote.h"
15 
16 #include <errno.h>
17 #include <mach-o/loader.h>
18 #include <mach/exception_types.h>
19 #include <signal.h>
20 #include <sys/stat.h>
21 #include <sys/sysctl.h>
22 #include <unistd.h>
23 
24 #if defined(__APPLE__)
25 #include <pthread.h>
26 #include <sched.h>
27 #endif
28 
29 #include "DNB.h"
30 #include "DNBDataRef.h"
31 #include "DNBLog.h"
32 #include "DNBThreadResumeActions.h"
33 #include "DarwinLogCollector.h"
34 #include "DarwinLogEvent.h"
35 #include "JSON.h"
36 #include "JSONGenerator.h"
37 #include "JSONGenerator.h"
38 #include "MacOSX/Genealogy.h"
39 #include "OsLogger.h"
40 #include "RNBContext.h"
41 #include "RNBServices.h"
42 #include "RNBSocket.h"
43 #include "StdStringExtractor.h"
44 
45 #if defined(HAVE_LIBCOMPRESSION)
46 #include <compression.h>
47 #endif
48 
49 #if defined(HAVE_LIBZ)
50 #include <zlib.h>
51 #endif
52 
53 #include <TargetConditionals.h> // for endianness predefines
54 #include <iomanip>
55 #include <sstream>
56 #include <unordered_set>
57 
58 //----------------------------------------------------------------------
59 // constants
60 //----------------------------------------------------------------------
61 
62 static const std::string OS_LOG_EVENTS_KEY_NAME("events");
63 static const std::string JSON_ASYNC_TYPE_KEY_NAME("type");
64 static const DarwinLogEventVector::size_type DARWIN_LOG_MAX_EVENTS_PER_PACKET =
65     10;
66 
67 //----------------------------------------------------------------------
68 // std::iostream formatting macros
69 //----------------------------------------------------------------------
70 #define RAW_HEXBASE std::setfill('0') << std::hex << std::right
71 #define HEXBASE '0' << 'x' << RAW_HEXBASE
72 #define RAWHEX8(x) RAW_HEXBASE << std::setw(2) << ((uint32_t)((uint8_t)x))
73 #define RAWHEX16 RAW_HEXBASE << std::setw(4)
74 #define RAWHEX32 RAW_HEXBASE << std::setw(8)
75 #define RAWHEX64 RAW_HEXBASE << std::setw(16)
76 #define HEX8(x) HEXBASE << std::setw(2) << ((uint32_t)(x))
77 #define HEX16 HEXBASE << std::setw(4)
78 #define HEX32 HEXBASE << std::setw(8)
79 #define HEX64 HEXBASE << std::setw(16)
80 #define RAW_HEX(x) RAW_HEXBASE << std::setw(sizeof(x) * 2) << (x)
81 #define HEX(x) HEXBASE << std::setw(sizeof(x) * 2) << (x)
82 #define RAWHEX_SIZE(x, sz) RAW_HEXBASE << std::setw((sz)) << (x)
83 #define HEX_SIZE(x, sz) HEXBASE << std::setw((sz)) << (x)
84 #define STRING_WIDTH(w) std::setfill(' ') << std::setw(w)
85 #define LEFT_STRING_WIDTH(s, w)                                                \
86   std::left << std::setfill(' ') << std::setw(w) << (s) << std::right
87 #define DECIMAL std::dec << std::setfill(' ')
88 #define DECIMAL_WIDTH(w) DECIMAL << std::setw(w)
89 #define FLOAT(n, d)                                                            \
90   std::setfill(' ') << std::setw((n) + (d) + 1) << std::setprecision(d)        \
91                     << std::showpoint << std::fixed
92 #define INDENT_WITH_SPACES(iword_idx)                                          \
93   std::setfill(' ') << std::setw((iword_idx)) << ""
94 #define INDENT_WITH_TABS(iword_idx)                                            \
95   std::setfill('\t') << std::setw((iword_idx)) << ""
96 // Class to handle communications via gdb remote protocol.
97 
98 //----------------------------------------------------------------------
99 // Prototypes
100 //----------------------------------------------------------------------
101 
102 static std::string binary_encode_string(const std::string &s);
103 
104 //----------------------------------------------------------------------
105 // Decode a single hex character and return the hex value as a number or
106 // -1 if "ch" is not a hex character.
107 //----------------------------------------------------------------------
108 static inline int xdigit_to_sint(char ch) {
109   if (ch >= 'a' && ch <= 'f')
110     return 10 + ch - 'a';
111   if (ch >= 'A' && ch <= 'F')
112     return 10 + ch - 'A';
113   if (ch >= '0' && ch <= '9')
114     return ch - '0';
115   return -1;
116 }
117 
118 //----------------------------------------------------------------------
119 // Decode a single hex ASCII byte. Return -1 on failure, a value 0-255
120 // on success.
121 //----------------------------------------------------------------------
122 static inline int decoded_hex_ascii_char(const char *p) {
123   const int hi_nibble = xdigit_to_sint(p[0]);
124   if (hi_nibble == -1)
125     return -1;
126   const int lo_nibble = xdigit_to_sint(p[1]);
127   if (lo_nibble == -1)
128     return -1;
129   return (uint8_t)((hi_nibble << 4) + lo_nibble);
130 }
131 
132 //----------------------------------------------------------------------
133 // Decode a hex ASCII string back into a string
134 //----------------------------------------------------------------------
135 static std::string decode_hex_ascii_string(const char *p,
136                                            uint32_t max_length = UINT32_MAX) {
137   std::string arg;
138   if (p) {
139     for (const char *c = p; ((c - p) / 2) < max_length; c += 2) {
140       int ch = decoded_hex_ascii_char(c);
141       if (ch == -1)
142         break;
143       else
144         arg.push_back(ch);
145     }
146   }
147   return arg;
148 }
149 
150 uint64_t decode_uint64(const char *p, int base, char **end = nullptr,
151                        uint64_t fail_value = 0) {
152   nub_addr_t addr = strtoull(p, end, 16);
153   if (addr == 0 && errno != 0)
154     return fail_value;
155   return addr;
156 }
157 
158 extern void ASLLogCallback(void *baton, uint32_t flags, const char *format,
159                            va_list args);
160 
161 #if defined(__APPLE__) &&                                                      \
162     (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101000)
163 // from System.framework/Versions/B/PrivateHeaders/sys/codesign.h
164 extern "C" {
165 #define CS_OPS_STATUS 0       /* return status */
166 #define CS_RESTRICT 0x0000800 /* tell dyld to treat restricted */
167 int csops(pid_t pid, unsigned int ops, void *useraddr, size_t usersize);
168 
169 // from rootless.h
170 bool rootless_allows_task_for_pid(pid_t pid);
171 
172 // from sys/csr.h
173 typedef uint32_t csr_config_t;
174 #define CSR_ALLOW_TASK_FOR_PID (1 << 2)
175 int csr_check(csr_config_t mask);
176 }
177 #endif
178 
179 RNBRemote::RNBRemote()
180     : m_ctx(), m_comm(), m_arch(), m_continue_thread(-1), m_thread(-1),
181       m_mutex(), m_dispatch_queue_offsets(),
182       m_dispatch_queue_offsets_addr(INVALID_NUB_ADDRESS),
183       m_qSymbol_index(UINT32_MAX), m_packets_recvd(0), m_packets(),
184       m_rx_packets(), m_rx_partial_data(), m_rx_pthread(0),
185       m_max_payload_size(DEFAULT_GDB_REMOTE_PROTOCOL_BUFSIZE - 4),
186       m_extended_mode(false), m_noack_mode(false),
187       m_thread_suffix_supported(false), m_list_threads_in_stop_reply(false),
188       m_compression_minsize(384), m_enable_compression_next_send_packet(false),
189       m_compression_mode(compression_types::none) {
190   DNBLogThreadedIf(LOG_RNB_REMOTE, "%s", __PRETTY_FUNCTION__);
191   CreatePacketTable();
192 }
193 
194 RNBRemote::~RNBRemote() {
195   DNBLogThreadedIf(LOG_RNB_REMOTE, "%s", __PRETTY_FUNCTION__);
196   StopReadRemoteDataThread();
197 }
198 
199 void RNBRemote::CreatePacketTable() {
200   // Step required to add new packets:
201   // 1 - Add new enumeration to RNBRemote::PacketEnum
202   // 2 - Create the RNBRemote::HandlePacket_ function if a new function is
203   // needed
204   // 3 - Register the Packet definition with any needed callbacks in this
205   // function
206   //          - If no response is needed for a command, then use NULL for the
207   //          normal callback
208   //          - If the packet is not supported while the target is running, use
209   //          NULL for the async callback
210   // 4 - If the packet is a standard packet (starts with a '$' character
211   //      followed by the payload and then '#' and checksum, then you are done
212   //      else go on to step 5
213   // 5 - if the packet is a fixed length packet:
214   //      - modify the switch statement for the first character in the payload
215   //        in RNBRemote::CommDataReceived so it doesn't reject the new packet
216   //        type as invalid
217   //      - modify the switch statement for the first character in the payload
218   //        in RNBRemote::GetPacketPayload and make sure the payload of the
219   //        packet
220   //        is returned correctly
221 
222   std::vector<Packet> &t = m_packets;
223   t.push_back(Packet(ack, NULL, NULL, "+", "ACK"));
224   t.push_back(Packet(nack, NULL, NULL, "-", "!ACK"));
225   t.push_back(Packet(read_memory, &RNBRemote::HandlePacket_m, NULL, "m",
226                      "Read memory"));
227   t.push_back(Packet(read_register, &RNBRemote::HandlePacket_p, NULL, "p",
228                      "Read one register"));
229   t.push_back(Packet(read_general_regs, &RNBRemote::HandlePacket_g, NULL, "g",
230                      "Read registers"));
231   t.push_back(Packet(write_memory, &RNBRemote::HandlePacket_M, NULL, "M",
232                      "Write memory"));
233   t.push_back(Packet(write_register, &RNBRemote::HandlePacket_P, NULL, "P",
234                      "Write one register"));
235   t.push_back(Packet(write_general_regs, &RNBRemote::HandlePacket_G, NULL, "G",
236                      "Write registers"));
237   t.push_back(Packet(insert_mem_bp, &RNBRemote::HandlePacket_z, NULL, "Z0",
238                      "Insert memory breakpoint"));
239   t.push_back(Packet(remove_mem_bp, &RNBRemote::HandlePacket_z, NULL, "z0",
240                      "Remove memory breakpoint"));
241   t.push_back(Packet(single_step, &RNBRemote::HandlePacket_s, NULL, "s",
242                      "Single step"));
243   t.push_back(Packet(cont, &RNBRemote::HandlePacket_c, NULL, "c", "continue"));
244   t.push_back(Packet(single_step_with_sig, &RNBRemote::HandlePacket_S, NULL,
245                      "S", "Single step with signal"));
246   t.push_back(
247       Packet(set_thread, &RNBRemote::HandlePacket_H, NULL, "H", "Set thread"));
248   t.push_back(Packet(halt, &RNBRemote::HandlePacket_last_signal,
249                      &RNBRemote::HandlePacket_stop_process, "\x03", "^C"));
250   //  t.push_back (Packet (use_extended_mode,
251   //  &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "!", "Use extended mode"));
252   t.push_back(Packet(why_halted, &RNBRemote::HandlePacket_last_signal, NULL,
253                      "?", "Why did target halt"));
254   t.push_back(
255       Packet(set_argv, &RNBRemote::HandlePacket_A, NULL, "A", "Set argv"));
256   //  t.push_back (Packet (set_bp,
257   //  &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "B", "Set/clear
258   //  breakpoint"));
259   t.push_back(Packet(continue_with_sig, &RNBRemote::HandlePacket_C, NULL, "C",
260                      "Continue with signal"));
261   t.push_back(Packet(detach, &RNBRemote::HandlePacket_D, NULL, "D",
262                      "Detach gdb from remote system"));
263   //  t.push_back (Packet (step_inferior_one_cycle,
264   //  &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "i", "Step inferior by one
265   //  clock cycle"));
266   //  t.push_back (Packet (signal_and_step_inf_one_cycle,
267   //  &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "I", "Signal inferior, then
268   //  step one clock cycle"));
269   t.push_back(Packet(kill, &RNBRemote::HandlePacket_k, NULL, "k", "Kill"));
270   //  t.push_back (Packet (restart,
271   //  &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "R", "Restart inferior"));
272   //  t.push_back (Packet (search_mem_backwards,
273   //  &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "t", "Search memory
274   //  backwards"));
275   t.push_back(Packet(thread_alive_p, &RNBRemote::HandlePacket_T, NULL, "T",
276                      "Is thread alive"));
277   t.push_back(Packet(query_supported_features,
278                      &RNBRemote::HandlePacket_qSupported, NULL, "qSupported",
279                      "Query about supported features"));
280   t.push_back(Packet(vattach, &RNBRemote::HandlePacket_v, NULL, "vAttach",
281                      "Attach to a new process"));
282   t.push_back(Packet(vattachwait, &RNBRemote::HandlePacket_v, NULL,
283                      "vAttachWait",
284                      "Wait for a process to start up then attach to it"));
285   t.push_back(Packet(vattachorwait, &RNBRemote::HandlePacket_v, NULL,
286                      "vAttachOrWait", "Attach to the process or if it doesn't "
287                                       "exist, wait for the process to start up "
288                                       "then attach to it"));
289   t.push_back(Packet(vattachname, &RNBRemote::HandlePacket_v, NULL,
290                      "vAttachName", "Attach to an existing process by name"));
291   t.push_back(Packet(vcont_list_actions, &RNBRemote::HandlePacket_v, NULL,
292                      "vCont;", "Verbose resume with thread actions"));
293   t.push_back(Packet(vcont_list_actions, &RNBRemote::HandlePacket_v, NULL,
294                      "vCont?",
295                      "List valid continue-with-thread-actions actions"));
296   t.push_back(Packet(read_data_from_memory, &RNBRemote::HandlePacket_x, NULL,
297                      "x", "Read data from memory"));
298   t.push_back(Packet(write_data_to_memory, &RNBRemote::HandlePacket_X, NULL,
299                      "X", "Write data to memory"));
300   //  t.push_back (Packet (insert_hardware_bp,
301   //  &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "Z1", "Insert hardware
302   //  breakpoint"));
303   //  t.push_back (Packet (remove_hardware_bp,
304   //  &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "z1", "Remove hardware
305   //  breakpoint"));
306   t.push_back(Packet(insert_write_watch_bp, &RNBRemote::HandlePacket_z, NULL,
307                      "Z2", "Insert write watchpoint"));
308   t.push_back(Packet(remove_write_watch_bp, &RNBRemote::HandlePacket_z, NULL,
309                      "z2", "Remove write watchpoint"));
310   t.push_back(Packet(insert_read_watch_bp, &RNBRemote::HandlePacket_z, NULL,
311                      "Z3", "Insert read watchpoint"));
312   t.push_back(Packet(remove_read_watch_bp, &RNBRemote::HandlePacket_z, NULL,
313                      "z3", "Remove read watchpoint"));
314   t.push_back(Packet(insert_access_watch_bp, &RNBRemote::HandlePacket_z, NULL,
315                      "Z4", "Insert access watchpoint"));
316   t.push_back(Packet(remove_access_watch_bp, &RNBRemote::HandlePacket_z, NULL,
317                      "z4", "Remove access watchpoint"));
318   t.push_back(Packet(query_monitor, &RNBRemote::HandlePacket_qRcmd, NULL,
319                      "qRcmd", "Monitor command"));
320   t.push_back(Packet(query_current_thread_id, &RNBRemote::HandlePacket_qC, NULL,
321                      "qC", "Query current thread ID"));
322   t.push_back(Packet(query_echo, &RNBRemote::HandlePacket_qEcho, NULL, "qEcho:",
323                      "Echo the packet back to allow the debugger to sync up "
324                      "with this server"));
325   t.push_back(Packet(query_get_pid, &RNBRemote::HandlePacket_qGetPid, NULL,
326                      "qGetPid", "Query process id"));
327   t.push_back(Packet(query_thread_ids_first,
328                      &RNBRemote::HandlePacket_qThreadInfo, NULL, "qfThreadInfo",
329                      "Get list of active threads (first req)"));
330   t.push_back(Packet(query_thread_ids_subsequent,
331                      &RNBRemote::HandlePacket_qThreadInfo, NULL, "qsThreadInfo",
332                      "Get list of active threads (subsequent req)"));
333   // APPLE LOCAL: qThreadStopInfo
334   // syntax: qThreadStopInfoTTTT
335   //  TTTT is hex thread ID
336   t.push_back(Packet(query_thread_stop_info,
337                      &RNBRemote::HandlePacket_qThreadStopInfo, NULL,
338                      "qThreadStopInfo",
339                      "Get detailed info on why the specified thread stopped"));
340   t.push_back(Packet(query_thread_extra_info,
341                      &RNBRemote::HandlePacket_qThreadExtraInfo, NULL,
342                      "qThreadExtraInfo", "Get printable status of a thread"));
343   //  t.push_back (Packet (query_image_offsets,
344   //  &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "qOffsets", "Report offset
345   //  of loaded program"));
346   t.push_back(Packet(
347       query_launch_success, &RNBRemote::HandlePacket_qLaunchSuccess, NULL,
348       "qLaunchSuccess", "Report the success or failure of the launch attempt"));
349   t.push_back(
350       Packet(query_register_info, &RNBRemote::HandlePacket_qRegisterInfo, NULL,
351              "qRegisterInfo",
352              "Dynamically discover remote register context information."));
353   t.push_back(Packet(
354       query_shlib_notify_info_addr, &RNBRemote::HandlePacket_qShlibInfoAddr,
355       NULL, "qShlibInfoAddr", "Returns the address that contains info needed "
356                               "for getting shared library notifications"));
357   t.push_back(Packet(query_step_packet_supported,
358                      &RNBRemote::HandlePacket_qStepPacketSupported, NULL,
359                      "qStepPacketSupported",
360                      "Replys with OK if the 's' packet is supported."));
361   t.push_back(
362       Packet(query_vattachorwait_supported,
363              &RNBRemote::HandlePacket_qVAttachOrWaitSupported, NULL,
364              "qVAttachOrWaitSupported",
365              "Replys with OK if the 'vAttachOrWait' packet is supported."));
366   t.push_back(
367       Packet(query_sync_thread_state_supported,
368              &RNBRemote::HandlePacket_qSyncThreadStateSupported, NULL,
369              "qSyncThreadStateSupported",
370              "Replys with OK if the 'QSyncThreadState:' packet is supported."));
371   t.push_back(Packet(
372       query_host_info, &RNBRemote::HandlePacket_qHostInfo, NULL, "qHostInfo",
373       "Replies with multiple 'key:value;' tuples appended to each other."));
374   t.push_back(Packet(
375       query_gdb_server_version, &RNBRemote::HandlePacket_qGDBServerVersion,
376       NULL, "qGDBServerVersion",
377       "Replies with multiple 'key:value;' tuples appended to each other."));
378   t.push_back(Packet(
379       query_process_info, &RNBRemote::HandlePacket_qProcessInfo, NULL,
380       "qProcessInfo",
381       "Replies with multiple 'key:value;' tuples appended to each other."));
382   t.push_back(Packet(
383       query_symbol_lookup, &RNBRemote::HandlePacket_qSymbol, NULL, "qSymbol:",
384       "Notify that host debugger is ready to do symbol lookups"));
385   t.push_back(Packet(json_query_thread_extended_info,
386                      &RNBRemote::HandlePacket_jThreadExtendedInfo, NULL,
387                      "jThreadExtendedInfo",
388                      "Replies with JSON data of thread extended information."));
389   t.push_back(Packet(json_query_get_loaded_dynamic_libraries_infos,
390                      &RNBRemote::HandlePacket_jGetLoadedDynamicLibrariesInfos,
391                      NULL, "jGetLoadedDynamicLibrariesInfos",
392                      "Replies with JSON data of all the shared libraries "
393                      "loaded in this process."));
394   t.push_back(
395       Packet(json_query_threads_info, &RNBRemote::HandlePacket_jThreadsInfo,
396              NULL, "jThreadsInfo",
397              "Replies with JSON data with information about all threads."));
398   t.push_back(Packet(json_query_get_shared_cache_info,
399                      &RNBRemote::HandlePacket_jGetSharedCacheInfo, NULL,
400                      "jGetSharedCacheInfo", "Replies with JSON data about the "
401                                             "location and uuid of the shared "
402                                             "cache in the inferior process."));
403   t.push_back(Packet(start_noack_mode, &RNBRemote::HandlePacket_QStartNoAckMode,
404                      NULL, "QStartNoAckMode",
405                      "Request that " DEBUGSERVER_PROGRAM_NAME
406                      " stop acking remote protocol packets"));
407   t.push_back(Packet(prefix_reg_packets_with_tid,
408                      &RNBRemote::HandlePacket_QThreadSuffixSupported, NULL,
409                      "QThreadSuffixSupported",
410                      "Check if thread specific packets (register packets 'g', "
411                      "'G', 'p', and 'P') support having the thread ID appended "
412                      "to the end of the command"));
413   t.push_back(Packet(set_logging_mode, &RNBRemote::HandlePacket_QSetLogging,
414                      NULL, "QSetLogging:", "Check if register packets ('g', "
415                                            "'G', 'p', and 'P' support having "
416                                            "the thread ID prefix"));
417   t.push_back(Packet(
418       set_max_packet_size, &RNBRemote::HandlePacket_QSetMaxPacketSize, NULL,
419       "QSetMaxPacketSize:",
420       "Tell " DEBUGSERVER_PROGRAM_NAME " the max sized packet gdb can handle"));
421   t.push_back(Packet(
422       set_max_payload_size, &RNBRemote::HandlePacket_QSetMaxPayloadSize, NULL,
423       "QSetMaxPayloadSize:", "Tell " DEBUGSERVER_PROGRAM_NAME
424                              " the max sized payload gdb can handle"));
425   t.push_back(
426       Packet(set_environment_variable, &RNBRemote::HandlePacket_QEnvironment,
427              NULL, "QEnvironment:",
428              "Add an environment variable to the inferior's environment"));
429   t.push_back(
430       Packet(set_environment_variable_hex,
431              &RNBRemote::HandlePacket_QEnvironmentHexEncoded, NULL,
432              "QEnvironmentHexEncoded:",
433              "Add an environment variable to the inferior's environment"));
434   t.push_back(Packet(set_launch_arch, &RNBRemote::HandlePacket_QLaunchArch,
435                      NULL, "QLaunchArch:", "Set the architecture to use when "
436                                            "launching a process for hosts that "
437                                            "can run multiple architecture "
438                                            "slices from universal files."));
439   t.push_back(Packet(set_disable_aslr, &RNBRemote::HandlePacket_QSetDisableASLR,
440                      NULL, "QSetDisableASLR:",
441                      "Set whether to disable ASLR when launching the process "
442                      "with the set argv ('A') packet"));
443   t.push_back(Packet(set_stdin, &RNBRemote::HandlePacket_QSetSTDIO, NULL,
444                      "QSetSTDIN:", "Set the standard input for a process to be "
445                                    "launched with the 'A' packet"));
446   t.push_back(Packet(set_stdout, &RNBRemote::HandlePacket_QSetSTDIO, NULL,
447                      "QSetSTDOUT:", "Set the standard output for a process to "
448                                     "be launched with the 'A' packet"));
449   t.push_back(Packet(set_stderr, &RNBRemote::HandlePacket_QSetSTDIO, NULL,
450                      "QSetSTDERR:", "Set the standard error for a process to "
451                                     "be launched with the 'A' packet"));
452   t.push_back(Packet(set_working_dir, &RNBRemote::HandlePacket_QSetWorkingDir,
453                      NULL, "QSetWorkingDir:", "Set the working directory for a "
454                                               "process to be launched with the "
455                                               "'A' packet"));
456   t.push_back(Packet(set_list_threads_in_stop_reply,
457                      &RNBRemote::HandlePacket_QListThreadsInStopReply, NULL,
458                      "QListThreadsInStopReply",
459                      "Set if the 'threads' key should be added to the stop "
460                      "reply packets with a list of all thread IDs."));
461   t.push_back(Packet(
462       sync_thread_state, &RNBRemote::HandlePacket_QSyncThreadState, NULL,
463       "QSyncThreadState:", "Do whatever is necessary to make sure 'thread' is "
464                            "in a safe state to call functions on."));
465   //  t.push_back (Packet (pass_signals_to_inferior,
466   //  &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "QPassSignals:", "Specify
467   //  which signals are passed to the inferior"));
468   t.push_back(Packet(allocate_memory, &RNBRemote::HandlePacket_AllocateMemory,
469                      NULL, "_M", "Allocate memory in the inferior process."));
470   t.push_back(Packet(deallocate_memory,
471                      &RNBRemote::HandlePacket_DeallocateMemory, NULL, "_m",
472                      "Deallocate memory in the inferior process."));
473   t.push_back(Packet(
474       save_register_state, &RNBRemote::HandlePacket_SaveRegisterState, NULL,
475       "QSaveRegisterState", "Save the register state for the current thread "
476                             "and return a decimal save ID."));
477   t.push_back(Packet(restore_register_state,
478                      &RNBRemote::HandlePacket_RestoreRegisterState, NULL,
479                      "QRestoreRegisterState:",
480                      "Restore the register state given a save ID previously "
481                      "returned from a call to QSaveRegisterState."));
482   t.push_back(Packet(
483       memory_region_info, &RNBRemote::HandlePacket_MemoryRegionInfo, NULL,
484       "qMemoryRegionInfo", "Return size and attributes of a memory region that "
485                            "contains the given address"));
486   t.push_back(Packet(get_profile_data, &RNBRemote::HandlePacket_GetProfileData,
487                      NULL, "qGetProfileData",
488                      "Return profiling data of the current target."));
489   t.push_back(Packet(set_enable_profiling,
490                      &RNBRemote::HandlePacket_SetEnableAsyncProfiling, NULL,
491                      "QSetEnableAsyncProfiling",
492                      "Enable or disable the profiling of current target."));
493   t.push_back(Packet(enable_compression,
494                      &RNBRemote::HandlePacket_QEnableCompression, NULL,
495                      "QEnableCompression:",
496                      "Enable compression for the remainder of the connection"));
497   t.push_back(Packet(watchpoint_support_info,
498                      &RNBRemote::HandlePacket_WatchpointSupportInfo, NULL,
499                      "qWatchpointSupportInfo",
500                      "Return the number of supported hardware watchpoints"));
501   t.push_back(Packet(set_process_event,
502                      &RNBRemote::HandlePacket_QSetProcessEvent, NULL,
503                      "QSetProcessEvent:", "Set a process event, to be passed "
504                                           "to the process, can be set before "
505                                           "the process is started, or after."));
506   t.push_back(
507       Packet(set_detach_on_error, &RNBRemote::HandlePacket_QSetDetachOnError,
508              NULL, "QSetDetachOnError:",
509              "Set whether debugserver will detach (1) or kill (0) from the "
510              "process it is controlling if it loses connection to lldb."));
511   t.push_back(Packet(
512       speed_test, &RNBRemote::HandlePacket_qSpeedTest, NULL, "qSpeedTest:",
513       "Test the maximum speed at which packet can be sent/received."));
514   t.push_back(Packet(query_transfer, &RNBRemote::HandlePacket_qXfer, NULL,
515                      "qXfer:", "Support the qXfer packet."));
516   t.push_back(
517       Packet(query_supported_async_json_packets,
518              &RNBRemote::HandlePacket_qStructuredDataPlugins, NULL,
519              "qStructuredDataPlugins",
520              "Query for the structured data plugins supported by the remote."));
521   t.push_back(
522       Packet(configure_darwin_log, &RNBRemote::HandlePacket_QConfigureDarwinLog,
523              NULL, "QConfigureDarwinLog:",
524              "Configure the DarwinLog structured data plugin support."));
525 }
526 
527 void RNBRemote::FlushSTDIO() {
528   if (m_ctx.HasValidProcessID()) {
529     nub_process_t pid = m_ctx.ProcessID();
530     char buf[256];
531     nub_size_t count;
532     do {
533       count = DNBProcessGetAvailableSTDOUT(pid, buf, sizeof(buf));
534       if (count > 0) {
535         SendSTDOUTPacket(buf, count);
536       }
537     } while (count > 0);
538 
539     do {
540       count = DNBProcessGetAvailableSTDERR(pid, buf, sizeof(buf));
541       if (count > 0) {
542         SendSTDERRPacket(buf, count);
543       }
544     } while (count > 0);
545   }
546 }
547 
548 void RNBRemote::SendAsyncProfileData() {
549   if (m_ctx.HasValidProcessID()) {
550     nub_process_t pid = m_ctx.ProcessID();
551     char buf[1024];
552     nub_size_t count;
553     do {
554       count = DNBProcessGetAvailableProfileData(pid, buf, sizeof(buf));
555       if (count > 0) {
556         SendAsyncProfileDataPacket(buf, count);
557       }
558     } while (count > 0);
559   }
560 }
561 
562 void RNBRemote::SendAsyncDarwinLogData() {
563   DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): enter", __FUNCTION__);
564 
565   if (!m_ctx.HasValidProcessID()) {
566     DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): ignoring due to"
567                                      "invalid process id",
568                      __FUNCTION__);
569     return;
570   }
571 
572   nub_process_t pid = m_ctx.ProcessID();
573   DarwinLogEventVector::size_type entry_count = 0;
574 
575   // NOTE: the current looping structure here does nothing
576   // to guarantee that we can send off async packets faster
577   // than we generate them.  It will keep sending as long
578   // as there's data to send.
579   do {
580     DarwinLogEventVector events = DNBProcessGetAvailableDarwinLogEvents(pid);
581     entry_count = events.size();
582 
583     DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): outer loop enter",
584                      __FUNCTION__);
585 
586     for (DarwinLogEventVector::size_type base_entry = 0;
587          base_entry < entry_count;
588          base_entry += DARWIN_LOG_MAX_EVENTS_PER_PACKET) {
589       DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): inner loop enter",
590                        __FUNCTION__);
591 
592       // We limit the total number of entries we pack
593       // into a single JSON async packet just so it
594       // doesn't get too large.
595       JSONGenerator::Dictionary async_dictionary;
596 
597       // Specify the type of the JSON async data we're sending.
598       async_dictionary.AddStringItem(JSON_ASYNC_TYPE_KEY_NAME, "DarwinLog");
599 
600       // Create an array entry in the dictionary to hold all
601       // the events going in this packet.
602       JSONGenerator::ArraySP events_array(new JSONGenerator::Array());
603       async_dictionary.AddItem(OS_LOG_EVENTS_KEY_NAME, events_array);
604 
605       // We bundle up to DARWIN_LOG_MAX_EVENTS_PER_PACKET events in
606       // a single packet.
607       const auto inner_loop_bound =
608           std::min(base_entry + DARWIN_LOG_MAX_EVENTS_PER_PACKET, entry_count);
609       for (DarwinLogEventVector::size_type i = base_entry; i < inner_loop_bound;
610            ++i) {
611         DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): adding "
612                                          "entry index %lu to the JSON packet",
613                          __FUNCTION__, i);
614         events_array->AddItem(events[i]);
615       }
616 
617       // Send off the packet.
618       DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): sending JSON "
619                                        "packet, %lu entries remain",
620                        __FUNCTION__, entry_count - inner_loop_bound);
621       SendAsyncJSONPacket(async_dictionary);
622     }
623 
624     DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): outer loop exit",
625                      __FUNCTION__);
626 
627   } while (entry_count > 0);
628 
629   DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): exit",
630                    __PRETTY_FUNCTION__);
631 }
632 
633 rnb_err_t RNBRemote::SendHexEncodedBytePacket(const char *header,
634                                               const void *buf, size_t buf_len,
635                                               const char *footer) {
636   std::ostringstream packet_sstrm;
637   // Append the header cstr if there was one
638   if (header && header[0])
639     packet_sstrm << header;
640   nub_size_t i;
641   const uint8_t *ubuf8 = (const uint8_t *)buf;
642   for (i = 0; i < buf_len; i++) {
643     packet_sstrm << RAWHEX8(ubuf8[i]);
644   }
645   // Append the footer cstr if there was one
646   if (footer && footer[0])
647     packet_sstrm << footer;
648 
649   return SendPacket(packet_sstrm.str());
650 }
651 
652 rnb_err_t RNBRemote::SendSTDOUTPacket(char *buf, nub_size_t buf_size) {
653   if (buf_size == 0)
654     return rnb_success;
655   return SendHexEncodedBytePacket("O", buf, buf_size, NULL);
656 }
657 
658 rnb_err_t RNBRemote::SendSTDERRPacket(char *buf, nub_size_t buf_size) {
659   if (buf_size == 0)
660     return rnb_success;
661   return SendHexEncodedBytePacket("O", buf, buf_size, NULL);
662 }
663 
664 // This makes use of asynchronous bit 'A' in the gdb remote protocol.
665 rnb_err_t RNBRemote::SendAsyncProfileDataPacket(char *buf,
666                                                 nub_size_t buf_size) {
667   if (buf_size == 0)
668     return rnb_success;
669 
670   std::string packet("A");
671   packet.append(buf, buf_size);
672   return SendPacket(packet);
673 }
674 
675 rnb_err_t
676 RNBRemote::SendAsyncJSONPacket(const JSONGenerator::Dictionary &dictionary) {
677   std::ostringstream stream;
678   // We're choosing something that is easy to spot if we somehow get one
679   // of these coming out at the wrong time (i.e. when the remote side
680   // is not waiting for a process control completion response).
681   stream << "JSON-async:";
682   dictionary.Dump(stream);
683   const std::string payload = binary_encode_string(stream.str());
684   return SendPacket(payload);
685 }
686 
687 // Given a std::string packet contents to send, possibly encode/compress it.
688 // If compression is enabled, the returned std::string will be in one of two
689 // forms:
690 //
691 //    N<original packet contents uncompressed>
692 //    C<size of original decompressed packet>:<packet compressed with the
693 //    requested compression scheme>
694 //
695 // If compression is not requested, the original packet contents are returned
696 
697 std::string RNBRemote::CompressString(const std::string &orig) {
698   std::string compressed;
699   compression_types compression_type = GetCompressionType();
700   if (compression_type != compression_types::none) {
701     bool compress_this_packet = false;
702 
703     if (orig.size() > m_compression_minsize) {
704       compress_this_packet = true;
705     }
706 
707     if (compress_this_packet) {
708       const size_t encoded_data_buf_size = orig.size() + 128;
709       std::vector<uint8_t> encoded_data(encoded_data_buf_size);
710       size_t compressed_size = 0;
711 
712 #if defined(HAVE_LIBCOMPRESSION)
713       if (compression_decode_buffer &&
714           compression_type == compression_types::lz4) {
715         compressed_size = compression_encode_buffer(
716             encoded_data.data(), encoded_data_buf_size, (uint8_t *)orig.c_str(),
717             orig.size(), nullptr, COMPRESSION_LZ4_RAW);
718       }
719       if (compression_decode_buffer &&
720           compression_type == compression_types::zlib_deflate) {
721         compressed_size = compression_encode_buffer(
722             encoded_data.data(), encoded_data_buf_size, (uint8_t *)orig.c_str(),
723             orig.size(), nullptr, COMPRESSION_ZLIB);
724       }
725       if (compression_decode_buffer &&
726           compression_type == compression_types::lzma) {
727         compressed_size = compression_encode_buffer(
728             encoded_data.data(), encoded_data_buf_size, (uint8_t *)orig.c_str(),
729             orig.size(), nullptr, COMPRESSION_LZMA);
730       }
731       if (compression_decode_buffer &&
732           compression_type == compression_types::lzfse) {
733         compressed_size = compression_encode_buffer(
734             encoded_data.data(), encoded_data_buf_size, (uint8_t *)orig.c_str(),
735             orig.size(), nullptr, COMPRESSION_LZFSE);
736       }
737 #endif
738 
739 #if defined(HAVE_LIBZ)
740       if (compressed_size == 0 &&
741           compression_type == compression_types::zlib_deflate) {
742         z_stream stream;
743         memset(&stream, 0, sizeof(z_stream));
744         stream.next_in = (Bytef *)orig.c_str();
745         stream.avail_in = (uInt)orig.size();
746         stream.next_out = (Bytef *)encoded_data.data();
747         stream.avail_out = (uInt)encoded_data_buf_size;
748         stream.zalloc = Z_NULL;
749         stream.zfree = Z_NULL;
750         stream.opaque = Z_NULL;
751         deflateInit2(&stream, 5, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
752         int compress_status = deflate(&stream, Z_FINISH);
753         deflateEnd(&stream);
754         if (compress_status == Z_STREAM_END && stream.total_out > 0) {
755           compressed_size = stream.total_out;
756         }
757       }
758 #endif
759 
760       if (compressed_size > 0) {
761         compressed.clear();
762         compressed.reserve(compressed_size);
763         compressed = "C";
764         char numbuf[16];
765         snprintf(numbuf, sizeof(numbuf), "%zu:", orig.size());
766         numbuf[sizeof(numbuf) - 1] = '\0';
767         compressed.append(numbuf);
768 
769         for (size_t i = 0; i < compressed_size; i++) {
770           uint8_t byte = encoded_data[i];
771           if (byte == '#' || byte == '$' || byte == '}' || byte == '*' ||
772               byte == '\0') {
773             compressed.push_back(0x7d);
774             compressed.push_back(byte ^ 0x20);
775           } else {
776             compressed.push_back(byte);
777           }
778         }
779       } else {
780         compressed = "N" + orig;
781       }
782     } else {
783       compressed = "N" + orig;
784     }
785   } else {
786     compressed = orig;
787   }
788 
789   return compressed;
790 }
791 
792 rnb_err_t RNBRemote::SendPacket(const std::string &s) {
793   DNBLogThreadedIf(LOG_RNB_MAX, "%8d RNBRemote::%s (%s) called",
794                    (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
795                    __FUNCTION__, s.c_str());
796 
797   std::string s_compressed = CompressString(s);
798 
799   std::string sendpacket = "$" + s_compressed + "#";
800   int cksum = 0;
801   char hexbuf[5];
802 
803   if (m_noack_mode) {
804     sendpacket += "00";
805   } else {
806     for (size_t i = 0; i != s_compressed.size(); ++i)
807       cksum += s_compressed[i];
808     snprintf(hexbuf, sizeof hexbuf, "%02x", cksum & 0xff);
809     sendpacket += hexbuf;
810   }
811 
812   rnb_err_t err = m_comm.Write(sendpacket.c_str(), sendpacket.size());
813   if (err != rnb_success)
814     return err;
815 
816   if (m_noack_mode)
817     return rnb_success;
818 
819   std::string reply;
820   RNBRemote::Packet packet;
821   err = GetPacket(reply, packet, true);
822 
823   if (err != rnb_success) {
824     DNBLogThreadedIf(LOG_RNB_REMOTE,
825                      "%8d RNBRemote::%s (%s) got error trying to get reply...",
826                      (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
827                      __FUNCTION__, sendpacket.c_str());
828     return err;
829   }
830 
831   DNBLogThreadedIf(LOG_RNB_MAX, "%8d RNBRemote::%s (%s) got reply: '%s'",
832                    (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
833                    __FUNCTION__, sendpacket.c_str(), reply.c_str());
834 
835   if (packet.type == ack)
836     return rnb_success;
837 
838   // Should we try to resend the packet at this layer?
839   //  if (packet.command == nack)
840   return rnb_err;
841 }
842 
843 /* Get a packet via gdb remote protocol.
844  Strip off the prefix/suffix, verify the checksum to make sure
845  a valid packet was received, send an ACK if they match.  */
846 
847 rnb_err_t RNBRemote::GetPacketPayload(std::string &return_packet) {
848   // DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s called",
849   // (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
850 
851   PThreadMutex::Locker locker(m_mutex);
852   if (m_rx_packets.empty()) {
853     // Only reset the remote command available event if we have no more packets
854     m_ctx.Events().ResetEvents(RNBContext::event_read_packet_available);
855     // DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s error: no packets
856     // available...", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
857     // __FUNCTION__);
858     return rnb_err;
859   }
860 
861   // DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s has %u queued packets",
862   // (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__,
863   // m_rx_packets.size());
864   return_packet.swap(m_rx_packets.front());
865   m_rx_packets.pop_front();
866   locker.Reset(); // Release our lock on the mutex
867 
868   if (m_rx_packets.empty()) {
869     // Reset the remote command available event if we have no more packets
870     m_ctx.Events().ResetEvents(RNBContext::event_read_packet_available);
871   }
872 
873   // DNBLogThreadedIf (LOG_RNB_MEDIUM, "%8u RNBRemote::%s: '%s'",
874   // (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__,
875   // return_packet.c_str());
876 
877   switch (return_packet[0]) {
878   case '+':
879   case '-':
880   case '\x03':
881     break;
882 
883   case '$': {
884     long packet_checksum = 0;
885     if (!m_noack_mode) {
886       for (size_t i = return_packet.size() - 2; i < return_packet.size(); ++i) {
887         char checksum_char = tolower(return_packet[i]);
888         if (!isxdigit(checksum_char)) {
889           m_comm.Write("-", 1);
890           DNBLogThreadedIf(LOG_RNB_REMOTE, "%8u RNBRemote::%s error: packet "
891                                            "with invalid checksum characters: "
892                                            "%s",
893                            (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
894                            __FUNCTION__, return_packet.c_str());
895           return rnb_err;
896         }
897       }
898       packet_checksum =
899           strtol(&return_packet[return_packet.size() - 2], NULL, 16);
900     }
901 
902     return_packet.erase(0, 1);                     // Strip the leading '$'
903     return_packet.erase(return_packet.size() - 3); // Strip the #XX checksum
904 
905     if (!m_noack_mode) {
906       // Compute the checksum
907       int computed_checksum = 0;
908       for (std::string::iterator it = return_packet.begin();
909            it != return_packet.end(); ++it) {
910         computed_checksum += *it;
911       }
912 
913       if (packet_checksum == (computed_checksum & 0xff)) {
914         // DNBLogThreadedIf (LOG_RNB_MEDIUM, "%8u RNBRemote::%s sending ACK for
915         // '%s'", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
916         // __FUNCTION__, return_packet.c_str());
917         m_comm.Write("+", 1);
918       } else {
919         DNBLogThreadedIf(
920             LOG_RNB_MEDIUM, "%8u RNBRemote::%s sending ACK for '%s' (error: "
921                             "packet checksum mismatch  (0x%2.2lx != 0x%2.2x))",
922             (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__,
923             return_packet.c_str(), packet_checksum, computed_checksum);
924         m_comm.Write("-", 1);
925         return rnb_err;
926       }
927     }
928   } break;
929 
930   default:
931     DNBLogThreadedIf(LOG_RNB_REMOTE,
932                      "%8u RNBRemote::%s tossing unexpected packet???? %s",
933                      (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
934                      __FUNCTION__, return_packet.c_str());
935     if (!m_noack_mode)
936       m_comm.Write("-", 1);
937     return rnb_err;
938   }
939 
940   return rnb_success;
941 }
942 
943 rnb_err_t RNBRemote::HandlePacket_UNIMPLEMENTED(const char *p) {
944   DNBLogThreadedIf(LOG_RNB_MAX, "%8u RNBRemote::%s(\"%s\")",
945                    (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
946                    __FUNCTION__, p ? p : "NULL");
947   return SendPacket("");
948 }
949 
950 rnb_err_t RNBRemote::HandlePacket_ILLFORMED(const char *file, int line,
951                                             const char *p,
952                                             const char *description) {
953   DNBLogThreadedIf(LOG_RNB_PACKETS, "%8u %s:%i ILLFORMED: '%s' (%s)",
954                    (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), file,
955                    line, __FUNCTION__, p);
956   return SendPacket("E03");
957 }
958 
959 rnb_err_t RNBRemote::GetPacket(std::string &packet_payload,
960                                RNBRemote::Packet &packet_info, bool wait) {
961   std::string payload;
962   rnb_err_t err = GetPacketPayload(payload);
963   if (err != rnb_success) {
964     PThreadEvent &events = m_ctx.Events();
965     nub_event_t set_events = events.GetEventBits();
966     // TODO: add timeout version of GetPacket?? We would then need to pass
967     // that timeout value along to DNBProcessTimedWaitForEvent.
968     if (!wait || ((set_events & RNBContext::event_read_thread_running) == 0))
969       return err;
970 
971     const nub_event_t events_to_wait_for =
972         RNBContext::event_read_packet_available |
973         RNBContext::event_read_thread_exiting;
974 
975     while ((set_events = events.WaitForSetEvents(events_to_wait_for)) != 0) {
976       if (set_events & RNBContext::event_read_packet_available) {
977         // Try the queue again now that we got an event
978         err = GetPacketPayload(payload);
979         if (err == rnb_success)
980           break;
981       }
982 
983       if (set_events & RNBContext::event_read_thread_exiting)
984         err = rnb_not_connected;
985 
986       if (err == rnb_not_connected)
987         return err;
988     }
989     while (err == rnb_err)
990       ;
991 
992     if (set_events == 0)
993       err = rnb_not_connected;
994   }
995 
996   if (err == rnb_success) {
997     Packet::iterator it;
998     for (it = m_packets.begin(); it != m_packets.end(); ++it) {
999       if (payload.compare(0, it->abbrev.size(), it->abbrev) == 0)
1000         break;
1001     }
1002 
1003     // A packet we don't have an entry for. This can happen when we
1004     // get a packet that we don't know about or support. We just reply
1005     // accordingly and go on.
1006     if (it == m_packets.end()) {
1007       DNBLogThreadedIf(LOG_RNB_PACKETS, "unimplemented packet: '%s'",
1008                        payload.c_str());
1009       HandlePacket_UNIMPLEMENTED(payload.c_str());
1010       return rnb_err;
1011     } else {
1012       packet_info = *it;
1013       packet_payload = payload;
1014     }
1015   }
1016   return err;
1017 }
1018 
1019 rnb_err_t RNBRemote::HandleAsyncPacket(PacketEnum *type) {
1020   DNBLogThreadedIf(LOG_RNB_REMOTE, "%8u RNBRemote::%s",
1021                    (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
1022                    __FUNCTION__);
1023   static DNBTimer g_packetTimer(true);
1024   rnb_err_t err = rnb_err;
1025   std::string packet_data;
1026   RNBRemote::Packet packet_info;
1027   err = GetPacket(packet_data, packet_info, false);
1028 
1029   if (err == rnb_success) {
1030     if (!packet_data.empty() && isprint(packet_data[0]))
1031       DNBLogThreadedIf(LOG_RNB_REMOTE | LOG_RNB_PACKETS,
1032                        "HandleAsyncPacket (\"%s\");", packet_data.c_str());
1033     else
1034       DNBLogThreadedIf(LOG_RNB_REMOTE | LOG_RNB_PACKETS,
1035                        "HandleAsyncPacket (%s);",
1036                        packet_info.printable_name.c_str());
1037 
1038     HandlePacketCallback packet_callback = packet_info.async;
1039     if (packet_callback != NULL) {
1040       if (type != NULL)
1041         *type = packet_info.type;
1042       return (this->*packet_callback)(packet_data.c_str());
1043     }
1044   }
1045 
1046   return err;
1047 }
1048 
1049 rnb_err_t RNBRemote::HandleReceivedPacket(PacketEnum *type) {
1050   static DNBTimer g_packetTimer(true);
1051 
1052   //  DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s",
1053   //  (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
1054   rnb_err_t err = rnb_err;
1055   std::string packet_data;
1056   RNBRemote::Packet packet_info;
1057   err = GetPacket(packet_data, packet_info, false);
1058 
1059   if (err == rnb_success) {
1060     DNBLogThreadedIf(LOG_RNB_REMOTE, "HandleReceivedPacket (\"%s\");",
1061                      packet_data.c_str());
1062     HandlePacketCallback packet_callback = packet_info.normal;
1063     if (packet_callback != NULL) {
1064       if (type != NULL)
1065         *type = packet_info.type;
1066       return (this->*packet_callback)(packet_data.c_str());
1067     } else {
1068       // Do not fall through to end of this function, if we have valid
1069       // packet_info and it has a NULL callback, then we need to respect
1070       // that it may not want any response or anything to be done.
1071       return err;
1072     }
1073   }
1074   return rnb_err;
1075 }
1076 
1077 void RNBRemote::CommDataReceived(const std::string &new_data) {
1078   //  DNBLogThreadedIf (LOG_RNB_REMOTE, "%8d RNBRemote::%s called",
1079   //  (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
1080   {
1081     // Put the packet data into the buffer in a thread safe fashion
1082     PThreadMutex::Locker locker(m_mutex);
1083 
1084     std::string data;
1085     // See if we have any left over data from a previous call to this
1086     // function?
1087     if (!m_rx_partial_data.empty()) {
1088       // We do, so lets start with that data
1089       data.swap(m_rx_partial_data);
1090     }
1091     // Append the new incoming data
1092     data += new_data;
1093 
1094     // Parse up the packets into gdb remote packets
1095     size_t idx = 0;
1096     const size_t data_size = data.size();
1097 
1098     while (idx < data_size) {
1099       // end_idx must be one past the last valid packet byte. Start
1100       // it off with an invalid value that is the same as the current
1101       // index.
1102       size_t end_idx = idx;
1103 
1104       switch (data[idx]) {
1105       case '+':            // Look for ack
1106       case '-':            // Look for cancel
1107       case '\x03':         // ^C to halt target
1108         end_idx = idx + 1; // The command is one byte long...
1109         break;
1110 
1111       case '$':
1112         // Look for a standard gdb packet?
1113         end_idx = data.find('#', idx + 1);
1114         if (end_idx == std::string::npos || end_idx + 3 > data_size) {
1115           end_idx = std::string::npos;
1116         } else {
1117           // Add two for the checksum bytes and 1 to point to the
1118           // byte just past the end of this packet
1119           end_idx += 3;
1120         }
1121         break;
1122 
1123       default:
1124         break;
1125       }
1126 
1127       if (end_idx == std::string::npos) {
1128         // Not all data may be here for the packet yet, save it for
1129         // next time through this function.
1130         m_rx_partial_data += data.substr(idx);
1131         // DNBLogThreadedIf (LOG_RNB_MAX, "%8d RNBRemote::%s saving data for
1132         // later[%u, npos):
1133         // '%s'",(uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
1134         // __FUNCTION__, idx, m_rx_partial_data.c_str());
1135         idx = end_idx;
1136       } else if (idx < end_idx) {
1137         m_packets_recvd++;
1138         // Hack to get rid of initial '+' ACK???
1139         if (m_packets_recvd == 1 && (end_idx == idx + 1) && data[idx] == '+') {
1140           // DNBLogThreadedIf (LOG_RNB_REMOTE, "%8d RNBRemote::%s throwing first
1141           // ACK away....[%u, npos):
1142           // '+'",(uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
1143           // __FUNCTION__, idx);
1144         } else {
1145           // We have a valid packet...
1146           m_rx_packets.push_back(data.substr(idx, end_idx - idx));
1147           DNBLogThreadedIf(LOG_RNB_PACKETS, "getpkt: %s",
1148                            m_rx_packets.back().c_str());
1149         }
1150         idx = end_idx;
1151       } else {
1152         DNBLogThreadedIf(LOG_RNB_MAX,
1153                          "%8d RNBRemote::%s tossing junk byte at %c",
1154                          (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
1155                          __FUNCTION__, data[idx]);
1156         idx = idx + 1;
1157       }
1158     }
1159   }
1160 
1161   if (!m_rx_packets.empty()) {
1162     // Let the main thread know we have received a packet
1163 
1164     // DNBLogThreadedIf (LOG_RNB_EVENTS, "%8d RNBRemote::%s   called
1165     // events.SetEvent(RNBContext::event_read_packet_available)",
1166     // (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
1167     PThreadEvent &events = m_ctx.Events();
1168     events.SetEvents(RNBContext::event_read_packet_available);
1169   }
1170 }
1171 
1172 rnb_err_t RNBRemote::GetCommData() {
1173   //  DNBLogThreadedIf (LOG_RNB_REMOTE, "%8d RNBRemote::%s called",
1174   //  (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
1175   std::string comm_data;
1176   rnb_err_t err = m_comm.Read(comm_data);
1177   if (err == rnb_success) {
1178     if (!comm_data.empty())
1179       CommDataReceived(comm_data);
1180   }
1181   return err;
1182 }
1183 
1184 void RNBRemote::StartReadRemoteDataThread() {
1185   DNBLogThreadedIf(LOG_RNB_REMOTE, "%8u RNBRemote::%s called",
1186                    (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
1187                    __FUNCTION__);
1188   PThreadEvent &events = m_ctx.Events();
1189   if ((events.GetEventBits() & RNBContext::event_read_thread_running) == 0) {
1190     events.ResetEvents(RNBContext::event_read_thread_exiting);
1191     int err = ::pthread_create(&m_rx_pthread, NULL,
1192                                ThreadFunctionReadRemoteData, this);
1193     if (err == 0) {
1194       // Our thread was successfully kicked off, wait for it to
1195       // set the started event so we can safely continue
1196       events.WaitForSetEvents(RNBContext::event_read_thread_running);
1197     } else {
1198       events.ResetEvents(RNBContext::event_read_thread_running);
1199       events.SetEvents(RNBContext::event_read_thread_exiting);
1200     }
1201   }
1202 }
1203 
1204 void RNBRemote::StopReadRemoteDataThread() {
1205   DNBLogThreadedIf(LOG_RNB_REMOTE, "%8u RNBRemote::%s called",
1206                    (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
1207                    __FUNCTION__);
1208   PThreadEvent &events = m_ctx.Events();
1209   if ((events.GetEventBits() & RNBContext::event_read_thread_running) ==
1210       RNBContext::event_read_thread_running) {
1211     m_comm.Disconnect(true);
1212     struct timespec timeout_abstime;
1213     DNBTimer::OffsetTimeOfDay(&timeout_abstime, 2, 0);
1214 
1215     // Wait for 2 seconds for the remote data thread to exit
1216     if (events.WaitForSetEvents(RNBContext::event_read_thread_exiting,
1217                                 &timeout_abstime) == 0) {
1218       // Kill the remote data thread???
1219     }
1220   }
1221 }
1222 
1223 void *RNBRemote::ThreadFunctionReadRemoteData(void *arg) {
1224   // Keep a shared pointer reference so this doesn't go away on us before the
1225   // thread is killed.
1226   DNBLogThreadedIf(LOG_RNB_REMOTE, "RNBRemote::%s (%p): thread starting...",
1227                    __FUNCTION__, arg);
1228   RNBRemoteSP remoteSP(g_remoteSP);
1229   if (remoteSP.get() != NULL) {
1230 
1231 #if defined(__APPLE__)
1232     pthread_setname_np("read gdb-remote packets thread");
1233 #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
1234     struct sched_param thread_param;
1235     int thread_sched_policy;
1236     if (pthread_getschedparam(pthread_self(), &thread_sched_policy,
1237                               &thread_param) == 0) {
1238       thread_param.sched_priority = 47;
1239       pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param);
1240     }
1241 #endif
1242 #endif
1243 
1244     RNBRemote *remote = remoteSP.get();
1245     PThreadEvent &events = remote->Context().Events();
1246     events.SetEvents(RNBContext::event_read_thread_running);
1247     // START: main receive remote command thread loop
1248     bool done = false;
1249     while (!done) {
1250       rnb_err_t err = remote->GetCommData();
1251 
1252       switch (err) {
1253       case rnb_success:
1254         break;
1255 
1256       case rnb_err:
1257         DNBLogThreadedIf(LOG_RNB_REMOTE,
1258                          "RNBSocket::GetCommData returned error %u", err);
1259         done = true;
1260         break;
1261 
1262       case rnb_not_connected:
1263         DNBLogThreadedIf(LOG_RNB_REMOTE,
1264                          "RNBSocket::GetCommData returned not connected...");
1265         done = true;
1266         break;
1267       }
1268     }
1269     // START: main receive remote command thread loop
1270     events.ResetEvents(RNBContext::event_read_thread_running);
1271     events.SetEvents(RNBContext::event_read_thread_exiting);
1272   }
1273   DNBLogThreadedIf(LOG_RNB_REMOTE, "RNBRemote::%s (%p): thread exiting...",
1274                    __FUNCTION__, arg);
1275   return NULL;
1276 }
1277 
1278 // If we fail to get back a valid CPU type for the remote process,
1279 // make a best guess for the CPU type based on the currently running
1280 // debugserver binary -- the debugger may not handle the case of an
1281 // un-specified process CPU type correctly.
1282 
1283 static cpu_type_t best_guess_cpu_type() {
1284 #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
1285   if (sizeof(char *) == 8) {
1286     return CPU_TYPE_ARM64;
1287   } else {
1288     return CPU_TYPE_ARM;
1289   }
1290 #elif defined(__i386__) || defined(__x86_64__)
1291   if (sizeof(char *) == 8) {
1292     return CPU_TYPE_X86_64;
1293   } else {
1294     return CPU_TYPE_I386;
1295   }
1296 #endif
1297   return 0;
1298 }
1299 
1300 /* Read the bytes in STR which are GDB Remote Protocol binary encoded bytes
1301  (8-bit bytes).
1302  This encoding uses 0x7d ('}') as an escape character for
1303  0x7d ('}'), 0x23 ('#'), 0x24 ('$'), 0x2a ('*').
1304  LEN is the number of bytes to be processed.  If a character is escaped,
1305  it is 2 characters for LEN.  A LEN of -1 means decode-until-nul-byte
1306  (end of string).  */
1307 
1308 std::vector<uint8_t> decode_binary_data(const char *str, size_t len) {
1309   std::vector<uint8_t> bytes;
1310   if (len == 0) {
1311     return bytes;
1312   }
1313   if (len == (size_t)-1)
1314     len = strlen(str);
1315 
1316   while (len--) {
1317     unsigned char c = *str++;
1318     if (c == 0x7d && len > 0) {
1319       len--;
1320       c = *str++ ^ 0x20;
1321     }
1322     bytes.push_back(c);
1323   }
1324   return bytes;
1325 }
1326 
1327 // Quote any meta characters in a std::string as per the binary
1328 // packet convention in the gdb-remote protocol.
1329 
1330 static std::string binary_encode_string(const std::string &s) {
1331   std::string output;
1332   const size_t s_size = s.size();
1333   const char *s_chars = s.c_str();
1334 
1335   for (size_t i = 0; i < s_size; i++) {
1336     unsigned char ch = *(s_chars + i);
1337     if (ch == '#' || ch == '$' || ch == '}' || ch == '*') {
1338       output.push_back('}'); // 0x7d
1339       output.push_back(ch ^ 0x20);
1340     } else {
1341       output.push_back(ch);
1342     }
1343   }
1344   return output;
1345 }
1346 
1347 // If the value side of a key-value pair in JSON is a string,
1348 // and that string has a " character in it, the " character must
1349 // be escaped.
1350 
1351 std::string json_string_quote_metachars(const std::string &s) {
1352   if (s.find('"') == std::string::npos)
1353     return s;
1354 
1355   std::string output;
1356   const size_t s_size = s.size();
1357   const char *s_chars = s.c_str();
1358   for (size_t i = 0; i < s_size; i++) {
1359     unsigned char ch = *(s_chars + i);
1360     if (ch == '"') {
1361       output.push_back('\\');
1362     }
1363     output.push_back(ch);
1364   }
1365   return output;
1366 }
1367 
1368 typedef struct register_map_entry {
1369   uint32_t debugserver_regnum; // debugserver register number
1370   uint32_t offset; // Offset in bytes into the register context data with no
1371                    // padding between register values
1372   DNBRegisterInfo nub_info; // debugnub register info
1373   std::vector<uint32_t> value_regnums;
1374   std::vector<uint32_t> invalidate_regnums;
1375 } register_map_entry_t;
1376 
1377 // If the notion of registers differs from what is handed out by the
1378 // architecture, then flavors can be defined here.
1379 
1380 static std::vector<register_map_entry_t> g_dynamic_register_map;
1381 static register_map_entry_t *g_reg_entries = NULL;
1382 static size_t g_num_reg_entries = 0;
1383 
1384 void RNBRemote::Initialize() { DNBInitialize(); }
1385 
1386 bool RNBRemote::InitializeRegisters(bool force) {
1387   pid_t pid = m_ctx.ProcessID();
1388   if (pid == INVALID_NUB_PROCESS)
1389     return false;
1390 
1391   DNBLogThreadedIf(
1392       LOG_RNB_PROC,
1393       "RNBRemote::%s() getting native registers from DNB interface",
1394       __FUNCTION__);
1395   // Discover the registers by querying the DNB interface and letting it
1396   // state the registers that it would like to export. This allows the
1397   // registers to be discovered using multiple qRegisterInfo calls to get
1398   // all register information after the architecture for the process is
1399   // determined.
1400   if (force) {
1401     g_dynamic_register_map.clear();
1402     g_reg_entries = NULL;
1403     g_num_reg_entries = 0;
1404   }
1405 
1406   if (g_dynamic_register_map.empty()) {
1407     nub_size_t num_reg_sets = 0;
1408     const DNBRegisterSetInfo *reg_sets = DNBGetRegisterSetInfo(&num_reg_sets);
1409 
1410     assert(num_reg_sets > 0 && reg_sets != NULL);
1411 
1412     uint32_t regnum = 0;
1413     uint32_t reg_data_offset = 0;
1414     typedef std::map<std::string, uint32_t> NameToRegNum;
1415     NameToRegNum name_to_regnum;
1416     for (nub_size_t set = 0; set < num_reg_sets; ++set) {
1417       if (reg_sets[set].registers == NULL)
1418         continue;
1419 
1420       for (uint32_t reg = 0; reg < reg_sets[set].num_registers; ++reg) {
1421         register_map_entry_t reg_entry = {
1422             regnum++, // register number starts at zero and goes up with no gaps
1423             reg_data_offset, // Offset into register context data, no gaps
1424                              // between registers
1425             reg_sets[set].registers[reg], // DNBRegisterInfo
1426             {},
1427             {},
1428         };
1429 
1430         name_to_regnum[reg_entry.nub_info.name] = reg_entry.debugserver_regnum;
1431 
1432         if (reg_entry.nub_info.value_regs == NULL) {
1433           reg_data_offset += reg_entry.nub_info.size;
1434         }
1435 
1436         g_dynamic_register_map.push_back(reg_entry);
1437       }
1438     }
1439 
1440     // Now we must find any registers whose values are in other registers and
1441     // fix up
1442     // the offsets since we removed all gaps...
1443     for (auto &reg_entry : g_dynamic_register_map) {
1444       if (reg_entry.nub_info.value_regs) {
1445         uint32_t new_offset = UINT32_MAX;
1446         for (size_t i = 0; reg_entry.nub_info.value_regs[i] != NULL; ++i) {
1447           const char *name = reg_entry.nub_info.value_regs[i];
1448           auto pos = name_to_regnum.find(name);
1449           if (pos != name_to_regnum.end()) {
1450             regnum = pos->second;
1451             reg_entry.value_regnums.push_back(regnum);
1452             if (regnum < g_dynamic_register_map.size()) {
1453               // The offset for value_regs registers is the offset within the
1454               // register with the lowest offset
1455               const uint32_t reg_offset =
1456                   g_dynamic_register_map[regnum].offset +
1457                   reg_entry.nub_info.offset;
1458               if (new_offset > reg_offset)
1459                 new_offset = reg_offset;
1460             }
1461           }
1462         }
1463 
1464         if (new_offset != UINT32_MAX) {
1465           reg_entry.offset = new_offset;
1466         } else {
1467           DNBLogThreaded("no offset was calculated entry for register %s",
1468                          reg_entry.nub_info.name);
1469           reg_entry.offset = UINT32_MAX;
1470         }
1471       }
1472 
1473       if (reg_entry.nub_info.update_regs) {
1474         for (size_t i = 0; reg_entry.nub_info.update_regs[i] != NULL; ++i) {
1475           const char *name = reg_entry.nub_info.update_regs[i];
1476           auto pos = name_to_regnum.find(name);
1477           if (pos != name_to_regnum.end()) {
1478             regnum = pos->second;
1479             reg_entry.invalidate_regnums.push_back(regnum);
1480           }
1481         }
1482       }
1483     }
1484 
1485     //        for (auto &reg_entry: g_dynamic_register_map)
1486     //        {
1487     //            DNBLogThreaded("%4i: size = %3u, pseudo = %i, name = %s",
1488     //                           reg_entry.offset,
1489     //                           reg_entry.nub_info.size,
1490     //                           reg_entry.nub_info.value_regs != NULL,
1491     //                           reg_entry.nub_info.name);
1492     //        }
1493 
1494     g_reg_entries = g_dynamic_register_map.data();
1495     g_num_reg_entries = g_dynamic_register_map.size();
1496   }
1497   return true;
1498 }
1499 
1500 /* The inferior has stopped executing; send a packet
1501  to gdb to let it know.  */
1502 
1503 void RNBRemote::NotifyThatProcessStopped(void) {
1504   RNBRemote::HandlePacket_last_signal(NULL);
1505   return;
1506 }
1507 
1508 /* 'A arglen,argnum,arg,...'
1509  Update the inferior context CTX with the program name and arg
1510  list.
1511  The documentation for this packet is underwhelming but my best reading
1512  of this is that it is a series of (len, position #, arg)'s, one for
1513  each argument with "arg" hex encoded (two 0-9a-f chars?).
1514  Why we need BOTH a "len" and a hex encoded "arg" is beyond me - either
1515  is sufficient to get around the "," position separator escape issue.
1516 
1517  e.g. our best guess for a valid 'A' packet for "gdb -q a.out" is
1518 
1519  6,0,676462,4,1,2d71,10,2,612e6f7574
1520 
1521  Note that "argnum" and "arglen" are numbers in base 10.  Again, that's
1522  not documented either way but I'm assuming it's so.  */
1523 
1524 rnb_err_t RNBRemote::HandlePacket_A(const char *p) {
1525   if (p == NULL || *p == '\0') {
1526     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
1527                                   "Null packet for 'A' pkt");
1528   }
1529   p++;
1530   if (*p == '\0' || !isdigit(*p)) {
1531     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
1532                                   "arglen not specified on 'A' pkt");
1533   }
1534 
1535   /* I promise I don't modify it anywhere in this function.  strtoul()'s
1536    2nd arg has to be non-const which makes it problematic to step
1537    through the string easily.  */
1538   char *buf = const_cast<char *>(p);
1539 
1540   RNBContext &ctx = Context();
1541 
1542   while (*buf != '\0') {
1543     unsigned long arglen, argnum;
1544     std::string arg;
1545     char *c;
1546 
1547     errno = 0;
1548     arglen = strtoul(buf, &c, 10);
1549     if (errno != 0 && arglen == 0) {
1550       return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
1551                                     "arglen not a number on 'A' pkt");
1552     }
1553     if (*c != ',') {
1554       return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
1555                                     "arglen not followed by comma on 'A' pkt");
1556     }
1557     buf = c + 1;
1558 
1559     errno = 0;
1560     argnum = strtoul(buf, &c, 10);
1561     if (errno != 0 && argnum == 0) {
1562       return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
1563                                     "argnum not a number on 'A' pkt");
1564     }
1565     if (*c != ',') {
1566       return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
1567                                     "arglen not followed by comma on 'A' pkt");
1568     }
1569     buf = c + 1;
1570 
1571     c = buf;
1572     buf = buf + arglen;
1573     while (c < buf && *c != '\0' && c + 1 < buf && *(c + 1) != '\0') {
1574       char smallbuf[3];
1575       smallbuf[0] = *c;
1576       smallbuf[1] = *(c + 1);
1577       smallbuf[2] = '\0';
1578 
1579       errno = 0;
1580       int ch = static_cast<int>(strtoul(smallbuf, NULL, 16));
1581       if (errno != 0 && ch == 0) {
1582         return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
1583                                       "non-hex char in arg on 'A' pkt");
1584       }
1585 
1586       arg.push_back(ch);
1587       c += 2;
1588     }
1589 
1590     ctx.PushArgument(arg.c_str());
1591     if (*buf == ',')
1592       buf++;
1593   }
1594   SendPacket("OK");
1595 
1596   return rnb_success;
1597 }
1598 
1599 /* 'H c t'
1600  Set the thread for subsequent actions; 'c' for step/continue ops,
1601  'g' for other ops.  -1 means all threads, 0 means any thread.  */
1602 
1603 rnb_err_t RNBRemote::HandlePacket_H(const char *p) {
1604   p++; // skip 'H'
1605   if (*p != 'c' && *p != 'g') {
1606     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
1607                                   "Missing 'c' or 'g' type in H packet");
1608   }
1609 
1610   if (!m_ctx.HasValidProcessID()) {
1611     // We allow gdb to connect to a server that hasn't started running
1612     // the target yet.  gdb still wants to ask questions about it and
1613     // freaks out if it gets an error.  So just return OK here.
1614   }
1615 
1616   errno = 0;
1617   nub_thread_t tid = strtoul(p + 1, NULL, 16);
1618   if (errno != 0 && tid == 0) {
1619     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
1620                                   "Invalid thread number in H packet");
1621   }
1622   if (*p == 'c')
1623     SetContinueThread(tid);
1624   if (*p == 'g')
1625     SetCurrentThread(tid);
1626 
1627   return SendPacket("OK");
1628 }
1629 
1630 rnb_err_t RNBRemote::HandlePacket_qLaunchSuccess(const char *p) {
1631   if (m_ctx.HasValidProcessID() || m_ctx.LaunchStatus().Error() == 0)
1632     return SendPacket("OK");
1633   std::ostringstream ret_str;
1634   std::string status_str;
1635   ret_str << "E" << m_ctx.LaunchStatusAsString(status_str);
1636 
1637   return SendPacket(ret_str.str());
1638 }
1639 
1640 rnb_err_t RNBRemote::HandlePacket_qShlibInfoAddr(const char *p) {
1641   if (m_ctx.HasValidProcessID()) {
1642     nub_addr_t shlib_info_addr =
1643         DNBProcessGetSharedLibraryInfoAddress(m_ctx.ProcessID());
1644     if (shlib_info_addr != INVALID_NUB_ADDRESS) {
1645       std::ostringstream ostrm;
1646       ostrm << RAW_HEXBASE << shlib_info_addr;
1647       return SendPacket(ostrm.str());
1648     }
1649   }
1650   return SendPacket("E44");
1651 }
1652 
1653 rnb_err_t RNBRemote::HandlePacket_qStepPacketSupported(const char *p) {
1654   // Normally the "s" packet is mandatory, yet in gdb when using ARM, they
1655   // get around the need for this packet by implementing software single
1656   // stepping from gdb. Current versions of debugserver do support the "s"
1657   // packet, yet some older versions do not. We need a way to tell if this
1658   // packet is supported so we can disable software single stepping in gdb
1659   // for remote targets (so the "s" packet will get used).
1660   return SendPacket("OK");
1661 }
1662 
1663 rnb_err_t RNBRemote::HandlePacket_qSyncThreadStateSupported(const char *p) {
1664   // We support attachOrWait meaning attach if the process exists, otherwise
1665   // wait to attach.
1666   return SendPacket("OK");
1667 }
1668 
1669 rnb_err_t RNBRemote::HandlePacket_qVAttachOrWaitSupported(const char *p) {
1670   // We support attachOrWait meaning attach if the process exists, otherwise
1671   // wait to attach.
1672   return SendPacket("OK");
1673 }
1674 
1675 rnb_err_t RNBRemote::HandlePacket_qThreadStopInfo(const char *p) {
1676   p += strlen("qThreadStopInfo");
1677   nub_thread_t tid = strtoul(p, 0, 16);
1678   return SendStopReplyPacketForThread(tid);
1679 }
1680 
1681 rnb_err_t RNBRemote::HandlePacket_qThreadInfo(const char *p) {
1682   // We allow gdb to connect to a server that hasn't started running
1683   // the target yet.  gdb still wants to ask questions about it and
1684   // freaks out if it gets an error.  So just return OK here.
1685   nub_process_t pid = m_ctx.ProcessID();
1686   if (pid == INVALID_NUB_PROCESS)
1687     return SendPacket("OK");
1688 
1689   // Only "qfThreadInfo" and "qsThreadInfo" get into this function so
1690   // we only need to check the second byte to tell which is which
1691   if (p[1] == 'f') {
1692     nub_size_t numthreads = DNBProcessGetNumThreads(pid);
1693     std::ostringstream ostrm;
1694     ostrm << "m";
1695     bool first = true;
1696     for (nub_size_t i = 0; i < numthreads; ++i) {
1697       if (first)
1698         first = false;
1699       else
1700         ostrm << ",";
1701       nub_thread_t th = DNBProcessGetThreadAtIndex(pid, i);
1702       ostrm << std::hex << th;
1703     }
1704     return SendPacket(ostrm.str());
1705   } else {
1706     return SendPacket("l");
1707   }
1708 }
1709 
1710 rnb_err_t RNBRemote::HandlePacket_qThreadExtraInfo(const char *p) {
1711   // We allow gdb to connect to a server that hasn't started running
1712   // the target yet.  gdb still wants to ask questions about it and
1713   // freaks out if it gets an error.  So just return OK here.
1714   nub_process_t pid = m_ctx.ProcessID();
1715   if (pid == INVALID_NUB_PROCESS)
1716     return SendPacket("OK");
1717 
1718   /* This is supposed to return a string like 'Runnable' or
1719    'Blocked on Mutex'.
1720    The returned string is formatted like the "A" packet - a
1721    sequence of letters encoded in as 2-hex-chars-per-letter.  */
1722   p += strlen("qThreadExtraInfo");
1723   if (*p++ != ',')
1724     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
1725                                   "Illformed qThreadExtraInfo packet");
1726   errno = 0;
1727   nub_thread_t tid = strtoul(p, NULL, 16);
1728   if (errno != 0 && tid == 0) {
1729     return HandlePacket_ILLFORMED(
1730         __FILE__, __LINE__, p,
1731         "Invalid thread number in qThreadExtraInfo packet");
1732   }
1733 
1734   const char *threadInfo = DNBThreadGetInfo(pid, tid);
1735   if (threadInfo != NULL && threadInfo[0]) {
1736     return SendHexEncodedBytePacket(NULL, threadInfo, strlen(threadInfo), NULL);
1737   } else {
1738     // "OK" == 4f6b
1739     // Return "OK" as a ASCII hex byte stream if things go wrong
1740     return SendPacket("4f6b");
1741   }
1742 
1743   return SendPacket("");
1744 }
1745 
1746 const char *k_space_delimiters = " \t";
1747 static void skip_spaces(std::string &line) {
1748   if (!line.empty()) {
1749     size_t space_pos = line.find_first_not_of(k_space_delimiters);
1750     if (space_pos > 0)
1751       line.erase(0, space_pos);
1752   }
1753 }
1754 
1755 static std::string get_identifier(std::string &line) {
1756   std::string word;
1757   skip_spaces(line);
1758   const size_t line_size = line.size();
1759   size_t end_pos;
1760   for (end_pos = 0; end_pos < line_size; ++end_pos) {
1761     if (end_pos == 0) {
1762       if (isalpha(line[end_pos]) || line[end_pos] == '_')
1763         continue;
1764     } else if (isalnum(line[end_pos]) || line[end_pos] == '_')
1765       continue;
1766     break;
1767   }
1768   word.assign(line, 0, end_pos);
1769   line.erase(0, end_pos);
1770   return word;
1771 }
1772 
1773 static std::string get_operator(std::string &line) {
1774   std::string op;
1775   skip_spaces(line);
1776   if (!line.empty()) {
1777     if (line[0] == '=') {
1778       op = '=';
1779       line.erase(0, 1);
1780     }
1781   }
1782   return op;
1783 }
1784 
1785 static std::string get_value(std::string &line) {
1786   std::string value;
1787   skip_spaces(line);
1788   if (!line.empty()) {
1789     value.swap(line);
1790   }
1791   return value;
1792 }
1793 
1794 extern void FileLogCallback(void *baton, uint32_t flags, const char *format,
1795                             va_list args);
1796 extern void ASLLogCallback(void *baton, uint32_t flags, const char *format,
1797                            va_list args);
1798 
1799 rnb_err_t RNBRemote::HandlePacket_qRcmd(const char *p) {
1800   const char *c = p + strlen("qRcmd,");
1801   std::string line;
1802   while (c[0] && c[1]) {
1803     char smallbuf[3] = {c[0], c[1], '\0'};
1804     errno = 0;
1805     int ch = static_cast<int>(strtoul(smallbuf, NULL, 16));
1806     if (errno != 0 && ch == 0)
1807       return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
1808                                     "non-hex char in payload of qRcmd packet");
1809     line.push_back(ch);
1810     c += 2;
1811   }
1812   if (*c == '\0') {
1813     std::string command = get_identifier(line);
1814     if (command.compare("set") == 0) {
1815       std::string variable = get_identifier(line);
1816       std::string op = get_operator(line);
1817       std::string value = get_value(line);
1818       if (variable.compare("logfile") == 0) {
1819         FILE *log_file = fopen(value.c_str(), "w");
1820         if (log_file) {
1821           DNBLogSetLogCallback(FileLogCallback, log_file);
1822           return SendPacket("OK");
1823         }
1824         return SendPacket("E71");
1825       } else if (variable.compare("logmask") == 0) {
1826         char *end;
1827         errno = 0;
1828         uint32_t logmask =
1829             static_cast<uint32_t>(strtoul(value.c_str(), &end, 0));
1830         if (errno == 0 && end && *end == '\0') {
1831           DNBLogSetLogMask(logmask);
1832           if (!DNBLogGetLogCallback())
1833             DNBLogSetLogCallback(ASLLogCallback, NULL);
1834           return SendPacket("OK");
1835         }
1836         errno = 0;
1837         logmask = static_cast<uint32_t>(strtoul(value.c_str(), &end, 16));
1838         if (errno == 0 && end && *end == '\0') {
1839           DNBLogSetLogMask(logmask);
1840           return SendPacket("OK");
1841         }
1842         return SendPacket("E72");
1843       }
1844       return SendPacket("E70");
1845     }
1846     return SendPacket("E69");
1847   }
1848   return SendPacket("E73");
1849 }
1850 
1851 rnb_err_t RNBRemote::HandlePacket_qC(const char *p) {
1852   nub_thread_t tid;
1853   std::ostringstream rep;
1854   // If we haven't run the process yet, we tell the debugger the
1855   // pid is 0.  That way it can know to tell use to run later on.
1856   if (!m_ctx.HasValidProcessID())
1857     tid = 0;
1858   else {
1859     // Grab the current thread.
1860     tid = DNBProcessGetCurrentThread(m_ctx.ProcessID());
1861     // Make sure we set the current thread so g and p packets return
1862     // the data the gdb will expect.
1863     SetCurrentThread(tid);
1864   }
1865   rep << "QC" << std::hex << tid;
1866   return SendPacket(rep.str());
1867 }
1868 
1869 rnb_err_t RNBRemote::HandlePacket_qEcho(const char *p) {
1870   // Just send the exact same packet back that we received to
1871   // synchronize the response packets after a previous packet
1872   // timed out. This allows the debugger to get back on track
1873   // with responses after a packet timeout.
1874   return SendPacket(p);
1875 }
1876 
1877 rnb_err_t RNBRemote::HandlePacket_qGetPid(const char *p) {
1878   nub_process_t pid;
1879   std::ostringstream rep;
1880   // If we haven't run the process yet, we tell the debugger the
1881   // pid is 0.  That way it can know to tell use to run later on.
1882   if (m_ctx.HasValidProcessID())
1883     pid = m_ctx.ProcessID();
1884   else
1885     pid = 0;
1886   rep << std::hex << pid;
1887   return SendPacket(rep.str());
1888 }
1889 
1890 rnb_err_t RNBRemote::HandlePacket_qRegisterInfo(const char *p) {
1891   if (g_num_reg_entries == 0)
1892     InitializeRegisters();
1893 
1894   p += strlen("qRegisterInfo");
1895 
1896   nub_size_t num_reg_sets = 0;
1897   const DNBRegisterSetInfo *reg_set_info = DNBGetRegisterSetInfo(&num_reg_sets);
1898   uint32_t reg_num = static_cast<uint32_t>(strtoul(p, 0, 16));
1899 
1900   if (reg_num < g_num_reg_entries) {
1901     const register_map_entry_t *reg_entry = &g_reg_entries[reg_num];
1902     std::ostringstream ostrm;
1903     if (reg_entry->nub_info.name)
1904       ostrm << "name:" << reg_entry->nub_info.name << ';';
1905     if (reg_entry->nub_info.alt)
1906       ostrm << "alt-name:" << reg_entry->nub_info.alt << ';';
1907 
1908     ostrm << "bitsize:" << std::dec << reg_entry->nub_info.size * 8 << ';';
1909     ostrm << "offset:" << std::dec << reg_entry->offset << ';';
1910 
1911     switch (reg_entry->nub_info.type) {
1912     case Uint:
1913       ostrm << "encoding:uint;";
1914       break;
1915     case Sint:
1916       ostrm << "encoding:sint;";
1917       break;
1918     case IEEE754:
1919       ostrm << "encoding:ieee754;";
1920       break;
1921     case Vector:
1922       ostrm << "encoding:vector;";
1923       break;
1924     }
1925 
1926     switch (reg_entry->nub_info.format) {
1927     case Binary:
1928       ostrm << "format:binary;";
1929       break;
1930     case Decimal:
1931       ostrm << "format:decimal;";
1932       break;
1933     case Hex:
1934       ostrm << "format:hex;";
1935       break;
1936     case Float:
1937       ostrm << "format:float;";
1938       break;
1939     case VectorOfSInt8:
1940       ostrm << "format:vector-sint8;";
1941       break;
1942     case VectorOfUInt8:
1943       ostrm << "format:vector-uint8;";
1944       break;
1945     case VectorOfSInt16:
1946       ostrm << "format:vector-sint16;";
1947       break;
1948     case VectorOfUInt16:
1949       ostrm << "format:vector-uint16;";
1950       break;
1951     case VectorOfSInt32:
1952       ostrm << "format:vector-sint32;";
1953       break;
1954     case VectorOfUInt32:
1955       ostrm << "format:vector-uint32;";
1956       break;
1957     case VectorOfFloat32:
1958       ostrm << "format:vector-float32;";
1959       break;
1960     case VectorOfUInt128:
1961       ostrm << "format:vector-uint128;";
1962       break;
1963     };
1964 
1965     if (reg_set_info && reg_entry->nub_info.set < num_reg_sets)
1966       ostrm << "set:" << reg_set_info[reg_entry->nub_info.set].name << ';';
1967 
1968     if (reg_entry->nub_info.reg_ehframe != INVALID_NUB_REGNUM)
1969       ostrm << "ehframe:" << std::dec << reg_entry->nub_info.reg_ehframe << ';';
1970 
1971     if (reg_entry->nub_info.reg_dwarf != INVALID_NUB_REGNUM)
1972       ostrm << "dwarf:" << std::dec << reg_entry->nub_info.reg_dwarf << ';';
1973 
1974     switch (reg_entry->nub_info.reg_generic) {
1975     case GENERIC_REGNUM_FP:
1976       ostrm << "generic:fp;";
1977       break;
1978     case GENERIC_REGNUM_PC:
1979       ostrm << "generic:pc;";
1980       break;
1981     case GENERIC_REGNUM_SP:
1982       ostrm << "generic:sp;";
1983       break;
1984     case GENERIC_REGNUM_RA:
1985       ostrm << "generic:ra;";
1986       break;
1987     case GENERIC_REGNUM_FLAGS:
1988       ostrm << "generic:flags;";
1989       break;
1990     case GENERIC_REGNUM_ARG1:
1991       ostrm << "generic:arg1;";
1992       break;
1993     case GENERIC_REGNUM_ARG2:
1994       ostrm << "generic:arg2;";
1995       break;
1996     case GENERIC_REGNUM_ARG3:
1997       ostrm << "generic:arg3;";
1998       break;
1999     case GENERIC_REGNUM_ARG4:
2000       ostrm << "generic:arg4;";
2001       break;
2002     case GENERIC_REGNUM_ARG5:
2003       ostrm << "generic:arg5;";
2004       break;
2005     case GENERIC_REGNUM_ARG6:
2006       ostrm << "generic:arg6;";
2007       break;
2008     case GENERIC_REGNUM_ARG7:
2009       ostrm << "generic:arg7;";
2010       break;
2011     case GENERIC_REGNUM_ARG8:
2012       ostrm << "generic:arg8;";
2013       break;
2014     default:
2015       break;
2016     }
2017 
2018     if (!reg_entry->value_regnums.empty()) {
2019       ostrm << "container-regs:";
2020       for (size_t i = 0, n = reg_entry->value_regnums.size(); i < n; ++i) {
2021         if (i > 0)
2022           ostrm << ',';
2023         ostrm << RAW_HEXBASE << reg_entry->value_regnums[i];
2024       }
2025       ostrm << ';';
2026     }
2027 
2028     if (!reg_entry->invalidate_regnums.empty()) {
2029       ostrm << "invalidate-regs:";
2030       for (size_t i = 0, n = reg_entry->invalidate_regnums.size(); i < n; ++i) {
2031         if (i > 0)
2032           ostrm << ',';
2033         ostrm << RAW_HEXBASE << reg_entry->invalidate_regnums[i];
2034       }
2035       ostrm << ';';
2036     }
2037 
2038     return SendPacket(ostrm.str());
2039   }
2040   return SendPacket("E45");
2041 }
2042 
2043 /* This expects a packet formatted like
2044 
2045  QSetLogging:bitmask=LOG_ALL|LOG_RNB_REMOTE;
2046 
2047  with the "QSetLogging:" already removed from the start.  Maybe in the
2048  future this packet will include other keyvalue pairs like
2049 
2050  QSetLogging:bitmask=LOG_ALL;mode=asl;
2051  */
2052 
2053 rnb_err_t set_logging(const char *p) {
2054   int bitmask = 0;
2055   while (p && *p != '\0') {
2056     if (strncmp(p, "bitmask=", sizeof("bitmask=") - 1) == 0) {
2057       p += sizeof("bitmask=") - 1;
2058       while (p && *p != '\0' && *p != ';') {
2059         if (*p == '|')
2060           p++;
2061 
2062         // to regenerate the LOG_ entries (not including the LOG_RNB entries)
2063         // $ for logname in `grep '^#define LOG_' DNBDefs.h | egrep -v
2064         // 'LOG_HI|LOG_LO' | awk '{print $2}'`
2065         // do
2066         //   echo "                else if (strncmp (p, \"$logname\", sizeof
2067         //   (\"$logname\") - 1) == 0)"
2068         //   echo "                {"
2069         //   echo "                    p += sizeof (\"$logname\") - 1;"
2070         //   echo "                    bitmask |= $logname;"
2071         //   echo "                }"
2072         // done
2073         if (strncmp(p, "LOG_VERBOSE", sizeof("LOG_VERBOSE") - 1) == 0) {
2074           p += sizeof("LOG_VERBOSE") - 1;
2075           bitmask |= LOG_VERBOSE;
2076         } else if (strncmp(p, "LOG_PROCESS", sizeof("LOG_PROCESS") - 1) == 0) {
2077           p += sizeof("LOG_PROCESS") - 1;
2078           bitmask |= LOG_PROCESS;
2079         } else if (strncmp(p, "LOG_THREAD", sizeof("LOG_THREAD") - 1) == 0) {
2080           p += sizeof("LOG_THREAD") - 1;
2081           bitmask |= LOG_THREAD;
2082         } else if (strncmp(p, "LOG_EXCEPTIONS", sizeof("LOG_EXCEPTIONS") - 1) ==
2083                    0) {
2084           p += sizeof("LOG_EXCEPTIONS") - 1;
2085           bitmask |= LOG_EXCEPTIONS;
2086         } else if (strncmp(p, "LOG_SHLIB", sizeof("LOG_SHLIB") - 1) == 0) {
2087           p += sizeof("LOG_SHLIB") - 1;
2088           bitmask |= LOG_SHLIB;
2089         } else if (strncmp(p, "LOG_MEMORY", sizeof("LOG_MEMORY") - 1) == 0) {
2090           p += sizeof("LOG_MEMORY") - 1;
2091           bitmask |= LOG_MEMORY;
2092         } else if (strncmp(p, "LOG_MEMORY_DATA_SHORT",
2093                            sizeof("LOG_MEMORY_DATA_SHORT") - 1) == 0) {
2094           p += sizeof("LOG_MEMORY_DATA_SHORT") - 1;
2095           bitmask |= LOG_MEMORY_DATA_SHORT;
2096         } else if (strncmp(p, "LOG_MEMORY_DATA_LONG",
2097                            sizeof("LOG_MEMORY_DATA_LONG") - 1) == 0) {
2098           p += sizeof("LOG_MEMORY_DATA_LONG") - 1;
2099           bitmask |= LOG_MEMORY_DATA_LONG;
2100         } else if (strncmp(p, "LOG_MEMORY_PROTECTIONS",
2101                            sizeof("LOG_MEMORY_PROTECTIONS") - 1) == 0) {
2102           p += sizeof("LOG_MEMORY_PROTECTIONS") - 1;
2103           bitmask |= LOG_MEMORY_PROTECTIONS;
2104         } else if (strncmp(p, "LOG_BREAKPOINTS",
2105                            sizeof("LOG_BREAKPOINTS") - 1) == 0) {
2106           p += sizeof("LOG_BREAKPOINTS") - 1;
2107           bitmask |= LOG_BREAKPOINTS;
2108         } else if (strncmp(p, "LOG_EVENTS", sizeof("LOG_EVENTS") - 1) == 0) {
2109           p += sizeof("LOG_EVENTS") - 1;
2110           bitmask |= LOG_EVENTS;
2111         } else if (strncmp(p, "LOG_WATCHPOINTS",
2112                            sizeof("LOG_WATCHPOINTS") - 1) == 0) {
2113           p += sizeof("LOG_WATCHPOINTS") - 1;
2114           bitmask |= LOG_WATCHPOINTS;
2115         } else if (strncmp(p, "LOG_STEP", sizeof("LOG_STEP") - 1) == 0) {
2116           p += sizeof("LOG_STEP") - 1;
2117           bitmask |= LOG_STEP;
2118         } else if (strncmp(p, "LOG_TASK", sizeof("LOG_TASK") - 1) == 0) {
2119           p += sizeof("LOG_TASK") - 1;
2120           bitmask |= LOG_TASK;
2121         } else if (strncmp(p, "LOG_ALL", sizeof("LOG_ALL") - 1) == 0) {
2122           p += sizeof("LOG_ALL") - 1;
2123           bitmask |= LOG_ALL;
2124         } else if (strncmp(p, "LOG_DEFAULT", sizeof("LOG_DEFAULT") - 1) == 0) {
2125           p += sizeof("LOG_DEFAULT") - 1;
2126           bitmask |= LOG_DEFAULT;
2127         }
2128         // end of auto-generated entries
2129 
2130         else if (strncmp(p, "LOG_NONE", sizeof("LOG_NONE") - 1) == 0) {
2131           p += sizeof("LOG_NONE") - 1;
2132           bitmask = 0;
2133         } else if (strncmp(p, "LOG_RNB_MINIMAL",
2134                            sizeof("LOG_RNB_MINIMAL") - 1) == 0) {
2135           p += sizeof("LOG_RNB_MINIMAL") - 1;
2136           bitmask |= LOG_RNB_MINIMAL;
2137         } else if (strncmp(p, "LOG_RNB_MEDIUM", sizeof("LOG_RNB_MEDIUM") - 1) ==
2138                    0) {
2139           p += sizeof("LOG_RNB_MEDIUM") - 1;
2140           bitmask |= LOG_RNB_MEDIUM;
2141         } else if (strncmp(p, "LOG_RNB_MAX", sizeof("LOG_RNB_MAX") - 1) == 0) {
2142           p += sizeof("LOG_RNB_MAX") - 1;
2143           bitmask |= LOG_RNB_MAX;
2144         } else if (strncmp(p, "LOG_RNB_COMM", sizeof("LOG_RNB_COMM") - 1) ==
2145                    0) {
2146           p += sizeof("LOG_RNB_COMM") - 1;
2147           bitmask |= LOG_RNB_COMM;
2148         } else if (strncmp(p, "LOG_RNB_REMOTE", sizeof("LOG_RNB_REMOTE") - 1) ==
2149                    0) {
2150           p += sizeof("LOG_RNB_REMOTE") - 1;
2151           bitmask |= LOG_RNB_REMOTE;
2152         } else if (strncmp(p, "LOG_RNB_EVENTS", sizeof("LOG_RNB_EVENTS") - 1) ==
2153                    0) {
2154           p += sizeof("LOG_RNB_EVENTS") - 1;
2155           bitmask |= LOG_RNB_EVENTS;
2156         } else if (strncmp(p, "LOG_RNB_PROC", sizeof("LOG_RNB_PROC") - 1) ==
2157                    0) {
2158           p += sizeof("LOG_RNB_PROC") - 1;
2159           bitmask |= LOG_RNB_PROC;
2160         } else if (strncmp(p, "LOG_RNB_PACKETS",
2161                            sizeof("LOG_RNB_PACKETS") - 1) == 0) {
2162           p += sizeof("LOG_RNB_PACKETS") - 1;
2163           bitmask |= LOG_RNB_PACKETS;
2164         } else if (strncmp(p, "LOG_RNB_ALL", sizeof("LOG_RNB_ALL") - 1) == 0) {
2165           p += sizeof("LOG_RNB_ALL") - 1;
2166           bitmask |= LOG_RNB_ALL;
2167         } else if (strncmp(p, "LOG_RNB_DEFAULT",
2168                            sizeof("LOG_RNB_DEFAULT") - 1) == 0) {
2169           p += sizeof("LOG_RNB_DEFAULT") - 1;
2170           bitmask |= LOG_RNB_DEFAULT;
2171         } else if (strncmp(p, "LOG_DARWIN_LOG", sizeof("LOG_DARWIN_LOG") - 1) ==
2172                    0) {
2173           p += sizeof("LOG_DARWIN_LOG") - 1;
2174           bitmask |= LOG_DARWIN_LOG;
2175         } else if (strncmp(p, "LOG_RNB_NONE", sizeof("LOG_RNB_NONE") - 1) ==
2176                    0) {
2177           p += sizeof("LOG_RNB_NONE") - 1;
2178           bitmask = 0;
2179         } else {
2180           /* Unrecognized logging bit; ignore it.  */
2181           const char *c = strchr(p, '|');
2182           if (c) {
2183             p = c;
2184           } else {
2185             c = strchr(p, ';');
2186             if (c) {
2187               p = c;
2188             } else {
2189               // Improperly terminated word; just go to end of str
2190               p = strchr(p, '\0');
2191             }
2192           }
2193         }
2194       }
2195       // Did we get a properly formatted logging bitmask?
2196       if (p && *p == ';') {
2197         // Enable DNB logging.
2198         // Use the existing log callback if one was already configured.
2199         if (!DNBLogGetLogCallback()) {
2200           // Use the os_log()-based logger if available; otherwise,
2201           // fallback to ASL.
2202           auto log_callback = OsLogger::GetLogFunction();
2203           if (log_callback)
2204             DNBLogSetLogCallback(log_callback, nullptr);
2205           else
2206             DNBLogSetLogCallback(ASLLogCallback, nullptr);
2207         }
2208 
2209         // Update logging to use the configured log channel bitmask.
2210         DNBLogSetLogMask(bitmask);
2211         p++;
2212       }
2213     }
2214 // We're not going to support logging to a file for now.  All logging
2215 // goes through ASL or the previously arranged log callback.
2216 #if 0
2217         else if (strncmp (p, "mode=", sizeof ("mode=") - 1) == 0)
2218         {
2219             p += sizeof ("mode=") - 1;
2220             if (strncmp (p, "asl;", sizeof ("asl;") - 1) == 0)
2221             {
2222                 DNBLogToASL ();
2223                 p += sizeof ("asl;") - 1;
2224             }
2225             else if (strncmp (p, "file;", sizeof ("file;") - 1) == 0)
2226             {
2227                 DNBLogToFile ();
2228                 p += sizeof ("file;") - 1;
2229             }
2230             else
2231             {
2232                 // Ignore unknown argument
2233                 const char *c = strchr (p, ';');
2234                 if (c)
2235                     p = c + 1;
2236                 else
2237                     p = strchr (p, '\0');
2238             }
2239         }
2240         else if (strncmp (p, "filename=", sizeof ("filename=") - 1) == 0)
2241         {
2242             p += sizeof ("filename=") - 1;
2243             const char *c = strchr (p, ';');
2244             if (c == NULL)
2245             {
2246                 c = strchr (p, '\0');
2247                 continue;
2248             }
2249             char *fn = (char *) alloca (c - p + 1);
2250             strncpy (fn, p, c - p);
2251             fn[c - p] = '\0';
2252 
2253             // A file name of "asl" is special and is another way to indicate
2254             // that logging should be done via ASL, not by file.
2255             if (strcmp (fn, "asl") == 0)
2256             {
2257                 DNBLogToASL ();
2258             }
2259             else
2260             {
2261                 FILE *f = fopen (fn, "w");
2262                 if (f)
2263                 {
2264                     DNBLogSetLogFile (f);
2265                     DNBEnableLogging (f, DNBLogGetLogMask ());
2266                     DNBLogToFile ();
2267                 }
2268             }
2269             p = c + 1;
2270         }
2271 #endif /* #if 0 to enforce ASL logging only.  */
2272     else {
2273       // Ignore unknown argument
2274       const char *c = strchr(p, ';');
2275       if (c)
2276         p = c + 1;
2277       else
2278         p = strchr(p, '\0');
2279     }
2280   }
2281 
2282   return rnb_success;
2283 }
2284 
2285 rnb_err_t RNBRemote::HandlePacket_QThreadSuffixSupported(const char *p) {
2286   m_thread_suffix_supported = true;
2287   return SendPacket("OK");
2288 }
2289 
2290 rnb_err_t RNBRemote::HandlePacket_QStartNoAckMode(const char *p) {
2291   // Send the OK packet first so the correct checksum is appended...
2292   rnb_err_t result = SendPacket("OK");
2293   m_noack_mode = true;
2294   return result;
2295 }
2296 
2297 rnb_err_t RNBRemote::HandlePacket_QSetLogging(const char *p) {
2298   p += sizeof("QSetLogging:") - 1;
2299   rnb_err_t result = set_logging(p);
2300   if (result == rnb_success)
2301     return SendPacket("OK");
2302   else
2303     return SendPacket("E35");
2304 }
2305 
2306 rnb_err_t RNBRemote::HandlePacket_QSetDisableASLR(const char *p) {
2307   extern int g_disable_aslr;
2308   p += sizeof("QSetDisableASLR:") - 1;
2309   switch (*p) {
2310   case '0':
2311     g_disable_aslr = 0;
2312     break;
2313   case '1':
2314     g_disable_aslr = 1;
2315     break;
2316   default:
2317     return SendPacket("E56");
2318   }
2319   return SendPacket("OK");
2320 }
2321 
2322 rnb_err_t RNBRemote::HandlePacket_QSetSTDIO(const char *p) {
2323   // Only set stdin/out/err if we don't already have a process
2324   if (!m_ctx.HasValidProcessID()) {
2325     bool success = false;
2326     // Check the seventh character since the packet will be one of:
2327     // QSetSTDIN
2328     // QSetSTDOUT
2329     // QSetSTDERR
2330     StdStringExtractor packet(p);
2331     packet.SetFilePos(7);
2332     char ch = packet.GetChar();
2333     while (packet.GetChar() != ':')
2334       /* Do nothing. */;
2335 
2336     switch (ch) {
2337     case 'I': // STDIN
2338       packet.GetHexByteString(m_ctx.GetSTDIN());
2339       success = !m_ctx.GetSTDIN().empty();
2340       break;
2341 
2342     case 'O': // STDOUT
2343       packet.GetHexByteString(m_ctx.GetSTDOUT());
2344       success = !m_ctx.GetSTDOUT().empty();
2345       break;
2346 
2347     case 'E': // STDERR
2348       packet.GetHexByteString(m_ctx.GetSTDERR());
2349       success = !m_ctx.GetSTDERR().empty();
2350       break;
2351 
2352     default:
2353       break;
2354     }
2355     if (success)
2356       return SendPacket("OK");
2357     return SendPacket("E57");
2358   }
2359   return SendPacket("E58");
2360 }
2361 
2362 rnb_err_t RNBRemote::HandlePacket_QSetWorkingDir(const char *p) {
2363   // Only set the working directory if we don't already have a process
2364   if (!m_ctx.HasValidProcessID()) {
2365     StdStringExtractor packet(p += sizeof("QSetWorkingDir:") - 1);
2366     if (packet.GetHexByteString(m_ctx.GetWorkingDir())) {
2367       struct stat working_dir_stat;
2368       if (::stat(m_ctx.GetWorkingDirPath(), &working_dir_stat) == -1) {
2369         m_ctx.GetWorkingDir().clear();
2370         return SendPacket("E61"); // Working directory doesn't exist...
2371       } else if ((working_dir_stat.st_mode & S_IFMT) == S_IFDIR) {
2372         return SendPacket("OK");
2373       } else {
2374         m_ctx.GetWorkingDir().clear();
2375         return SendPacket("E62"); // Working directory isn't a directory...
2376       }
2377     }
2378     return SendPacket("E59"); // Invalid path
2379   }
2380   return SendPacket(
2381       "E60"); // Already had a process, too late to set working dir
2382 }
2383 
2384 rnb_err_t RNBRemote::HandlePacket_QSyncThreadState(const char *p) {
2385   if (!m_ctx.HasValidProcessID()) {
2386     // We allow gdb to connect to a server that hasn't started running
2387     // the target yet.  gdb still wants to ask questions about it and
2388     // freaks out if it gets an error.  So just return OK here.
2389     return SendPacket("OK");
2390   }
2391 
2392   errno = 0;
2393   p += strlen("QSyncThreadState:");
2394   nub_thread_t tid = strtoul(p, NULL, 16);
2395   if (errno != 0 && tid == 0) {
2396     return HandlePacket_ILLFORMED(
2397         __FILE__, __LINE__, p,
2398         "Invalid thread number in QSyncThreadState packet");
2399   }
2400   if (DNBProcessSyncThreadState(m_ctx.ProcessID(), tid))
2401     return SendPacket("OK");
2402   else
2403     return SendPacket("E61");
2404 }
2405 
2406 rnb_err_t RNBRemote::HandlePacket_QSetDetachOnError(const char *p) {
2407   p += sizeof("QSetDetachOnError:") - 1;
2408   bool should_detach = true;
2409   switch (*p) {
2410   case '0':
2411     should_detach = false;
2412     break;
2413   case '1':
2414     should_detach = true;
2415     break;
2416   default:
2417     return HandlePacket_ILLFORMED(
2418         __FILE__, __LINE__, p,
2419         "Invalid value for QSetDetachOnError - should be 0 or 1");
2420     break;
2421   }
2422 
2423   m_ctx.SetDetachOnError(should_detach);
2424   return SendPacket("OK");
2425 }
2426 
2427 rnb_err_t RNBRemote::HandlePacket_qStructuredDataPlugins(const char *p) {
2428   // We'll return a JSON array of supported packet types.
2429   // The type is significant.  For each of the supported
2430   // packet types that have been enabled, there will be a
2431   // 'J' async packet sent to the client with payload data.
2432   // This payload data will be a JSON dictionary, and the
2433   // top level dictionary will contain a string field with
2434   // its value set to the relevant packet type from this list.
2435   JSONGenerator::Array supported_json_packets;
2436 
2437   // Check for DarwinLog (libtrace os_log/activity support).
2438   if (DarwinLogCollector::IsSupported())
2439     supported_json_packets.AddItem(
2440         JSONGenerator::StringSP(new JSONGenerator::String("DarwinLog")));
2441 
2442   // Send back the array.
2443   std::ostringstream stream;
2444   supported_json_packets.Dump(stream);
2445   return SendPacket(stream.str());
2446 }
2447 
2448 rnb_err_t RNBRemote::HandlePacket_QConfigureDarwinLog(const char *p) {
2449   if (!DarwinLogCollector::IsSupported()) {
2450     // We should never have been given this request.
2451     return SendPacket("E89");
2452   }
2453 
2454   // Ensure we have a process.  We expect a separate configure request for
2455   // each process launched/attached.
2456   const nub_process_t pid = m_ctx.ProcessID();
2457   if (pid == INVALID_NUB_PROCESS)
2458     return SendPacket("E94");
2459 
2460   // Get the configuration dictionary.
2461   p += strlen("QConfigureDarwinLog:");
2462 
2463   // The configuration dictionary is binary encoded.
2464   std::vector<uint8_t> unescaped_config_data = decode_binary_data(p, -1);
2465   std::string unescaped_config_string((const char *)&unescaped_config_data[0],
2466                                       unescaped_config_data.size());
2467   DNBLogThreadedIf(LOG_DARWIN_LOG, "DarwinLog: received config data: \"%s\"",
2468                    unescaped_config_string.c_str());
2469   auto configuration_sp =
2470       JSONParser(unescaped_config_string.c_str()).ParseJSONValue();
2471   if (!configuration_sp) {
2472     // Malformed request - we require configuration data
2473     // indicating whether we're enabling or disabling.
2474     return SendPacket("E90");
2475   }
2476 
2477   if (!JSONObject::classof(configuration_sp.get())) {
2478     // Configuration data is not of the right type.
2479     return SendPacket("E91");
2480   }
2481   JSONObject &config_dict = *static_cast<JSONObject *>(configuration_sp.get());
2482 
2483   // Check if we're enabling or disabling.
2484   auto enabled_sp = config_dict.GetObject("enabled");
2485   if (!enabled_sp) {
2486     // Missing required "enabled" field.
2487     return SendPacket("E92");
2488   }
2489   if (!JSONTrue::classof(enabled_sp.get()) &&
2490       !JSONFalse::classof(enabled_sp.get())) {
2491     // Should be a boolean type, but wasn't.
2492     return SendPacket("E93");
2493   }
2494   const bool enabling = JSONTrue::classof(enabled_sp.get());
2495 
2496   // TODO - handle other configuration parameters here.
2497 
2498   // Shut down any active activity stream for the process.
2499   DarwinLogCollector::CancelStreamForProcess(pid);
2500 
2501   if (enabling) {
2502     // Look up the procecess.
2503     if (!DarwinLogCollector::StartCollectingForProcess(pid, config_dict))
2504       return SendPacket("E95");
2505   }
2506 
2507   return SendPacket("OK");
2508 }
2509 
2510 rnb_err_t RNBRemote::HandlePacket_QListThreadsInStopReply(const char *p) {
2511   // If this packet is received, it allows us to send an extra key/value
2512   // pair in the stop reply packets where we will list all of the thread IDs
2513   // separated by commas:
2514   //
2515   //  "threads:10a,10b,10c;"
2516   //
2517   // This will get included in the stop reply packet as something like:
2518   //
2519   //  "T11thread:10a;00:00000000;01:00010203:threads:10a,10b,10c;"
2520   //
2521   // This can save two packets on each stop: qfThreadInfo/qsThreadInfo and
2522   // speed things up a bit.
2523   //
2524   // Send the OK packet first so the correct checksum is appended...
2525   rnb_err_t result = SendPacket("OK");
2526   m_list_threads_in_stop_reply = true;
2527 
2528   return result;
2529 }
2530 
2531 rnb_err_t RNBRemote::HandlePacket_QSetMaxPayloadSize(const char *p) {
2532   /* The number of characters in a packet payload that gdb is
2533    prepared to accept.  The packet-start char, packet-end char,
2534    2 checksum chars and terminating null character are not included
2535    in this size.  */
2536   p += sizeof("QSetMaxPayloadSize:") - 1;
2537   errno = 0;
2538   uint32_t size = static_cast<uint32_t>(strtoul(p, NULL, 16));
2539   if (errno != 0 && size == 0) {
2540     return HandlePacket_ILLFORMED(
2541         __FILE__, __LINE__, p, "Invalid length in QSetMaxPayloadSize packet");
2542   }
2543   m_max_payload_size = size;
2544   return SendPacket("OK");
2545 }
2546 
2547 rnb_err_t RNBRemote::HandlePacket_QSetMaxPacketSize(const char *p) {
2548   /* This tells us the largest packet that gdb can handle.
2549    i.e. the size of gdb's packet-reading buffer.
2550    QSetMaxPayloadSize is preferred because it is less ambiguous.  */
2551   p += sizeof("QSetMaxPacketSize:") - 1;
2552   errno = 0;
2553   uint32_t size = static_cast<uint32_t>(strtoul(p, NULL, 16));
2554   if (errno != 0 && size == 0) {
2555     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
2556                                   "Invalid length in QSetMaxPacketSize packet");
2557   }
2558   m_max_payload_size = size - 5;
2559   return SendPacket("OK");
2560 }
2561 
2562 rnb_err_t RNBRemote::HandlePacket_QEnvironment(const char *p) {
2563   /* This sets the environment for the target program.  The packet is of the
2564    form:
2565 
2566    QEnvironment:VARIABLE=VALUE
2567 
2568    */
2569 
2570   DNBLogThreadedIf(
2571       LOG_RNB_REMOTE, "%8u RNBRemote::%s Handling QEnvironment: \"%s\"",
2572       (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, p);
2573 
2574   p += sizeof("QEnvironment:") - 1;
2575   RNBContext &ctx = Context();
2576 
2577   ctx.PushEnvironment(p);
2578   return SendPacket("OK");
2579 }
2580 
2581 rnb_err_t RNBRemote::HandlePacket_QEnvironmentHexEncoded(const char *p) {
2582   /* This sets the environment for the target program.  The packet is of the
2583      form:
2584 
2585       QEnvironmentHexEncoded:VARIABLE=VALUE
2586 
2587       The VARIABLE=VALUE part is sent hex-encoded so characters like '#' with
2588      special
2589       meaning in the remote protocol won't break it.
2590   */
2591 
2592   DNBLogThreadedIf(LOG_RNB_REMOTE,
2593                    "%8u RNBRemote::%s Handling QEnvironmentHexEncoded: \"%s\"",
2594                    (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
2595                    __FUNCTION__, p);
2596 
2597   p += sizeof("QEnvironmentHexEncoded:") - 1;
2598 
2599   std::string arg;
2600   const char *c;
2601   c = p;
2602   while (*c != '\0') {
2603     if (*(c + 1) == '\0') {
2604       return HandlePacket_ILLFORMED(
2605           __FILE__, __LINE__, p,
2606           "non-hex char in arg on 'QEnvironmentHexEncoded' pkt");
2607     }
2608     char smallbuf[3];
2609     smallbuf[0] = *c;
2610     smallbuf[1] = *(c + 1);
2611     smallbuf[2] = '\0';
2612     errno = 0;
2613     int ch = static_cast<int>(strtoul(smallbuf, NULL, 16));
2614     if (errno != 0 && ch == 0) {
2615       return HandlePacket_ILLFORMED(
2616           __FILE__, __LINE__, p,
2617           "non-hex char in arg on 'QEnvironmentHexEncoded' pkt");
2618     }
2619     arg.push_back(ch);
2620     c += 2;
2621   }
2622 
2623   RNBContext &ctx = Context();
2624   if (arg.length() > 0)
2625     ctx.PushEnvironment(arg.c_str());
2626 
2627   return SendPacket("OK");
2628 }
2629 
2630 rnb_err_t RNBRemote::HandlePacket_QLaunchArch(const char *p) {
2631   p += sizeof("QLaunchArch:") - 1;
2632   if (DNBSetArchitecture(p))
2633     return SendPacket("OK");
2634   return SendPacket("E63");
2635 }
2636 
2637 rnb_err_t RNBRemote::HandlePacket_QSetProcessEvent(const char *p) {
2638   p += sizeof("QSetProcessEvent:") - 1;
2639   // If the process is running, then send the event to the process, otherwise
2640   // store it in the context.
2641   if (Context().HasValidProcessID()) {
2642     if (DNBProcessSendEvent(Context().ProcessID(), p))
2643       return SendPacket("OK");
2644     else
2645       return SendPacket("E80");
2646   } else {
2647     Context().PushProcessEvent(p);
2648   }
2649   return SendPacket("OK");
2650 }
2651 
2652 void append_hex_value(std::ostream &ostrm, const void *buf, size_t buf_size,
2653                       bool swap) {
2654   int i;
2655   const uint8_t *p = (const uint8_t *)buf;
2656   if (swap) {
2657     for (i = static_cast<int>(buf_size) - 1; i >= 0; i--)
2658       ostrm << RAWHEX8(p[i]);
2659   } else {
2660     for (size_t i = 0; i < buf_size; i++)
2661       ostrm << RAWHEX8(p[i]);
2662   }
2663 }
2664 
2665 void append_hexified_string(std::ostream &ostrm, const std::string &string) {
2666   size_t string_size = string.size();
2667   const char *string_buf = string.c_str();
2668   for (size_t i = 0; i < string_size; i++) {
2669     ostrm << RAWHEX8(*(string_buf + i));
2670   }
2671 }
2672 
2673 void register_value_in_hex_fixed_width(std::ostream &ostrm, nub_process_t pid,
2674                                        nub_thread_t tid,
2675                                        const register_map_entry_t *reg,
2676                                        const DNBRegisterValue *reg_value_ptr) {
2677   if (reg != NULL) {
2678     DNBRegisterValue reg_value;
2679     if (reg_value_ptr == NULL) {
2680       if (DNBThreadGetRegisterValueByID(pid, tid, reg->nub_info.set,
2681                                         reg->nub_info.reg, &reg_value))
2682         reg_value_ptr = &reg_value;
2683     }
2684 
2685     if (reg_value_ptr) {
2686       append_hex_value(ostrm, reg_value_ptr->value.v_uint8, reg->nub_info.size,
2687                        false);
2688     } else {
2689       // If we fail to read a register value, check if it has a default
2690       // fail value. If it does, return this instead in case some of
2691       // the registers are not available on the current system.
2692       if (reg->nub_info.size > 0) {
2693         std::basic_string<uint8_t> zeros(reg->nub_info.size, '\0');
2694         append_hex_value(ostrm, zeros.data(), zeros.size(), false);
2695       }
2696     }
2697   }
2698 }
2699 
2700 void debugserver_regnum_with_fixed_width_hex_register_value(
2701     std::ostream &ostrm, nub_process_t pid, nub_thread_t tid,
2702     const register_map_entry_t *reg, const DNBRegisterValue *reg_value_ptr) {
2703   // Output the register number as 'NN:VVVVVVVV;' where NN is a 2 bytes HEX
2704   // gdb register number, and VVVVVVVV is the correct number of hex bytes
2705   // as ASCII for the register value.
2706   if (reg != NULL) {
2707     ostrm << RAWHEX8(reg->debugserver_regnum) << ':';
2708     register_value_in_hex_fixed_width(ostrm, pid, tid, reg, reg_value_ptr);
2709     ostrm << ';';
2710   }
2711 }
2712 
2713 void RNBRemote::DispatchQueueOffsets::GetThreadQueueInfo(
2714     nub_process_t pid, nub_addr_t dispatch_qaddr, nub_addr_t &dispatch_queue_t,
2715     std::string &queue_name, uint64_t &queue_width,
2716     uint64_t &queue_serialnum) const {
2717   queue_name.clear();
2718   queue_width = 0;
2719   queue_serialnum = 0;
2720 
2721   if (IsValid() && dispatch_qaddr != INVALID_NUB_ADDRESS &&
2722       dispatch_qaddr != 0) {
2723     dispatch_queue_t = DNBProcessMemoryReadPointer(pid, dispatch_qaddr);
2724     if (dispatch_queue_t) {
2725       queue_width = DNBProcessMemoryReadInteger(
2726           pid, dispatch_queue_t + dqo_width, dqo_width_size, 0);
2727       queue_serialnum = DNBProcessMemoryReadInteger(
2728           pid, dispatch_queue_t + dqo_serialnum, dqo_serialnum_size, 0);
2729 
2730       if (dqo_version >= 4) {
2731         // libdispatch versions 4+, pointer to dispatch name is in the
2732         // queue structure.
2733         nub_addr_t pointer_to_label_address = dispatch_queue_t + dqo_label;
2734         nub_addr_t label_addr =
2735             DNBProcessMemoryReadPointer(pid, pointer_to_label_address);
2736         if (label_addr)
2737           queue_name = DNBProcessMemoryReadCString(pid, label_addr);
2738       } else {
2739         // libdispatch versions 1-3, dispatch name is a fixed width char array
2740         // in the queue structure.
2741         queue_name = DNBProcessMemoryReadCStringFixed(
2742             pid, dispatch_queue_t + dqo_label, dqo_label_size);
2743       }
2744     }
2745   }
2746 }
2747 
2748 struct StackMemory {
2749   uint8_t bytes[2 * sizeof(nub_addr_t)];
2750   nub_size_t length;
2751 };
2752 typedef std::map<nub_addr_t, StackMemory> StackMemoryMap;
2753 
2754 static void ReadStackMemory(nub_process_t pid, nub_thread_t tid,
2755                             StackMemoryMap &stack_mmap,
2756                             uint32_t backtrace_limit = 256) {
2757   DNBRegisterValue reg_value;
2758   if (DNBThreadGetRegisterValueByID(pid, tid, REGISTER_SET_GENERIC,
2759                                     GENERIC_REGNUM_FP, &reg_value)) {
2760     uint32_t frame_count = 0;
2761     uint64_t fp = 0;
2762     if (reg_value.info.size == 4)
2763       fp = reg_value.value.uint32;
2764     else
2765       fp = reg_value.value.uint64;
2766     while (fp != 0) {
2767       // Make sure we never recurse more than 256 times so we don't recurse too
2768       // far or
2769       // store up too much memory in the expedited cache
2770       if (++frame_count > backtrace_limit)
2771         break;
2772 
2773       const nub_size_t read_size = reg_value.info.size * 2;
2774       StackMemory stack_memory;
2775       stack_memory.length = read_size;
2776       if (DNBProcessMemoryRead(pid, fp, read_size, stack_memory.bytes) !=
2777           read_size)
2778         break;
2779       // Make sure we don't try to put the same stack memory in more than once
2780       if (stack_mmap.find(fp) != stack_mmap.end())
2781         break;
2782       // Put the entry into the cache
2783       stack_mmap[fp] = stack_memory;
2784       // Dereference the frame pointer to get to the previous frame pointer
2785       if (reg_value.info.size == 4)
2786         fp = ((uint32_t *)stack_memory.bytes)[0];
2787       else
2788         fp = ((uint64_t *)stack_memory.bytes)[0];
2789     }
2790   }
2791 }
2792 
2793 rnb_err_t RNBRemote::SendStopReplyPacketForThread(nub_thread_t tid) {
2794   const nub_process_t pid = m_ctx.ProcessID();
2795   if (pid == INVALID_NUB_PROCESS)
2796     return SendPacket("E50");
2797 
2798   struct DNBThreadStopInfo tid_stop_info;
2799 
2800   /* Fill the remaining space in this packet with as many registers
2801    as we can stuff in there.  */
2802 
2803   if (DNBThreadGetStopReason(pid, tid, &tid_stop_info)) {
2804     const bool did_exec = tid_stop_info.reason == eStopTypeExec;
2805     if (did_exec) {
2806       RNBRemote::InitializeRegisters(true);
2807 
2808       // Reset any symbols that need resetting when we exec
2809       m_dispatch_queue_offsets_addr = INVALID_NUB_ADDRESS;
2810       m_dispatch_queue_offsets.Clear();
2811     }
2812 
2813     std::ostringstream ostrm;
2814     // Output the T packet with the thread
2815     ostrm << 'T';
2816     int signum = tid_stop_info.details.signal.signo;
2817     DNBLogThreadedIf(
2818         LOG_RNB_PROC, "%8d %s got signal signo = %u, exc_type = %u",
2819         (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__,
2820         signum, tid_stop_info.details.exception.type);
2821 
2822     // Translate any mach exceptions to gdb versions, unless they are
2823     // common exceptions like a breakpoint or a soft signal.
2824     switch (tid_stop_info.details.exception.type) {
2825     default:
2826       signum = 0;
2827       break;
2828     case EXC_BREAKPOINT:
2829       signum = SIGTRAP;
2830       break;
2831     case EXC_BAD_ACCESS:
2832       signum = TARGET_EXC_BAD_ACCESS;
2833       break;
2834     case EXC_BAD_INSTRUCTION:
2835       signum = TARGET_EXC_BAD_INSTRUCTION;
2836       break;
2837     case EXC_ARITHMETIC:
2838       signum = TARGET_EXC_ARITHMETIC;
2839       break;
2840     case EXC_EMULATION:
2841       signum = TARGET_EXC_EMULATION;
2842       break;
2843     case EXC_SOFTWARE:
2844       if (tid_stop_info.details.exception.data_count == 2 &&
2845           tid_stop_info.details.exception.data[0] == EXC_SOFT_SIGNAL)
2846         signum = static_cast<int>(tid_stop_info.details.exception.data[1]);
2847       else
2848         signum = TARGET_EXC_SOFTWARE;
2849       break;
2850     }
2851 
2852     ostrm << RAWHEX8(signum & 0xff);
2853 
2854     ostrm << std::hex << "thread:" << tid << ';';
2855 
2856     const char *thread_name = DNBThreadGetName(pid, tid);
2857     if (thread_name && thread_name[0]) {
2858       size_t thread_name_len = strlen(thread_name);
2859 
2860       if (::strcspn(thread_name, "$#+-;:") == thread_name_len)
2861         ostrm << std::hex << "name:" << thread_name << ';';
2862       else {
2863         // the thread name contains special chars, send as hex bytes
2864         ostrm << std::hex << "hexname:";
2865         uint8_t *u_thread_name = (uint8_t *)thread_name;
2866         for (size_t i = 0; i < thread_name_len; i++)
2867           ostrm << RAWHEX8(u_thread_name[i]);
2868         ostrm << ';';
2869       }
2870     }
2871 
2872     // If a 'QListThreadsInStopReply' was sent to enable this feature, we
2873     // will send all thread IDs back in the "threads" key whose value is
2874     // a list of hex thread IDs separated by commas:
2875     //  "threads:10a,10b,10c;"
2876     // This will save the debugger from having to send a pair of qfThreadInfo
2877     // and qsThreadInfo packets, but it also might take a lot of room in the
2878     // stop reply packet, so it must be enabled only on systems where there
2879     // are no limits on packet lengths.
2880     if (m_list_threads_in_stop_reply) {
2881       const nub_size_t numthreads = DNBProcessGetNumThreads(pid);
2882       if (numthreads > 0) {
2883         std::vector<uint64_t> pc_values;
2884         ostrm << std::hex << "threads:";
2885         for (nub_size_t i = 0; i < numthreads; ++i) {
2886           nub_thread_t th = DNBProcessGetThreadAtIndex(pid, i);
2887           if (i > 0)
2888             ostrm << ',';
2889           ostrm << std::hex << th;
2890           DNBRegisterValue pc_regval;
2891           if (DNBThreadGetRegisterValueByID(pid, th, REGISTER_SET_GENERIC,
2892                                             GENERIC_REGNUM_PC, &pc_regval)) {
2893             uint64_t pc = INVALID_NUB_ADDRESS;
2894             if (pc_regval.value.uint64 != INVALID_NUB_ADDRESS) {
2895               if (pc_regval.info.size == 4) {
2896                 pc = pc_regval.value.uint32;
2897               } else if (pc_regval.info.size == 8) {
2898                 pc = pc_regval.value.uint64;
2899               }
2900               if (pc != INVALID_NUB_ADDRESS) {
2901                 pc_values.push_back(pc);
2902               }
2903             }
2904           }
2905         }
2906         ostrm << ';';
2907 
2908         // If we failed to get any of the thread pc values, the size of our
2909         // vector will not
2910         // be the same as the # of threads.  Don't provide any expedited thread
2911         // pc values in
2912         // that case.  This should not happen.
2913         if (pc_values.size() == numthreads) {
2914           ostrm << std::hex << "thread-pcs:";
2915           for (nub_size_t i = 0; i < numthreads; ++i) {
2916             if (i > 0)
2917               ostrm << ',';
2918             ostrm << std::hex << pc_values[i];
2919           }
2920           ostrm << ';';
2921         }
2922       }
2923 
2924       // Include JSON info that describes the stop reason for any threads
2925       // that actually have stop reasons. We use the new "jstopinfo" key
2926       // whose values is hex ascii JSON that contains the thread IDs
2927       // thread stop info only for threads that have stop reasons. Only send
2928       // this if we have more than one thread otherwise this packet has all
2929       // the info it needs.
2930       if (numthreads > 1) {
2931         const bool threads_with_valid_stop_info_only = true;
2932         JSONGenerator::ObjectSP threads_info_sp =
2933             GetJSONThreadsInfo(threads_with_valid_stop_info_only);
2934         if (threads_info_sp) {
2935           ostrm << std::hex << "jstopinfo:";
2936           std::ostringstream json_strm;
2937           threads_info_sp->Dump(json_strm);
2938           append_hexified_string(ostrm, json_strm.str());
2939           ostrm << ';';
2940         }
2941       }
2942     }
2943 
2944     if (g_num_reg_entries == 0)
2945       InitializeRegisters();
2946 
2947     if (g_reg_entries != NULL) {
2948       DNBRegisterValue reg_value;
2949       for (uint32_t reg = 0; reg < g_num_reg_entries; reg++) {
2950         // Expedite all registers in the first register set that aren't
2951         // contained in other registers
2952         if (g_reg_entries[reg].nub_info.set == 1 &&
2953             g_reg_entries[reg].nub_info.value_regs == NULL) {
2954           if (!DNBThreadGetRegisterValueByID(
2955                   pid, tid, g_reg_entries[reg].nub_info.set,
2956                   g_reg_entries[reg].nub_info.reg, &reg_value))
2957             continue;
2958 
2959           debugserver_regnum_with_fixed_width_hex_register_value(
2960               ostrm, pid, tid, &g_reg_entries[reg], &reg_value);
2961         }
2962       }
2963     }
2964 
2965     if (did_exec) {
2966       ostrm << "reason:exec;";
2967     } else if (tid_stop_info.details.exception.type) {
2968       ostrm << "metype:" << std::hex << tid_stop_info.details.exception.type
2969             << ';';
2970       ostrm << "mecount:" << std::hex
2971             << tid_stop_info.details.exception.data_count << ';';
2972       for (nub_size_t i = 0; i < tid_stop_info.details.exception.data_count;
2973            ++i)
2974         ostrm << "medata:" << std::hex
2975               << tid_stop_info.details.exception.data[i] << ';';
2976     }
2977 
2978     // Add expedited stack memory so stack backtracing doesn't need to read
2979     // anything from the
2980     // frame pointer chain.
2981     StackMemoryMap stack_mmap;
2982     ReadStackMemory(pid, tid, stack_mmap, 2);
2983     if (!stack_mmap.empty()) {
2984       for (const auto &stack_memory : stack_mmap) {
2985         ostrm << "memory:" << HEXBASE << stack_memory.first << '=';
2986         append_hex_value(ostrm, stack_memory.second.bytes,
2987                          stack_memory.second.length, false);
2988         ostrm << ';';
2989       }
2990     }
2991 
2992     return SendPacket(ostrm.str());
2993   }
2994   return SendPacket("E51");
2995 }
2996 
2997 /* '?'
2998  The stop reply packet - tell gdb what the status of the inferior is.
2999  Often called the questionmark_packet.  */
3000 
3001 rnb_err_t RNBRemote::HandlePacket_last_signal(const char *unused) {
3002   if (!m_ctx.HasValidProcessID()) {
3003     // Inferior is not yet specified/running
3004     return SendPacket("E02");
3005   }
3006 
3007   nub_process_t pid = m_ctx.ProcessID();
3008   nub_state_t pid_state = DNBProcessGetState(pid);
3009 
3010   switch (pid_state) {
3011   case eStateAttaching:
3012   case eStateLaunching:
3013   case eStateRunning:
3014   case eStateStepping:
3015   case eStateDetached:
3016     return rnb_success; // Ignore
3017 
3018   case eStateSuspended:
3019   case eStateStopped:
3020   case eStateCrashed: {
3021     nub_thread_t tid = DNBProcessGetCurrentThread(pid);
3022     // Make sure we set the current thread so g and p packets return
3023     // the data the gdb will expect.
3024     SetCurrentThread(tid);
3025 
3026     SendStopReplyPacketForThread(tid);
3027   } break;
3028 
3029   case eStateInvalid:
3030   case eStateUnloaded:
3031   case eStateExited: {
3032     char pid_exited_packet[16] = "";
3033     int pid_status = 0;
3034     // Process exited with exit status
3035     if (!DNBProcessGetExitStatus(pid, &pid_status))
3036       pid_status = 0;
3037 
3038     if (pid_status) {
3039       if (WIFEXITED(pid_status))
3040         snprintf(pid_exited_packet, sizeof(pid_exited_packet), "W%02x",
3041                  WEXITSTATUS(pid_status));
3042       else if (WIFSIGNALED(pid_status))
3043         snprintf(pid_exited_packet, sizeof(pid_exited_packet), "X%02x",
3044                  WEXITSTATUS(pid_status));
3045       else if (WIFSTOPPED(pid_status))
3046         snprintf(pid_exited_packet, sizeof(pid_exited_packet), "S%02x",
3047                  WSTOPSIG(pid_status));
3048     }
3049 
3050     // If we have an empty exit packet, lets fill one in to be safe.
3051     if (!pid_exited_packet[0]) {
3052       strncpy(pid_exited_packet, "W00", sizeof(pid_exited_packet) - 1);
3053       pid_exited_packet[sizeof(pid_exited_packet) - 1] = '\0';
3054     }
3055 
3056     const char *exit_info = DNBProcessGetExitInfo(pid);
3057     if (exit_info != NULL && *exit_info != '\0') {
3058       std::ostringstream exit_packet;
3059       exit_packet << pid_exited_packet;
3060       exit_packet << ';';
3061       exit_packet << RAW_HEXBASE << "description";
3062       exit_packet << ':';
3063       for (size_t i = 0; exit_info[i] != '\0'; i++)
3064         exit_packet << RAWHEX8(exit_info[i]);
3065       exit_packet << ';';
3066       return SendPacket(exit_packet.str());
3067     } else
3068       return SendPacket(pid_exited_packet);
3069   } break;
3070   }
3071   return rnb_success;
3072 }
3073 
3074 rnb_err_t RNBRemote::HandlePacket_M(const char *p) {
3075   if (p == NULL || p[0] == '\0' || strlen(p) < 3) {
3076     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, "Too short M packet");
3077   }
3078 
3079   char *c;
3080   p++;
3081   errno = 0;
3082   nub_addr_t addr = strtoull(p, &c, 16);
3083   if (errno != 0 && addr == 0) {
3084     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3085                                   "Invalid address in M packet");
3086   }
3087   if (*c != ',') {
3088     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3089                                   "Comma sep missing in M packet");
3090   }
3091 
3092   /* Advance 'p' to the length part of the packet.  */
3093   p += (c - p) + 1;
3094 
3095   errno = 0;
3096   unsigned long length = strtoul(p, &c, 16);
3097   if (errno != 0 && length == 0) {
3098     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3099                                   "Invalid length in M packet");
3100   }
3101   if (length == 0) {
3102     return SendPacket("OK");
3103   }
3104 
3105   if (*c != ':') {
3106     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3107                                   "Missing colon in M packet");
3108   }
3109   /* Advance 'p' to the data part of the packet.  */
3110   p += (c - p) + 1;
3111 
3112   size_t datalen = strlen(p);
3113   if (datalen & 0x1) {
3114     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3115                                   "Uneven # of hex chars for data in M packet");
3116   }
3117   if (datalen == 0) {
3118     return SendPacket("OK");
3119   }
3120 
3121   uint8_t *buf = (uint8_t *)alloca(datalen / 2);
3122   uint8_t *i = buf;
3123 
3124   while (*p != '\0' && *(p + 1) != '\0') {
3125     char hexbuf[3];
3126     hexbuf[0] = *p;
3127     hexbuf[1] = *(p + 1);
3128     hexbuf[2] = '\0';
3129     errno = 0;
3130     uint8_t byte = strtoul(hexbuf, NULL, 16);
3131     if (errno != 0 && byte == 0) {
3132       return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3133                                     "Invalid hex byte in M packet");
3134     }
3135     *i++ = byte;
3136     p += 2;
3137   }
3138 
3139   nub_size_t wrote =
3140       DNBProcessMemoryWrite(m_ctx.ProcessID(), addr, length, buf);
3141   if (wrote != length)
3142     return SendPacket("E09");
3143   else
3144     return SendPacket("OK");
3145 }
3146 
3147 rnb_err_t RNBRemote::HandlePacket_m(const char *p) {
3148   if (p == NULL || p[0] == '\0' || strlen(p) < 3) {
3149     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, "Too short m packet");
3150   }
3151 
3152   char *c;
3153   p++;
3154   errno = 0;
3155   nub_addr_t addr = strtoull(p, &c, 16);
3156   if (errno != 0 && addr == 0) {
3157     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3158                                   "Invalid address in m packet");
3159   }
3160   if (*c != ',') {
3161     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3162                                   "Comma sep missing in m packet");
3163   }
3164 
3165   /* Advance 'p' to the length part of the packet.  */
3166   p += (c - p) + 1;
3167 
3168   errno = 0;
3169   auto length = strtoul(p, NULL, 16);
3170   if (errno != 0 && length == 0) {
3171     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3172                                   "Invalid length in m packet");
3173   }
3174   if (length == 0) {
3175     return SendPacket("");
3176   }
3177 
3178   std::string buf(length, '\0');
3179   if (buf.empty()) {
3180     return SendPacket("E78");
3181   }
3182   nub_size_t bytes_read =
3183       DNBProcessMemoryRead(m_ctx.ProcessID(), addr, buf.size(), &buf[0]);
3184   if (bytes_read == 0) {
3185     return SendPacket("E08");
3186   }
3187 
3188   // "The reply may contain fewer bytes than requested if the server was able
3189   //  to read only part of the region of memory."
3190   length = bytes_read;
3191 
3192   std::ostringstream ostrm;
3193   for (unsigned long i = 0; i < length; i++)
3194     ostrm << RAWHEX8(buf[i]);
3195   return SendPacket(ostrm.str());
3196 }
3197 
3198 // Read memory, sent it up as binary data.
3199 // Usage:  xADDR,LEN
3200 // ADDR and LEN are both base 16.
3201 
3202 // Responds with 'OK' for zero-length request
3203 // or
3204 //
3205 // DATA
3206 //
3207 // where DATA is the binary data payload.
3208 
3209 rnb_err_t RNBRemote::HandlePacket_x(const char *p) {
3210   if (p == NULL || p[0] == '\0' || strlen(p) < 3) {
3211     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, "Too short X packet");
3212   }
3213 
3214   char *c;
3215   p++;
3216   errno = 0;
3217   nub_addr_t addr = strtoull(p, &c, 16);
3218   if (errno != 0) {
3219     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3220                                   "Invalid address in X packet");
3221   }
3222   if (*c != ',') {
3223     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3224                                   "Comma sep missing in X packet");
3225   }
3226 
3227   /* Advance 'p' to the number of bytes to be read.  */
3228   p += (c - p) + 1;
3229 
3230   errno = 0;
3231   auto length = strtoul(p, NULL, 16);
3232   if (errno != 0) {
3233     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3234                                   "Invalid length in x packet");
3235   }
3236 
3237   // zero length read means this is a test of whether that packet is implemented
3238   // or not.
3239   if (length == 0) {
3240     return SendPacket("OK");
3241   }
3242 
3243   std::vector<uint8_t> buf(length);
3244 
3245   if (buf.capacity() != length) {
3246     return SendPacket("E79");
3247   }
3248   nub_size_t bytes_read =
3249       DNBProcessMemoryRead(m_ctx.ProcessID(), addr, buf.size(), &buf[0]);
3250   if (bytes_read == 0) {
3251     return SendPacket("E80");
3252   }
3253 
3254   std::vector<uint8_t> buf_quoted;
3255   buf_quoted.reserve(bytes_read + 30);
3256   for (nub_size_t i = 0; i < bytes_read; i++) {
3257     if (buf[i] == '#' || buf[i] == '$' || buf[i] == '}' || buf[i] == '*') {
3258       buf_quoted.push_back(0x7d);
3259       buf_quoted.push_back(buf[i] ^ 0x20);
3260     } else {
3261       buf_quoted.push_back(buf[i]);
3262     }
3263   }
3264   length = buf_quoted.size();
3265 
3266   std::ostringstream ostrm;
3267   for (unsigned long i = 0; i < length; i++)
3268     ostrm << buf_quoted[i];
3269 
3270   return SendPacket(ostrm.str());
3271 }
3272 
3273 rnb_err_t RNBRemote::HandlePacket_X(const char *p) {
3274   if (p == NULL || p[0] == '\0' || strlen(p) < 3) {
3275     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, "Too short X packet");
3276   }
3277 
3278   char *c;
3279   p++;
3280   errno = 0;
3281   nub_addr_t addr = strtoull(p, &c, 16);
3282   if (errno != 0 && addr == 0) {
3283     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3284                                   "Invalid address in X packet");
3285   }
3286   if (*c != ',') {
3287     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3288                                   "Comma sep missing in X packet");
3289   }
3290 
3291   /* Advance 'p' to the length part of the packet.  NB this is the length of the
3292      packet
3293      including any escaped chars.  The data payload may be a little bit smaller
3294      after
3295      decoding.  */
3296   p += (c - p) + 1;
3297 
3298   errno = 0;
3299   auto length = strtoul(p, NULL, 16);
3300   if (errno != 0 && length == 0) {
3301     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3302                                   "Invalid length in X packet");
3303   }
3304 
3305   // I think gdb sends a zero length write request to test whether this
3306   // packet is accepted.
3307   if (length == 0) {
3308     return SendPacket("OK");
3309   }
3310 
3311   std::vector<uint8_t> data = decode_binary_data(c, -1);
3312   std::vector<uint8_t>::const_iterator it;
3313   uint8_t *buf = (uint8_t *)alloca(data.size());
3314   uint8_t *i = buf;
3315   for (it = data.begin(); it != data.end(); ++it) {
3316     *i++ = *it;
3317   }
3318 
3319   nub_size_t wrote =
3320       DNBProcessMemoryWrite(m_ctx.ProcessID(), addr, data.size(), buf);
3321   if (wrote != data.size())
3322     return SendPacket("E08");
3323   return SendPacket("OK");
3324 }
3325 
3326 /* 'g' -- read registers
3327  Get the contents of the registers for the current thread,
3328  send them to gdb.
3329  Should the setting of the Hg packet determine which thread's registers
3330  are returned?  */
3331 
3332 rnb_err_t RNBRemote::HandlePacket_g(const char *p) {
3333   std::ostringstream ostrm;
3334   if (!m_ctx.HasValidProcessID()) {
3335     return SendPacket("E11");
3336   }
3337 
3338   if (g_num_reg_entries == 0)
3339     InitializeRegisters();
3340 
3341   nub_process_t pid = m_ctx.ProcessID();
3342   nub_thread_t tid = ExtractThreadIDFromThreadSuffix(p + 1);
3343   if (tid == INVALID_NUB_THREAD)
3344     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3345                                   "No thread specified in p packet");
3346 
3347   // Get the register context size first by calling with NULL buffer
3348   nub_size_t reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, NULL, 0);
3349   if (reg_ctx_size) {
3350     // Now allocate enough space for the entire register context
3351     std::vector<uint8_t> reg_ctx;
3352     reg_ctx.resize(reg_ctx_size);
3353     // Now read the register context
3354     reg_ctx_size =
3355         DNBThreadGetRegisterContext(pid, tid, &reg_ctx[0], reg_ctx.size());
3356     if (reg_ctx_size) {
3357       append_hex_value(ostrm, reg_ctx.data(), reg_ctx.size(), false);
3358       return SendPacket(ostrm.str());
3359     }
3360   }
3361   return SendPacket("E74");
3362 }
3363 
3364 /* 'G XXX...' -- write registers
3365  How is the thread for these specified, beyond "the current thread"?
3366  Does gdb actually use the Hg packet to set this?  */
3367 
3368 rnb_err_t RNBRemote::HandlePacket_G(const char *p) {
3369   if (!m_ctx.HasValidProcessID()) {
3370     return SendPacket("E11");
3371   }
3372 
3373   if (g_num_reg_entries == 0)
3374     InitializeRegisters();
3375 
3376   StdStringExtractor packet(p);
3377   packet.SetFilePos(1); // Skip the 'G'
3378 
3379   nub_process_t pid = m_ctx.ProcessID();
3380   nub_thread_t tid = ExtractThreadIDFromThreadSuffix(p);
3381   if (tid == INVALID_NUB_THREAD)
3382     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3383                                   "No thread specified in p packet");
3384 
3385   // Get the register context size first by calling with NULL buffer
3386   nub_size_t reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, NULL, 0);
3387   if (reg_ctx_size) {
3388     // Now allocate enough space for the entire register context
3389     std::vector<uint8_t> reg_ctx;
3390     reg_ctx.resize(reg_ctx_size);
3391 
3392     const nub_size_t bytes_extracted =
3393         packet.GetHexBytes(&reg_ctx[0], reg_ctx.size(), 0xcc);
3394     if (bytes_extracted == reg_ctx.size()) {
3395       // Now write the register context
3396       reg_ctx_size =
3397           DNBThreadSetRegisterContext(pid, tid, reg_ctx.data(), reg_ctx.size());
3398       if (reg_ctx_size == reg_ctx.size())
3399         return SendPacket("OK");
3400       else
3401         return SendPacket("E55");
3402     } else {
3403       DNBLogError("RNBRemote::HandlePacket_G(%s): extracted %llu of %llu "
3404                   "bytes, size mismatch\n",
3405                   p, (uint64_t)bytes_extracted, (uint64_t)reg_ctx_size);
3406       return SendPacket("E64");
3407     }
3408   }
3409   return SendPacket("E65");
3410 }
3411 
3412 static bool RNBRemoteShouldCancelCallback(void *not_used) {
3413   RNBRemoteSP remoteSP(g_remoteSP);
3414   if (remoteSP.get() != NULL) {
3415     RNBRemote *remote = remoteSP.get();
3416     if (remote->Comm().IsConnected())
3417       return false;
3418     else
3419       return true;
3420   }
3421   return true;
3422 }
3423 
3424 // FORMAT: _MXXXXXX,PPP
3425 //      XXXXXX: big endian hex chars
3426 //      PPP: permissions can be any combo of r w x chars
3427 //
3428 // RESPONSE: XXXXXX
3429 //      XXXXXX: hex address of the newly allocated memory
3430 //      EXX: error code
3431 //
3432 // EXAMPLES:
3433 //      _M123000,rw
3434 //      _M123000,rwx
3435 //      _M123000,xw
3436 
3437 rnb_err_t RNBRemote::HandlePacket_AllocateMemory(const char *p) {
3438   StdStringExtractor packet(p);
3439   packet.SetFilePos(2); // Skip the "_M"
3440 
3441   nub_addr_t size = packet.GetHexMaxU64(StdStringExtractor::BigEndian, 0);
3442   if (size != 0) {
3443     if (packet.GetChar() == ',') {
3444       uint32_t permissions = 0;
3445       char ch;
3446       bool success = true;
3447       while (success && (ch = packet.GetChar()) != '\0') {
3448         switch (ch) {
3449         case 'r':
3450           permissions |= eMemoryPermissionsReadable;
3451           break;
3452         case 'w':
3453           permissions |= eMemoryPermissionsWritable;
3454           break;
3455         case 'x':
3456           permissions |= eMemoryPermissionsExecutable;
3457           break;
3458         default:
3459           success = false;
3460           break;
3461         }
3462       }
3463 
3464       if (success) {
3465         nub_addr_t addr =
3466             DNBProcessMemoryAllocate(m_ctx.ProcessID(), size, permissions);
3467         if (addr != INVALID_NUB_ADDRESS) {
3468           std::ostringstream ostrm;
3469           ostrm << RAW_HEXBASE << addr;
3470           return SendPacket(ostrm.str());
3471         }
3472       }
3473     }
3474   }
3475   return SendPacket("E53");
3476 }
3477 
3478 // FORMAT: _mXXXXXX
3479 //      XXXXXX: address that was previously allocated
3480 //
3481 // RESPONSE: XXXXXX
3482 //      OK: address was deallocated
3483 //      EXX: error code
3484 //
3485 // EXAMPLES:
3486 //      _m123000
3487 
3488 rnb_err_t RNBRemote::HandlePacket_DeallocateMemory(const char *p) {
3489   StdStringExtractor packet(p);
3490   packet.SetFilePos(2); // Skip the "_m"
3491   nub_addr_t addr =
3492       packet.GetHexMaxU64(StdStringExtractor::BigEndian, INVALID_NUB_ADDRESS);
3493 
3494   if (addr != INVALID_NUB_ADDRESS) {
3495     if (DNBProcessMemoryDeallocate(m_ctx.ProcessID(), addr))
3496       return SendPacket("OK");
3497   }
3498   return SendPacket("E54");
3499 }
3500 
3501 // FORMAT: QSaveRegisterState;thread:TTTT;  (when thread suffix is supported)
3502 // FORMAT: QSaveRegisterState               (when thread suffix is NOT
3503 // supported)
3504 //      TTTT: thread ID in hex
3505 //
3506 // RESPONSE:
3507 //      SAVEID: Where SAVEID is a decimal number that represents the save ID
3508 //              that can be passed back into a "QRestoreRegisterState" packet
3509 //      EXX: error code
3510 //
3511 // EXAMPLES:
3512 //      QSaveRegisterState;thread:1E34;     (when thread suffix is supported)
3513 //      QSaveRegisterState                  (when thread suffix is NOT
3514 //      supported)
3515 
3516 rnb_err_t RNBRemote::HandlePacket_SaveRegisterState(const char *p) {
3517   nub_process_t pid = m_ctx.ProcessID();
3518   nub_thread_t tid = ExtractThreadIDFromThreadSuffix(p);
3519   if (tid == INVALID_NUB_THREAD) {
3520     if (m_thread_suffix_supported)
3521       return HandlePacket_ILLFORMED(
3522           __FILE__, __LINE__, p,
3523           "No thread specified in QSaveRegisterState packet");
3524     else
3525       return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3526                                     "No thread was is set with the Hg packet");
3527   }
3528 
3529   // Get the register context size first by calling with NULL buffer
3530   const uint32_t save_id = DNBThreadSaveRegisterState(pid, tid);
3531   if (save_id != 0) {
3532     char response[64];
3533     snprintf(response, sizeof(response), "%u", save_id);
3534     return SendPacket(response);
3535   } else {
3536     return SendPacket("E75");
3537   }
3538 }
3539 // FORMAT: QRestoreRegisterState:SAVEID;thread:TTTT;  (when thread suffix is
3540 // supported)
3541 // FORMAT: QRestoreRegisterState:SAVEID               (when thread suffix is NOT
3542 // supported)
3543 //      TTTT: thread ID in hex
3544 //      SAVEID: a decimal number that represents the save ID that was
3545 //              returned from a call to "QSaveRegisterState"
3546 //
3547 // RESPONSE:
3548 //      OK: successfully restored registers for the specified thread
3549 //      EXX: error code
3550 //
3551 // EXAMPLES:
3552 //      QRestoreRegisterState:1;thread:1E34;     (when thread suffix is
3553 //      supported)
3554 //      QRestoreRegisterState:1                  (when thread suffix is NOT
3555 //      supported)
3556 
3557 rnb_err_t RNBRemote::HandlePacket_RestoreRegisterState(const char *p) {
3558   nub_process_t pid = m_ctx.ProcessID();
3559   nub_thread_t tid = ExtractThreadIDFromThreadSuffix(p);
3560   if (tid == INVALID_NUB_THREAD) {
3561     if (m_thread_suffix_supported)
3562       return HandlePacket_ILLFORMED(
3563           __FILE__, __LINE__, p,
3564           "No thread specified in QSaveRegisterState packet");
3565     else
3566       return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3567                                     "No thread was is set with the Hg packet");
3568   }
3569 
3570   StdStringExtractor packet(p);
3571   packet.SetFilePos(
3572       strlen("QRestoreRegisterState:")); // Skip the "QRestoreRegisterState:"
3573   const uint32_t save_id = packet.GetU32(0);
3574 
3575   if (save_id != 0) {
3576     // Get the register context size first by calling with NULL buffer
3577     if (DNBThreadRestoreRegisterState(pid, tid, save_id))
3578       return SendPacket("OK");
3579     else
3580       return SendPacket("E77");
3581   }
3582   return SendPacket("E76");
3583 }
3584 
3585 static bool GetProcessNameFrom_vAttach(const char *&p,
3586                                        std::string &attach_name) {
3587   bool return_val = true;
3588   while (*p != '\0') {
3589     char smallbuf[3];
3590     smallbuf[0] = *p;
3591     smallbuf[1] = *(p + 1);
3592     smallbuf[2] = '\0';
3593 
3594     errno = 0;
3595     int ch = static_cast<int>(strtoul(smallbuf, NULL, 16));
3596     if (errno != 0 && ch == 0) {
3597       return_val = false;
3598       break;
3599     }
3600 
3601     attach_name.push_back(ch);
3602     p += 2;
3603   }
3604   return return_val;
3605 }
3606 
3607 rnb_err_t RNBRemote::HandlePacket_qSupported(const char *p) {
3608   uint32_t max_packet_size = 128 * 1024; // 128KBytes is a reasonable max packet
3609                                          // size--debugger can always use less
3610   char buf[256];
3611   snprintf(buf, sizeof(buf), "qXfer:features:read+;PacketSize=%x;qEcho+",
3612            max_packet_size);
3613 
3614   // By default, don't enable compression.  It's only worth doing when we are
3615   // working
3616   // with a low speed communication channel.
3617   bool enable_compression = false;
3618   (void)enable_compression;
3619 
3620 // Enable compression when debugserver is running on a watchOS device where
3621 // communication may be over Bluetooth.
3622 #if defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
3623   enable_compression = true;
3624 #endif
3625 
3626 #if defined(HAVE_LIBCOMPRESSION)
3627   // libcompression is weak linked so test if compression_decode_buffer() is
3628   // available
3629   if (enable_compression && compression_decode_buffer != NULL) {
3630     strcat(buf, ";SupportedCompressions=lzfse,zlib-deflate,lz4,lzma;"
3631                 "DefaultCompressionMinSize=");
3632     char numbuf[16];
3633     snprintf(numbuf, sizeof(numbuf), "%zu", m_compression_minsize);
3634     numbuf[sizeof(numbuf) - 1] = '\0';
3635     strcat(buf, numbuf);
3636   }
3637 #elif defined(HAVE_LIBZ)
3638   if (enable_compression) {
3639     strcat(buf,
3640            ";SupportedCompressions=zlib-deflate;DefaultCompressionMinSize=");
3641     char numbuf[16];
3642     snprintf(numbuf, sizeof(numbuf), "%zu", m_compression_minsize);
3643     numbuf[sizeof(numbuf) - 1] = '\0';
3644     strcat(buf, numbuf);
3645   }
3646 #endif
3647 
3648   return SendPacket(buf);
3649 }
3650 
3651 /*
3652  vAttach;pid
3653 
3654  Attach to a new process with the specified process ID. pid is a hexadecimal
3655  integer
3656  identifying the process. If the stub is currently controlling a process, it is
3657  killed. The attached process is stopped.This packet is only available in
3658  extended
3659  mode (see extended mode).
3660 
3661  Reply:
3662  "ENN"                      for an error
3663  "Any Stop Reply Packet"     for success
3664  */
3665 
3666 rnb_err_t RNBRemote::HandlePacket_v(const char *p) {
3667   if (strcmp(p, "vCont;c") == 0) {
3668     // Simple continue
3669     return RNBRemote::HandlePacket_c("c");
3670   } else if (strcmp(p, "vCont;s") == 0) {
3671     // Simple step
3672     return RNBRemote::HandlePacket_s("s");
3673   } else if (strstr(p, "vCont") == p) {
3674     DNBThreadResumeActions thread_actions;
3675     char *c = (char *)(p += strlen("vCont"));
3676     char *c_end = c + strlen(c);
3677     if (*c == '?')
3678       return SendPacket("vCont;c;C;s;S");
3679 
3680     while (c < c_end && *c == ';') {
3681       ++c; // Skip the semi-colon
3682       DNBThreadResumeAction thread_action;
3683       thread_action.tid = INVALID_NUB_THREAD;
3684       thread_action.state = eStateInvalid;
3685       thread_action.signal = 0;
3686       thread_action.addr = INVALID_NUB_ADDRESS;
3687 
3688       char action = *c++;
3689 
3690       switch (action) {
3691       case 'C':
3692         errno = 0;
3693         thread_action.signal = static_cast<int>(strtoul(c, &c, 16));
3694         if (errno != 0)
3695           return HandlePacket_ILLFORMED(
3696               __FILE__, __LINE__, p, "Could not parse signal in vCont packet");
3697       // Fall through to next case...
3698 
3699       case 'c':
3700         // Continue
3701         thread_action.state = eStateRunning;
3702         break;
3703 
3704       case 'S':
3705         errno = 0;
3706         thread_action.signal = static_cast<int>(strtoul(c, &c, 16));
3707         if (errno != 0)
3708           return HandlePacket_ILLFORMED(
3709               __FILE__, __LINE__, p, "Could not parse signal in vCont packet");
3710       // Fall through to next case...
3711 
3712       case 's':
3713         // Step
3714         thread_action.state = eStateStepping;
3715         break;
3716 
3717       default:
3718         HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3719                                "Unsupported action in vCont packet");
3720         break;
3721       }
3722       if (*c == ':') {
3723         errno = 0;
3724         thread_action.tid = strtoul(++c, &c, 16);
3725         if (errno != 0)
3726           return HandlePacket_ILLFORMED(
3727               __FILE__, __LINE__, p,
3728               "Could not parse thread number in vCont packet");
3729       }
3730 
3731       thread_actions.Append(thread_action);
3732     }
3733 
3734     // If a default action for all other threads wasn't mentioned
3735     // then we should stop the threads
3736     thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
3737     DNBProcessResume(m_ctx.ProcessID(), thread_actions.GetFirst(),
3738                      thread_actions.GetSize());
3739     return rnb_success;
3740   } else if (strstr(p, "vAttach") == p) {
3741     nub_process_t attach_pid =
3742         INVALID_NUB_PROCESS; // attach_pid will be set to 0 if the attach fails
3743     nub_process_t pid_attaching_to =
3744         INVALID_NUB_PROCESS; // pid_attaching_to is the original pid specified
3745     char err_str[1024] = {'\0'};
3746     std::string attach_name;
3747 
3748     if (strstr(p, "vAttachWait;") == p) {
3749       p += strlen("vAttachWait;");
3750       if (!GetProcessNameFrom_vAttach(p, attach_name)) {
3751         return HandlePacket_ILLFORMED(
3752             __FILE__, __LINE__, p, "non-hex char in arg on 'vAttachWait' pkt");
3753       }
3754       const bool ignore_existing = true;
3755       attach_pid = DNBProcessAttachWait(
3756           attach_name.c_str(), m_ctx.LaunchFlavor(), ignore_existing, NULL,
3757           1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback);
3758 
3759     } else if (strstr(p, "vAttachOrWait;") == p) {
3760       p += strlen("vAttachOrWait;");
3761       if (!GetProcessNameFrom_vAttach(p, attach_name)) {
3762         return HandlePacket_ILLFORMED(
3763             __FILE__, __LINE__, p,
3764             "non-hex char in arg on 'vAttachOrWait' pkt");
3765       }
3766       const bool ignore_existing = false;
3767       attach_pid = DNBProcessAttachWait(
3768           attach_name.c_str(), m_ctx.LaunchFlavor(), ignore_existing, NULL,
3769           1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback);
3770     } else if (strstr(p, "vAttachName;") == p) {
3771       p += strlen("vAttachName;");
3772       if (!GetProcessNameFrom_vAttach(p, attach_name)) {
3773         return HandlePacket_ILLFORMED(
3774             __FILE__, __LINE__, p, "non-hex char in arg on 'vAttachName' pkt");
3775       }
3776 
3777       attach_pid = DNBProcessAttachByName(attach_name.c_str(), NULL, err_str,
3778                                           sizeof(err_str));
3779 
3780     } else if (strstr(p, "vAttach;") == p) {
3781       p += strlen("vAttach;");
3782       char *end = NULL;
3783       pid_attaching_to = static_cast<int>(
3784           strtoul(p, &end, 16)); // PID will be in hex, so use base 16 to decode
3785       if (p != end && *end == '\0') {
3786         // Wait at most 30 second for attach
3787         struct timespec attach_timeout_abstime;
3788         DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, 30, 0);
3789         attach_pid = DNBProcessAttach(pid_attaching_to, &attach_timeout_abstime,
3790                                       err_str, sizeof(err_str));
3791       }
3792     } else {
3793       return HandlePacket_UNIMPLEMENTED(p);
3794     }
3795 
3796     if (attach_pid != INVALID_NUB_PROCESS) {
3797       if (m_ctx.ProcessID() != attach_pid)
3798         m_ctx.SetProcessID(attach_pid);
3799       // Send a stop reply packet to indicate we successfully attached!
3800       NotifyThatProcessStopped();
3801       return rnb_success;
3802     } else {
3803       m_ctx.LaunchStatus().SetError(-1, DNBError::Generic);
3804       if (err_str[0])
3805         m_ctx.LaunchStatus().SetErrorString(err_str);
3806       else
3807         m_ctx.LaunchStatus().SetErrorString("attach failed");
3808 
3809 #if defined(__APPLE__) &&                                                      \
3810     (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101000)
3811       if (pid_attaching_to == INVALID_NUB_PROCESS && !attach_name.empty()) {
3812         pid_attaching_to = DNBProcessGetPIDByName(attach_name.c_str());
3813       }
3814       if (pid_attaching_to != INVALID_NUB_PROCESS &&
3815           strcmp(err_str, "No such process") != 0) {
3816         // csr_check(CSR_ALLOW_TASK_FOR_PID) will be nonzero if System Integrity
3817         // Protection is in effect.
3818         if (csr_check(CSR_ALLOW_TASK_FOR_PID) != 0) {
3819           bool attach_failed_due_to_sip = false;
3820 
3821           if (rootless_allows_task_for_pid(pid_attaching_to) == 0) {
3822             attach_failed_due_to_sip = true;
3823           }
3824 
3825           if (attach_failed_due_to_sip == false) {
3826             int csops_flags = 0;
3827             int retval = ::csops(pid_attaching_to, CS_OPS_STATUS, &csops_flags,
3828                                  sizeof(csops_flags));
3829             if (retval != -1 && (csops_flags & CS_RESTRICT)) {
3830               attach_failed_due_to_sip = true;
3831             }
3832           }
3833           if (attach_failed_due_to_sip) {
3834             SendPacket("E87"); // E87 is the magic value which says that we are
3835                                // not allowed to attach
3836             DNBLogError("Attach failed because process does not allow "
3837                         "attaching: \"%s\".",
3838                         err_str);
3839             return rnb_err;
3840           }
3841         }
3842       }
3843 
3844 #endif
3845 
3846       SendPacket("E01"); // E01 is our magic error value for attach failed.
3847       DNBLogError("Attach failed: \"%s\".", err_str);
3848       return rnb_err;
3849     }
3850   }
3851 
3852   // All other failures come through here
3853   return HandlePacket_UNIMPLEMENTED(p);
3854 }
3855 
3856 /* 'T XX' -- status of thread
3857  Check if the specified thread is alive.
3858  The thread number is in hex?  */
3859 
3860 rnb_err_t RNBRemote::HandlePacket_T(const char *p) {
3861   p++;
3862   if (p == NULL || *p == '\0') {
3863     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3864                                   "No thread specified in T packet");
3865   }
3866   if (!m_ctx.HasValidProcessID()) {
3867     return SendPacket("E15");
3868   }
3869   errno = 0;
3870   nub_thread_t tid = strtoul(p, NULL, 16);
3871   if (errno != 0 && tid == 0) {
3872     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3873                                   "Could not parse thread number in T packet");
3874   }
3875 
3876   nub_state_t state = DNBThreadGetState(m_ctx.ProcessID(), tid);
3877   if (state == eStateInvalid || state == eStateExited ||
3878       state == eStateCrashed) {
3879     return SendPacket("E16");
3880   }
3881 
3882   return SendPacket("OK");
3883 }
3884 
3885 rnb_err_t RNBRemote::HandlePacket_z(const char *p) {
3886   if (p == NULL || *p == '\0')
3887     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3888                                   "No thread specified in z packet");
3889 
3890   if (!m_ctx.HasValidProcessID())
3891     return SendPacket("E15");
3892 
3893   char packet_cmd = *p++;
3894   char break_type = *p++;
3895 
3896   if (*p++ != ',')
3897     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3898                                   "Comma separator missing in z packet");
3899 
3900   char *c = NULL;
3901   nub_process_t pid = m_ctx.ProcessID();
3902   errno = 0;
3903   nub_addr_t addr = strtoull(p, &c, 16);
3904   if (errno != 0 && addr == 0)
3905     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3906                                   "Invalid address in z packet");
3907   p = c;
3908   if (*p++ != ',')
3909     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3910                                   "Comma separator missing in z packet");
3911 
3912   errno = 0;
3913   auto byte_size = strtoul(p, &c, 16);
3914   if (errno != 0 && byte_size == 0)
3915     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3916                                   "Invalid length in z packet");
3917 
3918   if (packet_cmd == 'Z') {
3919     // set
3920     switch (break_type) {
3921     case '0': // set software breakpoint
3922     case '1': // set hardware breakpoint
3923     {
3924       // gdb can send multiple Z packets for the same address and
3925       // these calls must be ref counted.
3926       bool hardware = (break_type == '1');
3927 
3928       if (DNBBreakpointSet(pid, addr, byte_size, hardware)) {
3929         // We successfully created a breakpoint, now lets full out
3930         // a ref count structure with the breakID and add it to our
3931         // map.
3932         return SendPacket("OK");
3933       } else {
3934         // We failed to set the software breakpoint
3935         return SendPacket("E09");
3936       }
3937     } break;
3938 
3939     case '2': // set write watchpoint
3940     case '3': // set read watchpoint
3941     case '4': // set access watchpoint
3942     {
3943       bool hardware = true;
3944       uint32_t watch_flags = 0;
3945       if (break_type == '2')
3946         watch_flags = WATCH_TYPE_WRITE;
3947       else if (break_type == '3')
3948         watch_flags = WATCH_TYPE_READ;
3949       else
3950         watch_flags = WATCH_TYPE_READ | WATCH_TYPE_WRITE;
3951 
3952       if (DNBWatchpointSet(pid, addr, byte_size, watch_flags, hardware)) {
3953         return SendPacket("OK");
3954       } else {
3955         // We failed to set the watchpoint
3956         return SendPacket("E09");
3957       }
3958     } break;
3959 
3960     default:
3961       break;
3962     }
3963   } else if (packet_cmd == 'z') {
3964     // remove
3965     switch (break_type) {
3966     case '0': // remove software breakpoint
3967     case '1': // remove hardware breakpoint
3968       if (DNBBreakpointClear(pid, addr)) {
3969         return SendPacket("OK");
3970       } else {
3971         return SendPacket("E08");
3972       }
3973       break;
3974 
3975     case '2': // remove write watchpoint
3976     case '3': // remove read watchpoint
3977     case '4': // remove access watchpoint
3978       if (DNBWatchpointClear(pid, addr)) {
3979         return SendPacket("OK");
3980       } else {
3981         return SendPacket("E08");
3982       }
3983       break;
3984 
3985     default:
3986       break;
3987     }
3988   }
3989   return HandlePacket_UNIMPLEMENTED(p);
3990 }
3991 
3992 // Extract the thread number from the thread suffix that might be appended to
3993 // thread specific packets. This will only be enabled if
3994 // m_thread_suffix_supported
3995 // is true.
3996 nub_thread_t RNBRemote::ExtractThreadIDFromThreadSuffix(const char *p) {
3997   if (m_thread_suffix_supported) {
3998     nub_thread_t tid = INVALID_NUB_THREAD;
3999     if (p) {
4000       const char *tid_cstr = strstr(p, "thread:");
4001       if (tid_cstr) {
4002         tid_cstr += strlen("thread:");
4003         tid = strtoul(tid_cstr, NULL, 16);
4004       }
4005     }
4006     return tid;
4007   }
4008   return GetCurrentThread();
4009 }
4010 
4011 /* 'p XX'
4012  print the contents of register X */
4013 
4014 rnb_err_t RNBRemote::HandlePacket_p(const char *p) {
4015   if (g_num_reg_entries == 0)
4016     InitializeRegisters();
4017 
4018   if (p == NULL || *p == '\0') {
4019     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4020                                   "No thread specified in p packet");
4021   }
4022   if (!m_ctx.HasValidProcessID()) {
4023     return SendPacket("E15");
4024   }
4025   nub_process_t pid = m_ctx.ProcessID();
4026   errno = 0;
4027   char *tid_cstr = NULL;
4028   uint32_t reg = static_cast<uint32_t>(strtoul(p + 1, &tid_cstr, 16));
4029   if (errno != 0 && reg == 0) {
4030     return HandlePacket_ILLFORMED(
4031         __FILE__, __LINE__, p, "Could not parse register number in p packet");
4032   }
4033 
4034   nub_thread_t tid = ExtractThreadIDFromThreadSuffix(tid_cstr);
4035   if (tid == INVALID_NUB_THREAD)
4036     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4037                                   "No thread specified in p packet");
4038 
4039   const register_map_entry_t *reg_entry;
4040 
4041   if (reg < g_num_reg_entries)
4042     reg_entry = &g_reg_entries[reg];
4043   else
4044     reg_entry = NULL;
4045 
4046   std::ostringstream ostrm;
4047   if (reg_entry == NULL) {
4048     DNBLogError(
4049         "RNBRemote::HandlePacket_p(%s): unknown register number %u requested\n",
4050         p, reg);
4051     ostrm << "00000000";
4052   } else if (reg_entry->nub_info.reg == (uint32_t)-1) {
4053     if (reg_entry->nub_info.size > 0) {
4054       std::basic_string<uint8_t> zeros(reg_entry->nub_info.size, '\0');
4055       append_hex_value(ostrm, zeros.data(), zeros.size(), false);
4056     }
4057   } else {
4058     register_value_in_hex_fixed_width(ostrm, pid, tid, reg_entry, NULL);
4059   }
4060   return SendPacket(ostrm.str());
4061 }
4062 
4063 /* 'Pnn=rrrrr'
4064  Set register number n to value r.
4065  n and r are hex strings.  */
4066 
4067 rnb_err_t RNBRemote::HandlePacket_P(const char *p) {
4068   if (g_num_reg_entries == 0)
4069     InitializeRegisters();
4070 
4071   if (p == NULL || *p == '\0') {
4072     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, "Empty P packet");
4073   }
4074   if (!m_ctx.HasValidProcessID()) {
4075     return SendPacket("E28");
4076   }
4077 
4078   nub_process_t pid = m_ctx.ProcessID();
4079 
4080   StdStringExtractor packet(p);
4081 
4082   const char cmd_char = packet.GetChar();
4083   // Register ID is always in big endian
4084   const uint32_t reg = packet.GetHexMaxU32(false, UINT32_MAX);
4085   const char equal_char = packet.GetChar();
4086 
4087   if (cmd_char != 'P')
4088     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4089                                   "Improperly formed P packet");
4090 
4091   if (reg == UINT32_MAX)
4092     return SendPacket("E29");
4093 
4094   if (equal_char != '=')
4095     return SendPacket("E30");
4096 
4097   const register_map_entry_t *reg_entry;
4098 
4099   if (reg >= g_num_reg_entries)
4100     return SendPacket("E47");
4101 
4102   reg_entry = &g_reg_entries[reg];
4103 
4104   if (reg_entry->nub_info.set == (uint32_t)-1 &&
4105       reg_entry->nub_info.reg == (uint32_t)-1) {
4106     DNBLogError(
4107         "RNBRemote::HandlePacket_P(%s): unknown register number %u requested\n",
4108         p, reg);
4109     return SendPacket("E48");
4110   }
4111 
4112   DNBRegisterValue reg_value;
4113   reg_value.info = reg_entry->nub_info;
4114   packet.GetHexBytes(reg_value.value.v_sint8, reg_entry->nub_info.size, 0xcc);
4115 
4116   nub_thread_t tid = ExtractThreadIDFromThreadSuffix(p);
4117   if (tid == INVALID_NUB_THREAD)
4118     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4119                                   "No thread specified in p packet");
4120 
4121   if (!DNBThreadSetRegisterValueByID(pid, tid, reg_entry->nub_info.set,
4122                                      reg_entry->nub_info.reg, &reg_value)) {
4123     return SendPacket("E32");
4124   }
4125   return SendPacket("OK");
4126 }
4127 
4128 /* 'c [addr]'
4129  Continue, optionally from a specified address. */
4130 
4131 rnb_err_t RNBRemote::HandlePacket_c(const char *p) {
4132   const nub_process_t pid = m_ctx.ProcessID();
4133 
4134   if (pid == INVALID_NUB_PROCESS)
4135     return SendPacket("E23");
4136 
4137   DNBThreadResumeAction action = {INVALID_NUB_THREAD, eStateRunning, 0,
4138                                   INVALID_NUB_ADDRESS};
4139 
4140   if (*(p + 1) != '\0') {
4141     action.tid = GetContinueThread();
4142     errno = 0;
4143     action.addr = strtoull(p + 1, NULL, 16);
4144     if (errno != 0 && action.addr == 0)
4145       return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4146                                     "Could not parse address in c packet");
4147   }
4148 
4149   DNBThreadResumeActions thread_actions;
4150   thread_actions.Append(action);
4151   thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, 0);
4152   if (!DNBProcessResume(pid, thread_actions.GetFirst(),
4153                         thread_actions.GetSize()))
4154     return SendPacket("E25");
4155   // Don't send an "OK" packet; response is the stopped/exited message.
4156   return rnb_success;
4157 }
4158 
4159 rnb_err_t RNBRemote::HandlePacket_MemoryRegionInfo(const char *p) {
4160   /* This packet will find memory attributes (e.g. readable, writable,
4161      executable, stack, jitted code)
4162      for the memory region containing a given address and return that
4163      information.
4164 
4165      Users of this packet must be prepared for three results:
4166 
4167          Region information is returned
4168          Region information is unavailable for this address because the address
4169      is in unmapped memory
4170          Region lookup cannot be performed on this platform or process is not
4171      yet launched
4172          This packet isn't implemented
4173 
4174      Examples of use:
4175         qMemoryRegionInfo:3a55140
4176         start:3a50000,size:100000,permissions:rwx
4177 
4178         qMemoryRegionInfo:0
4179         error:address in unmapped region
4180 
4181         qMemoryRegionInfo:3a551140   (on a different platform)
4182         error:region lookup cannot be performed
4183 
4184         qMemoryRegionInfo
4185         OK                   // this packet is implemented by the remote nub
4186   */
4187 
4188   p += sizeof("qMemoryRegionInfo") - 1;
4189   if (*p == '\0')
4190     return SendPacket("OK");
4191   if (*p++ != ':')
4192     return SendPacket("E67");
4193   if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X'))
4194     p += 2;
4195 
4196   errno = 0;
4197   uint64_t address = strtoul(p, NULL, 16);
4198   if (errno != 0 && address == 0) {
4199     return HandlePacket_ILLFORMED(
4200         __FILE__, __LINE__, p, "Invalid address in qMemoryRegionInfo packet");
4201   }
4202 
4203   DNBRegionInfo region_info = {0, 0, 0};
4204   DNBProcessMemoryRegionInfo(m_ctx.ProcessID(), address, &region_info);
4205   std::ostringstream ostrm;
4206 
4207   // start:3a50000,size:100000,permissions:rwx
4208   ostrm << "start:" << std::hex << region_info.addr << ';';
4209 
4210   if (region_info.size > 0)
4211     ostrm << "size:" << std::hex << region_info.size << ';';
4212 
4213   if (region_info.permissions) {
4214     ostrm << "permissions:";
4215 
4216     if (region_info.permissions & eMemoryPermissionsReadable)
4217       ostrm << 'r';
4218     if (region_info.permissions & eMemoryPermissionsWritable)
4219       ostrm << 'w';
4220     if (region_info.permissions & eMemoryPermissionsExecutable)
4221       ostrm << 'x';
4222     ostrm << ';';
4223   }
4224   return SendPacket(ostrm.str());
4225 }
4226 
4227 // qGetProfileData;scan_type:0xYYYYYYY
4228 rnb_err_t RNBRemote::HandlePacket_GetProfileData(const char *p) {
4229   nub_process_t pid = m_ctx.ProcessID();
4230   if (pid == INVALID_NUB_PROCESS)
4231     return SendPacket("OK");
4232 
4233   StdStringExtractor packet(p += sizeof("qGetProfileData"));
4234   DNBProfileDataScanType scan_type = eProfileAll;
4235   std::string name;
4236   std::string value;
4237   while (packet.GetNameColonValue(name, value)) {
4238     if (name.compare("scan_type") == 0) {
4239       std::istringstream iss(value);
4240       uint32_t int_value = 0;
4241       if (iss >> std::hex >> int_value) {
4242         scan_type = (DNBProfileDataScanType)int_value;
4243       }
4244     }
4245   }
4246 
4247   std::string data = DNBProcessGetProfileData(pid, scan_type);
4248   if (!data.empty()) {
4249     return SendPacket(data.c_str());
4250   } else {
4251     return SendPacket("OK");
4252   }
4253 }
4254 
4255 // QSetEnableAsyncProfiling;enable:[0|1]:interval_usec:XXXXXX;scan_type:0xYYYYYYY
4256 rnb_err_t RNBRemote::HandlePacket_SetEnableAsyncProfiling(const char *p) {
4257   nub_process_t pid = m_ctx.ProcessID();
4258   if (pid == INVALID_NUB_PROCESS)
4259     return SendPacket("OK");
4260 
4261   StdStringExtractor packet(p += sizeof("QSetEnableAsyncProfiling"));
4262   bool enable = false;
4263   uint64_t interval_usec = 0;
4264   DNBProfileDataScanType scan_type = eProfileAll;
4265   std::string name;
4266   std::string value;
4267   while (packet.GetNameColonValue(name, value)) {
4268     if (name.compare("enable") == 0) {
4269       enable = strtoul(value.c_str(), NULL, 10) > 0;
4270     } else if (name.compare("interval_usec") == 0) {
4271       interval_usec = strtoul(value.c_str(), NULL, 10);
4272     } else if (name.compare("scan_type") == 0) {
4273       std::istringstream iss(value);
4274       uint32_t int_value = 0;
4275       if (iss >> std::hex >> int_value) {
4276         scan_type = (DNBProfileDataScanType)int_value;
4277       }
4278     }
4279   }
4280 
4281   if (interval_usec == 0) {
4282     enable = 0;
4283   }
4284 
4285   DNBProcessSetEnableAsyncProfiling(pid, enable, interval_usec, scan_type);
4286   return SendPacket("OK");
4287 }
4288 
4289 // QEnableCompression:type:<COMPRESSION-TYPE>;minsize:<MINIMUM PACKET SIZE TO
4290 // COMPRESS>;
4291 //
4292 // type: must be a type previously reported by the qXfer:features:
4293 // SupportedCompressions list
4294 //
4295 // minsize: is optional; by default the qXfer:features:
4296 // DefaultCompressionMinSize value is used
4297 // debugserver may have a better idea of what a good minimum packet size to
4298 // compress is than lldb.
4299 
4300 rnb_err_t RNBRemote::HandlePacket_QEnableCompression(const char *p) {
4301   p += sizeof("QEnableCompression:") - 1;
4302 
4303   size_t new_compression_minsize = m_compression_minsize;
4304   const char *new_compression_minsize_str = strstr(p, "minsize:");
4305   if (new_compression_minsize_str) {
4306     new_compression_minsize_str += strlen("minsize:");
4307     errno = 0;
4308     new_compression_minsize = strtoul(new_compression_minsize_str, NULL, 10);
4309     if (errno != 0 || new_compression_minsize == ULONG_MAX) {
4310       new_compression_minsize = m_compression_minsize;
4311     }
4312   }
4313 
4314 #if defined(HAVE_LIBCOMPRESSION)
4315   if (compression_decode_buffer != NULL) {
4316     if (strstr(p, "type:zlib-deflate;") != nullptr) {
4317       EnableCompressionNextSendPacket(compression_types::zlib_deflate);
4318       m_compression_minsize = new_compression_minsize;
4319       return SendPacket("OK");
4320     } else if (strstr(p, "type:lz4;") != nullptr) {
4321       EnableCompressionNextSendPacket(compression_types::lz4);
4322       m_compression_minsize = new_compression_minsize;
4323       return SendPacket("OK");
4324     } else if (strstr(p, "type:lzma;") != nullptr) {
4325       EnableCompressionNextSendPacket(compression_types::lzma);
4326       m_compression_minsize = new_compression_minsize;
4327       return SendPacket("OK");
4328     } else if (strstr(p, "type:lzfse;") != nullptr) {
4329       EnableCompressionNextSendPacket(compression_types::lzfse);
4330       m_compression_minsize = new_compression_minsize;
4331       return SendPacket("OK");
4332     }
4333   }
4334 #endif
4335 
4336 #if defined(HAVE_LIBZ)
4337   if (strstr(p, "type:zlib-deflate;") != nullptr) {
4338     EnableCompressionNextSendPacket(compression_types::zlib_deflate);
4339     m_compression_minsize = new_compression_minsize;
4340     return SendPacket("OK");
4341   }
4342 #endif
4343 
4344   return SendPacket("E88");
4345 }
4346 
4347 rnb_err_t RNBRemote::HandlePacket_qSpeedTest(const char *p) {
4348   p += strlen("qSpeedTest:response_size:");
4349   char *end = NULL;
4350   errno = 0;
4351   uint64_t response_size = ::strtoul(p, &end, 16);
4352   if (errno != 0)
4353     return HandlePacket_ILLFORMED(
4354         __FILE__, __LINE__, p,
4355         "Didn't find response_size value at right offset");
4356   else if (*end == ';') {
4357     static char g_data[4 * 1024 * 1024 + 16] = "data:";
4358     memset(g_data + 5, 'a', response_size);
4359     g_data[response_size + 5] = '\0';
4360     return SendPacket(g_data);
4361   } else {
4362     return SendPacket("E79");
4363   }
4364 }
4365 
4366 rnb_err_t RNBRemote::HandlePacket_WatchpointSupportInfo(const char *p) {
4367   /* This packet simply returns the number of supported hardware watchpoints.
4368 
4369      Examples of use:
4370         qWatchpointSupportInfo:
4371         num:4
4372 
4373         qWatchpointSupportInfo
4374         OK                   // this packet is implemented by the remote nub
4375   */
4376 
4377   p += sizeof("qWatchpointSupportInfo") - 1;
4378   if (*p == '\0')
4379     return SendPacket("OK");
4380   if (*p++ != ':')
4381     return SendPacket("E67");
4382 
4383   errno = 0;
4384   uint32_t num = DNBWatchpointGetNumSupportedHWP(m_ctx.ProcessID());
4385   std::ostringstream ostrm;
4386 
4387   // size:4
4388   ostrm << "num:" << std::dec << num << ';';
4389   return SendPacket(ostrm.str());
4390 }
4391 
4392 /* 'C sig [;addr]'
4393  Resume with signal sig, optionally at address addr.  */
4394 
4395 rnb_err_t RNBRemote::HandlePacket_C(const char *p) {
4396   const nub_process_t pid = m_ctx.ProcessID();
4397 
4398   if (pid == INVALID_NUB_PROCESS)
4399     return SendPacket("E36");
4400 
4401   DNBThreadResumeAction action = {INVALID_NUB_THREAD, eStateRunning, 0,
4402                                   INVALID_NUB_ADDRESS};
4403   int process_signo = -1;
4404   if (*(p + 1) != '\0') {
4405     action.tid = GetContinueThread();
4406     char *end = NULL;
4407     errno = 0;
4408     process_signo = static_cast<int>(strtoul(p + 1, &end, 16));
4409     if (errno != 0)
4410       return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4411                                     "Could not parse signal in C packet");
4412     else if (*end == ';') {
4413       errno = 0;
4414       action.addr = strtoull(end + 1, NULL, 16);
4415       if (errno != 0 && action.addr == 0)
4416         return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4417                                       "Could not parse address in C packet");
4418     }
4419   }
4420 
4421   DNBThreadResumeActions thread_actions;
4422   thread_actions.Append(action);
4423   thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, action.signal);
4424   if (!DNBProcessSignal(pid, process_signo))
4425     return SendPacket("E52");
4426   if (!DNBProcessResume(pid, thread_actions.GetFirst(),
4427                         thread_actions.GetSize()))
4428     return SendPacket("E38");
4429   /* Don't send an "OK" packet; response is the stopped/exited message.  */
4430   return rnb_success;
4431 }
4432 
4433 //----------------------------------------------------------------------
4434 // 'D' packet
4435 // Detach from gdb.
4436 //----------------------------------------------------------------------
4437 rnb_err_t RNBRemote::HandlePacket_D(const char *p) {
4438   if (m_ctx.HasValidProcessID()) {
4439     if (DNBProcessDetach(m_ctx.ProcessID()))
4440       SendPacket("OK");
4441     else
4442       SendPacket("E");
4443   } else {
4444     SendPacket("E");
4445   }
4446   return rnb_success;
4447 }
4448 
4449 /* 'k'
4450  Kill the inferior process.  */
4451 
4452 rnb_err_t RNBRemote::HandlePacket_k(const char *p) {
4453   DNBLog("Got a 'k' packet, killing the inferior process.");
4454   // No response to should be sent to the kill packet
4455   if (m_ctx.HasValidProcessID())
4456     DNBProcessKill(m_ctx.ProcessID());
4457   SendPacket("X09");
4458   return rnb_success;
4459 }
4460 
4461 rnb_err_t RNBRemote::HandlePacket_stop_process(const char *p) {
4462 //#define TEST_EXIT_ON_INTERRUPT // This should only be uncommented to test
4463 //exiting on interrupt
4464 #if defined(TEST_EXIT_ON_INTERRUPT)
4465   rnb_err_t err = HandlePacket_k(p);
4466   m_comm.Disconnect(true);
4467   return err;
4468 #else
4469   if (!DNBProcessInterrupt(m_ctx.ProcessID())) {
4470     // If we failed to interrupt the process, then send a stop
4471     // reply packet as the process was probably already stopped
4472     DNBLogThreaded("RNBRemote::HandlePacket_stop_process() sending extra stop "
4473                    "reply because DNBProcessInterrupt returned false");
4474     HandlePacket_last_signal(NULL);
4475   }
4476   return rnb_success;
4477 #endif
4478 }
4479 
4480 /* 's'
4481  Step the inferior process.  */
4482 
4483 rnb_err_t RNBRemote::HandlePacket_s(const char *p) {
4484   const nub_process_t pid = m_ctx.ProcessID();
4485   if (pid == INVALID_NUB_PROCESS)
4486     return SendPacket("E32");
4487 
4488   // Hardware supported stepping not supported on arm
4489   nub_thread_t tid = GetContinueThread();
4490   if (tid == 0 || tid == (nub_thread_t)-1)
4491     tid = GetCurrentThread();
4492 
4493   if (tid == INVALID_NUB_THREAD)
4494     return SendPacket("E33");
4495 
4496   DNBThreadResumeActions thread_actions;
4497   thread_actions.AppendAction(tid, eStateStepping);
4498 
4499   // Make all other threads stop when we are stepping
4500   thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
4501   if (!DNBProcessResume(pid, thread_actions.GetFirst(),
4502                         thread_actions.GetSize()))
4503     return SendPacket("E49");
4504   // Don't send an "OK" packet; response is the stopped/exited message.
4505   return rnb_success;
4506 }
4507 
4508 /* 'S sig [;addr]'
4509  Step with signal sig, optionally at address addr.  */
4510 
4511 rnb_err_t RNBRemote::HandlePacket_S(const char *p) {
4512   const nub_process_t pid = m_ctx.ProcessID();
4513   if (pid == INVALID_NUB_PROCESS)
4514     return SendPacket("E36");
4515 
4516   DNBThreadResumeAction action = {INVALID_NUB_THREAD, eStateStepping, 0,
4517                                   INVALID_NUB_ADDRESS};
4518 
4519   if (*(p + 1) != '\0') {
4520     char *end = NULL;
4521     errno = 0;
4522     action.signal = static_cast<int>(strtoul(p + 1, &end, 16));
4523     if (errno != 0)
4524       return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4525                                     "Could not parse signal in S packet");
4526     else if (*end == ';') {
4527       errno = 0;
4528       action.addr = strtoull(end + 1, NULL, 16);
4529       if (errno != 0 && action.addr == 0) {
4530         return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4531                                       "Could not parse address in S packet");
4532       }
4533     }
4534   }
4535 
4536   action.tid = GetContinueThread();
4537   if (action.tid == 0 || action.tid == (nub_thread_t)-1)
4538     return SendPacket("E40");
4539 
4540   nub_state_t tstate = DNBThreadGetState(pid, action.tid);
4541   if (tstate == eStateInvalid || tstate == eStateExited)
4542     return SendPacket("E37");
4543 
4544   DNBThreadResumeActions thread_actions;
4545   thread_actions.Append(action);
4546 
4547   // Make all other threads stop when we are stepping
4548   thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
4549   if (!DNBProcessResume(pid, thread_actions.GetFirst(),
4550                         thread_actions.GetSize()))
4551     return SendPacket("E39");
4552 
4553   // Don't send an "OK" packet; response is the stopped/exited message.
4554   return rnb_success;
4555 }
4556 
4557 static const char *GetArchName(const uint32_t cputype,
4558                                const uint32_t cpusubtype) {
4559   switch (cputype) {
4560   case CPU_TYPE_ARM:
4561     switch (cpusubtype) {
4562     case 5:
4563       return "armv4";
4564     case 6:
4565       return "armv6";
4566     case 7:
4567       return "armv5t";
4568     case 8:
4569       return "xscale";
4570     case 9:
4571       return "armv7";
4572     case 10:
4573       return "armv7f";
4574     case 11:
4575       return "armv7s";
4576     case 12:
4577       return "armv7k";
4578     case 14:
4579       return "armv6m";
4580     case 15:
4581       return "armv7m";
4582     case 16:
4583       return "armv7em";
4584     default:
4585       return "arm";
4586     }
4587     break;
4588   case CPU_TYPE_ARM64:
4589     return "arm64";
4590   case CPU_TYPE_I386:
4591     return "i386";
4592   case CPU_TYPE_X86_64:
4593     switch (cpusubtype) {
4594     default:
4595       return "x86_64";
4596     case 8:
4597       return "x86_64h";
4598     }
4599     break;
4600   }
4601   return NULL;
4602 }
4603 
4604 static bool GetHostCPUType(uint32_t &cputype, uint32_t &cpusubtype,
4605                            uint32_t &is_64_bit_capable, bool &promoted_to_64) {
4606   static uint32_t g_host_cputype = 0;
4607   static uint32_t g_host_cpusubtype = 0;
4608   static uint32_t g_is_64_bit_capable = 0;
4609   static bool g_promoted_to_64 = false;
4610 
4611   if (g_host_cputype == 0) {
4612     g_promoted_to_64 = false;
4613     size_t len = sizeof(uint32_t);
4614     if (::sysctlbyname("hw.cputype", &g_host_cputype, &len, NULL, 0) == 0) {
4615       len = sizeof(uint32_t);
4616       if (::sysctlbyname("hw.cpu64bit_capable", &g_is_64_bit_capable, &len,
4617                          NULL, 0) == 0) {
4618         if (g_is_64_bit_capable && ((g_host_cputype & CPU_ARCH_ABI64) == 0)) {
4619           g_promoted_to_64 = true;
4620           g_host_cputype |= CPU_ARCH_ABI64;
4621         }
4622       }
4623     }
4624 
4625     len = sizeof(uint32_t);
4626     if (::sysctlbyname("hw.cpusubtype", &g_host_cpusubtype, &len, NULL, 0) ==
4627         0) {
4628       if (g_promoted_to_64 && g_host_cputype == CPU_TYPE_X86_64 &&
4629           g_host_cpusubtype == CPU_SUBTYPE_486)
4630         g_host_cpusubtype = CPU_SUBTYPE_X86_64_ALL;
4631     }
4632   }
4633 
4634   cputype = g_host_cputype;
4635   cpusubtype = g_host_cpusubtype;
4636   is_64_bit_capable = g_is_64_bit_capable;
4637   promoted_to_64 = g_promoted_to_64;
4638   return g_host_cputype != 0;
4639 }
4640 
4641 rnb_err_t RNBRemote::HandlePacket_qHostInfo(const char *p) {
4642   std::ostringstream strm;
4643 
4644   uint32_t cputype = 0;
4645   uint32_t cpusubtype = 0;
4646   uint32_t is_64_bit_capable = 0;
4647   bool promoted_to_64 = false;
4648   if (GetHostCPUType(cputype, cpusubtype, is_64_bit_capable, promoted_to_64)) {
4649     strm << "cputype:" << std::dec << cputype << ';';
4650     strm << "cpusubtype:" << std::dec << cpusubtype << ';';
4651   }
4652 
4653   // The OS in the triple should be "ios" or "macosx" which doesn't match our
4654   // "Darwin" which gets returned from "kern.ostype", so we need to hardcode
4655   // this for now.
4656   if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64) {
4657 #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
4658     strm << "ostype:tvos;";
4659 #elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
4660     strm << "ostype:watchos;";
4661 #else
4662     strm << "ostype:ios;";
4663 #endif
4664 
4665     // On armv7 we use "synchronous" watchpoints which means the exception is
4666     // delivered before the instruction executes.
4667     strm << "watchpoint_exceptions_received:before;";
4668   } else {
4669     strm << "ostype:macosx;";
4670     strm << "watchpoint_exceptions_received:after;";
4671   }
4672   //    char ostype[64];
4673   //    len = sizeof(ostype);
4674   //    if (::sysctlbyname("kern.ostype", &ostype, &len, NULL, 0) == 0)
4675   //    {
4676   //        len = strlen(ostype);
4677   //        std::transform (ostype, ostype + len, ostype, tolower);
4678   //        strm << "ostype:" << std::dec << ostype << ';';
4679   //    }
4680 
4681   strm << "vendor:apple;";
4682 
4683   uint64_t major, minor, patch;
4684   if (DNBGetOSVersionNumbers(&major, &minor, &patch)) {
4685     strm << "os_version:" << major << "." << minor;
4686     if (patch != UINT64_MAX)
4687       strm << "." << patch;
4688     strm << ";";
4689   }
4690 
4691 #if defined(__LITTLE_ENDIAN__)
4692   strm << "endian:little;";
4693 #elif defined(__BIG_ENDIAN__)
4694   strm << "endian:big;";
4695 #elif defined(__PDP_ENDIAN__)
4696   strm << "endian:pdp;";
4697 #endif
4698 
4699   if (promoted_to_64)
4700     strm << "ptrsize:8;";
4701   else
4702     strm << "ptrsize:" << std::dec << sizeof(void *) << ';';
4703 
4704 #if defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
4705   strm << "default_packet_timeout:10;";
4706 #endif
4707 
4708   return SendPacket(strm.str());
4709 }
4710 
4711 void XMLElementStart(std::ostringstream &s, uint32_t indent, const char *name,
4712                      bool has_attributes) {
4713   if (indent)
4714     s << INDENT_WITH_SPACES(indent);
4715   s << '<' << name;
4716   if (!has_attributes)
4717     s << '>' << std::endl;
4718 }
4719 
4720 void XMLElementStartEndAttributes(std::ostringstream &s, bool empty) {
4721   if (empty)
4722     s << '/';
4723   s << '>' << std::endl;
4724 }
4725 
4726 void XMLElementEnd(std::ostringstream &s, uint32_t indent, const char *name) {
4727   if (indent)
4728     s << INDENT_WITH_SPACES(indent);
4729   s << '<' << '/' << name << '>' << std::endl;
4730 }
4731 
4732 void XMLElementWithStringValue(std::ostringstream &s, uint32_t indent,
4733                                const char *name, const char *value,
4734                                bool close = true) {
4735   if (value) {
4736     if (indent)
4737       s << INDENT_WITH_SPACES(indent);
4738     s << '<' << name << '>' << value;
4739     if (close)
4740       XMLElementEnd(s, 0, name);
4741   }
4742 }
4743 
4744 void XMLElementWithUnsignedValue(std::ostringstream &s, uint32_t indent,
4745                                  const char *name, uint64_t value,
4746                                  bool close = true) {
4747   if (indent)
4748     s << INDENT_WITH_SPACES(indent);
4749 
4750   s << '<' << name << '>' << DECIMAL << value;
4751   if (close)
4752     XMLElementEnd(s, 0, name);
4753 }
4754 
4755 void XMLAttributeString(std::ostringstream &s, const char *name,
4756                         const char *value, const char *default_value = NULL) {
4757   if (value) {
4758     if (default_value && strcmp(value, default_value) == 0)
4759       return; // No need to emit the attribute because it matches the default
4760               // value
4761     s << ' ' << name << "=\"" << value << "\"";
4762   }
4763 }
4764 
4765 void XMLAttributeUnsignedDecimal(std::ostringstream &s, const char *name,
4766                                  uint64_t value) {
4767   s << ' ' << name << "=\"" << DECIMAL << value << "\"";
4768 }
4769 
4770 void GenerateTargetXMLRegister(std::ostringstream &s, const uint32_t reg_num,
4771                                nub_size_t num_reg_sets,
4772                                const DNBRegisterSetInfo *reg_set_info,
4773                                const register_map_entry_t &reg) {
4774   const char *default_lldb_encoding = "uint";
4775   const char *lldb_encoding = default_lldb_encoding;
4776   const char *gdb_group = "general";
4777   const char *default_gdb_type = "int";
4778   const char *gdb_type = default_gdb_type;
4779   const char *default_lldb_format = "hex";
4780   const char *lldb_format = default_lldb_format;
4781   const char *lldb_set = NULL;
4782 
4783   switch (reg.nub_info.type) {
4784   case Uint:
4785     lldb_encoding = "uint";
4786     break;
4787   case Sint:
4788     lldb_encoding = "sint";
4789     break;
4790   case IEEE754:
4791     lldb_encoding = "ieee754";
4792     if (reg.nub_info.set > 0)
4793       gdb_group = "float";
4794     break;
4795   case Vector:
4796     lldb_encoding = "vector";
4797     if (reg.nub_info.set > 0)
4798       gdb_group = "vector";
4799     break;
4800   }
4801 
4802   switch (reg.nub_info.format) {
4803   case Binary:
4804     lldb_format = "binary";
4805     break;
4806   case Decimal:
4807     lldb_format = "decimal";
4808     break;
4809   case Hex:
4810     lldb_format = "hex";
4811     break;
4812   case Float:
4813     gdb_type = "float";
4814     lldb_format = "float";
4815     break;
4816   case VectorOfSInt8:
4817     gdb_type = "float";
4818     lldb_format = "vector-sint8";
4819     break;
4820   case VectorOfUInt8:
4821     gdb_type = "float";
4822     lldb_format = "vector-uint8";
4823     break;
4824   case VectorOfSInt16:
4825     gdb_type = "float";
4826     lldb_format = "vector-sint16";
4827     break;
4828   case VectorOfUInt16:
4829     gdb_type = "float";
4830     lldb_format = "vector-uint16";
4831     break;
4832   case VectorOfSInt32:
4833     gdb_type = "float";
4834     lldb_format = "vector-sint32";
4835     break;
4836   case VectorOfUInt32:
4837     gdb_type = "float";
4838     lldb_format = "vector-uint32";
4839     break;
4840   case VectorOfFloat32:
4841     gdb_type = "float";
4842     lldb_format = "vector-float32";
4843     break;
4844   case VectorOfUInt128:
4845     gdb_type = "float";
4846     lldb_format = "vector-uint128";
4847     break;
4848   };
4849   if (reg_set_info && reg.nub_info.set < num_reg_sets)
4850     lldb_set = reg_set_info[reg.nub_info.set].name;
4851 
4852   uint32_t indent = 2;
4853 
4854   XMLElementStart(s, indent, "reg", true);
4855   XMLAttributeString(s, "name", reg.nub_info.name);
4856   XMLAttributeUnsignedDecimal(s, "regnum", reg_num);
4857   XMLAttributeUnsignedDecimal(s, "offset", reg.offset);
4858   XMLAttributeUnsignedDecimal(s, "bitsize", reg.nub_info.size * 8);
4859   XMLAttributeString(s, "group", gdb_group);
4860   XMLAttributeString(s, "type", gdb_type, default_gdb_type);
4861   XMLAttributeString(s, "altname", reg.nub_info.alt);
4862   XMLAttributeString(s, "encoding", lldb_encoding, default_lldb_encoding);
4863   XMLAttributeString(s, "format", lldb_format, default_lldb_format);
4864   XMLAttributeUnsignedDecimal(s, "group_id", reg.nub_info.set);
4865   if (reg.nub_info.reg_ehframe != INVALID_NUB_REGNUM)
4866     XMLAttributeUnsignedDecimal(s, "ehframe_regnum", reg.nub_info.reg_ehframe);
4867   if (reg.nub_info.reg_dwarf != INVALID_NUB_REGNUM)
4868     XMLAttributeUnsignedDecimal(s, "dwarf_regnum", reg.nub_info.reg_dwarf);
4869 
4870   const char *lldb_generic = NULL;
4871   switch (reg.nub_info.reg_generic) {
4872   case GENERIC_REGNUM_FP:
4873     lldb_generic = "fp";
4874     break;
4875   case GENERIC_REGNUM_PC:
4876     lldb_generic = "pc";
4877     break;
4878   case GENERIC_REGNUM_SP:
4879     lldb_generic = "sp";
4880     break;
4881   case GENERIC_REGNUM_RA:
4882     lldb_generic = "ra";
4883     break;
4884   case GENERIC_REGNUM_FLAGS:
4885     lldb_generic = "flags";
4886     break;
4887   case GENERIC_REGNUM_ARG1:
4888     lldb_generic = "arg1";
4889     break;
4890   case GENERIC_REGNUM_ARG2:
4891     lldb_generic = "arg2";
4892     break;
4893   case GENERIC_REGNUM_ARG3:
4894     lldb_generic = "arg3";
4895     break;
4896   case GENERIC_REGNUM_ARG4:
4897     lldb_generic = "arg4";
4898     break;
4899   case GENERIC_REGNUM_ARG5:
4900     lldb_generic = "arg5";
4901     break;
4902   case GENERIC_REGNUM_ARG6:
4903     lldb_generic = "arg6";
4904     break;
4905   case GENERIC_REGNUM_ARG7:
4906     lldb_generic = "arg7";
4907     break;
4908   case GENERIC_REGNUM_ARG8:
4909     lldb_generic = "arg8";
4910     break;
4911   default:
4912     break;
4913   }
4914   XMLAttributeString(s, "generic", lldb_generic);
4915 
4916   bool empty = reg.value_regnums.empty() && reg.invalidate_regnums.empty();
4917   if (!empty) {
4918     if (!reg.value_regnums.empty()) {
4919       std::ostringstream regnums;
4920       bool first = true;
4921       regnums << DECIMAL;
4922       for (auto regnum : reg.value_regnums) {
4923         if (!first)
4924           regnums << ',';
4925         regnums << regnum;
4926         first = false;
4927       }
4928       XMLAttributeString(s, "value_regnums", regnums.str().c_str());
4929     }
4930 
4931     if (!reg.invalidate_regnums.empty()) {
4932       std::ostringstream regnums;
4933       bool first = true;
4934       regnums << DECIMAL;
4935       for (auto regnum : reg.invalidate_regnums) {
4936         if (!first)
4937           regnums << ',';
4938         regnums << regnum;
4939         first = false;
4940       }
4941       XMLAttributeString(s, "invalidate_regnums", regnums.str().c_str());
4942     }
4943   }
4944   XMLElementStartEndAttributes(s, true);
4945 }
4946 
4947 void GenerateTargetXMLRegisters(std::ostringstream &s) {
4948   nub_size_t num_reg_sets = 0;
4949   const DNBRegisterSetInfo *reg_sets = DNBGetRegisterSetInfo(&num_reg_sets);
4950 
4951   uint32_t cputype = DNBGetRegisterCPUType();
4952   if (cputype) {
4953     XMLElementStart(s, 0, "feature", true);
4954     std::ostringstream name_strm;
4955     name_strm << "com.apple.debugserver." << GetArchName(cputype, 0);
4956     XMLAttributeString(s, "name", name_strm.str().c_str());
4957     XMLElementStartEndAttributes(s, false);
4958     for (uint32_t reg_num = 0; reg_num < g_num_reg_entries; ++reg_num)
4959     //        for (const auto &reg: g_dynamic_register_map)
4960     {
4961       GenerateTargetXMLRegister(s, reg_num, num_reg_sets, reg_sets,
4962                                 g_reg_entries[reg_num]);
4963     }
4964     XMLElementEnd(s, 0, "feature");
4965 
4966     if (num_reg_sets > 0) {
4967       XMLElementStart(s, 0, "groups", false);
4968       for (uint32_t set = 1; set < num_reg_sets; ++set) {
4969         XMLElementStart(s, 2, "group", true);
4970         XMLAttributeUnsignedDecimal(s, "id", set);
4971         XMLAttributeString(s, "name", reg_sets[set].name);
4972         XMLElementStartEndAttributes(s, true);
4973       }
4974       XMLElementEnd(s, 0, "groups");
4975     }
4976   }
4977 }
4978 
4979 static const char *g_target_xml_header = R"(<?xml version="1.0"?>
4980 <target version="1.0">)";
4981 
4982 static const char *g_target_xml_footer = "</target>";
4983 
4984 static std::string g_target_xml;
4985 
4986 void UpdateTargetXML() {
4987   std::ostringstream s;
4988   s << g_target_xml_header << std::endl;
4989 
4990   // Set the architecture
4991   // s << "<architecture>" << arch "</architecture>" << std::endl;
4992 
4993   // Set the OSABI
4994   // s << "<osabi>abi-name</osabi>"
4995 
4996   GenerateTargetXMLRegisters(s);
4997 
4998   s << g_target_xml_footer << std::endl;
4999 
5000   // Save the XML output in case it gets retrieved in chunks
5001   g_target_xml = s.str();
5002 }
5003 
5004 rnb_err_t RNBRemote::HandlePacket_qXfer(const char *command) {
5005   const char *p = command;
5006   p += strlen("qXfer:");
5007   const char *sep = strchr(p, ':');
5008   if (sep) {
5009     std::string object(p, sep - p); // "auxv", "backtrace", "features", etc
5010     p = sep + 1;
5011     sep = strchr(p, ':');
5012     if (sep) {
5013       std::string rw(p, sep - p); // "read" or "write"
5014       p = sep + 1;
5015       sep = strchr(p, ':');
5016       if (sep) {
5017         std::string annex(p, sep - p); // "read" or "write"
5018 
5019         p = sep + 1;
5020         sep = strchr(p, ',');
5021         if (sep) {
5022           std::string offset_str(p, sep - p); // read the length as a string
5023           p = sep + 1;
5024           std::string length_str(p); // read the offset as a string
5025           char *end = nullptr;
5026           const uint64_t offset = strtoul(offset_str.c_str(), &end,
5027                                           16); // convert offset_str to a offset
5028           if (*end == '\0') {
5029             const uint64_t length = strtoul(
5030                 length_str.c_str(), &end, 16); // convert length_str to a length
5031             if (*end == '\0') {
5032               if (object == "features" && rw == "read" &&
5033                   annex == "target.xml") {
5034                 std::ostringstream xml_out;
5035 
5036                 if (offset == 0) {
5037                   InitializeRegisters(true);
5038 
5039                   UpdateTargetXML();
5040                   if (g_target_xml.empty())
5041                     return SendPacket("E83");
5042 
5043                   if (length > g_target_xml.size()) {
5044                     xml_out << 'l'; // No more data
5045                     xml_out << binary_encode_string(g_target_xml);
5046                   } else {
5047                     xml_out << 'm'; // More data needs to be read with a
5048                                     // subsequent call
5049                     xml_out << binary_encode_string(
5050                         std::string(g_target_xml, offset, length));
5051                   }
5052                 } else {
5053                   // Retrieving target XML in chunks
5054                   if (offset < g_target_xml.size()) {
5055                     std::string chunk(g_target_xml, offset, length);
5056                     if (chunk.size() < length)
5057                       xml_out << 'l'; // No more data
5058                     else
5059                       xml_out << 'm'; // More data needs to be read with a
5060                                       // subsequent call
5061                     xml_out << binary_encode_string(chunk.data());
5062                   }
5063                 }
5064                 return SendPacket(xml_out.str());
5065               }
5066               // Well formed, put not supported
5067               return HandlePacket_UNIMPLEMENTED(command);
5068             }
5069           }
5070         }
5071       } else {
5072         SendPacket("E85");
5073       }
5074     } else {
5075       SendPacket("E86");
5076     }
5077   }
5078   return SendPacket("E82");
5079 }
5080 
5081 rnb_err_t RNBRemote::HandlePacket_qGDBServerVersion(const char *p) {
5082   std::ostringstream strm;
5083 
5084 #if defined(DEBUGSERVER_PROGRAM_NAME)
5085   strm << "name:" DEBUGSERVER_PROGRAM_NAME ";";
5086 #else
5087   strm << "name:debugserver;";
5088 #endif
5089   strm << "version:" << DEBUGSERVER_VERSION_NUM << ";";
5090 
5091   return SendPacket(strm.str());
5092 }
5093 
5094 // A helper function that retrieves a single integer value from
5095 // a one-level-deep JSON dictionary of key-value pairs.  e.g.
5096 // jThreadExtendedInfo:{"plo_pthread_tsd_base_address_offset":0,"plo_pthread_tsd_base_offset":224,"plo_pthread_tsd_entry_size":8,"thread":144305}]
5097 //
5098 uint64_t get_integer_value_for_key_name_from_json(const char *key,
5099                                                   const char *json_string) {
5100   uint64_t retval = INVALID_NUB_ADDRESS;
5101   std::string key_with_quotes = "\"";
5102   key_with_quotes += key;
5103   key_with_quotes += "\"";
5104   const char *c = strstr(json_string, key_with_quotes.c_str());
5105   if (c) {
5106     c += key_with_quotes.size();
5107 
5108     while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5109       c++;
5110 
5111     if (*c == ':') {
5112       c++;
5113 
5114       while (*c != '\0' &&
5115              (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5116         c++;
5117 
5118       errno = 0;
5119       retval = strtoul(c, NULL, 10);
5120       if (errno != 0) {
5121         retval = INVALID_NUB_ADDRESS;
5122       }
5123     }
5124   }
5125   return retval;
5126 }
5127 
5128 // A helper function that retrieves a boolean value from
5129 // a one-level-deep JSON dictionary of key-value pairs.  e.g.
5130 // jGetLoadedDynamicLibrariesInfos:{"fetch_all_solibs":true}]
5131 
5132 // Returns true if it was able to find the key name, and sets the 'value'
5133 // argument to the value found.
5134 
5135 bool get_boolean_value_for_key_name_from_json(const char *key,
5136                                               const char *json_string,
5137                                               bool &value) {
5138   std::string key_with_quotes = "\"";
5139   key_with_quotes += key;
5140   key_with_quotes += "\"";
5141   const char *c = strstr(json_string, key_with_quotes.c_str());
5142   if (c) {
5143     c += key_with_quotes.size();
5144 
5145     while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5146       c++;
5147 
5148     if (*c == ':') {
5149       c++;
5150 
5151       while (*c != '\0' &&
5152              (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5153         c++;
5154 
5155       if (strncmp(c, "true", 4) == 0) {
5156         value = true;
5157         return true;
5158       } else if (strncmp(c, "false", 5) == 0) {
5159         value = false;
5160         return true;
5161       }
5162     }
5163   }
5164   return false;
5165 }
5166 
5167 // A helper function that reads an array of uint64_t's from
5168 // a one-level-deep JSON dictionary of key-value pairs.  e.g.
5169 // jGetLoadedDynamicLibrariesInfos:{"solib_addrs":[31345823,7768020384,7310483024]}]
5170 
5171 // Returns true if it was able to find the key name, false if it did not.
5172 // "ints" will have all integers found in the array appended to it.
5173 
5174 bool get_array_of_ints_value_for_key_name_from_json(
5175     const char *key, const char *json_string, std::vector<uint64_t> &ints) {
5176   std::string key_with_quotes = "\"";
5177   key_with_quotes += key;
5178   key_with_quotes += "\"";
5179   const char *c = strstr(json_string, key_with_quotes.c_str());
5180   if (c) {
5181     c += key_with_quotes.size();
5182 
5183     while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5184       c++;
5185 
5186     if (*c == ':') {
5187       c++;
5188 
5189       while (*c != '\0' &&
5190              (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5191         c++;
5192 
5193       if (*c == '[') {
5194         c++;
5195         while (*c != '\0' &&
5196                (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5197           c++;
5198         while (1) {
5199           if (!isdigit(*c)) {
5200             return true;
5201           }
5202 
5203           errno = 0;
5204           char *endptr;
5205           uint64_t value = strtoul(c, &endptr, 10);
5206           if (errno == 0) {
5207             ints.push_back(value);
5208           } else {
5209             break;
5210           }
5211           if (endptr == c || endptr == nullptr || *endptr == '\0') {
5212             break;
5213           }
5214           c = endptr;
5215 
5216           while (*c != '\0' &&
5217                  (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5218             c++;
5219           if (*c == ',')
5220             c++;
5221           while (*c != '\0' &&
5222                  (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5223             c++;
5224           if (*c == ']') {
5225             return true;
5226           }
5227         }
5228       }
5229     }
5230   }
5231   return false;
5232 }
5233 
5234 JSONGenerator::ObjectSP
5235 RNBRemote::GetJSONThreadsInfo(bool threads_with_valid_stop_info_only) {
5236   JSONGenerator::ArraySP threads_array_sp;
5237   if (m_ctx.HasValidProcessID()) {
5238     threads_array_sp.reset(new JSONGenerator::Array());
5239 
5240     nub_process_t pid = m_ctx.ProcessID();
5241 
5242     nub_size_t numthreads = DNBProcessGetNumThreads(pid);
5243     for (nub_size_t i = 0; i < numthreads; ++i) {
5244       nub_thread_t tid = DNBProcessGetThreadAtIndex(pid, i);
5245 
5246       struct DNBThreadStopInfo tid_stop_info;
5247 
5248       const bool stop_info_valid =
5249           DNBThreadGetStopReason(pid, tid, &tid_stop_info);
5250 
5251       // If we are doing stop info only, then we only show threads that have a
5252       // valid stop reason
5253       if (threads_with_valid_stop_info_only) {
5254         if (!stop_info_valid || tid_stop_info.reason == eStopTypeInvalid)
5255           continue;
5256       }
5257 
5258       JSONGenerator::DictionarySP thread_dict_sp(
5259           new JSONGenerator::Dictionary());
5260       thread_dict_sp->AddIntegerItem("tid", tid);
5261 
5262       std::string reason_value("none");
5263 
5264       if (stop_info_valid) {
5265         switch (tid_stop_info.reason) {
5266         case eStopTypeInvalid:
5267           break;
5268 
5269         case eStopTypeSignal:
5270           if (tid_stop_info.details.signal.signo != 0) {
5271             thread_dict_sp->AddIntegerItem("signal",
5272                                            tid_stop_info.details.signal.signo);
5273             reason_value = "signal";
5274           }
5275           break;
5276 
5277         case eStopTypeException:
5278           if (tid_stop_info.details.exception.type != 0) {
5279             reason_value = "exception";
5280             thread_dict_sp->AddIntegerItem(
5281                 "metype", tid_stop_info.details.exception.type);
5282             JSONGenerator::ArraySP medata_array_sp(new JSONGenerator::Array());
5283             for (nub_size_t i = 0;
5284                  i < tid_stop_info.details.exception.data_count; ++i) {
5285               medata_array_sp->AddItem(
5286                   JSONGenerator::IntegerSP(new JSONGenerator::Integer(
5287                       tid_stop_info.details.exception.data[i])));
5288             }
5289             thread_dict_sp->AddItem("medata", medata_array_sp);
5290           }
5291           break;
5292 
5293         case eStopTypeExec:
5294           reason_value = "exec";
5295           break;
5296         }
5297       }
5298 
5299       thread_dict_sp->AddStringItem("reason", reason_value);
5300 
5301       if (threads_with_valid_stop_info_only == false) {
5302         const char *thread_name = DNBThreadGetName(pid, tid);
5303         if (thread_name && thread_name[0])
5304           thread_dict_sp->AddStringItem("name", thread_name);
5305 
5306         thread_identifier_info_data_t thread_ident_info;
5307         if (DNBThreadGetIdentifierInfo(pid, tid, &thread_ident_info)) {
5308           if (thread_ident_info.dispatch_qaddr != 0) {
5309             thread_dict_sp->AddIntegerItem("qaddr",
5310                                            thread_ident_info.dispatch_qaddr);
5311 
5312             const DispatchQueueOffsets *dispatch_queue_offsets =
5313                 GetDispatchQueueOffsets();
5314             if (dispatch_queue_offsets) {
5315               std::string queue_name;
5316               uint64_t queue_width = 0;
5317               uint64_t queue_serialnum = 0;
5318               nub_addr_t dispatch_queue_t = INVALID_NUB_ADDRESS;
5319               dispatch_queue_offsets->GetThreadQueueInfo(
5320                   pid, thread_ident_info.dispatch_qaddr, dispatch_queue_t,
5321                   queue_name, queue_width, queue_serialnum);
5322               if (dispatch_queue_t == 0 && queue_name.empty() &&
5323                   queue_serialnum == 0) {
5324                 thread_dict_sp->AddBooleanItem("associated_with_dispatch_queue",
5325                                                false);
5326               } else {
5327                 thread_dict_sp->AddBooleanItem("associated_with_dispatch_queue",
5328                                                true);
5329               }
5330               if (dispatch_queue_t != INVALID_NUB_ADDRESS &&
5331                   dispatch_queue_t != 0)
5332                 thread_dict_sp->AddIntegerItem("dispatch_queue_t",
5333                                                dispatch_queue_t);
5334               if (!queue_name.empty())
5335                 thread_dict_sp->AddStringItem("qname", queue_name);
5336               if (queue_width == 1)
5337                 thread_dict_sp->AddStringItem("qkind", "serial");
5338               else if (queue_width > 1)
5339                 thread_dict_sp->AddStringItem("qkind", "concurrent");
5340               if (queue_serialnum > 0)
5341                 thread_dict_sp->AddIntegerItem("qserialnum", queue_serialnum);
5342             }
5343           }
5344         }
5345 
5346         DNBRegisterValue reg_value;
5347 
5348         if (g_reg_entries != NULL) {
5349           JSONGenerator::DictionarySP registers_dict_sp(
5350               new JSONGenerator::Dictionary());
5351 
5352           for (uint32_t reg = 0; reg < g_num_reg_entries; reg++) {
5353             // Expedite all registers in the first register set that aren't
5354             // contained in other registers
5355             if (g_reg_entries[reg].nub_info.set == 1 &&
5356                 g_reg_entries[reg].nub_info.value_regs == NULL) {
5357               if (!DNBThreadGetRegisterValueByID(
5358                       pid, tid, g_reg_entries[reg].nub_info.set,
5359                       g_reg_entries[reg].nub_info.reg, &reg_value))
5360                 continue;
5361 
5362               std::ostringstream reg_num;
5363               reg_num << std::dec << g_reg_entries[reg].debugserver_regnum;
5364               // Encode native byte ordered bytes as hex ascii
5365               registers_dict_sp->AddBytesAsHexASCIIString(
5366                   reg_num.str(), reg_value.value.v_uint8,
5367                   g_reg_entries[reg].nub_info.size);
5368             }
5369           }
5370           thread_dict_sp->AddItem("registers", registers_dict_sp);
5371         }
5372 
5373         // Add expedited stack memory so stack backtracing doesn't need to read
5374         // anything from the
5375         // frame pointer chain.
5376         StackMemoryMap stack_mmap;
5377         ReadStackMemory(pid, tid, stack_mmap);
5378         if (!stack_mmap.empty()) {
5379           JSONGenerator::ArraySP memory_array_sp(new JSONGenerator::Array());
5380 
5381           for (const auto &stack_memory : stack_mmap) {
5382             JSONGenerator::DictionarySP stack_memory_sp(
5383                 new JSONGenerator::Dictionary());
5384             stack_memory_sp->AddIntegerItem("address", stack_memory.first);
5385             stack_memory_sp->AddBytesAsHexASCIIString(
5386                 "bytes", stack_memory.second.bytes, stack_memory.second.length);
5387             memory_array_sp->AddItem(stack_memory_sp);
5388           }
5389           thread_dict_sp->AddItem("memory", memory_array_sp);
5390         }
5391       }
5392 
5393       threads_array_sp->AddItem(thread_dict_sp);
5394     }
5395   }
5396   return threads_array_sp;
5397 }
5398 
5399 rnb_err_t RNBRemote::HandlePacket_jThreadsInfo(const char *p) {
5400   JSONGenerator::ObjectSP threads_info_sp;
5401   std::ostringstream json;
5402   std::ostringstream reply_strm;
5403   // If we haven't run the process yet, return an error.
5404   if (m_ctx.HasValidProcessID()) {
5405     const bool threads_with_valid_stop_info_only = false;
5406     JSONGenerator::ObjectSP threads_info_sp =
5407         GetJSONThreadsInfo(threads_with_valid_stop_info_only);
5408 
5409     if (threads_info_sp) {
5410       std::ostringstream strm;
5411       threads_info_sp->Dump(strm);
5412       std::string binary_packet = binary_encode_string(strm.str());
5413       if (!binary_packet.empty())
5414         return SendPacket(binary_packet.c_str());
5415     }
5416   }
5417   return SendPacket("E85");
5418 }
5419 
5420 rnb_err_t RNBRemote::HandlePacket_jThreadExtendedInfo(const char *p) {
5421   nub_process_t pid;
5422   std::ostringstream json;
5423   // If we haven't run the process yet, return an error.
5424   if (!m_ctx.HasValidProcessID()) {
5425     return SendPacket("E81");
5426   }
5427 
5428   pid = m_ctx.ProcessID();
5429 
5430   const char thread_extended_info_str[] = {"jThreadExtendedInfo:{"};
5431   if (strncmp(p, thread_extended_info_str,
5432               sizeof(thread_extended_info_str) - 1) == 0) {
5433     p += strlen(thread_extended_info_str);
5434 
5435     uint64_t tid = get_integer_value_for_key_name_from_json("thread", p);
5436     uint64_t plo_pthread_tsd_base_address_offset =
5437         get_integer_value_for_key_name_from_json(
5438             "plo_pthread_tsd_base_address_offset", p);
5439     uint64_t plo_pthread_tsd_base_offset =
5440         get_integer_value_for_key_name_from_json("plo_pthread_tsd_base_offset",
5441                                                  p);
5442     uint64_t plo_pthread_tsd_entry_size =
5443         get_integer_value_for_key_name_from_json("plo_pthread_tsd_entry_size",
5444                                                  p);
5445     uint64_t dti_qos_class_index =
5446         get_integer_value_for_key_name_from_json("dti_qos_class_index", p);
5447     // Commented out the two variables below as they are not being used
5448     //        uint64_t dti_queue_index =
5449     //        get_integer_value_for_key_name_from_json ("dti_queue_index", p);
5450     //        uint64_t dti_voucher_index =
5451     //        get_integer_value_for_key_name_from_json ("dti_voucher_index", p);
5452 
5453     if (tid != INVALID_NUB_ADDRESS) {
5454       nub_addr_t pthread_t_value = DNBGetPThreadT(pid, tid);
5455 
5456       uint64_t tsd_address = INVALID_NUB_ADDRESS;
5457       if (plo_pthread_tsd_entry_size != INVALID_NUB_ADDRESS &&
5458           plo_pthread_tsd_base_offset != INVALID_NUB_ADDRESS &&
5459           plo_pthread_tsd_entry_size != INVALID_NUB_ADDRESS) {
5460         tsd_address = DNBGetTSDAddressForThread(
5461             pid, tid, plo_pthread_tsd_base_address_offset,
5462             plo_pthread_tsd_base_offset, plo_pthread_tsd_entry_size);
5463       }
5464 
5465       bool timed_out = false;
5466       Genealogy::ThreadActivitySP thread_activity_sp;
5467 
5468       // If the pthread_t value is invalid, or if we were able to fetch the
5469       // thread's TSD base
5470       // and got an invalid value back, then we have a thread in early startup
5471       // or shutdown and
5472       // it's possible that gathering the genealogy information for this thread
5473       // go badly.
5474       // Ideally fetching this info for a thread in these odd states shouldn't
5475       // matter - but
5476       // we've seen some problems with these new SPI and threads in edge-casey
5477       // states.
5478 
5479       double genealogy_fetch_time = 0;
5480       if (pthread_t_value != INVALID_NUB_ADDRESS &&
5481           tsd_address != INVALID_NUB_ADDRESS) {
5482         DNBTimer timer(false);
5483         thread_activity_sp = DNBGetGenealogyInfoForThread(pid, tid, timed_out);
5484         genealogy_fetch_time = timer.ElapsedMicroSeconds(false) / 1000000.0;
5485       }
5486 
5487       std::unordered_set<uint32_t>
5488           process_info_indexes; // an array of the process info #'s seen
5489 
5490       json << "{";
5491 
5492       bool need_to_print_comma = false;
5493 
5494       if (thread_activity_sp && timed_out == false) {
5495         const Genealogy::Activity *activity =
5496             &thread_activity_sp->current_activity;
5497         bool need_vouchers_comma_sep = false;
5498         json << "\"activity_query_timed_out\":false,";
5499         if (genealogy_fetch_time != 0) {
5500           //  If we append the floating point value with << we'll get it in
5501           //  scientific
5502           //  notation.
5503           char floating_point_ascii_buffer[64];
5504           floating_point_ascii_buffer[0] = '\0';
5505           snprintf(floating_point_ascii_buffer,
5506                    sizeof(floating_point_ascii_buffer), "%f",
5507                    genealogy_fetch_time);
5508           if (strlen(floating_point_ascii_buffer) > 0) {
5509             if (need_to_print_comma)
5510               json << ",";
5511             need_to_print_comma = true;
5512             json << "\"activity_query_duration\":"
5513                  << floating_point_ascii_buffer;
5514           }
5515         }
5516         if (activity->activity_id != 0) {
5517           if (need_to_print_comma)
5518             json << ",";
5519           need_to_print_comma = true;
5520           need_vouchers_comma_sep = true;
5521           json << "\"activity\":{";
5522           json << "\"start\":" << activity->activity_start << ",";
5523           json << "\"id\":" << activity->activity_id << ",";
5524           json << "\"parent_id\":" << activity->parent_id << ",";
5525           json << "\"name\":\""
5526                << json_string_quote_metachars(activity->activity_name) << "\",";
5527           json << "\"reason\":\""
5528                << json_string_quote_metachars(activity->reason) << "\"";
5529           json << "}";
5530         }
5531         if (thread_activity_sp->messages.size() > 0) {
5532           need_to_print_comma = true;
5533           if (need_vouchers_comma_sep)
5534             json << ",";
5535           need_vouchers_comma_sep = true;
5536           json << "\"trace_messages\":[";
5537           bool printed_one_message = false;
5538           for (auto iter = thread_activity_sp->messages.begin();
5539                iter != thread_activity_sp->messages.end(); ++iter) {
5540             if (printed_one_message)
5541               json << ",";
5542             else
5543               printed_one_message = true;
5544             json << "{";
5545             json << "\"timestamp\":" << iter->timestamp << ",";
5546             json << "\"activity_id\":" << iter->activity_id << ",";
5547             json << "\"trace_id\":" << iter->trace_id << ",";
5548             json << "\"thread\":" << iter->thread << ",";
5549             json << "\"type\":" << (int)iter->type << ",";
5550             json << "\"process_info_index\":" << iter->process_info_index
5551                  << ",";
5552             process_info_indexes.insert(iter->process_info_index);
5553             json << "\"message\":\""
5554                  << json_string_quote_metachars(iter->message) << "\"";
5555             json << "}";
5556           }
5557           json << "]";
5558         }
5559         if (thread_activity_sp->breadcrumbs.size() == 1) {
5560           need_to_print_comma = true;
5561           if (need_vouchers_comma_sep)
5562             json << ",";
5563           need_vouchers_comma_sep = true;
5564           json << "\"breadcrumb\":{";
5565           for (auto iter = thread_activity_sp->breadcrumbs.begin();
5566                iter != thread_activity_sp->breadcrumbs.end(); ++iter) {
5567             json << "\"breadcrumb_id\":" << iter->breadcrumb_id << ",";
5568             json << "\"activity_id\":" << iter->activity_id << ",";
5569             json << "\"timestamp\":" << iter->timestamp << ",";
5570             json << "\"name\":\"" << json_string_quote_metachars(iter->name)
5571                  << "\"";
5572           }
5573           json << "}";
5574         }
5575         if (process_info_indexes.size() > 0) {
5576           need_to_print_comma = true;
5577           if (need_vouchers_comma_sep)
5578             json << ",";
5579           need_vouchers_comma_sep = true;
5580           bool printed_one_process_info = false;
5581           for (auto iter = process_info_indexes.begin();
5582                iter != process_info_indexes.end(); ++iter) {
5583             if (printed_one_process_info)
5584               json << ",";
5585             Genealogy::ProcessExecutableInfoSP image_info_sp;
5586             uint32_t idx = *iter;
5587             image_info_sp = DNBGetGenealogyImageInfo(pid, idx);
5588             if (image_info_sp) {
5589               if (!printed_one_process_info) {
5590                 json << "\"process_infos\":[";
5591                 printed_one_process_info = true;
5592               }
5593 
5594               json << "{";
5595               char uuid_buf[37];
5596               uuid_unparse_upper(image_info_sp->image_uuid, uuid_buf);
5597               json << "\"process_info_index\":" << idx << ",";
5598               json << "\"image_path\":\""
5599                    << json_string_quote_metachars(image_info_sp->image_path)
5600                    << "\",";
5601               json << "\"image_uuid\":\"" << uuid_buf << "\"";
5602               json << "}";
5603             }
5604           }
5605           if (printed_one_process_info)
5606             json << "]";
5607         }
5608       } else {
5609         if (timed_out) {
5610           if (need_to_print_comma)
5611             json << ",";
5612           need_to_print_comma = true;
5613           json << "\"activity_query_timed_out\":true";
5614           if (genealogy_fetch_time != 0) {
5615             //  If we append the floating point value with << we'll get it in
5616             //  scientific
5617             //  notation.
5618             char floating_point_ascii_buffer[64];
5619             floating_point_ascii_buffer[0] = '\0';
5620             snprintf(floating_point_ascii_buffer,
5621                      sizeof(floating_point_ascii_buffer), "%f",
5622                      genealogy_fetch_time);
5623             if (strlen(floating_point_ascii_buffer) > 0) {
5624               json << ",";
5625               json << "\"activity_query_duration\":"
5626                    << floating_point_ascii_buffer;
5627             }
5628           }
5629         }
5630       }
5631 
5632       if (tsd_address != INVALID_NUB_ADDRESS) {
5633         if (need_to_print_comma)
5634           json << ",";
5635         need_to_print_comma = true;
5636         json << "\"tsd_address\":" << tsd_address;
5637 
5638         if (dti_qos_class_index != 0 && dti_qos_class_index != UINT64_MAX) {
5639           ThreadInfo::QoS requested_qos = DNBGetRequestedQoSForThread(
5640               pid, tid, tsd_address, dti_qos_class_index);
5641           if (requested_qos.IsValid()) {
5642             if (need_to_print_comma)
5643               json << ",";
5644             need_to_print_comma = true;
5645             json << "\"requested_qos\":{";
5646             json << "\"enum_value\":" << requested_qos.enum_value << ",";
5647             json << "\"constant_name\":\""
5648                  << json_string_quote_metachars(requested_qos.constant_name)
5649                  << "\",";
5650             json << "\"printable_name\":\""
5651                  << json_string_quote_metachars(requested_qos.printable_name)
5652                  << "\"";
5653             json << "}";
5654           }
5655         }
5656       }
5657 
5658       if (pthread_t_value != INVALID_NUB_ADDRESS) {
5659         if (need_to_print_comma)
5660           json << ",";
5661         need_to_print_comma = true;
5662         json << "\"pthread_t\":" << pthread_t_value;
5663       }
5664 
5665       nub_addr_t dispatch_queue_t_value = DNBGetDispatchQueueT(pid, tid);
5666       if (dispatch_queue_t_value != INVALID_NUB_ADDRESS) {
5667         if (need_to_print_comma)
5668           json << ",";
5669         need_to_print_comma = true;
5670         json << "\"dispatch_queue_t\":" << dispatch_queue_t_value;
5671       }
5672 
5673       json << "}";
5674       std::string json_quoted = binary_encode_string(json.str());
5675       return SendPacket(json_quoted);
5676     }
5677   }
5678   return SendPacket("OK");
5679 }
5680 
5681 //  This packet may be called in one of three ways:
5682 //
5683 //  jGetLoadedDynamicLibrariesInfos:{"image_count":40,"image_list_address":4295244704}
5684 //      Look for an array of the old dyld_all_image_infos style of binary infos
5685 //      at the image_list_address.
5686 //      This an array of {void* load_addr, void* mod_date, void* pathname}
5687 //
5688 //  jGetLoadedDynamicLibrariesInfos:{"fetch_all_solibs":true}
5689 //      Use the new style (macOS 10.12, tvOS 10, iOS 10, watchOS 3) dyld SPI to
5690 //      get a list of all the
5691 //      libraries loaded
5692 //
5693 //  jGetLoadedDynamicLibrariesInfos:{"solib_addresses":[8382824135,3258302053,830202858503]}
5694 //      Use the new style (macOS 10.12, tvOS 10, iOS 10, watchOS 3) dyld SPI to
5695 //      get the information
5696 //      about the libraries loaded at these addresses.
5697 //
5698 rnb_err_t
5699 RNBRemote::HandlePacket_jGetLoadedDynamicLibrariesInfos(const char *p) {
5700   nub_process_t pid;
5701   // If we haven't run the process yet, return an error.
5702   if (!m_ctx.HasValidProcessID()) {
5703     return SendPacket("E83");
5704   }
5705 
5706   pid = m_ctx.ProcessID();
5707 
5708   const char get_loaded_dynamic_libraries_infos_str[] = {
5709       "jGetLoadedDynamicLibrariesInfos:{"};
5710   if (strncmp(p, get_loaded_dynamic_libraries_infos_str,
5711               sizeof(get_loaded_dynamic_libraries_infos_str) - 1) == 0) {
5712     p += strlen(get_loaded_dynamic_libraries_infos_str);
5713 
5714     JSONGenerator::ObjectSP json_sp;
5715 
5716     std::vector<uint64_t> macho_addresses;
5717     bool fetch_all_solibs = false;
5718     if (get_boolean_value_for_key_name_from_json("fetch_all_solibs", p,
5719                                                  fetch_all_solibs) &&
5720         fetch_all_solibs) {
5721       json_sp = DNBGetAllLoadedLibrariesInfos(pid);
5722     } else if (get_array_of_ints_value_for_key_name_from_json(
5723                    "solib_addresses", p, macho_addresses)) {
5724       json_sp = DNBGetLibrariesInfoForAddresses(pid, macho_addresses);
5725     } else {
5726       nub_addr_t image_list_address =
5727           get_integer_value_for_key_name_from_json("image_list_address", p);
5728       nub_addr_t image_count =
5729           get_integer_value_for_key_name_from_json("image_count", p);
5730 
5731       if (image_list_address != INVALID_NUB_ADDRESS &&
5732           image_count != INVALID_NUB_ADDRESS) {
5733         json_sp = DNBGetLoadedDynamicLibrariesInfos(pid, image_list_address,
5734                                                     image_count);
5735       }
5736     }
5737 
5738     if (json_sp.get()) {
5739       std::ostringstream json_str;
5740       json_sp->Dump(json_str);
5741       if (json_str.str().size() > 0) {
5742         std::string json_str_quoted = binary_encode_string(json_str.str());
5743         return SendPacket(json_str_quoted.c_str());
5744       } else {
5745         SendPacket("E84");
5746       }
5747     }
5748   }
5749   return SendPacket("OK");
5750 }
5751 
5752 // This packet does not currently take any arguments.  So the behavior is
5753 //    jGetSharedCacheInfo:{}
5754 //         send information about the inferior's shared cache
5755 //    jGetSharedCacheInfo:
5756 //         send "OK" to indicate that this packet is supported
5757 rnb_err_t RNBRemote::HandlePacket_jGetSharedCacheInfo(const char *p) {
5758   nub_process_t pid;
5759   // If we haven't run the process yet, return an error.
5760   if (!m_ctx.HasValidProcessID()) {
5761     return SendPacket("E85");
5762   }
5763 
5764   pid = m_ctx.ProcessID();
5765 
5766   const char get_shared_cache_info_str[] = {"jGetSharedCacheInfo:{"};
5767   if (strncmp(p, get_shared_cache_info_str,
5768               sizeof(get_shared_cache_info_str) - 1) == 0) {
5769     JSONGenerator::ObjectSP json_sp = DNBGetSharedCacheInfo(pid);
5770 
5771     if (json_sp.get()) {
5772       std::ostringstream json_str;
5773       json_sp->Dump(json_str);
5774       if (json_str.str().size() > 0) {
5775         std::string json_str_quoted = binary_encode_string(json_str.str());
5776         return SendPacket(json_str_quoted.c_str());
5777       } else {
5778         SendPacket("E86");
5779       }
5780     }
5781   }
5782   return SendPacket("OK");
5783 }
5784 
5785 static bool MachHeaderIsMainExecutable(nub_process_t pid, uint32_t addr_size,
5786                                        nub_addr_t mach_header_addr,
5787                                        mach_header &mh) {
5788   DNBLogThreadedIf(LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = %u, "
5789                                  "addr_size = %u, mach_header_addr = "
5790                                  "0x%16.16llx)",
5791                    pid, addr_size, mach_header_addr);
5792   const nub_size_t bytes_read =
5793       DNBProcessMemoryRead(pid, mach_header_addr, sizeof(mh), &mh);
5794   if (bytes_read == sizeof(mh)) {
5795     DNBLogThreadedIf(
5796         LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = %u, addr_size = "
5797                       "%u, mach_header_addr = 0x%16.16llx): mh = {\n  magic = "
5798                       "0x%8.8x\n  cpu = 0x%8.8x\n  sub = 0x%8.8x\n  filetype = "
5799                       "%u\n  ncmds = %u\n  sizeofcmds = 0x%8.8x\n  flags = "
5800                       "0x%8.8x }",
5801         pid, addr_size, mach_header_addr, mh.magic, mh.cputype, mh.cpusubtype,
5802         mh.filetype, mh.ncmds, mh.sizeofcmds, mh.flags);
5803     if ((addr_size == 4 && mh.magic == MH_MAGIC) ||
5804         (addr_size == 8 && mh.magic == MH_MAGIC_64)) {
5805       if (mh.filetype == MH_EXECUTE) {
5806         DNBLogThreadedIf(LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = "
5807                                        "%u, addr_size = %u, mach_header_addr = "
5808                                        "0x%16.16llx) -> this is the "
5809                                        "executable!!!",
5810                          pid, addr_size, mach_header_addr);
5811         return true;
5812       }
5813     }
5814   }
5815   return false;
5816 }
5817 
5818 static nub_addr_t GetMachHeaderForMainExecutable(const nub_process_t pid,
5819                                                  const uint32_t addr_size,
5820                                                  mach_header &mh) {
5821   struct AllImageInfos {
5822     uint32_t version;
5823     uint32_t dylib_info_count;
5824     uint64_t dylib_info_addr;
5825   };
5826 
5827   uint64_t mach_header_addr = 0;
5828 
5829   const nub_addr_t shlib_addr = DNBProcessGetSharedLibraryInfoAddress(pid);
5830   uint8_t bytes[256];
5831   nub_size_t bytes_read = 0;
5832   DNBDataRef data(bytes, sizeof(bytes), false);
5833   DNBDataRef::offset_t offset = 0;
5834   data.SetPointerSize(addr_size);
5835 
5836   //----------------------------------------------------------------------
5837   // When we are sitting at __dyld_start, the kernel has placed the
5838   // address of the mach header of the main executable on the stack. If we
5839   // read the SP and dereference a pointer, we might find the mach header
5840   // for the executable. We also just make sure there is only 1 thread
5841   // since if we are at __dyld_start we shouldn't have multiple threads.
5842   //----------------------------------------------------------------------
5843   if (DNBProcessGetNumThreads(pid) == 1) {
5844     nub_thread_t tid = DNBProcessGetThreadAtIndex(pid, 0);
5845     if (tid != INVALID_NUB_THREAD) {
5846       DNBRegisterValue sp_value;
5847       if (DNBThreadGetRegisterValueByID(pid, tid, REGISTER_SET_GENERIC,
5848                                         GENERIC_REGNUM_SP, &sp_value)) {
5849         uint64_t sp =
5850             addr_size == 8 ? sp_value.value.uint64 : sp_value.value.uint32;
5851         bytes_read = DNBProcessMemoryRead(pid, sp, addr_size, bytes);
5852         if (bytes_read == addr_size) {
5853           offset = 0;
5854           mach_header_addr = data.GetPointer(&offset);
5855           if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, mh))
5856             return mach_header_addr;
5857         }
5858       }
5859     }
5860   }
5861 
5862   //----------------------------------------------------------------------
5863   // Check the dyld_all_image_info structure for a list of mach header
5864   // since it is a very easy thing to check
5865   //----------------------------------------------------------------------
5866   if (shlib_addr != INVALID_NUB_ADDRESS) {
5867     bytes_read =
5868         DNBProcessMemoryRead(pid, shlib_addr, sizeof(AllImageInfos), bytes);
5869     if (bytes_read > 0) {
5870       AllImageInfos aii;
5871       offset = 0;
5872       aii.version = data.Get32(&offset);
5873       aii.dylib_info_count = data.Get32(&offset);
5874       if (aii.dylib_info_count > 0) {
5875         aii.dylib_info_addr = data.GetPointer(&offset);
5876         if (aii.dylib_info_addr != 0) {
5877           const size_t image_info_byte_size = 3 * addr_size;
5878           for (uint32_t i = 0; i < aii.dylib_info_count; ++i) {
5879             bytes_read = DNBProcessMemoryRead(pid, aii.dylib_info_addr +
5880                                                        i * image_info_byte_size,
5881                                               image_info_byte_size, bytes);
5882             if (bytes_read != image_info_byte_size)
5883               break;
5884             offset = 0;
5885             mach_header_addr = data.GetPointer(&offset);
5886             if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr,
5887                                            mh))
5888               return mach_header_addr;
5889           }
5890         }
5891       }
5892     }
5893   }
5894 
5895   //----------------------------------------------------------------------
5896   // We failed to find the executable's mach header from the all image
5897   // infos and by dereferencing the stack pointer. Now we fall back to
5898   // enumerating the memory regions and looking for regions that are
5899   // executable.
5900   //----------------------------------------------------------------------
5901   DNBRegionInfo region_info;
5902   mach_header_addr = 0;
5903   while (DNBProcessMemoryRegionInfo(pid, mach_header_addr, &region_info)) {
5904     if (region_info.size == 0)
5905       break;
5906 
5907     if (region_info.permissions & eMemoryPermissionsExecutable) {
5908       DNBLogThreadedIf(
5909           LOG_RNB_PROC, "[0x%16.16llx - 0x%16.16llx) permissions = %c%c%c: "
5910                         "checking region for executable mach header",
5911           region_info.addr, region_info.addr + region_info.size,
5912           (region_info.permissions & eMemoryPermissionsReadable) ? 'r' : '-',
5913           (region_info.permissions & eMemoryPermissionsWritable) ? 'w' : '-',
5914           (region_info.permissions & eMemoryPermissionsExecutable) ? 'x' : '-');
5915       if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, mh))
5916         return mach_header_addr;
5917     } else {
5918       DNBLogThreadedIf(
5919           LOG_RNB_PROC,
5920           "[0x%16.16llx - 0x%16.16llx): permissions = %c%c%c: skipping region",
5921           region_info.addr, region_info.addr + region_info.size,
5922           (region_info.permissions & eMemoryPermissionsReadable) ? 'r' : '-',
5923           (region_info.permissions & eMemoryPermissionsWritable) ? 'w' : '-',
5924           (region_info.permissions & eMemoryPermissionsExecutable) ? 'x' : '-');
5925     }
5926     // Set the address to the next mapped region
5927     mach_header_addr = region_info.addr + region_info.size;
5928   }
5929   bzero(&mh, sizeof(mh));
5930   return INVALID_NUB_ADDRESS;
5931 }
5932 
5933 rnb_err_t RNBRemote::HandlePacket_qSymbol(const char *command) {
5934   const char *p = command;
5935   p += strlen("qSymbol:");
5936   const char *sep = strchr(p, ':');
5937 
5938   std::string symbol_name;
5939   std::string symbol_value_str;
5940   // Extract the symbol value if there is one
5941   if (sep > p)
5942     symbol_value_str.assign(p, sep - p);
5943   p = sep + 1;
5944 
5945   if (*p) {
5946     // We have a symbol name
5947     symbol_name = decode_hex_ascii_string(p);
5948     if (!symbol_value_str.empty()) {
5949       nub_addr_t symbol_value = decode_uint64(symbol_value_str.c_str(), 16);
5950       if (symbol_name == "dispatch_queue_offsets")
5951         m_dispatch_queue_offsets_addr = symbol_value;
5952     }
5953     ++m_qSymbol_index;
5954   } else {
5955     // No symbol name, set our symbol index to zero so we can
5956     // read any symbols that we need
5957     m_qSymbol_index = 0;
5958   }
5959 
5960   symbol_name.clear();
5961 
5962   if (m_qSymbol_index == 0) {
5963     if (m_dispatch_queue_offsets_addr == INVALID_NUB_ADDRESS)
5964       symbol_name = "dispatch_queue_offsets";
5965     else
5966       ++m_qSymbol_index;
5967   }
5968 
5969   //    // Lookup next symbol when we have one...
5970   //    if (m_qSymbol_index == 1)
5971   //    {
5972   //    }
5973 
5974   if (symbol_name.empty()) {
5975     // Done with symbol lookups
5976     return SendPacket("OK");
5977   } else {
5978     std::ostringstream reply;
5979     reply << "qSymbol:";
5980     for (size_t i = 0; i < symbol_name.size(); ++i)
5981       reply << RAWHEX8(symbol_name[i]);
5982     return SendPacket(reply.str().c_str());
5983   }
5984 }
5985 
5986 // Note that all numeric values returned by qProcessInfo are hex encoded,
5987 // including the pid and the cpu type.
5988 
5989 rnb_err_t RNBRemote::HandlePacket_qProcessInfo(const char *p) {
5990   nub_process_t pid;
5991   std::ostringstream rep;
5992 
5993   // If we haven't run the process yet, return an error.
5994   if (!m_ctx.HasValidProcessID())
5995     return SendPacket("E68");
5996 
5997   pid = m_ctx.ProcessID();
5998 
5999   rep << "pid:" << std::hex << pid << ';';
6000 
6001   int procpid_mib[4];
6002   procpid_mib[0] = CTL_KERN;
6003   procpid_mib[1] = KERN_PROC;
6004   procpid_mib[2] = KERN_PROC_PID;
6005   procpid_mib[3] = pid;
6006   struct kinfo_proc proc_kinfo;
6007   size_t proc_kinfo_size = sizeof(struct kinfo_proc);
6008 
6009   if (::sysctl(procpid_mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) {
6010     if (proc_kinfo_size > 0) {
6011       rep << "parent-pid:" << std::hex << proc_kinfo.kp_eproc.e_ppid << ';';
6012       rep << "real-uid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_ruid
6013           << ';';
6014       rep << "real-gid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_rgid
6015           << ';';
6016       rep << "effective-uid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_uid
6017           << ';';
6018       if (proc_kinfo.kp_eproc.e_ucred.cr_ngroups > 0)
6019         rep << "effective-gid:" << std::hex
6020             << proc_kinfo.kp_eproc.e_ucred.cr_groups[0] << ';';
6021     }
6022   }
6023 
6024   cpu_type_t cputype = DNBProcessGetCPUType(pid);
6025   if (cputype == 0) {
6026     DNBLog("Unable to get the process cpu_type, making a best guess.");
6027     cputype = best_guess_cpu_type();
6028   }
6029 
6030   uint32_t addr_size = 0;
6031   if (cputype != 0) {
6032     rep << "cputype:" << std::hex << cputype << ";";
6033     if (cputype & CPU_ARCH_ABI64)
6034       addr_size = 8;
6035     else
6036       addr_size = 4;
6037   }
6038 
6039   bool host_cpu_is_64bit = false;
6040   uint32_t is64bit_capable;
6041   size_t is64bit_capable_len = sizeof(is64bit_capable);
6042   if (sysctlbyname("hw.cpu64bit_capable", &is64bit_capable,
6043                    &is64bit_capable_len, NULL, 0) == 0)
6044     host_cpu_is_64bit = is64bit_capable != 0;
6045 
6046   uint32_t cpusubtype;
6047   size_t cpusubtype_len = sizeof(cpusubtype);
6048   if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &cpusubtype_len, NULL, 0) ==
6049       0) {
6050     // If a process is CPU_TYPE_X86, then ignore the cpusubtype that we detected
6051     // from the host and use CPU_SUBTYPE_I386_ALL because we don't want the
6052     // CPU_SUBTYPE_X86_ARCH1 or CPU_SUBTYPE_X86_64_H to be used as the cpu
6053     // subtype
6054     // for i386...
6055     if (host_cpu_is_64bit) {
6056       if (cputype == CPU_TYPE_X86) {
6057         cpusubtype = 3; // CPU_SUBTYPE_I386_ALL
6058       } else if (cputype == CPU_TYPE_ARM) {
6059         // We can query a process' cputype but we cannot query a process'
6060         // cpusubtype.
6061         // If the process has cputype CPU_TYPE_ARM, then it is an armv7 (32-bit
6062         // process) and we
6063         // need to override the host cpusubtype (which is in the
6064         // CPU_SUBTYPE_ARM64 subtype namespace)
6065         // with a reasonable CPU_SUBTYPE_ARMV7 subtype.
6066         cpusubtype = 11; // CPU_SUBTYPE_ARM_V7S
6067       }
6068     }
6069     rep << "cpusubtype:" << std::hex << cpusubtype << ';';
6070   }
6071 
6072   bool os_handled = false;
6073   if (addr_size > 0) {
6074     rep << "ptrsize:" << std::dec << addr_size << ';';
6075 
6076 #if (defined(__x86_64__) || defined(__i386__))
6077     // Try and get the OS type by looking at the load commands in the main
6078     // executable and looking for a LC_VERSION_MIN load command. This is the
6079     // most reliable way to determine the "ostype" value when on desktop.
6080 
6081     mach_header mh;
6082     nub_addr_t exe_mach_header_addr =
6083         GetMachHeaderForMainExecutable(pid, addr_size, mh);
6084     if (exe_mach_header_addr != INVALID_NUB_ADDRESS) {
6085       uint64_t load_command_addr =
6086           exe_mach_header_addr +
6087           ((addr_size == 8) ? sizeof(mach_header_64) : sizeof(mach_header));
6088       load_command lc;
6089       for (uint32_t i = 0; i < mh.ncmds && !os_handled; ++i) {
6090         const nub_size_t bytes_read =
6091             DNBProcessMemoryRead(pid, load_command_addr, sizeof(lc), &lc);
6092         uint32_t raw_cmd = lc.cmd & ~LC_REQ_DYLD;
6093         if (bytes_read != sizeof(lc))
6094           break;
6095         switch (raw_cmd) {
6096         case LC_VERSION_MIN_IPHONEOS:
6097           os_handled = true;
6098           rep << "ostype:ios;";
6099           DNBLogThreadedIf(LOG_RNB_PROC,
6100                            "LC_VERSION_MIN_IPHONEOS -> 'ostype:ios;'");
6101           break;
6102 
6103         case LC_VERSION_MIN_MACOSX:
6104           os_handled = true;
6105           rep << "ostype:macosx;";
6106           DNBLogThreadedIf(LOG_RNB_PROC,
6107                            "LC_VERSION_MIN_MACOSX -> 'ostype:macosx;'");
6108           break;
6109 
6110 #if defined(LC_VERSION_MIN_TVOS)
6111         case LC_VERSION_MIN_TVOS:
6112           os_handled = true;
6113           rep << "ostype:tvos;";
6114           DNBLogThreadedIf(LOG_RNB_PROC,
6115                            "LC_VERSION_MIN_TVOS -> 'ostype:tvos;'");
6116           break;
6117 #endif
6118 
6119 #if defined(LC_VERSION_MIN_WATCHOS)
6120         case LC_VERSION_MIN_WATCHOS:
6121           os_handled = true;
6122           rep << "ostype:watchos;";
6123           DNBLogThreadedIf(LOG_RNB_PROC,
6124                            "LC_VERSION_MIN_WATCHOS -> 'ostype:watchos;'");
6125           break;
6126 #endif
6127 
6128         default:
6129           break;
6130         }
6131         load_command_addr = load_command_addr + lc.cmdsize;
6132       }
6133     }
6134 #endif
6135   }
6136 
6137   // If we weren't able to find the OS in a LC_VERSION_MIN load command, try
6138   // to set it correctly by using the cpu type and other tricks
6139   if (!os_handled) {
6140     // The OS in the triple should be "ios" or "macosx" which doesn't match our
6141     // "Darwin" which gets returned from "kern.ostype", so we need to hardcode
6142     // this for now.
6143     if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64) {
6144 #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
6145       rep << "ostype:tvos;";
6146 #elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
6147       rep << "ostype:watchos;";
6148 #else
6149       rep << "ostype:ios;";
6150 #endif
6151     } else {
6152       bool is_ios_simulator = false;
6153       if (cputype == CPU_TYPE_X86 || cputype == CPU_TYPE_X86_64) {
6154         // Check for iOS simulator binaries by getting the process argument
6155         // and environment and checking for SIMULATOR_UDID in the environment
6156         int proc_args_mib[3] = {CTL_KERN, KERN_PROCARGS2, (int)pid};
6157 
6158         uint8_t arg_data[8192];
6159         size_t arg_data_size = sizeof(arg_data);
6160         if (::sysctl(proc_args_mib, 3, arg_data, &arg_data_size, NULL, 0) ==
6161             0) {
6162           DNBDataRef data(arg_data, arg_data_size, false);
6163           DNBDataRef::offset_t offset = 0;
6164           uint32_t argc = data.Get32(&offset);
6165           const char *cstr;
6166 
6167           cstr = data.GetCStr(&offset);
6168           if (cstr) {
6169             // Skip NULLs
6170             while (1) {
6171               const char *p = data.PeekCStr(offset);
6172               if ((p == NULL) || (*p != '\0'))
6173                 break;
6174               ++offset;
6175             }
6176             // Now skip all arguments
6177             for (uint32_t i = 0; i < argc; ++i) {
6178               data.GetCStr(&offset);
6179             }
6180 
6181             // Now iterate across all environment variables
6182             while ((cstr = data.GetCStr(&offset))) {
6183               if (strncmp(cstr, "SIMULATOR_UDID=", strlen("SIMULATOR_UDID=")) ==
6184                   0) {
6185                 is_ios_simulator = true;
6186                 break;
6187               }
6188               if (cstr[0] == '\0')
6189                 break;
6190             }
6191           }
6192         }
6193       }
6194       if (is_ios_simulator) {
6195 #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
6196         rep << "ostype:tvos;";
6197 #elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
6198         rep << "ostype:watchos;";
6199 #else
6200         rep << "ostype:ios;";
6201 #endif
6202       } else {
6203         rep << "ostype:macosx;";
6204       }
6205     }
6206   }
6207 
6208   rep << "vendor:apple;";
6209 
6210 #if defined(__LITTLE_ENDIAN__)
6211   rep << "endian:little;";
6212 #elif defined(__BIG_ENDIAN__)
6213   rep << "endian:big;";
6214 #elif defined(__PDP_ENDIAN__)
6215   rep << "endian:pdp;";
6216 #endif
6217 
6218   if (addr_size == 0) {
6219 #if (defined(__x86_64__) || defined(__i386__)) && defined(x86_THREAD_STATE)
6220     nub_thread_t thread = DNBProcessGetCurrentThreadMachPort(pid);
6221     kern_return_t kr;
6222     x86_thread_state_t gp_regs;
6223     mach_msg_type_number_t gp_count = x86_THREAD_STATE_COUNT;
6224     kr = thread_get_state(static_cast<thread_act_t>(thread), x86_THREAD_STATE,
6225                           (thread_state_t)&gp_regs, &gp_count);
6226     if (kr == KERN_SUCCESS) {
6227       if (gp_regs.tsh.flavor == x86_THREAD_STATE64)
6228         rep << "ptrsize:8;";
6229       else
6230         rep << "ptrsize:4;";
6231     }
6232 #elif defined(__arm__)
6233     rep << "ptrsize:4;";
6234 #elif (defined(__arm64__) || defined(__aarch64__)) &&                          \
6235     defined(ARM_UNIFIED_THREAD_STATE)
6236     nub_thread_t thread = DNBProcessGetCurrentThreadMachPort(pid);
6237     kern_return_t kr;
6238     arm_unified_thread_state_t gp_regs;
6239     mach_msg_type_number_t gp_count = ARM_UNIFIED_THREAD_STATE_COUNT;
6240     kr = thread_get_state(thread, ARM_UNIFIED_THREAD_STATE,
6241                           (thread_state_t)&gp_regs, &gp_count);
6242     if (kr == KERN_SUCCESS) {
6243       if (gp_regs.ash.flavor == ARM_THREAD_STATE64)
6244         rep << "ptrsize:8;";
6245       else
6246         rep << "ptrsize:4;";
6247     }
6248 #endif
6249   }
6250 
6251   return SendPacket(rep.str());
6252 }
6253 
6254 const RNBRemote::DispatchQueueOffsets *RNBRemote::GetDispatchQueueOffsets() {
6255   if (!m_dispatch_queue_offsets.IsValid() &&
6256       m_dispatch_queue_offsets_addr != INVALID_NUB_ADDRESS &&
6257       m_ctx.HasValidProcessID()) {
6258     nub_process_t pid = m_ctx.ProcessID();
6259     nub_size_t bytes_read = DNBProcessMemoryRead(
6260         pid, m_dispatch_queue_offsets_addr, sizeof(m_dispatch_queue_offsets),
6261         &m_dispatch_queue_offsets);
6262     if (bytes_read != sizeof(m_dispatch_queue_offsets))
6263       m_dispatch_queue_offsets.Clear();
6264   }
6265 
6266   if (m_dispatch_queue_offsets.IsValid())
6267     return &m_dispatch_queue_offsets;
6268   else
6269     return nullptr;
6270 }
6271 
6272 void RNBRemote::EnableCompressionNextSendPacket(compression_types type) {
6273   m_compression_mode = type;
6274   m_enable_compression_next_send_packet = true;
6275 }
6276 
6277 compression_types RNBRemote::GetCompressionType() {
6278   // The first packet we send back to the debugger after a QEnableCompression
6279   // request
6280   // should be uncompressed -- so we can indicate whether the compression was
6281   // enabled
6282   // or not via OK / Enn returns.  After that, all packets sent will be using
6283   // the
6284   // compression protocol.
6285 
6286   if (m_enable_compression_next_send_packet) {
6287     // One time, we send back "None" as our compression type
6288     m_enable_compression_next_send_packet = false;
6289     return compression_types::none;
6290   }
6291   return m_compression_mode;
6292 }
6293