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