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