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   ret_str << "E" << m_ctx.LaunchStatusAsString(status_str);
1647 
1648   return SendPacket(ret_str.str());
1649 }
1650 
1651 rnb_err_t RNBRemote::HandlePacket_qShlibInfoAddr(const char *p) {
1652   if (m_ctx.HasValidProcessID()) {
1653     nub_addr_t shlib_info_addr =
1654         DNBProcessGetSharedLibraryInfoAddress(m_ctx.ProcessID());
1655     if (shlib_info_addr != INVALID_NUB_ADDRESS) {
1656       std::ostringstream ostrm;
1657       ostrm << RAW_HEXBASE << shlib_info_addr;
1658       return SendPacket(ostrm.str());
1659     }
1660   }
1661   return SendPacket("E44");
1662 }
1663 
1664 rnb_err_t RNBRemote::HandlePacket_qStepPacketSupported(const char *p) {
1665   // Normally the "s" packet is mandatory, yet in gdb when using ARM, they
1666   // get around the need for this packet by implementing software single
1667   // stepping from gdb. Current versions of debugserver do support the "s"
1668   // packet, yet some older versions do not. We need a way to tell if this
1669   // packet is supported so we can disable software single stepping in gdb
1670   // for remote targets (so the "s" packet will get used).
1671   return SendPacket("OK");
1672 }
1673 
1674 rnb_err_t RNBRemote::HandlePacket_qSyncThreadStateSupported(const char *p) {
1675   // We support attachOrWait meaning attach if the process exists, otherwise
1676   // wait to attach.
1677   return SendPacket("OK");
1678 }
1679 
1680 rnb_err_t RNBRemote::HandlePacket_qVAttachOrWaitSupported(const char *p) {
1681   // We support attachOrWait meaning attach if the process exists, otherwise
1682   // wait to attach.
1683   return SendPacket("OK");
1684 }
1685 
1686 rnb_err_t RNBRemote::HandlePacket_qThreadStopInfo(const char *p) {
1687   p += strlen("qThreadStopInfo");
1688   nub_thread_t tid = strtoul(p, 0, 16);
1689   return SendStopReplyPacketForThread(tid);
1690 }
1691 
1692 rnb_err_t RNBRemote::HandlePacket_qThreadInfo(const char *p) {
1693   // We allow gdb to connect to a server that hasn't started running
1694   // the target yet.  gdb still wants to ask questions about it and
1695   // freaks out if it gets an error.  So just return OK here.
1696   nub_process_t pid = m_ctx.ProcessID();
1697   if (pid == INVALID_NUB_PROCESS)
1698     return SendPacket("OK");
1699 
1700   // Only "qfThreadInfo" and "qsThreadInfo" get into this function so
1701   // we only need to check the second byte to tell which is which
1702   if (p[1] == 'f') {
1703     nub_size_t numthreads = DNBProcessGetNumThreads(pid);
1704     std::ostringstream ostrm;
1705     ostrm << "m";
1706     bool first = true;
1707     for (nub_size_t i = 0; i < numthreads; ++i) {
1708       if (first)
1709         first = false;
1710       else
1711         ostrm << ",";
1712       nub_thread_t th = DNBProcessGetThreadAtIndex(pid, i);
1713       ostrm << std::hex << th;
1714     }
1715     return SendPacket(ostrm.str());
1716   } else {
1717     return SendPacket("l");
1718   }
1719 }
1720 
1721 rnb_err_t RNBRemote::HandlePacket_qThreadExtraInfo(const char *p) {
1722   // We allow gdb to connect to a server that hasn't started running
1723   // the target yet.  gdb still wants to ask questions about it and
1724   // freaks out if it gets an error.  So just return OK here.
1725   nub_process_t pid = m_ctx.ProcessID();
1726   if (pid == INVALID_NUB_PROCESS)
1727     return SendPacket("OK");
1728 
1729   /* This is supposed to return a string like 'Runnable' or
1730    'Blocked on Mutex'.
1731    The returned string is formatted like the "A" packet - a
1732    sequence of letters encoded in as 2-hex-chars-per-letter.  */
1733   p += strlen("qThreadExtraInfo");
1734   if (*p++ != ',')
1735     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
1736                                   "Illformed qThreadExtraInfo packet");
1737   errno = 0;
1738   nub_thread_t tid = strtoul(p, NULL, 16);
1739   if (errno != 0 && tid == 0) {
1740     return HandlePacket_ILLFORMED(
1741         __FILE__, __LINE__, p,
1742         "Invalid thread number in qThreadExtraInfo packet");
1743   }
1744 
1745   const char *threadInfo = DNBThreadGetInfo(pid, tid);
1746   if (threadInfo != NULL && threadInfo[0]) {
1747     return SendHexEncodedBytePacket(NULL, threadInfo, strlen(threadInfo), NULL);
1748   } else {
1749     // "OK" == 4f6b
1750     // Return "OK" as a ASCII hex byte stream if things go wrong
1751     return SendPacket("4f6b");
1752   }
1753 
1754   return SendPacket("");
1755 }
1756 
1757 const char *k_space_delimiters = " \t";
1758 static void skip_spaces(std::string &line) {
1759   if (!line.empty()) {
1760     size_t space_pos = line.find_first_not_of(k_space_delimiters);
1761     if (space_pos > 0)
1762       line.erase(0, space_pos);
1763   }
1764 }
1765 
1766 static std::string get_identifier(std::string &line) {
1767   std::string word;
1768   skip_spaces(line);
1769   const size_t line_size = line.size();
1770   size_t end_pos;
1771   for (end_pos = 0; end_pos < line_size; ++end_pos) {
1772     if (end_pos == 0) {
1773       if (isalpha(line[end_pos]) || line[end_pos] == '_')
1774         continue;
1775     } else if (isalnum(line[end_pos]) || line[end_pos] == '_')
1776       continue;
1777     break;
1778   }
1779   word.assign(line, 0, end_pos);
1780   line.erase(0, end_pos);
1781   return word;
1782 }
1783 
1784 static std::string get_operator(std::string &line) {
1785   std::string op;
1786   skip_spaces(line);
1787   if (!line.empty()) {
1788     if (line[0] == '=') {
1789       op = '=';
1790       line.erase(0, 1);
1791     }
1792   }
1793   return op;
1794 }
1795 
1796 static std::string get_value(std::string &line) {
1797   std::string value;
1798   skip_spaces(line);
1799   if (!line.empty()) {
1800     value.swap(line);
1801   }
1802   return value;
1803 }
1804 
1805 extern void FileLogCallback(void *baton, uint32_t flags, const char *format,
1806                             va_list args);
1807 extern void ASLLogCallback(void *baton, uint32_t flags, const char *format,
1808                            va_list args);
1809 
1810 rnb_err_t RNBRemote::HandlePacket_qRcmd(const char *p) {
1811   const char *c = p + strlen("qRcmd,");
1812   std::string line;
1813   while (c[0] && c[1]) {
1814     char smallbuf[3] = {c[0], c[1], '\0'};
1815     errno = 0;
1816     int ch = static_cast<int>(strtoul(smallbuf, NULL, 16));
1817     if (errno != 0 && ch == 0)
1818       return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
1819                                     "non-hex char in payload of qRcmd packet");
1820     line.push_back(ch);
1821     c += 2;
1822   }
1823   if (*c == '\0') {
1824     std::string command = get_identifier(line);
1825     if (command == "set") {
1826       std::string variable = get_identifier(line);
1827       std::string op = get_operator(line);
1828       std::string value = get_value(line);
1829       if (variable == "logfile") {
1830         FILE *log_file = fopen(value.c_str(), "w");
1831         if (log_file) {
1832           DNBLogSetLogCallback(FileLogCallback, log_file);
1833           return SendPacket("OK");
1834         }
1835         return SendPacket("E71");
1836       } else if (variable == "logmask") {
1837         char *end;
1838         errno = 0;
1839         uint32_t logmask =
1840             static_cast<uint32_t>(strtoul(value.c_str(), &end, 0));
1841         if (errno == 0 && end && *end == '\0') {
1842           DNBLogSetLogMask(logmask);
1843           if (!DNBLogGetLogCallback())
1844             DNBLogSetLogCallback(ASLLogCallback, NULL);
1845           return SendPacket("OK");
1846         }
1847         errno = 0;
1848         logmask = static_cast<uint32_t>(strtoul(value.c_str(), &end, 16));
1849         if (errno == 0 && end && *end == '\0') {
1850           DNBLogSetLogMask(logmask);
1851           return SendPacket("OK");
1852         }
1853         return SendPacket("E72");
1854       }
1855       return SendPacket("E70");
1856     }
1857     return SendPacket("E69");
1858   }
1859   return SendPacket("E73");
1860 }
1861 
1862 rnb_err_t RNBRemote::HandlePacket_qC(const char *p) {
1863   nub_thread_t tid;
1864   std::ostringstream rep;
1865   // If we haven't run the process yet, we tell the debugger the
1866   // pid is 0.  That way it can know to tell use to run later on.
1867   if (!m_ctx.HasValidProcessID())
1868     tid = 0;
1869   else {
1870     // Grab the current thread.
1871     tid = DNBProcessGetCurrentThread(m_ctx.ProcessID());
1872     // Make sure we set the current thread so g and p packets return
1873     // the data the gdb will expect.
1874     SetCurrentThread(tid);
1875   }
1876   rep << "QC" << std::hex << tid;
1877   return SendPacket(rep.str());
1878 }
1879 
1880 rnb_err_t RNBRemote::HandlePacket_qEcho(const char *p) {
1881   // Just send the exact same packet back that we received to
1882   // synchronize the response packets after a previous packet
1883   // timed out. This allows the debugger to get back on track
1884   // with responses after a packet timeout.
1885   return SendPacket(p);
1886 }
1887 
1888 rnb_err_t RNBRemote::HandlePacket_qGetPid(const char *p) {
1889   nub_process_t pid;
1890   std::ostringstream rep;
1891   // If we haven't run the process yet, we tell the debugger the
1892   // pid is 0.  That way it can know to tell use to run later on.
1893   if (m_ctx.HasValidProcessID())
1894     pid = m_ctx.ProcessID();
1895   else
1896     pid = 0;
1897   rep << std::hex << pid;
1898   return SendPacket(rep.str());
1899 }
1900 
1901 rnb_err_t RNBRemote::HandlePacket_qRegisterInfo(const char *p) {
1902   if (g_num_reg_entries == 0)
1903     InitializeRegisters();
1904 
1905   p += strlen("qRegisterInfo");
1906 
1907   nub_size_t num_reg_sets = 0;
1908   const DNBRegisterSetInfo *reg_set_info = DNBGetRegisterSetInfo(&num_reg_sets);
1909   uint32_t reg_num = static_cast<uint32_t>(strtoul(p, 0, 16));
1910 
1911   if (reg_num < g_num_reg_entries) {
1912     const register_map_entry_t *reg_entry = &g_reg_entries[reg_num];
1913     std::ostringstream ostrm;
1914     if (reg_entry->nub_info.name)
1915       ostrm << "name:" << reg_entry->nub_info.name << ';';
1916     if (reg_entry->nub_info.alt)
1917       ostrm << "alt-name:" << reg_entry->nub_info.alt << ';';
1918 
1919     ostrm << "bitsize:" << std::dec << reg_entry->nub_info.size * 8 << ';';
1920     ostrm << "offset:" << std::dec << reg_entry->offset << ';';
1921 
1922     switch (reg_entry->nub_info.type) {
1923     case Uint:
1924       ostrm << "encoding:uint;";
1925       break;
1926     case Sint:
1927       ostrm << "encoding:sint;";
1928       break;
1929     case IEEE754:
1930       ostrm << "encoding:ieee754;";
1931       break;
1932     case Vector:
1933       ostrm << "encoding:vector;";
1934       break;
1935     }
1936 
1937     switch (reg_entry->nub_info.format) {
1938     case Binary:
1939       ostrm << "format:binary;";
1940       break;
1941     case Decimal:
1942       ostrm << "format:decimal;";
1943       break;
1944     case Hex:
1945       ostrm << "format:hex;";
1946       break;
1947     case Float:
1948       ostrm << "format:float;";
1949       break;
1950     case VectorOfSInt8:
1951       ostrm << "format:vector-sint8;";
1952       break;
1953     case VectorOfUInt8:
1954       ostrm << "format:vector-uint8;";
1955       break;
1956     case VectorOfSInt16:
1957       ostrm << "format:vector-sint16;";
1958       break;
1959     case VectorOfUInt16:
1960       ostrm << "format:vector-uint16;";
1961       break;
1962     case VectorOfSInt32:
1963       ostrm << "format:vector-sint32;";
1964       break;
1965     case VectorOfUInt32:
1966       ostrm << "format:vector-uint32;";
1967       break;
1968     case VectorOfFloat32:
1969       ostrm << "format:vector-float32;";
1970       break;
1971     case VectorOfUInt128:
1972       ostrm << "format:vector-uint128;";
1973       break;
1974     };
1975 
1976     if (reg_set_info && reg_entry->nub_info.set < num_reg_sets)
1977       ostrm << "set:" << reg_set_info[reg_entry->nub_info.set].name << ';';
1978 
1979     if (reg_entry->nub_info.reg_ehframe != INVALID_NUB_REGNUM)
1980       ostrm << "ehframe:" << std::dec << reg_entry->nub_info.reg_ehframe << ';';
1981 
1982     if (reg_entry->nub_info.reg_dwarf != INVALID_NUB_REGNUM)
1983       ostrm << "dwarf:" << std::dec << reg_entry->nub_info.reg_dwarf << ';';
1984 
1985     switch (reg_entry->nub_info.reg_generic) {
1986     case GENERIC_REGNUM_FP:
1987       ostrm << "generic:fp;";
1988       break;
1989     case GENERIC_REGNUM_PC:
1990       ostrm << "generic:pc;";
1991       break;
1992     case GENERIC_REGNUM_SP:
1993       ostrm << "generic:sp;";
1994       break;
1995     case GENERIC_REGNUM_RA:
1996       ostrm << "generic:ra;";
1997       break;
1998     case GENERIC_REGNUM_FLAGS:
1999       ostrm << "generic:flags;";
2000       break;
2001     case GENERIC_REGNUM_ARG1:
2002       ostrm << "generic:arg1;";
2003       break;
2004     case GENERIC_REGNUM_ARG2:
2005       ostrm << "generic:arg2;";
2006       break;
2007     case GENERIC_REGNUM_ARG3:
2008       ostrm << "generic:arg3;";
2009       break;
2010     case GENERIC_REGNUM_ARG4:
2011       ostrm << "generic:arg4;";
2012       break;
2013     case GENERIC_REGNUM_ARG5:
2014       ostrm << "generic:arg5;";
2015       break;
2016     case GENERIC_REGNUM_ARG6:
2017       ostrm << "generic:arg6;";
2018       break;
2019     case GENERIC_REGNUM_ARG7:
2020       ostrm << "generic:arg7;";
2021       break;
2022     case GENERIC_REGNUM_ARG8:
2023       ostrm << "generic:arg8;";
2024       break;
2025     default:
2026       break;
2027     }
2028 
2029     if (!reg_entry->value_regnums.empty()) {
2030       ostrm << "container-regs:";
2031       for (size_t i = 0, n = reg_entry->value_regnums.size(); i < n; ++i) {
2032         if (i > 0)
2033           ostrm << ',';
2034         ostrm << RAW_HEXBASE << reg_entry->value_regnums[i];
2035       }
2036       ostrm << ';';
2037     }
2038 
2039     if (!reg_entry->invalidate_regnums.empty()) {
2040       ostrm << "invalidate-regs:";
2041       for (size_t i = 0, n = reg_entry->invalidate_regnums.size(); i < n; ++i) {
2042         if (i > 0)
2043           ostrm << ',';
2044         ostrm << RAW_HEXBASE << reg_entry->invalidate_regnums[i];
2045       }
2046       ostrm << ';';
2047     }
2048 
2049     return SendPacket(ostrm.str());
2050   }
2051   return SendPacket("E45");
2052 }
2053 
2054 /* This expects a packet formatted like
2055 
2056  QSetLogging:bitmask=LOG_ALL|LOG_RNB_REMOTE;
2057 
2058  with the "QSetLogging:" already removed from the start.  Maybe in the
2059  future this packet will include other keyvalue pairs like
2060 
2061  QSetLogging:bitmask=LOG_ALL;mode=asl;
2062  */
2063 
2064 rnb_err_t set_logging(const char *p) {
2065   int bitmask = 0;
2066   while (p && *p != '\0') {
2067     if (strncmp(p, "bitmask=", sizeof("bitmask=") - 1) == 0) {
2068       p += sizeof("bitmask=") - 1;
2069       while (p && *p != '\0' && *p != ';') {
2070         if (*p == '|')
2071           p++;
2072 
2073         // to regenerate the LOG_ entries (not including the LOG_RNB entries)
2074         // $ for logname in `grep '^#define LOG_' DNBDefs.h | egrep -v
2075         // 'LOG_HI|LOG_LO' | awk '{print $2}'`
2076         // do
2077         //   echo "                else if (strncmp (p, \"$logname\", sizeof
2078         //   (\"$logname\") - 1) == 0)"
2079         //   echo "                {"
2080         //   echo "                    p += sizeof (\"$logname\") - 1;"
2081         //   echo "                    bitmask |= $logname;"
2082         //   echo "                }"
2083         // done
2084         if (strncmp(p, "LOG_VERBOSE", sizeof("LOG_VERBOSE") - 1) == 0) {
2085           p += sizeof("LOG_VERBOSE") - 1;
2086           bitmask |= LOG_VERBOSE;
2087         } else if (strncmp(p, "LOG_PROCESS", sizeof("LOG_PROCESS") - 1) == 0) {
2088           p += sizeof("LOG_PROCESS") - 1;
2089           bitmask |= LOG_PROCESS;
2090         } else if (strncmp(p, "LOG_THREAD", sizeof("LOG_THREAD") - 1) == 0) {
2091           p += sizeof("LOG_THREAD") - 1;
2092           bitmask |= LOG_THREAD;
2093         } else if (strncmp(p, "LOG_EXCEPTIONS", sizeof("LOG_EXCEPTIONS") - 1) ==
2094                    0) {
2095           p += sizeof("LOG_EXCEPTIONS") - 1;
2096           bitmask |= LOG_EXCEPTIONS;
2097         } else if (strncmp(p, "LOG_SHLIB", sizeof("LOG_SHLIB") - 1) == 0) {
2098           p += sizeof("LOG_SHLIB") - 1;
2099           bitmask |= LOG_SHLIB;
2100         } else if (strncmp(p, "LOG_MEMORY_DATA_SHORT",
2101                            sizeof("LOG_MEMORY_DATA_SHORT") - 1) == 0) {
2102           p += sizeof("LOG_MEMORY_DATA_SHORT") - 1;
2103           bitmask |= LOG_MEMORY_DATA_SHORT;
2104         } else if (strncmp(p, "LOG_MEMORY_DATA_LONG",
2105                            sizeof("LOG_MEMORY_DATA_LONG") - 1) == 0) {
2106           p += sizeof("LOG_MEMORY_DATA_LONG") - 1;
2107           bitmask |= LOG_MEMORY_DATA_LONG;
2108         } else if (strncmp(p, "LOG_MEMORY_PROTECTIONS",
2109                            sizeof("LOG_MEMORY_PROTECTIONS") - 1) == 0) {
2110           p += sizeof("LOG_MEMORY_PROTECTIONS") - 1;
2111           bitmask |= LOG_MEMORY_PROTECTIONS;
2112         } else if (strncmp(p, "LOG_MEMORY", sizeof("LOG_MEMORY") - 1) == 0) {
2113           p += sizeof("LOG_MEMORY") - 1;
2114           bitmask |= LOG_MEMORY;
2115         } else if (strncmp(p, "LOG_BREAKPOINTS",
2116                            sizeof("LOG_BREAKPOINTS") - 1) == 0) {
2117           p += sizeof("LOG_BREAKPOINTS") - 1;
2118           bitmask |= LOG_BREAKPOINTS;
2119         } else if (strncmp(p, "LOG_EVENTS", sizeof("LOG_EVENTS") - 1) == 0) {
2120           p += sizeof("LOG_EVENTS") - 1;
2121           bitmask |= LOG_EVENTS;
2122         } else if (strncmp(p, "LOG_WATCHPOINTS",
2123                            sizeof("LOG_WATCHPOINTS") - 1) == 0) {
2124           p += sizeof("LOG_WATCHPOINTS") - 1;
2125           bitmask |= LOG_WATCHPOINTS;
2126         } else if (strncmp(p, "LOG_STEP", sizeof("LOG_STEP") - 1) == 0) {
2127           p += sizeof("LOG_STEP") - 1;
2128           bitmask |= LOG_STEP;
2129         } else if (strncmp(p, "LOG_TASK", sizeof("LOG_TASK") - 1) == 0) {
2130           p += sizeof("LOG_TASK") - 1;
2131           bitmask |= LOG_TASK;
2132         } else if (strncmp(p, "LOG_ALL", sizeof("LOG_ALL") - 1) == 0) {
2133           p += sizeof("LOG_ALL") - 1;
2134           bitmask |= LOG_ALL;
2135         } else if (strncmp(p, "LOG_DEFAULT", sizeof("LOG_DEFAULT") - 1) == 0) {
2136           p += sizeof("LOG_DEFAULT") - 1;
2137           bitmask |= LOG_DEFAULT;
2138         }
2139         // end of auto-generated entries
2140 
2141         else if (strncmp(p, "LOG_NONE", sizeof("LOG_NONE") - 1) == 0) {
2142           p += sizeof("LOG_NONE") - 1;
2143           bitmask = 0;
2144         } else if (strncmp(p, "LOG_RNB_MINIMAL",
2145                            sizeof("LOG_RNB_MINIMAL") - 1) == 0) {
2146           p += sizeof("LOG_RNB_MINIMAL") - 1;
2147           bitmask |= LOG_RNB_MINIMAL;
2148         } else if (strncmp(p, "LOG_RNB_MEDIUM", sizeof("LOG_RNB_MEDIUM") - 1) ==
2149                    0) {
2150           p += sizeof("LOG_RNB_MEDIUM") - 1;
2151           bitmask |= LOG_RNB_MEDIUM;
2152         } else if (strncmp(p, "LOG_RNB_MAX", sizeof("LOG_RNB_MAX") - 1) == 0) {
2153           p += sizeof("LOG_RNB_MAX") - 1;
2154           bitmask |= LOG_RNB_MAX;
2155         } else if (strncmp(p, "LOG_RNB_COMM", sizeof("LOG_RNB_COMM") - 1) ==
2156                    0) {
2157           p += sizeof("LOG_RNB_COMM") - 1;
2158           bitmask |= LOG_RNB_COMM;
2159         } else if (strncmp(p, "LOG_RNB_REMOTE", sizeof("LOG_RNB_REMOTE") - 1) ==
2160                    0) {
2161           p += sizeof("LOG_RNB_REMOTE") - 1;
2162           bitmask |= LOG_RNB_REMOTE;
2163         } else if (strncmp(p, "LOG_RNB_EVENTS", sizeof("LOG_RNB_EVENTS") - 1) ==
2164                    0) {
2165           p += sizeof("LOG_RNB_EVENTS") - 1;
2166           bitmask |= LOG_RNB_EVENTS;
2167         } else if (strncmp(p, "LOG_RNB_PROC", sizeof("LOG_RNB_PROC") - 1) ==
2168                    0) {
2169           p += sizeof("LOG_RNB_PROC") - 1;
2170           bitmask |= LOG_RNB_PROC;
2171         } else if (strncmp(p, "LOG_RNB_PACKETS",
2172                            sizeof("LOG_RNB_PACKETS") - 1) == 0) {
2173           p += sizeof("LOG_RNB_PACKETS") - 1;
2174           bitmask |= LOG_RNB_PACKETS;
2175         } else if (strncmp(p, "LOG_RNB_ALL", sizeof("LOG_RNB_ALL") - 1) == 0) {
2176           p += sizeof("LOG_RNB_ALL") - 1;
2177           bitmask |= LOG_RNB_ALL;
2178         } else if (strncmp(p, "LOG_RNB_DEFAULT",
2179                            sizeof("LOG_RNB_DEFAULT") - 1) == 0) {
2180           p += sizeof("LOG_RNB_DEFAULT") - 1;
2181           bitmask |= LOG_RNB_DEFAULT;
2182         } else if (strncmp(p, "LOG_DARWIN_LOG", sizeof("LOG_DARWIN_LOG") - 1) ==
2183                    0) {
2184           p += sizeof("LOG_DARWIN_LOG") - 1;
2185           bitmask |= LOG_DARWIN_LOG;
2186         } else if (strncmp(p, "LOG_RNB_NONE", sizeof("LOG_RNB_NONE") - 1) ==
2187                    0) {
2188           p += sizeof("LOG_RNB_NONE") - 1;
2189           bitmask = 0;
2190         } else {
2191           /* Unrecognized logging bit; ignore it.  */
2192           const char *c = strchr(p, '|');
2193           if (c) {
2194             p = c;
2195           } else {
2196             c = strchr(p, ';');
2197             if (c) {
2198               p = c;
2199             } else {
2200               // Improperly terminated word; just go to end of str
2201               p = strchr(p, '\0');
2202             }
2203           }
2204         }
2205       }
2206       // Did we get a properly formatted logging bitmask?
2207       if (p && *p == ';') {
2208         // Enable DNB logging.
2209         // Use the existing log callback if one was already configured.
2210         if (!DNBLogGetLogCallback()) {
2211           // Use the os_log()-based logger if available; otherwise,
2212           // fallback to ASL.
2213           auto log_callback = OsLogger::GetLogFunction();
2214           if (log_callback)
2215             DNBLogSetLogCallback(log_callback, nullptr);
2216           else
2217             DNBLogSetLogCallback(ASLLogCallback, nullptr);
2218         }
2219 
2220         // Update logging to use the configured log channel bitmask.
2221         DNBLogSetLogMask(bitmask);
2222         p++;
2223       }
2224     }
2225 // We're not going to support logging to a file for now.  All logging
2226 // goes through ASL or the previously arranged log callback.
2227 #if 0
2228         else if (strncmp (p, "mode=", sizeof ("mode=") - 1) == 0)
2229         {
2230             p += sizeof ("mode=") - 1;
2231             if (strncmp (p, "asl;", sizeof ("asl;") - 1) == 0)
2232             {
2233                 DNBLogToASL ();
2234                 p += sizeof ("asl;") - 1;
2235             }
2236             else if (strncmp (p, "file;", sizeof ("file;") - 1) == 0)
2237             {
2238                 DNBLogToFile ();
2239                 p += sizeof ("file;") - 1;
2240             }
2241             else
2242             {
2243                 // Ignore unknown argument
2244                 const char *c = strchr (p, ';');
2245                 if (c)
2246                     p = c + 1;
2247                 else
2248                     p = strchr (p, '\0');
2249             }
2250         }
2251         else if (strncmp (p, "filename=", sizeof ("filename=") - 1) == 0)
2252         {
2253             p += sizeof ("filename=") - 1;
2254             const char *c = strchr (p, ';');
2255             if (c == NULL)
2256             {
2257                 c = strchr (p, '\0');
2258                 continue;
2259             }
2260             char *fn = (char *) alloca (c - p + 1);
2261             strlcpy (fn, p, c - p);
2262             fn[c - p] = '\0';
2263 
2264             // A file name of "asl" is special and is another way to indicate
2265             // that logging should be done via ASL, not by file.
2266             if (strcmp (fn, "asl") == 0)
2267             {
2268                 DNBLogToASL ();
2269             }
2270             else
2271             {
2272                 FILE *f = fopen (fn, "w");
2273                 if (f)
2274                 {
2275                     DNBLogSetLogFile (f);
2276                     DNBEnableLogging (f, DNBLogGetLogMask ());
2277                     DNBLogToFile ();
2278                 }
2279             }
2280             p = c + 1;
2281         }
2282 #endif /* #if 0 to enforce ASL logging only.  */
2283     else {
2284       // Ignore unknown argument
2285       const char *c = strchr(p, ';');
2286       if (c)
2287         p = c + 1;
2288       else
2289         p = strchr(p, '\0');
2290     }
2291   }
2292 
2293   return rnb_success;
2294 }
2295 
2296 rnb_err_t RNBRemote::HandlePacket_QThreadSuffixSupported(const char *p) {
2297   m_thread_suffix_supported = true;
2298   return SendPacket("OK");
2299 }
2300 
2301 rnb_err_t RNBRemote::HandlePacket_QStartNoAckMode(const char *p) {
2302   // Send the OK packet first so the correct checksum is appended...
2303   rnb_err_t result = SendPacket("OK");
2304   m_noack_mode = true;
2305   return result;
2306 }
2307 
2308 rnb_err_t RNBRemote::HandlePacket_QSetLogging(const char *p) {
2309   p += sizeof("QSetLogging:") - 1;
2310   rnb_err_t result = set_logging(p);
2311   if (result == rnb_success)
2312     return SendPacket("OK");
2313   else
2314     return SendPacket("E35");
2315 }
2316 
2317 rnb_err_t RNBRemote::HandlePacket_QSetDisableASLR(const char *p) {
2318   extern int g_disable_aslr;
2319   p += sizeof("QSetDisableASLR:") - 1;
2320   switch (*p) {
2321   case '0':
2322     g_disable_aslr = 0;
2323     break;
2324   case '1':
2325     g_disable_aslr = 1;
2326     break;
2327   default:
2328     return SendPacket("E56");
2329   }
2330   return SendPacket("OK");
2331 }
2332 
2333 rnb_err_t RNBRemote::HandlePacket_QSetSTDIO(const char *p) {
2334   // Only set stdin/out/err if we don't already have a process
2335   if (!m_ctx.HasValidProcessID()) {
2336     bool success = false;
2337     // Check the seventh character since the packet will be one of:
2338     // QSetSTDIN
2339     // QSetSTDOUT
2340     // QSetSTDERR
2341     StdStringExtractor packet(p);
2342     packet.SetFilePos(7);
2343     char ch = packet.GetChar();
2344     while (packet.GetChar() != ':')
2345       /* Do nothing. */;
2346 
2347     switch (ch) {
2348     case 'I': // STDIN
2349       packet.GetHexByteString(m_ctx.GetSTDIN());
2350       success = !m_ctx.GetSTDIN().empty();
2351       break;
2352 
2353     case 'O': // STDOUT
2354       packet.GetHexByteString(m_ctx.GetSTDOUT());
2355       success = !m_ctx.GetSTDOUT().empty();
2356       break;
2357 
2358     case 'E': // STDERR
2359       packet.GetHexByteString(m_ctx.GetSTDERR());
2360       success = !m_ctx.GetSTDERR().empty();
2361       break;
2362 
2363     default:
2364       break;
2365     }
2366     if (success)
2367       return SendPacket("OK");
2368     return SendPacket("E57");
2369   }
2370   return SendPacket("E58");
2371 }
2372 
2373 rnb_err_t RNBRemote::HandlePacket_QSetWorkingDir(const char *p) {
2374   // Only set the working directory if we don't already have a process
2375   if (!m_ctx.HasValidProcessID()) {
2376     StdStringExtractor packet(p += sizeof("QSetWorkingDir:") - 1);
2377     if (packet.GetHexByteString(m_ctx.GetWorkingDir())) {
2378       struct stat working_dir_stat;
2379       if (::stat(m_ctx.GetWorkingDirPath(), &working_dir_stat) == -1) {
2380         m_ctx.GetWorkingDir().clear();
2381         return SendPacket("E61"); // Working directory doesn't exist...
2382       } else if ((working_dir_stat.st_mode & S_IFMT) == S_IFDIR) {
2383         return SendPacket("OK");
2384       } else {
2385         m_ctx.GetWorkingDir().clear();
2386         return SendPacket("E62"); // Working directory isn't a directory...
2387       }
2388     }
2389     return SendPacket("E59"); // Invalid path
2390   }
2391   return SendPacket(
2392       "E60"); // Already had a process, too late to set working dir
2393 }
2394 
2395 rnb_err_t RNBRemote::HandlePacket_QSyncThreadState(const char *p) {
2396   if (!m_ctx.HasValidProcessID()) {
2397     // We allow gdb to connect to a server that hasn't started running
2398     // the target yet.  gdb still wants to ask questions about it and
2399     // freaks out if it gets an error.  So just return OK here.
2400     return SendPacket("OK");
2401   }
2402 
2403   errno = 0;
2404   p += strlen("QSyncThreadState:");
2405   nub_thread_t tid = strtoul(p, NULL, 16);
2406   if (errno != 0 && tid == 0) {
2407     return HandlePacket_ILLFORMED(
2408         __FILE__, __LINE__, p,
2409         "Invalid thread number in QSyncThreadState packet");
2410   }
2411   if (DNBProcessSyncThreadState(m_ctx.ProcessID(), tid))
2412     return SendPacket("OK");
2413   else
2414     return SendPacket("E61");
2415 }
2416 
2417 rnb_err_t RNBRemote::HandlePacket_QSetDetachOnError(const char *p) {
2418   p += sizeof("QSetDetachOnError:") - 1;
2419   bool should_detach = true;
2420   switch (*p) {
2421   case '0':
2422     should_detach = false;
2423     break;
2424   case '1':
2425     should_detach = true;
2426     break;
2427   default:
2428     return HandlePacket_ILLFORMED(
2429         __FILE__, __LINE__, p,
2430         "Invalid value for QSetDetachOnError - should be 0 or 1");
2431     break;
2432   }
2433 
2434   m_ctx.SetDetachOnError(should_detach);
2435   return SendPacket("OK");
2436 }
2437 
2438 rnb_err_t RNBRemote::HandlePacket_qStructuredDataPlugins(const char *p) {
2439   // We'll return a JSON array of supported packet types.
2440   // The type is significant.  For each of the supported
2441   // packet types that have been enabled, there will be a
2442   // 'J' async packet sent to the client with payload data.
2443   // This payload data will be a JSON dictionary, and the
2444   // top level dictionary will contain a string field with
2445   // its value set to the relevant packet type from this list.
2446   JSONGenerator::Array supported_json_packets;
2447 
2448   // Check for DarwinLog (libtrace os_log/activity support).
2449   if (DarwinLogCollector::IsSupported())
2450     supported_json_packets.AddItem(
2451         JSONGenerator::StringSP(new JSONGenerator::String("DarwinLog")));
2452 
2453   // Send back the array.
2454   std::ostringstream stream;
2455   supported_json_packets.Dump(stream);
2456   return SendPacket(stream.str());
2457 }
2458 
2459 rnb_err_t RNBRemote::HandlePacket_QConfigureDarwinLog(const char *p) {
2460   if (!DarwinLogCollector::IsSupported()) {
2461     // We should never have been given this request.
2462     return SendPacket("E89");
2463   }
2464 
2465   // Ensure we have a process.  We expect a separate configure request for
2466   // each process launched/attached.
2467   const nub_process_t pid = m_ctx.ProcessID();
2468   if (pid == INVALID_NUB_PROCESS)
2469     return SendPacket("E94");
2470 
2471   // Get the configuration dictionary.
2472   p += strlen("QConfigureDarwinLog:");
2473 
2474   // The configuration dictionary is binary encoded.
2475   std::vector<uint8_t> unescaped_config_data = decode_binary_data(p, -1);
2476   std::string unescaped_config_string((const char *)&unescaped_config_data[0],
2477                                       unescaped_config_data.size());
2478   DNBLogThreadedIf(LOG_DARWIN_LOG, "DarwinLog: received config data: \"%s\"",
2479                    unescaped_config_string.c_str());
2480   auto configuration_sp =
2481       JSONParser(unescaped_config_string.c_str()).ParseJSONValue();
2482   if (!configuration_sp) {
2483     // Malformed request - we require configuration data
2484     // indicating whether we're enabling or disabling.
2485     return SendPacket("E90");
2486   }
2487 
2488   if (!JSONObject::classof(configuration_sp.get())) {
2489     // Configuration data is not of the right type.
2490     return SendPacket("E91");
2491   }
2492   JSONObject &config_dict = *static_cast<JSONObject *>(configuration_sp.get());
2493 
2494   // Check if we're enabling or disabling.
2495   auto enabled_sp = config_dict.GetObject("enabled");
2496   if (!enabled_sp) {
2497     // Missing required "enabled" field.
2498     return SendPacket("E92");
2499   }
2500   if (!JSONTrue::classof(enabled_sp.get()) &&
2501       !JSONFalse::classof(enabled_sp.get())) {
2502     // Should be a boolean type, but wasn't.
2503     return SendPacket("E93");
2504   }
2505   const bool enabling = JSONTrue::classof(enabled_sp.get());
2506 
2507   // TODO - handle other configuration parameters here.
2508 
2509   // Shut down any active activity stream for the process.
2510   DarwinLogCollector::CancelStreamForProcess(pid);
2511 
2512   if (enabling) {
2513     // Look up the procecess.
2514     if (!DarwinLogCollector::StartCollectingForProcess(pid, config_dict))
2515       return SendPacket("E95");
2516   }
2517 
2518   return SendPacket("OK");
2519 }
2520 
2521 rnb_err_t RNBRemote::HandlePacket_QListThreadsInStopReply(const char *p) {
2522   // If this packet is received, it allows us to send an extra key/value
2523   // pair in the stop reply packets where we will list all of the thread IDs
2524   // separated by commas:
2525   //
2526   //  "threads:10a,10b,10c;"
2527   //
2528   // This will get included in the stop reply packet as something like:
2529   //
2530   //  "T11thread:10a;00:00000000;01:00010203:threads:10a,10b,10c;"
2531   //
2532   // This can save two packets on each stop: qfThreadInfo/qsThreadInfo and
2533   // speed things up a bit.
2534   //
2535   // Send the OK packet first so the correct checksum is appended...
2536   rnb_err_t result = SendPacket("OK");
2537   m_list_threads_in_stop_reply = true;
2538 
2539   return result;
2540 }
2541 
2542 rnb_err_t RNBRemote::HandlePacket_QSetMaxPayloadSize(const char *p) {
2543   /* The number of characters in a packet payload that gdb is
2544    prepared to accept.  The packet-start char, packet-end char,
2545    2 checksum chars and terminating null character are not included
2546    in this size.  */
2547   p += sizeof("QSetMaxPayloadSize:") - 1;
2548   errno = 0;
2549   uint32_t size = static_cast<uint32_t>(strtoul(p, NULL, 16));
2550   if (errno != 0 && size == 0) {
2551     return HandlePacket_ILLFORMED(
2552         __FILE__, __LINE__, p, "Invalid length in QSetMaxPayloadSize packet");
2553   }
2554   m_max_payload_size = size;
2555   return SendPacket("OK");
2556 }
2557 
2558 rnb_err_t RNBRemote::HandlePacket_QSetMaxPacketSize(const char *p) {
2559   /* This tells us the largest packet that gdb can handle.
2560    i.e. the size of gdb's packet-reading buffer.
2561    QSetMaxPayloadSize is preferred because it is less ambiguous.  */
2562   p += sizeof("QSetMaxPacketSize:") - 1;
2563   errno = 0;
2564   uint32_t size = static_cast<uint32_t>(strtoul(p, NULL, 16));
2565   if (errno != 0 && size == 0) {
2566     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
2567                                   "Invalid length in QSetMaxPacketSize packet");
2568   }
2569   m_max_payload_size = size - 5;
2570   return SendPacket("OK");
2571 }
2572 
2573 rnb_err_t RNBRemote::HandlePacket_QEnvironment(const char *p) {
2574   /* This sets the environment for the target program.  The packet is of the
2575    form:
2576 
2577    QEnvironment:VARIABLE=VALUE
2578 
2579    */
2580 
2581   DNBLogThreadedIf(
2582       LOG_RNB_REMOTE, "%8u RNBRemote::%s Handling QEnvironment: \"%s\"",
2583       (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, p);
2584 
2585   p += sizeof("QEnvironment:") - 1;
2586   RNBContext &ctx = Context();
2587 
2588   ctx.PushEnvironment(p);
2589   return SendPacket("OK");
2590 }
2591 
2592 rnb_err_t RNBRemote::HandlePacket_QEnvironmentHexEncoded(const char *p) {
2593   /* This sets the environment for the target program.  The packet is of the
2594      form:
2595 
2596       QEnvironmentHexEncoded:VARIABLE=VALUE
2597 
2598       The VARIABLE=VALUE part is sent hex-encoded so characters like '#' with
2599      special
2600       meaning in the remote protocol won't break it.
2601   */
2602 
2603   DNBLogThreadedIf(LOG_RNB_REMOTE,
2604                    "%8u RNBRemote::%s Handling QEnvironmentHexEncoded: \"%s\"",
2605                    (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
2606                    __FUNCTION__, p);
2607 
2608   p += sizeof("QEnvironmentHexEncoded:") - 1;
2609 
2610   std::string arg;
2611   const char *c;
2612   c = p;
2613   while (*c != '\0') {
2614     if (*(c + 1) == '\0') {
2615       return HandlePacket_ILLFORMED(
2616           __FILE__, __LINE__, p,
2617           "non-hex char in arg on 'QEnvironmentHexEncoded' pkt");
2618     }
2619     char smallbuf[3];
2620     smallbuf[0] = *c;
2621     smallbuf[1] = *(c + 1);
2622     smallbuf[2] = '\0';
2623     errno = 0;
2624     int ch = static_cast<int>(strtoul(smallbuf, NULL, 16));
2625     if (errno != 0 && ch == 0) {
2626       return HandlePacket_ILLFORMED(
2627           __FILE__, __LINE__, p,
2628           "non-hex char in arg on 'QEnvironmentHexEncoded' pkt");
2629     }
2630     arg.push_back(ch);
2631     c += 2;
2632   }
2633 
2634   RNBContext &ctx = Context();
2635   if (arg.length() > 0)
2636     ctx.PushEnvironment(arg.c_str());
2637 
2638   return SendPacket("OK");
2639 }
2640 
2641 rnb_err_t RNBRemote::HandlePacket_QLaunchArch(const char *p) {
2642   p += sizeof("QLaunchArch:") - 1;
2643   if (DNBSetArchitecture(p))
2644     return SendPacket("OK");
2645   return SendPacket("E63");
2646 }
2647 
2648 rnb_err_t RNBRemote::HandlePacket_QSetProcessEvent(const char *p) {
2649   p += sizeof("QSetProcessEvent:") - 1;
2650   // If the process is running, then send the event to the process, otherwise
2651   // store it in the context.
2652   if (Context().HasValidProcessID()) {
2653     if (DNBProcessSendEvent(Context().ProcessID(), p))
2654       return SendPacket("OK");
2655     else
2656       return SendPacket("E80");
2657   } else {
2658     Context().PushProcessEvent(p);
2659   }
2660   return SendPacket("OK");
2661 }
2662 
2663 void append_hex_value(std::ostream &ostrm, const void *buf, size_t buf_size,
2664                       bool swap) {
2665   int i;
2666   const uint8_t *p = (const uint8_t *)buf;
2667   if (swap) {
2668     for (i = static_cast<int>(buf_size) - 1; i >= 0; i--)
2669       ostrm << RAWHEX8(p[i]);
2670   } else {
2671     for (size_t i = 0; i < buf_size; i++)
2672       ostrm << RAWHEX8(p[i]);
2673   }
2674 }
2675 
2676 std::string cstring_to_asciihex_string(const char *str) {
2677   std::string hex_str;
2678   hex_str.reserve (strlen (str) * 2);
2679   while (str && *str) {
2680     char hexbuf[5];
2681     snprintf (hexbuf, sizeof(hexbuf), "%02x", *str++);
2682     hex_str += hexbuf;
2683   }
2684   return hex_str;
2685 }
2686 
2687 void append_hexified_string(std::ostream &ostrm, const std::string &string) {
2688   size_t string_size = string.size();
2689   const char *string_buf = string.c_str();
2690   for (size_t i = 0; i < string_size; i++) {
2691     ostrm << RAWHEX8(*(string_buf + i));
2692   }
2693 }
2694 
2695 void register_value_in_hex_fixed_width(std::ostream &ostrm, nub_process_t pid,
2696                                        nub_thread_t tid,
2697                                        const register_map_entry_t *reg,
2698                                        const DNBRegisterValue *reg_value_ptr) {
2699   if (reg != NULL) {
2700     DNBRegisterValue reg_value;
2701     if (reg_value_ptr == NULL) {
2702       if (DNBThreadGetRegisterValueByID(pid, tid, reg->nub_info.set,
2703                                         reg->nub_info.reg, &reg_value))
2704         reg_value_ptr = &reg_value;
2705     }
2706 
2707     if (reg_value_ptr) {
2708       append_hex_value(ostrm, reg_value_ptr->value.v_uint8, reg->nub_info.size,
2709                        false);
2710     } else {
2711       // If we fail to read a register value, check if it has a default
2712       // fail value. If it does, return this instead in case some of
2713       // the registers are not available on the current system.
2714       if (reg->nub_info.size > 0) {
2715         std::basic_string<uint8_t> zeros(reg->nub_info.size, '\0');
2716         append_hex_value(ostrm, zeros.data(), zeros.size(), false);
2717       }
2718     }
2719   }
2720 }
2721 
2722 void debugserver_regnum_with_fixed_width_hex_register_value(
2723     std::ostream &ostrm, nub_process_t pid, nub_thread_t tid,
2724     const register_map_entry_t *reg, const DNBRegisterValue *reg_value_ptr) {
2725   // Output the register number as 'NN:VVVVVVVV;' where NN is a 2 bytes HEX
2726   // gdb register number, and VVVVVVVV is the correct number of hex bytes
2727   // as ASCII for the register value.
2728   if (reg != NULL) {
2729     ostrm << RAWHEX8(reg->debugserver_regnum) << ':';
2730     register_value_in_hex_fixed_width(ostrm, pid, tid, reg, reg_value_ptr);
2731     ostrm << ';';
2732   }
2733 }
2734 
2735 void RNBRemote::DispatchQueueOffsets::GetThreadQueueInfo(
2736     nub_process_t pid, nub_addr_t dispatch_qaddr, nub_addr_t &dispatch_queue_t,
2737     std::string &queue_name, uint64_t &queue_width,
2738     uint64_t &queue_serialnum) const {
2739   queue_name.clear();
2740   queue_width = 0;
2741   queue_serialnum = 0;
2742 
2743   if (IsValid() && dispatch_qaddr != INVALID_NUB_ADDRESS &&
2744       dispatch_qaddr != 0) {
2745     dispatch_queue_t = DNBProcessMemoryReadPointer(pid, dispatch_qaddr);
2746     if (dispatch_queue_t) {
2747       queue_width = DNBProcessMemoryReadInteger(
2748           pid, dispatch_queue_t + dqo_width, dqo_width_size, 0);
2749       queue_serialnum = DNBProcessMemoryReadInteger(
2750           pid, dispatch_queue_t + dqo_serialnum, dqo_serialnum_size, 0);
2751 
2752       if (dqo_version >= 4) {
2753         // libdispatch versions 4+, pointer to dispatch name is in the
2754         // queue structure.
2755         nub_addr_t pointer_to_label_address = dispatch_queue_t + dqo_label;
2756         nub_addr_t label_addr =
2757             DNBProcessMemoryReadPointer(pid, pointer_to_label_address);
2758         if (label_addr)
2759           queue_name = DNBProcessMemoryReadCString(pid, label_addr);
2760       } else {
2761         // libdispatch versions 1-3, dispatch name is a fixed width char array
2762         // in the queue structure.
2763         queue_name = DNBProcessMemoryReadCStringFixed(
2764             pid, dispatch_queue_t + dqo_label, dqo_label_size);
2765       }
2766     }
2767   }
2768 }
2769 
2770 struct StackMemory {
2771   uint8_t bytes[2 * sizeof(nub_addr_t)];
2772   nub_size_t length;
2773 };
2774 typedef std::map<nub_addr_t, StackMemory> StackMemoryMap;
2775 
2776 static void ReadStackMemory(nub_process_t pid, nub_thread_t tid,
2777                             StackMemoryMap &stack_mmap,
2778                             uint32_t backtrace_limit = 256) {
2779   DNBRegisterValue reg_value;
2780   if (DNBThreadGetRegisterValueByID(pid, tid, REGISTER_SET_GENERIC,
2781                                     GENERIC_REGNUM_FP, &reg_value)) {
2782     uint32_t frame_count = 0;
2783     uint64_t fp = 0;
2784     if (reg_value.info.size == 4)
2785       fp = reg_value.value.uint32;
2786     else
2787       fp = reg_value.value.uint64;
2788     while (fp != 0) {
2789       // Make sure we never recurse more than 256 times so we don't recurse too
2790       // far or
2791       // store up too much memory in the expedited cache
2792       if (++frame_count > backtrace_limit)
2793         break;
2794 
2795       const nub_size_t read_size = reg_value.info.size * 2;
2796       StackMemory stack_memory;
2797       stack_memory.length = read_size;
2798       if (DNBProcessMemoryRead(pid, fp, read_size, stack_memory.bytes) !=
2799           read_size)
2800         break;
2801       // Make sure we don't try to put the same stack memory in more than once
2802       if (stack_mmap.find(fp) != stack_mmap.end())
2803         break;
2804       // Put the entry into the cache
2805       stack_mmap[fp] = stack_memory;
2806       // Dereference the frame pointer to get to the previous frame pointer
2807       if (reg_value.info.size == 4)
2808         fp = ((uint32_t *)stack_memory.bytes)[0];
2809       else
2810         fp = ((uint64_t *)stack_memory.bytes)[0];
2811     }
2812   }
2813 }
2814 
2815 rnb_err_t RNBRemote::SendStopReplyPacketForThread(nub_thread_t tid) {
2816   const nub_process_t pid = m_ctx.ProcessID();
2817   if (pid == INVALID_NUB_PROCESS)
2818     return SendPacket("E50");
2819 
2820   struct DNBThreadStopInfo tid_stop_info;
2821 
2822   /* Fill the remaining space in this packet with as many registers
2823    as we can stuff in there.  */
2824 
2825   if (DNBThreadGetStopReason(pid, tid, &tid_stop_info)) {
2826     const bool did_exec = tid_stop_info.reason == eStopTypeExec;
2827     if (did_exec) {
2828       RNBRemote::InitializeRegisters(true);
2829 
2830       // Reset any symbols that need resetting when we exec
2831       m_dispatch_queue_offsets_addr = INVALID_NUB_ADDRESS;
2832       m_dispatch_queue_offsets.Clear();
2833     }
2834 
2835     std::ostringstream ostrm;
2836     // Output the T packet with the thread
2837     ostrm << 'T';
2838     int signum = tid_stop_info.details.signal.signo;
2839     DNBLogThreadedIf(
2840         LOG_RNB_PROC, "%8d %s got signal signo = %u, exc_type = %u",
2841         (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__,
2842         signum, tid_stop_info.details.exception.type);
2843 
2844     // Translate any mach exceptions to gdb versions, unless they are
2845     // common exceptions like a breakpoint or a soft signal.
2846     switch (tid_stop_info.details.exception.type) {
2847     default:
2848       signum = 0;
2849       break;
2850     case EXC_BREAKPOINT:
2851       signum = SIGTRAP;
2852       break;
2853     case EXC_BAD_ACCESS:
2854       signum = TARGET_EXC_BAD_ACCESS;
2855       break;
2856     case EXC_BAD_INSTRUCTION:
2857       signum = TARGET_EXC_BAD_INSTRUCTION;
2858       break;
2859     case EXC_ARITHMETIC:
2860       signum = TARGET_EXC_ARITHMETIC;
2861       break;
2862     case EXC_EMULATION:
2863       signum = TARGET_EXC_EMULATION;
2864       break;
2865     case EXC_SOFTWARE:
2866       if (tid_stop_info.details.exception.data_count == 2 &&
2867           tid_stop_info.details.exception.data[0] == EXC_SOFT_SIGNAL)
2868         signum = static_cast<int>(tid_stop_info.details.exception.data[1]);
2869       else
2870         signum = TARGET_EXC_SOFTWARE;
2871       break;
2872     }
2873 
2874     ostrm << RAWHEX8(signum & 0xff);
2875 
2876     ostrm << std::hex << "thread:" << tid << ';';
2877 
2878     const char *thread_name = DNBThreadGetName(pid, tid);
2879     if (thread_name && thread_name[0]) {
2880       size_t thread_name_len = strlen(thread_name);
2881 
2882       if (::strcspn(thread_name, "$#+-;:") == thread_name_len)
2883         ostrm << std::hex << "name:" << thread_name << ';';
2884       else {
2885         // the thread name contains special chars, send as hex bytes
2886         ostrm << std::hex << "hexname:";
2887         const uint8_t *u_thread_name = (const uint8_t *)thread_name;
2888         for (size_t i = 0; i < thread_name_len; i++)
2889           ostrm << RAWHEX8(u_thread_name[i]);
2890         ostrm << ';';
2891       }
2892     }
2893 
2894     // If a 'QListThreadsInStopReply' was sent to enable this feature, we
2895     // will send all thread IDs back in the "threads" key whose value is
2896     // a list of hex thread IDs separated by commas:
2897     //  "threads:10a,10b,10c;"
2898     // This will save the debugger from having to send a pair of qfThreadInfo
2899     // and qsThreadInfo packets, but it also might take a lot of room in the
2900     // stop reply packet, so it must be enabled only on systems where there
2901     // are no limits on packet lengths.
2902     if (m_list_threads_in_stop_reply) {
2903       const nub_size_t numthreads = DNBProcessGetNumThreads(pid);
2904       if (numthreads > 0) {
2905         std::vector<uint64_t> pc_values;
2906         ostrm << std::hex << "threads:";
2907         for (nub_size_t i = 0; i < numthreads; ++i) {
2908           nub_thread_t th = DNBProcessGetThreadAtIndex(pid, i);
2909           if (i > 0)
2910             ostrm << ',';
2911           ostrm << std::hex << th;
2912           DNBRegisterValue pc_regval;
2913           if (DNBThreadGetRegisterValueByID(pid, th, REGISTER_SET_GENERIC,
2914                                             GENERIC_REGNUM_PC, &pc_regval)) {
2915             uint64_t pc = INVALID_NUB_ADDRESS;
2916             if (pc_regval.value.uint64 != INVALID_NUB_ADDRESS) {
2917               if (pc_regval.info.size == 4) {
2918                 pc = pc_regval.value.uint32;
2919               } else if (pc_regval.info.size == 8) {
2920                 pc = pc_regval.value.uint64;
2921               }
2922               if (pc != INVALID_NUB_ADDRESS) {
2923                 pc_values.push_back(pc);
2924               }
2925             }
2926           }
2927         }
2928         ostrm << ';';
2929 
2930         // If we failed to get any of the thread pc values, the size of our
2931         // vector will not
2932         // be the same as the # of threads.  Don't provide any expedited thread
2933         // pc values in
2934         // that case.  This should not happen.
2935         if (pc_values.size() == numthreads) {
2936           ostrm << std::hex << "thread-pcs:";
2937           for (nub_size_t i = 0; i < numthreads; ++i) {
2938             if (i > 0)
2939               ostrm << ',';
2940             ostrm << std::hex << pc_values[i];
2941           }
2942           ostrm << ';';
2943         }
2944       }
2945 
2946       // Include JSON info that describes the stop reason for any threads
2947       // that actually have stop reasons. We use the new "jstopinfo" key
2948       // whose values is hex ascii JSON that contains the thread IDs
2949       // thread stop info only for threads that have stop reasons. Only send
2950       // this if we have more than one thread otherwise this packet has all
2951       // the info it needs.
2952       if (numthreads > 1) {
2953         const bool threads_with_valid_stop_info_only = true;
2954         JSONGenerator::ObjectSP threads_info_sp =
2955             GetJSONThreadsInfo(threads_with_valid_stop_info_only);
2956         if (threads_info_sp) {
2957           ostrm << std::hex << "jstopinfo:";
2958           std::ostringstream json_strm;
2959           threads_info_sp->Dump(json_strm);
2960           append_hexified_string(ostrm, json_strm.str());
2961           ostrm << ';';
2962         }
2963       }
2964     }
2965 
2966     if (g_num_reg_entries == 0)
2967       InitializeRegisters();
2968 
2969     if (g_reg_entries != NULL) {
2970       DNBRegisterValue reg_value;
2971       for (uint32_t reg = 0; reg < g_num_reg_entries; reg++) {
2972         // Expedite all registers in the first register set that aren't
2973         // contained in other registers
2974         if (g_reg_entries[reg].nub_info.set == 1 &&
2975             g_reg_entries[reg].nub_info.value_regs == NULL) {
2976           if (!DNBThreadGetRegisterValueByID(
2977                   pid, tid, g_reg_entries[reg].nub_info.set,
2978                   g_reg_entries[reg].nub_info.reg, &reg_value))
2979             continue;
2980 
2981           debugserver_regnum_with_fixed_width_hex_register_value(
2982               ostrm, pid, tid, &g_reg_entries[reg], &reg_value);
2983         }
2984       }
2985     }
2986 
2987     if (did_exec) {
2988       ostrm << "reason:exec;";
2989     } else if (tid_stop_info.details.exception.type) {
2990       ostrm << "metype:" << std::hex << tid_stop_info.details.exception.type
2991             << ';';
2992       ostrm << "mecount:" << std::hex
2993             << tid_stop_info.details.exception.data_count << ';';
2994       for (nub_size_t i = 0; i < tid_stop_info.details.exception.data_count;
2995            ++i)
2996         ostrm << "medata:" << std::hex
2997               << tid_stop_info.details.exception.data[i] << ';';
2998     }
2999 
3000     // Add expedited stack memory so stack backtracing doesn't need to read
3001     // anything from the
3002     // frame pointer chain.
3003     StackMemoryMap stack_mmap;
3004     ReadStackMemory(pid, tid, stack_mmap, 2);
3005     if (!stack_mmap.empty()) {
3006       for (const auto &stack_memory : stack_mmap) {
3007         ostrm << "memory:" << HEXBASE << stack_memory.first << '=';
3008         append_hex_value(ostrm, stack_memory.second.bytes,
3009                          stack_memory.second.length, false);
3010         ostrm << ';';
3011       }
3012     }
3013 
3014     return SendPacket(ostrm.str());
3015   }
3016   return SendPacket("E51");
3017 }
3018 
3019 /* '?'
3020  The stop reply packet - tell gdb what the status of the inferior is.
3021  Often called the questionmark_packet.  */
3022 
3023 rnb_err_t RNBRemote::HandlePacket_last_signal(const char *unused) {
3024   if (!m_ctx.HasValidProcessID()) {
3025     // Inferior is not yet specified/running
3026     return SendPacket("E02");
3027   }
3028 
3029   nub_process_t pid = m_ctx.ProcessID();
3030   nub_state_t pid_state = DNBProcessGetState(pid);
3031 
3032   switch (pid_state) {
3033   case eStateAttaching:
3034   case eStateLaunching:
3035   case eStateRunning:
3036   case eStateStepping:
3037   case eStateDetached:
3038     return rnb_success; // Ignore
3039 
3040   case eStateSuspended:
3041   case eStateStopped:
3042   case eStateCrashed: {
3043     nub_thread_t tid = DNBProcessGetCurrentThread(pid);
3044     // Make sure we set the current thread so g and p packets return
3045     // the data the gdb will expect.
3046     SetCurrentThread(tid);
3047 
3048     SendStopReplyPacketForThread(tid);
3049   } break;
3050 
3051   case eStateInvalid:
3052   case eStateUnloaded:
3053   case eStateExited: {
3054     char pid_exited_packet[16] = "";
3055     int pid_status = 0;
3056     // Process exited with exit status
3057     if (!DNBProcessGetExitStatus(pid, &pid_status))
3058       pid_status = 0;
3059 
3060     if (pid_status) {
3061       if (WIFEXITED(pid_status))
3062         snprintf(pid_exited_packet, sizeof(pid_exited_packet), "W%02x",
3063                  WEXITSTATUS(pid_status));
3064       else if (WIFSIGNALED(pid_status))
3065         snprintf(pid_exited_packet, sizeof(pid_exited_packet), "X%02x",
3066                  WEXITSTATUS(pid_status));
3067       else if (WIFSTOPPED(pid_status))
3068         snprintf(pid_exited_packet, sizeof(pid_exited_packet), "S%02x",
3069                  WSTOPSIG(pid_status));
3070     }
3071 
3072     // If we have an empty exit packet, lets fill one in to be safe.
3073     if (!pid_exited_packet[0]) {
3074       strlcpy(pid_exited_packet, "W00", sizeof(pid_exited_packet) - 1);
3075       pid_exited_packet[sizeof(pid_exited_packet) - 1] = '\0';
3076     }
3077 
3078     const char *exit_info = DNBProcessGetExitInfo(pid);
3079     if (exit_info != NULL && *exit_info != '\0') {
3080       std::ostringstream exit_packet;
3081       exit_packet << pid_exited_packet;
3082       exit_packet << ';';
3083       exit_packet << RAW_HEXBASE << "description";
3084       exit_packet << ':';
3085       for (size_t i = 0; exit_info[i] != '\0'; i++)
3086         exit_packet << RAWHEX8(exit_info[i]);
3087       exit_packet << ';';
3088       return SendPacket(exit_packet.str());
3089     } else
3090       return SendPacket(pid_exited_packet);
3091   } break;
3092   }
3093   return rnb_success;
3094 }
3095 
3096 rnb_err_t RNBRemote::HandlePacket_M(const char *p) {
3097   if (p == NULL || p[0] == '\0' || strlen(p) < 3) {
3098     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, "Too short M packet");
3099   }
3100 
3101   char *c;
3102   p++;
3103   errno = 0;
3104   nub_addr_t addr = strtoull(p, &c, 16);
3105   if (errno != 0 && addr == 0) {
3106     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3107                                   "Invalid address in M packet");
3108   }
3109   if (*c != ',') {
3110     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3111                                   "Comma sep missing in M packet");
3112   }
3113 
3114   /* Advance 'p' to the length part of the packet.  */
3115   p += (c - p) + 1;
3116 
3117   errno = 0;
3118   unsigned long length = strtoul(p, &c, 16);
3119   if (errno != 0 && length == 0) {
3120     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3121                                   "Invalid length in M packet");
3122   }
3123   if (length == 0) {
3124     return SendPacket("OK");
3125   }
3126 
3127   if (*c != ':') {
3128     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3129                                   "Missing colon in M packet");
3130   }
3131   /* Advance 'p' to the data part of the packet.  */
3132   p += (c - p) + 1;
3133 
3134   size_t datalen = strlen(p);
3135   if (datalen & 0x1) {
3136     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3137                                   "Uneven # of hex chars for data in M packet");
3138   }
3139   if (datalen == 0) {
3140     return SendPacket("OK");
3141   }
3142 
3143   uint8_t *buf = (uint8_t *)alloca(datalen / 2);
3144   uint8_t *i = buf;
3145 
3146   while (*p != '\0' && *(p + 1) != '\0') {
3147     char hexbuf[3];
3148     hexbuf[0] = *p;
3149     hexbuf[1] = *(p + 1);
3150     hexbuf[2] = '\0';
3151     errno = 0;
3152     uint8_t byte = strtoul(hexbuf, NULL, 16);
3153     if (errno != 0 && byte == 0) {
3154       return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3155                                     "Invalid hex byte in M packet");
3156     }
3157     *i++ = byte;
3158     p += 2;
3159   }
3160 
3161   nub_size_t wrote =
3162       DNBProcessMemoryWrite(m_ctx.ProcessID(), addr, length, buf);
3163   if (wrote != length)
3164     return SendPacket("E09");
3165   else
3166     return SendPacket("OK");
3167 }
3168 
3169 rnb_err_t RNBRemote::HandlePacket_m(const char *p) {
3170   if (p == NULL || p[0] == '\0' || strlen(p) < 3) {
3171     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, "Too short m packet");
3172   }
3173 
3174   char *c;
3175   p++;
3176   errno = 0;
3177   nub_addr_t addr = strtoull(p, &c, 16);
3178   if (errno != 0 && addr == 0) {
3179     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3180                                   "Invalid address in m packet");
3181   }
3182   if (*c != ',') {
3183     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3184                                   "Comma sep missing in m packet");
3185   }
3186 
3187   /* Advance 'p' to the length part of the packet.  */
3188   p += (c - p) + 1;
3189 
3190   errno = 0;
3191   auto length = strtoul(p, NULL, 16);
3192   if (errno != 0 && length == 0) {
3193     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3194                                   "Invalid length in m packet");
3195   }
3196   if (length == 0) {
3197     return SendPacket("");
3198   }
3199 
3200   std::string buf(length, '\0');
3201   if (buf.empty()) {
3202     return SendPacket("E78");
3203   }
3204   nub_size_t bytes_read =
3205       DNBProcessMemoryRead(m_ctx.ProcessID(), addr, buf.size(), &buf[0]);
3206   if (bytes_read == 0) {
3207     return SendPacket("E08");
3208   }
3209 
3210   // "The reply may contain fewer bytes than requested if the server was able
3211   //  to read only part of the region of memory."
3212   length = bytes_read;
3213 
3214   std::ostringstream ostrm;
3215   for (unsigned long i = 0; i < length; i++)
3216     ostrm << RAWHEX8(buf[i]);
3217   return SendPacket(ostrm.str());
3218 }
3219 
3220 // Read memory, sent it up as binary data.
3221 // Usage:  xADDR,LEN
3222 // ADDR and LEN are both base 16.
3223 
3224 // Responds with 'OK' for zero-length request
3225 // or
3226 //
3227 // DATA
3228 //
3229 // where DATA is the binary data payload.
3230 
3231 rnb_err_t RNBRemote::HandlePacket_x(const char *p) {
3232   if (p == NULL || p[0] == '\0' || strlen(p) < 3) {
3233     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, "Too short X packet");
3234   }
3235 
3236   char *c;
3237   p++;
3238   errno = 0;
3239   nub_addr_t addr = strtoull(p, &c, 16);
3240   if (errno != 0) {
3241     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3242                                   "Invalid address in X packet");
3243   }
3244   if (*c != ',') {
3245     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3246                                   "Comma sep missing in X packet");
3247   }
3248 
3249   /* Advance 'p' to the number of bytes to be read.  */
3250   p += (c - p) + 1;
3251 
3252   errno = 0;
3253   auto length = strtoul(p, NULL, 16);
3254   if (errno != 0) {
3255     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3256                                   "Invalid length in x packet");
3257   }
3258 
3259   // zero length read means this is a test of whether that packet is implemented
3260   // or not.
3261   if (length == 0) {
3262     return SendPacket("OK");
3263   }
3264 
3265   std::vector<uint8_t> buf(length);
3266 
3267   if (buf.capacity() != length) {
3268     return SendPacket("E79");
3269   }
3270   nub_size_t bytes_read =
3271       DNBProcessMemoryRead(m_ctx.ProcessID(), addr, buf.size(), &buf[0]);
3272   if (bytes_read == 0) {
3273     return SendPacket("E80");
3274   }
3275 
3276   std::vector<uint8_t> buf_quoted;
3277   buf_quoted.reserve(bytes_read + 30);
3278   for (nub_size_t i = 0; i < bytes_read; i++) {
3279     if (buf[i] == '#' || buf[i] == '$' || buf[i] == '}' || buf[i] == '*') {
3280       buf_quoted.push_back(0x7d);
3281       buf_quoted.push_back(buf[i] ^ 0x20);
3282     } else {
3283       buf_quoted.push_back(buf[i]);
3284     }
3285   }
3286   length = buf_quoted.size();
3287 
3288   std::ostringstream ostrm;
3289   for (unsigned long i = 0; i < length; i++)
3290     ostrm << buf_quoted[i];
3291 
3292   return SendPacket(ostrm.str());
3293 }
3294 
3295 rnb_err_t RNBRemote::HandlePacket_X(const char *p) {
3296   if (p == NULL || p[0] == '\0' || strlen(p) < 3) {
3297     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, "Too short X packet");
3298   }
3299 
3300   char *c;
3301   p++;
3302   errno = 0;
3303   nub_addr_t addr = strtoull(p, &c, 16);
3304   if (errno != 0 && addr == 0) {
3305     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3306                                   "Invalid address in X packet");
3307   }
3308   if (*c != ',') {
3309     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3310                                   "Comma sep missing in X packet");
3311   }
3312 
3313   /* Advance 'p' to the length part of the packet.  NB this is the length of the
3314      packet
3315      including any escaped chars.  The data payload may be a little bit smaller
3316      after
3317      decoding.  */
3318   p += (c - p) + 1;
3319 
3320   errno = 0;
3321   auto length = strtoul(p, NULL, 16);
3322   if (errno != 0 && length == 0) {
3323     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3324                                   "Invalid length in X packet");
3325   }
3326 
3327   // I think gdb sends a zero length write request to test whether this
3328   // packet is accepted.
3329   if (length == 0) {
3330     return SendPacket("OK");
3331   }
3332 
3333   std::vector<uint8_t> data = decode_binary_data(c, -1);
3334   std::vector<uint8_t>::const_iterator it;
3335   uint8_t *buf = (uint8_t *)alloca(data.size());
3336   uint8_t *i = buf;
3337   for (it = data.begin(); it != data.end(); ++it) {
3338     *i++ = *it;
3339   }
3340 
3341   nub_size_t wrote =
3342       DNBProcessMemoryWrite(m_ctx.ProcessID(), addr, data.size(), buf);
3343   if (wrote != data.size())
3344     return SendPacket("E08");
3345   return SendPacket("OK");
3346 }
3347 
3348 /* 'g' -- read registers
3349  Get the contents of the registers for the current thread,
3350  send them to gdb.
3351  Should the setting of the Hg packet determine which thread's registers
3352  are returned?  */
3353 
3354 rnb_err_t RNBRemote::HandlePacket_g(const char *p) {
3355   std::ostringstream ostrm;
3356   if (!m_ctx.HasValidProcessID()) {
3357     return SendPacket("E11");
3358   }
3359 
3360   if (g_num_reg_entries == 0)
3361     InitializeRegisters();
3362 
3363   nub_process_t pid = m_ctx.ProcessID();
3364   nub_thread_t tid = ExtractThreadIDFromThreadSuffix(p + 1);
3365   if (tid == INVALID_NUB_THREAD)
3366     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3367                                   "No thread specified in p packet");
3368 
3369   // Get the register context size first by calling with NULL buffer
3370   nub_size_t reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, NULL, 0);
3371   if (reg_ctx_size) {
3372     // Now allocate enough space for the entire register context
3373     std::vector<uint8_t> reg_ctx;
3374     reg_ctx.resize(reg_ctx_size);
3375     // Now read the register context
3376     reg_ctx_size =
3377         DNBThreadGetRegisterContext(pid, tid, &reg_ctx[0], reg_ctx.size());
3378     if (reg_ctx_size) {
3379       append_hex_value(ostrm, reg_ctx.data(), reg_ctx.size(), false);
3380       return SendPacket(ostrm.str());
3381     }
3382   }
3383   return SendPacket("E74");
3384 }
3385 
3386 /* 'G XXX...' -- write registers
3387  How is the thread for these specified, beyond "the current thread"?
3388  Does gdb actually use the Hg packet to set this?  */
3389 
3390 rnb_err_t RNBRemote::HandlePacket_G(const char *p) {
3391   if (!m_ctx.HasValidProcessID()) {
3392     return SendPacket("E11");
3393   }
3394 
3395   if (g_num_reg_entries == 0)
3396     InitializeRegisters();
3397 
3398   StdStringExtractor packet(p);
3399   packet.SetFilePos(1); // Skip the 'G'
3400 
3401   nub_process_t pid = m_ctx.ProcessID();
3402   nub_thread_t tid = ExtractThreadIDFromThreadSuffix(p);
3403   if (tid == INVALID_NUB_THREAD)
3404     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3405                                   "No thread specified in p packet");
3406 
3407   // Get the register context size first by calling with NULL buffer
3408   nub_size_t reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, NULL, 0);
3409   if (reg_ctx_size) {
3410     // Now allocate enough space for the entire register context
3411     std::vector<uint8_t> reg_ctx;
3412     reg_ctx.resize(reg_ctx_size);
3413 
3414     const nub_size_t bytes_extracted =
3415         packet.GetHexBytes(&reg_ctx[0], reg_ctx.size(), 0xcc);
3416     if (bytes_extracted == reg_ctx.size()) {
3417       // Now write the register context
3418       reg_ctx_size =
3419           DNBThreadSetRegisterContext(pid, tid, reg_ctx.data(), reg_ctx.size());
3420       if (reg_ctx_size == reg_ctx.size())
3421         return SendPacket("OK");
3422       else
3423         return SendPacket("E55");
3424     } else {
3425       DNBLogError("RNBRemote::HandlePacket_G(%s): extracted %llu of %llu "
3426                   "bytes, size mismatch\n",
3427                   p, (uint64_t)bytes_extracted, (uint64_t)reg_ctx_size);
3428       return SendPacket("E64");
3429     }
3430   }
3431   return SendPacket("E65");
3432 }
3433 
3434 static bool RNBRemoteShouldCancelCallback(void *not_used) {
3435   RNBRemoteSP remoteSP(g_remoteSP);
3436   if (remoteSP.get() != NULL) {
3437     RNBRemote *remote = remoteSP.get();
3438     return !remote->Comm().IsConnected();
3439   }
3440   return true;
3441 }
3442 
3443 // FORMAT: _MXXXXXX,PPP
3444 //      XXXXXX: big endian hex chars
3445 //      PPP: permissions can be any combo of r w x chars
3446 //
3447 // RESPONSE: XXXXXX
3448 //      XXXXXX: hex address of the newly allocated memory
3449 //      EXX: error code
3450 //
3451 // EXAMPLES:
3452 //      _M123000,rw
3453 //      _M123000,rwx
3454 //      _M123000,xw
3455 
3456 rnb_err_t RNBRemote::HandlePacket_AllocateMemory(const char *p) {
3457   StdStringExtractor packet(p);
3458   packet.SetFilePos(2); // Skip the "_M"
3459 
3460   nub_addr_t size = packet.GetHexMaxU64(StdStringExtractor::BigEndian, 0);
3461   if (size != 0) {
3462     if (packet.GetChar() == ',') {
3463       uint32_t permissions = 0;
3464       char ch;
3465       bool success = true;
3466       while (success && (ch = packet.GetChar()) != '\0') {
3467         switch (ch) {
3468         case 'r':
3469           permissions |= eMemoryPermissionsReadable;
3470           break;
3471         case 'w':
3472           permissions |= eMemoryPermissionsWritable;
3473           break;
3474         case 'x':
3475           permissions |= eMemoryPermissionsExecutable;
3476           break;
3477         default:
3478           success = false;
3479           break;
3480         }
3481       }
3482 
3483       if (success) {
3484         nub_addr_t addr =
3485             DNBProcessMemoryAllocate(m_ctx.ProcessID(), size, permissions);
3486         if (addr != INVALID_NUB_ADDRESS) {
3487           std::ostringstream ostrm;
3488           ostrm << RAW_HEXBASE << addr;
3489           return SendPacket(ostrm.str());
3490         }
3491       }
3492     }
3493   }
3494   return SendPacket("E53");
3495 }
3496 
3497 // FORMAT: _mXXXXXX
3498 //      XXXXXX: address that was previously allocated
3499 //
3500 // RESPONSE: XXXXXX
3501 //      OK: address was deallocated
3502 //      EXX: error code
3503 //
3504 // EXAMPLES:
3505 //      _m123000
3506 
3507 rnb_err_t RNBRemote::HandlePacket_DeallocateMemory(const char *p) {
3508   StdStringExtractor packet(p);
3509   packet.SetFilePos(2); // Skip the "_m"
3510   nub_addr_t addr =
3511       packet.GetHexMaxU64(StdStringExtractor::BigEndian, INVALID_NUB_ADDRESS);
3512 
3513   if (addr != INVALID_NUB_ADDRESS) {
3514     if (DNBProcessMemoryDeallocate(m_ctx.ProcessID(), addr))
3515       return SendPacket("OK");
3516   }
3517   return SendPacket("E54");
3518 }
3519 
3520 // FORMAT: QSaveRegisterState;thread:TTTT;  (when thread suffix is supported)
3521 // FORMAT: QSaveRegisterState               (when thread suffix is NOT
3522 // supported)
3523 //      TTTT: thread ID in hex
3524 //
3525 // RESPONSE:
3526 //      SAVEID: Where SAVEID is a decimal number that represents the save ID
3527 //              that can be passed back into a "QRestoreRegisterState" packet
3528 //      EXX: error code
3529 //
3530 // EXAMPLES:
3531 //      QSaveRegisterState;thread:1E34;     (when thread suffix is supported)
3532 //      QSaveRegisterState                  (when thread suffix is NOT
3533 //      supported)
3534 
3535 rnb_err_t RNBRemote::HandlePacket_SaveRegisterState(const char *p) {
3536   nub_process_t pid = m_ctx.ProcessID();
3537   nub_thread_t tid = ExtractThreadIDFromThreadSuffix(p);
3538   if (tid == INVALID_NUB_THREAD) {
3539     if (m_thread_suffix_supported)
3540       return HandlePacket_ILLFORMED(
3541           __FILE__, __LINE__, p,
3542           "No thread specified in QSaveRegisterState packet");
3543     else
3544       return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3545                                     "No thread was is set with the Hg packet");
3546   }
3547 
3548   // Get the register context size first by calling with NULL buffer
3549   const uint32_t save_id = DNBThreadSaveRegisterState(pid, tid);
3550   if (save_id != 0) {
3551     char response[64];
3552     snprintf(response, sizeof(response), "%u", save_id);
3553     return SendPacket(response);
3554   } else {
3555     return SendPacket("E75");
3556   }
3557 }
3558 // FORMAT: QRestoreRegisterState:SAVEID;thread:TTTT;  (when thread suffix is
3559 // supported)
3560 // FORMAT: QRestoreRegisterState:SAVEID               (when thread suffix is NOT
3561 // supported)
3562 //      TTTT: thread ID in hex
3563 //      SAVEID: a decimal number that represents the save ID that was
3564 //              returned from a call to "QSaveRegisterState"
3565 //
3566 // RESPONSE:
3567 //      OK: successfully restored registers for the specified thread
3568 //      EXX: error code
3569 //
3570 // EXAMPLES:
3571 //      QRestoreRegisterState:1;thread:1E34;     (when thread suffix is
3572 //      supported)
3573 //      QRestoreRegisterState:1                  (when thread suffix is NOT
3574 //      supported)
3575 
3576 rnb_err_t RNBRemote::HandlePacket_RestoreRegisterState(const char *p) {
3577   nub_process_t pid = m_ctx.ProcessID();
3578   nub_thread_t tid = ExtractThreadIDFromThreadSuffix(p);
3579   if (tid == INVALID_NUB_THREAD) {
3580     if (m_thread_suffix_supported)
3581       return HandlePacket_ILLFORMED(
3582           __FILE__, __LINE__, p,
3583           "No thread specified in QSaveRegisterState packet");
3584     else
3585       return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3586                                     "No thread was is set with the Hg packet");
3587   }
3588 
3589   StdStringExtractor packet(p);
3590   packet.SetFilePos(
3591       strlen("QRestoreRegisterState:")); // Skip the "QRestoreRegisterState:"
3592   const uint32_t save_id = packet.GetU32(0);
3593 
3594   if (save_id != 0) {
3595     // Get the register context size first by calling with NULL buffer
3596     if (DNBThreadRestoreRegisterState(pid, tid, save_id))
3597       return SendPacket("OK");
3598     else
3599       return SendPacket("E77");
3600   }
3601   return SendPacket("E76");
3602 }
3603 
3604 static bool GetProcessNameFrom_vAttach(const char *&p,
3605                                        std::string &attach_name) {
3606   bool return_val = true;
3607   while (*p != '\0') {
3608     char smallbuf[3];
3609     smallbuf[0] = *p;
3610     smallbuf[1] = *(p + 1);
3611     smallbuf[2] = '\0';
3612 
3613     errno = 0;
3614     int ch = static_cast<int>(strtoul(smallbuf, NULL, 16));
3615     if (errno != 0 && ch == 0) {
3616       return_val = false;
3617       break;
3618     }
3619 
3620     attach_name.push_back(ch);
3621     p += 2;
3622   }
3623   return return_val;
3624 }
3625 
3626 rnb_err_t RNBRemote::HandlePacket_qSupported(const char *p) {
3627   uint32_t max_packet_size = 128 * 1024; // 128KBytes is a reasonable max packet
3628                                          // size--debugger can always use less
3629   char buf[256];
3630   snprintf(buf, sizeof(buf), "qXfer:features:read+;PacketSize=%x;qEcho+",
3631            max_packet_size);
3632 
3633   bool enable_compression = false;
3634   (void)enable_compression;
3635 
3636 #if (defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1) \
3637     || (defined (TARGET_OS_IOS) && TARGET_OS_IOS == 1) \
3638     || (defined (TARGET_OS_TV) && TARGET_OS_TV == 1) \
3639     || (defined (TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1)
3640   enable_compression = true;
3641 #endif
3642 
3643   if (enable_compression) {
3644     strcat(buf, ";SupportedCompressions=lzfse,zlib-deflate,lz4,lzma;"
3645                 "DefaultCompressionMinSize=");
3646     char numbuf[16];
3647     snprintf(numbuf, sizeof(numbuf), "%zu", m_compression_minsize);
3648     numbuf[sizeof(numbuf) - 1] = '\0';
3649     strcat(buf, numbuf);
3650   }
3651 
3652   return SendPacket(buf);
3653 }
3654 
3655 static bool process_does_not_exist (nub_process_t pid) {
3656   std::vector<struct kinfo_proc> proc_infos;
3657   DNBGetAllInfos (proc_infos);
3658   const size_t infos_size = proc_infos.size();
3659   for (size_t i = 0; i < infos_size; i++)
3660     if (proc_infos[i].kp_proc.p_pid == pid)
3661       return false;
3662 
3663   return true; // process does not exist
3664 }
3665 
3666 // my_uid and process_uid are only initialized if this function
3667 // returns true -- that there was a uid mismatch -- and those
3668 // id's may want to be used in the error message.
3669 //
3670 // NOTE: this should only be called after process_does_not_exist().
3671 // This sysctl will return uninitialized data if we ask for a pid
3672 // that doesn't exist.  The alternative would be to fetch all
3673 // processes and step through to find the one we're looking for
3674 // (as process_does_not_exist() does).
3675 static bool attach_failed_due_to_uid_mismatch (nub_process_t pid,
3676                                                uid_t &my_uid,
3677                                                uid_t &process_uid) {
3678   struct kinfo_proc kinfo;
3679   int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
3680   size_t len = sizeof(struct kinfo_proc);
3681   if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), &kinfo, &len, NULL, 0) != 0) {
3682     return false; // pid doesn't exist? can't check uid mismatch - it was fine
3683   }
3684   my_uid = geteuid();
3685   if (my_uid == 0)
3686     return false; // if we're root, attach didn't fail because of uid mismatch
3687   process_uid = kinfo.kp_eproc.e_ucred.cr_uid;
3688 
3689   // If my uid != the process' uid, then the attach probably failed because
3690   // of that.
3691   if (my_uid != process_uid)
3692     return true;
3693   else
3694     return false;
3695 }
3696 
3697 // NOTE: this should only be called after process_does_not_exist().
3698 // This sysctl will return uninitialized data if we ask for a pid
3699 // that doesn't exist.  The alternative would be to fetch all
3700 // processes and step through to find the one we're looking for
3701 // (as process_does_not_exist() does).
3702 static bool process_is_already_being_debugged (nub_process_t pid) {
3703   struct kinfo_proc kinfo;
3704   int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
3705   size_t len = sizeof(struct kinfo_proc);
3706   if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), &kinfo, &len, NULL, 0) != 0) {
3707     return false; // pid doesn't exist? well, it's not being debugged...
3708   }
3709   if (kinfo.kp_proc.p_flag & P_TRACED)
3710     return true; // is being debugged already
3711   else
3712     return false;
3713 }
3714 
3715 // Test if this current login session has a connection to the
3716 // window server (if it does not have that access, it cannot ask
3717 // for debug permission by popping up a dialog box and attach
3718 // may fail outright).
3719 static bool login_session_has_gui_access () {
3720   // I believe this API only works on macOS.
3721 #if TARGET_OS_OSX == 0
3722   return true;
3723 #else
3724   auditinfo_addr_t info;
3725   getaudit_addr(&info, sizeof(info));
3726   if (info.ai_flags & AU_SESSION_FLAG_HAS_GRAPHIC_ACCESS)
3727     return true;
3728   else
3729     return false;
3730 #endif
3731 }
3732 
3733 // Checking for
3734 //
3735 //  {
3736 //    'class' : 'rule',
3737 //    'comment' : 'For use by Apple.  WARNING: administrators are advised
3738 //              not to modify this right.',
3739 //    'k-of-n' : '1',
3740 //    'rule' : [
3741 //      'is-admin',
3742 //      'is-developer',
3743 //      'authenticate-developer'
3744 //    ]
3745 //  }
3746 //
3747 // $ security authorizationdb read system.privilege.taskport.debug
3748 
3749 static bool developer_mode_enabled () {
3750   // This API only exists on macOS.
3751 #if TARGET_OS_OSX == 0
3752   return true;
3753 #else
3754  CFDictionaryRef currentRightDict = NULL;
3755  const char *debug_right = "system.privilege.taskport.debug";
3756  // caller must free dictionary initialized by the following
3757  OSStatus status = AuthorizationRightGet(debug_right, &currentRightDict);
3758  if (status != errAuthorizationSuccess) {
3759    // could not check authorization
3760    return true;
3761  }
3762 
3763  bool devmode_enabled = true;
3764 
3765  if (!CFDictionaryContainsKey(currentRightDict, CFSTR("k-of-n"))) {
3766    devmode_enabled = false;
3767  } else {
3768    CFNumberRef item = (CFNumberRef) CFDictionaryGetValue(currentRightDict, CFSTR("k-of-n"));
3769    if (item && CFGetTypeID(item) == CFNumberGetTypeID()) {
3770       int64_t num = 0;
3771       ::CFNumberGetValue(item, kCFNumberSInt64Type, &num);
3772       if (num != 1) {
3773         devmode_enabled = false;
3774       }
3775    } else {
3776      devmode_enabled = false;
3777    }
3778  }
3779 
3780  if (!CFDictionaryContainsKey(currentRightDict, CFSTR("class"))) {
3781    devmode_enabled = false;
3782  } else {
3783    CFStringRef item = (CFStringRef) CFDictionaryGetValue(currentRightDict, CFSTR("class"));
3784    if (item && CFGetTypeID(item) == CFStringGetTypeID()) {
3785      char tmpbuf[128];
3786      if (CFStringGetCString (item, tmpbuf, sizeof(tmpbuf), CFStringGetSystemEncoding())) {
3787        tmpbuf[sizeof (tmpbuf) - 1] = '\0';
3788        if (strcmp (tmpbuf, "rule") != 0) {
3789          devmode_enabled = false;
3790        }
3791      } else {
3792        devmode_enabled = false;
3793      }
3794    } else {
3795      devmode_enabled = false;
3796    }
3797  }
3798 
3799  if (!CFDictionaryContainsKey(currentRightDict, CFSTR("rule"))) {
3800    devmode_enabled = false;
3801  } else {
3802    CFArrayRef item = (CFArrayRef) CFDictionaryGetValue(currentRightDict, CFSTR("rule"));
3803    if (item && CFGetTypeID(item) == CFArrayGetTypeID()) {
3804      int count = ::CFArrayGetCount(item);
3805       CFRange range = CFRangeMake (0, count);
3806      if (!::CFArrayContainsValue (item, range, CFSTR("is-admin")))
3807        devmode_enabled = false;
3808      if (!::CFArrayContainsValue (item, range, CFSTR("is-developer")))
3809        devmode_enabled = false;
3810      if (!::CFArrayContainsValue (item, range, CFSTR("authenticate-developer")))
3811        devmode_enabled = false;
3812    } else {
3813      devmode_enabled = false;
3814    }
3815  }
3816  ::CFRelease(currentRightDict);
3817 
3818  return devmode_enabled;
3819 #endif // TARGET_OS_OSX
3820 }
3821 
3822 /*
3823  vAttach;pid
3824 
3825  Attach to a new process with the specified process ID. pid is a hexadecimal
3826  integer
3827  identifying the process. If the stub is currently controlling a process, it is
3828  killed. The attached process is stopped.This packet is only available in
3829  extended
3830  mode (see extended mode).
3831 
3832  Reply:
3833  "ENN"                      for an error
3834  "Any Stop Reply Packet"     for success
3835  */
3836 
3837 rnb_err_t RNBRemote::HandlePacket_v(const char *p) {
3838   if (strcmp(p, "vCont;c") == 0) {
3839     // Simple continue
3840     return RNBRemote::HandlePacket_c("c");
3841   } else if (strcmp(p, "vCont;s") == 0) {
3842     // Simple step
3843     return RNBRemote::HandlePacket_s("s");
3844   } else if (strstr(p, "vCont") == p) {
3845     DNBThreadResumeActions thread_actions;
3846     char *c = const_cast<char *>(p += strlen("vCont"));
3847     char *c_end = c + strlen(c);
3848     if (*c == '?')
3849       return SendPacket("vCont;c;C;s;S");
3850 
3851     while (c < c_end && *c == ';') {
3852       ++c; // Skip the semi-colon
3853       DNBThreadResumeAction thread_action;
3854       thread_action.tid = INVALID_NUB_THREAD;
3855       thread_action.state = eStateInvalid;
3856       thread_action.signal = 0;
3857       thread_action.addr = INVALID_NUB_ADDRESS;
3858 
3859       char action = *c++;
3860 
3861       switch (action) {
3862       case 'C':
3863         errno = 0;
3864         thread_action.signal = static_cast<int>(strtoul(c, &c, 16));
3865         if (errno != 0)
3866           return HandlePacket_ILLFORMED(
3867               __FILE__, __LINE__, p, "Could not parse signal in vCont packet");
3868       // Fall through to next case...
3869         [[clang::fallthrough]];
3870       case 'c':
3871         // Continue
3872         thread_action.state = eStateRunning;
3873         break;
3874 
3875       case 'S':
3876         errno = 0;
3877         thread_action.signal = static_cast<int>(strtoul(c, &c, 16));
3878         if (errno != 0)
3879           return HandlePacket_ILLFORMED(
3880               __FILE__, __LINE__, p, "Could not parse signal in vCont packet");
3881       // Fall through to next case...
3882         [[clang::fallthrough]];
3883       case 's':
3884         // Step
3885         thread_action.state = eStateStepping;
3886         break;
3887 
3888       default:
3889         HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3890                                "Unsupported action in vCont packet");
3891         break;
3892       }
3893       if (*c == ':') {
3894         errno = 0;
3895         thread_action.tid = strtoul(++c, &c, 16);
3896         if (errno != 0)
3897           return HandlePacket_ILLFORMED(
3898               __FILE__, __LINE__, p,
3899               "Could not parse thread number in vCont packet");
3900       }
3901 
3902       thread_actions.Append(thread_action);
3903     }
3904 
3905     // If a default action for all other threads wasn't mentioned
3906     // then we should stop the threads
3907     thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
3908     DNBProcessResume(m_ctx.ProcessID(), thread_actions.GetFirst(),
3909                      thread_actions.GetSize());
3910     return rnb_success;
3911   } else if (strstr(p, "vAttach") == p) {
3912     nub_process_t attach_pid =
3913         INVALID_NUB_PROCESS; // attach_pid will be set to 0 if the attach fails
3914     nub_process_t pid_attaching_to =
3915         INVALID_NUB_PROCESS; // pid_attaching_to is the original pid specified
3916     char err_str[1024] = {'\0'};
3917     std::string attach_name;
3918 
3919     if (strstr(p, "vAttachWait;") == p) {
3920       p += strlen("vAttachWait;");
3921       if (!GetProcessNameFrom_vAttach(p, attach_name)) {
3922         return HandlePacket_ILLFORMED(
3923             __FILE__, __LINE__, p, "non-hex char in arg on 'vAttachWait' pkt");
3924       }
3925       const bool ignore_existing = true;
3926       attach_pid = DNBProcessAttachWait(
3927           attach_name.c_str(), m_ctx.LaunchFlavor(), ignore_existing, NULL,
3928           1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback);
3929 
3930     } else if (strstr(p, "vAttachOrWait;") == p) {
3931       p += strlen("vAttachOrWait;");
3932       if (!GetProcessNameFrom_vAttach(p, attach_name)) {
3933         return HandlePacket_ILLFORMED(
3934             __FILE__, __LINE__, p,
3935             "non-hex char in arg on 'vAttachOrWait' pkt");
3936       }
3937       const bool ignore_existing = false;
3938       attach_pid = DNBProcessAttachWait(
3939           attach_name.c_str(), m_ctx.LaunchFlavor(), ignore_existing, NULL,
3940           1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback);
3941     } else if (strstr(p, "vAttachName;") == p) {
3942       p += strlen("vAttachName;");
3943       if (!GetProcessNameFrom_vAttach(p, attach_name)) {
3944         return HandlePacket_ILLFORMED(
3945             __FILE__, __LINE__, p, "non-hex char in arg on 'vAttachName' pkt");
3946       }
3947 
3948       attach_pid = DNBProcessAttachByName(attach_name.c_str(), NULL, err_str,
3949                                           sizeof(err_str));
3950 
3951     } else if (strstr(p, "vAttach;") == p) {
3952       p += strlen("vAttach;");
3953       char *end = NULL;
3954       pid_attaching_to = static_cast<int>(
3955           strtoul(p, &end, 16)); // PID will be in hex, so use base 16 to decode
3956       if (p != end && *end == '\0') {
3957         // Wait at most 30 second for attach
3958         struct timespec attach_timeout_abstime;
3959         DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, 30, 0);
3960         attach_pid = DNBProcessAttach(pid_attaching_to, &attach_timeout_abstime,
3961                                       err_str, sizeof(err_str));
3962       }
3963     } else {
3964       return HandlePacket_UNIMPLEMENTED(p);
3965     }
3966 
3967     if (attach_pid != INVALID_NUB_PROCESS) {
3968       if (m_ctx.ProcessID() != attach_pid)
3969         m_ctx.SetProcessID(attach_pid);
3970       // Send a stop reply packet to indicate we successfully attached!
3971       NotifyThatProcessStopped();
3972       return rnb_success;
3973     } else {
3974       m_ctx.LaunchStatus().SetError(-1, DNBError::Generic);
3975       if (err_str[0])
3976         m_ctx.LaunchStatus().SetErrorString(err_str);
3977       else
3978         m_ctx.LaunchStatus().SetErrorString("attach failed");
3979 
3980       if (pid_attaching_to == INVALID_NUB_PROCESS && !attach_name.empty()) {
3981         pid_attaching_to = DNBProcessGetPIDByName(attach_name.c_str());
3982       }
3983 
3984       // attach_pid is INVALID_NUB_PROCESS - we did not succeed in attaching
3985       // if the original request, pid_attaching_to, is available, see if we
3986       // can figure out why we couldn't attach.  Return an informative error
3987       // string to lldb.
3988 
3989       if (pid_attaching_to != INVALID_NUB_PROCESS) {
3990         // The order of these checks is important.
3991         if (process_does_not_exist (pid_attaching_to)) {
3992           DNBLogError("Tried to attach to pid that doesn't exist");
3993           std::string return_message = "E96;";
3994           return_message += cstring_to_asciihex_string("no such process.");
3995           return SendPacket(return_message.c_str());
3996         }
3997         if (process_is_already_being_debugged (pid_attaching_to)) {
3998           DNBLogError("Tried to attach to process already being debugged");
3999           std::string return_message = "E96;";
4000           return_message += cstring_to_asciihex_string("tried to attach to "
4001                                            "process already being debugged");
4002           return SendPacket(return_message.c_str());
4003         }
4004         uid_t my_uid, process_uid;
4005         if (attach_failed_due_to_uid_mismatch (pid_attaching_to,
4006                                                my_uid, process_uid)) {
4007           std::string my_username = "uid " + std::to_string (my_uid);
4008           std::string process_username = "uid " + std::to_string (process_uid);
4009           struct passwd *pw = getpwuid (my_uid);
4010           if (pw && pw->pw_name) {
4011             my_username = pw->pw_name;
4012           }
4013           pw = getpwuid (process_uid);
4014           if (pw && pw->pw_name) {
4015             process_username = pw->pw_name;
4016           }
4017           DNBLogError("Tried to attach to process with uid mismatch");
4018           std::string return_message = "E96;";
4019           std::string msg = "tried to attach to process as user '"
4020                             + my_username + "' and process is running "
4021                             "as user '" + process_username + "'";
4022           return_message += cstring_to_asciihex_string(msg.c_str());
4023           return SendPacket(return_message.c_str());
4024         }
4025         if (!login_session_has_gui_access() && !developer_mode_enabled()) {
4026           DNBLogError("Developer mode is not enabled and this is a "
4027                       "non-interactive session");
4028           std::string return_message = "E96;";
4029           return_message += cstring_to_asciihex_string("developer mode is "
4030                                            "not enabled on this machine "
4031                                            "and this is a non-interactive "
4032                                            "debug session.");
4033           return SendPacket(return_message.c_str());
4034         }
4035         if (!login_session_has_gui_access()) {
4036           DNBLogError("This is a non-interactive session");
4037           std::string return_message = "E96;";
4038           return_message += cstring_to_asciihex_string("this is a "
4039                                            "non-interactive debug session, "
4040                                            "cannot get permission to debug "
4041                                            "processes.");
4042           return SendPacket(return_message.c_str());
4043         }
4044       }
4045 
4046       std::string error_explainer = "attach failed";
4047       if (err_str[0] != '\0') {
4048         // This is not a super helpful message for end users
4049         if (strcmp (err_str, "unable to start the exception thread") == 0) {
4050           snprintf (err_str, sizeof (err_str) - 1,
4051                     "Not allowed to attach to process.  Look in the console "
4052                     "messages (Console.app), near the debugserver entries "
4053                     "when the attached failed.  The subsystem that denied "
4054                     "the attach permission will likely have logged an "
4055                     "informative message about why it was denied.");
4056           err_str[sizeof (err_str) - 1] = '\0';
4057         }
4058         error_explainer += " (";
4059         error_explainer += err_str;
4060         error_explainer += ")";
4061       }
4062       std::string default_return_msg = "E96;";
4063       default_return_msg += cstring_to_asciihex_string
4064                               (error_explainer.c_str());
4065       SendPacket (default_return_msg.c_str());
4066       DNBLogError("Attach failed: \"%s\".", err_str);
4067       return rnb_err;
4068     }
4069   }
4070 
4071   // All other failures come through here
4072   return HandlePacket_UNIMPLEMENTED(p);
4073 }
4074 
4075 /* 'T XX' -- status of thread
4076  Check if the specified thread is alive.
4077  The thread number is in hex?  */
4078 
4079 rnb_err_t RNBRemote::HandlePacket_T(const char *p) {
4080   p++;
4081   if (p == NULL || *p == '\0') {
4082     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4083                                   "No thread specified in T packet");
4084   }
4085   if (!m_ctx.HasValidProcessID()) {
4086     return SendPacket("E15");
4087   }
4088   errno = 0;
4089   nub_thread_t tid = strtoul(p, NULL, 16);
4090   if (errno != 0 && tid == 0) {
4091     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4092                                   "Could not parse thread number in T packet");
4093   }
4094 
4095   nub_state_t state = DNBThreadGetState(m_ctx.ProcessID(), tid);
4096   if (state == eStateInvalid || state == eStateExited ||
4097       state == eStateCrashed) {
4098     return SendPacket("E16");
4099   }
4100 
4101   return SendPacket("OK");
4102 }
4103 
4104 rnb_err_t RNBRemote::HandlePacket_z(const char *p) {
4105   if (p == NULL || *p == '\0')
4106     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4107                                   "No thread specified in z packet");
4108 
4109   if (!m_ctx.HasValidProcessID())
4110     return SendPacket("E15");
4111 
4112   char packet_cmd = *p++;
4113   char break_type = *p++;
4114 
4115   if (*p++ != ',')
4116     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4117                                   "Comma separator missing in z packet");
4118 
4119   char *c = NULL;
4120   nub_process_t pid = m_ctx.ProcessID();
4121   errno = 0;
4122   nub_addr_t addr = strtoull(p, &c, 16);
4123   if (errno != 0 && addr == 0)
4124     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4125                                   "Invalid address in z packet");
4126   p = c;
4127   if (*p++ != ',')
4128     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4129                                   "Comma separator missing in z packet");
4130 
4131   errno = 0;
4132   auto byte_size = strtoul(p, &c, 16);
4133   if (errno != 0 && byte_size == 0)
4134     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4135                                   "Invalid length in z packet");
4136 
4137   if (packet_cmd == 'Z') {
4138     // set
4139     switch (break_type) {
4140     case '0': // set software breakpoint
4141     case '1': // set hardware breakpoint
4142     {
4143       // gdb can send multiple Z packets for the same address and
4144       // these calls must be ref counted.
4145       bool hardware = (break_type == '1');
4146 
4147       if (DNBBreakpointSet(pid, addr, byte_size, hardware)) {
4148         // We successfully created a breakpoint, now lets full out
4149         // a ref count structure with the breakID and add it to our
4150         // map.
4151         return SendPacket("OK");
4152       } else {
4153         // We failed to set the software breakpoint
4154         return SendPacket("E09");
4155       }
4156     } break;
4157 
4158     case '2': // set write watchpoint
4159     case '3': // set read watchpoint
4160     case '4': // set access watchpoint
4161     {
4162       bool hardware = true;
4163       uint32_t watch_flags = 0;
4164       if (break_type == '2')
4165         watch_flags = WATCH_TYPE_WRITE;
4166       else if (break_type == '3')
4167         watch_flags = WATCH_TYPE_READ;
4168       else
4169         watch_flags = WATCH_TYPE_READ | WATCH_TYPE_WRITE;
4170 
4171       if (DNBWatchpointSet(pid, addr, byte_size, watch_flags, hardware)) {
4172         return SendPacket("OK");
4173       } else {
4174         // We failed to set the watchpoint
4175         return SendPacket("E09");
4176       }
4177     } break;
4178 
4179     default:
4180       break;
4181     }
4182   } else if (packet_cmd == 'z') {
4183     // remove
4184     switch (break_type) {
4185     case '0': // remove software breakpoint
4186     case '1': // remove hardware breakpoint
4187       if (DNBBreakpointClear(pid, addr)) {
4188         return SendPacket("OK");
4189       } else {
4190         return SendPacket("E08");
4191       }
4192       break;
4193 
4194     case '2': // remove write watchpoint
4195     case '3': // remove read watchpoint
4196     case '4': // remove access watchpoint
4197       if (DNBWatchpointClear(pid, addr)) {
4198         return SendPacket("OK");
4199       } else {
4200         return SendPacket("E08");
4201       }
4202       break;
4203 
4204     default:
4205       break;
4206     }
4207   }
4208   return HandlePacket_UNIMPLEMENTED(p);
4209 }
4210 
4211 // Extract the thread number from the thread suffix that might be appended to
4212 // thread specific packets. This will only be enabled if
4213 // m_thread_suffix_supported
4214 // is true.
4215 nub_thread_t RNBRemote::ExtractThreadIDFromThreadSuffix(const char *p) {
4216   if (m_thread_suffix_supported) {
4217     nub_thread_t tid = INVALID_NUB_THREAD;
4218     if (p) {
4219       const char *tid_cstr = strstr(p, "thread:");
4220       if (tid_cstr) {
4221         tid_cstr += strlen("thread:");
4222         tid = strtoul(tid_cstr, NULL, 16);
4223       }
4224     }
4225     return tid;
4226   }
4227   return GetCurrentThread();
4228 }
4229 
4230 /* 'p XX'
4231  print the contents of register X */
4232 
4233 rnb_err_t RNBRemote::HandlePacket_p(const char *p) {
4234   if (g_num_reg_entries == 0)
4235     InitializeRegisters();
4236 
4237   if (p == NULL || *p == '\0') {
4238     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4239                                   "No thread specified in p packet");
4240   }
4241   if (!m_ctx.HasValidProcessID()) {
4242     return SendPacket("E15");
4243   }
4244   nub_process_t pid = m_ctx.ProcessID();
4245   errno = 0;
4246   char *tid_cstr = NULL;
4247   uint32_t reg = static_cast<uint32_t>(strtoul(p + 1, &tid_cstr, 16));
4248   if (errno != 0 && reg == 0) {
4249     return HandlePacket_ILLFORMED(
4250         __FILE__, __LINE__, p, "Could not parse register number in p packet");
4251   }
4252 
4253   nub_thread_t tid = ExtractThreadIDFromThreadSuffix(tid_cstr);
4254   if (tid == INVALID_NUB_THREAD)
4255     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4256                                   "No thread specified in p packet");
4257 
4258   const register_map_entry_t *reg_entry;
4259 
4260   if (reg < g_num_reg_entries)
4261     reg_entry = &g_reg_entries[reg];
4262   else
4263     reg_entry = NULL;
4264 
4265   std::ostringstream ostrm;
4266   if (reg_entry == NULL) {
4267     DNBLogError(
4268         "RNBRemote::HandlePacket_p(%s): unknown register number %u requested\n",
4269         p, reg);
4270     ostrm << "00000000";
4271   } else if (reg_entry->nub_info.reg == (uint32_t)-1) {
4272     if (reg_entry->nub_info.size > 0) {
4273       std::basic_string<uint8_t> zeros(reg_entry->nub_info.size, '\0');
4274       append_hex_value(ostrm, zeros.data(), zeros.size(), false);
4275     }
4276   } else {
4277     register_value_in_hex_fixed_width(ostrm, pid, tid, reg_entry, NULL);
4278   }
4279   return SendPacket(ostrm.str());
4280 }
4281 
4282 /* 'Pnn=rrrrr'
4283  Set register number n to value r.
4284  n and r are hex strings.  */
4285 
4286 rnb_err_t RNBRemote::HandlePacket_P(const char *p) {
4287   if (g_num_reg_entries == 0)
4288     InitializeRegisters();
4289 
4290   if (p == NULL || *p == '\0') {
4291     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, "Empty P packet");
4292   }
4293   if (!m_ctx.HasValidProcessID()) {
4294     return SendPacket("E28");
4295   }
4296 
4297   nub_process_t pid = m_ctx.ProcessID();
4298 
4299   StdStringExtractor packet(p);
4300 
4301   const char cmd_char = packet.GetChar();
4302   // Register ID is always in big endian
4303   const uint32_t reg = packet.GetHexMaxU32(false, UINT32_MAX);
4304   const char equal_char = packet.GetChar();
4305 
4306   if (cmd_char != 'P')
4307     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4308                                   "Improperly formed P packet");
4309 
4310   if (reg == UINT32_MAX)
4311     return SendPacket("E29");
4312 
4313   if (equal_char != '=')
4314     return SendPacket("E30");
4315 
4316   const register_map_entry_t *reg_entry;
4317 
4318   if (reg >= g_num_reg_entries)
4319     return SendPacket("E47");
4320 
4321   reg_entry = &g_reg_entries[reg];
4322 
4323   if (reg_entry->nub_info.set == (uint32_t)-1 &&
4324       reg_entry->nub_info.reg == (uint32_t)-1) {
4325     DNBLogError(
4326         "RNBRemote::HandlePacket_P(%s): unknown register number %u requested\n",
4327         p, reg);
4328     return SendPacket("E48");
4329   }
4330 
4331   DNBRegisterValue reg_value;
4332   reg_value.info = reg_entry->nub_info;
4333   packet.GetHexBytes(reg_value.value.v_sint8, reg_entry->nub_info.size, 0xcc);
4334 
4335   nub_thread_t tid = ExtractThreadIDFromThreadSuffix(p);
4336   if (tid == INVALID_NUB_THREAD)
4337     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4338                                   "No thread specified in p packet");
4339 
4340   if (!DNBThreadSetRegisterValueByID(pid, tid, reg_entry->nub_info.set,
4341                                      reg_entry->nub_info.reg, &reg_value)) {
4342     return SendPacket("E32");
4343   }
4344   return SendPacket("OK");
4345 }
4346 
4347 /* 'c [addr]'
4348  Continue, optionally from a specified address. */
4349 
4350 rnb_err_t RNBRemote::HandlePacket_c(const char *p) {
4351   const nub_process_t pid = m_ctx.ProcessID();
4352 
4353   if (pid == INVALID_NUB_PROCESS)
4354     return SendPacket("E23");
4355 
4356   DNBThreadResumeAction action = {INVALID_NUB_THREAD, eStateRunning, 0,
4357                                   INVALID_NUB_ADDRESS};
4358 
4359   if (*(p + 1) != '\0') {
4360     action.tid = GetContinueThread();
4361     errno = 0;
4362     action.addr = strtoull(p + 1, NULL, 16);
4363     if (errno != 0 && action.addr == 0)
4364       return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4365                                     "Could not parse address in c packet");
4366   }
4367 
4368   DNBThreadResumeActions thread_actions;
4369   thread_actions.Append(action);
4370   thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, 0);
4371   if (!DNBProcessResume(pid, thread_actions.GetFirst(),
4372                         thread_actions.GetSize()))
4373     return SendPacket("E25");
4374   // Don't send an "OK" packet; response is the stopped/exited message.
4375   return rnb_success;
4376 }
4377 
4378 rnb_err_t RNBRemote::HandlePacket_MemoryRegionInfo(const char *p) {
4379   /* This packet will find memory attributes (e.g. readable, writable,
4380      executable, stack, jitted code)
4381      for the memory region containing a given address and return that
4382      information.
4383 
4384      Users of this packet must be prepared for three results:
4385 
4386          Region information is returned
4387          Region information is unavailable for this address because the address
4388      is in unmapped memory
4389          Region lookup cannot be performed on this platform or process is not
4390      yet launched
4391          This packet isn't implemented
4392 
4393      Examples of use:
4394         qMemoryRegionInfo:3a55140
4395         start:3a50000,size:100000,permissions:rwx
4396 
4397         qMemoryRegionInfo:0
4398         error:address in unmapped region
4399 
4400         qMemoryRegionInfo:3a551140   (on a different platform)
4401         error:region lookup cannot be performed
4402 
4403         qMemoryRegionInfo
4404         OK                   // this packet is implemented by the remote nub
4405   */
4406 
4407   p += sizeof("qMemoryRegionInfo") - 1;
4408   if (*p == '\0')
4409     return SendPacket("OK");
4410   if (*p++ != ':')
4411     return SendPacket("E67");
4412   if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X'))
4413     p += 2;
4414 
4415   errno = 0;
4416   uint64_t address = strtoul(p, NULL, 16);
4417   if (errno != 0 && address == 0) {
4418     return HandlePacket_ILLFORMED(
4419         __FILE__, __LINE__, p, "Invalid address in qMemoryRegionInfo packet");
4420   }
4421 
4422   DNBRegionInfo region_info = {0, 0, 0};
4423   DNBProcessMemoryRegionInfo(m_ctx.ProcessID(), address, &region_info);
4424   std::ostringstream ostrm;
4425 
4426   // start:3a50000,size:100000,permissions:rwx
4427   ostrm << "start:" << std::hex << region_info.addr << ';';
4428 
4429   if (region_info.size > 0)
4430     ostrm << "size:" << std::hex << region_info.size << ';';
4431 
4432   if (region_info.permissions) {
4433     ostrm << "permissions:";
4434 
4435     if (region_info.permissions & eMemoryPermissionsReadable)
4436       ostrm << 'r';
4437     if (region_info.permissions & eMemoryPermissionsWritable)
4438       ostrm << 'w';
4439     if (region_info.permissions & eMemoryPermissionsExecutable)
4440       ostrm << 'x';
4441     ostrm << ';';
4442   }
4443   return SendPacket(ostrm.str());
4444 }
4445 
4446 // qGetProfileData;scan_type:0xYYYYYYY
4447 rnb_err_t RNBRemote::HandlePacket_GetProfileData(const char *p) {
4448   nub_process_t pid = m_ctx.ProcessID();
4449   if (pid == INVALID_NUB_PROCESS)
4450     return SendPacket("OK");
4451 
4452   StdStringExtractor packet(p += sizeof("qGetProfileData"));
4453   DNBProfileDataScanType scan_type = eProfileAll;
4454   std::string name;
4455   std::string value;
4456   while (packet.GetNameColonValue(name, value)) {
4457     if (name == "scan_type") {
4458       std::istringstream iss(value);
4459       uint32_t int_value = 0;
4460       if (iss >> std::hex >> int_value) {
4461         scan_type = (DNBProfileDataScanType)int_value;
4462       }
4463     }
4464   }
4465 
4466   std::string data = DNBProcessGetProfileData(pid, scan_type);
4467   if (!data.empty()) {
4468     return SendPacket(data.c_str());
4469   } else {
4470     return SendPacket("OK");
4471   }
4472 }
4473 
4474 // QSetEnableAsyncProfiling;enable:[0|1]:interval_usec:XXXXXX;scan_type:0xYYYYYYY
4475 rnb_err_t RNBRemote::HandlePacket_SetEnableAsyncProfiling(const char *p) {
4476   nub_process_t pid = m_ctx.ProcessID();
4477   if (pid == INVALID_NUB_PROCESS)
4478     return SendPacket("OK");
4479 
4480   StdStringExtractor packet(p += sizeof("QSetEnableAsyncProfiling"));
4481   bool enable = false;
4482   uint64_t interval_usec = 0;
4483   DNBProfileDataScanType scan_type = eProfileAll;
4484   std::string name;
4485   std::string value;
4486   while (packet.GetNameColonValue(name, value)) {
4487     if (name == "enable") {
4488       enable = strtoul(value.c_str(), NULL, 10) > 0;
4489     } else if (name == "interval_usec") {
4490       interval_usec = strtoul(value.c_str(), NULL, 10);
4491     } else if (name == "scan_type") {
4492       std::istringstream iss(value);
4493       uint32_t int_value = 0;
4494       if (iss >> std::hex >> int_value) {
4495         scan_type = (DNBProfileDataScanType)int_value;
4496       }
4497     }
4498   }
4499 
4500   if (interval_usec == 0) {
4501     enable = false;
4502   }
4503 
4504   DNBProcessSetEnableAsyncProfiling(pid, enable, interval_usec, scan_type);
4505   return SendPacket("OK");
4506 }
4507 
4508 // QEnableCompression:type:<COMPRESSION-TYPE>;minsize:<MINIMUM PACKET SIZE TO
4509 // COMPRESS>;
4510 //
4511 // type: must be a type previously reported by the qXfer:features:
4512 // SupportedCompressions list
4513 //
4514 // minsize: is optional; by default the qXfer:features:
4515 // DefaultCompressionMinSize value is used
4516 // debugserver may have a better idea of what a good minimum packet size to
4517 // compress is than lldb.
4518 
4519 rnb_err_t RNBRemote::HandlePacket_QEnableCompression(const char *p) {
4520   p += sizeof("QEnableCompression:") - 1;
4521 
4522   size_t new_compression_minsize = m_compression_minsize;
4523   const char *new_compression_minsize_str = strstr(p, "minsize:");
4524   if (new_compression_minsize_str) {
4525     new_compression_minsize_str += strlen("minsize:");
4526     errno = 0;
4527     new_compression_minsize = strtoul(new_compression_minsize_str, NULL, 10);
4528     if (errno != 0 || new_compression_minsize == ULONG_MAX) {
4529       new_compression_minsize = m_compression_minsize;
4530     }
4531   }
4532 
4533   if (strstr(p, "type:zlib-deflate;") != nullptr) {
4534     EnableCompressionNextSendPacket(compression_types::zlib_deflate);
4535     m_compression_minsize = new_compression_minsize;
4536     return SendPacket("OK");
4537   } else if (strstr(p, "type:lz4;") != nullptr) {
4538     EnableCompressionNextSendPacket(compression_types::lz4);
4539     m_compression_minsize = new_compression_minsize;
4540     return SendPacket("OK");
4541   } else if (strstr(p, "type:lzma;") != nullptr) {
4542     EnableCompressionNextSendPacket(compression_types::lzma);
4543     m_compression_minsize = new_compression_minsize;
4544     return SendPacket("OK");
4545   } else if (strstr(p, "type:lzfse;") != nullptr) {
4546     EnableCompressionNextSendPacket(compression_types::lzfse);
4547     m_compression_minsize = new_compression_minsize;
4548     return SendPacket("OK");
4549   }
4550 
4551   return SendPacket("E88");
4552 }
4553 
4554 rnb_err_t RNBRemote::HandlePacket_qSpeedTest(const char *p) {
4555   p += strlen("qSpeedTest:response_size:");
4556   char *end = NULL;
4557   errno = 0;
4558   uint64_t response_size = ::strtoul(p, &end, 16);
4559   if (errno != 0)
4560     return HandlePacket_ILLFORMED(
4561         __FILE__, __LINE__, p,
4562         "Didn't find response_size value at right offset");
4563   else if (*end == ';') {
4564     static char g_data[4 * 1024 * 1024 + 16] = "data:";
4565     memset(g_data + 5, 'a', response_size);
4566     g_data[response_size + 5] = '\0';
4567     return SendPacket(g_data);
4568   } else {
4569     return SendPacket("E79");
4570   }
4571 }
4572 
4573 rnb_err_t RNBRemote::HandlePacket_WatchpointSupportInfo(const char *p) {
4574   /* This packet simply returns the number of supported hardware watchpoints.
4575 
4576      Examples of use:
4577         qWatchpointSupportInfo:
4578         num:4
4579 
4580         qWatchpointSupportInfo
4581         OK                   // this packet is implemented by the remote nub
4582   */
4583 
4584   p += sizeof("qWatchpointSupportInfo") - 1;
4585   if (*p == '\0')
4586     return SendPacket("OK");
4587   if (*p++ != ':')
4588     return SendPacket("E67");
4589 
4590   errno = 0;
4591   uint32_t num = DNBWatchpointGetNumSupportedHWP(m_ctx.ProcessID());
4592   std::ostringstream ostrm;
4593 
4594   // size:4
4595   ostrm << "num:" << std::dec << num << ';';
4596   return SendPacket(ostrm.str());
4597 }
4598 
4599 /* 'C sig [;addr]'
4600  Resume with signal sig, optionally at address addr.  */
4601 
4602 rnb_err_t RNBRemote::HandlePacket_C(const char *p) {
4603   const nub_process_t pid = m_ctx.ProcessID();
4604 
4605   if (pid == INVALID_NUB_PROCESS)
4606     return SendPacket("E36");
4607 
4608   DNBThreadResumeAction action = {INVALID_NUB_THREAD, eStateRunning, 0,
4609                                   INVALID_NUB_ADDRESS};
4610   int process_signo = -1;
4611   if (*(p + 1) != '\0') {
4612     action.tid = GetContinueThread();
4613     char *end = NULL;
4614     errno = 0;
4615     process_signo = static_cast<int>(strtoul(p + 1, &end, 16));
4616     if (errno != 0)
4617       return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4618                                     "Could not parse signal in C packet");
4619     else if (*end == ';') {
4620       errno = 0;
4621       action.addr = strtoull(end + 1, NULL, 16);
4622       if (errno != 0 && action.addr == 0)
4623         return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4624                                       "Could not parse address in C packet");
4625     }
4626   }
4627 
4628   DNBThreadResumeActions thread_actions;
4629   thread_actions.Append(action);
4630   thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, action.signal);
4631   if (!DNBProcessSignal(pid, process_signo))
4632     return SendPacket("E52");
4633   if (!DNBProcessResume(pid, thread_actions.GetFirst(),
4634                         thread_actions.GetSize()))
4635     return SendPacket("E38");
4636   /* Don't send an "OK" packet; response is the stopped/exited message.  */
4637   return rnb_success;
4638 }
4639 
4640 // 'D' packet
4641 // Detach from gdb.
4642 rnb_err_t RNBRemote::HandlePacket_D(const char *p) {
4643   if (m_ctx.HasValidProcessID()) {
4644     if (DNBProcessDetach(m_ctx.ProcessID()))
4645       SendPacket("OK");
4646     else
4647       SendPacket("E");
4648   } else {
4649     SendPacket("E");
4650   }
4651   return rnb_success;
4652 }
4653 
4654 /* 'k'
4655  Kill the inferior process.  */
4656 
4657 rnb_err_t RNBRemote::HandlePacket_k(const char *p) {
4658   DNBLog("Got a 'k' packet, killing the inferior process.");
4659   // No response to should be sent to the kill packet
4660   if (m_ctx.HasValidProcessID())
4661     DNBProcessKill(m_ctx.ProcessID());
4662   SendPacket("X09");
4663   return rnb_success;
4664 }
4665 
4666 rnb_err_t RNBRemote::HandlePacket_stop_process(const char *p) {
4667 //#define TEST_EXIT_ON_INTERRUPT // This should only be uncommented to test
4668 //exiting on interrupt
4669 #if defined(TEST_EXIT_ON_INTERRUPT)
4670   rnb_err_t err = HandlePacket_k(p);
4671   m_comm.Disconnect(true);
4672   return err;
4673 #else
4674   if (!DNBProcessInterrupt(m_ctx.ProcessID())) {
4675     // If we failed to interrupt the process, then send a stop
4676     // reply packet as the process was probably already stopped
4677     DNBLogThreaded("RNBRemote::HandlePacket_stop_process() sending extra stop "
4678                    "reply because DNBProcessInterrupt returned false");
4679     HandlePacket_last_signal(NULL);
4680   }
4681   return rnb_success;
4682 #endif
4683 }
4684 
4685 /* 's'
4686  Step the inferior process.  */
4687 
4688 rnb_err_t RNBRemote::HandlePacket_s(const char *p) {
4689   const nub_process_t pid = m_ctx.ProcessID();
4690   if (pid == INVALID_NUB_PROCESS)
4691     return SendPacket("E32");
4692 
4693   // Hardware supported stepping not supported on arm
4694   nub_thread_t tid = GetContinueThread();
4695   if (tid == 0 || tid == (nub_thread_t)-1)
4696     tid = GetCurrentThread();
4697 
4698   if (tid == INVALID_NUB_THREAD)
4699     return SendPacket("E33");
4700 
4701   DNBThreadResumeActions thread_actions;
4702   thread_actions.AppendAction(tid, eStateStepping);
4703 
4704   // Make all other threads stop when we are stepping
4705   thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
4706   if (!DNBProcessResume(pid, thread_actions.GetFirst(),
4707                         thread_actions.GetSize()))
4708     return SendPacket("E49");
4709   // Don't send an "OK" packet; response is the stopped/exited message.
4710   return rnb_success;
4711 }
4712 
4713 /* 'S sig [;addr]'
4714  Step with signal sig, optionally at address addr.  */
4715 
4716 rnb_err_t RNBRemote::HandlePacket_S(const char *p) {
4717   const nub_process_t pid = m_ctx.ProcessID();
4718   if (pid == INVALID_NUB_PROCESS)
4719     return SendPacket("E36");
4720 
4721   DNBThreadResumeAction action = {INVALID_NUB_THREAD, eStateStepping, 0,
4722                                   INVALID_NUB_ADDRESS};
4723 
4724   if (*(p + 1) != '\0') {
4725     char *end = NULL;
4726     errno = 0;
4727     action.signal = static_cast<int>(strtoul(p + 1, &end, 16));
4728     if (errno != 0)
4729       return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4730                                     "Could not parse signal in S packet");
4731     else if (*end == ';') {
4732       errno = 0;
4733       action.addr = strtoull(end + 1, NULL, 16);
4734       if (errno != 0 && action.addr == 0) {
4735         return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4736                                       "Could not parse address in S packet");
4737       }
4738     }
4739   }
4740 
4741   action.tid = GetContinueThread();
4742   if (action.tid == 0 || action.tid == (nub_thread_t)-1)
4743     return SendPacket("E40");
4744 
4745   nub_state_t tstate = DNBThreadGetState(pid, action.tid);
4746   if (tstate == eStateInvalid || tstate == eStateExited)
4747     return SendPacket("E37");
4748 
4749   DNBThreadResumeActions thread_actions;
4750   thread_actions.Append(action);
4751 
4752   // Make all other threads stop when we are stepping
4753   thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
4754   if (!DNBProcessResume(pid, thread_actions.GetFirst(),
4755                         thread_actions.GetSize()))
4756     return SendPacket("E39");
4757 
4758   // Don't send an "OK" packet; response is the stopped/exited message.
4759   return rnb_success;
4760 }
4761 
4762 static const char *GetArchName(const uint32_t cputype,
4763                                const uint32_t cpusubtype) {
4764   switch (cputype) {
4765   case CPU_TYPE_ARM:
4766     switch (cpusubtype) {
4767     case 5:
4768       return "armv4";
4769     case 6:
4770       return "armv6";
4771     case 7:
4772       return "armv5t";
4773     case 8:
4774       return "xscale";
4775     case 9:
4776       return "armv7";
4777     case 10:
4778       return "armv7f";
4779     case 11:
4780       return "armv7s";
4781     case 12:
4782       return "armv7k";
4783     case 14:
4784       return "armv6m";
4785     case 15:
4786       return "armv7m";
4787     case 16:
4788       return "armv7em";
4789     default:
4790       return "arm";
4791     }
4792     break;
4793   case CPU_TYPE_ARM64:
4794     return "arm64";
4795   case CPU_TYPE_ARM64_32:
4796     return "arm64_32";
4797   case CPU_TYPE_I386:
4798     return "i386";
4799   case CPU_TYPE_X86_64:
4800     switch (cpusubtype) {
4801     default:
4802       return "x86_64";
4803     case 8:
4804       return "x86_64h";
4805     }
4806     break;
4807   }
4808   return NULL;
4809 }
4810 
4811 static bool GetHostCPUType(uint32_t &cputype, uint32_t &cpusubtype,
4812                            uint32_t &is_64_bit_capable, bool &promoted_to_64) {
4813   static uint32_t g_host_cputype = 0;
4814   static uint32_t g_host_cpusubtype = 0;
4815   static uint32_t g_is_64_bit_capable = 0;
4816   static bool g_promoted_to_64 = false;
4817 
4818   if (g_host_cputype == 0) {
4819     g_promoted_to_64 = false;
4820     size_t len = sizeof(uint32_t);
4821     if (::sysctlbyname("hw.cputype", &g_host_cputype, &len, NULL, 0) == 0) {
4822       len = sizeof(uint32_t);
4823       if (::sysctlbyname("hw.cpu64bit_capable", &g_is_64_bit_capable, &len,
4824                          NULL, 0) == 0) {
4825         if (g_is_64_bit_capable && ((g_host_cputype & CPU_ARCH_ABI64) == 0)) {
4826           g_promoted_to_64 = true;
4827           g_host_cputype |= CPU_ARCH_ABI64;
4828         }
4829       }
4830 #if defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
4831       if (g_host_cputype == CPU_TYPE_ARM64 && sizeof (void*) == 4)
4832         g_host_cputype = CPU_TYPE_ARM64_32;
4833 #endif
4834     }
4835 
4836     len = sizeof(uint32_t);
4837     if (::sysctlbyname("hw.cpusubtype", &g_host_cpusubtype, &len, NULL, 0) ==
4838         0) {
4839       if (g_promoted_to_64 && g_host_cputype == CPU_TYPE_X86_64 &&
4840           g_host_cpusubtype == CPU_SUBTYPE_486)
4841         g_host_cpusubtype = CPU_SUBTYPE_X86_64_ALL;
4842     }
4843 #if defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
4844     // on arm64_32 devices, the machine's native cpu type is
4845     // CPU_TYPE_ARM64 and subtype is 2 indicating arm64e.
4846     // But we change the cputype to CPU_TYPE_ARM64_32 because
4847     // the user processes are all ILP32 processes today.
4848     // We also need to rewrite the cpusubtype so we vend
4849     // a valid cputype + cpusubtype combination.
4850     if (g_host_cputype == CPU_TYPE_ARM64_32)
4851       g_host_cpusubtype = CPU_SUBTYPE_ARM64_32_V8;
4852 #endif
4853   }
4854 
4855   cputype = g_host_cputype;
4856   cpusubtype = g_host_cpusubtype;
4857   is_64_bit_capable = g_is_64_bit_capable;
4858   promoted_to_64 = g_promoted_to_64;
4859   return g_host_cputype != 0;
4860 }
4861 
4862 static bool GetAddressingBits(uint32_t &addressing_bits) {
4863   static uint32_t g_addressing_bits = 0;
4864   static bool g_tried_addressing_bits_syscall = false;
4865   if (g_tried_addressing_bits_syscall == false) {
4866     size_t len = sizeof (uint32_t);
4867     if (::sysctlbyname("machdep.virtual_address_size",
4868           &g_addressing_bits, &len, NULL, 0) != 0) {
4869       g_addressing_bits = 0;
4870     }
4871   }
4872   g_tried_addressing_bits_syscall = true;
4873   addressing_bits = g_addressing_bits;
4874   if (addressing_bits > 0)
4875     return true;
4876   else
4877     return false;
4878 }
4879 
4880 rnb_err_t RNBRemote::HandlePacket_qHostInfo(const char *p) {
4881   std::ostringstream strm;
4882 
4883   uint32_t cputype = 0;
4884   uint32_t cpusubtype = 0;
4885   uint32_t is_64_bit_capable = 0;
4886   bool promoted_to_64 = false;
4887   if (GetHostCPUType(cputype, cpusubtype, is_64_bit_capable, promoted_to_64)) {
4888     strm << "cputype:" << std::dec << cputype << ';';
4889     strm << "cpusubtype:" << std::dec << cpusubtype << ';';
4890   }
4891 
4892   uint32_t addressing_bits = 0;
4893   if (GetAddressingBits(addressing_bits)) {
4894     strm << "addressing_bits:" << std::dec << addressing_bits << ';';
4895   }
4896 
4897   // The OS in the triple should be "ios" or "macosx" which doesn't match our
4898   // "Darwin" which gets returned from "kern.ostype", so we need to hardcode
4899   // this for now.
4900   if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64
4901       || cputype == CPU_TYPE_ARM64_32) {
4902 #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
4903     strm << "ostype:tvos;";
4904 #elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
4905     strm << "ostype:watchos;";
4906 #elif defined(TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1
4907     strm << "ostype:bridgeos;";
4908 #else
4909     strm << "ostype:ios;";
4910 #endif
4911 
4912     // On armv7 we use "synchronous" watchpoints which means the exception is
4913     // delivered before the instruction executes.
4914     strm << "watchpoint_exceptions_received:before;";
4915   } else {
4916     strm << "ostype:macosx;";
4917     strm << "watchpoint_exceptions_received:after;";
4918   }
4919   //    char ostype[64];
4920   //    len = sizeof(ostype);
4921   //    if (::sysctlbyname("kern.ostype", &ostype, &len, NULL, 0) == 0)
4922   //    {
4923   //        len = strlen(ostype);
4924   //        std::transform (ostype, ostype + len, ostype, tolower);
4925   //        strm << "ostype:" << std::dec << ostype << ';';
4926   //    }
4927 
4928   strm << "vendor:apple;";
4929 
4930   uint64_t major, minor, patch;
4931   if (DNBGetOSVersionNumbers(&major, &minor, &patch)) {
4932     strm << "os_version:" << major << "." << minor;
4933     if (patch != UINT64_MAX)
4934       strm << "." << patch;
4935     strm << ";";
4936   }
4937 
4938   std::string maccatalyst_version = DNBGetMacCatalystVersionString();
4939   if (!maccatalyst_version.empty() &&
4940       std::all_of(maccatalyst_version.begin(), maccatalyst_version.end(),
4941                   [](char c) { return (c >= '0' && c <= '9') || c == '.'; }))
4942     strm << "maccatalyst_version:" << maccatalyst_version << ";";
4943 
4944 #if defined(__LITTLE_ENDIAN__)
4945   strm << "endian:little;";
4946 #elif defined(__BIG_ENDIAN__)
4947   strm << "endian:big;";
4948 #elif defined(__PDP_ENDIAN__)
4949   strm << "endian:pdp;";
4950 #endif
4951 
4952   if (promoted_to_64)
4953     strm << "ptrsize:8;";
4954   else
4955     strm << "ptrsize:" << std::dec << sizeof(void *) << ';';
4956 
4957 #if defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
4958   strm << "default_packet_timeout:10;";
4959 #endif
4960 
4961   return SendPacket(strm.str());
4962 }
4963 
4964 void XMLElementStart(std::ostringstream &s, uint32_t indent, const char *name,
4965                      bool has_attributes) {
4966   if (indent)
4967     s << INDENT_WITH_SPACES(indent);
4968   s << '<' << name;
4969   if (!has_attributes)
4970     s << '>' << std::endl;
4971 }
4972 
4973 void XMLElementStartEndAttributes(std::ostringstream &s, bool empty) {
4974   if (empty)
4975     s << '/';
4976   s << '>' << std::endl;
4977 }
4978 
4979 void XMLElementEnd(std::ostringstream &s, uint32_t indent, const char *name) {
4980   if (indent)
4981     s << INDENT_WITH_SPACES(indent);
4982   s << '<' << '/' << name << '>' << std::endl;
4983 }
4984 
4985 void XMLElementWithStringValue(std::ostringstream &s, uint32_t indent,
4986                                const char *name, const char *value,
4987                                bool close = true) {
4988   if (value) {
4989     if (indent)
4990       s << INDENT_WITH_SPACES(indent);
4991     s << '<' << name << '>' << value;
4992     if (close)
4993       XMLElementEnd(s, 0, name);
4994   }
4995 }
4996 
4997 void XMLElementWithUnsignedValue(std::ostringstream &s, uint32_t indent,
4998                                  const char *name, uint64_t value,
4999                                  bool close = true) {
5000   if (indent)
5001     s << INDENT_WITH_SPACES(indent);
5002 
5003   s << '<' << name << '>' << DECIMAL << value;
5004   if (close)
5005     XMLElementEnd(s, 0, name);
5006 }
5007 
5008 void XMLAttributeString(std::ostringstream &s, const char *name,
5009                         const char *value, const char *default_value = NULL) {
5010   if (value) {
5011     if (default_value && strcmp(value, default_value) == 0)
5012       return; // No need to emit the attribute because it matches the default
5013               // value
5014     s << ' ' << name << "=\"" << value << "\"";
5015   }
5016 }
5017 
5018 void XMLAttributeUnsignedDecimal(std::ostringstream &s, const char *name,
5019                                  uint64_t value) {
5020   s << ' ' << name << "=\"" << DECIMAL << value << "\"";
5021 }
5022 
5023 void GenerateTargetXMLRegister(std::ostringstream &s, const uint32_t reg_num,
5024                                nub_size_t num_reg_sets,
5025                                const DNBRegisterSetInfo *reg_set_info,
5026                                const register_map_entry_t &reg) {
5027   const char *default_lldb_encoding = "uint";
5028   const char *lldb_encoding = default_lldb_encoding;
5029   const char *gdb_group = "general";
5030   const char *default_gdb_type = "int";
5031   const char *gdb_type = default_gdb_type;
5032   const char *default_lldb_format = "hex";
5033   const char *lldb_format = default_lldb_format;
5034   const char *lldb_set = NULL;
5035 
5036   switch (reg.nub_info.type) {
5037   case Uint:
5038     lldb_encoding = "uint";
5039     break;
5040   case Sint:
5041     lldb_encoding = "sint";
5042     break;
5043   case IEEE754:
5044     lldb_encoding = "ieee754";
5045     if (reg.nub_info.set > 0)
5046       gdb_group = "float";
5047     break;
5048   case Vector:
5049     lldb_encoding = "vector";
5050     if (reg.nub_info.set > 0)
5051       gdb_group = "vector";
5052     break;
5053   }
5054 
5055   switch (reg.nub_info.format) {
5056   case Binary:
5057     lldb_format = "binary";
5058     break;
5059   case Decimal:
5060     lldb_format = "decimal";
5061     break;
5062   case Hex:
5063     lldb_format = "hex";
5064     break;
5065   case Float:
5066     gdb_type = "float";
5067     lldb_format = "float";
5068     break;
5069   case VectorOfSInt8:
5070     gdb_type = "float";
5071     lldb_format = "vector-sint8";
5072     break;
5073   case VectorOfUInt8:
5074     gdb_type = "float";
5075     lldb_format = "vector-uint8";
5076     break;
5077   case VectorOfSInt16:
5078     gdb_type = "float";
5079     lldb_format = "vector-sint16";
5080     break;
5081   case VectorOfUInt16:
5082     gdb_type = "float";
5083     lldb_format = "vector-uint16";
5084     break;
5085   case VectorOfSInt32:
5086     gdb_type = "float";
5087     lldb_format = "vector-sint32";
5088     break;
5089   case VectorOfUInt32:
5090     gdb_type = "float";
5091     lldb_format = "vector-uint32";
5092     break;
5093   case VectorOfFloat32:
5094     gdb_type = "float";
5095     lldb_format = "vector-float32";
5096     break;
5097   case VectorOfUInt128:
5098     gdb_type = "float";
5099     lldb_format = "vector-uint128";
5100     break;
5101   };
5102   if (reg_set_info && reg.nub_info.set < num_reg_sets)
5103     lldb_set = reg_set_info[reg.nub_info.set].name;
5104 
5105   uint32_t indent = 2;
5106 
5107   XMLElementStart(s, indent, "reg", true);
5108   XMLAttributeString(s, "name", reg.nub_info.name);
5109   XMLAttributeUnsignedDecimal(s, "regnum", reg_num);
5110   XMLAttributeUnsignedDecimal(s, "offset", reg.offset);
5111   XMLAttributeUnsignedDecimal(s, "bitsize", reg.nub_info.size * 8);
5112   XMLAttributeString(s, "group", gdb_group);
5113   XMLAttributeString(s, "type", gdb_type, default_gdb_type);
5114   XMLAttributeString(s, "altname", reg.nub_info.alt);
5115   XMLAttributeString(s, "encoding", lldb_encoding, default_lldb_encoding);
5116   XMLAttributeString(s, "format", lldb_format, default_lldb_format);
5117   XMLAttributeUnsignedDecimal(s, "group_id", reg.nub_info.set);
5118   if (reg.nub_info.reg_ehframe != INVALID_NUB_REGNUM)
5119     XMLAttributeUnsignedDecimal(s, "ehframe_regnum", reg.nub_info.reg_ehframe);
5120   if (reg.nub_info.reg_dwarf != INVALID_NUB_REGNUM)
5121     XMLAttributeUnsignedDecimal(s, "dwarf_regnum", reg.nub_info.reg_dwarf);
5122 
5123   const char *lldb_generic = NULL;
5124   switch (reg.nub_info.reg_generic) {
5125   case GENERIC_REGNUM_FP:
5126     lldb_generic = "fp";
5127     break;
5128   case GENERIC_REGNUM_PC:
5129     lldb_generic = "pc";
5130     break;
5131   case GENERIC_REGNUM_SP:
5132     lldb_generic = "sp";
5133     break;
5134   case GENERIC_REGNUM_RA:
5135     lldb_generic = "ra";
5136     break;
5137   case GENERIC_REGNUM_FLAGS:
5138     lldb_generic = "flags";
5139     break;
5140   case GENERIC_REGNUM_ARG1:
5141     lldb_generic = "arg1";
5142     break;
5143   case GENERIC_REGNUM_ARG2:
5144     lldb_generic = "arg2";
5145     break;
5146   case GENERIC_REGNUM_ARG3:
5147     lldb_generic = "arg3";
5148     break;
5149   case GENERIC_REGNUM_ARG4:
5150     lldb_generic = "arg4";
5151     break;
5152   case GENERIC_REGNUM_ARG5:
5153     lldb_generic = "arg5";
5154     break;
5155   case GENERIC_REGNUM_ARG6:
5156     lldb_generic = "arg6";
5157     break;
5158   case GENERIC_REGNUM_ARG7:
5159     lldb_generic = "arg7";
5160     break;
5161   case GENERIC_REGNUM_ARG8:
5162     lldb_generic = "arg8";
5163     break;
5164   default:
5165     break;
5166   }
5167   XMLAttributeString(s, "generic", lldb_generic);
5168 
5169   bool empty = reg.value_regnums.empty() && reg.invalidate_regnums.empty();
5170   if (!empty) {
5171     if (!reg.value_regnums.empty()) {
5172       std::ostringstream regnums;
5173       bool first = true;
5174       regnums << DECIMAL;
5175       for (auto regnum : reg.value_regnums) {
5176         if (!first)
5177           regnums << ',';
5178         regnums << regnum;
5179         first = false;
5180       }
5181       XMLAttributeString(s, "value_regnums", regnums.str().c_str());
5182     }
5183 
5184     if (!reg.invalidate_regnums.empty()) {
5185       std::ostringstream regnums;
5186       bool first = true;
5187       regnums << DECIMAL;
5188       for (auto regnum : reg.invalidate_regnums) {
5189         if (!first)
5190           regnums << ',';
5191         regnums << regnum;
5192         first = false;
5193       }
5194       XMLAttributeString(s, "invalidate_regnums", regnums.str().c_str());
5195     }
5196   }
5197   XMLElementStartEndAttributes(s, true);
5198 }
5199 
5200 void GenerateTargetXMLRegisters(std::ostringstream &s) {
5201   nub_size_t num_reg_sets = 0;
5202   const DNBRegisterSetInfo *reg_sets = DNBGetRegisterSetInfo(&num_reg_sets);
5203 
5204   uint32_t cputype = DNBGetRegisterCPUType();
5205   if (cputype) {
5206     XMLElementStart(s, 0, "feature", true);
5207     std::ostringstream name_strm;
5208     name_strm << "com.apple.debugserver." << GetArchName(cputype, 0);
5209     XMLAttributeString(s, "name", name_strm.str().c_str());
5210     XMLElementStartEndAttributes(s, false);
5211     for (uint32_t reg_num = 0; reg_num < g_num_reg_entries; ++reg_num)
5212     //        for (const auto &reg: g_dynamic_register_map)
5213     {
5214       GenerateTargetXMLRegister(s, reg_num, num_reg_sets, reg_sets,
5215                                 g_reg_entries[reg_num]);
5216     }
5217     XMLElementEnd(s, 0, "feature");
5218 
5219     if (num_reg_sets > 0) {
5220       XMLElementStart(s, 0, "groups", false);
5221       for (uint32_t set = 1; set < num_reg_sets; ++set) {
5222         XMLElementStart(s, 2, "group", true);
5223         XMLAttributeUnsignedDecimal(s, "id", set);
5224         XMLAttributeString(s, "name", reg_sets[set].name);
5225         XMLElementStartEndAttributes(s, true);
5226       }
5227       XMLElementEnd(s, 0, "groups");
5228     }
5229   }
5230 }
5231 
5232 static const char *g_target_xml_header = R"(<?xml version="1.0"?>
5233 <target version="1.0">)";
5234 
5235 static const char *g_target_xml_footer = "</target>";
5236 
5237 static std::string g_target_xml;
5238 
5239 void UpdateTargetXML() {
5240   std::ostringstream s;
5241   s << g_target_xml_header << std::endl;
5242 
5243   // Set the architecture
5244   //
5245   // On raw targets (no OS, vendor info), I've seen replies like
5246   // <architecture>i386:x86-64</architecture> (for x86_64 systems - from vmware)
5247   // <architecture>arm</architecture> (for an unspecified arm device - from a Segger JLink)
5248   // For good interop, I'm not sure what's expected here.  e.g. will anyone understand
5249   // <architecture>x86_64</architecture> ? Or is i386:x86_64 the expected phrasing?
5250   //
5251   // s << "<architecture>" << arch "</architecture>" << std::endl;
5252 
5253   // Set the OSABI
5254   // s << "<osabi>abi-name</osabi>"
5255 
5256   GenerateTargetXMLRegisters(s);
5257 
5258   s << g_target_xml_footer << std::endl;
5259 
5260   // Save the XML output in case it gets retrieved in chunks
5261   g_target_xml = s.str();
5262 }
5263 
5264 rnb_err_t RNBRemote::HandlePacket_qXfer(const char *command) {
5265   const char *p = command;
5266   p += strlen("qXfer:");
5267   const char *sep = strchr(p, ':');
5268   if (sep) {
5269     std::string object(p, sep - p); // "auxv", "backtrace", "features", etc
5270     p = sep + 1;
5271     sep = strchr(p, ':');
5272     if (sep) {
5273       std::string rw(p, sep - p); // "read" or "write"
5274       p = sep + 1;
5275       sep = strchr(p, ':');
5276       if (sep) {
5277         std::string annex(p, sep - p); // "read" or "write"
5278 
5279         p = sep + 1;
5280         sep = strchr(p, ',');
5281         if (sep) {
5282           std::string offset_str(p, sep - p); // read the length as a string
5283           p = sep + 1;
5284           std::string length_str(p); // read the offset as a string
5285           char *end = nullptr;
5286           const uint64_t offset = strtoul(offset_str.c_str(), &end,
5287                                           16); // convert offset_str to a offset
5288           if (*end == '\0') {
5289             const uint64_t length = strtoul(
5290                 length_str.c_str(), &end, 16); // convert length_str to a length
5291             if (*end == '\0') {
5292               if (object == "features" && rw == "read" &&
5293                   annex == "target.xml") {
5294                 std::ostringstream xml_out;
5295 
5296                 if (offset == 0) {
5297                   InitializeRegisters(true);
5298 
5299                   UpdateTargetXML();
5300                   if (g_target_xml.empty())
5301                     return SendPacket("E83");
5302 
5303                   if (length > g_target_xml.size()) {
5304                     xml_out << 'l'; // No more data
5305                     xml_out << binary_encode_string(g_target_xml);
5306                   } else {
5307                     xml_out << 'm'; // More data needs to be read with a
5308                                     // subsequent call
5309                     xml_out << binary_encode_string(
5310                         std::string(g_target_xml, offset, length));
5311                   }
5312                 } else {
5313                   // Retrieving target XML in chunks
5314                   if (offset < g_target_xml.size()) {
5315                     std::string chunk(g_target_xml, offset, length);
5316                     if (chunk.size() < length)
5317                       xml_out << 'l'; // No more data
5318                     else
5319                       xml_out << 'm'; // More data needs to be read with a
5320                                       // subsequent call
5321                     xml_out << binary_encode_string(chunk.data());
5322                   }
5323                 }
5324                 return SendPacket(xml_out.str());
5325               }
5326               // Well formed, put not supported
5327               return HandlePacket_UNIMPLEMENTED(command);
5328             }
5329           }
5330         }
5331       } else {
5332         SendPacket("E85");
5333       }
5334     } else {
5335       SendPacket("E86");
5336     }
5337   }
5338   return SendPacket("E82");
5339 }
5340 
5341 rnb_err_t RNBRemote::HandlePacket_qGDBServerVersion(const char *p) {
5342   std::ostringstream strm;
5343 
5344 #if defined(DEBUGSERVER_PROGRAM_NAME)
5345   strm << "name:" DEBUGSERVER_PROGRAM_NAME ";";
5346 #else
5347   strm << "name:debugserver;";
5348 #endif
5349   strm << "version:" << DEBUGSERVER_VERSION_NUM << ";";
5350 
5351   return SendPacket(strm.str());
5352 }
5353 
5354 // A helper function that retrieves a single integer value from
5355 // a one-level-deep JSON dictionary of key-value pairs.  e.g.
5356 // jThreadExtendedInfo:{"plo_pthread_tsd_base_address_offset":0,"plo_pthread_tsd_base_offset":224,"plo_pthread_tsd_entry_size":8,"thread":144305}]
5357 //
5358 uint64_t get_integer_value_for_key_name_from_json(const char *key,
5359                                                   const char *json_string) {
5360   uint64_t retval = INVALID_NUB_ADDRESS;
5361   std::string key_with_quotes = "\"";
5362   key_with_quotes += key;
5363   key_with_quotes += "\"";
5364   const char *c = strstr(json_string, key_with_quotes.c_str());
5365   if (c) {
5366     c += key_with_quotes.size();
5367 
5368     while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5369       c++;
5370 
5371     if (*c == ':') {
5372       c++;
5373 
5374       while (*c != '\0' &&
5375              (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5376         c++;
5377 
5378       errno = 0;
5379       retval = strtoul(c, NULL, 10);
5380       if (errno != 0) {
5381         retval = INVALID_NUB_ADDRESS;
5382       }
5383     }
5384   }
5385   return retval;
5386 }
5387 
5388 // A helper function that retrieves a boolean value from
5389 // a one-level-deep JSON dictionary of key-value pairs.  e.g.
5390 // jGetLoadedDynamicLibrariesInfos:{"fetch_all_solibs":true}]
5391 
5392 // Returns true if it was able to find the key name, and sets the 'value'
5393 // argument to the value found.
5394 
5395 bool get_boolean_value_for_key_name_from_json(const char *key,
5396                                               const char *json_string,
5397                                               bool &value) {
5398   std::string key_with_quotes = "\"";
5399   key_with_quotes += key;
5400   key_with_quotes += "\"";
5401   const char *c = strstr(json_string, key_with_quotes.c_str());
5402   if (c) {
5403     c += key_with_quotes.size();
5404 
5405     while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5406       c++;
5407 
5408     if (*c == ':') {
5409       c++;
5410 
5411       while (*c != '\0' &&
5412              (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5413         c++;
5414 
5415       if (strncmp(c, "true", 4) == 0) {
5416         value = true;
5417         return true;
5418       } else if (strncmp(c, "false", 5) == 0) {
5419         value = false;
5420         return true;
5421       }
5422     }
5423   }
5424   return false;
5425 }
5426 
5427 // A helper function that reads an array of uint64_t's from
5428 // a one-level-deep JSON dictionary of key-value pairs.  e.g.
5429 // jGetLoadedDynamicLibrariesInfos:{"solib_addrs":[31345823,7768020384,7310483024]}]
5430 
5431 // Returns true if it was able to find the key name, false if it did not.
5432 // "ints" will have all integers found in the array appended to it.
5433 
5434 bool get_array_of_ints_value_for_key_name_from_json(
5435     const char *key, const char *json_string, std::vector<uint64_t> &ints) {
5436   std::string key_with_quotes = "\"";
5437   key_with_quotes += key;
5438   key_with_quotes += "\"";
5439   const char *c = strstr(json_string, key_with_quotes.c_str());
5440   if (c) {
5441     c += key_with_quotes.size();
5442 
5443     while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5444       c++;
5445 
5446     if (*c == ':') {
5447       c++;
5448 
5449       while (*c != '\0' &&
5450              (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5451         c++;
5452 
5453       if (*c == '[') {
5454         c++;
5455         while (*c != '\0' &&
5456                (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5457           c++;
5458         while (true) {
5459           if (!isdigit(*c)) {
5460             return true;
5461           }
5462 
5463           errno = 0;
5464           char *endptr;
5465           uint64_t value = strtoul(c, &endptr, 10);
5466           if (errno == 0) {
5467             ints.push_back(value);
5468           } else {
5469             break;
5470           }
5471           if (endptr == c || endptr == nullptr || *endptr == '\0') {
5472             break;
5473           }
5474           c = endptr;
5475 
5476           while (*c != '\0' &&
5477                  (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5478             c++;
5479           if (*c == ',')
5480             c++;
5481           while (*c != '\0' &&
5482                  (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5483             c++;
5484           if (*c == ']') {
5485             return true;
5486           }
5487         }
5488       }
5489     }
5490   }
5491   return false;
5492 }
5493 
5494 JSONGenerator::ObjectSP
5495 RNBRemote::GetJSONThreadsInfo(bool threads_with_valid_stop_info_only) {
5496   JSONGenerator::ArraySP threads_array_sp;
5497   if (m_ctx.HasValidProcessID()) {
5498     threads_array_sp = std::make_shared<JSONGenerator::Array>();
5499 
5500     nub_process_t pid = m_ctx.ProcessID();
5501 
5502     nub_size_t numthreads = DNBProcessGetNumThreads(pid);
5503     for (nub_size_t i = 0; i < numthreads; ++i) {
5504       nub_thread_t tid = DNBProcessGetThreadAtIndex(pid, i);
5505 
5506       struct DNBThreadStopInfo tid_stop_info;
5507 
5508       const bool stop_info_valid =
5509           DNBThreadGetStopReason(pid, tid, &tid_stop_info);
5510 
5511       // If we are doing stop info only, then we only show threads that have a
5512       // valid stop reason
5513       if (threads_with_valid_stop_info_only) {
5514         if (!stop_info_valid || tid_stop_info.reason == eStopTypeInvalid)
5515           continue;
5516       }
5517 
5518       JSONGenerator::DictionarySP thread_dict_sp(
5519           new JSONGenerator::Dictionary());
5520       thread_dict_sp->AddIntegerItem("tid", tid);
5521 
5522       std::string reason_value("none");
5523 
5524       if (stop_info_valid) {
5525         switch (tid_stop_info.reason) {
5526         case eStopTypeInvalid:
5527           break;
5528 
5529         case eStopTypeSignal:
5530           if (tid_stop_info.details.signal.signo != 0) {
5531             thread_dict_sp->AddIntegerItem("signal",
5532                                            tid_stop_info.details.signal.signo);
5533             reason_value = "signal";
5534           }
5535           break;
5536 
5537         case eStopTypeException:
5538           if (tid_stop_info.details.exception.type != 0) {
5539             reason_value = "exception";
5540             thread_dict_sp->AddIntegerItem(
5541                 "metype", tid_stop_info.details.exception.type);
5542             JSONGenerator::ArraySP medata_array_sp(new JSONGenerator::Array());
5543             for (nub_size_t i = 0;
5544                  i < tid_stop_info.details.exception.data_count; ++i) {
5545               medata_array_sp->AddItem(
5546                   JSONGenerator::IntegerSP(new JSONGenerator::Integer(
5547                       tid_stop_info.details.exception.data[i])));
5548             }
5549             thread_dict_sp->AddItem("medata", medata_array_sp);
5550           }
5551           break;
5552 
5553         case eStopTypeExec:
5554           reason_value = "exec";
5555           break;
5556         }
5557       }
5558 
5559       thread_dict_sp->AddStringItem("reason", reason_value);
5560 
5561       if (!threads_with_valid_stop_info_only) {
5562         const char *thread_name = DNBThreadGetName(pid, tid);
5563         if (thread_name && thread_name[0])
5564           thread_dict_sp->AddStringItem("name", thread_name);
5565 
5566         thread_identifier_info_data_t thread_ident_info;
5567         if (DNBThreadGetIdentifierInfo(pid, tid, &thread_ident_info)) {
5568           if (thread_ident_info.dispatch_qaddr != 0) {
5569             thread_dict_sp->AddIntegerItem("qaddr",
5570                                            thread_ident_info.dispatch_qaddr);
5571 
5572             const DispatchQueueOffsets *dispatch_queue_offsets =
5573                 GetDispatchQueueOffsets();
5574             if (dispatch_queue_offsets) {
5575               std::string queue_name;
5576               uint64_t queue_width = 0;
5577               uint64_t queue_serialnum = 0;
5578               nub_addr_t dispatch_queue_t = INVALID_NUB_ADDRESS;
5579               dispatch_queue_offsets->GetThreadQueueInfo(
5580                   pid, thread_ident_info.dispatch_qaddr, dispatch_queue_t,
5581                   queue_name, queue_width, queue_serialnum);
5582               if (dispatch_queue_t == 0 && queue_name.empty() &&
5583                   queue_serialnum == 0) {
5584                 thread_dict_sp->AddBooleanItem("associated_with_dispatch_queue",
5585                                                false);
5586               } else {
5587                 thread_dict_sp->AddBooleanItem("associated_with_dispatch_queue",
5588                                                true);
5589               }
5590               if (dispatch_queue_t != INVALID_NUB_ADDRESS &&
5591                   dispatch_queue_t != 0)
5592                 thread_dict_sp->AddIntegerItem("dispatch_queue_t",
5593                                                dispatch_queue_t);
5594               if (!queue_name.empty())
5595                 thread_dict_sp->AddStringItem("qname", queue_name);
5596               if (queue_width == 1)
5597                 thread_dict_sp->AddStringItem("qkind", "serial");
5598               else if (queue_width > 1)
5599                 thread_dict_sp->AddStringItem("qkind", "concurrent");
5600               if (queue_serialnum > 0)
5601                 thread_dict_sp->AddIntegerItem("qserialnum", queue_serialnum);
5602             }
5603           }
5604         }
5605 
5606         DNBRegisterValue reg_value;
5607 
5608         if (g_reg_entries != NULL) {
5609           JSONGenerator::DictionarySP registers_dict_sp(
5610               new JSONGenerator::Dictionary());
5611 
5612           for (uint32_t reg = 0; reg < g_num_reg_entries; reg++) {
5613             // Expedite all registers in the first register set that aren't
5614             // contained in other registers
5615             if (g_reg_entries[reg].nub_info.set == 1 &&
5616                 g_reg_entries[reg].nub_info.value_regs == NULL) {
5617               if (!DNBThreadGetRegisterValueByID(
5618                       pid, tid, g_reg_entries[reg].nub_info.set,
5619                       g_reg_entries[reg].nub_info.reg, &reg_value))
5620                 continue;
5621 
5622               std::ostringstream reg_num;
5623               reg_num << std::dec << g_reg_entries[reg].debugserver_regnum;
5624               // Encode native byte ordered bytes as hex ascii
5625               registers_dict_sp->AddBytesAsHexASCIIString(
5626                   reg_num.str(), reg_value.value.v_uint8,
5627                   g_reg_entries[reg].nub_info.size);
5628             }
5629           }
5630           thread_dict_sp->AddItem("registers", registers_dict_sp);
5631         }
5632 
5633         // Add expedited stack memory so stack backtracing doesn't need to read
5634         // anything from the
5635         // frame pointer chain.
5636         StackMemoryMap stack_mmap;
5637         ReadStackMemory(pid, tid, stack_mmap);
5638         if (!stack_mmap.empty()) {
5639           JSONGenerator::ArraySP memory_array_sp(new JSONGenerator::Array());
5640 
5641           for (const auto &stack_memory : stack_mmap) {
5642             JSONGenerator::DictionarySP stack_memory_sp(
5643                 new JSONGenerator::Dictionary());
5644             stack_memory_sp->AddIntegerItem("address", stack_memory.first);
5645             stack_memory_sp->AddBytesAsHexASCIIString(
5646                 "bytes", stack_memory.second.bytes, stack_memory.second.length);
5647             memory_array_sp->AddItem(stack_memory_sp);
5648           }
5649           thread_dict_sp->AddItem("memory", memory_array_sp);
5650         }
5651       }
5652 
5653       threads_array_sp->AddItem(thread_dict_sp);
5654     }
5655   }
5656   return threads_array_sp;
5657 }
5658 
5659 rnb_err_t RNBRemote::HandlePacket_jThreadsInfo(const char *p) {
5660   JSONGenerator::ObjectSP threads_info_sp;
5661   std::ostringstream json;
5662   std::ostringstream reply_strm;
5663   // If we haven't run the process yet, return an error.
5664   if (m_ctx.HasValidProcessID()) {
5665     const bool threads_with_valid_stop_info_only = false;
5666     JSONGenerator::ObjectSP threads_info_sp =
5667         GetJSONThreadsInfo(threads_with_valid_stop_info_only);
5668 
5669     if (threads_info_sp) {
5670       std::ostringstream strm;
5671       threads_info_sp->Dump(strm);
5672       std::string binary_packet = binary_encode_string(strm.str());
5673       if (!binary_packet.empty())
5674         return SendPacket(binary_packet.c_str());
5675     }
5676   }
5677   return SendPacket("E85");
5678 }
5679 
5680 rnb_err_t RNBRemote::HandlePacket_jThreadExtendedInfo(const char *p) {
5681   nub_process_t pid;
5682   std::ostringstream json;
5683   // If we haven't run the process yet, return an error.
5684   if (!m_ctx.HasValidProcessID()) {
5685     return SendPacket("E81");
5686   }
5687 
5688   pid = m_ctx.ProcessID();
5689 
5690   const char thread_extended_info_str[] = {"jThreadExtendedInfo:{"};
5691   if (strncmp(p, thread_extended_info_str,
5692               sizeof(thread_extended_info_str) - 1) == 0) {
5693     p += strlen(thread_extended_info_str);
5694 
5695     uint64_t tid = get_integer_value_for_key_name_from_json("thread", p);
5696     uint64_t plo_pthread_tsd_base_address_offset =
5697         get_integer_value_for_key_name_from_json(
5698             "plo_pthread_tsd_base_address_offset", p);
5699     uint64_t plo_pthread_tsd_base_offset =
5700         get_integer_value_for_key_name_from_json("plo_pthread_tsd_base_offset",
5701                                                  p);
5702     uint64_t plo_pthread_tsd_entry_size =
5703         get_integer_value_for_key_name_from_json("plo_pthread_tsd_entry_size",
5704                                                  p);
5705     uint64_t dti_qos_class_index =
5706         get_integer_value_for_key_name_from_json("dti_qos_class_index", p);
5707 
5708     if (tid != INVALID_NUB_ADDRESS) {
5709       nub_addr_t pthread_t_value = DNBGetPThreadT(pid, tid);
5710 
5711       uint64_t tsd_address = INVALID_NUB_ADDRESS;
5712       if (plo_pthread_tsd_entry_size != INVALID_NUB_ADDRESS &&
5713           plo_pthread_tsd_base_offset != INVALID_NUB_ADDRESS &&
5714           plo_pthread_tsd_entry_size != INVALID_NUB_ADDRESS) {
5715         tsd_address = DNBGetTSDAddressForThread(
5716             pid, tid, plo_pthread_tsd_base_address_offset,
5717             plo_pthread_tsd_base_offset, plo_pthread_tsd_entry_size);
5718       }
5719 
5720       bool timed_out = false;
5721       Genealogy::ThreadActivitySP thread_activity_sp;
5722 
5723       // If the pthread_t value is invalid, or if we were able to fetch the
5724       // thread's TSD base
5725       // and got an invalid value back, then we have a thread in early startup
5726       // or shutdown and
5727       // it's possible that gathering the genealogy information for this thread
5728       // go badly.
5729       // Ideally fetching this info for a thread in these odd states shouldn't
5730       // matter - but
5731       // we've seen some problems with these new SPI and threads in edge-casey
5732       // states.
5733 
5734       double genealogy_fetch_time = 0;
5735       if (pthread_t_value != INVALID_NUB_ADDRESS &&
5736           tsd_address != INVALID_NUB_ADDRESS) {
5737         DNBTimer timer(false);
5738         thread_activity_sp = DNBGetGenealogyInfoForThread(pid, tid, timed_out);
5739         genealogy_fetch_time = timer.ElapsedMicroSeconds(false) / 1000000.0;
5740       }
5741 
5742       std::unordered_set<uint32_t>
5743           process_info_indexes; // an array of the process info #'s seen
5744 
5745       json << "{";
5746 
5747       bool need_to_print_comma = false;
5748 
5749       if (thread_activity_sp && !timed_out) {
5750         const Genealogy::Activity *activity =
5751             &thread_activity_sp->current_activity;
5752         bool need_vouchers_comma_sep = false;
5753         json << "\"activity_query_timed_out\":false,";
5754         if (genealogy_fetch_time != 0) {
5755           //  If we append the floating point value with << we'll get it in
5756           //  scientific
5757           //  notation.
5758           char floating_point_ascii_buffer[64];
5759           floating_point_ascii_buffer[0] = '\0';
5760           snprintf(floating_point_ascii_buffer,
5761                    sizeof(floating_point_ascii_buffer), "%f",
5762                    genealogy_fetch_time);
5763           if (strlen(floating_point_ascii_buffer) > 0) {
5764             if (need_to_print_comma)
5765               json << ",";
5766             need_to_print_comma = true;
5767             json << "\"activity_query_duration\":"
5768                  << floating_point_ascii_buffer;
5769           }
5770         }
5771         if (activity->activity_id != 0) {
5772           if (need_to_print_comma)
5773             json << ",";
5774           need_to_print_comma = true;
5775           need_vouchers_comma_sep = true;
5776           json << "\"activity\":{";
5777           json << "\"start\":" << activity->activity_start << ",";
5778           json << "\"id\":" << activity->activity_id << ",";
5779           json << "\"parent_id\":" << activity->parent_id << ",";
5780           json << "\"name\":\""
5781                << json_string_quote_metachars(activity->activity_name) << "\",";
5782           json << "\"reason\":\""
5783                << json_string_quote_metachars(activity->reason) << "\"";
5784           json << "}";
5785         }
5786         if (thread_activity_sp->messages.size() > 0) {
5787           need_to_print_comma = true;
5788           if (need_vouchers_comma_sep)
5789             json << ",";
5790           need_vouchers_comma_sep = true;
5791           json << "\"trace_messages\":[";
5792           bool printed_one_message = false;
5793           for (auto iter = thread_activity_sp->messages.begin();
5794                iter != thread_activity_sp->messages.end(); ++iter) {
5795             if (printed_one_message)
5796               json << ",";
5797             else
5798               printed_one_message = true;
5799             json << "{";
5800             json << "\"timestamp\":" << iter->timestamp << ",";
5801             json << "\"activity_id\":" << iter->activity_id << ",";
5802             json << "\"trace_id\":" << iter->trace_id << ",";
5803             json << "\"thread\":" << iter->thread << ",";
5804             json << "\"type\":" << (int)iter->type << ",";
5805             json << "\"process_info_index\":" << iter->process_info_index
5806                  << ",";
5807             process_info_indexes.insert(iter->process_info_index);
5808             json << "\"message\":\""
5809                  << json_string_quote_metachars(iter->message) << "\"";
5810             json << "}";
5811           }
5812           json << "]";
5813         }
5814         if (thread_activity_sp->breadcrumbs.size() == 1) {
5815           need_to_print_comma = true;
5816           if (need_vouchers_comma_sep)
5817             json << ",";
5818           need_vouchers_comma_sep = true;
5819           json << "\"breadcrumb\":{";
5820           for (auto iter = thread_activity_sp->breadcrumbs.begin();
5821                iter != thread_activity_sp->breadcrumbs.end(); ++iter) {
5822             json << "\"breadcrumb_id\":" << iter->breadcrumb_id << ",";
5823             json << "\"activity_id\":" << iter->activity_id << ",";
5824             json << "\"timestamp\":" << iter->timestamp << ",";
5825             json << "\"name\":\"" << json_string_quote_metachars(iter->name)
5826                  << "\"";
5827           }
5828           json << "}";
5829         }
5830         if (process_info_indexes.size() > 0) {
5831           need_to_print_comma = true;
5832           if (need_vouchers_comma_sep)
5833             json << ",";
5834           need_vouchers_comma_sep = true;
5835           bool printed_one_process_info = false;
5836           for (auto iter = process_info_indexes.begin();
5837                iter != process_info_indexes.end(); ++iter) {
5838             if (printed_one_process_info)
5839               json << ",";
5840             Genealogy::ProcessExecutableInfoSP image_info_sp;
5841             uint32_t idx = *iter;
5842             image_info_sp = DNBGetGenealogyImageInfo(pid, idx);
5843             if (image_info_sp) {
5844               if (!printed_one_process_info) {
5845                 json << "\"process_infos\":[";
5846                 printed_one_process_info = true;
5847               }
5848 
5849               json << "{";
5850               char uuid_buf[37];
5851               uuid_unparse_upper(image_info_sp->image_uuid, uuid_buf);
5852               json << "\"process_info_index\":" << idx << ",";
5853               json << "\"image_path\":\""
5854                    << json_string_quote_metachars(image_info_sp->image_path)
5855                    << "\",";
5856               json << "\"image_uuid\":\"" << uuid_buf << "\"";
5857               json << "}";
5858             }
5859           }
5860           if (printed_one_process_info)
5861             json << "]";
5862         }
5863       } else {
5864         if (timed_out) {
5865           if (need_to_print_comma)
5866             json << ",";
5867           need_to_print_comma = true;
5868           json << "\"activity_query_timed_out\":true";
5869           if (genealogy_fetch_time != 0) {
5870             //  If we append the floating point value with << we'll get it in
5871             //  scientific
5872             //  notation.
5873             char floating_point_ascii_buffer[64];
5874             floating_point_ascii_buffer[0] = '\0';
5875             snprintf(floating_point_ascii_buffer,
5876                      sizeof(floating_point_ascii_buffer), "%f",
5877                      genealogy_fetch_time);
5878             if (strlen(floating_point_ascii_buffer) > 0) {
5879               json << ",";
5880               json << "\"activity_query_duration\":"
5881                    << floating_point_ascii_buffer;
5882             }
5883           }
5884         }
5885       }
5886 
5887       if (tsd_address != INVALID_NUB_ADDRESS) {
5888         if (need_to_print_comma)
5889           json << ",";
5890         need_to_print_comma = true;
5891         json << "\"tsd_address\":" << tsd_address;
5892 
5893         if (dti_qos_class_index != 0 && dti_qos_class_index != UINT64_MAX) {
5894           ThreadInfo::QoS requested_qos = DNBGetRequestedQoSForThread(
5895               pid, tid, tsd_address, dti_qos_class_index);
5896           if (requested_qos.IsValid()) {
5897             if (need_to_print_comma)
5898               json << ",";
5899             need_to_print_comma = true;
5900             json << "\"requested_qos\":{";
5901             json << "\"enum_value\":" << requested_qos.enum_value << ",";
5902             json << "\"constant_name\":\""
5903                  << json_string_quote_metachars(requested_qos.constant_name)
5904                  << "\",";
5905             json << "\"printable_name\":\""
5906                  << json_string_quote_metachars(requested_qos.printable_name)
5907                  << "\"";
5908             json << "}";
5909           }
5910         }
5911       }
5912 
5913       if (pthread_t_value != INVALID_NUB_ADDRESS) {
5914         if (need_to_print_comma)
5915           json << ",";
5916         need_to_print_comma = true;
5917         json << "\"pthread_t\":" << pthread_t_value;
5918       }
5919 
5920       nub_addr_t dispatch_queue_t_value = DNBGetDispatchQueueT(pid, tid);
5921       if (dispatch_queue_t_value != INVALID_NUB_ADDRESS) {
5922         if (need_to_print_comma)
5923           json << ",";
5924         need_to_print_comma = true;
5925         json << "\"dispatch_queue_t\":" << dispatch_queue_t_value;
5926       }
5927 
5928       json << "}";
5929       std::string json_quoted = binary_encode_string(json.str());
5930       return SendPacket(json_quoted);
5931     }
5932   }
5933   return SendPacket("OK");
5934 }
5935 
5936 //  This packet may be called in one of three ways:
5937 //
5938 //  jGetLoadedDynamicLibrariesInfos:{"image_count":40,"image_list_address":4295244704}
5939 //      Look for an array of the old dyld_all_image_infos style of binary infos
5940 //      at the image_list_address.
5941 //      This an array of {void* load_addr, void* mod_date, void* pathname}
5942 //
5943 //  jGetLoadedDynamicLibrariesInfos:{"fetch_all_solibs":true}
5944 //      Use the new style (macOS 10.12, tvOS 10, iOS 10, watchOS 3) dyld SPI to
5945 //      get a list of all the
5946 //      libraries loaded
5947 //
5948 //  jGetLoadedDynamicLibrariesInfos:{"solib_addresses":[8382824135,3258302053,830202858503]}
5949 //      Use the new style (macOS 10.12, tvOS 10, iOS 10, watchOS 3) dyld SPI to
5950 //      get the information
5951 //      about the libraries loaded at these addresses.
5952 //
5953 rnb_err_t
5954 RNBRemote::HandlePacket_jGetLoadedDynamicLibrariesInfos(const char *p) {
5955   nub_process_t pid;
5956   // If we haven't run the process yet, return an error.
5957   if (!m_ctx.HasValidProcessID()) {
5958     return SendPacket("E83");
5959   }
5960 
5961   pid = m_ctx.ProcessID();
5962 
5963   const char get_loaded_dynamic_libraries_infos_str[] = {
5964       "jGetLoadedDynamicLibrariesInfos:{"};
5965   if (strncmp(p, get_loaded_dynamic_libraries_infos_str,
5966               sizeof(get_loaded_dynamic_libraries_infos_str) - 1) == 0) {
5967     p += strlen(get_loaded_dynamic_libraries_infos_str);
5968 
5969     JSONGenerator::ObjectSP json_sp;
5970 
5971     std::vector<uint64_t> macho_addresses;
5972     bool fetch_all_solibs = false;
5973     if (get_boolean_value_for_key_name_from_json("fetch_all_solibs", p,
5974                                                  fetch_all_solibs) &&
5975         fetch_all_solibs) {
5976       json_sp = DNBGetAllLoadedLibrariesInfos(pid);
5977     } else if (get_array_of_ints_value_for_key_name_from_json(
5978                    "solib_addresses", p, macho_addresses)) {
5979       json_sp = DNBGetLibrariesInfoForAddresses(pid, macho_addresses);
5980     } else {
5981       nub_addr_t image_list_address =
5982           get_integer_value_for_key_name_from_json("image_list_address", p);
5983       nub_addr_t image_count =
5984           get_integer_value_for_key_name_from_json("image_count", p);
5985 
5986       if (image_list_address != INVALID_NUB_ADDRESS &&
5987           image_count != INVALID_NUB_ADDRESS) {
5988         json_sp = DNBGetLoadedDynamicLibrariesInfos(pid, image_list_address,
5989                                                     image_count);
5990       }
5991     }
5992 
5993     if (json_sp.get()) {
5994       std::ostringstream json_str;
5995       json_sp->Dump(json_str);
5996       if (json_str.str().size() > 0) {
5997         std::string json_str_quoted = binary_encode_string(json_str.str());
5998         return SendPacket(json_str_quoted.c_str());
5999       } else {
6000         SendPacket("E84");
6001       }
6002     }
6003   }
6004   return SendPacket("OK");
6005 }
6006 
6007 // This packet does not currently take any arguments.  So the behavior is
6008 //    jGetSharedCacheInfo:{}
6009 //         send information about the inferior's shared cache
6010 //    jGetSharedCacheInfo:
6011 //         send "OK" to indicate that this packet is supported
6012 rnb_err_t RNBRemote::HandlePacket_jGetSharedCacheInfo(const char *p) {
6013   nub_process_t pid;
6014   // If we haven't run the process yet, return an error.
6015   if (!m_ctx.HasValidProcessID()) {
6016     return SendPacket("E85");
6017   }
6018 
6019   pid = m_ctx.ProcessID();
6020 
6021   const char get_shared_cache_info_str[] = {"jGetSharedCacheInfo:{"};
6022   if (strncmp(p, get_shared_cache_info_str,
6023               sizeof(get_shared_cache_info_str) - 1) == 0) {
6024     JSONGenerator::ObjectSP json_sp = DNBGetSharedCacheInfo(pid);
6025 
6026     if (json_sp.get()) {
6027       std::ostringstream json_str;
6028       json_sp->Dump(json_str);
6029       if (json_str.str().size() > 0) {
6030         std::string json_str_quoted = binary_encode_string(json_str.str());
6031         return SendPacket(json_str_quoted.c_str());
6032       } else {
6033         SendPacket("E86");
6034       }
6035     }
6036   }
6037   return SendPacket("OK");
6038 }
6039 
6040 static bool MachHeaderIsMainExecutable(nub_process_t pid, uint32_t addr_size,
6041                                        nub_addr_t mach_header_addr,
6042                                        mach_header &mh) {
6043   DNBLogThreadedIf(LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = %u, "
6044                                  "addr_size = %u, mach_header_addr = "
6045                                  "0x%16.16llx)",
6046                    pid, addr_size, mach_header_addr);
6047   const nub_size_t bytes_read =
6048       DNBProcessMemoryRead(pid, mach_header_addr, sizeof(mh), &mh);
6049   if (bytes_read == sizeof(mh)) {
6050     DNBLogThreadedIf(
6051         LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = %u, addr_size = "
6052                       "%u, mach_header_addr = 0x%16.16llx): mh = {\n  magic = "
6053                       "0x%8.8x\n  cpu = 0x%8.8x\n  sub = 0x%8.8x\n  filetype = "
6054                       "%u\n  ncmds = %u\n  sizeofcmds = 0x%8.8x\n  flags = "
6055                       "0x%8.8x }",
6056         pid, addr_size, mach_header_addr, mh.magic, mh.cputype, mh.cpusubtype,
6057         mh.filetype, mh.ncmds, mh.sizeofcmds, mh.flags);
6058     if ((addr_size == 4 && mh.magic == MH_MAGIC) ||
6059         (addr_size == 8 && mh.magic == MH_MAGIC_64)) {
6060       if (mh.filetype == MH_EXECUTE) {
6061         DNBLogThreadedIf(LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = "
6062                                        "%u, addr_size = %u, mach_header_addr = "
6063                                        "0x%16.16llx) -> this is the "
6064                                        "executable!!!",
6065                          pid, addr_size, mach_header_addr);
6066         return true;
6067       }
6068     }
6069   }
6070   return false;
6071 }
6072 
6073 static nub_addr_t GetMachHeaderForMainExecutable(const nub_process_t pid,
6074                                                  const uint32_t addr_size,
6075                                                  mach_header &mh) {
6076   struct AllImageInfos {
6077     uint32_t version;
6078     uint32_t dylib_info_count;
6079     uint64_t dylib_info_addr;
6080   };
6081 
6082   uint64_t mach_header_addr = 0;
6083 
6084   const nub_addr_t shlib_addr = DNBProcessGetSharedLibraryInfoAddress(pid);
6085   uint8_t bytes[256];
6086   nub_size_t bytes_read = 0;
6087   DNBDataRef data(bytes, sizeof(bytes), false);
6088   DNBDataRef::offset_t offset = 0;
6089   data.SetPointerSize(addr_size);
6090 
6091   // When we are sitting at __dyld_start, the kernel has placed the
6092   // address of the mach header of the main executable on the stack. If we
6093   // read the SP and dereference a pointer, we might find the mach header
6094   // for the executable. We also just make sure there is only 1 thread
6095   // since if we are at __dyld_start we shouldn't have multiple threads.
6096   if (DNBProcessGetNumThreads(pid) == 1) {
6097     nub_thread_t tid = DNBProcessGetThreadAtIndex(pid, 0);
6098     if (tid != INVALID_NUB_THREAD) {
6099       DNBRegisterValue sp_value;
6100       if (DNBThreadGetRegisterValueByID(pid, tid, REGISTER_SET_GENERIC,
6101                                         GENERIC_REGNUM_SP, &sp_value)) {
6102         uint64_t sp =
6103             addr_size == 8 ? sp_value.value.uint64 : sp_value.value.uint32;
6104         bytes_read = DNBProcessMemoryRead(pid, sp, addr_size, bytes);
6105         if (bytes_read == addr_size) {
6106           offset = 0;
6107           mach_header_addr = data.GetPointer(&offset);
6108           if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, mh))
6109             return mach_header_addr;
6110         }
6111       }
6112     }
6113   }
6114 
6115   // Check the dyld_all_image_info structure for a list of mach header
6116   // since it is a very easy thing to check
6117   if (shlib_addr != INVALID_NUB_ADDRESS) {
6118     bytes_read =
6119         DNBProcessMemoryRead(pid, shlib_addr, sizeof(AllImageInfos), bytes);
6120     if (bytes_read > 0) {
6121       AllImageInfos aii;
6122       offset = 0;
6123       aii.version = data.Get32(&offset);
6124       aii.dylib_info_count = data.Get32(&offset);
6125       if (aii.dylib_info_count > 0) {
6126         aii.dylib_info_addr = data.GetPointer(&offset);
6127         if (aii.dylib_info_addr != 0) {
6128           const size_t image_info_byte_size = 3 * addr_size;
6129           for (uint32_t i = 0; i < aii.dylib_info_count; ++i) {
6130             bytes_read = DNBProcessMemoryRead(pid, aii.dylib_info_addr +
6131                                                        i * image_info_byte_size,
6132                                               image_info_byte_size, bytes);
6133             if (bytes_read != image_info_byte_size)
6134               break;
6135             offset = 0;
6136             mach_header_addr = data.GetPointer(&offset);
6137             if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr,
6138                                            mh))
6139               return mach_header_addr;
6140           }
6141         }
6142       }
6143     }
6144   }
6145 
6146   // We failed to find the executable's mach header from the all image
6147   // infos and by dereferencing the stack pointer. Now we fall back to
6148   // enumerating the memory regions and looking for regions that are
6149   // executable.
6150   DNBRegionInfo region_info;
6151   mach_header_addr = 0;
6152   while (DNBProcessMemoryRegionInfo(pid, mach_header_addr, &region_info)) {
6153     if (region_info.size == 0)
6154       break;
6155 
6156     if (region_info.permissions & eMemoryPermissionsExecutable) {
6157       DNBLogThreadedIf(
6158           LOG_RNB_PROC, "[0x%16.16llx - 0x%16.16llx) permissions = %c%c%c: "
6159                         "checking region for executable mach header",
6160           region_info.addr, region_info.addr + region_info.size,
6161           (region_info.permissions & eMemoryPermissionsReadable) ? 'r' : '-',
6162           (region_info.permissions & eMemoryPermissionsWritable) ? 'w' : '-',
6163           (region_info.permissions & eMemoryPermissionsExecutable) ? 'x' : '-');
6164       if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, mh))
6165         return mach_header_addr;
6166     } else {
6167       DNBLogThreadedIf(
6168           LOG_RNB_PROC,
6169           "[0x%16.16llx - 0x%16.16llx): permissions = %c%c%c: skipping region",
6170           region_info.addr, region_info.addr + region_info.size,
6171           (region_info.permissions & eMemoryPermissionsReadable) ? 'r' : '-',
6172           (region_info.permissions & eMemoryPermissionsWritable) ? 'w' : '-',
6173           (region_info.permissions & eMemoryPermissionsExecutable) ? 'x' : '-');
6174     }
6175     // Set the address to the next mapped region
6176     mach_header_addr = region_info.addr + region_info.size;
6177   }
6178   bzero(&mh, sizeof(mh));
6179   return INVALID_NUB_ADDRESS;
6180 }
6181 
6182 rnb_err_t RNBRemote::HandlePacket_qSymbol(const char *command) {
6183   const char *p = command;
6184   p += strlen("qSymbol:");
6185   const char *sep = strchr(p, ':');
6186 
6187   std::string symbol_name;
6188   std::string symbol_value_str;
6189   // Extract the symbol value if there is one
6190   if (sep > p)
6191     symbol_value_str.assign(p, sep - p);
6192   p = sep + 1;
6193 
6194   if (*p) {
6195     // We have a symbol name
6196     symbol_name = decode_hex_ascii_string(p);
6197     if (!symbol_value_str.empty()) {
6198       nub_addr_t symbol_value = decode_uint64(symbol_value_str.c_str(), 16);
6199       if (symbol_name == "dispatch_queue_offsets")
6200         m_dispatch_queue_offsets_addr = symbol_value;
6201     }
6202     ++m_qSymbol_index;
6203   } else {
6204     // No symbol name, set our symbol index to zero so we can
6205     // read any symbols that we need
6206     m_qSymbol_index = 0;
6207   }
6208 
6209   symbol_name.clear();
6210 
6211   if (m_qSymbol_index == 0) {
6212     if (m_dispatch_queue_offsets_addr == INVALID_NUB_ADDRESS)
6213       symbol_name = "dispatch_queue_offsets";
6214     else
6215       ++m_qSymbol_index;
6216   }
6217 
6218   //    // Lookup next symbol when we have one...
6219   //    if (m_qSymbol_index == 1)
6220   //    {
6221   //    }
6222 
6223   if (symbol_name.empty()) {
6224     // Done with symbol lookups
6225     return SendPacket("OK");
6226   } else {
6227     std::ostringstream reply;
6228     reply << "qSymbol:";
6229     for (size_t i = 0; i < symbol_name.size(); ++i)
6230       reply << RAWHEX8(symbol_name[i]);
6231     return SendPacket(reply.str().c_str());
6232   }
6233 }
6234 
6235 // Note that all numeric values returned by qProcessInfo are hex encoded,
6236 // including the pid and the cpu type.
6237 
6238 rnb_err_t RNBRemote::HandlePacket_qProcessInfo(const char *p) {
6239   nub_process_t pid;
6240   std::ostringstream rep;
6241 
6242   // If we haven't run the process yet, return an error.
6243   if (!m_ctx.HasValidProcessID())
6244     return SendPacket("E68");
6245 
6246   pid = m_ctx.ProcessID();
6247 
6248   rep << "pid:" << std::hex << pid << ';';
6249 
6250   int procpid_mib[4];
6251   procpid_mib[0] = CTL_KERN;
6252   procpid_mib[1] = KERN_PROC;
6253   procpid_mib[2] = KERN_PROC_PID;
6254   procpid_mib[3] = pid;
6255   struct kinfo_proc proc_kinfo;
6256   size_t proc_kinfo_size = sizeof(struct kinfo_proc);
6257 
6258   if (::sysctl(procpid_mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) {
6259     if (proc_kinfo_size > 0) {
6260       rep << "parent-pid:" << std::hex << proc_kinfo.kp_eproc.e_ppid << ';';
6261       rep << "real-uid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_ruid
6262           << ';';
6263       rep << "real-gid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_rgid
6264           << ';';
6265       rep << "effective-uid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_uid
6266           << ';';
6267       if (proc_kinfo.kp_eproc.e_ucred.cr_ngroups > 0)
6268         rep << "effective-gid:" << std::hex
6269             << proc_kinfo.kp_eproc.e_ucred.cr_groups[0] << ';';
6270     }
6271   }
6272 
6273   cpu_type_t cputype = DNBProcessGetCPUType(pid);
6274   if (cputype == 0) {
6275     DNBLog("Unable to get the process cpu_type, making a best guess.");
6276     cputype = best_guess_cpu_type();
6277   }
6278 
6279   uint32_t addr_size = 0;
6280   if (cputype != 0) {
6281     rep << "cputype:" << std::hex << cputype << ";";
6282     if (cputype & CPU_ARCH_ABI64)
6283       addr_size = 8;
6284     else
6285       addr_size = 4;
6286   }
6287 
6288   bool host_cpu_is_64bit = false;
6289   uint32_t is64bit_capable;
6290   size_t is64bit_capable_len = sizeof(is64bit_capable);
6291   if (sysctlbyname("hw.cpu64bit_capable", &is64bit_capable,
6292                    &is64bit_capable_len, NULL, 0) == 0)
6293     host_cpu_is_64bit = is64bit_capable != 0;
6294 
6295   uint32_t cpusubtype;
6296   size_t cpusubtype_len = sizeof(cpusubtype);
6297   if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &cpusubtype_len, NULL, 0) ==
6298       0) {
6299     // If a process is CPU_TYPE_X86, then ignore the cpusubtype that we detected
6300     // from the host and use CPU_SUBTYPE_I386_ALL because we don't want the
6301     // CPU_SUBTYPE_X86_ARCH1 or CPU_SUBTYPE_X86_64_H to be used as the cpu
6302     // subtype
6303     // for i386...
6304     if (host_cpu_is_64bit) {
6305       if (cputype == CPU_TYPE_X86) {
6306         cpusubtype = 3; // CPU_SUBTYPE_I386_ALL
6307       } else if (cputype == CPU_TYPE_ARM) {
6308         // We can query a process' cputype but we cannot query a process'
6309         // cpusubtype.
6310         // If the process has cputype CPU_TYPE_ARM, then it is an armv7 (32-bit
6311         // process) and we
6312         // need to override the host cpusubtype (which is in the
6313         // CPU_SUBTYPE_ARM64 subtype namespace)
6314         // with a reasonable CPU_SUBTYPE_ARMV7 subtype.
6315         cpusubtype = 12; // CPU_SUBTYPE_ARM_V7K
6316       }
6317     }
6318 #if defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
6319     // on arm64_32 devices, the machine's native cpu type is
6320     // CPU_TYPE_ARM64 and subtype is 2 indicating arm64e.
6321     // But we change the cputype to CPU_TYPE_ARM64_32 because
6322     // the user processes are all ILP32 processes today.
6323     // We also need to rewrite the cpusubtype so we vend
6324     // a valid cputype + cpusubtype combination.
6325     if (cputype == CPU_TYPE_ARM64_32 && cpusubtype == 2)
6326       cpusubtype = CPU_SUBTYPE_ARM64_32_V8;
6327 #endif
6328 
6329     rep << "cpusubtype:" << std::hex << cpusubtype << ';';
6330   }
6331 
6332   bool os_handled = false;
6333   if (addr_size > 0) {
6334     rep << "ptrsize:" << std::dec << addr_size << ';';
6335 
6336 #if (defined(__x86_64__) || defined(__i386__))
6337     // Try and get the OS type by looking at the load commands in the main
6338     // executable and looking for a LC_VERSION_MIN load command. This is the
6339     // most reliable way to determine the "ostype" value when on desktop.
6340 
6341     mach_header mh;
6342     nub_addr_t exe_mach_header_addr =
6343         GetMachHeaderForMainExecutable(pid, addr_size, mh);
6344     if (exe_mach_header_addr != INVALID_NUB_ADDRESS) {
6345       uint64_t load_command_addr =
6346           exe_mach_header_addr +
6347           ((addr_size == 8) ? sizeof(mach_header_64) : sizeof(mach_header));
6348       load_command lc;
6349       for (uint32_t i = 0; i < mh.ncmds && !os_handled; ++i) {
6350         const nub_size_t bytes_read =
6351             DNBProcessMemoryRead(pid, load_command_addr, sizeof(lc), &lc);
6352         (void)bytes_read;
6353 
6354         uint32_t major_version, minor_version, patch_version;
6355         auto *platform = DNBGetDeploymentInfo(pid, lc, load_command_addr,
6356                                               major_version, minor_version,
6357                                               patch_version);
6358         if (platform) {
6359           os_handled = true;
6360           rep << "ostype:" << platform << ";";
6361           break;
6362         }
6363         load_command_addr = load_command_addr + lc.cmdsize;
6364       }
6365     }
6366 #endif // when compiling this on x86 targets
6367   }
6368 
6369   // If we weren't able to find the OS in a LC_VERSION_MIN load command, try
6370   // to set it correctly by using the cpu type and other tricks
6371   if (!os_handled) {
6372     // The OS in the triple should be "ios" or "macosx" which doesn't match our
6373     // "Darwin" which gets returned from "kern.ostype", so we need to hardcode
6374     // this for now.
6375     if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64
6376         || cputype == CPU_TYPE_ARM64_32) {
6377 #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
6378       rep << "ostype:tvos;";
6379 #elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
6380       rep << "ostype:watchos;";
6381 #elif defined(TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1
6382       rep << "ostype:bridgeos;";
6383 #else
6384       rep << "ostype:ios;";
6385 #endif
6386     } else {
6387       bool is_ios_simulator = false;
6388       if (cputype == CPU_TYPE_X86 || cputype == CPU_TYPE_X86_64) {
6389         // Check for iOS simulator binaries by getting the process argument
6390         // and environment and checking for SIMULATOR_UDID in the environment
6391         int proc_args_mib[3] = {CTL_KERN, KERN_PROCARGS2, (int)pid};
6392 
6393         uint8_t arg_data[8192];
6394         size_t arg_data_size = sizeof(arg_data);
6395         if (::sysctl(proc_args_mib, 3, arg_data, &arg_data_size, NULL, 0) ==
6396             0) {
6397           DNBDataRef data(arg_data, arg_data_size, false);
6398           DNBDataRef::offset_t offset = 0;
6399           uint32_t argc = data.Get32(&offset);
6400           const char *cstr;
6401 
6402           cstr = data.GetCStr(&offset);
6403           if (cstr) {
6404             // Skip NULLs
6405             while (true) {
6406               const char *p = data.PeekCStr(offset);
6407               if ((p == NULL) || (*p != '\0'))
6408                 break;
6409               ++offset;
6410             }
6411             // Now skip all arguments
6412             for (uint32_t i = 0; i < argc; ++i) {
6413               data.GetCStr(&offset);
6414             }
6415 
6416             // Now iterate across all environment variables
6417             while ((cstr = data.GetCStr(&offset))) {
6418               if (strncmp(cstr, "SIMULATOR_UDID=", strlen("SIMULATOR_UDID=")) ==
6419                   0) {
6420                 is_ios_simulator = true;
6421                 break;
6422               }
6423               if (cstr[0] == '\0')
6424                 break;
6425             }
6426           }
6427         }
6428       }
6429       if (is_ios_simulator) {
6430 #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
6431         rep << "ostype:tvos;";
6432 #elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
6433         rep << "ostype:watchos;";
6434 #elif defined(TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1
6435         rep << "ostype:bridgeos;";
6436 #else
6437         rep << "ostype:ios;";
6438 #endif
6439       } else {
6440         rep << "ostype:macosx;";
6441       }
6442     }
6443   }
6444 
6445   rep << "vendor:apple;";
6446 
6447 #if defined(__LITTLE_ENDIAN__)
6448   rep << "endian:little;";
6449 #elif defined(__BIG_ENDIAN__)
6450   rep << "endian:big;";
6451 #elif defined(__PDP_ENDIAN__)
6452   rep << "endian:pdp;";
6453 #endif
6454 
6455   if (addr_size == 0) {
6456 #if (defined(__x86_64__) || defined(__i386__)) && defined(x86_THREAD_STATE)
6457     nub_thread_t thread = DNBProcessGetCurrentThreadMachPort(pid);
6458     kern_return_t kr;
6459     x86_thread_state_t gp_regs;
6460     mach_msg_type_number_t gp_count = x86_THREAD_STATE_COUNT;
6461     kr = thread_get_state(static_cast<thread_act_t>(thread), x86_THREAD_STATE,
6462                           (thread_state_t)&gp_regs, &gp_count);
6463     if (kr == KERN_SUCCESS) {
6464       if (gp_regs.tsh.flavor == x86_THREAD_STATE64)
6465         rep << "ptrsize:8;";
6466       else
6467         rep << "ptrsize:4;";
6468     }
6469 #elif defined(__arm__)
6470     rep << "ptrsize:4;";
6471 #elif (defined(__arm64__) || defined(__aarch64__)) &&                          \
6472     defined(ARM_UNIFIED_THREAD_STATE)
6473     nub_thread_t thread = DNBProcessGetCurrentThreadMachPort(pid);
6474     kern_return_t kr;
6475     arm_unified_thread_state_t gp_regs;
6476     mach_msg_type_number_t gp_count = ARM_UNIFIED_THREAD_STATE_COUNT;
6477     kr = thread_get_state(thread, ARM_UNIFIED_THREAD_STATE,
6478                           (thread_state_t)&gp_regs, &gp_count);
6479     if (kr == KERN_SUCCESS) {
6480       if (gp_regs.ash.flavor == ARM_THREAD_STATE64)
6481         rep << "ptrsize:8;";
6482       else
6483         rep << "ptrsize:4;";
6484     }
6485 #endif
6486   }
6487 
6488   return SendPacket(rep.str());
6489 }
6490 
6491 const RNBRemote::DispatchQueueOffsets *RNBRemote::GetDispatchQueueOffsets() {
6492   if (!m_dispatch_queue_offsets.IsValid() &&
6493       m_dispatch_queue_offsets_addr != INVALID_NUB_ADDRESS &&
6494       m_ctx.HasValidProcessID()) {
6495     nub_process_t pid = m_ctx.ProcessID();
6496     nub_size_t bytes_read = DNBProcessMemoryRead(
6497         pid, m_dispatch_queue_offsets_addr, sizeof(m_dispatch_queue_offsets),
6498         &m_dispatch_queue_offsets);
6499     if (bytes_read != sizeof(m_dispatch_queue_offsets))
6500       m_dispatch_queue_offsets.Clear();
6501   }
6502 
6503   if (m_dispatch_queue_offsets.IsValid())
6504     return &m_dispatch_queue_offsets;
6505   else
6506     return nullptr;
6507 }
6508 
6509 void RNBRemote::EnableCompressionNextSendPacket(compression_types type) {
6510   m_compression_mode = type;
6511   m_enable_compression_next_send_packet = true;
6512 }
6513 
6514 compression_types RNBRemote::GetCompressionType() {
6515   // The first packet we send back to the debugger after a QEnableCompression
6516   // request
6517   // should be uncompressed -- so we can indicate whether the compression was
6518   // enabled
6519   // or not via OK / Enn returns.  After that, all packets sent will be using
6520   // the
6521   // compression protocol.
6522 
6523   if (m_enable_compression_next_send_packet) {
6524     // One time, we send back "None" as our compression type
6525     m_enable_compression_next_send_packet = false;
6526     return compression_types::none;
6527   }
6528   return m_compression_mode;
6529 }
6530