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