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