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