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_type == compression_types::lz4) {
714         compressed_size = compression_encode_buffer(
715             encoded_data.data(), encoded_data_buf_size,
716             (const uint8_t *)orig.c_str(), orig.size(), nullptr,
717             COMPRESSION_LZ4_RAW);
718       }
719       if (compression_type == compression_types::zlib_deflate) {
720         compressed_size = compression_encode_buffer(
721             encoded_data.data(), encoded_data_buf_size,
722             (const uint8_t *)orig.c_str(), orig.size(), nullptr,
723             COMPRESSION_ZLIB);
724       }
725       if (compression_type == compression_types::lzma) {
726         compressed_size = compression_encode_buffer(
727             encoded_data.data(), encoded_data_buf_size,
728             (const uint8_t *)orig.c_str(), orig.size(), nullptr,
729             COMPRESSION_LZMA);
730       }
731       if (compression_type == compression_types::lzfse) {
732         compressed_size = compression_encode_buffer(
733             encoded_data.data(), encoded_data_buf_size,
734             (const uint8_t *)orig.c_str(), orig.size(), nullptr,
735             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             strlcpy (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         const uint8_t *u_thread_name = (const 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       strlcpy(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) {
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 = const_cast<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 (strstr(p, "type:zlib-deflate;") != nullptr) {
4311     EnableCompressionNextSendPacket(compression_types::zlib_deflate);
4312     m_compression_minsize = new_compression_minsize;
4313     return SendPacket("OK");
4314   } else if (strstr(p, "type:lz4;") != nullptr) {
4315     EnableCompressionNextSendPacket(compression_types::lz4);
4316     m_compression_minsize = new_compression_minsize;
4317     return SendPacket("OK");
4318   } else if (strstr(p, "type:lzma;") != nullptr) {
4319     EnableCompressionNextSendPacket(compression_types::lzma);
4320     m_compression_minsize = new_compression_minsize;
4321     return SendPacket("OK");
4322   } else if (strstr(p, "type:lzfse;") != nullptr) {
4323     EnableCompressionNextSendPacket(compression_types::lzfse);
4324     m_compression_minsize = new_compression_minsize;
4325     return SendPacket("OK");
4326   }
4327 #endif
4328 
4329 #if defined(HAVE_LIBZ)
4330   if (strstr(p, "type:zlib-deflate;") != nullptr) {
4331     EnableCompressionNextSendPacket(compression_types::zlib_deflate);
4332     m_compression_minsize = new_compression_minsize;
4333     return SendPacket("OK");
4334   }
4335 #endif
4336 
4337   return SendPacket("E88");
4338 }
4339 
4340 rnb_err_t RNBRemote::HandlePacket_qSpeedTest(const char *p) {
4341   p += strlen("qSpeedTest:response_size:");
4342   char *end = NULL;
4343   errno = 0;
4344   uint64_t response_size = ::strtoul(p, &end, 16);
4345   if (errno != 0)
4346     return HandlePacket_ILLFORMED(
4347         __FILE__, __LINE__, p,
4348         "Didn't find response_size value at right offset");
4349   else if (*end == ';') {
4350     static char g_data[4 * 1024 * 1024 + 16] = "data:";
4351     memset(g_data + 5, 'a', response_size);
4352     g_data[response_size + 5] = '\0';
4353     return SendPacket(g_data);
4354   } else {
4355     return SendPacket("E79");
4356   }
4357 }
4358 
4359 rnb_err_t RNBRemote::HandlePacket_WatchpointSupportInfo(const char *p) {
4360   /* This packet simply returns the number of supported hardware watchpoints.
4361 
4362      Examples of use:
4363         qWatchpointSupportInfo:
4364         num:4
4365 
4366         qWatchpointSupportInfo
4367         OK                   // this packet is implemented by the remote nub
4368   */
4369 
4370   p += sizeof("qWatchpointSupportInfo") - 1;
4371   if (*p == '\0')
4372     return SendPacket("OK");
4373   if (*p++ != ':')
4374     return SendPacket("E67");
4375 
4376   errno = 0;
4377   uint32_t num = DNBWatchpointGetNumSupportedHWP(m_ctx.ProcessID());
4378   std::ostringstream ostrm;
4379 
4380   // size:4
4381   ostrm << "num:" << std::dec << num << ';';
4382   return SendPacket(ostrm.str());
4383 }
4384 
4385 /* 'C sig [;addr]'
4386  Resume with signal sig, optionally at address addr.  */
4387 
4388 rnb_err_t RNBRemote::HandlePacket_C(const char *p) {
4389   const nub_process_t pid = m_ctx.ProcessID();
4390 
4391   if (pid == INVALID_NUB_PROCESS)
4392     return SendPacket("E36");
4393 
4394   DNBThreadResumeAction action = {INVALID_NUB_THREAD, eStateRunning, 0,
4395                                   INVALID_NUB_ADDRESS};
4396   int process_signo = -1;
4397   if (*(p + 1) != '\0') {
4398     action.tid = GetContinueThread();
4399     char *end = NULL;
4400     errno = 0;
4401     process_signo = static_cast<int>(strtoul(p + 1, &end, 16));
4402     if (errno != 0)
4403       return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4404                                     "Could not parse signal in C packet");
4405     else if (*end == ';') {
4406       errno = 0;
4407       action.addr = strtoull(end + 1, NULL, 16);
4408       if (errno != 0 && action.addr == 0)
4409         return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4410                                       "Could not parse address in C packet");
4411     }
4412   }
4413 
4414   DNBThreadResumeActions thread_actions;
4415   thread_actions.Append(action);
4416   thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, action.signal);
4417   if (!DNBProcessSignal(pid, process_signo))
4418     return SendPacket("E52");
4419   if (!DNBProcessResume(pid, thread_actions.GetFirst(),
4420                         thread_actions.GetSize()))
4421     return SendPacket("E38");
4422   /* Don't send an "OK" packet; response is the stopped/exited message.  */
4423   return rnb_success;
4424 }
4425 
4426 //----------------------------------------------------------------------
4427 // 'D' packet
4428 // Detach from gdb.
4429 //----------------------------------------------------------------------
4430 rnb_err_t RNBRemote::HandlePacket_D(const char *p) {
4431   if (m_ctx.HasValidProcessID()) {
4432     if (DNBProcessDetach(m_ctx.ProcessID()))
4433       SendPacket("OK");
4434     else
4435       SendPacket("E");
4436   } else {
4437     SendPacket("E");
4438   }
4439   return rnb_success;
4440 }
4441 
4442 /* 'k'
4443  Kill the inferior process.  */
4444 
4445 rnb_err_t RNBRemote::HandlePacket_k(const char *p) {
4446   DNBLog("Got a 'k' packet, killing the inferior process.");
4447   // No response to should be sent to the kill packet
4448   if (m_ctx.HasValidProcessID())
4449     DNBProcessKill(m_ctx.ProcessID());
4450   SendPacket("X09");
4451   return rnb_success;
4452 }
4453 
4454 rnb_err_t RNBRemote::HandlePacket_stop_process(const char *p) {
4455 //#define TEST_EXIT_ON_INTERRUPT // This should only be uncommented to test
4456 //exiting on interrupt
4457 #if defined(TEST_EXIT_ON_INTERRUPT)
4458   rnb_err_t err = HandlePacket_k(p);
4459   m_comm.Disconnect(true);
4460   return err;
4461 #else
4462   if (!DNBProcessInterrupt(m_ctx.ProcessID())) {
4463     // If we failed to interrupt the process, then send a stop
4464     // reply packet as the process was probably already stopped
4465     DNBLogThreaded("RNBRemote::HandlePacket_stop_process() sending extra stop "
4466                    "reply because DNBProcessInterrupt returned false");
4467     HandlePacket_last_signal(NULL);
4468   }
4469   return rnb_success;
4470 #endif
4471 }
4472 
4473 /* 's'
4474  Step the inferior process.  */
4475 
4476 rnb_err_t RNBRemote::HandlePacket_s(const char *p) {
4477   const nub_process_t pid = m_ctx.ProcessID();
4478   if (pid == INVALID_NUB_PROCESS)
4479     return SendPacket("E32");
4480 
4481   // Hardware supported stepping not supported on arm
4482   nub_thread_t tid = GetContinueThread();
4483   if (tid == 0 || tid == (nub_thread_t)-1)
4484     tid = GetCurrentThread();
4485 
4486   if (tid == INVALID_NUB_THREAD)
4487     return SendPacket("E33");
4488 
4489   DNBThreadResumeActions thread_actions;
4490   thread_actions.AppendAction(tid, eStateStepping);
4491 
4492   // Make all other threads stop when we are stepping
4493   thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
4494   if (!DNBProcessResume(pid, thread_actions.GetFirst(),
4495                         thread_actions.GetSize()))
4496     return SendPacket("E49");
4497   // Don't send an "OK" packet; response is the stopped/exited message.
4498   return rnb_success;
4499 }
4500 
4501 /* 'S sig [;addr]'
4502  Step with signal sig, optionally at address addr.  */
4503 
4504 rnb_err_t RNBRemote::HandlePacket_S(const char *p) {
4505   const nub_process_t pid = m_ctx.ProcessID();
4506   if (pid == INVALID_NUB_PROCESS)
4507     return SendPacket("E36");
4508 
4509   DNBThreadResumeAction action = {INVALID_NUB_THREAD, eStateStepping, 0,
4510                                   INVALID_NUB_ADDRESS};
4511 
4512   if (*(p + 1) != '\0') {
4513     char *end = NULL;
4514     errno = 0;
4515     action.signal = static_cast<int>(strtoul(p + 1, &end, 16));
4516     if (errno != 0)
4517       return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4518                                     "Could not parse signal in S packet");
4519     else if (*end == ';') {
4520       errno = 0;
4521       action.addr = strtoull(end + 1, NULL, 16);
4522       if (errno != 0 && action.addr == 0) {
4523         return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4524                                       "Could not parse address in S packet");
4525       }
4526     }
4527   }
4528 
4529   action.tid = GetContinueThread();
4530   if (action.tid == 0 || action.tid == (nub_thread_t)-1)
4531     return SendPacket("E40");
4532 
4533   nub_state_t tstate = DNBThreadGetState(pid, action.tid);
4534   if (tstate == eStateInvalid || tstate == eStateExited)
4535     return SendPacket("E37");
4536 
4537   DNBThreadResumeActions thread_actions;
4538   thread_actions.Append(action);
4539 
4540   // Make all other threads stop when we are stepping
4541   thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
4542   if (!DNBProcessResume(pid, thread_actions.GetFirst(),
4543                         thread_actions.GetSize()))
4544     return SendPacket("E39");
4545 
4546   // Don't send an "OK" packet; response is the stopped/exited message.
4547   return rnb_success;
4548 }
4549 
4550 static const char *GetArchName(const uint32_t cputype,
4551                                const uint32_t cpusubtype) {
4552   switch (cputype) {
4553   case CPU_TYPE_ARM:
4554     switch (cpusubtype) {
4555     case 5:
4556       return "armv4";
4557     case 6:
4558       return "armv6";
4559     case 7:
4560       return "armv5t";
4561     case 8:
4562       return "xscale";
4563     case 9:
4564       return "armv7";
4565     case 10:
4566       return "armv7f";
4567     case 11:
4568       return "armv7s";
4569     case 12:
4570       return "armv7k";
4571     case 14:
4572       return "armv6m";
4573     case 15:
4574       return "armv7m";
4575     case 16:
4576       return "armv7em";
4577     default:
4578       return "arm";
4579     }
4580     break;
4581   case CPU_TYPE_ARM64:
4582     return "arm64";
4583   case CPU_TYPE_I386:
4584     return "i386";
4585   case CPU_TYPE_X86_64:
4586     switch (cpusubtype) {
4587     default:
4588       return "x86_64";
4589     case 8:
4590       return "x86_64h";
4591     }
4592     break;
4593   }
4594   return NULL;
4595 }
4596 
4597 static bool GetHostCPUType(uint32_t &cputype, uint32_t &cpusubtype,
4598                            uint32_t &is_64_bit_capable, bool &promoted_to_64) {
4599   static uint32_t g_host_cputype = 0;
4600   static uint32_t g_host_cpusubtype = 0;
4601   static uint32_t g_is_64_bit_capable = 0;
4602   static bool g_promoted_to_64 = false;
4603 
4604   if (g_host_cputype == 0) {
4605     g_promoted_to_64 = false;
4606     size_t len = sizeof(uint32_t);
4607     if (::sysctlbyname("hw.cputype", &g_host_cputype, &len, NULL, 0) == 0) {
4608       len = sizeof(uint32_t);
4609       if (::sysctlbyname("hw.cpu64bit_capable", &g_is_64_bit_capable, &len,
4610                          NULL, 0) == 0) {
4611         if (g_is_64_bit_capable && ((g_host_cputype & CPU_ARCH_ABI64) == 0)) {
4612           g_promoted_to_64 = true;
4613           g_host_cputype |= CPU_ARCH_ABI64;
4614         }
4615       }
4616     }
4617 
4618     len = sizeof(uint32_t);
4619     if (::sysctlbyname("hw.cpusubtype", &g_host_cpusubtype, &len, NULL, 0) ==
4620         0) {
4621       if (g_promoted_to_64 && g_host_cputype == CPU_TYPE_X86_64 &&
4622           g_host_cpusubtype == CPU_SUBTYPE_486)
4623         g_host_cpusubtype = CPU_SUBTYPE_X86_64_ALL;
4624     }
4625   }
4626 
4627   cputype = g_host_cputype;
4628   cpusubtype = g_host_cpusubtype;
4629   is_64_bit_capable = g_is_64_bit_capable;
4630   promoted_to_64 = g_promoted_to_64;
4631   return g_host_cputype != 0;
4632 }
4633 
4634 rnb_err_t RNBRemote::HandlePacket_qHostInfo(const char *p) {
4635   std::ostringstream strm;
4636 
4637   uint32_t cputype = 0;
4638   uint32_t cpusubtype = 0;
4639   uint32_t is_64_bit_capable = 0;
4640   bool promoted_to_64 = false;
4641   if (GetHostCPUType(cputype, cpusubtype, is_64_bit_capable, promoted_to_64)) {
4642     strm << "cputype:" << std::dec << cputype << ';';
4643     strm << "cpusubtype:" << std::dec << cpusubtype << ';';
4644   }
4645 
4646   // The OS in the triple should be "ios" or "macosx" which doesn't match our
4647   // "Darwin" which gets returned from "kern.ostype", so we need to hardcode
4648   // this for now.
4649   if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64) {
4650 #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
4651     strm << "ostype:tvos;";
4652 #elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
4653     strm << "ostype:watchos;";
4654 #else
4655     strm << "ostype:ios;";
4656 #endif
4657 
4658     // On armv7 we use "synchronous" watchpoints which means the exception is
4659     // delivered before the instruction executes.
4660     strm << "watchpoint_exceptions_received:before;";
4661   } else {
4662     strm << "ostype:macosx;";
4663     strm << "watchpoint_exceptions_received:after;";
4664   }
4665   //    char ostype[64];
4666   //    len = sizeof(ostype);
4667   //    if (::sysctlbyname("kern.ostype", &ostype, &len, NULL, 0) == 0)
4668   //    {
4669   //        len = strlen(ostype);
4670   //        std::transform (ostype, ostype + len, ostype, tolower);
4671   //        strm << "ostype:" << std::dec << ostype << ';';
4672   //    }
4673 
4674   strm << "vendor:apple;";
4675 
4676   uint64_t major, minor, patch;
4677   if (DNBGetOSVersionNumbers(&major, &minor, &patch)) {
4678     strm << "os_version:" << major << "." << minor;
4679     if (patch != UINT64_MAX)
4680       strm << "." << patch;
4681     strm << ";";
4682   }
4683 
4684 #if defined(__LITTLE_ENDIAN__)
4685   strm << "endian:little;";
4686 #elif defined(__BIG_ENDIAN__)
4687   strm << "endian:big;";
4688 #elif defined(__PDP_ENDIAN__)
4689   strm << "endian:pdp;";
4690 #endif
4691 
4692   if (promoted_to_64)
4693     strm << "ptrsize:8;";
4694   else
4695     strm << "ptrsize:" << std::dec << sizeof(void *) << ';';
4696 
4697 #if defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
4698   strm << "default_packet_timeout:10;";
4699 #endif
4700 
4701   return SendPacket(strm.str());
4702 }
4703 
4704 void XMLElementStart(std::ostringstream &s, uint32_t indent, const char *name,
4705                      bool has_attributes) {
4706   if (indent)
4707     s << INDENT_WITH_SPACES(indent);
4708   s << '<' << name;
4709   if (!has_attributes)
4710     s << '>' << std::endl;
4711 }
4712 
4713 void XMLElementStartEndAttributes(std::ostringstream &s, bool empty) {
4714   if (empty)
4715     s << '/';
4716   s << '>' << std::endl;
4717 }
4718 
4719 void XMLElementEnd(std::ostringstream &s, uint32_t indent, const char *name) {
4720   if (indent)
4721     s << INDENT_WITH_SPACES(indent);
4722   s << '<' << '/' << name << '>' << std::endl;
4723 }
4724 
4725 void XMLElementWithStringValue(std::ostringstream &s, uint32_t indent,
4726                                const char *name, const char *value,
4727                                bool close = true) {
4728   if (value) {
4729     if (indent)
4730       s << INDENT_WITH_SPACES(indent);
4731     s << '<' << name << '>' << value;
4732     if (close)
4733       XMLElementEnd(s, 0, name);
4734   }
4735 }
4736 
4737 void XMLElementWithUnsignedValue(std::ostringstream &s, uint32_t indent,
4738                                  const char *name, uint64_t value,
4739                                  bool close = true) {
4740   if (indent)
4741     s << INDENT_WITH_SPACES(indent);
4742 
4743   s << '<' << name << '>' << DECIMAL << value;
4744   if (close)
4745     XMLElementEnd(s, 0, name);
4746 }
4747 
4748 void XMLAttributeString(std::ostringstream &s, const char *name,
4749                         const char *value, const char *default_value = NULL) {
4750   if (value) {
4751     if (default_value && strcmp(value, default_value) == 0)
4752       return; // No need to emit the attribute because it matches the default
4753               // value
4754     s << ' ' << name << "=\"" << value << "\"";
4755   }
4756 }
4757 
4758 void XMLAttributeUnsignedDecimal(std::ostringstream &s, const char *name,
4759                                  uint64_t value) {
4760   s << ' ' << name << "=\"" << DECIMAL << value << "\"";
4761 }
4762 
4763 void GenerateTargetXMLRegister(std::ostringstream &s, const uint32_t reg_num,
4764                                nub_size_t num_reg_sets,
4765                                const DNBRegisterSetInfo *reg_set_info,
4766                                const register_map_entry_t &reg) {
4767   const char *default_lldb_encoding = "uint";
4768   const char *lldb_encoding = default_lldb_encoding;
4769   const char *gdb_group = "general";
4770   const char *default_gdb_type = "int";
4771   const char *gdb_type = default_gdb_type;
4772   const char *default_lldb_format = "hex";
4773   const char *lldb_format = default_lldb_format;
4774   const char *lldb_set = NULL;
4775 
4776   switch (reg.nub_info.type) {
4777   case Uint:
4778     lldb_encoding = "uint";
4779     break;
4780   case Sint:
4781     lldb_encoding = "sint";
4782     break;
4783   case IEEE754:
4784     lldb_encoding = "ieee754";
4785     if (reg.nub_info.set > 0)
4786       gdb_group = "float";
4787     break;
4788   case Vector:
4789     lldb_encoding = "vector";
4790     if (reg.nub_info.set > 0)
4791       gdb_group = "vector";
4792     break;
4793   }
4794 
4795   switch (reg.nub_info.format) {
4796   case Binary:
4797     lldb_format = "binary";
4798     break;
4799   case Decimal:
4800     lldb_format = "decimal";
4801     break;
4802   case Hex:
4803     lldb_format = "hex";
4804     break;
4805   case Float:
4806     gdb_type = "float";
4807     lldb_format = "float";
4808     break;
4809   case VectorOfSInt8:
4810     gdb_type = "float";
4811     lldb_format = "vector-sint8";
4812     break;
4813   case VectorOfUInt8:
4814     gdb_type = "float";
4815     lldb_format = "vector-uint8";
4816     break;
4817   case VectorOfSInt16:
4818     gdb_type = "float";
4819     lldb_format = "vector-sint16";
4820     break;
4821   case VectorOfUInt16:
4822     gdb_type = "float";
4823     lldb_format = "vector-uint16";
4824     break;
4825   case VectorOfSInt32:
4826     gdb_type = "float";
4827     lldb_format = "vector-sint32";
4828     break;
4829   case VectorOfUInt32:
4830     gdb_type = "float";
4831     lldb_format = "vector-uint32";
4832     break;
4833   case VectorOfFloat32:
4834     gdb_type = "float";
4835     lldb_format = "vector-float32";
4836     break;
4837   case VectorOfUInt128:
4838     gdb_type = "float";
4839     lldb_format = "vector-uint128";
4840     break;
4841   };
4842   if (reg_set_info && reg.nub_info.set < num_reg_sets)
4843     lldb_set = reg_set_info[reg.nub_info.set].name;
4844 
4845   uint32_t indent = 2;
4846 
4847   XMLElementStart(s, indent, "reg", true);
4848   XMLAttributeString(s, "name", reg.nub_info.name);
4849   XMLAttributeUnsignedDecimal(s, "regnum", reg_num);
4850   XMLAttributeUnsignedDecimal(s, "offset", reg.offset);
4851   XMLAttributeUnsignedDecimal(s, "bitsize", reg.nub_info.size * 8);
4852   XMLAttributeString(s, "group", gdb_group);
4853   XMLAttributeString(s, "type", gdb_type, default_gdb_type);
4854   XMLAttributeString(s, "altname", reg.nub_info.alt);
4855   XMLAttributeString(s, "encoding", lldb_encoding, default_lldb_encoding);
4856   XMLAttributeString(s, "format", lldb_format, default_lldb_format);
4857   XMLAttributeUnsignedDecimal(s, "group_id", reg.nub_info.set);
4858   if (reg.nub_info.reg_ehframe != INVALID_NUB_REGNUM)
4859     XMLAttributeUnsignedDecimal(s, "ehframe_regnum", reg.nub_info.reg_ehframe);
4860   if (reg.nub_info.reg_dwarf != INVALID_NUB_REGNUM)
4861     XMLAttributeUnsignedDecimal(s, "dwarf_regnum", reg.nub_info.reg_dwarf);
4862 
4863   const char *lldb_generic = NULL;
4864   switch (reg.nub_info.reg_generic) {
4865   case GENERIC_REGNUM_FP:
4866     lldb_generic = "fp";
4867     break;
4868   case GENERIC_REGNUM_PC:
4869     lldb_generic = "pc";
4870     break;
4871   case GENERIC_REGNUM_SP:
4872     lldb_generic = "sp";
4873     break;
4874   case GENERIC_REGNUM_RA:
4875     lldb_generic = "ra";
4876     break;
4877   case GENERIC_REGNUM_FLAGS:
4878     lldb_generic = "flags";
4879     break;
4880   case GENERIC_REGNUM_ARG1:
4881     lldb_generic = "arg1";
4882     break;
4883   case GENERIC_REGNUM_ARG2:
4884     lldb_generic = "arg2";
4885     break;
4886   case GENERIC_REGNUM_ARG3:
4887     lldb_generic = "arg3";
4888     break;
4889   case GENERIC_REGNUM_ARG4:
4890     lldb_generic = "arg4";
4891     break;
4892   case GENERIC_REGNUM_ARG5:
4893     lldb_generic = "arg5";
4894     break;
4895   case GENERIC_REGNUM_ARG6:
4896     lldb_generic = "arg6";
4897     break;
4898   case GENERIC_REGNUM_ARG7:
4899     lldb_generic = "arg7";
4900     break;
4901   case GENERIC_REGNUM_ARG8:
4902     lldb_generic = "arg8";
4903     break;
4904   default:
4905     break;
4906   }
4907   XMLAttributeString(s, "generic", lldb_generic);
4908 
4909   bool empty = reg.value_regnums.empty() && reg.invalidate_regnums.empty();
4910   if (!empty) {
4911     if (!reg.value_regnums.empty()) {
4912       std::ostringstream regnums;
4913       bool first = true;
4914       regnums << DECIMAL;
4915       for (auto regnum : reg.value_regnums) {
4916         if (!first)
4917           regnums << ',';
4918         regnums << regnum;
4919         first = false;
4920       }
4921       XMLAttributeString(s, "value_regnums", regnums.str().c_str());
4922     }
4923 
4924     if (!reg.invalidate_regnums.empty()) {
4925       std::ostringstream regnums;
4926       bool first = true;
4927       regnums << DECIMAL;
4928       for (auto regnum : reg.invalidate_regnums) {
4929         if (!first)
4930           regnums << ',';
4931         regnums << regnum;
4932         first = false;
4933       }
4934       XMLAttributeString(s, "invalidate_regnums", regnums.str().c_str());
4935     }
4936   }
4937   XMLElementStartEndAttributes(s, true);
4938 }
4939 
4940 void GenerateTargetXMLRegisters(std::ostringstream &s) {
4941   nub_size_t num_reg_sets = 0;
4942   const DNBRegisterSetInfo *reg_sets = DNBGetRegisterSetInfo(&num_reg_sets);
4943 
4944   uint32_t cputype = DNBGetRegisterCPUType();
4945   if (cputype) {
4946     XMLElementStart(s, 0, "feature", true);
4947     std::ostringstream name_strm;
4948     name_strm << "com.apple.debugserver." << GetArchName(cputype, 0);
4949     XMLAttributeString(s, "name", name_strm.str().c_str());
4950     XMLElementStartEndAttributes(s, false);
4951     for (uint32_t reg_num = 0; reg_num < g_num_reg_entries; ++reg_num)
4952     //        for (const auto &reg: g_dynamic_register_map)
4953     {
4954       GenerateTargetXMLRegister(s, reg_num, num_reg_sets, reg_sets,
4955                                 g_reg_entries[reg_num]);
4956     }
4957     XMLElementEnd(s, 0, "feature");
4958 
4959     if (num_reg_sets > 0) {
4960       XMLElementStart(s, 0, "groups", false);
4961       for (uint32_t set = 1; set < num_reg_sets; ++set) {
4962         XMLElementStart(s, 2, "group", true);
4963         XMLAttributeUnsignedDecimal(s, "id", set);
4964         XMLAttributeString(s, "name", reg_sets[set].name);
4965         XMLElementStartEndAttributes(s, true);
4966       }
4967       XMLElementEnd(s, 0, "groups");
4968     }
4969   }
4970 }
4971 
4972 static const char *g_target_xml_header = R"(<?xml version="1.0"?>
4973 <target version="1.0">)";
4974 
4975 static const char *g_target_xml_footer = "</target>";
4976 
4977 static std::string g_target_xml;
4978 
4979 void UpdateTargetXML() {
4980   std::ostringstream s;
4981   s << g_target_xml_header << std::endl;
4982 
4983   // Set the architecture
4984   //
4985   // On raw targets (no OS, vendor info), I've seen replies like
4986   // <architecture>i386:x86-64</architecture> (for x86_64 systems - from vmware)
4987   // <architecture>arm</architecture> (for an unspecified arm device - from a Segger JLink)
4988   // For good interop, I'm not sure what's expected here.  e.g. will anyone understand
4989   // <architecture>x86_64</architecture> ? Or is i386:x86_64 the expected phrasing?
4990   //
4991   // s << "<architecture>" << arch "</architecture>" << std::endl;
4992 
4993   // Set the OSABI
4994   // s << "<osabi>abi-name</osabi>"
4995 
4996   GenerateTargetXMLRegisters(s);
4997 
4998   s << g_target_xml_footer << std::endl;
4999 
5000   // Save the XML output in case it gets retrieved in chunks
5001   g_target_xml = s.str();
5002 }
5003 
5004 rnb_err_t RNBRemote::HandlePacket_qXfer(const char *command) {
5005   const char *p = command;
5006   p += strlen("qXfer:");
5007   const char *sep = strchr(p, ':');
5008   if (sep) {
5009     std::string object(p, sep - p); // "auxv", "backtrace", "features", etc
5010     p = sep + 1;
5011     sep = strchr(p, ':');
5012     if (sep) {
5013       std::string rw(p, sep - p); // "read" or "write"
5014       p = sep + 1;
5015       sep = strchr(p, ':');
5016       if (sep) {
5017         std::string annex(p, sep - p); // "read" or "write"
5018 
5019         p = sep + 1;
5020         sep = strchr(p, ',');
5021         if (sep) {
5022           std::string offset_str(p, sep - p); // read the length as a string
5023           p = sep + 1;
5024           std::string length_str(p); // read the offset as a string
5025           char *end = nullptr;
5026           const uint64_t offset = strtoul(offset_str.c_str(), &end,
5027                                           16); // convert offset_str to a offset
5028           if (*end == '\0') {
5029             const uint64_t length = strtoul(
5030                 length_str.c_str(), &end, 16); // convert length_str to a length
5031             if (*end == '\0') {
5032               if (object == "features" && rw == "read" &&
5033                   annex == "target.xml") {
5034                 std::ostringstream xml_out;
5035 
5036                 if (offset == 0) {
5037                   InitializeRegisters(true);
5038 
5039                   UpdateTargetXML();
5040                   if (g_target_xml.empty())
5041                     return SendPacket("E83");
5042 
5043                   if (length > g_target_xml.size()) {
5044                     xml_out << 'l'; // No more data
5045                     xml_out << binary_encode_string(g_target_xml);
5046                   } else {
5047                     xml_out << 'm'; // More data needs to be read with a
5048                                     // subsequent call
5049                     xml_out << binary_encode_string(
5050                         std::string(g_target_xml, offset, length));
5051                   }
5052                 } else {
5053                   // Retrieving target XML in chunks
5054                   if (offset < g_target_xml.size()) {
5055                     std::string chunk(g_target_xml, offset, length);
5056                     if (chunk.size() < length)
5057                       xml_out << 'l'; // No more data
5058                     else
5059                       xml_out << 'm'; // More data needs to be read with a
5060                                       // subsequent call
5061                     xml_out << binary_encode_string(chunk.data());
5062                   }
5063                 }
5064                 return SendPacket(xml_out.str());
5065               }
5066               // Well formed, put not supported
5067               return HandlePacket_UNIMPLEMENTED(command);
5068             }
5069           }
5070         }
5071       } else {
5072         SendPacket("E85");
5073       }
5074     } else {
5075       SendPacket("E86");
5076     }
5077   }
5078   return SendPacket("E82");
5079 }
5080 
5081 rnb_err_t RNBRemote::HandlePacket_qGDBServerVersion(const char *p) {
5082   std::ostringstream strm;
5083 
5084 #if defined(DEBUGSERVER_PROGRAM_NAME)
5085   strm << "name:" DEBUGSERVER_PROGRAM_NAME ";";
5086 #else
5087   strm << "name:debugserver;";
5088 #endif
5089   strm << "version:" << DEBUGSERVER_VERSION_NUM << ";";
5090 
5091   return SendPacket(strm.str());
5092 }
5093 
5094 // A helper function that retrieves a single integer value from
5095 // a one-level-deep JSON dictionary of key-value pairs.  e.g.
5096 // jThreadExtendedInfo:{"plo_pthread_tsd_base_address_offset":0,"plo_pthread_tsd_base_offset":224,"plo_pthread_tsd_entry_size":8,"thread":144305}]
5097 //
5098 uint64_t get_integer_value_for_key_name_from_json(const char *key,
5099                                                   const char *json_string) {
5100   uint64_t retval = INVALID_NUB_ADDRESS;
5101   std::string key_with_quotes = "\"";
5102   key_with_quotes += key;
5103   key_with_quotes += "\"";
5104   const char *c = strstr(json_string, key_with_quotes.c_str());
5105   if (c) {
5106     c += key_with_quotes.size();
5107 
5108     while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5109       c++;
5110 
5111     if (*c == ':') {
5112       c++;
5113 
5114       while (*c != '\0' &&
5115              (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5116         c++;
5117 
5118       errno = 0;
5119       retval = strtoul(c, NULL, 10);
5120       if (errno != 0) {
5121         retval = INVALID_NUB_ADDRESS;
5122       }
5123     }
5124   }
5125   return retval;
5126 }
5127 
5128 // A helper function that retrieves a boolean value from
5129 // a one-level-deep JSON dictionary of key-value pairs.  e.g.
5130 // jGetLoadedDynamicLibrariesInfos:{"fetch_all_solibs":true}]
5131 
5132 // Returns true if it was able to find the key name, and sets the 'value'
5133 // argument to the value found.
5134 
5135 bool get_boolean_value_for_key_name_from_json(const char *key,
5136                                               const char *json_string,
5137                                               bool &value) {
5138   std::string key_with_quotes = "\"";
5139   key_with_quotes += key;
5140   key_with_quotes += "\"";
5141   const char *c = strstr(json_string, key_with_quotes.c_str());
5142   if (c) {
5143     c += key_with_quotes.size();
5144 
5145     while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5146       c++;
5147 
5148     if (*c == ':') {
5149       c++;
5150 
5151       while (*c != '\0' &&
5152              (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5153         c++;
5154 
5155       if (strncmp(c, "true", 4) == 0) {
5156         value = true;
5157         return true;
5158       } else if (strncmp(c, "false", 5) == 0) {
5159         value = false;
5160         return true;
5161       }
5162     }
5163   }
5164   return false;
5165 }
5166 
5167 // A helper function that reads an array of uint64_t's from
5168 // a one-level-deep JSON dictionary of key-value pairs.  e.g.
5169 // jGetLoadedDynamicLibrariesInfos:{"solib_addrs":[31345823,7768020384,7310483024]}]
5170 
5171 // Returns true if it was able to find the key name, false if it did not.
5172 // "ints" will have all integers found in the array appended to it.
5173 
5174 bool get_array_of_ints_value_for_key_name_from_json(
5175     const char *key, const char *json_string, std::vector<uint64_t> &ints) {
5176   std::string key_with_quotes = "\"";
5177   key_with_quotes += key;
5178   key_with_quotes += "\"";
5179   const char *c = strstr(json_string, key_with_quotes.c_str());
5180   if (c) {
5181     c += key_with_quotes.size();
5182 
5183     while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5184       c++;
5185 
5186     if (*c == ':') {
5187       c++;
5188 
5189       while (*c != '\0' &&
5190              (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5191         c++;
5192 
5193       if (*c == '[') {
5194         c++;
5195         while (*c != '\0' &&
5196                (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5197           c++;
5198         while (1) {
5199           if (!isdigit(*c)) {
5200             return true;
5201           }
5202 
5203           errno = 0;
5204           char *endptr;
5205           uint64_t value = strtoul(c, &endptr, 10);
5206           if (errno == 0) {
5207             ints.push_back(value);
5208           } else {
5209             break;
5210           }
5211           if (endptr == c || endptr == nullptr || *endptr == '\0') {
5212             break;
5213           }
5214           c = endptr;
5215 
5216           while (*c != '\0' &&
5217                  (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5218             c++;
5219           if (*c == ',')
5220             c++;
5221           while (*c != '\0' &&
5222                  (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5223             c++;
5224           if (*c == ']') {
5225             return true;
5226           }
5227         }
5228       }
5229     }
5230   }
5231   return false;
5232 }
5233 
5234 JSONGenerator::ObjectSP
5235 RNBRemote::GetJSONThreadsInfo(bool threads_with_valid_stop_info_only) {
5236   JSONGenerator::ArraySP threads_array_sp;
5237   if (m_ctx.HasValidProcessID()) {
5238     threads_array_sp.reset(new JSONGenerator::Array());
5239 
5240     nub_process_t pid = m_ctx.ProcessID();
5241 
5242     nub_size_t numthreads = DNBProcessGetNumThreads(pid);
5243     for (nub_size_t i = 0; i < numthreads; ++i) {
5244       nub_thread_t tid = DNBProcessGetThreadAtIndex(pid, i);
5245 
5246       struct DNBThreadStopInfo tid_stop_info;
5247 
5248       const bool stop_info_valid =
5249           DNBThreadGetStopReason(pid, tid, &tid_stop_info);
5250 
5251       // If we are doing stop info only, then we only show threads that have a
5252       // valid stop reason
5253       if (threads_with_valid_stop_info_only) {
5254         if (!stop_info_valid || tid_stop_info.reason == eStopTypeInvalid)
5255           continue;
5256       }
5257 
5258       JSONGenerator::DictionarySP thread_dict_sp(
5259           new JSONGenerator::Dictionary());
5260       thread_dict_sp->AddIntegerItem("tid", tid);
5261 
5262       std::string reason_value("none");
5263 
5264       if (stop_info_valid) {
5265         switch (tid_stop_info.reason) {
5266         case eStopTypeInvalid:
5267           break;
5268 
5269         case eStopTypeSignal:
5270           if (tid_stop_info.details.signal.signo != 0) {
5271             thread_dict_sp->AddIntegerItem("signal",
5272                                            tid_stop_info.details.signal.signo);
5273             reason_value = "signal";
5274           }
5275           break;
5276 
5277         case eStopTypeException:
5278           if (tid_stop_info.details.exception.type != 0) {
5279             reason_value = "exception";
5280             thread_dict_sp->AddIntegerItem(
5281                 "metype", tid_stop_info.details.exception.type);
5282             JSONGenerator::ArraySP medata_array_sp(new JSONGenerator::Array());
5283             for (nub_size_t i = 0;
5284                  i < tid_stop_info.details.exception.data_count; ++i) {
5285               medata_array_sp->AddItem(
5286                   JSONGenerator::IntegerSP(new JSONGenerator::Integer(
5287                       tid_stop_info.details.exception.data[i])));
5288             }
5289             thread_dict_sp->AddItem("medata", medata_array_sp);
5290           }
5291           break;
5292 
5293         case eStopTypeExec:
5294           reason_value = "exec";
5295           break;
5296         }
5297       }
5298 
5299       thread_dict_sp->AddStringItem("reason", reason_value);
5300 
5301       if (threads_with_valid_stop_info_only == false) {
5302         const char *thread_name = DNBThreadGetName(pid, tid);
5303         if (thread_name && thread_name[0])
5304           thread_dict_sp->AddStringItem("name", thread_name);
5305 
5306         thread_identifier_info_data_t thread_ident_info;
5307         if (DNBThreadGetIdentifierInfo(pid, tid, &thread_ident_info)) {
5308           if (thread_ident_info.dispatch_qaddr != 0) {
5309             thread_dict_sp->AddIntegerItem("qaddr",
5310                                            thread_ident_info.dispatch_qaddr);
5311 
5312             const DispatchQueueOffsets *dispatch_queue_offsets =
5313                 GetDispatchQueueOffsets();
5314             if (dispatch_queue_offsets) {
5315               std::string queue_name;
5316               uint64_t queue_width = 0;
5317               uint64_t queue_serialnum = 0;
5318               nub_addr_t dispatch_queue_t = INVALID_NUB_ADDRESS;
5319               dispatch_queue_offsets->GetThreadQueueInfo(
5320                   pid, thread_ident_info.dispatch_qaddr, dispatch_queue_t,
5321                   queue_name, queue_width, queue_serialnum);
5322               if (dispatch_queue_t == 0 && queue_name.empty() &&
5323                   queue_serialnum == 0) {
5324                 thread_dict_sp->AddBooleanItem("associated_with_dispatch_queue",
5325                                                false);
5326               } else {
5327                 thread_dict_sp->AddBooleanItem("associated_with_dispatch_queue",
5328                                                true);
5329               }
5330               if (dispatch_queue_t != INVALID_NUB_ADDRESS &&
5331                   dispatch_queue_t != 0)
5332                 thread_dict_sp->AddIntegerItem("dispatch_queue_t",
5333                                                dispatch_queue_t);
5334               if (!queue_name.empty())
5335                 thread_dict_sp->AddStringItem("qname", queue_name);
5336               if (queue_width == 1)
5337                 thread_dict_sp->AddStringItem("qkind", "serial");
5338               else if (queue_width > 1)
5339                 thread_dict_sp->AddStringItem("qkind", "concurrent");
5340               if (queue_serialnum > 0)
5341                 thread_dict_sp->AddIntegerItem("qserialnum", queue_serialnum);
5342             }
5343           }
5344         }
5345 
5346         DNBRegisterValue reg_value;
5347 
5348         if (g_reg_entries != NULL) {
5349           JSONGenerator::DictionarySP registers_dict_sp(
5350               new JSONGenerator::Dictionary());
5351 
5352           for (uint32_t reg = 0; reg < g_num_reg_entries; reg++) {
5353             // Expedite all registers in the first register set that aren't
5354             // contained in other registers
5355             if (g_reg_entries[reg].nub_info.set == 1 &&
5356                 g_reg_entries[reg].nub_info.value_regs == NULL) {
5357               if (!DNBThreadGetRegisterValueByID(
5358                       pid, tid, g_reg_entries[reg].nub_info.set,
5359                       g_reg_entries[reg].nub_info.reg, &reg_value))
5360                 continue;
5361 
5362               std::ostringstream reg_num;
5363               reg_num << std::dec << g_reg_entries[reg].debugserver_regnum;
5364               // Encode native byte ordered bytes as hex ascii
5365               registers_dict_sp->AddBytesAsHexASCIIString(
5366                   reg_num.str(), reg_value.value.v_uint8,
5367                   g_reg_entries[reg].nub_info.size);
5368             }
5369           }
5370           thread_dict_sp->AddItem("registers", registers_dict_sp);
5371         }
5372 
5373         // Add expedited stack memory so stack backtracing doesn't need to read
5374         // anything from the
5375         // frame pointer chain.
5376         StackMemoryMap stack_mmap;
5377         ReadStackMemory(pid, tid, stack_mmap);
5378         if (!stack_mmap.empty()) {
5379           JSONGenerator::ArraySP memory_array_sp(new JSONGenerator::Array());
5380 
5381           for (const auto &stack_memory : stack_mmap) {
5382             JSONGenerator::DictionarySP stack_memory_sp(
5383                 new JSONGenerator::Dictionary());
5384             stack_memory_sp->AddIntegerItem("address", stack_memory.first);
5385             stack_memory_sp->AddBytesAsHexASCIIString(
5386                 "bytes", stack_memory.second.bytes, stack_memory.second.length);
5387             memory_array_sp->AddItem(stack_memory_sp);
5388           }
5389           thread_dict_sp->AddItem("memory", memory_array_sp);
5390         }
5391       }
5392 
5393       threads_array_sp->AddItem(thread_dict_sp);
5394     }
5395   }
5396   return threads_array_sp;
5397 }
5398 
5399 rnb_err_t RNBRemote::HandlePacket_jThreadsInfo(const char *p) {
5400   JSONGenerator::ObjectSP threads_info_sp;
5401   std::ostringstream json;
5402   std::ostringstream reply_strm;
5403   // If we haven't run the process yet, return an error.
5404   if (m_ctx.HasValidProcessID()) {
5405     const bool threads_with_valid_stop_info_only = false;
5406     JSONGenerator::ObjectSP threads_info_sp =
5407         GetJSONThreadsInfo(threads_with_valid_stop_info_only);
5408 
5409     if (threads_info_sp) {
5410       std::ostringstream strm;
5411       threads_info_sp->Dump(strm);
5412       std::string binary_packet = binary_encode_string(strm.str());
5413       if (!binary_packet.empty())
5414         return SendPacket(binary_packet.c_str());
5415     }
5416   }
5417   return SendPacket("E85");
5418 }
5419 
5420 rnb_err_t RNBRemote::HandlePacket_jThreadExtendedInfo(const char *p) {
5421   nub_process_t pid;
5422   std::ostringstream json;
5423   // If we haven't run the process yet, return an error.
5424   if (!m_ctx.HasValidProcessID()) {
5425     return SendPacket("E81");
5426   }
5427 
5428   pid = m_ctx.ProcessID();
5429 
5430   const char thread_extended_info_str[] = {"jThreadExtendedInfo:{"};
5431   if (strncmp(p, thread_extended_info_str,
5432               sizeof(thread_extended_info_str) - 1) == 0) {
5433     p += strlen(thread_extended_info_str);
5434 
5435     uint64_t tid = get_integer_value_for_key_name_from_json("thread", p);
5436     uint64_t plo_pthread_tsd_base_address_offset =
5437         get_integer_value_for_key_name_from_json(
5438             "plo_pthread_tsd_base_address_offset", p);
5439     uint64_t plo_pthread_tsd_base_offset =
5440         get_integer_value_for_key_name_from_json("plo_pthread_tsd_base_offset",
5441                                                  p);
5442     uint64_t plo_pthread_tsd_entry_size =
5443         get_integer_value_for_key_name_from_json("plo_pthread_tsd_entry_size",
5444                                                  p);
5445     uint64_t dti_qos_class_index =
5446         get_integer_value_for_key_name_from_json("dti_qos_class_index", p);
5447     // Commented out the two variables below as they are not being used
5448     //        uint64_t dti_queue_index =
5449     //        get_integer_value_for_key_name_from_json ("dti_queue_index", p);
5450     //        uint64_t dti_voucher_index =
5451     //        get_integer_value_for_key_name_from_json ("dti_voucher_index", p);
5452 
5453     if (tid != INVALID_NUB_ADDRESS) {
5454       nub_addr_t pthread_t_value = DNBGetPThreadT(pid, tid);
5455 
5456       uint64_t tsd_address = INVALID_NUB_ADDRESS;
5457       if (plo_pthread_tsd_entry_size != INVALID_NUB_ADDRESS &&
5458           plo_pthread_tsd_base_offset != INVALID_NUB_ADDRESS &&
5459           plo_pthread_tsd_entry_size != INVALID_NUB_ADDRESS) {
5460         tsd_address = DNBGetTSDAddressForThread(
5461             pid, tid, plo_pthread_tsd_base_address_offset,
5462             plo_pthread_tsd_base_offset, plo_pthread_tsd_entry_size);
5463       }
5464 
5465       bool timed_out = false;
5466       Genealogy::ThreadActivitySP thread_activity_sp;
5467 
5468       // If the pthread_t value is invalid, or if we were able to fetch the
5469       // thread's TSD base
5470       // and got an invalid value back, then we have a thread in early startup
5471       // or shutdown and
5472       // it's possible that gathering the genealogy information for this thread
5473       // go badly.
5474       // Ideally fetching this info for a thread in these odd states shouldn't
5475       // matter - but
5476       // we've seen some problems with these new SPI and threads in edge-casey
5477       // states.
5478 
5479       double genealogy_fetch_time = 0;
5480       if (pthread_t_value != INVALID_NUB_ADDRESS &&
5481           tsd_address != INVALID_NUB_ADDRESS) {
5482         DNBTimer timer(false);
5483         thread_activity_sp = DNBGetGenealogyInfoForThread(pid, tid, timed_out);
5484         genealogy_fetch_time = timer.ElapsedMicroSeconds(false) / 1000000.0;
5485       }
5486 
5487       std::unordered_set<uint32_t>
5488           process_info_indexes; // an array of the process info #'s seen
5489 
5490       json << "{";
5491 
5492       bool need_to_print_comma = false;
5493 
5494       if (thread_activity_sp && timed_out == false) {
5495         const Genealogy::Activity *activity =
5496             &thread_activity_sp->current_activity;
5497         bool need_vouchers_comma_sep = false;
5498         json << "\"activity_query_timed_out\":false,";
5499         if (genealogy_fetch_time != 0) {
5500           //  If we append the floating point value with << we'll get it in
5501           //  scientific
5502           //  notation.
5503           char floating_point_ascii_buffer[64];
5504           floating_point_ascii_buffer[0] = '\0';
5505           snprintf(floating_point_ascii_buffer,
5506                    sizeof(floating_point_ascii_buffer), "%f",
5507                    genealogy_fetch_time);
5508           if (strlen(floating_point_ascii_buffer) > 0) {
5509             if (need_to_print_comma)
5510               json << ",";
5511             need_to_print_comma = true;
5512             json << "\"activity_query_duration\":"
5513                  << floating_point_ascii_buffer;
5514           }
5515         }
5516         if (activity->activity_id != 0) {
5517           if (need_to_print_comma)
5518             json << ",";
5519           need_to_print_comma = true;
5520           need_vouchers_comma_sep = true;
5521           json << "\"activity\":{";
5522           json << "\"start\":" << activity->activity_start << ",";
5523           json << "\"id\":" << activity->activity_id << ",";
5524           json << "\"parent_id\":" << activity->parent_id << ",";
5525           json << "\"name\":\""
5526                << json_string_quote_metachars(activity->activity_name) << "\",";
5527           json << "\"reason\":\""
5528                << json_string_quote_metachars(activity->reason) << "\"";
5529           json << "}";
5530         }
5531         if (thread_activity_sp->messages.size() > 0) {
5532           need_to_print_comma = true;
5533           if (need_vouchers_comma_sep)
5534             json << ",";
5535           need_vouchers_comma_sep = true;
5536           json << "\"trace_messages\":[";
5537           bool printed_one_message = false;
5538           for (auto iter = thread_activity_sp->messages.begin();
5539                iter != thread_activity_sp->messages.end(); ++iter) {
5540             if (printed_one_message)
5541               json << ",";
5542             else
5543               printed_one_message = true;
5544             json << "{";
5545             json << "\"timestamp\":" << iter->timestamp << ",";
5546             json << "\"activity_id\":" << iter->activity_id << ",";
5547             json << "\"trace_id\":" << iter->trace_id << ",";
5548             json << "\"thread\":" << iter->thread << ",";
5549             json << "\"type\":" << (int)iter->type << ",";
5550             json << "\"process_info_index\":" << iter->process_info_index
5551                  << ",";
5552             process_info_indexes.insert(iter->process_info_index);
5553             json << "\"message\":\""
5554                  << json_string_quote_metachars(iter->message) << "\"";
5555             json << "}";
5556           }
5557           json << "]";
5558         }
5559         if (thread_activity_sp->breadcrumbs.size() == 1) {
5560           need_to_print_comma = true;
5561           if (need_vouchers_comma_sep)
5562             json << ",";
5563           need_vouchers_comma_sep = true;
5564           json << "\"breadcrumb\":{";
5565           for (auto iter = thread_activity_sp->breadcrumbs.begin();
5566                iter != thread_activity_sp->breadcrumbs.end(); ++iter) {
5567             json << "\"breadcrumb_id\":" << iter->breadcrumb_id << ",";
5568             json << "\"activity_id\":" << iter->activity_id << ",";
5569             json << "\"timestamp\":" << iter->timestamp << ",";
5570             json << "\"name\":\"" << json_string_quote_metachars(iter->name)
5571                  << "\"";
5572           }
5573           json << "}";
5574         }
5575         if (process_info_indexes.size() > 0) {
5576           need_to_print_comma = true;
5577           if (need_vouchers_comma_sep)
5578             json << ",";
5579           need_vouchers_comma_sep = true;
5580           bool printed_one_process_info = false;
5581           for (auto iter = process_info_indexes.begin();
5582                iter != process_info_indexes.end(); ++iter) {
5583             if (printed_one_process_info)
5584               json << ",";
5585             Genealogy::ProcessExecutableInfoSP image_info_sp;
5586             uint32_t idx = *iter;
5587             image_info_sp = DNBGetGenealogyImageInfo(pid, idx);
5588             if (image_info_sp) {
5589               if (!printed_one_process_info) {
5590                 json << "\"process_infos\":[";
5591                 printed_one_process_info = true;
5592               }
5593 
5594               json << "{";
5595               char uuid_buf[37];
5596               uuid_unparse_upper(image_info_sp->image_uuid, uuid_buf);
5597               json << "\"process_info_index\":" << idx << ",";
5598               json << "\"image_path\":\""
5599                    << json_string_quote_metachars(image_info_sp->image_path)
5600                    << "\",";
5601               json << "\"image_uuid\":\"" << uuid_buf << "\"";
5602               json << "}";
5603             }
5604           }
5605           if (printed_one_process_info)
5606             json << "]";
5607         }
5608       } else {
5609         if (timed_out) {
5610           if (need_to_print_comma)
5611             json << ",";
5612           need_to_print_comma = true;
5613           json << "\"activity_query_timed_out\":true";
5614           if (genealogy_fetch_time != 0) {
5615             //  If we append the floating point value with << we'll get it in
5616             //  scientific
5617             //  notation.
5618             char floating_point_ascii_buffer[64];
5619             floating_point_ascii_buffer[0] = '\0';
5620             snprintf(floating_point_ascii_buffer,
5621                      sizeof(floating_point_ascii_buffer), "%f",
5622                      genealogy_fetch_time);
5623             if (strlen(floating_point_ascii_buffer) > 0) {
5624               json << ",";
5625               json << "\"activity_query_duration\":"
5626                    << floating_point_ascii_buffer;
5627             }
5628           }
5629         }
5630       }
5631 
5632       if (tsd_address != INVALID_NUB_ADDRESS) {
5633         if (need_to_print_comma)
5634           json << ",";
5635         need_to_print_comma = true;
5636         json << "\"tsd_address\":" << tsd_address;
5637 
5638         if (dti_qos_class_index != 0 && dti_qos_class_index != UINT64_MAX) {
5639           ThreadInfo::QoS requested_qos = DNBGetRequestedQoSForThread(
5640               pid, tid, tsd_address, dti_qos_class_index);
5641           if (requested_qos.IsValid()) {
5642             if (need_to_print_comma)
5643               json << ",";
5644             need_to_print_comma = true;
5645             json << "\"requested_qos\":{";
5646             json << "\"enum_value\":" << requested_qos.enum_value << ",";
5647             json << "\"constant_name\":\""
5648                  << json_string_quote_metachars(requested_qos.constant_name)
5649                  << "\",";
5650             json << "\"printable_name\":\""
5651                  << json_string_quote_metachars(requested_qos.printable_name)
5652                  << "\"";
5653             json << "}";
5654           }
5655         }
5656       }
5657 
5658       if (pthread_t_value != INVALID_NUB_ADDRESS) {
5659         if (need_to_print_comma)
5660           json << ",";
5661         need_to_print_comma = true;
5662         json << "\"pthread_t\":" << pthread_t_value;
5663       }
5664 
5665       nub_addr_t dispatch_queue_t_value = DNBGetDispatchQueueT(pid, tid);
5666       if (dispatch_queue_t_value != INVALID_NUB_ADDRESS) {
5667         if (need_to_print_comma)
5668           json << ",";
5669         need_to_print_comma = true;
5670         json << "\"dispatch_queue_t\":" << dispatch_queue_t_value;
5671       }
5672 
5673       json << "}";
5674       std::string json_quoted = binary_encode_string(json.str());
5675       return SendPacket(json_quoted);
5676     }
5677   }
5678   return SendPacket("OK");
5679 }
5680 
5681 //  This packet may be called in one of three ways:
5682 //
5683 //  jGetLoadedDynamicLibrariesInfos:{"image_count":40,"image_list_address":4295244704}
5684 //      Look for an array of the old dyld_all_image_infos style of binary infos
5685 //      at the image_list_address.
5686 //      This an array of {void* load_addr, void* mod_date, void* pathname}
5687 //
5688 //  jGetLoadedDynamicLibrariesInfos:{"fetch_all_solibs":true}
5689 //      Use the new style (macOS 10.12, tvOS 10, iOS 10, watchOS 3) dyld SPI to
5690 //      get a list of all the
5691 //      libraries loaded
5692 //
5693 //  jGetLoadedDynamicLibrariesInfos:{"solib_addresses":[8382824135,3258302053,830202858503]}
5694 //      Use the new style (macOS 10.12, tvOS 10, iOS 10, watchOS 3) dyld SPI to
5695 //      get the information
5696 //      about the libraries loaded at these addresses.
5697 //
5698 rnb_err_t
5699 RNBRemote::HandlePacket_jGetLoadedDynamicLibrariesInfos(const char *p) {
5700   nub_process_t pid;
5701   // If we haven't run the process yet, return an error.
5702   if (!m_ctx.HasValidProcessID()) {
5703     return SendPacket("E83");
5704   }
5705 
5706   pid = m_ctx.ProcessID();
5707 
5708   const char get_loaded_dynamic_libraries_infos_str[] = {
5709       "jGetLoadedDynamicLibrariesInfos:{"};
5710   if (strncmp(p, get_loaded_dynamic_libraries_infos_str,
5711               sizeof(get_loaded_dynamic_libraries_infos_str) - 1) == 0) {
5712     p += strlen(get_loaded_dynamic_libraries_infos_str);
5713 
5714     JSONGenerator::ObjectSP json_sp;
5715 
5716     std::vector<uint64_t> macho_addresses;
5717     bool fetch_all_solibs = false;
5718     if (get_boolean_value_for_key_name_from_json("fetch_all_solibs", p,
5719                                                  fetch_all_solibs) &&
5720         fetch_all_solibs) {
5721       json_sp = DNBGetAllLoadedLibrariesInfos(pid);
5722     } else if (get_array_of_ints_value_for_key_name_from_json(
5723                    "solib_addresses", p, macho_addresses)) {
5724       json_sp = DNBGetLibrariesInfoForAddresses(pid, macho_addresses);
5725     } else {
5726       nub_addr_t image_list_address =
5727           get_integer_value_for_key_name_from_json("image_list_address", p);
5728       nub_addr_t image_count =
5729           get_integer_value_for_key_name_from_json("image_count", p);
5730 
5731       if (image_list_address != INVALID_NUB_ADDRESS &&
5732           image_count != INVALID_NUB_ADDRESS) {
5733         json_sp = DNBGetLoadedDynamicLibrariesInfos(pid, image_list_address,
5734                                                     image_count);
5735       }
5736     }
5737 
5738     if (json_sp.get()) {
5739       std::ostringstream json_str;
5740       json_sp->Dump(json_str);
5741       if (json_str.str().size() > 0) {
5742         std::string json_str_quoted = binary_encode_string(json_str.str());
5743         return SendPacket(json_str_quoted.c_str());
5744       } else {
5745         SendPacket("E84");
5746       }
5747     }
5748   }
5749   return SendPacket("OK");
5750 }
5751 
5752 // This packet does not currently take any arguments.  So the behavior is
5753 //    jGetSharedCacheInfo:{}
5754 //         send information about the inferior's shared cache
5755 //    jGetSharedCacheInfo:
5756 //         send "OK" to indicate that this packet is supported
5757 rnb_err_t RNBRemote::HandlePacket_jGetSharedCacheInfo(const char *p) {
5758   nub_process_t pid;
5759   // If we haven't run the process yet, return an error.
5760   if (!m_ctx.HasValidProcessID()) {
5761     return SendPacket("E85");
5762   }
5763 
5764   pid = m_ctx.ProcessID();
5765 
5766   const char get_shared_cache_info_str[] = {"jGetSharedCacheInfo:{"};
5767   if (strncmp(p, get_shared_cache_info_str,
5768               sizeof(get_shared_cache_info_str) - 1) == 0) {
5769     JSONGenerator::ObjectSP json_sp = DNBGetSharedCacheInfo(pid);
5770 
5771     if (json_sp.get()) {
5772       std::ostringstream json_str;
5773       json_sp->Dump(json_str);
5774       if (json_str.str().size() > 0) {
5775         std::string json_str_quoted = binary_encode_string(json_str.str());
5776         return SendPacket(json_str_quoted.c_str());
5777       } else {
5778         SendPacket("E86");
5779       }
5780     }
5781   }
5782   return SendPacket("OK");
5783 }
5784 
5785 static bool MachHeaderIsMainExecutable(nub_process_t pid, uint32_t addr_size,
5786                                        nub_addr_t mach_header_addr,
5787                                        mach_header &mh) {
5788   DNBLogThreadedIf(LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = %u, "
5789                                  "addr_size = %u, mach_header_addr = "
5790                                  "0x%16.16llx)",
5791                    pid, addr_size, mach_header_addr);
5792   const nub_size_t bytes_read =
5793       DNBProcessMemoryRead(pid, mach_header_addr, sizeof(mh), &mh);
5794   if (bytes_read == sizeof(mh)) {
5795     DNBLogThreadedIf(
5796         LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = %u, addr_size = "
5797                       "%u, mach_header_addr = 0x%16.16llx): mh = {\n  magic = "
5798                       "0x%8.8x\n  cpu = 0x%8.8x\n  sub = 0x%8.8x\n  filetype = "
5799                       "%u\n  ncmds = %u\n  sizeofcmds = 0x%8.8x\n  flags = "
5800                       "0x%8.8x }",
5801         pid, addr_size, mach_header_addr, mh.magic, mh.cputype, mh.cpusubtype,
5802         mh.filetype, mh.ncmds, mh.sizeofcmds, mh.flags);
5803     if ((addr_size == 4 && mh.magic == MH_MAGIC) ||
5804         (addr_size == 8 && mh.magic == MH_MAGIC_64)) {
5805       if (mh.filetype == MH_EXECUTE) {
5806         DNBLogThreadedIf(LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = "
5807                                        "%u, addr_size = %u, mach_header_addr = "
5808                                        "0x%16.16llx) -> this is the "
5809                                        "executable!!!",
5810                          pid, addr_size, mach_header_addr);
5811         return true;
5812       }
5813     }
5814   }
5815   return false;
5816 }
5817 
5818 static nub_addr_t GetMachHeaderForMainExecutable(const nub_process_t pid,
5819                                                  const uint32_t addr_size,
5820                                                  mach_header &mh) {
5821   struct AllImageInfos {
5822     uint32_t version;
5823     uint32_t dylib_info_count;
5824     uint64_t dylib_info_addr;
5825   };
5826 
5827   uint64_t mach_header_addr = 0;
5828 
5829   const nub_addr_t shlib_addr = DNBProcessGetSharedLibraryInfoAddress(pid);
5830   uint8_t bytes[256];
5831   nub_size_t bytes_read = 0;
5832   DNBDataRef data(bytes, sizeof(bytes), false);
5833   DNBDataRef::offset_t offset = 0;
5834   data.SetPointerSize(addr_size);
5835 
5836   //----------------------------------------------------------------------
5837   // When we are sitting at __dyld_start, the kernel has placed the
5838   // address of the mach header of the main executable on the stack. If we
5839   // read the SP and dereference a pointer, we might find the mach header
5840   // for the executable. We also just make sure there is only 1 thread
5841   // since if we are at __dyld_start we shouldn't have multiple threads.
5842   //----------------------------------------------------------------------
5843   if (DNBProcessGetNumThreads(pid) == 1) {
5844     nub_thread_t tid = DNBProcessGetThreadAtIndex(pid, 0);
5845     if (tid != INVALID_NUB_THREAD) {
5846       DNBRegisterValue sp_value;
5847       if (DNBThreadGetRegisterValueByID(pid, tid, REGISTER_SET_GENERIC,
5848                                         GENERIC_REGNUM_SP, &sp_value)) {
5849         uint64_t sp =
5850             addr_size == 8 ? sp_value.value.uint64 : sp_value.value.uint32;
5851         bytes_read = DNBProcessMemoryRead(pid, sp, addr_size, bytes);
5852         if (bytes_read == addr_size) {
5853           offset = 0;
5854           mach_header_addr = data.GetPointer(&offset);
5855           if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, mh))
5856             return mach_header_addr;
5857         }
5858       }
5859     }
5860   }
5861 
5862   //----------------------------------------------------------------------
5863   // Check the dyld_all_image_info structure for a list of mach header
5864   // since it is a very easy thing to check
5865   //----------------------------------------------------------------------
5866   if (shlib_addr != INVALID_NUB_ADDRESS) {
5867     bytes_read =
5868         DNBProcessMemoryRead(pid, shlib_addr, sizeof(AllImageInfos), bytes);
5869     if (bytes_read > 0) {
5870       AllImageInfos aii;
5871       offset = 0;
5872       aii.version = data.Get32(&offset);
5873       aii.dylib_info_count = data.Get32(&offset);
5874       if (aii.dylib_info_count > 0) {
5875         aii.dylib_info_addr = data.GetPointer(&offset);
5876         if (aii.dylib_info_addr != 0) {
5877           const size_t image_info_byte_size = 3 * addr_size;
5878           for (uint32_t i = 0; i < aii.dylib_info_count; ++i) {
5879             bytes_read = DNBProcessMemoryRead(pid, aii.dylib_info_addr +
5880                                                        i * image_info_byte_size,
5881                                               image_info_byte_size, bytes);
5882             if (bytes_read != image_info_byte_size)
5883               break;
5884             offset = 0;
5885             mach_header_addr = data.GetPointer(&offset);
5886             if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr,
5887                                            mh))
5888               return mach_header_addr;
5889           }
5890         }
5891       }
5892     }
5893   }
5894 
5895   //----------------------------------------------------------------------
5896   // We failed to find the executable's mach header from the all image
5897   // infos and by dereferencing the stack pointer. Now we fall back to
5898   // enumerating the memory regions and looking for regions that are
5899   // executable.
5900   //----------------------------------------------------------------------
5901   DNBRegionInfo region_info;
5902   mach_header_addr = 0;
5903   while (DNBProcessMemoryRegionInfo(pid, mach_header_addr, &region_info)) {
5904     if (region_info.size == 0)
5905       break;
5906 
5907     if (region_info.permissions & eMemoryPermissionsExecutable) {
5908       DNBLogThreadedIf(
5909           LOG_RNB_PROC, "[0x%16.16llx - 0x%16.16llx) permissions = %c%c%c: "
5910                         "checking region for executable mach header",
5911           region_info.addr, region_info.addr + region_info.size,
5912           (region_info.permissions & eMemoryPermissionsReadable) ? 'r' : '-',
5913           (region_info.permissions & eMemoryPermissionsWritable) ? 'w' : '-',
5914           (region_info.permissions & eMemoryPermissionsExecutable) ? 'x' : '-');
5915       if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, mh))
5916         return mach_header_addr;
5917     } else {
5918       DNBLogThreadedIf(
5919           LOG_RNB_PROC,
5920           "[0x%16.16llx - 0x%16.16llx): permissions = %c%c%c: skipping region",
5921           region_info.addr, region_info.addr + region_info.size,
5922           (region_info.permissions & eMemoryPermissionsReadable) ? 'r' : '-',
5923           (region_info.permissions & eMemoryPermissionsWritable) ? 'w' : '-',
5924           (region_info.permissions & eMemoryPermissionsExecutable) ? 'x' : '-');
5925     }
5926     // Set the address to the next mapped region
5927     mach_header_addr = region_info.addr + region_info.size;
5928   }
5929   bzero(&mh, sizeof(mh));
5930   return INVALID_NUB_ADDRESS;
5931 }
5932 
5933 rnb_err_t RNBRemote::HandlePacket_qSymbol(const char *command) {
5934   const char *p = command;
5935   p += strlen("qSymbol:");
5936   const char *sep = strchr(p, ':');
5937 
5938   std::string symbol_name;
5939   std::string symbol_value_str;
5940   // Extract the symbol value if there is one
5941   if (sep > p)
5942     symbol_value_str.assign(p, sep - p);
5943   p = sep + 1;
5944 
5945   if (*p) {
5946     // We have a symbol name
5947     symbol_name = decode_hex_ascii_string(p);
5948     if (!symbol_value_str.empty()) {
5949       nub_addr_t symbol_value = decode_uint64(symbol_value_str.c_str(), 16);
5950       if (symbol_name == "dispatch_queue_offsets")
5951         m_dispatch_queue_offsets_addr = symbol_value;
5952     }
5953     ++m_qSymbol_index;
5954   } else {
5955     // No symbol name, set our symbol index to zero so we can
5956     // read any symbols that we need
5957     m_qSymbol_index = 0;
5958   }
5959 
5960   symbol_name.clear();
5961 
5962   if (m_qSymbol_index == 0) {
5963     if (m_dispatch_queue_offsets_addr == INVALID_NUB_ADDRESS)
5964       symbol_name = "dispatch_queue_offsets";
5965     else
5966       ++m_qSymbol_index;
5967   }
5968 
5969   //    // Lookup next symbol when we have one...
5970   //    if (m_qSymbol_index == 1)
5971   //    {
5972   //    }
5973 
5974   if (symbol_name.empty()) {
5975     // Done with symbol lookups
5976     return SendPacket("OK");
5977   } else {
5978     std::ostringstream reply;
5979     reply << "qSymbol:";
5980     for (size_t i = 0; i < symbol_name.size(); ++i)
5981       reply << RAWHEX8(symbol_name[i]);
5982     return SendPacket(reply.str().c_str());
5983   }
5984 }
5985 
5986 // Note that all numeric values returned by qProcessInfo are hex encoded,
5987 // including the pid and the cpu type.
5988 
5989 rnb_err_t RNBRemote::HandlePacket_qProcessInfo(const char *p) {
5990   nub_process_t pid;
5991   std::ostringstream rep;
5992 
5993   // If we haven't run the process yet, return an error.
5994   if (!m_ctx.HasValidProcessID())
5995     return SendPacket("E68");
5996 
5997   pid = m_ctx.ProcessID();
5998 
5999   rep << "pid:" << std::hex << pid << ';';
6000 
6001   int procpid_mib[4];
6002   procpid_mib[0] = CTL_KERN;
6003   procpid_mib[1] = KERN_PROC;
6004   procpid_mib[2] = KERN_PROC_PID;
6005   procpid_mib[3] = pid;
6006   struct kinfo_proc proc_kinfo;
6007   size_t proc_kinfo_size = sizeof(struct kinfo_proc);
6008 
6009   if (::sysctl(procpid_mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) {
6010     if (proc_kinfo_size > 0) {
6011       rep << "parent-pid:" << std::hex << proc_kinfo.kp_eproc.e_ppid << ';';
6012       rep << "real-uid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_ruid
6013           << ';';
6014       rep << "real-gid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_rgid
6015           << ';';
6016       rep << "effective-uid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_uid
6017           << ';';
6018       if (proc_kinfo.kp_eproc.e_ucred.cr_ngroups > 0)
6019         rep << "effective-gid:" << std::hex
6020             << proc_kinfo.kp_eproc.e_ucred.cr_groups[0] << ';';
6021     }
6022   }
6023 
6024   cpu_type_t cputype = DNBProcessGetCPUType(pid);
6025   if (cputype == 0) {
6026     DNBLog("Unable to get the process cpu_type, making a best guess.");
6027     cputype = best_guess_cpu_type();
6028   }
6029 
6030   uint32_t addr_size = 0;
6031   if (cputype != 0) {
6032     rep << "cputype:" << std::hex << cputype << ";";
6033     if (cputype & CPU_ARCH_ABI64)
6034       addr_size = 8;
6035     else
6036       addr_size = 4;
6037   }
6038 
6039   bool host_cpu_is_64bit = false;
6040   uint32_t is64bit_capable;
6041   size_t is64bit_capable_len = sizeof(is64bit_capable);
6042   if (sysctlbyname("hw.cpu64bit_capable", &is64bit_capable,
6043                    &is64bit_capable_len, NULL, 0) == 0)
6044     host_cpu_is_64bit = is64bit_capable != 0;
6045 
6046   uint32_t cpusubtype;
6047   size_t cpusubtype_len = sizeof(cpusubtype);
6048   if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &cpusubtype_len, NULL, 0) ==
6049       0) {
6050     // If a process is CPU_TYPE_X86, then ignore the cpusubtype that we detected
6051     // from the host and use CPU_SUBTYPE_I386_ALL because we don't want the
6052     // CPU_SUBTYPE_X86_ARCH1 or CPU_SUBTYPE_X86_64_H to be used as the cpu
6053     // subtype
6054     // for i386...
6055     if (host_cpu_is_64bit) {
6056       if (cputype == CPU_TYPE_X86) {
6057         cpusubtype = 3; // CPU_SUBTYPE_I386_ALL
6058       } else if (cputype == CPU_TYPE_ARM) {
6059         // We can query a process' cputype but we cannot query a process'
6060         // cpusubtype.
6061         // If the process has cputype CPU_TYPE_ARM, then it is an armv7 (32-bit
6062         // process) and we
6063         // need to override the host cpusubtype (which is in the
6064         // CPU_SUBTYPE_ARM64 subtype namespace)
6065         // with a reasonable CPU_SUBTYPE_ARMV7 subtype.
6066         cpusubtype = 12; // CPU_SUBTYPE_ARM_V7K
6067       }
6068     }
6069     rep << "cpusubtype:" << std::hex << cpusubtype << ';';
6070   }
6071 
6072   bool os_handled = false;
6073   if (addr_size > 0) {
6074     rep << "ptrsize:" << std::dec << addr_size << ';';
6075 
6076 #if (defined(__x86_64__) || defined(__i386__))
6077     // Try and get the OS type by looking at the load commands in the main
6078     // executable and looking for a LC_VERSION_MIN load command. This is the
6079     // most reliable way to determine the "ostype" value when on desktop.
6080 
6081     mach_header mh;
6082     nub_addr_t exe_mach_header_addr =
6083         GetMachHeaderForMainExecutable(pid, addr_size, mh);
6084     if (exe_mach_header_addr != INVALID_NUB_ADDRESS) {
6085       uint64_t load_command_addr =
6086           exe_mach_header_addr +
6087           ((addr_size == 8) ? sizeof(mach_header_64) : sizeof(mach_header));
6088       load_command lc;
6089       for (uint32_t i = 0; i < mh.ncmds && !os_handled; ++i) {
6090         const nub_size_t bytes_read =
6091             DNBProcessMemoryRead(pid, load_command_addr, sizeof(lc), &lc);
6092         uint32_t raw_cmd = lc.cmd & ~LC_REQ_DYLD;
6093         if (bytes_read != sizeof(lc))
6094           break;
6095         switch (raw_cmd) {
6096         case LC_VERSION_MIN_IPHONEOS:
6097           os_handled = true;
6098           rep << "ostype:ios;";
6099           DNBLogThreadedIf(LOG_RNB_PROC,
6100                            "LC_VERSION_MIN_IPHONEOS -> 'ostype:ios;'");
6101           break;
6102 
6103         case LC_VERSION_MIN_MACOSX:
6104           os_handled = true;
6105           rep << "ostype:macosx;";
6106           DNBLogThreadedIf(LOG_RNB_PROC,
6107                            "LC_VERSION_MIN_MACOSX -> 'ostype:macosx;'");
6108           break;
6109 
6110 #if defined(LC_VERSION_MIN_TVOS)
6111         case LC_VERSION_MIN_TVOS:
6112           os_handled = true;
6113           rep << "ostype:tvos;";
6114           DNBLogThreadedIf(LOG_RNB_PROC,
6115                            "LC_VERSION_MIN_TVOS -> 'ostype:tvos;'");
6116           break;
6117 #endif
6118 
6119 #if defined(LC_VERSION_MIN_WATCHOS)
6120         case LC_VERSION_MIN_WATCHOS:
6121           os_handled = true;
6122           rep << "ostype:watchos;";
6123           DNBLogThreadedIf(LOG_RNB_PROC,
6124                            "LC_VERSION_MIN_WATCHOS -> 'ostype:watchos;'");
6125           break;
6126 #endif
6127 
6128         default:
6129           break;
6130         }
6131         load_command_addr = load_command_addr + lc.cmdsize;
6132       }
6133     }
6134 #endif
6135   }
6136 
6137   // If we weren't able to find the OS in a LC_VERSION_MIN load command, try
6138   // to set it correctly by using the cpu type and other tricks
6139   if (!os_handled) {
6140     // The OS in the triple should be "ios" or "macosx" which doesn't match our
6141     // "Darwin" which gets returned from "kern.ostype", so we need to hardcode
6142     // this for now.
6143     if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64) {
6144 #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
6145       rep << "ostype:tvos;";
6146 #elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
6147       rep << "ostype:watchos;";
6148 #else
6149       rep << "ostype:ios;";
6150 #endif
6151     } else {
6152       bool is_ios_simulator = false;
6153       if (cputype == CPU_TYPE_X86 || cputype == CPU_TYPE_X86_64) {
6154         // Check for iOS simulator binaries by getting the process argument
6155         // and environment and checking for SIMULATOR_UDID in the environment
6156         int proc_args_mib[3] = {CTL_KERN, KERN_PROCARGS2, (int)pid};
6157 
6158         uint8_t arg_data[8192];
6159         size_t arg_data_size = sizeof(arg_data);
6160         if (::sysctl(proc_args_mib, 3, arg_data, &arg_data_size, NULL, 0) ==
6161             0) {
6162           DNBDataRef data(arg_data, arg_data_size, false);
6163           DNBDataRef::offset_t offset = 0;
6164           uint32_t argc = data.Get32(&offset);
6165           const char *cstr;
6166 
6167           cstr = data.GetCStr(&offset);
6168           if (cstr) {
6169             // Skip NULLs
6170             while (1) {
6171               const char *p = data.PeekCStr(offset);
6172               if ((p == NULL) || (*p != '\0'))
6173                 break;
6174               ++offset;
6175             }
6176             // Now skip all arguments
6177             for (uint32_t i = 0; i < argc; ++i) {
6178               data.GetCStr(&offset);
6179             }
6180 
6181             // Now iterate across all environment variables
6182             while ((cstr = data.GetCStr(&offset))) {
6183               if (strncmp(cstr, "SIMULATOR_UDID=", strlen("SIMULATOR_UDID=")) ==
6184                   0) {
6185                 is_ios_simulator = true;
6186                 break;
6187               }
6188               if (cstr[0] == '\0')
6189                 break;
6190             }
6191           }
6192         }
6193       }
6194       if (is_ios_simulator) {
6195 #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
6196         rep << "ostype:tvos;";
6197 #elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
6198         rep << "ostype:watchos;";
6199 #else
6200         rep << "ostype:ios;";
6201 #endif
6202       } else {
6203         rep << "ostype:macosx;";
6204       }
6205     }
6206   }
6207 
6208   rep << "vendor:apple;";
6209 
6210 #if defined(__LITTLE_ENDIAN__)
6211   rep << "endian:little;";
6212 #elif defined(__BIG_ENDIAN__)
6213   rep << "endian:big;";
6214 #elif defined(__PDP_ENDIAN__)
6215   rep << "endian:pdp;";
6216 #endif
6217 
6218   if (addr_size == 0) {
6219 #if (defined(__x86_64__) || defined(__i386__)) && defined(x86_THREAD_STATE)
6220     nub_thread_t thread = DNBProcessGetCurrentThreadMachPort(pid);
6221     kern_return_t kr;
6222     x86_thread_state_t gp_regs;
6223     mach_msg_type_number_t gp_count = x86_THREAD_STATE_COUNT;
6224     kr = thread_get_state(static_cast<thread_act_t>(thread), x86_THREAD_STATE,
6225                           (thread_state_t)&gp_regs, &gp_count);
6226     if (kr == KERN_SUCCESS) {
6227       if (gp_regs.tsh.flavor == x86_THREAD_STATE64)
6228         rep << "ptrsize:8;";
6229       else
6230         rep << "ptrsize:4;";
6231     }
6232 #elif defined(__arm__)
6233     rep << "ptrsize:4;";
6234 #elif (defined(__arm64__) || defined(__aarch64__)) &&                          \
6235     defined(ARM_UNIFIED_THREAD_STATE)
6236     nub_thread_t thread = DNBProcessGetCurrentThreadMachPort(pid);
6237     kern_return_t kr;
6238     arm_unified_thread_state_t gp_regs;
6239     mach_msg_type_number_t gp_count = ARM_UNIFIED_THREAD_STATE_COUNT;
6240     kr = thread_get_state(thread, ARM_UNIFIED_THREAD_STATE,
6241                           (thread_state_t)&gp_regs, &gp_count);
6242     if (kr == KERN_SUCCESS) {
6243       if (gp_regs.ash.flavor == ARM_THREAD_STATE64)
6244         rep << "ptrsize:8;";
6245       else
6246         rep << "ptrsize:4;";
6247     }
6248 #endif
6249   }
6250 
6251   return SendPacket(rep.str());
6252 }
6253 
6254 const RNBRemote::DispatchQueueOffsets *RNBRemote::GetDispatchQueueOffsets() {
6255   if (!m_dispatch_queue_offsets.IsValid() &&
6256       m_dispatch_queue_offsets_addr != INVALID_NUB_ADDRESS &&
6257       m_ctx.HasValidProcessID()) {
6258     nub_process_t pid = m_ctx.ProcessID();
6259     nub_size_t bytes_read = DNBProcessMemoryRead(
6260         pid, m_dispatch_queue_offsets_addr, sizeof(m_dispatch_queue_offsets),
6261         &m_dispatch_queue_offsets);
6262     if (bytes_read != sizeof(m_dispatch_queue_offsets))
6263       m_dispatch_queue_offsets.Clear();
6264   }
6265 
6266   if (m_dispatch_queue_offsets.IsValid())
6267     return &m_dispatch_queue_offsets;
6268   else
6269     return nullptr;
6270 }
6271 
6272 void RNBRemote::EnableCompressionNextSendPacket(compression_types type) {
6273   m_compression_mode = type;
6274   m_enable_compression_next_send_packet = true;
6275 }
6276 
6277 compression_types RNBRemote::GetCompressionType() {
6278   // The first packet we send back to the debugger after a QEnableCompression
6279   // request
6280   // should be uncompressed -- so we can indicate whether the compression was
6281   // enabled
6282   // or not via OK / Enn returns.  After that, all packets sent will be using
6283   // the
6284   // compression protocol.
6285 
6286   if (m_enable_compression_next_send_packet) {
6287     // One time, we send back "None" as our compression type
6288     m_enable_compression_next_send_packet = false;
6289     return compression_types::none;
6290   }
6291   return m_compression_mode;
6292 }
6293