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