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