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