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