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