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