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