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 static bool attach_failed_due_to_sip (nub_process_t pid) {
3667   bool retval = false;
3668 #if defined(__APPLE__) &&                                                      \
3669   (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101000)
3670 
3671   // csr_check(CSR_ALLOW_TASK_FOR_PID) will be nonzero if System Integrity
3672   // Protection is in effect.
3673   if (csr_check(CSR_ALLOW_TASK_FOR_PID) == 0)
3674     return false;
3675 
3676   if (rootless_allows_task_for_pid(pid) == 0)
3677     retval = true;
3678 
3679   int csops_flags = 0;
3680   int csops_ret = ::csops(pid, CS_OPS_STATUS, &csops_flags,
3681                        sizeof(csops_flags));
3682   if (csops_ret != -1 && (csops_flags & CS_RESTRICT)) {
3683     retval = true;
3684   }
3685 #endif
3686 
3687   return retval;
3688 }
3689 
3690 // my_uid and process_uid are only initialized if this function
3691 // returns true -- that there was a uid mismatch -- and those
3692 // id's may want to be used in the error message.
3693 //
3694 // NOTE: this should only be called after process_does_not_exist().
3695 // This sysctl will return uninitialized data if we ask for a pid
3696 // that doesn't exist.  The alternative would be to fetch all
3697 // processes and step through to find the one we're looking for
3698 // (as process_does_not_exist() does).
3699 static bool attach_failed_due_to_uid_mismatch (nub_process_t pid,
3700                                                uid_t &my_uid,
3701                                                uid_t &process_uid) {
3702   struct kinfo_proc kinfo;
3703   int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
3704   size_t len = sizeof(struct kinfo_proc);
3705   if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), &kinfo, &len, NULL, 0) != 0) {
3706     return false; // pid doesn't exist? can't check uid mismatch - it was fine
3707   }
3708   my_uid = geteuid();
3709   if (my_uid == 0)
3710     return false; // if we're root, attach didn't fail because of uid mismatch
3711   process_uid = kinfo.kp_eproc.e_ucred.cr_uid;
3712 
3713   // If my uid != the process' uid, then the attach probably failed because
3714   // of that.
3715   if (my_uid != process_uid)
3716     return true;
3717   else
3718     return false;
3719 }
3720 
3721 // NOTE: this should only be called after process_does_not_exist().
3722 // This sysctl will return uninitialized data if we ask for a pid
3723 // that doesn't exist.  The alternative would be to fetch all
3724 // processes and step through to find the one we're looking for
3725 // (as process_does_not_exist() does).
3726 static bool process_is_already_being_debugged (nub_process_t pid) {
3727   struct kinfo_proc kinfo;
3728   int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
3729   size_t len = sizeof(struct kinfo_proc);
3730   if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), &kinfo, &len, NULL, 0) != 0) {
3731     return false; // pid doesn't exist? well, it's not being debugged...
3732   }
3733   if (kinfo.kp_proc.p_flag & P_TRACED)
3734     return true; // is being debugged already
3735   else
3736     return false;
3737 }
3738 
3739 // Test if this current login session has a connection to the
3740 // window server (if it does not have that access, it cannot ask
3741 // for debug permission by popping up a dialog box and attach
3742 // may fail outright).
3743 static bool login_session_has_gui_access () {
3744   auditinfo_addr_t info;
3745   getaudit_addr(&info, sizeof(info));
3746   if (info.ai_flags & AU_SESSION_FLAG_HAS_GRAPHIC_ACCESS)
3747     return true;
3748   else
3749     return false;
3750 }
3751 
3752 // Checking for
3753 //
3754 //  {
3755 //    'class' : 'rule',
3756 //    'comment' : 'For use by Apple.  WARNING: administrators are advised
3757 //              not to modify this right.',
3758 //    'k-of-n' : '1',
3759 //    'rule' : [
3760 //      'is-admin',
3761 //      'is-developer',
3762 //      'authenticate-developer'
3763 //    ]
3764 //  }
3765 //
3766 // $ security authorizationdb read system.privilege.taskport.debug
3767 
3768 static bool developer_mode_enabled () {
3769 #if TARGET_OS_OSX == 0
3770   return true;
3771 #else
3772  CFDictionaryRef currentRightDict = NULL;
3773  const char *debug_right = "system.privilege.taskport.debug";
3774  // caller must free dictionary initialized by the following
3775  OSStatus status = AuthorizationRightGet(debug_right, &currentRightDict);
3776  if (status != errAuthorizationSuccess) {
3777    // could not check authorization
3778    return true;
3779  }
3780 
3781  bool devmode_enabled = true;
3782 
3783  if (!CFDictionaryContainsKey(currentRightDict, CFSTR("k-of-n"))) {
3784    devmode_enabled = false;
3785  } else {
3786    CFNumberRef item = (CFNumberRef) CFDictionaryGetValue(currentRightDict, CFSTR("k-of-n"));
3787    if (item && CFGetTypeID(item) == CFNumberGetTypeID()) {
3788       int64_t num = 0;
3789       ::CFNumberGetValue(item, kCFNumberSInt64Type, &num);
3790       if (num != 1) {
3791         devmode_enabled = false;
3792       }
3793    } else {
3794      devmode_enabled = false;
3795    }
3796  }
3797 
3798  if (!CFDictionaryContainsKey(currentRightDict, CFSTR("class"))) {
3799    devmode_enabled = false;
3800  } else {
3801    CFStringRef item = (CFStringRef) CFDictionaryGetValue(currentRightDict, CFSTR("class"));
3802    if (item && CFGetTypeID(item) == CFStringGetTypeID()) {
3803      char tmpbuf[128];
3804      if (CFStringGetCString (item, tmpbuf, sizeof(tmpbuf), CFStringGetSystemEncoding())) {
3805        tmpbuf[sizeof (tmpbuf) - 1] = '\0';
3806        if (strcmp (tmpbuf, "rule") != 0) {
3807          devmode_enabled = false;
3808        }
3809      } else {
3810        devmode_enabled = false;
3811      }
3812    } else {
3813      devmode_enabled = false;
3814    }
3815  }
3816 
3817  if (!CFDictionaryContainsKey(currentRightDict, CFSTR("rule"))) {
3818    devmode_enabled = false;
3819  } else {
3820    CFArrayRef item = (CFArrayRef) CFDictionaryGetValue(currentRightDict, CFSTR("rule"));
3821    if (item && CFGetTypeID(item) == CFArrayGetTypeID()) {
3822      int count = ::CFArrayGetCount(item);
3823       CFRange range = CFRangeMake (0, count);
3824      if (!::CFArrayContainsValue (item, range, CFSTR("is-admin")))
3825        devmode_enabled = false;
3826      if (!::CFArrayContainsValue (item, range, CFSTR("is-developer")))
3827        devmode_enabled = false;
3828      if (!::CFArrayContainsValue (item, range, CFSTR("authenticate-developer")))
3829        devmode_enabled = false;
3830    } else {
3831      devmode_enabled = false;
3832    }
3833  }
3834  ::CFRelease(currentRightDict);
3835 
3836  return devmode_enabled;
3837 #endif // TARGET_OS_OSX
3838 }
3839 
3840 /*
3841  vAttach;pid
3842 
3843  Attach to a new process with the specified process ID. pid is a hexadecimal
3844  integer
3845  identifying the process. If the stub is currently controlling a process, it is
3846  killed. The attached process is stopped.This packet is only available in
3847  extended
3848  mode (see extended mode).
3849 
3850  Reply:
3851  "ENN"                      for an error
3852  "Any Stop Reply Packet"     for success
3853  */
3854 
3855 rnb_err_t RNBRemote::HandlePacket_v(const char *p) {
3856   if (strcmp(p, "vCont;c") == 0) {
3857     // Simple continue
3858     return RNBRemote::HandlePacket_c("c");
3859   } else if (strcmp(p, "vCont;s") == 0) {
3860     // Simple step
3861     return RNBRemote::HandlePacket_s("s");
3862   } else if (strstr(p, "vCont") == p) {
3863     DNBThreadResumeActions thread_actions;
3864     char *c = const_cast<char *>(p += strlen("vCont"));
3865     char *c_end = c + strlen(c);
3866     if (*c == '?')
3867       return SendPacket("vCont;c;C;s;S");
3868 
3869     while (c < c_end && *c == ';') {
3870       ++c; // Skip the semi-colon
3871       DNBThreadResumeAction thread_action;
3872       thread_action.tid = INVALID_NUB_THREAD;
3873       thread_action.state = eStateInvalid;
3874       thread_action.signal = 0;
3875       thread_action.addr = INVALID_NUB_ADDRESS;
3876 
3877       char action = *c++;
3878 
3879       switch (action) {
3880       case 'C':
3881         errno = 0;
3882         thread_action.signal = static_cast<int>(strtoul(c, &c, 16));
3883         if (errno != 0)
3884           return HandlePacket_ILLFORMED(
3885               __FILE__, __LINE__, p, "Could not parse signal in vCont packet");
3886       // Fall through to next case...
3887         [[clang::fallthrough]];
3888       case 'c':
3889         // Continue
3890         thread_action.state = eStateRunning;
3891         break;
3892 
3893       case 'S':
3894         errno = 0;
3895         thread_action.signal = static_cast<int>(strtoul(c, &c, 16));
3896         if (errno != 0)
3897           return HandlePacket_ILLFORMED(
3898               __FILE__, __LINE__, p, "Could not parse signal in vCont packet");
3899       // Fall through to next case...
3900         [[clang::fallthrough]];
3901       case 's':
3902         // Step
3903         thread_action.state = eStateStepping;
3904         break;
3905 
3906       default:
3907         HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3908                                "Unsupported action in vCont packet");
3909         break;
3910       }
3911       if (*c == ':') {
3912         errno = 0;
3913         thread_action.tid = strtoul(++c, &c, 16);
3914         if (errno != 0)
3915           return HandlePacket_ILLFORMED(
3916               __FILE__, __LINE__, p,
3917               "Could not parse thread number in vCont packet");
3918       }
3919 
3920       thread_actions.Append(thread_action);
3921     }
3922 
3923     // If a default action for all other threads wasn't mentioned
3924     // then we should stop the threads
3925     thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
3926     DNBProcessResume(m_ctx.ProcessID(), thread_actions.GetFirst(),
3927                      thread_actions.GetSize());
3928     return rnb_success;
3929   } else if (strstr(p, "vAttach") == p) {
3930     nub_process_t attach_pid =
3931         INVALID_NUB_PROCESS; // attach_pid will be set to 0 if the attach fails
3932     nub_process_t pid_attaching_to =
3933         INVALID_NUB_PROCESS; // pid_attaching_to is the original pid specified
3934     char err_str[1024] = {'\0'};
3935     std::string attach_name;
3936 
3937     if (strstr(p, "vAttachWait;") == p) {
3938       p += strlen("vAttachWait;");
3939       if (!GetProcessNameFrom_vAttach(p, attach_name)) {
3940         return HandlePacket_ILLFORMED(
3941             __FILE__, __LINE__, p, "non-hex char in arg on 'vAttachWait' pkt");
3942       }
3943       const bool ignore_existing = true;
3944       attach_pid = DNBProcessAttachWait(
3945           attach_name.c_str(), m_ctx.LaunchFlavor(), ignore_existing, NULL,
3946           1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback);
3947 
3948     } else if (strstr(p, "vAttachOrWait;") == p) {
3949       p += strlen("vAttachOrWait;");
3950       if (!GetProcessNameFrom_vAttach(p, attach_name)) {
3951         return HandlePacket_ILLFORMED(
3952             __FILE__, __LINE__, p,
3953             "non-hex char in arg on 'vAttachOrWait' pkt");
3954       }
3955       const bool ignore_existing = false;
3956       attach_pid = DNBProcessAttachWait(
3957           attach_name.c_str(), m_ctx.LaunchFlavor(), ignore_existing, NULL,
3958           1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback);
3959     } else if (strstr(p, "vAttachName;") == p) {
3960       p += strlen("vAttachName;");
3961       if (!GetProcessNameFrom_vAttach(p, attach_name)) {
3962         return HandlePacket_ILLFORMED(
3963             __FILE__, __LINE__, p, "non-hex char in arg on 'vAttachName' pkt");
3964       }
3965 
3966       attach_pid = DNBProcessAttachByName(attach_name.c_str(), NULL, err_str,
3967                                           sizeof(err_str));
3968 
3969     } else if (strstr(p, "vAttach;") == p) {
3970       p += strlen("vAttach;");
3971       char *end = NULL;
3972       pid_attaching_to = static_cast<int>(
3973           strtoul(p, &end, 16)); // PID will be in hex, so use base 16 to decode
3974       if (p != end && *end == '\0') {
3975         // Wait at most 30 second for attach
3976         struct timespec attach_timeout_abstime;
3977         DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, 30, 0);
3978         attach_pid = DNBProcessAttach(pid_attaching_to, &attach_timeout_abstime,
3979                                       err_str, sizeof(err_str));
3980       }
3981     } else {
3982       return HandlePacket_UNIMPLEMENTED(p);
3983     }
3984 
3985     if (attach_pid != INVALID_NUB_PROCESS) {
3986       if (m_ctx.ProcessID() != attach_pid)
3987         m_ctx.SetProcessID(attach_pid);
3988       // Send a stop reply packet to indicate we successfully attached!
3989       NotifyThatProcessStopped();
3990       return rnb_success;
3991     } else {
3992       m_ctx.LaunchStatus().SetError(-1, DNBError::Generic);
3993       if (err_str[0])
3994         m_ctx.LaunchStatus().SetErrorString(err_str);
3995       else
3996         m_ctx.LaunchStatus().SetErrorString("attach failed");
3997 
3998       if (pid_attaching_to == INVALID_NUB_PROCESS && !attach_name.empty()) {
3999         pid_attaching_to = DNBProcessGetPIDByName(attach_name.c_str());
4000       }
4001 
4002       // attach_pid is INVALID_NUB_PROCESS - we did not succeed in attaching
4003       // if the original request, pid_attaching_to, is available, see if we
4004       // can figure out why we couldn't attach.  Return an informative error
4005       // string to lldb.
4006 
4007       if (pid_attaching_to != INVALID_NUB_PROCESS) {
4008         // The order of these checks is important.
4009         if (process_does_not_exist (pid_attaching_to)) {
4010           DNBLogError("Tried to attach to pid that doesn't exist");
4011           std::string return_message = "E96;";
4012           return_message += cstring_to_asciihex_string("no such process.");
4013           return SendPacket(return_message.c_str());
4014         }
4015         if (process_is_already_being_debugged (pid_attaching_to)) {
4016           DNBLogError("Tried to attach to process already being debugged");
4017           std::string return_message = "E96;";
4018           return_message += cstring_to_asciihex_string("tried to attach to "
4019                                            "process already being debugged");
4020           return SendPacket(return_message.c_str());
4021         }
4022         uid_t my_uid, process_uid;
4023         if (attach_failed_due_to_uid_mismatch (pid_attaching_to,
4024                                                my_uid, process_uid)) {
4025           std::string my_username = "uid " + std::to_string (my_uid);
4026           std::string process_username = "uid " + std::to_string (process_uid);
4027           struct passwd *pw = getpwuid (my_uid);
4028           if (pw && pw->pw_name) {
4029             my_username = pw->pw_name;
4030           }
4031           pw = getpwuid (process_uid);
4032           if (pw && pw->pw_name) {
4033             process_username = pw->pw_name;
4034           }
4035           DNBLogError("Tried to attach to process with uid mismatch");
4036           std::string return_message = "E96;";
4037           std::string msg = "tried to attach to process as user '"
4038                             + my_username + "' and process is running "
4039                             "as user '" + process_username + "'";
4040           return_message += cstring_to_asciihex_string(msg.c_str());
4041           return SendPacket(return_message.c_str());
4042         }
4043         if (!login_session_has_gui_access() && !developer_mode_enabled()) {
4044           DNBLogError("Developer mode is not enabled and this is a "
4045                       "non-interactive session");
4046           std::string return_message = "E96;";
4047           return_message += cstring_to_asciihex_string("developer mode is "
4048                                            "not enabled on this machine "
4049                                            "and this is a non-interactive "
4050                                            "debug session.");
4051           return SendPacket(return_message.c_str());
4052         }
4053         if (!login_session_has_gui_access()) {
4054           DNBLogError("This is a non-interactive session");
4055           std::string return_message = "E96;";
4056           return_message += cstring_to_asciihex_string("this is a "
4057                                            "non-interactive debug session, "
4058                                            "cannot get permission to debug "
4059                                            "processes.");
4060           return SendPacket(return_message.c_str());
4061         }
4062         if (attach_failed_due_to_sip (pid_attaching_to)) {
4063           DNBLogError("Attach failed because of SIP protection.");
4064           std::string return_message = "E96;";
4065           return_message += cstring_to_asciihex_string("cannot attach "
4066                             "to process due to System Integrity Protection");
4067           return SendPacket(return_message.c_str());
4068         }
4069       }
4070 
4071       std::string error_explainer = "attach failed";
4072       if (err_str[0] != '\0') {
4073         error_explainer += " (";
4074         error_explainer += err_str;
4075         error_explainer += ")";
4076       }
4077       std::string default_return_msg = "E96;";
4078       default_return_msg += cstring_to_asciihex_string
4079                               (error_explainer.c_str());
4080       SendPacket (default_return_msg.c_str());
4081       DNBLogError("Attach failed: \"%s\".", err_str);
4082       return rnb_err;
4083     }
4084   }
4085 
4086   // All other failures come through here
4087   return HandlePacket_UNIMPLEMENTED(p);
4088 }
4089 
4090 /* 'T XX' -- status of thread
4091  Check if the specified thread is alive.
4092  The thread number is in hex?  */
4093 
4094 rnb_err_t RNBRemote::HandlePacket_T(const char *p) {
4095   p++;
4096   if (p == NULL || *p == '\0') {
4097     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4098                                   "No thread specified in T packet");
4099   }
4100   if (!m_ctx.HasValidProcessID()) {
4101     return SendPacket("E15");
4102   }
4103   errno = 0;
4104   nub_thread_t tid = strtoul(p, NULL, 16);
4105   if (errno != 0 && tid == 0) {
4106     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4107                                   "Could not parse thread number in T packet");
4108   }
4109 
4110   nub_state_t state = DNBThreadGetState(m_ctx.ProcessID(), tid);
4111   if (state == eStateInvalid || state == eStateExited ||
4112       state == eStateCrashed) {
4113     return SendPacket("E16");
4114   }
4115 
4116   return SendPacket("OK");
4117 }
4118 
4119 rnb_err_t RNBRemote::HandlePacket_z(const char *p) {
4120   if (p == NULL || *p == '\0')
4121     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4122                                   "No thread specified in z packet");
4123 
4124   if (!m_ctx.HasValidProcessID())
4125     return SendPacket("E15");
4126 
4127   char packet_cmd = *p++;
4128   char break_type = *p++;
4129 
4130   if (*p++ != ',')
4131     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4132                                   "Comma separator missing in z packet");
4133 
4134   char *c = NULL;
4135   nub_process_t pid = m_ctx.ProcessID();
4136   errno = 0;
4137   nub_addr_t addr = strtoull(p, &c, 16);
4138   if (errno != 0 && addr == 0)
4139     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4140                                   "Invalid address in z packet");
4141   p = c;
4142   if (*p++ != ',')
4143     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4144                                   "Comma separator missing in z packet");
4145 
4146   errno = 0;
4147   auto byte_size = strtoul(p, &c, 16);
4148   if (errno != 0 && byte_size == 0)
4149     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4150                                   "Invalid length in z packet");
4151 
4152   if (packet_cmd == 'Z') {
4153     // set
4154     switch (break_type) {
4155     case '0': // set software breakpoint
4156     case '1': // set hardware breakpoint
4157     {
4158       // gdb can send multiple Z packets for the same address and
4159       // these calls must be ref counted.
4160       bool hardware = (break_type == '1');
4161 
4162       if (DNBBreakpointSet(pid, addr, byte_size, hardware)) {
4163         // We successfully created a breakpoint, now lets full out
4164         // a ref count structure with the breakID and add it to our
4165         // map.
4166         return SendPacket("OK");
4167       } else {
4168         // We failed to set the software breakpoint
4169         return SendPacket("E09");
4170       }
4171     } break;
4172 
4173     case '2': // set write watchpoint
4174     case '3': // set read watchpoint
4175     case '4': // set access watchpoint
4176     {
4177       bool hardware = true;
4178       uint32_t watch_flags = 0;
4179       if (break_type == '2')
4180         watch_flags = WATCH_TYPE_WRITE;
4181       else if (break_type == '3')
4182         watch_flags = WATCH_TYPE_READ;
4183       else
4184         watch_flags = WATCH_TYPE_READ | WATCH_TYPE_WRITE;
4185 
4186       if (DNBWatchpointSet(pid, addr, byte_size, watch_flags, hardware)) {
4187         return SendPacket("OK");
4188       } else {
4189         // We failed to set the watchpoint
4190         return SendPacket("E09");
4191       }
4192     } break;
4193 
4194     default:
4195       break;
4196     }
4197   } else if (packet_cmd == 'z') {
4198     // remove
4199     switch (break_type) {
4200     case '0': // remove software breakpoint
4201     case '1': // remove hardware breakpoint
4202       if (DNBBreakpointClear(pid, addr)) {
4203         return SendPacket("OK");
4204       } else {
4205         return SendPacket("E08");
4206       }
4207       break;
4208 
4209     case '2': // remove write watchpoint
4210     case '3': // remove read watchpoint
4211     case '4': // remove access watchpoint
4212       if (DNBWatchpointClear(pid, addr)) {
4213         return SendPacket("OK");
4214       } else {
4215         return SendPacket("E08");
4216       }
4217       break;
4218 
4219     default:
4220       break;
4221     }
4222   }
4223   return HandlePacket_UNIMPLEMENTED(p);
4224 }
4225 
4226 // Extract the thread number from the thread suffix that might be appended to
4227 // thread specific packets. This will only be enabled if
4228 // m_thread_suffix_supported
4229 // is true.
4230 nub_thread_t RNBRemote::ExtractThreadIDFromThreadSuffix(const char *p) {
4231   if (m_thread_suffix_supported) {
4232     nub_thread_t tid = INVALID_NUB_THREAD;
4233     if (p) {
4234       const char *tid_cstr = strstr(p, "thread:");
4235       if (tid_cstr) {
4236         tid_cstr += strlen("thread:");
4237         tid = strtoul(tid_cstr, NULL, 16);
4238       }
4239     }
4240     return tid;
4241   }
4242   return GetCurrentThread();
4243 }
4244 
4245 /* 'p XX'
4246  print the contents of register X */
4247 
4248 rnb_err_t RNBRemote::HandlePacket_p(const char *p) {
4249   if (g_num_reg_entries == 0)
4250     InitializeRegisters();
4251 
4252   if (p == NULL || *p == '\0') {
4253     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4254                                   "No thread specified in p packet");
4255   }
4256   if (!m_ctx.HasValidProcessID()) {
4257     return SendPacket("E15");
4258   }
4259   nub_process_t pid = m_ctx.ProcessID();
4260   errno = 0;
4261   char *tid_cstr = NULL;
4262   uint32_t reg = static_cast<uint32_t>(strtoul(p + 1, &tid_cstr, 16));
4263   if (errno != 0 && reg == 0) {
4264     return HandlePacket_ILLFORMED(
4265         __FILE__, __LINE__, p, "Could not parse register number in p packet");
4266   }
4267 
4268   nub_thread_t tid = ExtractThreadIDFromThreadSuffix(tid_cstr);
4269   if (tid == INVALID_NUB_THREAD)
4270     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4271                                   "No thread specified in p packet");
4272 
4273   const register_map_entry_t *reg_entry;
4274 
4275   if (reg < g_num_reg_entries)
4276     reg_entry = &g_reg_entries[reg];
4277   else
4278     reg_entry = NULL;
4279 
4280   std::ostringstream ostrm;
4281   if (reg_entry == NULL) {
4282     DNBLogError(
4283         "RNBRemote::HandlePacket_p(%s): unknown register number %u requested\n",
4284         p, reg);
4285     ostrm << "00000000";
4286   } else if (reg_entry->nub_info.reg == (uint32_t)-1) {
4287     if (reg_entry->nub_info.size > 0) {
4288       std::basic_string<uint8_t> zeros(reg_entry->nub_info.size, '\0');
4289       append_hex_value(ostrm, zeros.data(), zeros.size(), false);
4290     }
4291   } else {
4292     register_value_in_hex_fixed_width(ostrm, pid, tid, reg_entry, NULL);
4293   }
4294   return SendPacket(ostrm.str());
4295 }
4296 
4297 /* 'Pnn=rrrrr'
4298  Set register number n to value r.
4299  n and r are hex strings.  */
4300 
4301 rnb_err_t RNBRemote::HandlePacket_P(const char *p) {
4302   if (g_num_reg_entries == 0)
4303     InitializeRegisters();
4304 
4305   if (p == NULL || *p == '\0') {
4306     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, "Empty P packet");
4307   }
4308   if (!m_ctx.HasValidProcessID()) {
4309     return SendPacket("E28");
4310   }
4311 
4312   nub_process_t pid = m_ctx.ProcessID();
4313 
4314   StdStringExtractor packet(p);
4315 
4316   const char cmd_char = packet.GetChar();
4317   // Register ID is always in big endian
4318   const uint32_t reg = packet.GetHexMaxU32(false, UINT32_MAX);
4319   const char equal_char = packet.GetChar();
4320 
4321   if (cmd_char != 'P')
4322     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4323                                   "Improperly formed P packet");
4324 
4325   if (reg == UINT32_MAX)
4326     return SendPacket("E29");
4327 
4328   if (equal_char != '=')
4329     return SendPacket("E30");
4330 
4331   const register_map_entry_t *reg_entry;
4332 
4333   if (reg >= g_num_reg_entries)
4334     return SendPacket("E47");
4335 
4336   reg_entry = &g_reg_entries[reg];
4337 
4338   if (reg_entry->nub_info.set == (uint32_t)-1 &&
4339       reg_entry->nub_info.reg == (uint32_t)-1) {
4340     DNBLogError(
4341         "RNBRemote::HandlePacket_P(%s): unknown register number %u requested\n",
4342         p, reg);
4343     return SendPacket("E48");
4344   }
4345 
4346   DNBRegisterValue reg_value;
4347   reg_value.info = reg_entry->nub_info;
4348   packet.GetHexBytes(reg_value.value.v_sint8, reg_entry->nub_info.size, 0xcc);
4349 
4350   nub_thread_t tid = ExtractThreadIDFromThreadSuffix(p);
4351   if (tid == INVALID_NUB_THREAD)
4352     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4353                                   "No thread specified in p packet");
4354 
4355   if (!DNBThreadSetRegisterValueByID(pid, tid, reg_entry->nub_info.set,
4356                                      reg_entry->nub_info.reg, &reg_value)) {
4357     return SendPacket("E32");
4358   }
4359   return SendPacket("OK");
4360 }
4361 
4362 /* 'c [addr]'
4363  Continue, optionally from a specified address. */
4364 
4365 rnb_err_t RNBRemote::HandlePacket_c(const char *p) {
4366   const nub_process_t pid = m_ctx.ProcessID();
4367 
4368   if (pid == INVALID_NUB_PROCESS)
4369     return SendPacket("E23");
4370 
4371   DNBThreadResumeAction action = {INVALID_NUB_THREAD, eStateRunning, 0,
4372                                   INVALID_NUB_ADDRESS};
4373 
4374   if (*(p + 1) != '\0') {
4375     action.tid = GetContinueThread();
4376     errno = 0;
4377     action.addr = strtoull(p + 1, NULL, 16);
4378     if (errno != 0 && action.addr == 0)
4379       return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4380                                     "Could not parse address in c packet");
4381   }
4382 
4383   DNBThreadResumeActions thread_actions;
4384   thread_actions.Append(action);
4385   thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, 0);
4386   if (!DNBProcessResume(pid, thread_actions.GetFirst(),
4387                         thread_actions.GetSize()))
4388     return SendPacket("E25");
4389   // Don't send an "OK" packet; response is the stopped/exited message.
4390   return rnb_success;
4391 }
4392 
4393 rnb_err_t RNBRemote::HandlePacket_MemoryRegionInfo(const char *p) {
4394   /* This packet will find memory attributes (e.g. readable, writable,
4395      executable, stack, jitted code)
4396      for the memory region containing a given address and return that
4397      information.
4398 
4399      Users of this packet must be prepared for three results:
4400 
4401          Region information is returned
4402          Region information is unavailable for this address because the address
4403      is in unmapped memory
4404          Region lookup cannot be performed on this platform or process is not
4405      yet launched
4406          This packet isn't implemented
4407 
4408      Examples of use:
4409         qMemoryRegionInfo:3a55140
4410         start:3a50000,size:100000,permissions:rwx
4411 
4412         qMemoryRegionInfo:0
4413         error:address in unmapped region
4414 
4415         qMemoryRegionInfo:3a551140   (on a different platform)
4416         error:region lookup cannot be performed
4417 
4418         qMemoryRegionInfo
4419         OK                   // this packet is implemented by the remote nub
4420   */
4421 
4422   p += sizeof("qMemoryRegionInfo") - 1;
4423   if (*p == '\0')
4424     return SendPacket("OK");
4425   if (*p++ != ':')
4426     return SendPacket("E67");
4427   if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X'))
4428     p += 2;
4429 
4430   errno = 0;
4431   uint64_t address = strtoul(p, NULL, 16);
4432   if (errno != 0 && address == 0) {
4433     return HandlePacket_ILLFORMED(
4434         __FILE__, __LINE__, p, "Invalid address in qMemoryRegionInfo packet");
4435   }
4436 
4437   DNBRegionInfo region_info = {0, 0, 0};
4438   DNBProcessMemoryRegionInfo(m_ctx.ProcessID(), address, &region_info);
4439   std::ostringstream ostrm;
4440 
4441   // start:3a50000,size:100000,permissions:rwx
4442   ostrm << "start:" << std::hex << region_info.addr << ';';
4443 
4444   if (region_info.size > 0)
4445     ostrm << "size:" << std::hex << region_info.size << ';';
4446 
4447   if (region_info.permissions) {
4448     ostrm << "permissions:";
4449 
4450     if (region_info.permissions & eMemoryPermissionsReadable)
4451       ostrm << 'r';
4452     if (region_info.permissions & eMemoryPermissionsWritable)
4453       ostrm << 'w';
4454     if (region_info.permissions & eMemoryPermissionsExecutable)
4455       ostrm << 'x';
4456     ostrm << ';';
4457   }
4458   return SendPacket(ostrm.str());
4459 }
4460 
4461 // qGetProfileData;scan_type:0xYYYYYYY
4462 rnb_err_t RNBRemote::HandlePacket_GetProfileData(const char *p) {
4463   nub_process_t pid = m_ctx.ProcessID();
4464   if (pid == INVALID_NUB_PROCESS)
4465     return SendPacket("OK");
4466 
4467   StdStringExtractor packet(p += sizeof("qGetProfileData"));
4468   DNBProfileDataScanType scan_type = eProfileAll;
4469   std::string name;
4470   std::string value;
4471   while (packet.GetNameColonValue(name, value)) {
4472     if (name == "scan_type") {
4473       std::istringstream iss(value);
4474       uint32_t int_value = 0;
4475       if (iss >> std::hex >> int_value) {
4476         scan_type = (DNBProfileDataScanType)int_value;
4477       }
4478     }
4479   }
4480 
4481   std::string data = DNBProcessGetProfileData(pid, scan_type);
4482   if (!data.empty()) {
4483     return SendPacket(data.c_str());
4484   } else {
4485     return SendPacket("OK");
4486   }
4487 }
4488 
4489 // QSetEnableAsyncProfiling;enable:[0|1]:interval_usec:XXXXXX;scan_type:0xYYYYYYY
4490 rnb_err_t RNBRemote::HandlePacket_SetEnableAsyncProfiling(const char *p) {
4491   nub_process_t pid = m_ctx.ProcessID();
4492   if (pid == INVALID_NUB_PROCESS)
4493     return SendPacket("OK");
4494 
4495   StdStringExtractor packet(p += sizeof("QSetEnableAsyncProfiling"));
4496   bool enable = false;
4497   uint64_t interval_usec = 0;
4498   DNBProfileDataScanType scan_type = eProfileAll;
4499   std::string name;
4500   std::string value;
4501   while (packet.GetNameColonValue(name, value)) {
4502     if (name == "enable") {
4503       enable = strtoul(value.c_str(), NULL, 10) > 0;
4504     } else if (name == "interval_usec") {
4505       interval_usec = strtoul(value.c_str(), NULL, 10);
4506     } else if (name == "scan_type") {
4507       std::istringstream iss(value);
4508       uint32_t int_value = 0;
4509       if (iss >> std::hex >> int_value) {
4510         scan_type = (DNBProfileDataScanType)int_value;
4511       }
4512     }
4513   }
4514 
4515   if (interval_usec == 0) {
4516     enable = false;
4517   }
4518 
4519   DNBProcessSetEnableAsyncProfiling(pid, enable, interval_usec, scan_type);
4520   return SendPacket("OK");
4521 }
4522 
4523 // QEnableCompression:type:<COMPRESSION-TYPE>;minsize:<MINIMUM PACKET SIZE TO
4524 // COMPRESS>;
4525 //
4526 // type: must be a type previously reported by the qXfer:features:
4527 // SupportedCompressions list
4528 //
4529 // minsize: is optional; by default the qXfer:features:
4530 // DefaultCompressionMinSize value is used
4531 // debugserver may have a better idea of what a good minimum packet size to
4532 // compress is than lldb.
4533 
4534 rnb_err_t RNBRemote::HandlePacket_QEnableCompression(const char *p) {
4535   p += sizeof("QEnableCompression:") - 1;
4536 
4537   size_t new_compression_minsize = m_compression_minsize;
4538   const char *new_compression_minsize_str = strstr(p, "minsize:");
4539   if (new_compression_minsize_str) {
4540     new_compression_minsize_str += strlen("minsize:");
4541     errno = 0;
4542     new_compression_minsize = strtoul(new_compression_minsize_str, NULL, 10);
4543     if (errno != 0 || new_compression_minsize == ULONG_MAX) {
4544       new_compression_minsize = m_compression_minsize;
4545     }
4546   }
4547 
4548   if (strstr(p, "type:zlib-deflate;") != nullptr) {
4549     EnableCompressionNextSendPacket(compression_types::zlib_deflate);
4550     m_compression_minsize = new_compression_minsize;
4551     return SendPacket("OK");
4552   } else if (strstr(p, "type:lz4;") != nullptr) {
4553     EnableCompressionNextSendPacket(compression_types::lz4);
4554     m_compression_minsize = new_compression_minsize;
4555     return SendPacket("OK");
4556   } else if (strstr(p, "type:lzma;") != nullptr) {
4557     EnableCompressionNextSendPacket(compression_types::lzma);
4558     m_compression_minsize = new_compression_minsize;
4559     return SendPacket("OK");
4560   } else if (strstr(p, "type:lzfse;") != nullptr) {
4561     EnableCompressionNextSendPacket(compression_types::lzfse);
4562     m_compression_minsize = new_compression_minsize;
4563     return SendPacket("OK");
4564   }
4565 
4566   return SendPacket("E88");
4567 }
4568 
4569 rnb_err_t RNBRemote::HandlePacket_qSpeedTest(const char *p) {
4570   p += strlen("qSpeedTest:response_size:");
4571   char *end = NULL;
4572   errno = 0;
4573   uint64_t response_size = ::strtoul(p, &end, 16);
4574   if (errno != 0)
4575     return HandlePacket_ILLFORMED(
4576         __FILE__, __LINE__, p,
4577         "Didn't find response_size value at right offset");
4578   else if (*end == ';') {
4579     static char g_data[4 * 1024 * 1024 + 16] = "data:";
4580     memset(g_data + 5, 'a', response_size);
4581     g_data[response_size + 5] = '\0';
4582     return SendPacket(g_data);
4583   } else {
4584     return SendPacket("E79");
4585   }
4586 }
4587 
4588 rnb_err_t RNBRemote::HandlePacket_WatchpointSupportInfo(const char *p) {
4589   /* This packet simply returns the number of supported hardware watchpoints.
4590 
4591      Examples of use:
4592         qWatchpointSupportInfo:
4593         num:4
4594 
4595         qWatchpointSupportInfo
4596         OK                   // this packet is implemented by the remote nub
4597   */
4598 
4599   p += sizeof("qWatchpointSupportInfo") - 1;
4600   if (*p == '\0')
4601     return SendPacket("OK");
4602   if (*p++ != ':')
4603     return SendPacket("E67");
4604 
4605   errno = 0;
4606   uint32_t num = DNBWatchpointGetNumSupportedHWP(m_ctx.ProcessID());
4607   std::ostringstream ostrm;
4608 
4609   // size:4
4610   ostrm << "num:" << std::dec << num << ';';
4611   return SendPacket(ostrm.str());
4612 }
4613 
4614 /* 'C sig [;addr]'
4615  Resume with signal sig, optionally at address addr.  */
4616 
4617 rnb_err_t RNBRemote::HandlePacket_C(const char *p) {
4618   const nub_process_t pid = m_ctx.ProcessID();
4619 
4620   if (pid == INVALID_NUB_PROCESS)
4621     return SendPacket("E36");
4622 
4623   DNBThreadResumeAction action = {INVALID_NUB_THREAD, eStateRunning, 0,
4624                                   INVALID_NUB_ADDRESS};
4625   int process_signo = -1;
4626   if (*(p + 1) != '\0') {
4627     action.tid = GetContinueThread();
4628     char *end = NULL;
4629     errno = 0;
4630     process_signo = static_cast<int>(strtoul(p + 1, &end, 16));
4631     if (errno != 0)
4632       return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4633                                     "Could not parse signal in C packet");
4634     else if (*end == ';') {
4635       errno = 0;
4636       action.addr = strtoull(end + 1, NULL, 16);
4637       if (errno != 0 && action.addr == 0)
4638         return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4639                                       "Could not parse address in C packet");
4640     }
4641   }
4642 
4643   DNBThreadResumeActions thread_actions;
4644   thread_actions.Append(action);
4645   thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, action.signal);
4646   if (!DNBProcessSignal(pid, process_signo))
4647     return SendPacket("E52");
4648   if (!DNBProcessResume(pid, thread_actions.GetFirst(),
4649                         thread_actions.GetSize()))
4650     return SendPacket("E38");
4651   /* Don't send an "OK" packet; response is the stopped/exited message.  */
4652   return rnb_success;
4653 }
4654 
4655 // 'D' packet
4656 // Detach from gdb.
4657 rnb_err_t RNBRemote::HandlePacket_D(const char *p) {
4658   if (m_ctx.HasValidProcessID()) {
4659     if (DNBProcessDetach(m_ctx.ProcessID()))
4660       SendPacket("OK");
4661     else
4662       SendPacket("E");
4663   } else {
4664     SendPacket("E");
4665   }
4666   return rnb_success;
4667 }
4668 
4669 /* 'k'
4670  Kill the inferior process.  */
4671 
4672 rnb_err_t RNBRemote::HandlePacket_k(const char *p) {
4673   DNBLog("Got a 'k' packet, killing the inferior process.");
4674   // No response to should be sent to the kill packet
4675   if (m_ctx.HasValidProcessID())
4676     DNBProcessKill(m_ctx.ProcessID());
4677   SendPacket("X09");
4678   return rnb_success;
4679 }
4680 
4681 rnb_err_t RNBRemote::HandlePacket_stop_process(const char *p) {
4682 //#define TEST_EXIT_ON_INTERRUPT // This should only be uncommented to test
4683 //exiting on interrupt
4684 #if defined(TEST_EXIT_ON_INTERRUPT)
4685   rnb_err_t err = HandlePacket_k(p);
4686   m_comm.Disconnect(true);
4687   return err;
4688 #else
4689   if (!DNBProcessInterrupt(m_ctx.ProcessID())) {
4690     // If we failed to interrupt the process, then send a stop
4691     // reply packet as the process was probably already stopped
4692     DNBLogThreaded("RNBRemote::HandlePacket_stop_process() sending extra stop "
4693                    "reply because DNBProcessInterrupt returned false");
4694     HandlePacket_last_signal(NULL);
4695   }
4696   return rnb_success;
4697 #endif
4698 }
4699 
4700 /* 's'
4701  Step the inferior process.  */
4702 
4703 rnb_err_t RNBRemote::HandlePacket_s(const char *p) {
4704   const nub_process_t pid = m_ctx.ProcessID();
4705   if (pid == INVALID_NUB_PROCESS)
4706     return SendPacket("E32");
4707 
4708   // Hardware supported stepping not supported on arm
4709   nub_thread_t tid = GetContinueThread();
4710   if (tid == 0 || tid == (nub_thread_t)-1)
4711     tid = GetCurrentThread();
4712 
4713   if (tid == INVALID_NUB_THREAD)
4714     return SendPacket("E33");
4715 
4716   DNBThreadResumeActions thread_actions;
4717   thread_actions.AppendAction(tid, eStateStepping);
4718 
4719   // Make all other threads stop when we are stepping
4720   thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
4721   if (!DNBProcessResume(pid, thread_actions.GetFirst(),
4722                         thread_actions.GetSize()))
4723     return SendPacket("E49");
4724   // Don't send an "OK" packet; response is the stopped/exited message.
4725   return rnb_success;
4726 }
4727 
4728 /* 'S sig [;addr]'
4729  Step with signal sig, optionally at address addr.  */
4730 
4731 rnb_err_t RNBRemote::HandlePacket_S(const char *p) {
4732   const nub_process_t pid = m_ctx.ProcessID();
4733   if (pid == INVALID_NUB_PROCESS)
4734     return SendPacket("E36");
4735 
4736   DNBThreadResumeAction action = {INVALID_NUB_THREAD, eStateStepping, 0,
4737                                   INVALID_NUB_ADDRESS};
4738 
4739   if (*(p + 1) != '\0') {
4740     char *end = NULL;
4741     errno = 0;
4742     action.signal = static_cast<int>(strtoul(p + 1, &end, 16));
4743     if (errno != 0)
4744       return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4745                                     "Could not parse signal in S packet");
4746     else if (*end == ';') {
4747       errno = 0;
4748       action.addr = strtoull(end + 1, NULL, 16);
4749       if (errno != 0 && action.addr == 0) {
4750         return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4751                                       "Could not parse address in S packet");
4752       }
4753     }
4754   }
4755 
4756   action.tid = GetContinueThread();
4757   if (action.tid == 0 || action.tid == (nub_thread_t)-1)
4758     return SendPacket("E40");
4759 
4760   nub_state_t tstate = DNBThreadGetState(pid, action.tid);
4761   if (tstate == eStateInvalid || tstate == eStateExited)
4762     return SendPacket("E37");
4763 
4764   DNBThreadResumeActions thread_actions;
4765   thread_actions.Append(action);
4766 
4767   // Make all other threads stop when we are stepping
4768   thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
4769   if (!DNBProcessResume(pid, thread_actions.GetFirst(),
4770                         thread_actions.GetSize()))
4771     return SendPacket("E39");
4772 
4773   // Don't send an "OK" packet; response is the stopped/exited message.
4774   return rnb_success;
4775 }
4776 
4777 static const char *GetArchName(const uint32_t cputype,
4778                                const uint32_t cpusubtype) {
4779   switch (cputype) {
4780   case CPU_TYPE_ARM:
4781     switch (cpusubtype) {
4782     case 5:
4783       return "armv4";
4784     case 6:
4785       return "armv6";
4786     case 7:
4787       return "armv5t";
4788     case 8:
4789       return "xscale";
4790     case 9:
4791       return "armv7";
4792     case 10:
4793       return "armv7f";
4794     case 11:
4795       return "armv7s";
4796     case 12:
4797       return "armv7k";
4798     case 14:
4799       return "armv6m";
4800     case 15:
4801       return "armv7m";
4802     case 16:
4803       return "armv7em";
4804     default:
4805       return "arm";
4806     }
4807     break;
4808   case CPU_TYPE_ARM64:
4809     return "arm64";
4810   case CPU_TYPE_ARM64_32:
4811     return "arm64_32";
4812   case CPU_TYPE_I386:
4813     return "i386";
4814   case CPU_TYPE_X86_64:
4815     switch (cpusubtype) {
4816     default:
4817       return "x86_64";
4818     case 8:
4819       return "x86_64h";
4820     }
4821     break;
4822   }
4823   return NULL;
4824 }
4825 
4826 static bool GetHostCPUType(uint32_t &cputype, uint32_t &cpusubtype,
4827                            uint32_t &is_64_bit_capable, bool &promoted_to_64) {
4828   static uint32_t g_host_cputype = 0;
4829   static uint32_t g_host_cpusubtype = 0;
4830   static uint32_t g_is_64_bit_capable = 0;
4831   static bool g_promoted_to_64 = false;
4832 
4833   if (g_host_cputype == 0) {
4834     g_promoted_to_64 = false;
4835     size_t len = sizeof(uint32_t);
4836     if (::sysctlbyname("hw.cputype", &g_host_cputype, &len, NULL, 0) == 0) {
4837       len = sizeof(uint32_t);
4838       if (::sysctlbyname("hw.cpu64bit_capable", &g_is_64_bit_capable, &len,
4839                          NULL, 0) == 0) {
4840         if (g_is_64_bit_capable && ((g_host_cputype & CPU_ARCH_ABI64) == 0)) {
4841           g_promoted_to_64 = true;
4842           g_host_cputype |= CPU_ARCH_ABI64;
4843         }
4844       }
4845 #if defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
4846       if (g_host_cputype == CPU_TYPE_ARM64 && sizeof (void*) == 4)
4847         g_host_cputype = CPU_TYPE_ARM64_32;
4848 #endif
4849     }
4850 
4851     len = sizeof(uint32_t);
4852     if (::sysctlbyname("hw.cpusubtype", &g_host_cpusubtype, &len, NULL, 0) ==
4853         0) {
4854       if (g_promoted_to_64 && g_host_cputype == CPU_TYPE_X86_64 &&
4855           g_host_cpusubtype == CPU_SUBTYPE_486)
4856         g_host_cpusubtype = CPU_SUBTYPE_X86_64_ALL;
4857     }
4858 #if defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
4859     // on arm64_32 devices, the machine's native cpu type is
4860     // CPU_TYPE_ARM64 and subtype is 2 indicating arm64e.
4861     // But we change the cputype to CPU_TYPE_ARM64_32 because
4862     // the user processes are all ILP32 processes today.
4863     // We also need to rewrite the cpusubtype so we vend
4864     // a valid cputype + cpusubtype combination.
4865     if (g_host_cputype == CPU_TYPE_ARM64_32)
4866       g_host_cpusubtype = CPU_SUBTYPE_ARM64_32_V8;
4867 #endif
4868   }
4869 
4870   cputype = g_host_cputype;
4871   cpusubtype = g_host_cpusubtype;
4872   is_64_bit_capable = g_is_64_bit_capable;
4873   promoted_to_64 = g_promoted_to_64;
4874   return g_host_cputype != 0;
4875 }
4876 
4877 static bool GetAddressingBits(uint32_t &addressing_bits) {
4878   static uint32_t g_addressing_bits = 0;
4879   static bool g_tried_addressing_bits_syscall = false;
4880   if (g_tried_addressing_bits_syscall == false) {
4881     size_t len = sizeof (uint32_t);
4882     if (::sysctlbyname("machdep.virtual_address_size",
4883           &g_addressing_bits, &len, NULL, 0) != 0) {
4884       g_addressing_bits = 0;
4885     }
4886   }
4887   g_tried_addressing_bits_syscall = true;
4888   addressing_bits = g_addressing_bits;
4889   if (addressing_bits > 0)
4890     return true;
4891   else
4892     return false;
4893 }
4894 
4895 rnb_err_t RNBRemote::HandlePacket_qHostInfo(const char *p) {
4896   std::ostringstream strm;
4897 
4898   uint32_t cputype = 0;
4899   uint32_t cpusubtype = 0;
4900   uint32_t is_64_bit_capable = 0;
4901   bool promoted_to_64 = false;
4902   if (GetHostCPUType(cputype, cpusubtype, is_64_bit_capable, promoted_to_64)) {
4903     strm << "cputype:" << std::dec << cputype << ';';
4904     strm << "cpusubtype:" << std::dec << cpusubtype << ';';
4905   }
4906 
4907   uint32_t addressing_bits = 0;
4908   if (GetAddressingBits(addressing_bits)) {
4909     strm << "addressing_bits:" << std::dec << addressing_bits << ';';
4910   }
4911 
4912   // The OS in the triple should be "ios" or "macosx" which doesn't match our
4913   // "Darwin" which gets returned from "kern.ostype", so we need to hardcode
4914   // this for now.
4915   if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64
4916       || cputype == CPU_TYPE_ARM64_32) {
4917 #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
4918     strm << "ostype:tvos;";
4919 #elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
4920     strm << "ostype:watchos;";
4921 #elif defined(TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1
4922     strm << "ostype:bridgeos;";
4923 #else
4924     strm << "ostype:ios;";
4925 #endif
4926 
4927     // On armv7 we use "synchronous" watchpoints which means the exception is
4928     // delivered before the instruction executes.
4929     strm << "watchpoint_exceptions_received:before;";
4930   } else {
4931     strm << "ostype:macosx;";
4932     strm << "watchpoint_exceptions_received:after;";
4933   }
4934   //    char ostype[64];
4935   //    len = sizeof(ostype);
4936   //    if (::sysctlbyname("kern.ostype", &ostype, &len, NULL, 0) == 0)
4937   //    {
4938   //        len = strlen(ostype);
4939   //        std::transform (ostype, ostype + len, ostype, tolower);
4940   //        strm << "ostype:" << std::dec << ostype << ';';
4941   //    }
4942 
4943   strm << "vendor:apple;";
4944 
4945   uint64_t major, minor, patch;
4946   if (DNBGetOSVersionNumbers(&major, &minor, &patch)) {
4947     strm << "os_version:" << major << "." << minor;
4948     if (patch != UINT64_MAX)
4949       strm << "." << patch;
4950     strm << ";";
4951   }
4952 
4953   std::string maccatalyst_version = DNBGetMacCatalystVersionString();
4954   if (!maccatalyst_version.empty() &&
4955       std::all_of(maccatalyst_version.begin(), maccatalyst_version.end(),
4956                   [](char c) { return (c >= '0' && c <= '9') || c == '.'; }))
4957     strm << "maccatalyst_version:" << maccatalyst_version << ";";
4958 
4959 #if defined(__LITTLE_ENDIAN__)
4960   strm << "endian:little;";
4961 #elif defined(__BIG_ENDIAN__)
4962   strm << "endian:big;";
4963 #elif defined(__PDP_ENDIAN__)
4964   strm << "endian:pdp;";
4965 #endif
4966 
4967   if (promoted_to_64)
4968     strm << "ptrsize:8;";
4969   else
4970     strm << "ptrsize:" << std::dec << sizeof(void *) << ';';
4971 
4972 #if defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
4973   strm << "default_packet_timeout:10;";
4974 #endif
4975 
4976   return SendPacket(strm.str());
4977 }
4978 
4979 void XMLElementStart(std::ostringstream &s, uint32_t indent, const char *name,
4980                      bool has_attributes) {
4981   if (indent)
4982     s << INDENT_WITH_SPACES(indent);
4983   s << '<' << name;
4984   if (!has_attributes)
4985     s << '>' << std::endl;
4986 }
4987 
4988 void XMLElementStartEndAttributes(std::ostringstream &s, bool empty) {
4989   if (empty)
4990     s << '/';
4991   s << '>' << std::endl;
4992 }
4993 
4994 void XMLElementEnd(std::ostringstream &s, uint32_t indent, const char *name) {
4995   if (indent)
4996     s << INDENT_WITH_SPACES(indent);
4997   s << '<' << '/' << name << '>' << std::endl;
4998 }
4999 
5000 void XMLElementWithStringValue(std::ostringstream &s, uint32_t indent,
5001                                const char *name, const char *value,
5002                                bool close = true) {
5003   if (value) {
5004     if (indent)
5005       s << INDENT_WITH_SPACES(indent);
5006     s << '<' << name << '>' << value;
5007     if (close)
5008       XMLElementEnd(s, 0, name);
5009   }
5010 }
5011 
5012 void XMLElementWithUnsignedValue(std::ostringstream &s, uint32_t indent,
5013                                  const char *name, uint64_t value,
5014                                  bool close = true) {
5015   if (indent)
5016     s << INDENT_WITH_SPACES(indent);
5017 
5018   s << '<' << name << '>' << DECIMAL << value;
5019   if (close)
5020     XMLElementEnd(s, 0, name);
5021 }
5022 
5023 void XMLAttributeString(std::ostringstream &s, const char *name,
5024                         const char *value, const char *default_value = NULL) {
5025   if (value) {
5026     if (default_value && strcmp(value, default_value) == 0)
5027       return; // No need to emit the attribute because it matches the default
5028               // value
5029     s << ' ' << name << "=\"" << value << "\"";
5030   }
5031 }
5032 
5033 void XMLAttributeUnsignedDecimal(std::ostringstream &s, const char *name,
5034                                  uint64_t value) {
5035   s << ' ' << name << "=\"" << DECIMAL << value << "\"";
5036 }
5037 
5038 void GenerateTargetXMLRegister(std::ostringstream &s, const uint32_t reg_num,
5039                                nub_size_t num_reg_sets,
5040                                const DNBRegisterSetInfo *reg_set_info,
5041                                const register_map_entry_t &reg) {
5042   const char *default_lldb_encoding = "uint";
5043   const char *lldb_encoding = default_lldb_encoding;
5044   const char *gdb_group = "general";
5045   const char *default_gdb_type = "int";
5046   const char *gdb_type = default_gdb_type;
5047   const char *default_lldb_format = "hex";
5048   const char *lldb_format = default_lldb_format;
5049   const char *lldb_set = NULL;
5050 
5051   switch (reg.nub_info.type) {
5052   case Uint:
5053     lldb_encoding = "uint";
5054     break;
5055   case Sint:
5056     lldb_encoding = "sint";
5057     break;
5058   case IEEE754:
5059     lldb_encoding = "ieee754";
5060     if (reg.nub_info.set > 0)
5061       gdb_group = "float";
5062     break;
5063   case Vector:
5064     lldb_encoding = "vector";
5065     if (reg.nub_info.set > 0)
5066       gdb_group = "vector";
5067     break;
5068   }
5069 
5070   switch (reg.nub_info.format) {
5071   case Binary:
5072     lldb_format = "binary";
5073     break;
5074   case Decimal:
5075     lldb_format = "decimal";
5076     break;
5077   case Hex:
5078     lldb_format = "hex";
5079     break;
5080   case Float:
5081     gdb_type = "float";
5082     lldb_format = "float";
5083     break;
5084   case VectorOfSInt8:
5085     gdb_type = "float";
5086     lldb_format = "vector-sint8";
5087     break;
5088   case VectorOfUInt8:
5089     gdb_type = "float";
5090     lldb_format = "vector-uint8";
5091     break;
5092   case VectorOfSInt16:
5093     gdb_type = "float";
5094     lldb_format = "vector-sint16";
5095     break;
5096   case VectorOfUInt16:
5097     gdb_type = "float";
5098     lldb_format = "vector-uint16";
5099     break;
5100   case VectorOfSInt32:
5101     gdb_type = "float";
5102     lldb_format = "vector-sint32";
5103     break;
5104   case VectorOfUInt32:
5105     gdb_type = "float";
5106     lldb_format = "vector-uint32";
5107     break;
5108   case VectorOfFloat32:
5109     gdb_type = "float";
5110     lldb_format = "vector-float32";
5111     break;
5112   case VectorOfUInt128:
5113     gdb_type = "float";
5114     lldb_format = "vector-uint128";
5115     break;
5116   };
5117   if (reg_set_info && reg.nub_info.set < num_reg_sets)
5118     lldb_set = reg_set_info[reg.nub_info.set].name;
5119 
5120   uint32_t indent = 2;
5121 
5122   XMLElementStart(s, indent, "reg", true);
5123   XMLAttributeString(s, "name", reg.nub_info.name);
5124   XMLAttributeUnsignedDecimal(s, "regnum", reg_num);
5125   XMLAttributeUnsignedDecimal(s, "offset", reg.offset);
5126   XMLAttributeUnsignedDecimal(s, "bitsize", reg.nub_info.size * 8);
5127   XMLAttributeString(s, "group", gdb_group);
5128   XMLAttributeString(s, "type", gdb_type, default_gdb_type);
5129   XMLAttributeString(s, "altname", reg.nub_info.alt);
5130   XMLAttributeString(s, "encoding", lldb_encoding, default_lldb_encoding);
5131   XMLAttributeString(s, "format", lldb_format, default_lldb_format);
5132   XMLAttributeUnsignedDecimal(s, "group_id", reg.nub_info.set);
5133   if (reg.nub_info.reg_ehframe != INVALID_NUB_REGNUM)
5134     XMLAttributeUnsignedDecimal(s, "ehframe_regnum", reg.nub_info.reg_ehframe);
5135   if (reg.nub_info.reg_dwarf != INVALID_NUB_REGNUM)
5136     XMLAttributeUnsignedDecimal(s, "dwarf_regnum", reg.nub_info.reg_dwarf);
5137 
5138   const char *lldb_generic = NULL;
5139   switch (reg.nub_info.reg_generic) {
5140   case GENERIC_REGNUM_FP:
5141     lldb_generic = "fp";
5142     break;
5143   case GENERIC_REGNUM_PC:
5144     lldb_generic = "pc";
5145     break;
5146   case GENERIC_REGNUM_SP:
5147     lldb_generic = "sp";
5148     break;
5149   case GENERIC_REGNUM_RA:
5150     lldb_generic = "ra";
5151     break;
5152   case GENERIC_REGNUM_FLAGS:
5153     lldb_generic = "flags";
5154     break;
5155   case GENERIC_REGNUM_ARG1:
5156     lldb_generic = "arg1";
5157     break;
5158   case GENERIC_REGNUM_ARG2:
5159     lldb_generic = "arg2";
5160     break;
5161   case GENERIC_REGNUM_ARG3:
5162     lldb_generic = "arg3";
5163     break;
5164   case GENERIC_REGNUM_ARG4:
5165     lldb_generic = "arg4";
5166     break;
5167   case GENERIC_REGNUM_ARG5:
5168     lldb_generic = "arg5";
5169     break;
5170   case GENERIC_REGNUM_ARG6:
5171     lldb_generic = "arg6";
5172     break;
5173   case GENERIC_REGNUM_ARG7:
5174     lldb_generic = "arg7";
5175     break;
5176   case GENERIC_REGNUM_ARG8:
5177     lldb_generic = "arg8";
5178     break;
5179   default:
5180     break;
5181   }
5182   XMLAttributeString(s, "generic", lldb_generic);
5183 
5184   bool empty = reg.value_regnums.empty() && reg.invalidate_regnums.empty();
5185   if (!empty) {
5186     if (!reg.value_regnums.empty()) {
5187       std::ostringstream regnums;
5188       bool first = true;
5189       regnums << DECIMAL;
5190       for (auto regnum : reg.value_regnums) {
5191         if (!first)
5192           regnums << ',';
5193         regnums << regnum;
5194         first = false;
5195       }
5196       XMLAttributeString(s, "value_regnums", regnums.str().c_str());
5197     }
5198 
5199     if (!reg.invalidate_regnums.empty()) {
5200       std::ostringstream regnums;
5201       bool first = true;
5202       regnums << DECIMAL;
5203       for (auto regnum : reg.invalidate_regnums) {
5204         if (!first)
5205           regnums << ',';
5206         regnums << regnum;
5207         first = false;
5208       }
5209       XMLAttributeString(s, "invalidate_regnums", regnums.str().c_str());
5210     }
5211   }
5212   XMLElementStartEndAttributes(s, true);
5213 }
5214 
5215 void GenerateTargetXMLRegisters(std::ostringstream &s) {
5216   nub_size_t num_reg_sets = 0;
5217   const DNBRegisterSetInfo *reg_sets = DNBGetRegisterSetInfo(&num_reg_sets);
5218 
5219   uint32_t cputype = DNBGetRegisterCPUType();
5220   if (cputype) {
5221     XMLElementStart(s, 0, "feature", true);
5222     std::ostringstream name_strm;
5223     name_strm << "com.apple.debugserver." << GetArchName(cputype, 0);
5224     XMLAttributeString(s, "name", name_strm.str().c_str());
5225     XMLElementStartEndAttributes(s, false);
5226     for (uint32_t reg_num = 0; reg_num < g_num_reg_entries; ++reg_num)
5227     //        for (const auto &reg: g_dynamic_register_map)
5228     {
5229       GenerateTargetXMLRegister(s, reg_num, num_reg_sets, reg_sets,
5230                                 g_reg_entries[reg_num]);
5231     }
5232     XMLElementEnd(s, 0, "feature");
5233 
5234     if (num_reg_sets > 0) {
5235       XMLElementStart(s, 0, "groups", false);
5236       for (uint32_t set = 1; set < num_reg_sets; ++set) {
5237         XMLElementStart(s, 2, "group", true);
5238         XMLAttributeUnsignedDecimal(s, "id", set);
5239         XMLAttributeString(s, "name", reg_sets[set].name);
5240         XMLElementStartEndAttributes(s, true);
5241       }
5242       XMLElementEnd(s, 0, "groups");
5243     }
5244   }
5245 }
5246 
5247 static const char *g_target_xml_header = R"(<?xml version="1.0"?>
5248 <target version="1.0">)";
5249 
5250 static const char *g_target_xml_footer = "</target>";
5251 
5252 static std::string g_target_xml;
5253 
5254 void UpdateTargetXML() {
5255   std::ostringstream s;
5256   s << g_target_xml_header << std::endl;
5257 
5258   // Set the architecture
5259   //
5260   // On raw targets (no OS, vendor info), I've seen replies like
5261   // <architecture>i386:x86-64</architecture> (for x86_64 systems - from vmware)
5262   // <architecture>arm</architecture> (for an unspecified arm device - from a Segger JLink)
5263   // For good interop, I'm not sure what's expected here.  e.g. will anyone understand
5264   // <architecture>x86_64</architecture> ? Or is i386:x86_64 the expected phrasing?
5265   //
5266   // s << "<architecture>" << arch "</architecture>" << std::endl;
5267 
5268   // Set the OSABI
5269   // s << "<osabi>abi-name</osabi>"
5270 
5271   GenerateTargetXMLRegisters(s);
5272 
5273   s << g_target_xml_footer << std::endl;
5274 
5275   // Save the XML output in case it gets retrieved in chunks
5276   g_target_xml = s.str();
5277 }
5278 
5279 rnb_err_t RNBRemote::HandlePacket_qXfer(const char *command) {
5280   const char *p = command;
5281   p += strlen("qXfer:");
5282   const char *sep = strchr(p, ':');
5283   if (sep) {
5284     std::string object(p, sep - p); // "auxv", "backtrace", "features", etc
5285     p = sep + 1;
5286     sep = strchr(p, ':');
5287     if (sep) {
5288       std::string rw(p, sep - p); // "read" or "write"
5289       p = sep + 1;
5290       sep = strchr(p, ':');
5291       if (sep) {
5292         std::string annex(p, sep - p); // "read" or "write"
5293 
5294         p = sep + 1;
5295         sep = strchr(p, ',');
5296         if (sep) {
5297           std::string offset_str(p, sep - p); // read the length as a string
5298           p = sep + 1;
5299           std::string length_str(p); // read the offset as a string
5300           char *end = nullptr;
5301           const uint64_t offset = strtoul(offset_str.c_str(), &end,
5302                                           16); // convert offset_str to a offset
5303           if (*end == '\0') {
5304             const uint64_t length = strtoul(
5305                 length_str.c_str(), &end, 16); // convert length_str to a length
5306             if (*end == '\0') {
5307               if (object == "features" && rw == "read" &&
5308                   annex == "target.xml") {
5309                 std::ostringstream xml_out;
5310 
5311                 if (offset == 0) {
5312                   InitializeRegisters(true);
5313 
5314                   UpdateTargetXML();
5315                   if (g_target_xml.empty())
5316                     return SendPacket("E83");
5317 
5318                   if (length > g_target_xml.size()) {
5319                     xml_out << 'l'; // No more data
5320                     xml_out << binary_encode_string(g_target_xml);
5321                   } else {
5322                     xml_out << 'm'; // More data needs to be read with a
5323                                     // subsequent call
5324                     xml_out << binary_encode_string(
5325                         std::string(g_target_xml, offset, length));
5326                   }
5327                 } else {
5328                   // Retrieving target XML in chunks
5329                   if (offset < g_target_xml.size()) {
5330                     std::string chunk(g_target_xml, offset, length);
5331                     if (chunk.size() < length)
5332                       xml_out << 'l'; // No more data
5333                     else
5334                       xml_out << 'm'; // More data needs to be read with a
5335                                       // subsequent call
5336                     xml_out << binary_encode_string(chunk.data());
5337                   }
5338                 }
5339                 return SendPacket(xml_out.str());
5340               }
5341               // Well formed, put not supported
5342               return HandlePacket_UNIMPLEMENTED(command);
5343             }
5344           }
5345         }
5346       } else {
5347         SendPacket("E85");
5348       }
5349     } else {
5350       SendPacket("E86");
5351     }
5352   }
5353   return SendPacket("E82");
5354 }
5355 
5356 rnb_err_t RNBRemote::HandlePacket_qGDBServerVersion(const char *p) {
5357   std::ostringstream strm;
5358 
5359 #if defined(DEBUGSERVER_PROGRAM_NAME)
5360   strm << "name:" DEBUGSERVER_PROGRAM_NAME ";";
5361 #else
5362   strm << "name:debugserver;";
5363 #endif
5364   strm << "version:" << DEBUGSERVER_VERSION_NUM << ";";
5365 
5366   return SendPacket(strm.str());
5367 }
5368 
5369 // A helper function that retrieves a single integer value from
5370 // a one-level-deep JSON dictionary of key-value pairs.  e.g.
5371 // jThreadExtendedInfo:{"plo_pthread_tsd_base_address_offset":0,"plo_pthread_tsd_base_offset":224,"plo_pthread_tsd_entry_size":8,"thread":144305}]
5372 //
5373 uint64_t get_integer_value_for_key_name_from_json(const char *key,
5374                                                   const char *json_string) {
5375   uint64_t retval = INVALID_NUB_ADDRESS;
5376   std::string key_with_quotes = "\"";
5377   key_with_quotes += key;
5378   key_with_quotes += "\"";
5379   const char *c = strstr(json_string, key_with_quotes.c_str());
5380   if (c) {
5381     c += key_with_quotes.size();
5382 
5383     while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5384       c++;
5385 
5386     if (*c == ':') {
5387       c++;
5388 
5389       while (*c != '\0' &&
5390              (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5391         c++;
5392 
5393       errno = 0;
5394       retval = strtoul(c, NULL, 10);
5395       if (errno != 0) {
5396         retval = INVALID_NUB_ADDRESS;
5397       }
5398     }
5399   }
5400   return retval;
5401 }
5402 
5403 // A helper function that retrieves a boolean value from
5404 // a one-level-deep JSON dictionary of key-value pairs.  e.g.
5405 // jGetLoadedDynamicLibrariesInfos:{"fetch_all_solibs":true}]
5406 
5407 // Returns true if it was able to find the key name, and sets the 'value'
5408 // argument to the value found.
5409 
5410 bool get_boolean_value_for_key_name_from_json(const char *key,
5411                                               const char *json_string,
5412                                               bool &value) {
5413   std::string key_with_quotes = "\"";
5414   key_with_quotes += key;
5415   key_with_quotes += "\"";
5416   const char *c = strstr(json_string, key_with_quotes.c_str());
5417   if (c) {
5418     c += key_with_quotes.size();
5419 
5420     while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5421       c++;
5422 
5423     if (*c == ':') {
5424       c++;
5425 
5426       while (*c != '\0' &&
5427              (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5428         c++;
5429 
5430       if (strncmp(c, "true", 4) == 0) {
5431         value = true;
5432         return true;
5433       } else if (strncmp(c, "false", 5) == 0) {
5434         value = false;
5435         return true;
5436       }
5437     }
5438   }
5439   return false;
5440 }
5441 
5442 // A helper function that reads an array of uint64_t's from
5443 // a one-level-deep JSON dictionary of key-value pairs.  e.g.
5444 // jGetLoadedDynamicLibrariesInfos:{"solib_addrs":[31345823,7768020384,7310483024]}]
5445 
5446 // Returns true if it was able to find the key name, false if it did not.
5447 // "ints" will have all integers found in the array appended to it.
5448 
5449 bool get_array_of_ints_value_for_key_name_from_json(
5450     const char *key, const char *json_string, std::vector<uint64_t> &ints) {
5451   std::string key_with_quotes = "\"";
5452   key_with_quotes += key;
5453   key_with_quotes += "\"";
5454   const char *c = strstr(json_string, key_with_quotes.c_str());
5455   if (c) {
5456     c += key_with_quotes.size();
5457 
5458     while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5459       c++;
5460 
5461     if (*c == ':') {
5462       c++;
5463 
5464       while (*c != '\0' &&
5465              (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5466         c++;
5467 
5468       if (*c == '[') {
5469         c++;
5470         while (*c != '\0' &&
5471                (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5472           c++;
5473         while (true) {
5474           if (!isdigit(*c)) {
5475             return true;
5476           }
5477 
5478           errno = 0;
5479           char *endptr;
5480           uint64_t value = strtoul(c, &endptr, 10);
5481           if (errno == 0) {
5482             ints.push_back(value);
5483           } else {
5484             break;
5485           }
5486           if (endptr == c || endptr == nullptr || *endptr == '\0') {
5487             break;
5488           }
5489           c = endptr;
5490 
5491           while (*c != '\0' &&
5492                  (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5493             c++;
5494           if (*c == ',')
5495             c++;
5496           while (*c != '\0' &&
5497                  (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5498             c++;
5499           if (*c == ']') {
5500             return true;
5501           }
5502         }
5503       }
5504     }
5505   }
5506   return false;
5507 }
5508 
5509 JSONGenerator::ObjectSP
5510 RNBRemote::GetJSONThreadsInfo(bool threads_with_valid_stop_info_only) {
5511   JSONGenerator::ArraySP threads_array_sp;
5512   if (m_ctx.HasValidProcessID()) {
5513     threads_array_sp = std::make_shared<JSONGenerator::Array>();
5514 
5515     nub_process_t pid = m_ctx.ProcessID();
5516 
5517     nub_size_t numthreads = DNBProcessGetNumThreads(pid);
5518     for (nub_size_t i = 0; i < numthreads; ++i) {
5519       nub_thread_t tid = DNBProcessGetThreadAtIndex(pid, i);
5520 
5521       struct DNBThreadStopInfo tid_stop_info;
5522 
5523       const bool stop_info_valid =
5524           DNBThreadGetStopReason(pid, tid, &tid_stop_info);
5525 
5526       // If we are doing stop info only, then we only show threads that have a
5527       // valid stop reason
5528       if (threads_with_valid_stop_info_only) {
5529         if (!stop_info_valid || tid_stop_info.reason == eStopTypeInvalid)
5530           continue;
5531       }
5532 
5533       JSONGenerator::DictionarySP thread_dict_sp(
5534           new JSONGenerator::Dictionary());
5535       thread_dict_sp->AddIntegerItem("tid", tid);
5536 
5537       std::string reason_value("none");
5538 
5539       if (stop_info_valid) {
5540         switch (tid_stop_info.reason) {
5541         case eStopTypeInvalid:
5542           break;
5543 
5544         case eStopTypeSignal:
5545           if (tid_stop_info.details.signal.signo != 0) {
5546             thread_dict_sp->AddIntegerItem("signal",
5547                                            tid_stop_info.details.signal.signo);
5548             reason_value = "signal";
5549           }
5550           break;
5551 
5552         case eStopTypeException:
5553           if (tid_stop_info.details.exception.type != 0) {
5554             reason_value = "exception";
5555             thread_dict_sp->AddIntegerItem(
5556                 "metype", tid_stop_info.details.exception.type);
5557             JSONGenerator::ArraySP medata_array_sp(new JSONGenerator::Array());
5558             for (nub_size_t i = 0;
5559                  i < tid_stop_info.details.exception.data_count; ++i) {
5560               medata_array_sp->AddItem(
5561                   JSONGenerator::IntegerSP(new JSONGenerator::Integer(
5562                       tid_stop_info.details.exception.data[i])));
5563             }
5564             thread_dict_sp->AddItem("medata", medata_array_sp);
5565           }
5566           break;
5567 
5568         case eStopTypeExec:
5569           reason_value = "exec";
5570           break;
5571         }
5572       }
5573 
5574       thread_dict_sp->AddStringItem("reason", reason_value);
5575 
5576       if (!threads_with_valid_stop_info_only) {
5577         const char *thread_name = DNBThreadGetName(pid, tid);
5578         if (thread_name && thread_name[0])
5579           thread_dict_sp->AddStringItem("name", thread_name);
5580 
5581         thread_identifier_info_data_t thread_ident_info;
5582         if (DNBThreadGetIdentifierInfo(pid, tid, &thread_ident_info)) {
5583           if (thread_ident_info.dispatch_qaddr != 0) {
5584             thread_dict_sp->AddIntegerItem("qaddr",
5585                                            thread_ident_info.dispatch_qaddr);
5586 
5587             const DispatchQueueOffsets *dispatch_queue_offsets =
5588                 GetDispatchQueueOffsets();
5589             if (dispatch_queue_offsets) {
5590               std::string queue_name;
5591               uint64_t queue_width = 0;
5592               uint64_t queue_serialnum = 0;
5593               nub_addr_t dispatch_queue_t = INVALID_NUB_ADDRESS;
5594               dispatch_queue_offsets->GetThreadQueueInfo(
5595                   pid, thread_ident_info.dispatch_qaddr, dispatch_queue_t,
5596                   queue_name, queue_width, queue_serialnum);
5597               if (dispatch_queue_t == 0 && queue_name.empty() &&
5598                   queue_serialnum == 0) {
5599                 thread_dict_sp->AddBooleanItem("associated_with_dispatch_queue",
5600                                                false);
5601               } else {
5602                 thread_dict_sp->AddBooleanItem("associated_with_dispatch_queue",
5603                                                true);
5604               }
5605               if (dispatch_queue_t != INVALID_NUB_ADDRESS &&
5606                   dispatch_queue_t != 0)
5607                 thread_dict_sp->AddIntegerItem("dispatch_queue_t",
5608                                                dispatch_queue_t);
5609               if (!queue_name.empty())
5610                 thread_dict_sp->AddStringItem("qname", queue_name);
5611               if (queue_width == 1)
5612                 thread_dict_sp->AddStringItem("qkind", "serial");
5613               else if (queue_width > 1)
5614                 thread_dict_sp->AddStringItem("qkind", "concurrent");
5615               if (queue_serialnum > 0)
5616                 thread_dict_sp->AddIntegerItem("qserialnum", queue_serialnum);
5617             }
5618           }
5619         }
5620 
5621         DNBRegisterValue reg_value;
5622 
5623         if (g_reg_entries != NULL) {
5624           JSONGenerator::DictionarySP registers_dict_sp(
5625               new JSONGenerator::Dictionary());
5626 
5627           for (uint32_t reg = 0; reg < g_num_reg_entries; reg++) {
5628             // Expedite all registers in the first register set that aren't
5629             // contained in other registers
5630             if (g_reg_entries[reg].nub_info.set == 1 &&
5631                 g_reg_entries[reg].nub_info.value_regs == NULL) {
5632               if (!DNBThreadGetRegisterValueByID(
5633                       pid, tid, g_reg_entries[reg].nub_info.set,
5634                       g_reg_entries[reg].nub_info.reg, &reg_value))
5635                 continue;
5636 
5637               std::ostringstream reg_num;
5638               reg_num << std::dec << g_reg_entries[reg].debugserver_regnum;
5639               // Encode native byte ordered bytes as hex ascii
5640               registers_dict_sp->AddBytesAsHexASCIIString(
5641                   reg_num.str(), reg_value.value.v_uint8,
5642                   g_reg_entries[reg].nub_info.size);
5643             }
5644           }
5645           thread_dict_sp->AddItem("registers", registers_dict_sp);
5646         }
5647 
5648         // Add expedited stack memory so stack backtracing doesn't need to read
5649         // anything from the
5650         // frame pointer chain.
5651         StackMemoryMap stack_mmap;
5652         ReadStackMemory(pid, tid, stack_mmap);
5653         if (!stack_mmap.empty()) {
5654           JSONGenerator::ArraySP memory_array_sp(new JSONGenerator::Array());
5655 
5656           for (const auto &stack_memory : stack_mmap) {
5657             JSONGenerator::DictionarySP stack_memory_sp(
5658                 new JSONGenerator::Dictionary());
5659             stack_memory_sp->AddIntegerItem("address", stack_memory.first);
5660             stack_memory_sp->AddBytesAsHexASCIIString(
5661                 "bytes", stack_memory.second.bytes, stack_memory.second.length);
5662             memory_array_sp->AddItem(stack_memory_sp);
5663           }
5664           thread_dict_sp->AddItem("memory", memory_array_sp);
5665         }
5666       }
5667 
5668       threads_array_sp->AddItem(thread_dict_sp);
5669     }
5670   }
5671   return threads_array_sp;
5672 }
5673 
5674 rnb_err_t RNBRemote::HandlePacket_jThreadsInfo(const char *p) {
5675   JSONGenerator::ObjectSP threads_info_sp;
5676   std::ostringstream json;
5677   std::ostringstream reply_strm;
5678   // If we haven't run the process yet, return an error.
5679   if (m_ctx.HasValidProcessID()) {
5680     const bool threads_with_valid_stop_info_only = false;
5681     JSONGenerator::ObjectSP threads_info_sp =
5682         GetJSONThreadsInfo(threads_with_valid_stop_info_only);
5683 
5684     if (threads_info_sp) {
5685       std::ostringstream strm;
5686       threads_info_sp->Dump(strm);
5687       std::string binary_packet = binary_encode_string(strm.str());
5688       if (!binary_packet.empty())
5689         return SendPacket(binary_packet.c_str());
5690     }
5691   }
5692   return SendPacket("E85");
5693 }
5694 
5695 rnb_err_t RNBRemote::HandlePacket_jThreadExtendedInfo(const char *p) {
5696   nub_process_t pid;
5697   std::ostringstream json;
5698   // If we haven't run the process yet, return an error.
5699   if (!m_ctx.HasValidProcessID()) {
5700     return SendPacket("E81");
5701   }
5702 
5703   pid = m_ctx.ProcessID();
5704 
5705   const char thread_extended_info_str[] = {"jThreadExtendedInfo:{"};
5706   if (strncmp(p, thread_extended_info_str,
5707               sizeof(thread_extended_info_str) - 1) == 0) {
5708     p += strlen(thread_extended_info_str);
5709 
5710     uint64_t tid = get_integer_value_for_key_name_from_json("thread", p);
5711     uint64_t plo_pthread_tsd_base_address_offset =
5712         get_integer_value_for_key_name_from_json(
5713             "plo_pthread_tsd_base_address_offset", p);
5714     uint64_t plo_pthread_tsd_base_offset =
5715         get_integer_value_for_key_name_from_json("plo_pthread_tsd_base_offset",
5716                                                  p);
5717     uint64_t plo_pthread_tsd_entry_size =
5718         get_integer_value_for_key_name_from_json("plo_pthread_tsd_entry_size",
5719                                                  p);
5720     uint64_t dti_qos_class_index =
5721         get_integer_value_for_key_name_from_json("dti_qos_class_index", p);
5722 
5723     if (tid != INVALID_NUB_ADDRESS) {
5724       nub_addr_t pthread_t_value = DNBGetPThreadT(pid, tid);
5725 
5726       uint64_t tsd_address = INVALID_NUB_ADDRESS;
5727       if (plo_pthread_tsd_entry_size != INVALID_NUB_ADDRESS &&
5728           plo_pthread_tsd_base_offset != INVALID_NUB_ADDRESS &&
5729           plo_pthread_tsd_entry_size != INVALID_NUB_ADDRESS) {
5730         tsd_address = DNBGetTSDAddressForThread(
5731             pid, tid, plo_pthread_tsd_base_address_offset,
5732             plo_pthread_tsd_base_offset, plo_pthread_tsd_entry_size);
5733       }
5734 
5735       bool timed_out = false;
5736       Genealogy::ThreadActivitySP thread_activity_sp;
5737 
5738       // If the pthread_t value is invalid, or if we were able to fetch the
5739       // thread's TSD base
5740       // and got an invalid value back, then we have a thread in early startup
5741       // or shutdown and
5742       // it's possible that gathering the genealogy information for this thread
5743       // go badly.
5744       // Ideally fetching this info for a thread in these odd states shouldn't
5745       // matter - but
5746       // we've seen some problems with these new SPI and threads in edge-casey
5747       // states.
5748 
5749       double genealogy_fetch_time = 0;
5750       if (pthread_t_value != INVALID_NUB_ADDRESS &&
5751           tsd_address != INVALID_NUB_ADDRESS) {
5752         DNBTimer timer(false);
5753         thread_activity_sp = DNBGetGenealogyInfoForThread(pid, tid, timed_out);
5754         genealogy_fetch_time = timer.ElapsedMicroSeconds(false) / 1000000.0;
5755       }
5756 
5757       std::unordered_set<uint32_t>
5758           process_info_indexes; // an array of the process info #'s seen
5759 
5760       json << "{";
5761 
5762       bool need_to_print_comma = false;
5763 
5764       if (thread_activity_sp && !timed_out) {
5765         const Genealogy::Activity *activity =
5766             &thread_activity_sp->current_activity;
5767         bool need_vouchers_comma_sep = false;
5768         json << "\"activity_query_timed_out\":false,";
5769         if (genealogy_fetch_time != 0) {
5770           //  If we append the floating point value with << we'll get it in
5771           //  scientific
5772           //  notation.
5773           char floating_point_ascii_buffer[64];
5774           floating_point_ascii_buffer[0] = '\0';
5775           snprintf(floating_point_ascii_buffer,
5776                    sizeof(floating_point_ascii_buffer), "%f",
5777                    genealogy_fetch_time);
5778           if (strlen(floating_point_ascii_buffer) > 0) {
5779             if (need_to_print_comma)
5780               json << ",";
5781             need_to_print_comma = true;
5782             json << "\"activity_query_duration\":"
5783                  << floating_point_ascii_buffer;
5784           }
5785         }
5786         if (activity->activity_id != 0) {
5787           if (need_to_print_comma)
5788             json << ",";
5789           need_to_print_comma = true;
5790           need_vouchers_comma_sep = true;
5791           json << "\"activity\":{";
5792           json << "\"start\":" << activity->activity_start << ",";
5793           json << "\"id\":" << activity->activity_id << ",";
5794           json << "\"parent_id\":" << activity->parent_id << ",";
5795           json << "\"name\":\""
5796                << json_string_quote_metachars(activity->activity_name) << "\",";
5797           json << "\"reason\":\""
5798                << json_string_quote_metachars(activity->reason) << "\"";
5799           json << "}";
5800         }
5801         if (thread_activity_sp->messages.size() > 0) {
5802           need_to_print_comma = true;
5803           if (need_vouchers_comma_sep)
5804             json << ",";
5805           need_vouchers_comma_sep = true;
5806           json << "\"trace_messages\":[";
5807           bool printed_one_message = false;
5808           for (auto iter = thread_activity_sp->messages.begin();
5809                iter != thread_activity_sp->messages.end(); ++iter) {
5810             if (printed_one_message)
5811               json << ",";
5812             else
5813               printed_one_message = true;
5814             json << "{";
5815             json << "\"timestamp\":" << iter->timestamp << ",";
5816             json << "\"activity_id\":" << iter->activity_id << ",";
5817             json << "\"trace_id\":" << iter->trace_id << ",";
5818             json << "\"thread\":" << iter->thread << ",";
5819             json << "\"type\":" << (int)iter->type << ",";
5820             json << "\"process_info_index\":" << iter->process_info_index
5821                  << ",";
5822             process_info_indexes.insert(iter->process_info_index);
5823             json << "\"message\":\""
5824                  << json_string_quote_metachars(iter->message) << "\"";
5825             json << "}";
5826           }
5827           json << "]";
5828         }
5829         if (thread_activity_sp->breadcrumbs.size() == 1) {
5830           need_to_print_comma = true;
5831           if (need_vouchers_comma_sep)
5832             json << ",";
5833           need_vouchers_comma_sep = true;
5834           json << "\"breadcrumb\":{";
5835           for (auto iter = thread_activity_sp->breadcrumbs.begin();
5836                iter != thread_activity_sp->breadcrumbs.end(); ++iter) {
5837             json << "\"breadcrumb_id\":" << iter->breadcrumb_id << ",";
5838             json << "\"activity_id\":" << iter->activity_id << ",";
5839             json << "\"timestamp\":" << iter->timestamp << ",";
5840             json << "\"name\":\"" << json_string_quote_metachars(iter->name)
5841                  << "\"";
5842           }
5843           json << "}";
5844         }
5845         if (process_info_indexes.size() > 0) {
5846           need_to_print_comma = true;
5847           if (need_vouchers_comma_sep)
5848             json << ",";
5849           need_vouchers_comma_sep = true;
5850           bool printed_one_process_info = false;
5851           for (auto iter = process_info_indexes.begin();
5852                iter != process_info_indexes.end(); ++iter) {
5853             if (printed_one_process_info)
5854               json << ",";
5855             Genealogy::ProcessExecutableInfoSP image_info_sp;
5856             uint32_t idx = *iter;
5857             image_info_sp = DNBGetGenealogyImageInfo(pid, idx);
5858             if (image_info_sp) {
5859               if (!printed_one_process_info) {
5860                 json << "\"process_infos\":[";
5861                 printed_one_process_info = true;
5862               }
5863 
5864               json << "{";
5865               char uuid_buf[37];
5866               uuid_unparse_upper(image_info_sp->image_uuid, uuid_buf);
5867               json << "\"process_info_index\":" << idx << ",";
5868               json << "\"image_path\":\""
5869                    << json_string_quote_metachars(image_info_sp->image_path)
5870                    << "\",";
5871               json << "\"image_uuid\":\"" << uuid_buf << "\"";
5872               json << "}";
5873             }
5874           }
5875           if (printed_one_process_info)
5876             json << "]";
5877         }
5878       } else {
5879         if (timed_out) {
5880           if (need_to_print_comma)
5881             json << ",";
5882           need_to_print_comma = true;
5883           json << "\"activity_query_timed_out\":true";
5884           if (genealogy_fetch_time != 0) {
5885             //  If we append the floating point value with << we'll get it in
5886             //  scientific
5887             //  notation.
5888             char floating_point_ascii_buffer[64];
5889             floating_point_ascii_buffer[0] = '\0';
5890             snprintf(floating_point_ascii_buffer,
5891                      sizeof(floating_point_ascii_buffer), "%f",
5892                      genealogy_fetch_time);
5893             if (strlen(floating_point_ascii_buffer) > 0) {
5894               json << ",";
5895               json << "\"activity_query_duration\":"
5896                    << floating_point_ascii_buffer;
5897             }
5898           }
5899         }
5900       }
5901 
5902       if (tsd_address != INVALID_NUB_ADDRESS) {
5903         if (need_to_print_comma)
5904           json << ",";
5905         need_to_print_comma = true;
5906         json << "\"tsd_address\":" << tsd_address;
5907 
5908         if (dti_qos_class_index != 0 && dti_qos_class_index != UINT64_MAX) {
5909           ThreadInfo::QoS requested_qos = DNBGetRequestedQoSForThread(
5910               pid, tid, tsd_address, dti_qos_class_index);
5911           if (requested_qos.IsValid()) {
5912             if (need_to_print_comma)
5913               json << ",";
5914             need_to_print_comma = true;
5915             json << "\"requested_qos\":{";
5916             json << "\"enum_value\":" << requested_qos.enum_value << ",";
5917             json << "\"constant_name\":\""
5918                  << json_string_quote_metachars(requested_qos.constant_name)
5919                  << "\",";
5920             json << "\"printable_name\":\""
5921                  << json_string_quote_metachars(requested_qos.printable_name)
5922                  << "\"";
5923             json << "}";
5924           }
5925         }
5926       }
5927 
5928       if (pthread_t_value != INVALID_NUB_ADDRESS) {
5929         if (need_to_print_comma)
5930           json << ",";
5931         need_to_print_comma = true;
5932         json << "\"pthread_t\":" << pthread_t_value;
5933       }
5934 
5935       nub_addr_t dispatch_queue_t_value = DNBGetDispatchQueueT(pid, tid);
5936       if (dispatch_queue_t_value != INVALID_NUB_ADDRESS) {
5937         if (need_to_print_comma)
5938           json << ",";
5939         need_to_print_comma = true;
5940         json << "\"dispatch_queue_t\":" << dispatch_queue_t_value;
5941       }
5942 
5943       json << "}";
5944       std::string json_quoted = binary_encode_string(json.str());
5945       return SendPacket(json_quoted);
5946     }
5947   }
5948   return SendPacket("OK");
5949 }
5950 
5951 //  This packet may be called in one of three ways:
5952 //
5953 //  jGetLoadedDynamicLibrariesInfos:{"image_count":40,"image_list_address":4295244704}
5954 //      Look for an array of the old dyld_all_image_infos style of binary infos
5955 //      at the image_list_address.
5956 //      This an array of {void* load_addr, void* mod_date, void* pathname}
5957 //
5958 //  jGetLoadedDynamicLibrariesInfos:{"fetch_all_solibs":true}
5959 //      Use the new style (macOS 10.12, tvOS 10, iOS 10, watchOS 3) dyld SPI to
5960 //      get a list of all the
5961 //      libraries loaded
5962 //
5963 //  jGetLoadedDynamicLibrariesInfos:{"solib_addresses":[8382824135,3258302053,830202858503]}
5964 //      Use the new style (macOS 10.12, tvOS 10, iOS 10, watchOS 3) dyld SPI to
5965 //      get the information
5966 //      about the libraries loaded at these addresses.
5967 //
5968 rnb_err_t
5969 RNBRemote::HandlePacket_jGetLoadedDynamicLibrariesInfos(const char *p) {
5970   nub_process_t pid;
5971   // If we haven't run the process yet, return an error.
5972   if (!m_ctx.HasValidProcessID()) {
5973     return SendPacket("E83");
5974   }
5975 
5976   pid = m_ctx.ProcessID();
5977 
5978   const char get_loaded_dynamic_libraries_infos_str[] = {
5979       "jGetLoadedDynamicLibrariesInfos:{"};
5980   if (strncmp(p, get_loaded_dynamic_libraries_infos_str,
5981               sizeof(get_loaded_dynamic_libraries_infos_str) - 1) == 0) {
5982     p += strlen(get_loaded_dynamic_libraries_infos_str);
5983 
5984     JSONGenerator::ObjectSP json_sp;
5985 
5986     std::vector<uint64_t> macho_addresses;
5987     bool fetch_all_solibs = false;
5988     if (get_boolean_value_for_key_name_from_json("fetch_all_solibs", p,
5989                                                  fetch_all_solibs) &&
5990         fetch_all_solibs) {
5991       json_sp = DNBGetAllLoadedLibrariesInfos(pid);
5992     } else if (get_array_of_ints_value_for_key_name_from_json(
5993                    "solib_addresses", p, macho_addresses)) {
5994       json_sp = DNBGetLibrariesInfoForAddresses(pid, macho_addresses);
5995     } else {
5996       nub_addr_t image_list_address =
5997           get_integer_value_for_key_name_from_json("image_list_address", p);
5998       nub_addr_t image_count =
5999           get_integer_value_for_key_name_from_json("image_count", p);
6000 
6001       if (image_list_address != INVALID_NUB_ADDRESS &&
6002           image_count != INVALID_NUB_ADDRESS) {
6003         json_sp = DNBGetLoadedDynamicLibrariesInfos(pid, image_list_address,
6004                                                     image_count);
6005       }
6006     }
6007 
6008     if (json_sp.get()) {
6009       std::ostringstream json_str;
6010       json_sp->Dump(json_str);
6011       if (json_str.str().size() > 0) {
6012         std::string json_str_quoted = binary_encode_string(json_str.str());
6013         return SendPacket(json_str_quoted.c_str());
6014       } else {
6015         SendPacket("E84");
6016       }
6017     }
6018   }
6019   return SendPacket("OK");
6020 }
6021 
6022 // This packet does not currently take any arguments.  So the behavior is
6023 //    jGetSharedCacheInfo:{}
6024 //         send information about the inferior's shared cache
6025 //    jGetSharedCacheInfo:
6026 //         send "OK" to indicate that this packet is supported
6027 rnb_err_t RNBRemote::HandlePacket_jGetSharedCacheInfo(const char *p) {
6028   nub_process_t pid;
6029   // If we haven't run the process yet, return an error.
6030   if (!m_ctx.HasValidProcessID()) {
6031     return SendPacket("E85");
6032   }
6033 
6034   pid = m_ctx.ProcessID();
6035 
6036   const char get_shared_cache_info_str[] = {"jGetSharedCacheInfo:{"};
6037   if (strncmp(p, get_shared_cache_info_str,
6038               sizeof(get_shared_cache_info_str) - 1) == 0) {
6039     JSONGenerator::ObjectSP json_sp = DNBGetSharedCacheInfo(pid);
6040 
6041     if (json_sp.get()) {
6042       std::ostringstream json_str;
6043       json_sp->Dump(json_str);
6044       if (json_str.str().size() > 0) {
6045         std::string json_str_quoted = binary_encode_string(json_str.str());
6046         return SendPacket(json_str_quoted.c_str());
6047       } else {
6048         SendPacket("E86");
6049       }
6050     }
6051   }
6052   return SendPacket("OK");
6053 }
6054 
6055 static bool MachHeaderIsMainExecutable(nub_process_t pid, uint32_t addr_size,
6056                                        nub_addr_t mach_header_addr,
6057                                        mach_header &mh) {
6058   DNBLogThreadedIf(LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = %u, "
6059                                  "addr_size = %u, mach_header_addr = "
6060                                  "0x%16.16llx)",
6061                    pid, addr_size, mach_header_addr);
6062   const nub_size_t bytes_read =
6063       DNBProcessMemoryRead(pid, mach_header_addr, sizeof(mh), &mh);
6064   if (bytes_read == sizeof(mh)) {
6065     DNBLogThreadedIf(
6066         LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = %u, addr_size = "
6067                       "%u, mach_header_addr = 0x%16.16llx): mh = {\n  magic = "
6068                       "0x%8.8x\n  cpu = 0x%8.8x\n  sub = 0x%8.8x\n  filetype = "
6069                       "%u\n  ncmds = %u\n  sizeofcmds = 0x%8.8x\n  flags = "
6070                       "0x%8.8x }",
6071         pid, addr_size, mach_header_addr, mh.magic, mh.cputype, mh.cpusubtype,
6072         mh.filetype, mh.ncmds, mh.sizeofcmds, mh.flags);
6073     if ((addr_size == 4 && mh.magic == MH_MAGIC) ||
6074         (addr_size == 8 && mh.magic == MH_MAGIC_64)) {
6075       if (mh.filetype == MH_EXECUTE) {
6076         DNBLogThreadedIf(LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = "
6077                                        "%u, addr_size = %u, mach_header_addr = "
6078                                        "0x%16.16llx) -> this is the "
6079                                        "executable!!!",
6080                          pid, addr_size, mach_header_addr);
6081         return true;
6082       }
6083     }
6084   }
6085   return false;
6086 }
6087 
6088 static nub_addr_t GetMachHeaderForMainExecutable(const nub_process_t pid,
6089                                                  const uint32_t addr_size,
6090                                                  mach_header &mh) {
6091   struct AllImageInfos {
6092     uint32_t version;
6093     uint32_t dylib_info_count;
6094     uint64_t dylib_info_addr;
6095   };
6096 
6097   uint64_t mach_header_addr = 0;
6098 
6099   const nub_addr_t shlib_addr = DNBProcessGetSharedLibraryInfoAddress(pid);
6100   uint8_t bytes[256];
6101   nub_size_t bytes_read = 0;
6102   DNBDataRef data(bytes, sizeof(bytes), false);
6103   DNBDataRef::offset_t offset = 0;
6104   data.SetPointerSize(addr_size);
6105 
6106   // When we are sitting at __dyld_start, the kernel has placed the
6107   // address of the mach header of the main executable on the stack. If we
6108   // read the SP and dereference a pointer, we might find the mach header
6109   // for the executable. We also just make sure there is only 1 thread
6110   // since if we are at __dyld_start we shouldn't have multiple threads.
6111   if (DNBProcessGetNumThreads(pid) == 1) {
6112     nub_thread_t tid = DNBProcessGetThreadAtIndex(pid, 0);
6113     if (tid != INVALID_NUB_THREAD) {
6114       DNBRegisterValue sp_value;
6115       if (DNBThreadGetRegisterValueByID(pid, tid, REGISTER_SET_GENERIC,
6116                                         GENERIC_REGNUM_SP, &sp_value)) {
6117         uint64_t sp =
6118             addr_size == 8 ? sp_value.value.uint64 : sp_value.value.uint32;
6119         bytes_read = DNBProcessMemoryRead(pid, sp, addr_size, bytes);
6120         if (bytes_read == addr_size) {
6121           offset = 0;
6122           mach_header_addr = data.GetPointer(&offset);
6123           if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, mh))
6124             return mach_header_addr;
6125         }
6126       }
6127     }
6128   }
6129 
6130   // Check the dyld_all_image_info structure for a list of mach header
6131   // since it is a very easy thing to check
6132   if (shlib_addr != INVALID_NUB_ADDRESS) {
6133     bytes_read =
6134         DNBProcessMemoryRead(pid, shlib_addr, sizeof(AllImageInfos), bytes);
6135     if (bytes_read > 0) {
6136       AllImageInfos aii;
6137       offset = 0;
6138       aii.version = data.Get32(&offset);
6139       aii.dylib_info_count = data.Get32(&offset);
6140       if (aii.dylib_info_count > 0) {
6141         aii.dylib_info_addr = data.GetPointer(&offset);
6142         if (aii.dylib_info_addr != 0) {
6143           const size_t image_info_byte_size = 3 * addr_size;
6144           for (uint32_t i = 0; i < aii.dylib_info_count; ++i) {
6145             bytes_read = DNBProcessMemoryRead(pid, aii.dylib_info_addr +
6146                                                        i * image_info_byte_size,
6147                                               image_info_byte_size, bytes);
6148             if (bytes_read != image_info_byte_size)
6149               break;
6150             offset = 0;
6151             mach_header_addr = data.GetPointer(&offset);
6152             if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr,
6153                                            mh))
6154               return mach_header_addr;
6155           }
6156         }
6157       }
6158     }
6159   }
6160 
6161   // We failed to find the executable's mach header from the all image
6162   // infos and by dereferencing the stack pointer. Now we fall back to
6163   // enumerating the memory regions and looking for regions that are
6164   // executable.
6165   DNBRegionInfo region_info;
6166   mach_header_addr = 0;
6167   while (DNBProcessMemoryRegionInfo(pid, mach_header_addr, &region_info)) {
6168     if (region_info.size == 0)
6169       break;
6170 
6171     if (region_info.permissions & eMemoryPermissionsExecutable) {
6172       DNBLogThreadedIf(
6173           LOG_RNB_PROC, "[0x%16.16llx - 0x%16.16llx) permissions = %c%c%c: "
6174                         "checking region for executable mach header",
6175           region_info.addr, region_info.addr + region_info.size,
6176           (region_info.permissions & eMemoryPermissionsReadable) ? 'r' : '-',
6177           (region_info.permissions & eMemoryPermissionsWritable) ? 'w' : '-',
6178           (region_info.permissions & eMemoryPermissionsExecutable) ? 'x' : '-');
6179       if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, mh))
6180         return mach_header_addr;
6181     } else {
6182       DNBLogThreadedIf(
6183           LOG_RNB_PROC,
6184           "[0x%16.16llx - 0x%16.16llx): permissions = %c%c%c: skipping region",
6185           region_info.addr, region_info.addr + region_info.size,
6186           (region_info.permissions & eMemoryPermissionsReadable) ? 'r' : '-',
6187           (region_info.permissions & eMemoryPermissionsWritable) ? 'w' : '-',
6188           (region_info.permissions & eMemoryPermissionsExecutable) ? 'x' : '-');
6189     }
6190     // Set the address to the next mapped region
6191     mach_header_addr = region_info.addr + region_info.size;
6192   }
6193   bzero(&mh, sizeof(mh));
6194   return INVALID_NUB_ADDRESS;
6195 }
6196 
6197 rnb_err_t RNBRemote::HandlePacket_qSymbol(const char *command) {
6198   const char *p = command;
6199   p += strlen("qSymbol:");
6200   const char *sep = strchr(p, ':');
6201 
6202   std::string symbol_name;
6203   std::string symbol_value_str;
6204   // Extract the symbol value if there is one
6205   if (sep > p)
6206     symbol_value_str.assign(p, sep - p);
6207   p = sep + 1;
6208 
6209   if (*p) {
6210     // We have a symbol name
6211     symbol_name = decode_hex_ascii_string(p);
6212     if (!symbol_value_str.empty()) {
6213       nub_addr_t symbol_value = decode_uint64(symbol_value_str.c_str(), 16);
6214       if (symbol_name == "dispatch_queue_offsets")
6215         m_dispatch_queue_offsets_addr = symbol_value;
6216     }
6217     ++m_qSymbol_index;
6218   } else {
6219     // No symbol name, set our symbol index to zero so we can
6220     // read any symbols that we need
6221     m_qSymbol_index = 0;
6222   }
6223 
6224   symbol_name.clear();
6225 
6226   if (m_qSymbol_index == 0) {
6227     if (m_dispatch_queue_offsets_addr == INVALID_NUB_ADDRESS)
6228       symbol_name = "dispatch_queue_offsets";
6229     else
6230       ++m_qSymbol_index;
6231   }
6232 
6233   //    // Lookup next symbol when we have one...
6234   //    if (m_qSymbol_index == 1)
6235   //    {
6236   //    }
6237 
6238   if (symbol_name.empty()) {
6239     // Done with symbol lookups
6240     return SendPacket("OK");
6241   } else {
6242     std::ostringstream reply;
6243     reply << "qSymbol:";
6244     for (size_t i = 0; i < symbol_name.size(); ++i)
6245       reply << RAWHEX8(symbol_name[i]);
6246     return SendPacket(reply.str().c_str());
6247   }
6248 }
6249 
6250 // Note that all numeric values returned by qProcessInfo are hex encoded,
6251 // including the pid and the cpu type.
6252 
6253 rnb_err_t RNBRemote::HandlePacket_qProcessInfo(const char *p) {
6254   nub_process_t pid;
6255   std::ostringstream rep;
6256 
6257   // If we haven't run the process yet, return an error.
6258   if (!m_ctx.HasValidProcessID())
6259     return SendPacket("E68");
6260 
6261   pid = m_ctx.ProcessID();
6262 
6263   rep << "pid:" << std::hex << pid << ';';
6264 
6265   int procpid_mib[4];
6266   procpid_mib[0] = CTL_KERN;
6267   procpid_mib[1] = KERN_PROC;
6268   procpid_mib[2] = KERN_PROC_PID;
6269   procpid_mib[3] = pid;
6270   struct kinfo_proc proc_kinfo;
6271   size_t proc_kinfo_size = sizeof(struct kinfo_proc);
6272 
6273   if (::sysctl(procpid_mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) {
6274     if (proc_kinfo_size > 0) {
6275       rep << "parent-pid:" << std::hex << proc_kinfo.kp_eproc.e_ppid << ';';
6276       rep << "real-uid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_ruid
6277           << ';';
6278       rep << "real-gid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_rgid
6279           << ';';
6280       rep << "effective-uid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_uid
6281           << ';';
6282       if (proc_kinfo.kp_eproc.e_ucred.cr_ngroups > 0)
6283         rep << "effective-gid:" << std::hex
6284             << proc_kinfo.kp_eproc.e_ucred.cr_groups[0] << ';';
6285     }
6286   }
6287 
6288   cpu_type_t cputype = DNBProcessGetCPUType(pid);
6289   if (cputype == 0) {
6290     DNBLog("Unable to get the process cpu_type, making a best guess.");
6291     cputype = best_guess_cpu_type();
6292   }
6293 
6294   uint32_t addr_size = 0;
6295   if (cputype != 0) {
6296     rep << "cputype:" << std::hex << cputype << ";";
6297     if (cputype & CPU_ARCH_ABI64)
6298       addr_size = 8;
6299     else
6300       addr_size = 4;
6301   }
6302 
6303   bool host_cpu_is_64bit = false;
6304   uint32_t is64bit_capable;
6305   size_t is64bit_capable_len = sizeof(is64bit_capable);
6306   if (sysctlbyname("hw.cpu64bit_capable", &is64bit_capable,
6307                    &is64bit_capable_len, NULL, 0) == 0)
6308     host_cpu_is_64bit = is64bit_capable != 0;
6309 
6310   uint32_t cpusubtype;
6311   size_t cpusubtype_len = sizeof(cpusubtype);
6312   if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &cpusubtype_len, NULL, 0) ==
6313       0) {
6314     // If a process is CPU_TYPE_X86, then ignore the cpusubtype that we detected
6315     // from the host and use CPU_SUBTYPE_I386_ALL because we don't want the
6316     // CPU_SUBTYPE_X86_ARCH1 or CPU_SUBTYPE_X86_64_H to be used as the cpu
6317     // subtype
6318     // for i386...
6319     if (host_cpu_is_64bit) {
6320       if (cputype == CPU_TYPE_X86) {
6321         cpusubtype = 3; // CPU_SUBTYPE_I386_ALL
6322       } else if (cputype == CPU_TYPE_ARM) {
6323         // We can query a process' cputype but we cannot query a process'
6324         // cpusubtype.
6325         // If the process has cputype CPU_TYPE_ARM, then it is an armv7 (32-bit
6326         // process) and we
6327         // need to override the host cpusubtype (which is in the
6328         // CPU_SUBTYPE_ARM64 subtype namespace)
6329         // with a reasonable CPU_SUBTYPE_ARMV7 subtype.
6330         cpusubtype = 12; // CPU_SUBTYPE_ARM_V7K
6331       }
6332     }
6333 #if defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
6334     // on arm64_32 devices, the machine's native cpu type is
6335     // CPU_TYPE_ARM64 and subtype is 2 indicating arm64e.
6336     // But we change the cputype to CPU_TYPE_ARM64_32 because
6337     // the user processes are all ILP32 processes today.
6338     // We also need to rewrite the cpusubtype so we vend
6339     // a valid cputype + cpusubtype combination.
6340     if (cputype == CPU_TYPE_ARM64_32 && cpusubtype == 2)
6341       cpusubtype = CPU_SUBTYPE_ARM64_32_V8;
6342 #endif
6343 
6344     rep << "cpusubtype:" << std::hex << cpusubtype << ';';
6345   }
6346 
6347   bool os_handled = false;
6348   if (addr_size > 0) {
6349     rep << "ptrsize:" << std::dec << addr_size << ';';
6350 
6351 #if (defined(__x86_64__) || defined(__i386__))
6352     // Try and get the OS type by looking at the load commands in the main
6353     // executable and looking for a LC_VERSION_MIN load command. This is the
6354     // most reliable way to determine the "ostype" value when on desktop.
6355 
6356     mach_header mh;
6357     nub_addr_t exe_mach_header_addr =
6358         GetMachHeaderForMainExecutable(pid, addr_size, mh);
6359     if (exe_mach_header_addr != INVALID_NUB_ADDRESS) {
6360       uint64_t load_command_addr =
6361           exe_mach_header_addr +
6362           ((addr_size == 8) ? sizeof(mach_header_64) : sizeof(mach_header));
6363       load_command lc;
6364       for (uint32_t i = 0; i < mh.ncmds && !os_handled; ++i) {
6365         const nub_size_t bytes_read =
6366             DNBProcessMemoryRead(pid, load_command_addr, sizeof(lc), &lc);
6367         (void)bytes_read;
6368 
6369         uint32_t major_version, minor_version, patch_version;
6370         auto *platform = DNBGetDeploymentInfo(pid, lc, load_command_addr,
6371                                               major_version, minor_version,
6372                                               patch_version);
6373         if (platform) {
6374           os_handled = true;
6375           rep << "ostype:" << platform << ";";
6376           break;
6377         }
6378         load_command_addr = load_command_addr + lc.cmdsize;
6379       }
6380     }
6381 #endif // when compiling this on x86 targets
6382   }
6383 
6384   // If we weren't able to find the OS in a LC_VERSION_MIN load command, try
6385   // to set it correctly by using the cpu type and other tricks
6386   if (!os_handled) {
6387     // The OS in the triple should be "ios" or "macosx" which doesn't match our
6388     // "Darwin" which gets returned from "kern.ostype", so we need to hardcode
6389     // this for now.
6390     if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64
6391         || cputype == CPU_TYPE_ARM64_32) {
6392 #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
6393       rep << "ostype:tvos;";
6394 #elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
6395       rep << "ostype:watchos;";
6396 #elif defined(TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1
6397       rep << "ostype:bridgeos;";
6398 #else
6399       rep << "ostype:ios;";
6400 #endif
6401     } else {
6402       bool is_ios_simulator = false;
6403       if (cputype == CPU_TYPE_X86 || cputype == CPU_TYPE_X86_64) {
6404         // Check for iOS simulator binaries by getting the process argument
6405         // and environment and checking for SIMULATOR_UDID in the environment
6406         int proc_args_mib[3] = {CTL_KERN, KERN_PROCARGS2, (int)pid};
6407 
6408         uint8_t arg_data[8192];
6409         size_t arg_data_size = sizeof(arg_data);
6410         if (::sysctl(proc_args_mib, 3, arg_data, &arg_data_size, NULL, 0) ==
6411             0) {
6412           DNBDataRef data(arg_data, arg_data_size, false);
6413           DNBDataRef::offset_t offset = 0;
6414           uint32_t argc = data.Get32(&offset);
6415           const char *cstr;
6416 
6417           cstr = data.GetCStr(&offset);
6418           if (cstr) {
6419             // Skip NULLs
6420             while (true) {
6421               const char *p = data.PeekCStr(offset);
6422               if ((p == NULL) || (*p != '\0'))
6423                 break;
6424               ++offset;
6425             }
6426             // Now skip all arguments
6427             for (uint32_t i = 0; i < argc; ++i) {
6428               data.GetCStr(&offset);
6429             }
6430 
6431             // Now iterate across all environment variables
6432             while ((cstr = data.GetCStr(&offset))) {
6433               if (strncmp(cstr, "SIMULATOR_UDID=", strlen("SIMULATOR_UDID=")) ==
6434                   0) {
6435                 is_ios_simulator = true;
6436                 break;
6437               }
6438               if (cstr[0] == '\0')
6439                 break;
6440             }
6441           }
6442         }
6443       }
6444       if (is_ios_simulator) {
6445 #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
6446         rep << "ostype:tvos;";
6447 #elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
6448         rep << "ostype:watchos;";
6449 #elif defined(TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1
6450         rep << "ostype:bridgeos;";
6451 #else
6452         rep << "ostype:ios;";
6453 #endif
6454       } else {
6455         rep << "ostype:macosx;";
6456       }
6457     }
6458   }
6459 
6460   rep << "vendor:apple;";
6461 
6462 #if defined(__LITTLE_ENDIAN__)
6463   rep << "endian:little;";
6464 #elif defined(__BIG_ENDIAN__)
6465   rep << "endian:big;";
6466 #elif defined(__PDP_ENDIAN__)
6467   rep << "endian:pdp;";
6468 #endif
6469 
6470   if (addr_size == 0) {
6471 #if (defined(__x86_64__) || defined(__i386__)) && defined(x86_THREAD_STATE)
6472     nub_thread_t thread = DNBProcessGetCurrentThreadMachPort(pid);
6473     kern_return_t kr;
6474     x86_thread_state_t gp_regs;
6475     mach_msg_type_number_t gp_count = x86_THREAD_STATE_COUNT;
6476     kr = thread_get_state(static_cast<thread_act_t>(thread), x86_THREAD_STATE,
6477                           (thread_state_t)&gp_regs, &gp_count);
6478     if (kr == KERN_SUCCESS) {
6479       if (gp_regs.tsh.flavor == x86_THREAD_STATE64)
6480         rep << "ptrsize:8;";
6481       else
6482         rep << "ptrsize:4;";
6483     }
6484 #elif defined(__arm__)
6485     rep << "ptrsize:4;";
6486 #elif (defined(__arm64__) || defined(__aarch64__)) &&                          \
6487     defined(ARM_UNIFIED_THREAD_STATE)
6488     nub_thread_t thread = DNBProcessGetCurrentThreadMachPort(pid);
6489     kern_return_t kr;
6490     arm_unified_thread_state_t gp_regs;
6491     mach_msg_type_number_t gp_count = ARM_UNIFIED_THREAD_STATE_COUNT;
6492     kr = thread_get_state(thread, ARM_UNIFIED_THREAD_STATE,
6493                           (thread_state_t)&gp_regs, &gp_count);
6494     if (kr == KERN_SUCCESS) {
6495       if (gp_regs.ash.flavor == ARM_THREAD_STATE64)
6496         rep << "ptrsize:8;";
6497       else
6498         rep << "ptrsize:4;";
6499     }
6500 #endif
6501   }
6502 
6503   return SendPacket(rep.str());
6504 }
6505 
6506 const RNBRemote::DispatchQueueOffsets *RNBRemote::GetDispatchQueueOffsets() {
6507   if (!m_dispatch_queue_offsets.IsValid() &&
6508       m_dispatch_queue_offsets_addr != INVALID_NUB_ADDRESS &&
6509       m_ctx.HasValidProcessID()) {
6510     nub_process_t pid = m_ctx.ProcessID();
6511     nub_size_t bytes_read = DNBProcessMemoryRead(
6512         pid, m_dispatch_queue_offsets_addr, sizeof(m_dispatch_queue_offsets),
6513         &m_dispatch_queue_offsets);
6514     if (bytes_read != sizeof(m_dispatch_queue_offsets))
6515       m_dispatch_queue_offsets.Clear();
6516   }
6517 
6518   if (m_dispatch_queue_offsets.IsValid())
6519     return &m_dispatch_queue_offsets;
6520   else
6521     return nullptr;
6522 }
6523 
6524 void RNBRemote::EnableCompressionNextSendPacket(compression_types type) {
6525   m_compression_mode = type;
6526   m_enable_compression_next_send_packet = true;
6527 }
6528 
6529 compression_types RNBRemote::GetCompressionType() {
6530   // The first packet we send back to the debugger after a QEnableCompression
6531   // request
6532   // should be uncompressed -- so we can indicate whether the compression was
6533   // enabled
6534   // or not via OK / Enn returns.  After that, all packets sent will be using
6535   // the
6536   // compression protocol.
6537 
6538   if (m_enable_compression_next_send_packet) {
6539     // One time, we send back "None" as our compression type
6540     m_enable_compression_next_send_packet = false;
6541     return compression_types::none;
6542   }
6543   return m_compression_mode;
6544 }
6545