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