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