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