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