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