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().Status() == 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   bool enable_compression = false;
3615   (void)enable_compression;
3616 
3617 #if (defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1) || (defined (TARGET_OS_IOS) && TARGET_OS_IOS == 1) || (defined (TARGET_OS_TV) && TARGET_OS_TV == 1)
3618   enable_compression = true;
3619 #endif
3620 
3621 #if defined(HAVE_LIBCOMPRESSION)
3622   // libcompression is weak linked so test if compression_decode_buffer() is
3623   // available
3624   if (enable_compression && compression_decode_buffer != NULL) {
3625     strcat(buf, ";SupportedCompressions=lzfse,zlib-deflate,lz4,lzma;"
3626                 "DefaultCompressionMinSize=");
3627     char numbuf[16];
3628     snprintf(numbuf, sizeof(numbuf), "%zu", m_compression_minsize);
3629     numbuf[sizeof(numbuf) - 1] = '\0';
3630     strcat(buf, numbuf);
3631   }
3632 #elif defined(HAVE_LIBZ)
3633   if (enable_compression) {
3634     strcat(buf,
3635            ";SupportedCompressions=zlib-deflate;DefaultCompressionMinSize=");
3636     char numbuf[16];
3637     snprintf(numbuf, sizeof(numbuf), "%zu", m_compression_minsize);
3638     numbuf[sizeof(numbuf) - 1] = '\0';
3639     strcat(buf, numbuf);
3640   }
3641 #endif
3642 
3643   return SendPacket(buf);
3644 }
3645 
3646 /*
3647  vAttach;pid
3648 
3649  Attach to a new process with the specified process ID. pid is a hexadecimal
3650  integer
3651  identifying the process. If the stub is currently controlling a process, it is
3652  killed. The attached process is stopped.This packet is only available in
3653  extended
3654  mode (see extended mode).
3655 
3656  Reply:
3657  "ENN"                      for an error
3658  "Any Stop Reply Packet"     for success
3659  */
3660 
3661 rnb_err_t RNBRemote::HandlePacket_v(const char *p) {
3662   if (strcmp(p, "vCont;c") == 0) {
3663     // Simple continue
3664     return RNBRemote::HandlePacket_c("c");
3665   } else if (strcmp(p, "vCont;s") == 0) {
3666     // Simple step
3667     return RNBRemote::HandlePacket_s("s");
3668   } else if (strstr(p, "vCont") == p) {
3669     DNBThreadResumeActions thread_actions;
3670     char *c = (char *)(p += strlen("vCont"));
3671     char *c_end = c + strlen(c);
3672     if (*c == '?')
3673       return SendPacket("vCont;c;C;s;S");
3674 
3675     while (c < c_end && *c == ';') {
3676       ++c; // Skip the semi-colon
3677       DNBThreadResumeAction thread_action;
3678       thread_action.tid = INVALID_NUB_THREAD;
3679       thread_action.state = eStateInvalid;
3680       thread_action.signal = 0;
3681       thread_action.addr = INVALID_NUB_ADDRESS;
3682 
3683       char action = *c++;
3684 
3685       switch (action) {
3686       case 'C':
3687         errno = 0;
3688         thread_action.signal = static_cast<int>(strtoul(c, &c, 16));
3689         if (errno != 0)
3690           return HandlePacket_ILLFORMED(
3691               __FILE__, __LINE__, p, "Could not parse signal in vCont packet");
3692       // Fall through to next case...
3693 
3694       case 'c':
3695         // Continue
3696         thread_action.state = eStateRunning;
3697         break;
3698 
3699       case 'S':
3700         errno = 0;
3701         thread_action.signal = static_cast<int>(strtoul(c, &c, 16));
3702         if (errno != 0)
3703           return HandlePacket_ILLFORMED(
3704               __FILE__, __LINE__, p, "Could not parse signal in vCont packet");
3705       // Fall through to next case...
3706 
3707       case 's':
3708         // Step
3709         thread_action.state = eStateStepping;
3710         break;
3711 
3712       default:
3713         HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3714                                "Unsupported action in vCont packet");
3715         break;
3716       }
3717       if (*c == ':') {
3718         errno = 0;
3719         thread_action.tid = strtoul(++c, &c, 16);
3720         if (errno != 0)
3721           return HandlePacket_ILLFORMED(
3722               __FILE__, __LINE__, p,
3723               "Could not parse thread number in vCont packet");
3724       }
3725 
3726       thread_actions.Append(thread_action);
3727     }
3728 
3729     // If a default action for all other threads wasn't mentioned
3730     // then we should stop the threads
3731     thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
3732     DNBProcessResume(m_ctx.ProcessID(), thread_actions.GetFirst(),
3733                      thread_actions.GetSize());
3734     return rnb_success;
3735   } else if (strstr(p, "vAttach") == p) {
3736     nub_process_t attach_pid =
3737         INVALID_NUB_PROCESS; // attach_pid will be set to 0 if the attach fails
3738     nub_process_t pid_attaching_to =
3739         INVALID_NUB_PROCESS; // pid_attaching_to is the original pid specified
3740     char err_str[1024] = {'\0'};
3741     std::string attach_name;
3742 
3743     if (strstr(p, "vAttachWait;") == p) {
3744       p += strlen("vAttachWait;");
3745       if (!GetProcessNameFrom_vAttach(p, attach_name)) {
3746         return HandlePacket_ILLFORMED(
3747             __FILE__, __LINE__, p, "non-hex char in arg on 'vAttachWait' pkt");
3748       }
3749       const bool ignore_existing = true;
3750       attach_pid = DNBProcessAttachWait(
3751           attach_name.c_str(), m_ctx.LaunchFlavor(), ignore_existing, NULL,
3752           1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback);
3753 
3754     } else if (strstr(p, "vAttachOrWait;") == p) {
3755       p += strlen("vAttachOrWait;");
3756       if (!GetProcessNameFrom_vAttach(p, attach_name)) {
3757         return HandlePacket_ILLFORMED(
3758             __FILE__, __LINE__, p,
3759             "non-hex char in arg on 'vAttachOrWait' pkt");
3760       }
3761       const bool ignore_existing = false;
3762       attach_pid = DNBProcessAttachWait(
3763           attach_name.c_str(), m_ctx.LaunchFlavor(), ignore_existing, NULL,
3764           1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback);
3765     } else if (strstr(p, "vAttachName;") == p) {
3766       p += strlen("vAttachName;");
3767       if (!GetProcessNameFrom_vAttach(p, attach_name)) {
3768         return HandlePacket_ILLFORMED(
3769             __FILE__, __LINE__, p, "non-hex char in arg on 'vAttachName' pkt");
3770       }
3771 
3772       attach_pid = DNBProcessAttachByName(attach_name.c_str(), NULL, err_str,
3773                                           sizeof(err_str));
3774 
3775     } else if (strstr(p, "vAttach;") == p) {
3776       p += strlen("vAttach;");
3777       char *end = NULL;
3778       pid_attaching_to = static_cast<int>(
3779           strtoul(p, &end, 16)); // PID will be in hex, so use base 16 to decode
3780       if (p != end && *end == '\0') {
3781         // Wait at most 30 second for attach
3782         struct timespec attach_timeout_abstime;
3783         DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, 30, 0);
3784         attach_pid = DNBProcessAttach(pid_attaching_to, &attach_timeout_abstime,
3785                                       err_str, sizeof(err_str));
3786       }
3787     } else {
3788       return HandlePacket_UNIMPLEMENTED(p);
3789     }
3790 
3791     if (attach_pid != INVALID_NUB_PROCESS) {
3792       if (m_ctx.ProcessID() != attach_pid)
3793         m_ctx.SetProcessID(attach_pid);
3794       // Send a stop reply packet to indicate we successfully attached!
3795       NotifyThatProcessStopped();
3796       return rnb_success;
3797     } else {
3798       m_ctx.LaunchStatus().SetError(-1, DNBError::Generic);
3799       if (err_str[0])
3800         m_ctx.LaunchStatus().SetErrorString(err_str);
3801       else
3802         m_ctx.LaunchStatus().SetErrorString("attach failed");
3803 
3804 #if defined(__APPLE__) &&                                                      \
3805     (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101000)
3806       if (pid_attaching_to == INVALID_NUB_PROCESS && !attach_name.empty()) {
3807         pid_attaching_to = DNBProcessGetPIDByName(attach_name.c_str());
3808       }
3809       if (pid_attaching_to != INVALID_NUB_PROCESS &&
3810           strcmp(err_str, "No such process") != 0) {
3811         // csr_check(CSR_ALLOW_TASK_FOR_PID) will be nonzero if System Integrity
3812         // Protection is in effect.
3813         if (csr_check(CSR_ALLOW_TASK_FOR_PID) != 0) {
3814           bool attach_failed_due_to_sip = false;
3815 
3816           if (rootless_allows_task_for_pid(pid_attaching_to) == 0) {
3817             attach_failed_due_to_sip = true;
3818           }
3819 
3820           if (attach_failed_due_to_sip == false) {
3821             int csops_flags = 0;
3822             int retval = ::csops(pid_attaching_to, CS_OPS_STATUS, &csops_flags,
3823                                  sizeof(csops_flags));
3824             if (retval != -1 && (csops_flags & CS_RESTRICT)) {
3825               attach_failed_due_to_sip = true;
3826             }
3827           }
3828           if (attach_failed_due_to_sip) {
3829             SendPacket("E87"); // E87 is the magic value which says that we are
3830                                // not allowed to attach
3831             DNBLogError("Attach failed because process does not allow "
3832                         "attaching: \"%s\".",
3833                         err_str);
3834             return rnb_err;
3835           }
3836         }
3837       }
3838 
3839 #endif
3840 
3841       SendPacket("E01"); // E01 is our magic error value for attach failed.
3842       DNBLogError("Attach failed: \"%s\".", err_str);
3843       return rnb_err;
3844     }
3845   }
3846 
3847   // All other failures come through here
3848   return HandlePacket_UNIMPLEMENTED(p);
3849 }
3850 
3851 /* 'T XX' -- status of thread
3852  Check if the specified thread is alive.
3853  The thread number is in hex?  */
3854 
3855 rnb_err_t RNBRemote::HandlePacket_T(const char *p) {
3856   p++;
3857   if (p == NULL || *p == '\0') {
3858     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3859                                   "No thread specified in T packet");
3860   }
3861   if (!m_ctx.HasValidProcessID()) {
3862     return SendPacket("E15");
3863   }
3864   errno = 0;
3865   nub_thread_t tid = strtoul(p, NULL, 16);
3866   if (errno != 0 && tid == 0) {
3867     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3868                                   "Could not parse thread number in T packet");
3869   }
3870 
3871   nub_state_t state = DNBThreadGetState(m_ctx.ProcessID(), tid);
3872   if (state == eStateInvalid || state == eStateExited ||
3873       state == eStateCrashed) {
3874     return SendPacket("E16");
3875   }
3876 
3877   return SendPacket("OK");
3878 }
3879 
3880 rnb_err_t RNBRemote::HandlePacket_z(const char *p) {
3881   if (p == NULL || *p == '\0')
3882     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3883                                   "No thread specified in z packet");
3884 
3885   if (!m_ctx.HasValidProcessID())
3886     return SendPacket("E15");
3887 
3888   char packet_cmd = *p++;
3889   char break_type = *p++;
3890 
3891   if (*p++ != ',')
3892     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3893                                   "Comma separator missing in z packet");
3894 
3895   char *c = NULL;
3896   nub_process_t pid = m_ctx.ProcessID();
3897   errno = 0;
3898   nub_addr_t addr = strtoull(p, &c, 16);
3899   if (errno != 0 && addr == 0)
3900     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3901                                   "Invalid address in z packet");
3902   p = c;
3903   if (*p++ != ',')
3904     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3905                                   "Comma separator missing in z packet");
3906 
3907   errno = 0;
3908   auto byte_size = strtoul(p, &c, 16);
3909   if (errno != 0 && byte_size == 0)
3910     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3911                                   "Invalid length in z packet");
3912 
3913   if (packet_cmd == 'Z') {
3914     // set
3915     switch (break_type) {
3916     case '0': // set software breakpoint
3917     case '1': // set hardware breakpoint
3918     {
3919       // gdb can send multiple Z packets for the same address and
3920       // these calls must be ref counted.
3921       bool hardware = (break_type == '1');
3922 
3923       if (DNBBreakpointSet(pid, addr, byte_size, hardware)) {
3924         // We successfully created a breakpoint, now lets full out
3925         // a ref count structure with the breakID and add it to our
3926         // map.
3927         return SendPacket("OK");
3928       } else {
3929         // We failed to set the software breakpoint
3930         return SendPacket("E09");
3931       }
3932     } break;
3933 
3934     case '2': // set write watchpoint
3935     case '3': // set read watchpoint
3936     case '4': // set access watchpoint
3937     {
3938       bool hardware = true;
3939       uint32_t watch_flags = 0;
3940       if (break_type == '2')
3941         watch_flags = WATCH_TYPE_WRITE;
3942       else if (break_type == '3')
3943         watch_flags = WATCH_TYPE_READ;
3944       else
3945         watch_flags = WATCH_TYPE_READ | WATCH_TYPE_WRITE;
3946 
3947       if (DNBWatchpointSet(pid, addr, byte_size, watch_flags, hardware)) {
3948         return SendPacket("OK");
3949       } else {
3950         // We failed to set the watchpoint
3951         return SendPacket("E09");
3952       }
3953     } break;
3954 
3955     default:
3956       break;
3957     }
3958   } else if (packet_cmd == 'z') {
3959     // remove
3960     switch (break_type) {
3961     case '0': // remove software breakpoint
3962     case '1': // remove hardware breakpoint
3963       if (DNBBreakpointClear(pid, addr)) {
3964         return SendPacket("OK");
3965       } else {
3966         return SendPacket("E08");
3967       }
3968       break;
3969 
3970     case '2': // remove write watchpoint
3971     case '3': // remove read watchpoint
3972     case '4': // remove access watchpoint
3973       if (DNBWatchpointClear(pid, addr)) {
3974         return SendPacket("OK");
3975       } else {
3976         return SendPacket("E08");
3977       }
3978       break;
3979 
3980     default:
3981       break;
3982     }
3983   }
3984   return HandlePacket_UNIMPLEMENTED(p);
3985 }
3986 
3987 // Extract the thread number from the thread suffix that might be appended to
3988 // thread specific packets. This will only be enabled if
3989 // m_thread_suffix_supported
3990 // is true.
3991 nub_thread_t RNBRemote::ExtractThreadIDFromThreadSuffix(const char *p) {
3992   if (m_thread_suffix_supported) {
3993     nub_thread_t tid = INVALID_NUB_THREAD;
3994     if (p) {
3995       const char *tid_cstr = strstr(p, "thread:");
3996       if (tid_cstr) {
3997         tid_cstr += strlen("thread:");
3998         tid = strtoul(tid_cstr, NULL, 16);
3999       }
4000     }
4001     return tid;
4002   }
4003   return GetCurrentThread();
4004 }
4005 
4006 /* 'p XX'
4007  print the contents of register X */
4008 
4009 rnb_err_t RNBRemote::HandlePacket_p(const char *p) {
4010   if (g_num_reg_entries == 0)
4011     InitializeRegisters();
4012 
4013   if (p == NULL || *p == '\0') {
4014     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4015                                   "No thread specified in p packet");
4016   }
4017   if (!m_ctx.HasValidProcessID()) {
4018     return SendPacket("E15");
4019   }
4020   nub_process_t pid = m_ctx.ProcessID();
4021   errno = 0;
4022   char *tid_cstr = NULL;
4023   uint32_t reg = static_cast<uint32_t>(strtoul(p + 1, &tid_cstr, 16));
4024   if (errno != 0 && reg == 0) {
4025     return HandlePacket_ILLFORMED(
4026         __FILE__, __LINE__, p, "Could not parse register number in p packet");
4027   }
4028 
4029   nub_thread_t tid = ExtractThreadIDFromThreadSuffix(tid_cstr);
4030   if (tid == INVALID_NUB_THREAD)
4031     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4032                                   "No thread specified in p packet");
4033 
4034   const register_map_entry_t *reg_entry;
4035 
4036   if (reg < g_num_reg_entries)
4037     reg_entry = &g_reg_entries[reg];
4038   else
4039     reg_entry = NULL;
4040 
4041   std::ostringstream ostrm;
4042   if (reg_entry == NULL) {
4043     DNBLogError(
4044         "RNBRemote::HandlePacket_p(%s): unknown register number %u requested\n",
4045         p, reg);
4046     ostrm << "00000000";
4047   } else if (reg_entry->nub_info.reg == (uint32_t)-1) {
4048     if (reg_entry->nub_info.size > 0) {
4049       std::basic_string<uint8_t> zeros(reg_entry->nub_info.size, '\0');
4050       append_hex_value(ostrm, zeros.data(), zeros.size(), false);
4051     }
4052   } else {
4053     register_value_in_hex_fixed_width(ostrm, pid, tid, reg_entry, NULL);
4054   }
4055   return SendPacket(ostrm.str());
4056 }
4057 
4058 /* 'Pnn=rrrrr'
4059  Set register number n to value r.
4060  n and r are hex strings.  */
4061 
4062 rnb_err_t RNBRemote::HandlePacket_P(const char *p) {
4063   if (g_num_reg_entries == 0)
4064     InitializeRegisters();
4065 
4066   if (p == NULL || *p == '\0') {
4067     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, "Empty P packet");
4068   }
4069   if (!m_ctx.HasValidProcessID()) {
4070     return SendPacket("E28");
4071   }
4072 
4073   nub_process_t pid = m_ctx.ProcessID();
4074 
4075   StdStringExtractor packet(p);
4076 
4077   const char cmd_char = packet.GetChar();
4078   // Register ID is always in big endian
4079   const uint32_t reg = packet.GetHexMaxU32(false, UINT32_MAX);
4080   const char equal_char = packet.GetChar();
4081 
4082   if (cmd_char != 'P')
4083     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4084                                   "Improperly formed P packet");
4085 
4086   if (reg == UINT32_MAX)
4087     return SendPacket("E29");
4088 
4089   if (equal_char != '=')
4090     return SendPacket("E30");
4091 
4092   const register_map_entry_t *reg_entry;
4093 
4094   if (reg >= g_num_reg_entries)
4095     return SendPacket("E47");
4096 
4097   reg_entry = &g_reg_entries[reg];
4098 
4099   if (reg_entry->nub_info.set == (uint32_t)-1 &&
4100       reg_entry->nub_info.reg == (uint32_t)-1) {
4101     DNBLogError(
4102         "RNBRemote::HandlePacket_P(%s): unknown register number %u requested\n",
4103         p, reg);
4104     return SendPacket("E48");
4105   }
4106 
4107   DNBRegisterValue reg_value;
4108   reg_value.info = reg_entry->nub_info;
4109   packet.GetHexBytes(reg_value.value.v_sint8, reg_entry->nub_info.size, 0xcc);
4110 
4111   nub_thread_t tid = ExtractThreadIDFromThreadSuffix(p);
4112   if (tid == INVALID_NUB_THREAD)
4113     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4114                                   "No thread specified in p packet");
4115 
4116   if (!DNBThreadSetRegisterValueByID(pid, tid, reg_entry->nub_info.set,
4117                                      reg_entry->nub_info.reg, &reg_value)) {
4118     return SendPacket("E32");
4119   }
4120   return SendPacket("OK");
4121 }
4122 
4123 /* 'c [addr]'
4124  Continue, optionally from a specified address. */
4125 
4126 rnb_err_t RNBRemote::HandlePacket_c(const char *p) {
4127   const nub_process_t pid = m_ctx.ProcessID();
4128 
4129   if (pid == INVALID_NUB_PROCESS)
4130     return SendPacket("E23");
4131 
4132   DNBThreadResumeAction action = {INVALID_NUB_THREAD, eStateRunning, 0,
4133                                   INVALID_NUB_ADDRESS};
4134 
4135   if (*(p + 1) != '\0') {
4136     action.tid = GetContinueThread();
4137     errno = 0;
4138     action.addr = strtoull(p + 1, NULL, 16);
4139     if (errno != 0 && action.addr == 0)
4140       return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4141                                     "Could not parse address in c packet");
4142   }
4143 
4144   DNBThreadResumeActions thread_actions;
4145   thread_actions.Append(action);
4146   thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, 0);
4147   if (!DNBProcessResume(pid, thread_actions.GetFirst(),
4148                         thread_actions.GetSize()))
4149     return SendPacket("E25");
4150   // Don't send an "OK" packet; response is the stopped/exited message.
4151   return rnb_success;
4152 }
4153 
4154 rnb_err_t RNBRemote::HandlePacket_MemoryRegionInfo(const char *p) {
4155   /* This packet will find memory attributes (e.g. readable, writable,
4156      executable, stack, jitted code)
4157      for the memory region containing a given address and return that
4158      information.
4159 
4160      Users of this packet must be prepared for three results:
4161 
4162          Region information is returned
4163          Region information is unavailable for this address because the address
4164      is in unmapped memory
4165          Region lookup cannot be performed on this platform or process is not
4166      yet launched
4167          This packet isn't implemented
4168 
4169      Examples of use:
4170         qMemoryRegionInfo:3a55140
4171         start:3a50000,size:100000,permissions:rwx
4172 
4173         qMemoryRegionInfo:0
4174         error:address in unmapped region
4175 
4176         qMemoryRegionInfo:3a551140   (on a different platform)
4177         error:region lookup cannot be performed
4178 
4179         qMemoryRegionInfo
4180         OK                   // this packet is implemented by the remote nub
4181   */
4182 
4183   p += sizeof("qMemoryRegionInfo") - 1;
4184   if (*p == '\0')
4185     return SendPacket("OK");
4186   if (*p++ != ':')
4187     return SendPacket("E67");
4188   if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X'))
4189     p += 2;
4190 
4191   errno = 0;
4192   uint64_t address = strtoul(p, NULL, 16);
4193   if (errno != 0 && address == 0) {
4194     return HandlePacket_ILLFORMED(
4195         __FILE__, __LINE__, p, "Invalid address in qMemoryRegionInfo packet");
4196   }
4197 
4198   DNBRegionInfo region_info = {0, 0, 0};
4199   DNBProcessMemoryRegionInfo(m_ctx.ProcessID(), address, &region_info);
4200   std::ostringstream ostrm;
4201 
4202   // start:3a50000,size:100000,permissions:rwx
4203   ostrm << "start:" << std::hex << region_info.addr << ';';
4204 
4205   if (region_info.size > 0)
4206     ostrm << "size:" << std::hex << region_info.size << ';';
4207 
4208   if (region_info.permissions) {
4209     ostrm << "permissions:";
4210 
4211     if (region_info.permissions & eMemoryPermissionsReadable)
4212       ostrm << 'r';
4213     if (region_info.permissions & eMemoryPermissionsWritable)
4214       ostrm << 'w';
4215     if (region_info.permissions & eMemoryPermissionsExecutable)
4216       ostrm << 'x';
4217     ostrm << ';';
4218   }
4219   return SendPacket(ostrm.str());
4220 }
4221 
4222 // qGetProfileData;scan_type:0xYYYYYYY
4223 rnb_err_t RNBRemote::HandlePacket_GetProfileData(const char *p) {
4224   nub_process_t pid = m_ctx.ProcessID();
4225   if (pid == INVALID_NUB_PROCESS)
4226     return SendPacket("OK");
4227 
4228   StdStringExtractor packet(p += sizeof("qGetProfileData"));
4229   DNBProfileDataScanType scan_type = eProfileAll;
4230   std::string name;
4231   std::string value;
4232   while (packet.GetNameColonValue(name, value)) {
4233     if (name.compare("scan_type") == 0) {
4234       std::istringstream iss(value);
4235       uint32_t int_value = 0;
4236       if (iss >> std::hex >> int_value) {
4237         scan_type = (DNBProfileDataScanType)int_value;
4238       }
4239     }
4240   }
4241 
4242   std::string data = DNBProcessGetProfileData(pid, scan_type);
4243   if (!data.empty()) {
4244     return SendPacket(data.c_str());
4245   } else {
4246     return SendPacket("OK");
4247   }
4248 }
4249 
4250 // QSetEnableAsyncProfiling;enable:[0|1]:interval_usec:XXXXXX;scan_type:0xYYYYYYY
4251 rnb_err_t RNBRemote::HandlePacket_SetEnableAsyncProfiling(const char *p) {
4252   nub_process_t pid = m_ctx.ProcessID();
4253   if (pid == INVALID_NUB_PROCESS)
4254     return SendPacket("OK");
4255 
4256   StdStringExtractor packet(p += sizeof("QSetEnableAsyncProfiling"));
4257   bool enable = false;
4258   uint64_t interval_usec = 0;
4259   DNBProfileDataScanType scan_type = eProfileAll;
4260   std::string name;
4261   std::string value;
4262   while (packet.GetNameColonValue(name, value)) {
4263     if (name.compare("enable") == 0) {
4264       enable = strtoul(value.c_str(), NULL, 10) > 0;
4265     } else if (name.compare("interval_usec") == 0) {
4266       interval_usec = strtoul(value.c_str(), NULL, 10);
4267     } else if (name.compare("scan_type") == 0) {
4268       std::istringstream iss(value);
4269       uint32_t int_value = 0;
4270       if (iss >> std::hex >> int_value) {
4271         scan_type = (DNBProfileDataScanType)int_value;
4272       }
4273     }
4274   }
4275 
4276   if (interval_usec == 0) {
4277     enable = 0;
4278   }
4279 
4280   DNBProcessSetEnableAsyncProfiling(pid, enable, interval_usec, scan_type);
4281   return SendPacket("OK");
4282 }
4283 
4284 // QEnableCompression:type:<COMPRESSION-TYPE>;minsize:<MINIMUM PACKET SIZE TO
4285 // COMPRESS>;
4286 //
4287 // type: must be a type previously reported by the qXfer:features:
4288 // SupportedCompressions list
4289 //
4290 // minsize: is optional; by default the qXfer:features:
4291 // DefaultCompressionMinSize value is used
4292 // debugserver may have a better idea of what a good minimum packet size to
4293 // compress is than lldb.
4294 
4295 rnb_err_t RNBRemote::HandlePacket_QEnableCompression(const char *p) {
4296   p += sizeof("QEnableCompression:") - 1;
4297 
4298   size_t new_compression_minsize = m_compression_minsize;
4299   const char *new_compression_minsize_str = strstr(p, "minsize:");
4300   if (new_compression_minsize_str) {
4301     new_compression_minsize_str += strlen("minsize:");
4302     errno = 0;
4303     new_compression_minsize = strtoul(new_compression_minsize_str, NULL, 10);
4304     if (errno != 0 || new_compression_minsize == ULONG_MAX) {
4305       new_compression_minsize = m_compression_minsize;
4306     }
4307   }
4308 
4309 #if defined(HAVE_LIBCOMPRESSION)
4310   if (compression_decode_buffer != NULL) {
4311     if (strstr(p, "type:zlib-deflate;") != nullptr) {
4312       EnableCompressionNextSendPacket(compression_types::zlib_deflate);
4313       m_compression_minsize = new_compression_minsize;
4314       return SendPacket("OK");
4315     } else if (strstr(p, "type:lz4;") != nullptr) {
4316       EnableCompressionNextSendPacket(compression_types::lz4);
4317       m_compression_minsize = new_compression_minsize;
4318       return SendPacket("OK");
4319     } else if (strstr(p, "type:lzma;") != nullptr) {
4320       EnableCompressionNextSendPacket(compression_types::lzma);
4321       m_compression_minsize = new_compression_minsize;
4322       return SendPacket("OK");
4323     } else if (strstr(p, "type:lzfse;") != nullptr) {
4324       EnableCompressionNextSendPacket(compression_types::lzfse);
4325       m_compression_minsize = new_compression_minsize;
4326       return SendPacket("OK");
4327     }
4328   }
4329 #endif
4330 
4331 #if defined(HAVE_LIBZ)
4332   if (strstr(p, "type:zlib-deflate;") != nullptr) {
4333     EnableCompressionNextSendPacket(compression_types::zlib_deflate);
4334     m_compression_minsize = new_compression_minsize;
4335     return SendPacket("OK");
4336   }
4337 #endif
4338 
4339   return SendPacket("E88");
4340 }
4341 
4342 rnb_err_t RNBRemote::HandlePacket_qSpeedTest(const char *p) {
4343   p += strlen("qSpeedTest:response_size:");
4344   char *end = NULL;
4345   errno = 0;
4346   uint64_t response_size = ::strtoul(p, &end, 16);
4347   if (errno != 0)
4348     return HandlePacket_ILLFORMED(
4349         __FILE__, __LINE__, p,
4350         "Didn't find response_size value at right offset");
4351   else if (*end == ';') {
4352     static char g_data[4 * 1024 * 1024 + 16] = "data:";
4353     memset(g_data + 5, 'a', response_size);
4354     g_data[response_size + 5] = '\0';
4355     return SendPacket(g_data);
4356   } else {
4357     return SendPacket("E79");
4358   }
4359 }
4360 
4361 rnb_err_t RNBRemote::HandlePacket_WatchpointSupportInfo(const char *p) {
4362   /* This packet simply returns the number of supported hardware watchpoints.
4363 
4364      Examples of use:
4365         qWatchpointSupportInfo:
4366         num:4
4367 
4368         qWatchpointSupportInfo
4369         OK                   // this packet is implemented by the remote nub
4370   */
4371 
4372   p += sizeof("qWatchpointSupportInfo") - 1;
4373   if (*p == '\0')
4374     return SendPacket("OK");
4375   if (*p++ != ':')
4376     return SendPacket("E67");
4377 
4378   errno = 0;
4379   uint32_t num = DNBWatchpointGetNumSupportedHWP(m_ctx.ProcessID());
4380   std::ostringstream ostrm;
4381 
4382   // size:4
4383   ostrm << "num:" << std::dec << num << ';';
4384   return SendPacket(ostrm.str());
4385 }
4386 
4387 /* 'C sig [;addr]'
4388  Resume with signal sig, optionally at address addr.  */
4389 
4390 rnb_err_t RNBRemote::HandlePacket_C(const char *p) {
4391   const nub_process_t pid = m_ctx.ProcessID();
4392 
4393   if (pid == INVALID_NUB_PROCESS)
4394     return SendPacket("E36");
4395 
4396   DNBThreadResumeAction action = {INVALID_NUB_THREAD, eStateRunning, 0,
4397                                   INVALID_NUB_ADDRESS};
4398   int process_signo = -1;
4399   if (*(p + 1) != '\0') {
4400     action.tid = GetContinueThread();
4401     char *end = NULL;
4402     errno = 0;
4403     process_signo = static_cast<int>(strtoul(p + 1, &end, 16));
4404     if (errno != 0)
4405       return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4406                                     "Could not parse signal in C packet");
4407     else if (*end == ';') {
4408       errno = 0;
4409       action.addr = strtoull(end + 1, NULL, 16);
4410       if (errno != 0 && action.addr == 0)
4411         return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4412                                       "Could not parse address in C packet");
4413     }
4414   }
4415 
4416   DNBThreadResumeActions thread_actions;
4417   thread_actions.Append(action);
4418   thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, action.signal);
4419   if (!DNBProcessSignal(pid, process_signo))
4420     return SendPacket("E52");
4421   if (!DNBProcessResume(pid, thread_actions.GetFirst(),
4422                         thread_actions.GetSize()))
4423     return SendPacket("E38");
4424   /* Don't send an "OK" packet; response is the stopped/exited message.  */
4425   return rnb_success;
4426 }
4427 
4428 //----------------------------------------------------------------------
4429 // 'D' packet
4430 // Detach from gdb.
4431 //----------------------------------------------------------------------
4432 rnb_err_t RNBRemote::HandlePacket_D(const char *p) {
4433   if (m_ctx.HasValidProcessID()) {
4434     if (DNBProcessDetach(m_ctx.ProcessID()))
4435       SendPacket("OK");
4436     else
4437       SendPacket("E");
4438   } else {
4439     SendPacket("E");
4440   }
4441   return rnb_success;
4442 }
4443 
4444 /* 'k'
4445  Kill the inferior process.  */
4446 
4447 rnb_err_t RNBRemote::HandlePacket_k(const char *p) {
4448   DNBLog("Got a 'k' packet, killing the inferior process.");
4449   // No response to should be sent to the kill packet
4450   if (m_ctx.HasValidProcessID())
4451     DNBProcessKill(m_ctx.ProcessID());
4452   SendPacket("X09");
4453   return rnb_success;
4454 }
4455 
4456 rnb_err_t RNBRemote::HandlePacket_stop_process(const char *p) {
4457 //#define TEST_EXIT_ON_INTERRUPT // This should only be uncommented to test
4458 //exiting on interrupt
4459 #if defined(TEST_EXIT_ON_INTERRUPT)
4460   rnb_err_t err = HandlePacket_k(p);
4461   m_comm.Disconnect(true);
4462   return err;
4463 #else
4464   if (!DNBProcessInterrupt(m_ctx.ProcessID())) {
4465     // If we failed to interrupt the process, then send a stop
4466     // reply packet as the process was probably already stopped
4467     DNBLogThreaded("RNBRemote::HandlePacket_stop_process() sending extra stop "
4468                    "reply because DNBProcessInterrupt returned false");
4469     HandlePacket_last_signal(NULL);
4470   }
4471   return rnb_success;
4472 #endif
4473 }
4474 
4475 /* 's'
4476  Step the inferior process.  */
4477 
4478 rnb_err_t RNBRemote::HandlePacket_s(const char *p) {
4479   const nub_process_t pid = m_ctx.ProcessID();
4480   if (pid == INVALID_NUB_PROCESS)
4481     return SendPacket("E32");
4482 
4483   // Hardware supported stepping not supported on arm
4484   nub_thread_t tid = GetContinueThread();
4485   if (tid == 0 || tid == (nub_thread_t)-1)
4486     tid = GetCurrentThread();
4487 
4488   if (tid == INVALID_NUB_THREAD)
4489     return SendPacket("E33");
4490 
4491   DNBThreadResumeActions thread_actions;
4492   thread_actions.AppendAction(tid, eStateStepping);
4493 
4494   // Make all other threads stop when we are stepping
4495   thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
4496   if (!DNBProcessResume(pid, thread_actions.GetFirst(),
4497                         thread_actions.GetSize()))
4498     return SendPacket("E49");
4499   // Don't send an "OK" packet; response is the stopped/exited message.
4500   return rnb_success;
4501 }
4502 
4503 /* 'S sig [;addr]'
4504  Step with signal sig, optionally at address addr.  */
4505 
4506 rnb_err_t RNBRemote::HandlePacket_S(const char *p) {
4507   const nub_process_t pid = m_ctx.ProcessID();
4508   if (pid == INVALID_NUB_PROCESS)
4509     return SendPacket("E36");
4510 
4511   DNBThreadResumeAction action = {INVALID_NUB_THREAD, eStateStepping, 0,
4512                                   INVALID_NUB_ADDRESS};
4513 
4514   if (*(p + 1) != '\0') {
4515     char *end = NULL;
4516     errno = 0;
4517     action.signal = static_cast<int>(strtoul(p + 1, &end, 16));
4518     if (errno != 0)
4519       return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4520                                     "Could not parse signal in S packet");
4521     else if (*end == ';') {
4522       errno = 0;
4523       action.addr = strtoull(end + 1, NULL, 16);
4524       if (errno != 0 && action.addr == 0) {
4525         return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4526                                       "Could not parse address in S packet");
4527       }
4528     }
4529   }
4530 
4531   action.tid = GetContinueThread();
4532   if (action.tid == 0 || action.tid == (nub_thread_t)-1)
4533     return SendPacket("E40");
4534 
4535   nub_state_t tstate = DNBThreadGetState(pid, action.tid);
4536   if (tstate == eStateInvalid || tstate == eStateExited)
4537     return SendPacket("E37");
4538 
4539   DNBThreadResumeActions thread_actions;
4540   thread_actions.Append(action);
4541 
4542   // Make all other threads stop when we are stepping
4543   thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
4544   if (!DNBProcessResume(pid, thread_actions.GetFirst(),
4545                         thread_actions.GetSize()))
4546     return SendPacket("E39");
4547 
4548   // Don't send an "OK" packet; response is the stopped/exited message.
4549   return rnb_success;
4550 }
4551 
4552 static const char *GetArchName(const uint32_t cputype,
4553                                const uint32_t cpusubtype) {
4554   switch (cputype) {
4555   case CPU_TYPE_ARM:
4556     switch (cpusubtype) {
4557     case 5:
4558       return "armv4";
4559     case 6:
4560       return "armv6";
4561     case 7:
4562       return "armv5t";
4563     case 8:
4564       return "xscale";
4565     case 9:
4566       return "armv7";
4567     case 10:
4568       return "armv7f";
4569     case 11:
4570       return "armv7s";
4571     case 12:
4572       return "armv7k";
4573     case 14:
4574       return "armv6m";
4575     case 15:
4576       return "armv7m";
4577     case 16:
4578       return "armv7em";
4579     default:
4580       return "arm";
4581     }
4582     break;
4583   case CPU_TYPE_ARM64:
4584     return "arm64";
4585   case CPU_TYPE_I386:
4586     return "i386";
4587   case CPU_TYPE_X86_64:
4588     switch (cpusubtype) {
4589     default:
4590       return "x86_64";
4591     case 8:
4592       return "x86_64h";
4593     }
4594     break;
4595   }
4596   return NULL;
4597 }
4598 
4599 static bool GetHostCPUType(uint32_t &cputype, uint32_t &cpusubtype,
4600                            uint32_t &is_64_bit_capable, bool &promoted_to_64) {
4601   static uint32_t g_host_cputype = 0;
4602   static uint32_t g_host_cpusubtype = 0;
4603   static uint32_t g_is_64_bit_capable = 0;
4604   static bool g_promoted_to_64 = false;
4605 
4606   if (g_host_cputype == 0) {
4607     g_promoted_to_64 = false;
4608     size_t len = sizeof(uint32_t);
4609     if (::sysctlbyname("hw.cputype", &g_host_cputype, &len, NULL, 0) == 0) {
4610       len = sizeof(uint32_t);
4611       if (::sysctlbyname("hw.cpu64bit_capable", &g_is_64_bit_capable, &len,
4612                          NULL, 0) == 0) {
4613         if (g_is_64_bit_capable && ((g_host_cputype & CPU_ARCH_ABI64) == 0)) {
4614           g_promoted_to_64 = true;
4615           g_host_cputype |= CPU_ARCH_ABI64;
4616         }
4617       }
4618     }
4619 
4620     len = sizeof(uint32_t);
4621     if (::sysctlbyname("hw.cpusubtype", &g_host_cpusubtype, &len, NULL, 0) ==
4622         0) {
4623       if (g_promoted_to_64 && g_host_cputype == CPU_TYPE_X86_64 &&
4624           g_host_cpusubtype == CPU_SUBTYPE_486)
4625         g_host_cpusubtype = CPU_SUBTYPE_X86_64_ALL;
4626     }
4627   }
4628 
4629   cputype = g_host_cputype;
4630   cpusubtype = g_host_cpusubtype;
4631   is_64_bit_capable = g_is_64_bit_capable;
4632   promoted_to_64 = g_promoted_to_64;
4633   return g_host_cputype != 0;
4634 }
4635 
4636 rnb_err_t RNBRemote::HandlePacket_qHostInfo(const char *p) {
4637   std::ostringstream strm;
4638 
4639   uint32_t cputype = 0;
4640   uint32_t cpusubtype = 0;
4641   uint32_t is_64_bit_capable = 0;
4642   bool promoted_to_64 = false;
4643   if (GetHostCPUType(cputype, cpusubtype, is_64_bit_capable, promoted_to_64)) {
4644     strm << "cputype:" << std::dec << cputype << ';';
4645     strm << "cpusubtype:" << std::dec << cpusubtype << ';';
4646   }
4647 
4648   // The OS in the triple should be "ios" or "macosx" which doesn't match our
4649   // "Darwin" which gets returned from "kern.ostype", so we need to hardcode
4650   // this for now.
4651   if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64) {
4652 #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
4653     strm << "ostype:tvos;";
4654 #elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
4655     strm << "ostype:watchos;";
4656 #else
4657     strm << "ostype:ios;";
4658 #endif
4659 
4660     // On armv7 we use "synchronous" watchpoints which means the exception is
4661     // delivered before the instruction executes.
4662     strm << "watchpoint_exceptions_received:before;";
4663   } else {
4664     strm << "ostype:macosx;";
4665     strm << "watchpoint_exceptions_received:after;";
4666   }
4667   //    char ostype[64];
4668   //    len = sizeof(ostype);
4669   //    if (::sysctlbyname("kern.ostype", &ostype, &len, NULL, 0) == 0)
4670   //    {
4671   //        len = strlen(ostype);
4672   //        std::transform (ostype, ostype + len, ostype, tolower);
4673   //        strm << "ostype:" << std::dec << ostype << ';';
4674   //    }
4675 
4676   strm << "vendor:apple;";
4677 
4678   uint64_t major, minor, patch;
4679   if (DNBGetOSVersionNumbers(&major, &minor, &patch)) {
4680     strm << "os_version:" << major << "." << minor;
4681     if (patch != UINT64_MAX)
4682       strm << "." << patch;
4683     strm << ";";
4684   }
4685 
4686 #if defined(__LITTLE_ENDIAN__)
4687   strm << "endian:little;";
4688 #elif defined(__BIG_ENDIAN__)
4689   strm << "endian:big;";
4690 #elif defined(__PDP_ENDIAN__)
4691   strm << "endian:pdp;";
4692 #endif
4693 
4694   if (promoted_to_64)
4695     strm << "ptrsize:8;";
4696   else
4697     strm << "ptrsize:" << std::dec << sizeof(void *) << ';';
4698 
4699 #if defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
4700   strm << "default_packet_timeout:10;";
4701 #endif
4702 
4703   return SendPacket(strm.str());
4704 }
4705 
4706 void XMLElementStart(std::ostringstream &s, uint32_t indent, const char *name,
4707                      bool has_attributes) {
4708   if (indent)
4709     s << INDENT_WITH_SPACES(indent);
4710   s << '<' << name;
4711   if (!has_attributes)
4712     s << '>' << std::endl;
4713 }
4714 
4715 void XMLElementStartEndAttributes(std::ostringstream &s, bool empty) {
4716   if (empty)
4717     s << '/';
4718   s << '>' << std::endl;
4719 }
4720 
4721 void XMLElementEnd(std::ostringstream &s, uint32_t indent, const char *name) {
4722   if (indent)
4723     s << INDENT_WITH_SPACES(indent);
4724   s << '<' << '/' << name << '>' << std::endl;
4725 }
4726 
4727 void XMLElementWithStringValue(std::ostringstream &s, uint32_t indent,
4728                                const char *name, const char *value,
4729                                bool close = true) {
4730   if (value) {
4731     if (indent)
4732       s << INDENT_WITH_SPACES(indent);
4733     s << '<' << name << '>' << value;
4734     if (close)
4735       XMLElementEnd(s, 0, name);
4736   }
4737 }
4738 
4739 void XMLElementWithUnsignedValue(std::ostringstream &s, uint32_t indent,
4740                                  const char *name, uint64_t value,
4741                                  bool close = true) {
4742   if (indent)
4743     s << INDENT_WITH_SPACES(indent);
4744 
4745   s << '<' << name << '>' << DECIMAL << value;
4746   if (close)
4747     XMLElementEnd(s, 0, name);
4748 }
4749 
4750 void XMLAttributeString(std::ostringstream &s, const char *name,
4751                         const char *value, const char *default_value = NULL) {
4752   if (value) {
4753     if (default_value && strcmp(value, default_value) == 0)
4754       return; // No need to emit the attribute because it matches the default
4755               // value
4756     s << ' ' << name << "=\"" << value << "\"";
4757   }
4758 }
4759 
4760 void XMLAttributeUnsignedDecimal(std::ostringstream &s, const char *name,
4761                                  uint64_t value) {
4762   s << ' ' << name << "=\"" << DECIMAL << value << "\"";
4763 }
4764 
4765 void GenerateTargetXMLRegister(std::ostringstream &s, const uint32_t reg_num,
4766                                nub_size_t num_reg_sets,
4767                                const DNBRegisterSetInfo *reg_set_info,
4768                                const register_map_entry_t &reg) {
4769   const char *default_lldb_encoding = "uint";
4770   const char *lldb_encoding = default_lldb_encoding;
4771   const char *gdb_group = "general";
4772   const char *default_gdb_type = "int";
4773   const char *gdb_type = default_gdb_type;
4774   const char *default_lldb_format = "hex";
4775   const char *lldb_format = default_lldb_format;
4776   const char *lldb_set = NULL;
4777 
4778   switch (reg.nub_info.type) {
4779   case Uint:
4780     lldb_encoding = "uint";
4781     break;
4782   case Sint:
4783     lldb_encoding = "sint";
4784     break;
4785   case IEEE754:
4786     lldb_encoding = "ieee754";
4787     if (reg.nub_info.set > 0)
4788       gdb_group = "float";
4789     break;
4790   case Vector:
4791     lldb_encoding = "vector";
4792     if (reg.nub_info.set > 0)
4793       gdb_group = "vector";
4794     break;
4795   }
4796 
4797   switch (reg.nub_info.format) {
4798   case Binary:
4799     lldb_format = "binary";
4800     break;
4801   case Decimal:
4802     lldb_format = "decimal";
4803     break;
4804   case Hex:
4805     lldb_format = "hex";
4806     break;
4807   case Float:
4808     gdb_type = "float";
4809     lldb_format = "float";
4810     break;
4811   case VectorOfSInt8:
4812     gdb_type = "float";
4813     lldb_format = "vector-sint8";
4814     break;
4815   case VectorOfUInt8:
4816     gdb_type = "float";
4817     lldb_format = "vector-uint8";
4818     break;
4819   case VectorOfSInt16:
4820     gdb_type = "float";
4821     lldb_format = "vector-sint16";
4822     break;
4823   case VectorOfUInt16:
4824     gdb_type = "float";
4825     lldb_format = "vector-uint16";
4826     break;
4827   case VectorOfSInt32:
4828     gdb_type = "float";
4829     lldb_format = "vector-sint32";
4830     break;
4831   case VectorOfUInt32:
4832     gdb_type = "float";
4833     lldb_format = "vector-uint32";
4834     break;
4835   case VectorOfFloat32:
4836     gdb_type = "float";
4837     lldb_format = "vector-float32";
4838     break;
4839   case VectorOfUInt128:
4840     gdb_type = "float";
4841     lldb_format = "vector-uint128";
4842     break;
4843   };
4844   if (reg_set_info && reg.nub_info.set < num_reg_sets)
4845     lldb_set = reg_set_info[reg.nub_info.set].name;
4846 
4847   uint32_t indent = 2;
4848 
4849   XMLElementStart(s, indent, "reg", true);
4850   XMLAttributeString(s, "name", reg.nub_info.name);
4851   XMLAttributeUnsignedDecimal(s, "regnum", reg_num);
4852   XMLAttributeUnsignedDecimal(s, "offset", reg.offset);
4853   XMLAttributeUnsignedDecimal(s, "bitsize", reg.nub_info.size * 8);
4854   XMLAttributeString(s, "group", gdb_group);
4855   XMLAttributeString(s, "type", gdb_type, default_gdb_type);
4856   XMLAttributeString(s, "altname", reg.nub_info.alt);
4857   XMLAttributeString(s, "encoding", lldb_encoding, default_lldb_encoding);
4858   XMLAttributeString(s, "format", lldb_format, default_lldb_format);
4859   XMLAttributeUnsignedDecimal(s, "group_id", reg.nub_info.set);
4860   if (reg.nub_info.reg_ehframe != INVALID_NUB_REGNUM)
4861     XMLAttributeUnsignedDecimal(s, "ehframe_regnum", reg.nub_info.reg_ehframe);
4862   if (reg.nub_info.reg_dwarf != INVALID_NUB_REGNUM)
4863     XMLAttributeUnsignedDecimal(s, "dwarf_regnum", reg.nub_info.reg_dwarf);
4864 
4865   const char *lldb_generic = NULL;
4866   switch (reg.nub_info.reg_generic) {
4867   case GENERIC_REGNUM_FP:
4868     lldb_generic = "fp";
4869     break;
4870   case GENERIC_REGNUM_PC:
4871     lldb_generic = "pc";
4872     break;
4873   case GENERIC_REGNUM_SP:
4874     lldb_generic = "sp";
4875     break;
4876   case GENERIC_REGNUM_RA:
4877     lldb_generic = "ra";
4878     break;
4879   case GENERIC_REGNUM_FLAGS:
4880     lldb_generic = "flags";
4881     break;
4882   case GENERIC_REGNUM_ARG1:
4883     lldb_generic = "arg1";
4884     break;
4885   case GENERIC_REGNUM_ARG2:
4886     lldb_generic = "arg2";
4887     break;
4888   case GENERIC_REGNUM_ARG3:
4889     lldb_generic = "arg3";
4890     break;
4891   case GENERIC_REGNUM_ARG4:
4892     lldb_generic = "arg4";
4893     break;
4894   case GENERIC_REGNUM_ARG5:
4895     lldb_generic = "arg5";
4896     break;
4897   case GENERIC_REGNUM_ARG6:
4898     lldb_generic = "arg6";
4899     break;
4900   case GENERIC_REGNUM_ARG7:
4901     lldb_generic = "arg7";
4902     break;
4903   case GENERIC_REGNUM_ARG8:
4904     lldb_generic = "arg8";
4905     break;
4906   default:
4907     break;
4908   }
4909   XMLAttributeString(s, "generic", lldb_generic);
4910 
4911   bool empty = reg.value_regnums.empty() && reg.invalidate_regnums.empty();
4912   if (!empty) {
4913     if (!reg.value_regnums.empty()) {
4914       std::ostringstream regnums;
4915       bool first = true;
4916       regnums << DECIMAL;
4917       for (auto regnum : reg.value_regnums) {
4918         if (!first)
4919           regnums << ',';
4920         regnums << regnum;
4921         first = false;
4922       }
4923       XMLAttributeString(s, "value_regnums", regnums.str().c_str());
4924     }
4925 
4926     if (!reg.invalidate_regnums.empty()) {
4927       std::ostringstream regnums;
4928       bool first = true;
4929       regnums << DECIMAL;
4930       for (auto regnum : reg.invalidate_regnums) {
4931         if (!first)
4932           regnums << ',';
4933         regnums << regnum;
4934         first = false;
4935       }
4936       XMLAttributeString(s, "invalidate_regnums", regnums.str().c_str());
4937     }
4938   }
4939   XMLElementStartEndAttributes(s, true);
4940 }
4941 
4942 void GenerateTargetXMLRegisters(std::ostringstream &s) {
4943   nub_size_t num_reg_sets = 0;
4944   const DNBRegisterSetInfo *reg_sets = DNBGetRegisterSetInfo(&num_reg_sets);
4945 
4946   uint32_t cputype = DNBGetRegisterCPUType();
4947   if (cputype) {
4948     XMLElementStart(s, 0, "feature", true);
4949     std::ostringstream name_strm;
4950     name_strm << "com.apple.debugserver." << GetArchName(cputype, 0);
4951     XMLAttributeString(s, "name", name_strm.str().c_str());
4952     XMLElementStartEndAttributes(s, false);
4953     for (uint32_t reg_num = 0; reg_num < g_num_reg_entries; ++reg_num)
4954     //        for (const auto &reg: g_dynamic_register_map)
4955     {
4956       GenerateTargetXMLRegister(s, reg_num, num_reg_sets, reg_sets,
4957                                 g_reg_entries[reg_num]);
4958     }
4959     XMLElementEnd(s, 0, "feature");
4960 
4961     if (num_reg_sets > 0) {
4962       XMLElementStart(s, 0, "groups", false);
4963       for (uint32_t set = 1; set < num_reg_sets; ++set) {
4964         XMLElementStart(s, 2, "group", true);
4965         XMLAttributeUnsignedDecimal(s, "id", set);
4966         XMLAttributeString(s, "name", reg_sets[set].name);
4967         XMLElementStartEndAttributes(s, true);
4968       }
4969       XMLElementEnd(s, 0, "groups");
4970     }
4971   }
4972 }
4973 
4974 static const char *g_target_xml_header = R"(<?xml version="1.0"?>
4975 <target version="1.0">)";
4976 
4977 static const char *g_target_xml_footer = "</target>";
4978 
4979 static std::string g_target_xml;
4980 
4981 void UpdateTargetXML() {
4982   std::ostringstream s;
4983   s << g_target_xml_header << std::endl;
4984 
4985   // Set the architecture
4986   // s << "<architecture>" << arch "</architecture>" << std::endl;
4987 
4988   // Set the OSABI
4989   // s << "<osabi>abi-name</osabi>"
4990 
4991   GenerateTargetXMLRegisters(s);
4992 
4993   s << g_target_xml_footer << std::endl;
4994 
4995   // Save the XML output in case it gets retrieved in chunks
4996   g_target_xml = s.str();
4997 }
4998 
4999 rnb_err_t RNBRemote::HandlePacket_qXfer(const char *command) {
5000   const char *p = command;
5001   p += strlen("qXfer:");
5002   const char *sep = strchr(p, ':');
5003   if (sep) {
5004     std::string object(p, sep - p); // "auxv", "backtrace", "features", etc
5005     p = sep + 1;
5006     sep = strchr(p, ':');
5007     if (sep) {
5008       std::string rw(p, sep - p); // "read" or "write"
5009       p = sep + 1;
5010       sep = strchr(p, ':');
5011       if (sep) {
5012         std::string annex(p, sep - p); // "read" or "write"
5013 
5014         p = sep + 1;
5015         sep = strchr(p, ',');
5016         if (sep) {
5017           std::string offset_str(p, sep - p); // read the length as a string
5018           p = sep + 1;
5019           std::string length_str(p); // read the offset as a string
5020           char *end = nullptr;
5021           const uint64_t offset = strtoul(offset_str.c_str(), &end,
5022                                           16); // convert offset_str to a offset
5023           if (*end == '\0') {
5024             const uint64_t length = strtoul(
5025                 length_str.c_str(), &end, 16); // convert length_str to a length
5026             if (*end == '\0') {
5027               if (object == "features" && rw == "read" &&
5028                   annex == "target.xml") {
5029                 std::ostringstream xml_out;
5030 
5031                 if (offset == 0) {
5032                   InitializeRegisters(true);
5033 
5034                   UpdateTargetXML();
5035                   if (g_target_xml.empty())
5036                     return SendPacket("E83");
5037 
5038                   if (length > g_target_xml.size()) {
5039                     xml_out << 'l'; // No more data
5040                     xml_out << binary_encode_string(g_target_xml);
5041                   } else {
5042                     xml_out << 'm'; // More data needs to be read with a
5043                                     // subsequent call
5044                     xml_out << binary_encode_string(
5045                         std::string(g_target_xml, offset, length));
5046                   }
5047                 } else {
5048                   // Retrieving target XML in chunks
5049                   if (offset < g_target_xml.size()) {
5050                     std::string chunk(g_target_xml, offset, length);
5051                     if (chunk.size() < length)
5052                       xml_out << 'l'; // No more data
5053                     else
5054                       xml_out << 'm'; // More data needs to be read with a
5055                                       // subsequent call
5056                     xml_out << binary_encode_string(chunk.data());
5057                   }
5058                 }
5059                 return SendPacket(xml_out.str());
5060               }
5061               // Well formed, put not supported
5062               return HandlePacket_UNIMPLEMENTED(command);
5063             }
5064           }
5065         }
5066       } else {
5067         SendPacket("E85");
5068       }
5069     } else {
5070       SendPacket("E86");
5071     }
5072   }
5073   return SendPacket("E82");
5074 }
5075 
5076 rnb_err_t RNBRemote::HandlePacket_qGDBServerVersion(const char *p) {
5077   std::ostringstream strm;
5078 
5079 #if defined(DEBUGSERVER_PROGRAM_NAME)
5080   strm << "name:" DEBUGSERVER_PROGRAM_NAME ";";
5081 #else
5082   strm << "name:debugserver;";
5083 #endif
5084   strm << "version:" << DEBUGSERVER_VERSION_NUM << ";";
5085 
5086   return SendPacket(strm.str());
5087 }
5088 
5089 // A helper function that retrieves a single integer value from
5090 // a one-level-deep JSON dictionary of key-value pairs.  e.g.
5091 // jThreadExtendedInfo:{"plo_pthread_tsd_base_address_offset":0,"plo_pthread_tsd_base_offset":224,"plo_pthread_tsd_entry_size":8,"thread":144305}]
5092 //
5093 uint64_t get_integer_value_for_key_name_from_json(const char *key,
5094                                                   const char *json_string) {
5095   uint64_t retval = INVALID_NUB_ADDRESS;
5096   std::string key_with_quotes = "\"";
5097   key_with_quotes += key;
5098   key_with_quotes += "\"";
5099   const char *c = strstr(json_string, key_with_quotes.c_str());
5100   if (c) {
5101     c += key_with_quotes.size();
5102 
5103     while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5104       c++;
5105 
5106     if (*c == ':') {
5107       c++;
5108 
5109       while (*c != '\0' &&
5110              (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5111         c++;
5112 
5113       errno = 0;
5114       retval = strtoul(c, NULL, 10);
5115       if (errno != 0) {
5116         retval = INVALID_NUB_ADDRESS;
5117       }
5118     }
5119   }
5120   return retval;
5121 }
5122 
5123 // A helper function that retrieves a boolean value from
5124 // a one-level-deep JSON dictionary of key-value pairs.  e.g.
5125 // jGetLoadedDynamicLibrariesInfos:{"fetch_all_solibs":true}]
5126 
5127 // Returns true if it was able to find the key name, and sets the 'value'
5128 // argument to the value found.
5129 
5130 bool get_boolean_value_for_key_name_from_json(const char *key,
5131                                               const char *json_string,
5132                                               bool &value) {
5133   std::string key_with_quotes = "\"";
5134   key_with_quotes += key;
5135   key_with_quotes += "\"";
5136   const char *c = strstr(json_string, key_with_quotes.c_str());
5137   if (c) {
5138     c += key_with_quotes.size();
5139 
5140     while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5141       c++;
5142 
5143     if (*c == ':') {
5144       c++;
5145 
5146       while (*c != '\0' &&
5147              (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5148         c++;
5149 
5150       if (strncmp(c, "true", 4) == 0) {
5151         value = true;
5152         return true;
5153       } else if (strncmp(c, "false", 5) == 0) {
5154         value = false;
5155         return true;
5156       }
5157     }
5158   }
5159   return false;
5160 }
5161 
5162 // A helper function that reads an array of uint64_t's from
5163 // a one-level-deep JSON dictionary of key-value pairs.  e.g.
5164 // jGetLoadedDynamicLibrariesInfos:{"solib_addrs":[31345823,7768020384,7310483024]}]
5165 
5166 // Returns true if it was able to find the key name, false if it did not.
5167 // "ints" will have all integers found in the array appended to it.
5168 
5169 bool get_array_of_ints_value_for_key_name_from_json(
5170     const char *key, const char *json_string, std::vector<uint64_t> &ints) {
5171   std::string key_with_quotes = "\"";
5172   key_with_quotes += key;
5173   key_with_quotes += "\"";
5174   const char *c = strstr(json_string, key_with_quotes.c_str());
5175   if (c) {
5176     c += key_with_quotes.size();
5177 
5178     while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5179       c++;
5180 
5181     if (*c == ':') {
5182       c++;
5183 
5184       while (*c != '\0' &&
5185              (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5186         c++;
5187 
5188       if (*c == '[') {
5189         c++;
5190         while (*c != '\0' &&
5191                (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5192           c++;
5193         while (1) {
5194           if (!isdigit(*c)) {
5195             return true;
5196           }
5197 
5198           errno = 0;
5199           char *endptr;
5200           uint64_t value = strtoul(c, &endptr, 10);
5201           if (errno == 0) {
5202             ints.push_back(value);
5203           } else {
5204             break;
5205           }
5206           if (endptr == c || endptr == nullptr || *endptr == '\0') {
5207             break;
5208           }
5209           c = endptr;
5210 
5211           while (*c != '\0' &&
5212                  (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5213             c++;
5214           if (*c == ',')
5215             c++;
5216           while (*c != '\0' &&
5217                  (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5218             c++;
5219           if (*c == ']') {
5220             return true;
5221           }
5222         }
5223       }
5224     }
5225   }
5226   return false;
5227 }
5228 
5229 JSONGenerator::ObjectSP
5230 RNBRemote::GetJSONThreadsInfo(bool threads_with_valid_stop_info_only) {
5231   JSONGenerator::ArraySP threads_array_sp;
5232   if (m_ctx.HasValidProcessID()) {
5233     threads_array_sp.reset(new JSONGenerator::Array());
5234 
5235     nub_process_t pid = m_ctx.ProcessID();
5236 
5237     nub_size_t numthreads = DNBProcessGetNumThreads(pid);
5238     for (nub_size_t i = 0; i < numthreads; ++i) {
5239       nub_thread_t tid = DNBProcessGetThreadAtIndex(pid, i);
5240 
5241       struct DNBThreadStopInfo tid_stop_info;
5242 
5243       const bool stop_info_valid =
5244           DNBThreadGetStopReason(pid, tid, &tid_stop_info);
5245 
5246       // If we are doing stop info only, then we only show threads that have a
5247       // valid stop reason
5248       if (threads_with_valid_stop_info_only) {
5249         if (!stop_info_valid || tid_stop_info.reason == eStopTypeInvalid)
5250           continue;
5251       }
5252 
5253       JSONGenerator::DictionarySP thread_dict_sp(
5254           new JSONGenerator::Dictionary());
5255       thread_dict_sp->AddIntegerItem("tid", tid);
5256 
5257       std::string reason_value("none");
5258 
5259       if (stop_info_valid) {
5260         switch (tid_stop_info.reason) {
5261         case eStopTypeInvalid:
5262           break;
5263 
5264         case eStopTypeSignal:
5265           if (tid_stop_info.details.signal.signo != 0) {
5266             thread_dict_sp->AddIntegerItem("signal",
5267                                            tid_stop_info.details.signal.signo);
5268             reason_value = "signal";
5269           }
5270           break;
5271 
5272         case eStopTypeException:
5273           if (tid_stop_info.details.exception.type != 0) {
5274             reason_value = "exception";
5275             thread_dict_sp->AddIntegerItem(
5276                 "metype", tid_stop_info.details.exception.type);
5277             JSONGenerator::ArraySP medata_array_sp(new JSONGenerator::Array());
5278             for (nub_size_t i = 0;
5279                  i < tid_stop_info.details.exception.data_count; ++i) {
5280               medata_array_sp->AddItem(
5281                   JSONGenerator::IntegerSP(new JSONGenerator::Integer(
5282                       tid_stop_info.details.exception.data[i])));
5283             }
5284             thread_dict_sp->AddItem("medata", medata_array_sp);
5285           }
5286           break;
5287 
5288         case eStopTypeExec:
5289           reason_value = "exec";
5290           break;
5291         }
5292       }
5293 
5294       thread_dict_sp->AddStringItem("reason", reason_value);
5295 
5296       if (threads_with_valid_stop_info_only == false) {
5297         const char *thread_name = DNBThreadGetName(pid, tid);
5298         if (thread_name && thread_name[0])
5299           thread_dict_sp->AddStringItem("name", thread_name);
5300 
5301         thread_identifier_info_data_t thread_ident_info;
5302         if (DNBThreadGetIdentifierInfo(pid, tid, &thread_ident_info)) {
5303           if (thread_ident_info.dispatch_qaddr != 0) {
5304             thread_dict_sp->AddIntegerItem("qaddr",
5305                                            thread_ident_info.dispatch_qaddr);
5306 
5307             const DispatchQueueOffsets *dispatch_queue_offsets =
5308                 GetDispatchQueueOffsets();
5309             if (dispatch_queue_offsets) {
5310               std::string queue_name;
5311               uint64_t queue_width = 0;
5312               uint64_t queue_serialnum = 0;
5313               nub_addr_t dispatch_queue_t = INVALID_NUB_ADDRESS;
5314               dispatch_queue_offsets->GetThreadQueueInfo(
5315                   pid, thread_ident_info.dispatch_qaddr, dispatch_queue_t,
5316                   queue_name, queue_width, queue_serialnum);
5317               if (dispatch_queue_t == 0 && queue_name.empty() &&
5318                   queue_serialnum == 0) {
5319                 thread_dict_sp->AddBooleanItem("associated_with_dispatch_queue",
5320                                                false);
5321               } else {
5322                 thread_dict_sp->AddBooleanItem("associated_with_dispatch_queue",
5323                                                true);
5324               }
5325               if (dispatch_queue_t != INVALID_NUB_ADDRESS &&
5326                   dispatch_queue_t != 0)
5327                 thread_dict_sp->AddIntegerItem("dispatch_queue_t",
5328                                                dispatch_queue_t);
5329               if (!queue_name.empty())
5330                 thread_dict_sp->AddStringItem("qname", queue_name);
5331               if (queue_width == 1)
5332                 thread_dict_sp->AddStringItem("qkind", "serial");
5333               else if (queue_width > 1)
5334                 thread_dict_sp->AddStringItem("qkind", "concurrent");
5335               if (queue_serialnum > 0)
5336                 thread_dict_sp->AddIntegerItem("qserialnum", queue_serialnum);
5337             }
5338           }
5339         }
5340 
5341         DNBRegisterValue reg_value;
5342 
5343         if (g_reg_entries != NULL) {
5344           JSONGenerator::DictionarySP registers_dict_sp(
5345               new JSONGenerator::Dictionary());
5346 
5347           for (uint32_t reg = 0; reg < g_num_reg_entries; reg++) {
5348             // Expedite all registers in the first register set that aren't
5349             // contained in other registers
5350             if (g_reg_entries[reg].nub_info.set == 1 &&
5351                 g_reg_entries[reg].nub_info.value_regs == NULL) {
5352               if (!DNBThreadGetRegisterValueByID(
5353                       pid, tid, g_reg_entries[reg].nub_info.set,
5354                       g_reg_entries[reg].nub_info.reg, &reg_value))
5355                 continue;
5356 
5357               std::ostringstream reg_num;
5358               reg_num << std::dec << g_reg_entries[reg].debugserver_regnum;
5359               // Encode native byte ordered bytes as hex ascii
5360               registers_dict_sp->AddBytesAsHexASCIIString(
5361                   reg_num.str(), reg_value.value.v_uint8,
5362                   g_reg_entries[reg].nub_info.size);
5363             }
5364           }
5365           thread_dict_sp->AddItem("registers", registers_dict_sp);
5366         }
5367 
5368         // Add expedited stack memory so stack backtracing doesn't need to read
5369         // anything from the
5370         // frame pointer chain.
5371         StackMemoryMap stack_mmap;
5372         ReadStackMemory(pid, tid, stack_mmap);
5373         if (!stack_mmap.empty()) {
5374           JSONGenerator::ArraySP memory_array_sp(new JSONGenerator::Array());
5375 
5376           for (const auto &stack_memory : stack_mmap) {
5377             JSONGenerator::DictionarySP stack_memory_sp(
5378                 new JSONGenerator::Dictionary());
5379             stack_memory_sp->AddIntegerItem("address", stack_memory.first);
5380             stack_memory_sp->AddBytesAsHexASCIIString(
5381                 "bytes", stack_memory.second.bytes, stack_memory.second.length);
5382             memory_array_sp->AddItem(stack_memory_sp);
5383           }
5384           thread_dict_sp->AddItem("memory", memory_array_sp);
5385         }
5386       }
5387 
5388       threads_array_sp->AddItem(thread_dict_sp);
5389     }
5390   }
5391   return threads_array_sp;
5392 }
5393 
5394 rnb_err_t RNBRemote::HandlePacket_jThreadsInfo(const char *p) {
5395   JSONGenerator::ObjectSP threads_info_sp;
5396   std::ostringstream json;
5397   std::ostringstream reply_strm;
5398   // If we haven't run the process yet, return an error.
5399   if (m_ctx.HasValidProcessID()) {
5400     const bool threads_with_valid_stop_info_only = false;
5401     JSONGenerator::ObjectSP threads_info_sp =
5402         GetJSONThreadsInfo(threads_with_valid_stop_info_only);
5403 
5404     if (threads_info_sp) {
5405       std::ostringstream strm;
5406       threads_info_sp->Dump(strm);
5407       std::string binary_packet = binary_encode_string(strm.str());
5408       if (!binary_packet.empty())
5409         return SendPacket(binary_packet.c_str());
5410     }
5411   }
5412   return SendPacket("E85");
5413 }
5414 
5415 rnb_err_t RNBRemote::HandlePacket_jThreadExtendedInfo(const char *p) {
5416   nub_process_t pid;
5417   std::ostringstream json;
5418   // If we haven't run the process yet, return an error.
5419   if (!m_ctx.HasValidProcessID()) {
5420     return SendPacket("E81");
5421   }
5422 
5423   pid = m_ctx.ProcessID();
5424 
5425   const char thread_extended_info_str[] = {"jThreadExtendedInfo:{"};
5426   if (strncmp(p, thread_extended_info_str,
5427               sizeof(thread_extended_info_str) - 1) == 0) {
5428     p += strlen(thread_extended_info_str);
5429 
5430     uint64_t tid = get_integer_value_for_key_name_from_json("thread", p);
5431     uint64_t plo_pthread_tsd_base_address_offset =
5432         get_integer_value_for_key_name_from_json(
5433             "plo_pthread_tsd_base_address_offset", p);
5434     uint64_t plo_pthread_tsd_base_offset =
5435         get_integer_value_for_key_name_from_json("plo_pthread_tsd_base_offset",
5436                                                  p);
5437     uint64_t plo_pthread_tsd_entry_size =
5438         get_integer_value_for_key_name_from_json("plo_pthread_tsd_entry_size",
5439                                                  p);
5440     uint64_t dti_qos_class_index =
5441         get_integer_value_for_key_name_from_json("dti_qos_class_index", p);
5442     // Commented out the two variables below as they are not being used
5443     //        uint64_t dti_queue_index =
5444     //        get_integer_value_for_key_name_from_json ("dti_queue_index", p);
5445     //        uint64_t dti_voucher_index =
5446     //        get_integer_value_for_key_name_from_json ("dti_voucher_index", p);
5447 
5448     if (tid != INVALID_NUB_ADDRESS) {
5449       nub_addr_t pthread_t_value = DNBGetPThreadT(pid, tid);
5450 
5451       uint64_t tsd_address = INVALID_NUB_ADDRESS;
5452       if (plo_pthread_tsd_entry_size != INVALID_NUB_ADDRESS &&
5453           plo_pthread_tsd_base_offset != INVALID_NUB_ADDRESS &&
5454           plo_pthread_tsd_entry_size != INVALID_NUB_ADDRESS) {
5455         tsd_address = DNBGetTSDAddressForThread(
5456             pid, tid, plo_pthread_tsd_base_address_offset,
5457             plo_pthread_tsd_base_offset, plo_pthread_tsd_entry_size);
5458       }
5459 
5460       bool timed_out = false;
5461       Genealogy::ThreadActivitySP thread_activity_sp;
5462 
5463       // If the pthread_t value is invalid, or if we were able to fetch the
5464       // thread's TSD base
5465       // and got an invalid value back, then we have a thread in early startup
5466       // or shutdown and
5467       // it's possible that gathering the genealogy information for this thread
5468       // go badly.
5469       // Ideally fetching this info for a thread in these odd states shouldn't
5470       // matter - but
5471       // we've seen some problems with these new SPI and threads in edge-casey
5472       // states.
5473 
5474       double genealogy_fetch_time = 0;
5475       if (pthread_t_value != INVALID_NUB_ADDRESS &&
5476           tsd_address != INVALID_NUB_ADDRESS) {
5477         DNBTimer timer(false);
5478         thread_activity_sp = DNBGetGenealogyInfoForThread(pid, tid, timed_out);
5479         genealogy_fetch_time = timer.ElapsedMicroSeconds(false) / 1000000.0;
5480       }
5481 
5482       std::unordered_set<uint32_t>
5483           process_info_indexes; // an array of the process info #'s seen
5484 
5485       json << "{";
5486 
5487       bool need_to_print_comma = false;
5488 
5489       if (thread_activity_sp && timed_out == false) {
5490         const Genealogy::Activity *activity =
5491             &thread_activity_sp->current_activity;
5492         bool need_vouchers_comma_sep = false;
5493         json << "\"activity_query_timed_out\":false,";
5494         if (genealogy_fetch_time != 0) {
5495           //  If we append the floating point value with << we'll get it in
5496           //  scientific
5497           //  notation.
5498           char floating_point_ascii_buffer[64];
5499           floating_point_ascii_buffer[0] = '\0';
5500           snprintf(floating_point_ascii_buffer,
5501                    sizeof(floating_point_ascii_buffer), "%f",
5502                    genealogy_fetch_time);
5503           if (strlen(floating_point_ascii_buffer) > 0) {
5504             if (need_to_print_comma)
5505               json << ",";
5506             need_to_print_comma = true;
5507             json << "\"activity_query_duration\":"
5508                  << floating_point_ascii_buffer;
5509           }
5510         }
5511         if (activity->activity_id != 0) {
5512           if (need_to_print_comma)
5513             json << ",";
5514           need_to_print_comma = true;
5515           need_vouchers_comma_sep = true;
5516           json << "\"activity\":{";
5517           json << "\"start\":" << activity->activity_start << ",";
5518           json << "\"id\":" << activity->activity_id << ",";
5519           json << "\"parent_id\":" << activity->parent_id << ",";
5520           json << "\"name\":\""
5521                << json_string_quote_metachars(activity->activity_name) << "\",";
5522           json << "\"reason\":\""
5523                << json_string_quote_metachars(activity->reason) << "\"";
5524           json << "}";
5525         }
5526         if (thread_activity_sp->messages.size() > 0) {
5527           need_to_print_comma = true;
5528           if (need_vouchers_comma_sep)
5529             json << ",";
5530           need_vouchers_comma_sep = true;
5531           json << "\"trace_messages\":[";
5532           bool printed_one_message = false;
5533           for (auto iter = thread_activity_sp->messages.begin();
5534                iter != thread_activity_sp->messages.end(); ++iter) {
5535             if (printed_one_message)
5536               json << ",";
5537             else
5538               printed_one_message = true;
5539             json << "{";
5540             json << "\"timestamp\":" << iter->timestamp << ",";
5541             json << "\"activity_id\":" << iter->activity_id << ",";
5542             json << "\"trace_id\":" << iter->trace_id << ",";
5543             json << "\"thread\":" << iter->thread << ",";
5544             json << "\"type\":" << (int)iter->type << ",";
5545             json << "\"process_info_index\":" << iter->process_info_index
5546                  << ",";
5547             process_info_indexes.insert(iter->process_info_index);
5548             json << "\"message\":\""
5549                  << json_string_quote_metachars(iter->message) << "\"";
5550             json << "}";
5551           }
5552           json << "]";
5553         }
5554         if (thread_activity_sp->breadcrumbs.size() == 1) {
5555           need_to_print_comma = true;
5556           if (need_vouchers_comma_sep)
5557             json << ",";
5558           need_vouchers_comma_sep = true;
5559           json << "\"breadcrumb\":{";
5560           for (auto iter = thread_activity_sp->breadcrumbs.begin();
5561                iter != thread_activity_sp->breadcrumbs.end(); ++iter) {
5562             json << "\"breadcrumb_id\":" << iter->breadcrumb_id << ",";
5563             json << "\"activity_id\":" << iter->activity_id << ",";
5564             json << "\"timestamp\":" << iter->timestamp << ",";
5565             json << "\"name\":\"" << json_string_quote_metachars(iter->name)
5566                  << "\"";
5567           }
5568           json << "}";
5569         }
5570         if (process_info_indexes.size() > 0) {
5571           need_to_print_comma = true;
5572           if (need_vouchers_comma_sep)
5573             json << ",";
5574           need_vouchers_comma_sep = true;
5575           bool printed_one_process_info = false;
5576           for (auto iter = process_info_indexes.begin();
5577                iter != process_info_indexes.end(); ++iter) {
5578             if (printed_one_process_info)
5579               json << ",";
5580             Genealogy::ProcessExecutableInfoSP image_info_sp;
5581             uint32_t idx = *iter;
5582             image_info_sp = DNBGetGenealogyImageInfo(pid, idx);
5583             if (image_info_sp) {
5584               if (!printed_one_process_info) {
5585                 json << "\"process_infos\":[";
5586                 printed_one_process_info = true;
5587               }
5588 
5589               json << "{";
5590               char uuid_buf[37];
5591               uuid_unparse_upper(image_info_sp->image_uuid, uuid_buf);
5592               json << "\"process_info_index\":" << idx << ",";
5593               json << "\"image_path\":\""
5594                    << json_string_quote_metachars(image_info_sp->image_path)
5595                    << "\",";
5596               json << "\"image_uuid\":\"" << uuid_buf << "\"";
5597               json << "}";
5598             }
5599           }
5600           if (printed_one_process_info)
5601             json << "]";
5602         }
5603       } else {
5604         if (timed_out) {
5605           if (need_to_print_comma)
5606             json << ",";
5607           need_to_print_comma = true;
5608           json << "\"activity_query_timed_out\":true";
5609           if (genealogy_fetch_time != 0) {
5610             //  If we append the floating point value with << we'll get it in
5611             //  scientific
5612             //  notation.
5613             char floating_point_ascii_buffer[64];
5614             floating_point_ascii_buffer[0] = '\0';
5615             snprintf(floating_point_ascii_buffer,
5616                      sizeof(floating_point_ascii_buffer), "%f",
5617                      genealogy_fetch_time);
5618             if (strlen(floating_point_ascii_buffer) > 0) {
5619               json << ",";
5620               json << "\"activity_query_duration\":"
5621                    << floating_point_ascii_buffer;
5622             }
5623           }
5624         }
5625       }
5626 
5627       if (tsd_address != INVALID_NUB_ADDRESS) {
5628         if (need_to_print_comma)
5629           json << ",";
5630         need_to_print_comma = true;
5631         json << "\"tsd_address\":" << tsd_address;
5632 
5633         if (dti_qos_class_index != 0 && dti_qos_class_index != UINT64_MAX) {
5634           ThreadInfo::QoS requested_qos = DNBGetRequestedQoSForThread(
5635               pid, tid, tsd_address, dti_qos_class_index);
5636           if (requested_qos.IsValid()) {
5637             if (need_to_print_comma)
5638               json << ",";
5639             need_to_print_comma = true;
5640             json << "\"requested_qos\":{";
5641             json << "\"enum_value\":" << requested_qos.enum_value << ",";
5642             json << "\"constant_name\":\""
5643                  << json_string_quote_metachars(requested_qos.constant_name)
5644                  << "\",";
5645             json << "\"printable_name\":\""
5646                  << json_string_quote_metachars(requested_qos.printable_name)
5647                  << "\"";
5648             json << "}";
5649           }
5650         }
5651       }
5652 
5653       if (pthread_t_value != INVALID_NUB_ADDRESS) {
5654         if (need_to_print_comma)
5655           json << ",";
5656         need_to_print_comma = true;
5657         json << "\"pthread_t\":" << pthread_t_value;
5658       }
5659 
5660       nub_addr_t dispatch_queue_t_value = DNBGetDispatchQueueT(pid, tid);
5661       if (dispatch_queue_t_value != INVALID_NUB_ADDRESS) {
5662         if (need_to_print_comma)
5663           json << ",";
5664         need_to_print_comma = true;
5665         json << "\"dispatch_queue_t\":" << dispatch_queue_t_value;
5666       }
5667 
5668       json << "}";
5669       std::string json_quoted = binary_encode_string(json.str());
5670       return SendPacket(json_quoted);
5671     }
5672   }
5673   return SendPacket("OK");
5674 }
5675 
5676 //  This packet may be called in one of three ways:
5677 //
5678 //  jGetLoadedDynamicLibrariesInfos:{"image_count":40,"image_list_address":4295244704}
5679 //      Look for an array of the old dyld_all_image_infos style of binary infos
5680 //      at the image_list_address.
5681 //      This an array of {void* load_addr, void* mod_date, void* pathname}
5682 //
5683 //  jGetLoadedDynamicLibrariesInfos:{"fetch_all_solibs":true}
5684 //      Use the new style (macOS 10.12, tvOS 10, iOS 10, watchOS 3) dyld SPI to
5685 //      get a list of all the
5686 //      libraries loaded
5687 //
5688 //  jGetLoadedDynamicLibrariesInfos:{"solib_addresses":[8382824135,3258302053,830202858503]}
5689 //      Use the new style (macOS 10.12, tvOS 10, iOS 10, watchOS 3) dyld SPI to
5690 //      get the information
5691 //      about the libraries loaded at these addresses.
5692 //
5693 rnb_err_t
5694 RNBRemote::HandlePacket_jGetLoadedDynamicLibrariesInfos(const char *p) {
5695   nub_process_t pid;
5696   // If we haven't run the process yet, return an error.
5697   if (!m_ctx.HasValidProcessID()) {
5698     return SendPacket("E83");
5699   }
5700 
5701   pid = m_ctx.ProcessID();
5702 
5703   const char get_loaded_dynamic_libraries_infos_str[] = {
5704       "jGetLoadedDynamicLibrariesInfos:{"};
5705   if (strncmp(p, get_loaded_dynamic_libraries_infos_str,
5706               sizeof(get_loaded_dynamic_libraries_infos_str) - 1) == 0) {
5707     p += strlen(get_loaded_dynamic_libraries_infos_str);
5708 
5709     JSONGenerator::ObjectSP json_sp;
5710 
5711     std::vector<uint64_t> macho_addresses;
5712     bool fetch_all_solibs = false;
5713     if (get_boolean_value_for_key_name_from_json("fetch_all_solibs", p,
5714                                                  fetch_all_solibs) &&
5715         fetch_all_solibs) {
5716       json_sp = DNBGetAllLoadedLibrariesInfos(pid);
5717     } else if (get_array_of_ints_value_for_key_name_from_json(
5718                    "solib_addresses", p, macho_addresses)) {
5719       json_sp = DNBGetLibrariesInfoForAddresses(pid, macho_addresses);
5720     } else {
5721       nub_addr_t image_list_address =
5722           get_integer_value_for_key_name_from_json("image_list_address", p);
5723       nub_addr_t image_count =
5724           get_integer_value_for_key_name_from_json("image_count", p);
5725 
5726       if (image_list_address != INVALID_NUB_ADDRESS &&
5727           image_count != INVALID_NUB_ADDRESS) {
5728         json_sp = DNBGetLoadedDynamicLibrariesInfos(pid, image_list_address,
5729                                                     image_count);
5730       }
5731     }
5732 
5733     if (json_sp.get()) {
5734       std::ostringstream json_str;
5735       json_sp->Dump(json_str);
5736       if (json_str.str().size() > 0) {
5737         std::string json_str_quoted = binary_encode_string(json_str.str());
5738         return SendPacket(json_str_quoted.c_str());
5739       } else {
5740         SendPacket("E84");
5741       }
5742     }
5743   }
5744   return SendPacket("OK");
5745 }
5746 
5747 // This packet does not currently take any arguments.  So the behavior is
5748 //    jGetSharedCacheInfo:{}
5749 //         send information about the inferior's shared cache
5750 //    jGetSharedCacheInfo:
5751 //         send "OK" to indicate that this packet is supported
5752 rnb_err_t RNBRemote::HandlePacket_jGetSharedCacheInfo(const char *p) {
5753   nub_process_t pid;
5754   // If we haven't run the process yet, return an error.
5755   if (!m_ctx.HasValidProcessID()) {
5756     return SendPacket("E85");
5757   }
5758 
5759   pid = m_ctx.ProcessID();
5760 
5761   const char get_shared_cache_info_str[] = {"jGetSharedCacheInfo:{"};
5762   if (strncmp(p, get_shared_cache_info_str,
5763               sizeof(get_shared_cache_info_str) - 1) == 0) {
5764     JSONGenerator::ObjectSP json_sp = DNBGetSharedCacheInfo(pid);
5765 
5766     if (json_sp.get()) {
5767       std::ostringstream json_str;
5768       json_sp->Dump(json_str);
5769       if (json_str.str().size() > 0) {
5770         std::string json_str_quoted = binary_encode_string(json_str.str());
5771         return SendPacket(json_str_quoted.c_str());
5772       } else {
5773         SendPacket("E86");
5774       }
5775     }
5776   }
5777   return SendPacket("OK");
5778 }
5779 
5780 static bool MachHeaderIsMainExecutable(nub_process_t pid, uint32_t addr_size,
5781                                        nub_addr_t mach_header_addr,
5782                                        mach_header &mh) {
5783   DNBLogThreadedIf(LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = %u, "
5784                                  "addr_size = %u, mach_header_addr = "
5785                                  "0x%16.16llx)",
5786                    pid, addr_size, mach_header_addr);
5787   const nub_size_t bytes_read =
5788       DNBProcessMemoryRead(pid, mach_header_addr, sizeof(mh), &mh);
5789   if (bytes_read == sizeof(mh)) {
5790     DNBLogThreadedIf(
5791         LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = %u, addr_size = "
5792                       "%u, mach_header_addr = 0x%16.16llx): mh = {\n  magic = "
5793                       "0x%8.8x\n  cpu = 0x%8.8x\n  sub = 0x%8.8x\n  filetype = "
5794                       "%u\n  ncmds = %u\n  sizeofcmds = 0x%8.8x\n  flags = "
5795                       "0x%8.8x }",
5796         pid, addr_size, mach_header_addr, mh.magic, mh.cputype, mh.cpusubtype,
5797         mh.filetype, mh.ncmds, mh.sizeofcmds, mh.flags);
5798     if ((addr_size == 4 && mh.magic == MH_MAGIC) ||
5799         (addr_size == 8 && mh.magic == MH_MAGIC_64)) {
5800       if (mh.filetype == MH_EXECUTE) {
5801         DNBLogThreadedIf(LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = "
5802                                        "%u, addr_size = %u, mach_header_addr = "
5803                                        "0x%16.16llx) -> this is the "
5804                                        "executable!!!",
5805                          pid, addr_size, mach_header_addr);
5806         return true;
5807       }
5808     }
5809   }
5810   return false;
5811 }
5812 
5813 static nub_addr_t GetMachHeaderForMainExecutable(const nub_process_t pid,
5814                                                  const uint32_t addr_size,
5815                                                  mach_header &mh) {
5816   struct AllImageInfos {
5817     uint32_t version;
5818     uint32_t dylib_info_count;
5819     uint64_t dylib_info_addr;
5820   };
5821 
5822   uint64_t mach_header_addr = 0;
5823 
5824   const nub_addr_t shlib_addr = DNBProcessGetSharedLibraryInfoAddress(pid);
5825   uint8_t bytes[256];
5826   nub_size_t bytes_read = 0;
5827   DNBDataRef data(bytes, sizeof(bytes), false);
5828   DNBDataRef::offset_t offset = 0;
5829   data.SetPointerSize(addr_size);
5830 
5831   //----------------------------------------------------------------------
5832   // When we are sitting at __dyld_start, the kernel has placed the
5833   // address of the mach header of the main executable on the stack. If we
5834   // read the SP and dereference a pointer, we might find the mach header
5835   // for the executable. We also just make sure there is only 1 thread
5836   // since if we are at __dyld_start we shouldn't have multiple threads.
5837   //----------------------------------------------------------------------
5838   if (DNBProcessGetNumThreads(pid) == 1) {
5839     nub_thread_t tid = DNBProcessGetThreadAtIndex(pid, 0);
5840     if (tid != INVALID_NUB_THREAD) {
5841       DNBRegisterValue sp_value;
5842       if (DNBThreadGetRegisterValueByID(pid, tid, REGISTER_SET_GENERIC,
5843                                         GENERIC_REGNUM_SP, &sp_value)) {
5844         uint64_t sp =
5845             addr_size == 8 ? sp_value.value.uint64 : sp_value.value.uint32;
5846         bytes_read = DNBProcessMemoryRead(pid, sp, addr_size, bytes);
5847         if (bytes_read == addr_size) {
5848           offset = 0;
5849           mach_header_addr = data.GetPointer(&offset);
5850           if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, mh))
5851             return mach_header_addr;
5852         }
5853       }
5854     }
5855   }
5856 
5857   //----------------------------------------------------------------------
5858   // Check the dyld_all_image_info structure for a list of mach header
5859   // since it is a very easy thing to check
5860   //----------------------------------------------------------------------
5861   if (shlib_addr != INVALID_NUB_ADDRESS) {
5862     bytes_read =
5863         DNBProcessMemoryRead(pid, shlib_addr, sizeof(AllImageInfos), bytes);
5864     if (bytes_read > 0) {
5865       AllImageInfos aii;
5866       offset = 0;
5867       aii.version = data.Get32(&offset);
5868       aii.dylib_info_count = data.Get32(&offset);
5869       if (aii.dylib_info_count > 0) {
5870         aii.dylib_info_addr = data.GetPointer(&offset);
5871         if (aii.dylib_info_addr != 0) {
5872           const size_t image_info_byte_size = 3 * addr_size;
5873           for (uint32_t i = 0; i < aii.dylib_info_count; ++i) {
5874             bytes_read = DNBProcessMemoryRead(pid, aii.dylib_info_addr +
5875                                                        i * image_info_byte_size,
5876                                               image_info_byte_size, bytes);
5877             if (bytes_read != image_info_byte_size)
5878               break;
5879             offset = 0;
5880             mach_header_addr = data.GetPointer(&offset);
5881             if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr,
5882                                            mh))
5883               return mach_header_addr;
5884           }
5885         }
5886       }
5887     }
5888   }
5889 
5890   //----------------------------------------------------------------------
5891   // We failed to find the executable's mach header from the all image
5892   // infos and by dereferencing the stack pointer. Now we fall back to
5893   // enumerating the memory regions and looking for regions that are
5894   // executable.
5895   //----------------------------------------------------------------------
5896   DNBRegionInfo region_info;
5897   mach_header_addr = 0;
5898   while (DNBProcessMemoryRegionInfo(pid, mach_header_addr, &region_info)) {
5899     if (region_info.size == 0)
5900       break;
5901 
5902     if (region_info.permissions & eMemoryPermissionsExecutable) {
5903       DNBLogThreadedIf(
5904           LOG_RNB_PROC, "[0x%16.16llx - 0x%16.16llx) permissions = %c%c%c: "
5905                         "checking region for executable mach header",
5906           region_info.addr, region_info.addr + region_info.size,
5907           (region_info.permissions & eMemoryPermissionsReadable) ? 'r' : '-',
5908           (region_info.permissions & eMemoryPermissionsWritable) ? 'w' : '-',
5909           (region_info.permissions & eMemoryPermissionsExecutable) ? 'x' : '-');
5910       if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, mh))
5911         return mach_header_addr;
5912     } else {
5913       DNBLogThreadedIf(
5914           LOG_RNB_PROC,
5915           "[0x%16.16llx - 0x%16.16llx): permissions = %c%c%c: skipping region",
5916           region_info.addr, region_info.addr + region_info.size,
5917           (region_info.permissions & eMemoryPermissionsReadable) ? 'r' : '-',
5918           (region_info.permissions & eMemoryPermissionsWritable) ? 'w' : '-',
5919           (region_info.permissions & eMemoryPermissionsExecutable) ? 'x' : '-');
5920     }
5921     // Set the address to the next mapped region
5922     mach_header_addr = region_info.addr + region_info.size;
5923   }
5924   bzero(&mh, sizeof(mh));
5925   return INVALID_NUB_ADDRESS;
5926 }
5927 
5928 rnb_err_t RNBRemote::HandlePacket_qSymbol(const char *command) {
5929   const char *p = command;
5930   p += strlen("qSymbol:");
5931   const char *sep = strchr(p, ':');
5932 
5933   std::string symbol_name;
5934   std::string symbol_value_str;
5935   // Extract the symbol value if there is one
5936   if (sep > p)
5937     symbol_value_str.assign(p, sep - p);
5938   p = sep + 1;
5939 
5940   if (*p) {
5941     // We have a symbol name
5942     symbol_name = decode_hex_ascii_string(p);
5943     if (!symbol_value_str.empty()) {
5944       nub_addr_t symbol_value = decode_uint64(symbol_value_str.c_str(), 16);
5945       if (symbol_name == "dispatch_queue_offsets")
5946         m_dispatch_queue_offsets_addr = symbol_value;
5947     }
5948     ++m_qSymbol_index;
5949   } else {
5950     // No symbol name, set our symbol index to zero so we can
5951     // read any symbols that we need
5952     m_qSymbol_index = 0;
5953   }
5954 
5955   symbol_name.clear();
5956 
5957   if (m_qSymbol_index == 0) {
5958     if (m_dispatch_queue_offsets_addr == INVALID_NUB_ADDRESS)
5959       symbol_name = "dispatch_queue_offsets";
5960     else
5961       ++m_qSymbol_index;
5962   }
5963 
5964   //    // Lookup next symbol when we have one...
5965   //    if (m_qSymbol_index == 1)
5966   //    {
5967   //    }
5968 
5969   if (symbol_name.empty()) {
5970     // Done with symbol lookups
5971     return SendPacket("OK");
5972   } else {
5973     std::ostringstream reply;
5974     reply << "qSymbol:";
5975     for (size_t i = 0; i < symbol_name.size(); ++i)
5976       reply << RAWHEX8(symbol_name[i]);
5977     return SendPacket(reply.str().c_str());
5978   }
5979 }
5980 
5981 // Note that all numeric values returned by qProcessInfo are hex encoded,
5982 // including the pid and the cpu type.
5983 
5984 rnb_err_t RNBRemote::HandlePacket_qProcessInfo(const char *p) {
5985   nub_process_t pid;
5986   std::ostringstream rep;
5987 
5988   // If we haven't run the process yet, return an error.
5989   if (!m_ctx.HasValidProcessID())
5990     return SendPacket("E68");
5991 
5992   pid = m_ctx.ProcessID();
5993 
5994   rep << "pid:" << std::hex << pid << ';';
5995 
5996   int procpid_mib[4];
5997   procpid_mib[0] = CTL_KERN;
5998   procpid_mib[1] = KERN_PROC;
5999   procpid_mib[2] = KERN_PROC_PID;
6000   procpid_mib[3] = pid;
6001   struct kinfo_proc proc_kinfo;
6002   size_t proc_kinfo_size = sizeof(struct kinfo_proc);
6003 
6004   if (::sysctl(procpid_mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) {
6005     if (proc_kinfo_size > 0) {
6006       rep << "parent-pid:" << std::hex << proc_kinfo.kp_eproc.e_ppid << ';';
6007       rep << "real-uid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_ruid
6008           << ';';
6009       rep << "real-gid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_rgid
6010           << ';';
6011       rep << "effective-uid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_uid
6012           << ';';
6013       if (proc_kinfo.kp_eproc.e_ucred.cr_ngroups > 0)
6014         rep << "effective-gid:" << std::hex
6015             << proc_kinfo.kp_eproc.e_ucred.cr_groups[0] << ';';
6016     }
6017   }
6018 
6019   cpu_type_t cputype = DNBProcessGetCPUType(pid);
6020   if (cputype == 0) {
6021     DNBLog("Unable to get the process cpu_type, making a best guess.");
6022     cputype = best_guess_cpu_type();
6023   }
6024 
6025   uint32_t addr_size = 0;
6026   if (cputype != 0) {
6027     rep << "cputype:" << std::hex << cputype << ";";
6028     if (cputype & CPU_ARCH_ABI64)
6029       addr_size = 8;
6030     else
6031       addr_size = 4;
6032   }
6033 
6034   bool host_cpu_is_64bit = false;
6035   uint32_t is64bit_capable;
6036   size_t is64bit_capable_len = sizeof(is64bit_capable);
6037   if (sysctlbyname("hw.cpu64bit_capable", &is64bit_capable,
6038                    &is64bit_capable_len, NULL, 0) == 0)
6039     host_cpu_is_64bit = is64bit_capable != 0;
6040 
6041   uint32_t cpusubtype;
6042   size_t cpusubtype_len = sizeof(cpusubtype);
6043   if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &cpusubtype_len, NULL, 0) ==
6044       0) {
6045     // If a process is CPU_TYPE_X86, then ignore the cpusubtype that we detected
6046     // from the host and use CPU_SUBTYPE_I386_ALL because we don't want the
6047     // CPU_SUBTYPE_X86_ARCH1 or CPU_SUBTYPE_X86_64_H to be used as the cpu
6048     // subtype
6049     // for i386...
6050     if (host_cpu_is_64bit) {
6051       if (cputype == CPU_TYPE_X86) {
6052         cpusubtype = 3; // CPU_SUBTYPE_I386_ALL
6053       } else if (cputype == CPU_TYPE_ARM) {
6054         // We can query a process' cputype but we cannot query a process'
6055         // cpusubtype.
6056         // If the process has cputype CPU_TYPE_ARM, then it is an armv7 (32-bit
6057         // process) and we
6058         // need to override the host cpusubtype (which is in the
6059         // CPU_SUBTYPE_ARM64 subtype namespace)
6060         // with a reasonable CPU_SUBTYPE_ARMV7 subtype.
6061         cpusubtype = 12; // CPU_SUBTYPE_ARM_V7K
6062       }
6063     }
6064     rep << "cpusubtype:" << std::hex << cpusubtype << ';';
6065   }
6066 
6067   bool os_handled = false;
6068   if (addr_size > 0) {
6069     rep << "ptrsize:" << std::dec << addr_size << ';';
6070 
6071 #if (defined(__x86_64__) || defined(__i386__))
6072     // Try and get the OS type by looking at the load commands in the main
6073     // executable and looking for a LC_VERSION_MIN load command. This is the
6074     // most reliable way to determine the "ostype" value when on desktop.
6075 
6076     mach_header mh;
6077     nub_addr_t exe_mach_header_addr =
6078         GetMachHeaderForMainExecutable(pid, addr_size, mh);
6079     if (exe_mach_header_addr != INVALID_NUB_ADDRESS) {
6080       uint64_t load_command_addr =
6081           exe_mach_header_addr +
6082           ((addr_size == 8) ? sizeof(mach_header_64) : sizeof(mach_header));
6083       load_command lc;
6084       for (uint32_t i = 0; i < mh.ncmds && !os_handled; ++i) {
6085         const nub_size_t bytes_read =
6086             DNBProcessMemoryRead(pid, load_command_addr, sizeof(lc), &lc);
6087         uint32_t raw_cmd = lc.cmd & ~LC_REQ_DYLD;
6088         if (bytes_read != sizeof(lc))
6089           break;
6090         switch (raw_cmd) {
6091         case LC_VERSION_MIN_IPHONEOS:
6092           os_handled = true;
6093           rep << "ostype:ios;";
6094           DNBLogThreadedIf(LOG_RNB_PROC,
6095                            "LC_VERSION_MIN_IPHONEOS -> 'ostype:ios;'");
6096           break;
6097 
6098         case LC_VERSION_MIN_MACOSX:
6099           os_handled = true;
6100           rep << "ostype:macosx;";
6101           DNBLogThreadedIf(LOG_RNB_PROC,
6102                            "LC_VERSION_MIN_MACOSX -> 'ostype:macosx;'");
6103           break;
6104 
6105 #if defined(LC_VERSION_MIN_TVOS)
6106         case LC_VERSION_MIN_TVOS:
6107           os_handled = true;
6108           rep << "ostype:tvos;";
6109           DNBLogThreadedIf(LOG_RNB_PROC,
6110                            "LC_VERSION_MIN_TVOS -> 'ostype:tvos;'");
6111           break;
6112 #endif
6113 
6114 #if defined(LC_VERSION_MIN_WATCHOS)
6115         case LC_VERSION_MIN_WATCHOS:
6116           os_handled = true;
6117           rep << "ostype:watchos;";
6118           DNBLogThreadedIf(LOG_RNB_PROC,
6119                            "LC_VERSION_MIN_WATCHOS -> 'ostype:watchos;'");
6120           break;
6121 #endif
6122 
6123         default:
6124           break;
6125         }
6126         load_command_addr = load_command_addr + lc.cmdsize;
6127       }
6128     }
6129 #endif
6130   }
6131 
6132   // If we weren't able to find the OS in a LC_VERSION_MIN load command, try
6133   // to set it correctly by using the cpu type and other tricks
6134   if (!os_handled) {
6135     // The OS in the triple should be "ios" or "macosx" which doesn't match our
6136     // "Darwin" which gets returned from "kern.ostype", so we need to hardcode
6137     // this for now.
6138     if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64) {
6139 #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
6140       rep << "ostype:tvos;";
6141 #elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
6142       rep << "ostype:watchos;";
6143 #else
6144       rep << "ostype:ios;";
6145 #endif
6146     } else {
6147       bool is_ios_simulator = false;
6148       if (cputype == CPU_TYPE_X86 || cputype == CPU_TYPE_X86_64) {
6149         // Check for iOS simulator binaries by getting the process argument
6150         // and environment and checking for SIMULATOR_UDID in the environment
6151         int proc_args_mib[3] = {CTL_KERN, KERN_PROCARGS2, (int)pid};
6152 
6153         uint8_t arg_data[8192];
6154         size_t arg_data_size = sizeof(arg_data);
6155         if (::sysctl(proc_args_mib, 3, arg_data, &arg_data_size, NULL, 0) ==
6156             0) {
6157           DNBDataRef data(arg_data, arg_data_size, false);
6158           DNBDataRef::offset_t offset = 0;
6159           uint32_t argc = data.Get32(&offset);
6160           const char *cstr;
6161 
6162           cstr = data.GetCStr(&offset);
6163           if (cstr) {
6164             // Skip NULLs
6165             while (1) {
6166               const char *p = data.PeekCStr(offset);
6167               if ((p == NULL) || (*p != '\0'))
6168                 break;
6169               ++offset;
6170             }
6171             // Now skip all arguments
6172             for (uint32_t i = 0; i < argc; ++i) {
6173               data.GetCStr(&offset);
6174             }
6175 
6176             // Now iterate across all environment variables
6177             while ((cstr = data.GetCStr(&offset))) {
6178               if (strncmp(cstr, "SIMULATOR_UDID=", strlen("SIMULATOR_UDID=")) ==
6179                   0) {
6180                 is_ios_simulator = true;
6181                 break;
6182               }
6183               if (cstr[0] == '\0')
6184                 break;
6185             }
6186           }
6187         }
6188       }
6189       if (is_ios_simulator) {
6190 #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
6191         rep << "ostype:tvos;";
6192 #elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
6193         rep << "ostype:watchos;";
6194 #else
6195         rep << "ostype:ios;";
6196 #endif
6197       } else {
6198         rep << "ostype:macosx;";
6199       }
6200     }
6201   }
6202 
6203   rep << "vendor:apple;";
6204 
6205 #if defined(__LITTLE_ENDIAN__)
6206   rep << "endian:little;";
6207 #elif defined(__BIG_ENDIAN__)
6208   rep << "endian:big;";
6209 #elif defined(__PDP_ENDIAN__)
6210   rep << "endian:pdp;";
6211 #endif
6212 
6213   if (addr_size == 0) {
6214 #if (defined(__x86_64__) || defined(__i386__)) && defined(x86_THREAD_STATE)
6215     nub_thread_t thread = DNBProcessGetCurrentThreadMachPort(pid);
6216     kern_return_t kr;
6217     x86_thread_state_t gp_regs;
6218     mach_msg_type_number_t gp_count = x86_THREAD_STATE_COUNT;
6219     kr = thread_get_state(static_cast<thread_act_t>(thread), x86_THREAD_STATE,
6220                           (thread_state_t)&gp_regs, &gp_count);
6221     if (kr == KERN_SUCCESS) {
6222       if (gp_regs.tsh.flavor == x86_THREAD_STATE64)
6223         rep << "ptrsize:8;";
6224       else
6225         rep << "ptrsize:4;";
6226     }
6227 #elif defined(__arm__)
6228     rep << "ptrsize:4;";
6229 #elif (defined(__arm64__) || defined(__aarch64__)) &&                          \
6230     defined(ARM_UNIFIED_THREAD_STATE)
6231     nub_thread_t thread = DNBProcessGetCurrentThreadMachPort(pid);
6232     kern_return_t kr;
6233     arm_unified_thread_state_t gp_regs;
6234     mach_msg_type_number_t gp_count = ARM_UNIFIED_THREAD_STATE_COUNT;
6235     kr = thread_get_state(thread, ARM_UNIFIED_THREAD_STATE,
6236                           (thread_state_t)&gp_regs, &gp_count);
6237     if (kr == KERN_SUCCESS) {
6238       if (gp_regs.ash.flavor == ARM_THREAD_STATE64)
6239         rep << "ptrsize:8;";
6240       else
6241         rep << "ptrsize:4;";
6242     }
6243 #endif
6244   }
6245 
6246   return SendPacket(rep.str());
6247 }
6248 
6249 const RNBRemote::DispatchQueueOffsets *RNBRemote::GetDispatchQueueOffsets() {
6250   if (!m_dispatch_queue_offsets.IsValid() &&
6251       m_dispatch_queue_offsets_addr != INVALID_NUB_ADDRESS &&
6252       m_ctx.HasValidProcessID()) {
6253     nub_process_t pid = m_ctx.ProcessID();
6254     nub_size_t bytes_read = DNBProcessMemoryRead(
6255         pid, m_dispatch_queue_offsets_addr, sizeof(m_dispatch_queue_offsets),
6256         &m_dispatch_queue_offsets);
6257     if (bytes_read != sizeof(m_dispatch_queue_offsets))
6258       m_dispatch_queue_offsets.Clear();
6259   }
6260 
6261   if (m_dispatch_queue_offsets.IsValid())
6262     return &m_dispatch_queue_offsets;
6263   else
6264     return nullptr;
6265 }
6266 
6267 void RNBRemote::EnableCompressionNextSendPacket(compression_types type) {
6268   m_compression_mode = type;
6269   m_enable_compression_next_send_packet = true;
6270 }
6271 
6272 compression_types RNBRemote::GetCompressionType() {
6273   // The first packet we send back to the debugger after a QEnableCompression
6274   // request
6275   // should be uncompressed -- so we can indicate whether the compression was
6276   // enabled
6277   // or not via OK / Enn returns.  After that, all packets sent will be using
6278   // the
6279   // compression protocol.
6280 
6281   if (m_enable_compression_next_send_packet) {
6282     // One time, we send back "None" as our compression type
6283     m_enable_compression_next_send_packet = false;
6284     return compression_types::none;
6285   }
6286   return m_compression_mode;
6287 }
6288