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