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