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