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