• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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           &m_ctx, attach_name.c_str(), ignore_existing, NULL, 1000, err_str,
3931           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           &m_ctx, attach_name.c_str(), ignore_existing, NULL, 1000, err_str,
3943           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,
3952                                           Context().GetUnmaskSignals(), err_str,
3953                                           sizeof(err_str));
3954 
3955     } else if (strstr(p, "vAttach;") == p) {
3956       p += strlen("vAttach;");
3957       char *end = NULL;
3958       pid_attaching_to = static_cast<int>(
3959           strtoul(p, &end, 16)); // PID will be in hex, so use base 16 to decode
3960       if (p != end && *end == '\0') {
3961         // Wait at most 30 second for attach
3962         struct timespec attach_timeout_abstime;
3963         DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, 30, 0);
3964         attach_pid = DNBProcessAttach(pid_attaching_to, &attach_timeout_abstime,
3965                                       false, err_str, sizeof(err_str));
3966       }
3967     } else {
3968       return HandlePacket_UNIMPLEMENTED(p);
3969     }
3970 
3971     if (attach_pid != INVALID_NUB_PROCESS) {
3972       if (m_ctx.ProcessID() != attach_pid)
3973         m_ctx.SetProcessID(attach_pid);
3974       // Send a stop reply packet to indicate we successfully attached!
3975       NotifyThatProcessStopped();
3976       return rnb_success;
3977     } else {
3978       m_ctx.LaunchStatus().SetError(-1, DNBError::Generic);
3979       if (err_str[0])
3980         m_ctx.LaunchStatus().SetErrorString(err_str);
3981       else
3982         m_ctx.LaunchStatus().SetErrorString("attach failed");
3983 
3984       if (pid_attaching_to == INVALID_NUB_PROCESS && !attach_name.empty()) {
3985         pid_attaching_to = DNBProcessGetPIDByName(attach_name.c_str());
3986       }
3987 
3988       // attach_pid is INVALID_NUB_PROCESS - we did not succeed in attaching
3989       // if the original request, pid_attaching_to, is available, see if we
3990       // can figure out why we couldn't attach.  Return an informative error
3991       // string to lldb.
3992 
3993       if (pid_attaching_to != INVALID_NUB_PROCESS) {
3994         // The order of these checks is important.
3995         if (process_does_not_exist (pid_attaching_to)) {
3996           DNBLogError("Tried to attach to pid that doesn't exist");
3997           std::string return_message = "E96;";
3998           return_message += cstring_to_asciihex_string("no such process.");
3999           return SendPacket(return_message.c_str());
4000         }
4001         if (process_is_already_being_debugged (pid_attaching_to)) {
4002           DNBLogError("Tried to attach to process already being debugged");
4003           std::string return_message = "E96;";
4004           return_message += cstring_to_asciihex_string("tried to attach to "
4005                                            "process already being debugged");
4006           return SendPacket(return_message.c_str());
4007         }
4008         uid_t my_uid, process_uid;
4009         if (attach_failed_due_to_uid_mismatch (pid_attaching_to,
4010                                                my_uid, process_uid)) {
4011           std::string my_username = "uid " + std::to_string (my_uid);
4012           std::string process_username = "uid " + std::to_string (process_uid);
4013           struct passwd *pw = getpwuid (my_uid);
4014           if (pw && pw->pw_name) {
4015             my_username = pw->pw_name;
4016           }
4017           pw = getpwuid (process_uid);
4018           if (pw && pw->pw_name) {
4019             process_username = pw->pw_name;
4020           }
4021           DNBLogError("Tried to attach to process with uid mismatch");
4022           std::string return_message = "E96;";
4023           std::string msg = "tried to attach to process as user '"
4024                             + my_username + "' and process is running "
4025                             "as user '" + process_username + "'";
4026           return_message += cstring_to_asciihex_string(msg.c_str());
4027           return SendPacket(return_message.c_str());
4028         }
4029         if (!login_session_has_gui_access() && !developer_mode_enabled()) {
4030           DNBLogError("Developer mode is not enabled and this is a "
4031                       "non-interactive session");
4032           std::string return_message = "E96;";
4033           return_message += cstring_to_asciihex_string("developer mode is "
4034                                            "not enabled on this machine "
4035                                            "and this is a non-interactive "
4036                                            "debug session.");
4037           return SendPacket(return_message.c_str());
4038         }
4039         if (!login_session_has_gui_access()) {
4040           DNBLogError("This is a non-interactive session");
4041           std::string return_message = "E96;";
4042           return_message += cstring_to_asciihex_string("this is a "
4043                                            "non-interactive debug session, "
4044                                            "cannot get permission to debug "
4045                                            "processes.");
4046           return SendPacket(return_message.c_str());
4047         }
4048       }
4049 
4050       std::string error_explainer = "attach failed";
4051       if (err_str[0] != '\0') {
4052         // This is not a super helpful message for end users
4053         if (strcmp (err_str, "unable to start the exception thread") == 0) {
4054           snprintf (err_str, sizeof (err_str) - 1,
4055                     "Not allowed to attach to process.  Look in the console "
4056                     "messages (Console.app), near the debugserver entries, "
4057                     "when the attach failed.  The subsystem that denied "
4058                     "the attach permission will likely have logged an "
4059                     "informative message about why it was denied.");
4060           err_str[sizeof (err_str) - 1] = '\0';
4061         }
4062         error_explainer += " (";
4063         error_explainer += err_str;
4064         error_explainer += ")";
4065       }
4066       std::string default_return_msg = "E96;";
4067       default_return_msg += cstring_to_asciihex_string
4068                               (error_explainer.c_str());
4069       SendPacket (default_return_msg.c_str());
4070       DNBLogError("Attach failed: \"%s\".", err_str);
4071       return rnb_err;
4072     }
4073   }
4074 
4075   // All other failures come through here
4076   return HandlePacket_UNIMPLEMENTED(p);
4077 }
4078 
4079 /* 'T XX' -- status of thread
4080  Check if the specified thread is alive.
4081  The thread number is in hex?  */
4082 
HandlePacket_T(const char * p)4083 rnb_err_t RNBRemote::HandlePacket_T(const char *p) {
4084   p++;
4085   if (p == NULL || *p == '\0') {
4086     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4087                                   "No thread specified in T packet");
4088   }
4089   if (!m_ctx.HasValidProcessID()) {
4090     return SendPacket("E15");
4091   }
4092   errno = 0;
4093   nub_thread_t tid = strtoul(p, NULL, 16);
4094   if (errno != 0 && tid == 0) {
4095     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4096                                   "Could not parse thread number in T packet");
4097   }
4098 
4099   nub_state_t state = DNBThreadGetState(m_ctx.ProcessID(), tid);
4100   if (state == eStateInvalid || state == eStateExited ||
4101       state == eStateCrashed) {
4102     return SendPacket("E16");
4103   }
4104 
4105   return SendPacket("OK");
4106 }
4107 
HandlePacket_z(const char * p)4108 rnb_err_t RNBRemote::HandlePacket_z(const char *p) {
4109   if (p == NULL || *p == '\0')
4110     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4111                                   "No thread specified in z packet");
4112 
4113   if (!m_ctx.HasValidProcessID())
4114     return SendPacket("E15");
4115 
4116   char packet_cmd = *p++;
4117   char break_type = *p++;
4118 
4119   if (*p++ != ',')
4120     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4121                                   "Comma separator missing in z packet");
4122 
4123   char *c = NULL;
4124   nub_process_t pid = m_ctx.ProcessID();
4125   errno = 0;
4126   nub_addr_t addr = strtoull(p, &c, 16);
4127   if (errno != 0 && addr == 0)
4128     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4129                                   "Invalid address in z packet");
4130   p = c;
4131   if (*p++ != ',')
4132     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4133                                   "Comma separator missing in z packet");
4134 
4135   errno = 0;
4136   auto byte_size = strtoul(p, &c, 16);
4137   if (errno != 0 && byte_size == 0)
4138     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4139                                   "Invalid length in z packet");
4140 
4141   if (packet_cmd == 'Z') {
4142     // set
4143     switch (break_type) {
4144     case '0': // set software breakpoint
4145     case '1': // set hardware breakpoint
4146     {
4147       // gdb can send multiple Z packets for the same address and
4148       // these calls must be ref counted.
4149       bool hardware = (break_type == '1');
4150 
4151       if (DNBBreakpointSet(pid, addr, byte_size, hardware)) {
4152         // We successfully created a breakpoint, now lets full out
4153         // a ref count structure with the breakID and add it to our
4154         // map.
4155         return SendPacket("OK");
4156       } else {
4157         // We failed to set the software breakpoint
4158         return SendPacket("E09");
4159       }
4160     } break;
4161 
4162     case '2': // set write watchpoint
4163     case '3': // set read watchpoint
4164     case '4': // set access watchpoint
4165     {
4166       bool hardware = true;
4167       uint32_t watch_flags = 0;
4168       if (break_type == '2')
4169         watch_flags = WATCH_TYPE_WRITE;
4170       else if (break_type == '3')
4171         watch_flags = WATCH_TYPE_READ;
4172       else
4173         watch_flags = WATCH_TYPE_READ | WATCH_TYPE_WRITE;
4174 
4175       if (DNBWatchpointSet(pid, addr, byte_size, watch_flags, hardware)) {
4176         return SendPacket("OK");
4177       } else {
4178         // We failed to set the watchpoint
4179         return SendPacket("E09");
4180       }
4181     } break;
4182 
4183     default:
4184       break;
4185     }
4186   } else if (packet_cmd == 'z') {
4187     // remove
4188     switch (break_type) {
4189     case '0': // remove software breakpoint
4190     case '1': // remove hardware breakpoint
4191       if (DNBBreakpointClear(pid, addr)) {
4192         return SendPacket("OK");
4193       } else {
4194         return SendPacket("E08");
4195       }
4196       break;
4197 
4198     case '2': // remove write watchpoint
4199     case '3': // remove read watchpoint
4200     case '4': // remove access watchpoint
4201       if (DNBWatchpointClear(pid, addr)) {
4202         return SendPacket("OK");
4203       } else {
4204         return SendPacket("E08");
4205       }
4206       break;
4207 
4208     default:
4209       break;
4210     }
4211   }
4212   return HandlePacket_UNIMPLEMENTED(p);
4213 }
4214 
4215 // Extract the thread number from the thread suffix that might be appended to
4216 // thread specific packets. This will only be enabled if
4217 // m_thread_suffix_supported
4218 // is true.
ExtractThreadIDFromThreadSuffix(const char * p)4219 nub_thread_t RNBRemote::ExtractThreadIDFromThreadSuffix(const char *p) {
4220   if (m_thread_suffix_supported) {
4221     nub_thread_t tid = INVALID_NUB_THREAD;
4222     if (p) {
4223       const char *tid_cstr = strstr(p, "thread:");
4224       if (tid_cstr) {
4225         tid_cstr += strlen("thread:");
4226         tid = strtoul(tid_cstr, NULL, 16);
4227       }
4228     }
4229     return tid;
4230   }
4231   return GetCurrentThread();
4232 }
4233 
4234 /* 'p XX'
4235  print the contents of register X */
4236 
HandlePacket_p(const char * p)4237 rnb_err_t RNBRemote::HandlePacket_p(const char *p) {
4238   if (g_num_reg_entries == 0)
4239     InitializeRegisters();
4240 
4241   if (p == NULL || *p == '\0') {
4242     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4243                                   "No thread specified in p packet");
4244   }
4245   if (!m_ctx.HasValidProcessID()) {
4246     return SendPacket("E15");
4247   }
4248   nub_process_t pid = m_ctx.ProcessID();
4249   errno = 0;
4250   char *tid_cstr = NULL;
4251   uint32_t reg = static_cast<uint32_t>(strtoul(p + 1, &tid_cstr, 16));
4252   if (errno != 0 && reg == 0) {
4253     return HandlePacket_ILLFORMED(
4254         __FILE__, __LINE__, p, "Could not parse register number in p packet");
4255   }
4256 
4257   nub_thread_t tid = ExtractThreadIDFromThreadSuffix(tid_cstr);
4258   if (tid == INVALID_NUB_THREAD)
4259     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4260                                   "No thread specified in p packet");
4261 
4262   const register_map_entry_t *reg_entry;
4263 
4264   if (reg < g_num_reg_entries)
4265     reg_entry = &g_reg_entries[reg];
4266   else
4267     reg_entry = NULL;
4268 
4269   std::ostringstream ostrm;
4270   if (reg_entry == NULL) {
4271     DNBLogError(
4272         "RNBRemote::HandlePacket_p(%s): unknown register number %u requested\n",
4273         p, reg);
4274     ostrm << "00000000";
4275   } else if (reg_entry->nub_info.reg == (uint32_t)-1) {
4276     if (reg_entry->nub_info.size > 0) {
4277       std::basic_string<uint8_t> zeros(reg_entry->nub_info.size, '\0');
4278       append_hex_value(ostrm, zeros.data(), zeros.size(), false);
4279     }
4280   } else {
4281     register_value_in_hex_fixed_width(ostrm, pid, tid, reg_entry, NULL);
4282   }
4283   return SendPacket(ostrm.str());
4284 }
4285 
4286 /* 'Pnn=rrrrr'
4287  Set register number n to value r.
4288  n and r are hex strings.  */
4289 
HandlePacket_P(const char * p)4290 rnb_err_t RNBRemote::HandlePacket_P(const char *p) {
4291   if (g_num_reg_entries == 0)
4292     InitializeRegisters();
4293 
4294   if (p == NULL || *p == '\0') {
4295     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, "Empty P packet");
4296   }
4297   if (!m_ctx.HasValidProcessID()) {
4298     return SendPacket("E28");
4299   }
4300 
4301   nub_process_t pid = m_ctx.ProcessID();
4302 
4303   StdStringExtractor packet(p);
4304 
4305   const char cmd_char = packet.GetChar();
4306   // Register ID is always in big endian
4307   const uint32_t reg = packet.GetHexMaxU32(false, UINT32_MAX);
4308   const char equal_char = packet.GetChar();
4309 
4310   if (cmd_char != 'P')
4311     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4312                                   "Improperly formed P packet");
4313 
4314   if (reg == UINT32_MAX)
4315     return SendPacket("E29");
4316 
4317   if (equal_char != '=')
4318     return SendPacket("E30");
4319 
4320   const register_map_entry_t *reg_entry;
4321 
4322   if (reg >= g_num_reg_entries)
4323     return SendPacket("E47");
4324 
4325   reg_entry = &g_reg_entries[reg];
4326 
4327   if (reg_entry->nub_info.set == (uint32_t)-1 &&
4328       reg_entry->nub_info.reg == (uint32_t)-1) {
4329     DNBLogError(
4330         "RNBRemote::HandlePacket_P(%s): unknown register number %u requested\n",
4331         p, reg);
4332     return SendPacket("E48");
4333   }
4334 
4335   DNBRegisterValue reg_value;
4336   reg_value.info = reg_entry->nub_info;
4337   packet.GetHexBytes(reg_value.value.v_sint8, reg_entry->nub_info.size, 0xcc);
4338 
4339   nub_thread_t tid = ExtractThreadIDFromThreadSuffix(p);
4340   if (tid == INVALID_NUB_THREAD)
4341     return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4342                                   "No thread specified in p packet");
4343 
4344   if (!DNBThreadSetRegisterValueByID(pid, tid, reg_entry->nub_info.set,
4345                                      reg_entry->nub_info.reg, &reg_value)) {
4346     return SendPacket("E32");
4347   }
4348   return SendPacket("OK");
4349 }
4350 
4351 /* 'c [addr]'
4352  Continue, optionally from a specified address. */
4353 
HandlePacket_c(const char * p)4354 rnb_err_t RNBRemote::HandlePacket_c(const char *p) {
4355   const nub_process_t pid = m_ctx.ProcessID();
4356 
4357   if (pid == INVALID_NUB_PROCESS)
4358     return SendPacket("E23");
4359 
4360   DNBThreadResumeAction action = {INVALID_NUB_THREAD, eStateRunning, 0,
4361                                   INVALID_NUB_ADDRESS};
4362 
4363   if (*(p + 1) != '\0') {
4364     action.tid = GetContinueThread();
4365     errno = 0;
4366     action.addr = strtoull(p + 1, NULL, 16);
4367     if (errno != 0 && action.addr == 0)
4368       return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4369                                     "Could not parse address in c packet");
4370   }
4371 
4372   DNBThreadResumeActions thread_actions;
4373   thread_actions.Append(action);
4374   thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, 0);
4375   if (!DNBProcessResume(pid, thread_actions.GetFirst(),
4376                         thread_actions.GetSize()))
4377     return SendPacket("E25");
4378   // Don't send an "OK" packet; response is the stopped/exited message.
4379   return rnb_success;
4380 }
4381 
HandlePacket_MemoryRegionInfo(const char * p)4382 rnb_err_t RNBRemote::HandlePacket_MemoryRegionInfo(const char *p) {
4383   /* This packet will find memory attributes (e.g. readable, writable,
4384      executable, stack, jitted code)
4385      for the memory region containing a given address and return that
4386      information.
4387 
4388      Users of this packet must be prepared for three results:
4389 
4390          Region information is returned
4391          Region information is unavailable for this address because the address
4392      is in unmapped memory
4393          Region lookup cannot be performed on this platform or process is not
4394      yet launched
4395          This packet isn't implemented
4396 
4397      Examples of use:
4398         qMemoryRegionInfo:3a55140
4399         start:3a50000,size:100000,permissions:rwx
4400 
4401         qMemoryRegionInfo:0
4402         error:address in unmapped region
4403 
4404         qMemoryRegionInfo:3a551140   (on a different platform)
4405         error:region lookup cannot be performed
4406 
4407         qMemoryRegionInfo
4408         OK                   // this packet is implemented by the remote nub
4409   */
4410 
4411   p += sizeof("qMemoryRegionInfo") - 1;
4412   if (*p == '\0')
4413     return SendPacket("OK");
4414   if (*p++ != ':')
4415     return SendPacket("E67");
4416   if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X'))
4417     p += 2;
4418 
4419   errno = 0;
4420   uint64_t address = strtoul(p, NULL, 16);
4421   if (errno != 0 && address == 0) {
4422     return HandlePacket_ILLFORMED(
4423         __FILE__, __LINE__, p, "Invalid address in qMemoryRegionInfo packet");
4424   }
4425 
4426   DNBRegionInfo region_info = {0, 0, 0};
4427   DNBProcessMemoryRegionInfo(m_ctx.ProcessID(), address, &region_info);
4428   std::ostringstream ostrm;
4429 
4430   // start:3a50000,size:100000,permissions:rwx
4431   ostrm << "start:" << std::hex << region_info.addr << ';';
4432 
4433   if (region_info.size > 0)
4434     ostrm << "size:" << std::hex << region_info.size << ';';
4435 
4436   if (region_info.permissions) {
4437     ostrm << "permissions:";
4438 
4439     if (region_info.permissions & eMemoryPermissionsReadable)
4440       ostrm << 'r';
4441     if (region_info.permissions & eMemoryPermissionsWritable)
4442       ostrm << 'w';
4443     if (region_info.permissions & eMemoryPermissionsExecutable)
4444       ostrm << 'x';
4445     ostrm << ';';
4446   }
4447   return SendPacket(ostrm.str());
4448 }
4449 
4450 // qGetProfileData;scan_type:0xYYYYYYY
HandlePacket_GetProfileData(const char * p)4451 rnb_err_t RNBRemote::HandlePacket_GetProfileData(const char *p) {
4452   nub_process_t pid = m_ctx.ProcessID();
4453   if (pid == INVALID_NUB_PROCESS)
4454     return SendPacket("OK");
4455 
4456   StdStringExtractor packet(p += sizeof("qGetProfileData"));
4457   DNBProfileDataScanType scan_type = eProfileAll;
4458   std::string name;
4459   std::string value;
4460   while (packet.GetNameColonValue(name, value)) {
4461     if (name == "scan_type") {
4462       std::istringstream iss(value);
4463       uint32_t int_value = 0;
4464       if (iss >> std::hex >> int_value) {
4465         scan_type = (DNBProfileDataScanType)int_value;
4466       }
4467     }
4468   }
4469 
4470   std::string data = DNBProcessGetProfileData(pid, scan_type);
4471   if (!data.empty()) {
4472     return SendPacket(data.c_str());
4473   } else {
4474     return SendPacket("OK");
4475   }
4476 }
4477 
4478 // QSetEnableAsyncProfiling;enable:[0|1]:interval_usec:XXXXXX;scan_type:0xYYYYYYY
HandlePacket_SetEnableAsyncProfiling(const char * p)4479 rnb_err_t RNBRemote::HandlePacket_SetEnableAsyncProfiling(const char *p) {
4480   nub_process_t pid = m_ctx.ProcessID();
4481   if (pid == INVALID_NUB_PROCESS)
4482     return SendPacket("OK");
4483 
4484   StdStringExtractor packet(p += sizeof("QSetEnableAsyncProfiling"));
4485   bool enable = false;
4486   uint64_t interval_usec = 0;
4487   DNBProfileDataScanType scan_type = eProfileAll;
4488   std::string name;
4489   std::string value;
4490   while (packet.GetNameColonValue(name, value)) {
4491     if (name == "enable") {
4492       enable = strtoul(value.c_str(), NULL, 10) > 0;
4493     } else if (name == "interval_usec") {
4494       interval_usec = strtoul(value.c_str(), NULL, 10);
4495     } else if (name == "scan_type") {
4496       std::istringstream iss(value);
4497       uint32_t int_value = 0;
4498       if (iss >> std::hex >> int_value) {
4499         scan_type = (DNBProfileDataScanType)int_value;
4500       }
4501     }
4502   }
4503 
4504   if (interval_usec == 0) {
4505     enable = false;
4506   }
4507 
4508   DNBProcessSetEnableAsyncProfiling(pid, enable, interval_usec, scan_type);
4509   return SendPacket("OK");
4510 }
4511 
4512 // QEnableCompression:type:<COMPRESSION-TYPE>;minsize:<MINIMUM PACKET SIZE TO
4513 // COMPRESS>;
4514 //
4515 // type: must be a type previously reported by the qXfer:features:
4516 // SupportedCompressions list
4517 //
4518 // minsize: is optional; by default the qXfer:features:
4519 // DefaultCompressionMinSize value is used
4520 // debugserver may have a better idea of what a good minimum packet size to
4521 // compress is than lldb.
4522 
HandlePacket_QEnableCompression(const char * p)4523 rnb_err_t RNBRemote::HandlePacket_QEnableCompression(const char *p) {
4524   p += sizeof("QEnableCompression:") - 1;
4525 
4526   size_t new_compression_minsize = m_compression_minsize;
4527   const char *new_compression_minsize_str = strstr(p, "minsize:");
4528   if (new_compression_minsize_str) {
4529     new_compression_minsize_str += strlen("minsize:");
4530     errno = 0;
4531     new_compression_minsize = strtoul(new_compression_minsize_str, NULL, 10);
4532     if (errno != 0 || new_compression_minsize == ULONG_MAX) {
4533       new_compression_minsize = m_compression_minsize;
4534     }
4535   }
4536 
4537   if (strstr(p, "type:zlib-deflate;") != nullptr) {
4538     EnableCompressionNextSendPacket(compression_types::zlib_deflate);
4539     m_compression_minsize = new_compression_minsize;
4540     return SendPacket("OK");
4541   } else if (strstr(p, "type:lz4;") != nullptr) {
4542     EnableCompressionNextSendPacket(compression_types::lz4);
4543     m_compression_minsize = new_compression_minsize;
4544     return SendPacket("OK");
4545   } else if (strstr(p, "type:lzma;") != nullptr) {
4546     EnableCompressionNextSendPacket(compression_types::lzma);
4547     m_compression_minsize = new_compression_minsize;
4548     return SendPacket("OK");
4549   } else if (strstr(p, "type:lzfse;") != nullptr) {
4550     EnableCompressionNextSendPacket(compression_types::lzfse);
4551     m_compression_minsize = new_compression_minsize;
4552     return SendPacket("OK");
4553   }
4554 
4555   return SendPacket("E88");
4556 }
4557 
HandlePacket_qSpeedTest(const char * p)4558 rnb_err_t RNBRemote::HandlePacket_qSpeedTest(const char *p) {
4559   p += strlen("qSpeedTest:response_size:");
4560   char *end = NULL;
4561   errno = 0;
4562   uint64_t response_size = ::strtoul(p, &end, 16);
4563   if (errno != 0)
4564     return HandlePacket_ILLFORMED(
4565         __FILE__, __LINE__, p,
4566         "Didn't find response_size value at right offset");
4567   else if (*end == ';') {
4568     static char g_data[4 * 1024 * 1024 + 16] = "data:";
4569     memset(g_data + 5, 'a', response_size);
4570     g_data[response_size + 5] = '\0';
4571     return SendPacket(g_data);
4572   } else {
4573     return SendPacket("E79");
4574   }
4575 }
4576 
HandlePacket_WatchpointSupportInfo(const char * p)4577 rnb_err_t RNBRemote::HandlePacket_WatchpointSupportInfo(const char *p) {
4578   /* This packet simply returns the number of supported hardware watchpoints.
4579 
4580      Examples of use:
4581         qWatchpointSupportInfo:
4582         num:4
4583 
4584         qWatchpointSupportInfo
4585         OK                   // this packet is implemented by the remote nub
4586   */
4587 
4588   p += sizeof("qWatchpointSupportInfo") - 1;
4589   if (*p == '\0')
4590     return SendPacket("OK");
4591   if (*p++ != ':')
4592     return SendPacket("E67");
4593 
4594   errno = 0;
4595   uint32_t num = DNBWatchpointGetNumSupportedHWP(m_ctx.ProcessID());
4596   std::ostringstream ostrm;
4597 
4598   // size:4
4599   ostrm << "num:" << std::dec << num << ';';
4600   return SendPacket(ostrm.str());
4601 }
4602 
4603 /* 'C sig [;addr]'
4604  Resume with signal sig, optionally at address addr.  */
4605 
HandlePacket_C(const char * p)4606 rnb_err_t RNBRemote::HandlePacket_C(const char *p) {
4607   const nub_process_t pid = m_ctx.ProcessID();
4608 
4609   if (pid == INVALID_NUB_PROCESS)
4610     return SendPacket("E36");
4611 
4612   DNBThreadResumeAction action = {INVALID_NUB_THREAD, eStateRunning, 0,
4613                                   INVALID_NUB_ADDRESS};
4614   int process_signo = -1;
4615   if (*(p + 1) != '\0') {
4616     action.tid = GetContinueThread();
4617     char *end = NULL;
4618     errno = 0;
4619     process_signo = static_cast<int>(strtoul(p + 1, &end, 16));
4620     if (errno != 0)
4621       return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4622                                     "Could not parse signal in C packet");
4623     else if (*end == ';') {
4624       errno = 0;
4625       action.addr = strtoull(end + 1, NULL, 16);
4626       if (errno != 0 && action.addr == 0)
4627         return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4628                                       "Could not parse address in C packet");
4629     }
4630   }
4631 
4632   DNBThreadResumeActions thread_actions;
4633   thread_actions.Append(action);
4634   thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, action.signal);
4635   if (!DNBProcessSignal(pid, process_signo))
4636     return SendPacket("E52");
4637   if (!DNBProcessResume(pid, thread_actions.GetFirst(),
4638                         thread_actions.GetSize()))
4639     return SendPacket("E38");
4640   /* Don't send an "OK" packet; response is the stopped/exited message.  */
4641   return rnb_success;
4642 }
4643 
4644 // 'D' packet
4645 // Detach from gdb.
HandlePacket_D(const char * p)4646 rnb_err_t RNBRemote::HandlePacket_D(const char *p) {
4647   if (m_ctx.HasValidProcessID()) {
4648     if (DNBProcessDetach(m_ctx.ProcessID()))
4649       SendPacket("OK");
4650     else
4651       SendPacket("E");
4652   } else {
4653     SendPacket("E");
4654   }
4655   return rnb_success;
4656 }
4657 
4658 /* 'k'
4659  Kill the inferior process.  */
4660 
HandlePacket_k(const char * p)4661 rnb_err_t RNBRemote::HandlePacket_k(const char *p) {
4662   DNBLog("Got a 'k' packet, killing the inferior process.");
4663   // No response to should be sent to the kill packet
4664   if (m_ctx.HasValidProcessID())
4665     DNBProcessKill(m_ctx.ProcessID());
4666   SendPacket("X09");
4667   return rnb_success;
4668 }
4669 
HandlePacket_stop_process(const char * p)4670 rnb_err_t RNBRemote::HandlePacket_stop_process(const char *p) {
4671 //#define TEST_EXIT_ON_INTERRUPT // This should only be uncommented to test
4672 //exiting on interrupt
4673 #if defined(TEST_EXIT_ON_INTERRUPT)
4674   rnb_err_t err = HandlePacket_k(p);
4675   m_comm.Disconnect(true);
4676   return err;
4677 #else
4678   if (!DNBProcessInterrupt(m_ctx.ProcessID())) {
4679     // If we failed to interrupt the process, then send a stop
4680     // reply packet as the process was probably already stopped
4681     DNBLogThreaded("RNBRemote::HandlePacket_stop_process() sending extra stop "
4682                    "reply because DNBProcessInterrupt returned false");
4683     HandlePacket_last_signal(NULL);
4684   }
4685   return rnb_success;
4686 #endif
4687 }
4688 
4689 /* 's'
4690  Step the inferior process.  */
4691 
HandlePacket_s(const char * p)4692 rnb_err_t RNBRemote::HandlePacket_s(const char *p) {
4693   const nub_process_t pid = m_ctx.ProcessID();
4694   if (pid == INVALID_NUB_PROCESS)
4695     return SendPacket("E32");
4696 
4697   // Hardware supported stepping not supported on arm
4698   nub_thread_t tid = GetContinueThread();
4699   if (tid == 0 || tid == (nub_thread_t)-1)
4700     tid = GetCurrentThread();
4701 
4702   if (tid == INVALID_NUB_THREAD)
4703     return SendPacket("E33");
4704 
4705   DNBThreadResumeActions thread_actions;
4706   thread_actions.AppendAction(tid, eStateStepping);
4707 
4708   // Make all other threads stop when we are stepping
4709   thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
4710   if (!DNBProcessResume(pid, thread_actions.GetFirst(),
4711                         thread_actions.GetSize()))
4712     return SendPacket("E49");
4713   // Don't send an "OK" packet; response is the stopped/exited message.
4714   return rnb_success;
4715 }
4716 
4717 /* 'S sig [;addr]'
4718  Step with signal sig, optionally at address addr.  */
4719 
HandlePacket_S(const char * p)4720 rnb_err_t RNBRemote::HandlePacket_S(const char *p) {
4721   const nub_process_t pid = m_ctx.ProcessID();
4722   if (pid == INVALID_NUB_PROCESS)
4723     return SendPacket("E36");
4724 
4725   DNBThreadResumeAction action = {INVALID_NUB_THREAD, eStateStepping, 0,
4726                                   INVALID_NUB_ADDRESS};
4727 
4728   if (*(p + 1) != '\0') {
4729     char *end = NULL;
4730     errno = 0;
4731     action.signal = static_cast<int>(strtoul(p + 1, &end, 16));
4732     if (errno != 0)
4733       return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4734                                     "Could not parse signal in S packet");
4735     else if (*end == ';') {
4736       errno = 0;
4737       action.addr = strtoull(end + 1, NULL, 16);
4738       if (errno != 0 && action.addr == 0) {
4739         return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
4740                                       "Could not parse address in S packet");
4741       }
4742     }
4743   }
4744 
4745   action.tid = GetContinueThread();
4746   if (action.tid == 0 || action.tid == (nub_thread_t)-1)
4747     return SendPacket("E40");
4748 
4749   nub_state_t tstate = DNBThreadGetState(pid, action.tid);
4750   if (tstate == eStateInvalid || tstate == eStateExited)
4751     return SendPacket("E37");
4752 
4753   DNBThreadResumeActions thread_actions;
4754   thread_actions.Append(action);
4755 
4756   // Make all other threads stop when we are stepping
4757   thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
4758   if (!DNBProcessResume(pid, thread_actions.GetFirst(),
4759                         thread_actions.GetSize()))
4760     return SendPacket("E39");
4761 
4762   // Don't send an "OK" packet; response is the stopped/exited message.
4763   return rnb_success;
4764 }
4765 
GetArchName(const uint32_t cputype,const uint32_t cpusubtype)4766 static const char *GetArchName(const uint32_t cputype,
4767                                const uint32_t cpusubtype) {
4768   switch (cputype) {
4769   case CPU_TYPE_ARM:
4770     switch (cpusubtype) {
4771     case 5:
4772       return "armv4";
4773     case 6:
4774       return "armv6";
4775     case 7:
4776       return "armv5t";
4777     case 8:
4778       return "xscale";
4779     case 9:
4780       return "armv7";
4781     case 10:
4782       return "armv7f";
4783     case 11:
4784       return "armv7s";
4785     case 12:
4786       return "armv7k";
4787     case 14:
4788       return "armv6m";
4789     case 15:
4790       return "armv7m";
4791     case 16:
4792       return "armv7em";
4793     default:
4794       return "arm";
4795     }
4796     break;
4797   case CPU_TYPE_ARM64:
4798     return "arm64";
4799   case CPU_TYPE_ARM64_32:
4800     return "arm64_32";
4801   case CPU_TYPE_I386:
4802     return "i386";
4803   case CPU_TYPE_X86_64:
4804     switch (cpusubtype) {
4805     default:
4806       return "x86_64";
4807     case 8:
4808       return "x86_64h";
4809     }
4810     break;
4811   }
4812   return NULL;
4813 }
4814 
GetHostCPUType(uint32_t & cputype,uint32_t & cpusubtype,uint32_t & is_64_bit_capable,bool & promoted_to_64)4815 static bool GetHostCPUType(uint32_t &cputype, uint32_t &cpusubtype,
4816                            uint32_t &is_64_bit_capable, bool &promoted_to_64) {
4817   static uint32_t g_host_cputype = 0;
4818   static uint32_t g_host_cpusubtype = 0;
4819   static uint32_t g_is_64_bit_capable = 0;
4820   static bool g_promoted_to_64 = false;
4821 
4822   if (g_host_cputype == 0) {
4823     g_promoted_to_64 = false;
4824     size_t len = sizeof(uint32_t);
4825     if (::sysctlbyname("hw.cputype", &g_host_cputype, &len, NULL, 0) == 0) {
4826       len = sizeof(uint32_t);
4827       if (::sysctlbyname("hw.cpu64bit_capable", &g_is_64_bit_capable, &len,
4828                          NULL, 0) == 0) {
4829         if (g_is_64_bit_capable && ((g_host_cputype & CPU_ARCH_ABI64) == 0)) {
4830           g_promoted_to_64 = true;
4831           g_host_cputype |= CPU_ARCH_ABI64;
4832         }
4833       }
4834 #if defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
4835       if (g_host_cputype == CPU_TYPE_ARM64 && sizeof (void*) == 4)
4836         g_host_cputype = CPU_TYPE_ARM64_32;
4837 #endif
4838     }
4839 
4840     len = sizeof(uint32_t);
4841     if (::sysctlbyname("hw.cpusubtype", &g_host_cpusubtype, &len, NULL, 0) ==
4842         0) {
4843       if (g_promoted_to_64 && g_host_cputype == CPU_TYPE_X86_64 &&
4844           g_host_cpusubtype == CPU_SUBTYPE_486)
4845         g_host_cpusubtype = CPU_SUBTYPE_X86_64_ALL;
4846     }
4847 #if defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
4848     // on arm64_32 devices, the machine's native cpu type is
4849     // CPU_TYPE_ARM64 and subtype is 2 indicating arm64e.
4850     // But we change the cputype to CPU_TYPE_ARM64_32 because
4851     // the user processes are all ILP32 processes today.
4852     // We also need to rewrite the cpusubtype so we vend
4853     // a valid cputype + cpusubtype combination.
4854     if (g_host_cputype == CPU_TYPE_ARM64_32)
4855       g_host_cpusubtype = CPU_SUBTYPE_ARM64_32_V8;
4856 #endif
4857   }
4858 
4859   cputype = g_host_cputype;
4860   cpusubtype = g_host_cpusubtype;
4861   is_64_bit_capable = g_is_64_bit_capable;
4862   promoted_to_64 = g_promoted_to_64;
4863   return g_host_cputype != 0;
4864 }
4865 
GetAddressingBits(uint32_t & addressing_bits)4866 static bool GetAddressingBits(uint32_t &addressing_bits) {
4867   static uint32_t g_addressing_bits = 0;
4868   static bool g_tried_addressing_bits_syscall = false;
4869   if (g_tried_addressing_bits_syscall == false) {
4870     size_t len = sizeof (uint32_t);
4871     if (::sysctlbyname("machdep.virtual_address_size",
4872           &g_addressing_bits, &len, NULL, 0) != 0) {
4873       g_addressing_bits = 0;
4874     }
4875   }
4876   g_tried_addressing_bits_syscall = true;
4877   addressing_bits = g_addressing_bits;
4878   if (addressing_bits > 0)
4879     return true;
4880   else
4881     return false;
4882 }
4883 
HandlePacket_qHostInfo(const char * p)4884 rnb_err_t RNBRemote::HandlePacket_qHostInfo(const char *p) {
4885   std::ostringstream strm;
4886 
4887   uint32_t cputype = 0;
4888   uint32_t cpusubtype = 0;
4889   uint32_t is_64_bit_capable = 0;
4890   bool promoted_to_64 = false;
4891   if (GetHostCPUType(cputype, cpusubtype, is_64_bit_capable, promoted_to_64)) {
4892     strm << "cputype:" << std::dec << cputype << ';';
4893     strm << "cpusubtype:" << std::dec << cpusubtype << ';';
4894   }
4895 
4896   uint32_t addressing_bits = 0;
4897   if (GetAddressingBits(addressing_bits)) {
4898     strm << "addressing_bits:" << std::dec << addressing_bits << ';';
4899   }
4900 
4901   // The OS in the triple should be "ios" or "macosx" which doesn't match our
4902   // "Darwin" which gets returned from "kern.ostype", so we need to hardcode
4903   // this for now.
4904   if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64
4905       || cputype == CPU_TYPE_ARM64_32) {
4906 #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
4907     strm << "ostype:tvos;";
4908 #elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
4909     strm << "ostype:watchos;";
4910 #elif defined(TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1
4911     strm << "ostype:bridgeos;";
4912 #elif defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1
4913     strm << "ostype:macosx;";
4914 #else
4915     strm << "ostype:ios;";
4916 #endif
4917 
4918     // On armv7 we use "synchronous" watchpoints which means the exception is
4919     // delivered before the instruction executes.
4920     strm << "watchpoint_exceptions_received:before;";
4921   } else {
4922     strm << "ostype:macosx;";
4923     strm << "watchpoint_exceptions_received:after;";
4924   }
4925   //    char ostype[64];
4926   //    len = sizeof(ostype);
4927   //    if (::sysctlbyname("kern.ostype", &ostype, &len, NULL, 0) == 0)
4928   //    {
4929   //        len = strlen(ostype);
4930   //        std::transform (ostype, ostype + len, ostype, tolower);
4931   //        strm << "ostype:" << std::dec << ostype << ';';
4932   //    }
4933 
4934   strm << "vendor:apple;";
4935 
4936   uint64_t major, minor, patch;
4937   if (DNBGetOSVersionNumbers(&major, &minor, &patch)) {
4938     strm << "os_version:" << major << "." << minor;
4939     if (patch != UINT64_MAX)
4940       strm << "." << patch;
4941     strm << ";";
4942   }
4943 
4944   std::string maccatalyst_version = DNBGetMacCatalystVersionString();
4945   if (!maccatalyst_version.empty() &&
4946       std::all_of(maccatalyst_version.begin(), maccatalyst_version.end(),
4947                   [](char c) { return (c >= '0' && c <= '9') || c == '.'; }))
4948     strm << "maccatalyst_version:" << maccatalyst_version << ";";
4949 
4950 #if defined(__LITTLE_ENDIAN__)
4951   strm << "endian:little;";
4952 #elif defined(__BIG_ENDIAN__)
4953   strm << "endian:big;";
4954 #elif defined(__PDP_ENDIAN__)
4955   strm << "endian:pdp;";
4956 #endif
4957 
4958   if (promoted_to_64)
4959     strm << "ptrsize:8;";
4960   else
4961     strm << "ptrsize:" << std::dec << sizeof(void *) << ';';
4962 
4963 #if defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
4964   strm << "default_packet_timeout:10;";
4965 #endif
4966 
4967   return SendPacket(strm.str());
4968 }
4969 
XMLElementStart(std::ostringstream & s,uint32_t indent,const char * name,bool has_attributes)4970 void XMLElementStart(std::ostringstream &s, uint32_t indent, const char *name,
4971                      bool has_attributes) {
4972   if (indent)
4973     s << INDENT_WITH_SPACES(indent);
4974   s << '<' << name;
4975   if (!has_attributes)
4976     s << '>' << std::endl;
4977 }
4978 
XMLElementStartEndAttributes(std::ostringstream & s,bool empty)4979 void XMLElementStartEndAttributes(std::ostringstream &s, bool empty) {
4980   if (empty)
4981     s << '/';
4982   s << '>' << std::endl;
4983 }
4984 
XMLElementEnd(std::ostringstream & s,uint32_t indent,const char * name)4985 void XMLElementEnd(std::ostringstream &s, uint32_t indent, const char *name) {
4986   if (indent)
4987     s << INDENT_WITH_SPACES(indent);
4988   s << '<' << '/' << name << '>' << std::endl;
4989 }
4990 
XMLElementWithStringValue(std::ostringstream & s,uint32_t indent,const char * name,const char * value,bool close=true)4991 void XMLElementWithStringValue(std::ostringstream &s, uint32_t indent,
4992                                const char *name, const char *value,
4993                                bool close = true) {
4994   if (value) {
4995     if (indent)
4996       s << INDENT_WITH_SPACES(indent);
4997     s << '<' << name << '>' << value;
4998     if (close)
4999       XMLElementEnd(s, 0, name);
5000   }
5001 }
5002 
XMLElementWithUnsignedValue(std::ostringstream & s,uint32_t indent,const char * name,uint64_t value,bool close=true)5003 void XMLElementWithUnsignedValue(std::ostringstream &s, uint32_t indent,
5004                                  const char *name, uint64_t value,
5005                                  bool close = true) {
5006   if (indent)
5007     s << INDENT_WITH_SPACES(indent);
5008 
5009   s << '<' << name << '>' << DECIMAL << value;
5010   if (close)
5011     XMLElementEnd(s, 0, name);
5012 }
5013 
XMLAttributeString(std::ostringstream & s,const char * name,const char * value,const char * default_value=NULL)5014 void XMLAttributeString(std::ostringstream &s, const char *name,
5015                         const char *value, const char *default_value = NULL) {
5016   if (value) {
5017     if (default_value && strcmp(value, default_value) == 0)
5018       return; // No need to emit the attribute because it matches the default
5019               // value
5020     s << ' ' << name << "=\"" << value << "\"";
5021   }
5022 }
5023 
XMLAttributeUnsignedDecimal(std::ostringstream & s,const char * name,uint64_t value)5024 void XMLAttributeUnsignedDecimal(std::ostringstream &s, const char *name,
5025                                  uint64_t value) {
5026   s << ' ' << name << "=\"" << DECIMAL << value << "\"";
5027 }
5028 
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)5029 void GenerateTargetXMLRegister(std::ostringstream &s, const uint32_t reg_num,
5030                                nub_size_t num_reg_sets,
5031                                const DNBRegisterSetInfo *reg_set_info,
5032                                const register_map_entry_t &reg) {
5033   const char *default_lldb_encoding = "uint";
5034   const char *lldb_encoding = default_lldb_encoding;
5035   const char *gdb_group = "general";
5036   const char *default_gdb_type = "int";
5037   const char *gdb_type = default_gdb_type;
5038   const char *default_lldb_format = "hex";
5039   const char *lldb_format = default_lldb_format;
5040   const char *lldb_set = NULL;
5041 
5042   switch (reg.nub_info.type) {
5043   case Uint:
5044     lldb_encoding = "uint";
5045     break;
5046   case Sint:
5047     lldb_encoding = "sint";
5048     break;
5049   case IEEE754:
5050     lldb_encoding = "ieee754";
5051     if (reg.nub_info.set > 0)
5052       gdb_group = "float";
5053     break;
5054   case Vector:
5055     lldb_encoding = "vector";
5056     if (reg.nub_info.set > 0)
5057       gdb_group = "vector";
5058     break;
5059   }
5060 
5061   switch (reg.nub_info.format) {
5062   case Binary:
5063     lldb_format = "binary";
5064     break;
5065   case Decimal:
5066     lldb_format = "decimal";
5067     break;
5068   case Hex:
5069     lldb_format = "hex";
5070     break;
5071   case Float:
5072     gdb_type = "float";
5073     lldb_format = "float";
5074     break;
5075   case VectorOfSInt8:
5076     gdb_type = "float";
5077     lldb_format = "vector-sint8";
5078     break;
5079   case VectorOfUInt8:
5080     gdb_type = "float";
5081     lldb_format = "vector-uint8";
5082     break;
5083   case VectorOfSInt16:
5084     gdb_type = "float";
5085     lldb_format = "vector-sint16";
5086     break;
5087   case VectorOfUInt16:
5088     gdb_type = "float";
5089     lldb_format = "vector-uint16";
5090     break;
5091   case VectorOfSInt32:
5092     gdb_type = "float";
5093     lldb_format = "vector-sint32";
5094     break;
5095   case VectorOfUInt32:
5096     gdb_type = "float";
5097     lldb_format = "vector-uint32";
5098     break;
5099   case VectorOfFloat32:
5100     gdb_type = "float";
5101     lldb_format = "vector-float32";
5102     break;
5103   case VectorOfUInt128:
5104     gdb_type = "float";
5105     lldb_format = "vector-uint128";
5106     break;
5107   };
5108   if (reg_set_info && reg.nub_info.set < num_reg_sets)
5109     lldb_set = reg_set_info[reg.nub_info.set].name;
5110 
5111   uint32_t indent = 2;
5112 
5113   XMLElementStart(s, indent, "reg", true);
5114   XMLAttributeString(s, "name", reg.nub_info.name);
5115   XMLAttributeUnsignedDecimal(s, "regnum", reg_num);
5116   XMLAttributeUnsignedDecimal(s, "offset", reg.offset);
5117   XMLAttributeUnsignedDecimal(s, "bitsize", reg.nub_info.size * 8);
5118   XMLAttributeString(s, "group", gdb_group);
5119   XMLAttributeString(s, "type", gdb_type, default_gdb_type);
5120   XMLAttributeString(s, "altname", reg.nub_info.alt);
5121   XMLAttributeString(s, "encoding", lldb_encoding, default_lldb_encoding);
5122   XMLAttributeString(s, "format", lldb_format, default_lldb_format);
5123   XMLAttributeUnsignedDecimal(s, "group_id", reg.nub_info.set);
5124   if (reg.nub_info.reg_ehframe != INVALID_NUB_REGNUM)
5125     XMLAttributeUnsignedDecimal(s, "ehframe_regnum", reg.nub_info.reg_ehframe);
5126   if (reg.nub_info.reg_dwarf != INVALID_NUB_REGNUM)
5127     XMLAttributeUnsignedDecimal(s, "dwarf_regnum", reg.nub_info.reg_dwarf);
5128 
5129   const char *lldb_generic = NULL;
5130   switch (reg.nub_info.reg_generic) {
5131   case GENERIC_REGNUM_FP:
5132     lldb_generic = "fp";
5133     break;
5134   case GENERIC_REGNUM_PC:
5135     lldb_generic = "pc";
5136     break;
5137   case GENERIC_REGNUM_SP:
5138     lldb_generic = "sp";
5139     break;
5140   case GENERIC_REGNUM_RA:
5141     lldb_generic = "ra";
5142     break;
5143   case GENERIC_REGNUM_FLAGS:
5144     lldb_generic = "flags";
5145     break;
5146   case GENERIC_REGNUM_ARG1:
5147     lldb_generic = "arg1";
5148     break;
5149   case GENERIC_REGNUM_ARG2:
5150     lldb_generic = "arg2";
5151     break;
5152   case GENERIC_REGNUM_ARG3:
5153     lldb_generic = "arg3";
5154     break;
5155   case GENERIC_REGNUM_ARG4:
5156     lldb_generic = "arg4";
5157     break;
5158   case GENERIC_REGNUM_ARG5:
5159     lldb_generic = "arg5";
5160     break;
5161   case GENERIC_REGNUM_ARG6:
5162     lldb_generic = "arg6";
5163     break;
5164   case GENERIC_REGNUM_ARG7:
5165     lldb_generic = "arg7";
5166     break;
5167   case GENERIC_REGNUM_ARG8:
5168     lldb_generic = "arg8";
5169     break;
5170   default:
5171     break;
5172   }
5173   XMLAttributeString(s, "generic", lldb_generic);
5174 
5175   bool empty = reg.value_regnums.empty() && reg.invalidate_regnums.empty();
5176   if (!empty) {
5177     if (!reg.value_regnums.empty()) {
5178       std::ostringstream regnums;
5179       bool first = true;
5180       regnums << DECIMAL;
5181       for (auto regnum : reg.value_regnums) {
5182         if (!first)
5183           regnums << ',';
5184         regnums << regnum;
5185         first = false;
5186       }
5187       XMLAttributeString(s, "value_regnums", regnums.str().c_str());
5188     }
5189 
5190     if (!reg.invalidate_regnums.empty()) {
5191       std::ostringstream regnums;
5192       bool first = true;
5193       regnums << DECIMAL;
5194       for (auto regnum : reg.invalidate_regnums) {
5195         if (!first)
5196           regnums << ',';
5197         regnums << regnum;
5198         first = false;
5199       }
5200       XMLAttributeString(s, "invalidate_regnums", regnums.str().c_str());
5201     }
5202   }
5203   XMLElementStartEndAttributes(s, true);
5204 }
5205 
GenerateTargetXMLRegisters(std::ostringstream & s)5206 void GenerateTargetXMLRegisters(std::ostringstream &s) {
5207   nub_size_t num_reg_sets = 0;
5208   const DNBRegisterSetInfo *reg_sets = DNBGetRegisterSetInfo(&num_reg_sets);
5209 
5210   uint32_t cputype = DNBGetRegisterCPUType();
5211   if (cputype) {
5212     XMLElementStart(s, 0, "feature", true);
5213     std::ostringstream name_strm;
5214     name_strm << "com.apple.debugserver." << GetArchName(cputype, 0);
5215     XMLAttributeString(s, "name", name_strm.str().c_str());
5216     XMLElementStartEndAttributes(s, false);
5217     for (uint32_t reg_num = 0; reg_num < g_num_reg_entries; ++reg_num)
5218     //        for (const auto &reg: g_dynamic_register_map)
5219     {
5220       GenerateTargetXMLRegister(s, reg_num, num_reg_sets, reg_sets,
5221                                 g_reg_entries[reg_num]);
5222     }
5223     XMLElementEnd(s, 0, "feature");
5224 
5225     if (num_reg_sets > 0) {
5226       XMLElementStart(s, 0, "groups", false);
5227       for (uint32_t set = 1; set < num_reg_sets; ++set) {
5228         XMLElementStart(s, 2, "group", true);
5229         XMLAttributeUnsignedDecimal(s, "id", set);
5230         XMLAttributeString(s, "name", reg_sets[set].name);
5231         XMLElementStartEndAttributes(s, true);
5232       }
5233       XMLElementEnd(s, 0, "groups");
5234     }
5235   }
5236 }
5237 
5238 static const char *g_target_xml_header = R"(<?xml version="1.0"?>
5239 <target version="1.0">)";
5240 
5241 static const char *g_target_xml_footer = "</target>";
5242 
5243 static std::string g_target_xml;
5244 
UpdateTargetXML()5245 void UpdateTargetXML() {
5246   std::ostringstream s;
5247   s << g_target_xml_header << std::endl;
5248 
5249   // Set the architecture
5250   //
5251   // On raw targets (no OS, vendor info), I've seen replies like
5252   // <architecture>i386:x86-64</architecture> (for x86_64 systems - from vmware)
5253   // <architecture>arm</architecture> (for an unspecified arm device - from a Segger JLink)
5254   // For good interop, I'm not sure what's expected here.  e.g. will anyone understand
5255   // <architecture>x86_64</architecture> ? Or is i386:x86_64 the expected phrasing?
5256   //
5257   // s << "<architecture>" << arch "</architecture>" << std::endl;
5258 
5259   // Set the OSABI
5260   // s << "<osabi>abi-name</osabi>"
5261 
5262   GenerateTargetXMLRegisters(s);
5263 
5264   s << g_target_xml_footer << std::endl;
5265 
5266   // Save the XML output in case it gets retrieved in chunks
5267   g_target_xml = s.str();
5268 }
5269 
HandlePacket_qXfer(const char * command)5270 rnb_err_t RNBRemote::HandlePacket_qXfer(const char *command) {
5271   const char *p = command;
5272   p += strlen("qXfer:");
5273   const char *sep = strchr(p, ':');
5274   if (sep) {
5275     std::string object(p, sep - p); // "auxv", "backtrace", "features", etc
5276     p = sep + 1;
5277     sep = strchr(p, ':');
5278     if (sep) {
5279       std::string rw(p, sep - p); // "read" or "write"
5280       p = sep + 1;
5281       sep = strchr(p, ':');
5282       if (sep) {
5283         std::string annex(p, sep - p); // "read" or "write"
5284 
5285         p = sep + 1;
5286         sep = strchr(p, ',');
5287         if (sep) {
5288           std::string offset_str(p, sep - p); // read the length as a string
5289           p = sep + 1;
5290           std::string length_str(p); // read the offset as a string
5291           char *end = nullptr;
5292           const uint64_t offset = strtoul(offset_str.c_str(), &end,
5293                                           16); // convert offset_str to a offset
5294           if (*end == '\0') {
5295             const uint64_t length = strtoul(
5296                 length_str.c_str(), &end, 16); // convert length_str to a length
5297             if (*end == '\0') {
5298               if (object == "features" && rw == "read" &&
5299                   annex == "target.xml") {
5300                 std::ostringstream xml_out;
5301 
5302                 if (offset == 0) {
5303                   InitializeRegisters(true);
5304 
5305                   UpdateTargetXML();
5306                   if (g_target_xml.empty())
5307                     return SendPacket("E83");
5308 
5309                   if (length > g_target_xml.size()) {
5310                     xml_out << 'l'; // No more data
5311                     xml_out << binary_encode_string(g_target_xml);
5312                   } else {
5313                     xml_out << 'm'; // More data needs to be read with a
5314                                     // subsequent call
5315                     xml_out << binary_encode_string(
5316                         std::string(g_target_xml, offset, length));
5317                   }
5318                 } else {
5319                   // Retrieving target XML in chunks
5320                   if (offset < g_target_xml.size()) {
5321                     std::string chunk(g_target_xml, offset, length);
5322                     if (chunk.size() < length)
5323                       xml_out << 'l'; // No more data
5324                     else
5325                       xml_out << 'm'; // More data needs to be read with a
5326                                       // subsequent call
5327                     xml_out << binary_encode_string(chunk.data());
5328                   }
5329                 }
5330                 return SendPacket(xml_out.str());
5331               }
5332               // Well formed, put not supported
5333               return HandlePacket_UNIMPLEMENTED(command);
5334             }
5335           }
5336         }
5337       } else {
5338         SendPacket("E85");
5339       }
5340     } else {
5341       SendPacket("E86");
5342     }
5343   }
5344   return SendPacket("E82");
5345 }
5346 
HandlePacket_qGDBServerVersion(const char * p)5347 rnb_err_t RNBRemote::HandlePacket_qGDBServerVersion(const char *p) {
5348   std::ostringstream strm;
5349 
5350 #if defined(DEBUGSERVER_PROGRAM_NAME)
5351   strm << "name:" DEBUGSERVER_PROGRAM_NAME ";";
5352 #else
5353   strm << "name:debugserver;";
5354 #endif
5355   strm << "version:" << DEBUGSERVER_VERSION_NUM << ";";
5356 
5357   return SendPacket(strm.str());
5358 }
5359 
5360 // A helper function that retrieves a single integer value from
5361 // a one-level-deep JSON dictionary of key-value pairs.  e.g.
5362 // jThreadExtendedInfo:{"plo_pthread_tsd_base_address_offset":0,"plo_pthread_tsd_base_offset":224,"plo_pthread_tsd_entry_size":8,"thread":144305}]
5363 //
get_integer_value_for_key_name_from_json(const char * key,const char * json_string)5364 uint64_t get_integer_value_for_key_name_from_json(const char *key,
5365                                                   const char *json_string) {
5366   uint64_t retval = INVALID_NUB_ADDRESS;
5367   std::string key_with_quotes = "\"";
5368   key_with_quotes += key;
5369   key_with_quotes += "\"";
5370   const char *c = strstr(json_string, key_with_quotes.c_str());
5371   if (c) {
5372     c += key_with_quotes.size();
5373 
5374     while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5375       c++;
5376 
5377     if (*c == ':') {
5378       c++;
5379 
5380       while (*c != '\0' &&
5381              (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5382         c++;
5383 
5384       errno = 0;
5385       retval = strtoul(c, NULL, 10);
5386       if (errno != 0) {
5387         retval = INVALID_NUB_ADDRESS;
5388       }
5389     }
5390   }
5391   return retval;
5392 }
5393 
5394 // A helper function that retrieves a boolean value from
5395 // a one-level-deep JSON dictionary of key-value pairs.  e.g.
5396 // jGetLoadedDynamicLibrariesInfos:{"fetch_all_solibs":true}]
5397 
5398 // Returns true if it was able to find the key name, and sets the 'value'
5399 // argument to the value found.
5400 
get_boolean_value_for_key_name_from_json(const char * key,const char * json_string,bool & value)5401 bool get_boolean_value_for_key_name_from_json(const char *key,
5402                                               const char *json_string,
5403                                               bool &value) {
5404   std::string key_with_quotes = "\"";
5405   key_with_quotes += key;
5406   key_with_quotes += "\"";
5407   const char *c = strstr(json_string, key_with_quotes.c_str());
5408   if (c) {
5409     c += key_with_quotes.size();
5410 
5411     while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5412       c++;
5413 
5414     if (*c == ':') {
5415       c++;
5416 
5417       while (*c != '\0' &&
5418              (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5419         c++;
5420 
5421       if (strncmp(c, "true", 4) == 0) {
5422         value = true;
5423         return true;
5424       } else if (strncmp(c, "false", 5) == 0) {
5425         value = false;
5426         return true;
5427       }
5428     }
5429   }
5430   return false;
5431 }
5432 
5433 // A helper function that reads an array of uint64_t's from
5434 // a one-level-deep JSON dictionary of key-value pairs.  e.g.
5435 // jGetLoadedDynamicLibrariesInfos:{"solib_addrs":[31345823,7768020384,7310483024]}]
5436 
5437 // Returns true if it was able to find the key name, false if it did not.
5438 // "ints" will have all integers found in the array appended to it.
5439 
get_array_of_ints_value_for_key_name_from_json(const char * key,const char * json_string,std::vector<uint64_t> & ints)5440 bool get_array_of_ints_value_for_key_name_from_json(
5441     const char *key, const char *json_string, std::vector<uint64_t> &ints) {
5442   std::string key_with_quotes = "\"";
5443   key_with_quotes += key;
5444   key_with_quotes += "\"";
5445   const char *c = strstr(json_string, key_with_quotes.c_str());
5446   if (c) {
5447     c += key_with_quotes.size();
5448 
5449     while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5450       c++;
5451 
5452     if (*c == ':') {
5453       c++;
5454 
5455       while (*c != '\0' &&
5456              (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5457         c++;
5458 
5459       if (*c == '[') {
5460         c++;
5461         while (*c != '\0' &&
5462                (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5463           c++;
5464         while (true) {
5465           if (!isdigit(*c)) {
5466             return true;
5467           }
5468 
5469           errno = 0;
5470           char *endptr;
5471           uint64_t value = strtoul(c, &endptr, 10);
5472           if (errno == 0) {
5473             ints.push_back(value);
5474           } else {
5475             break;
5476           }
5477           if (endptr == c || endptr == nullptr || *endptr == '\0') {
5478             break;
5479           }
5480           c = endptr;
5481 
5482           while (*c != '\0' &&
5483                  (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5484             c++;
5485           if (*c == ',')
5486             c++;
5487           while (*c != '\0' &&
5488                  (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5489             c++;
5490           if (*c == ']') {
5491             return true;
5492           }
5493         }
5494       }
5495     }
5496   }
5497   return false;
5498 }
5499 
5500 JSONGenerator::ObjectSP
GetJSONThreadsInfo(bool threads_with_valid_stop_info_only)5501 RNBRemote::GetJSONThreadsInfo(bool threads_with_valid_stop_info_only) {
5502   JSONGenerator::ArraySP threads_array_sp;
5503   if (m_ctx.HasValidProcessID()) {
5504     threads_array_sp = std::make_shared<JSONGenerator::Array>();
5505 
5506     nub_process_t pid = m_ctx.ProcessID();
5507 
5508     nub_size_t numthreads = DNBProcessGetNumThreads(pid);
5509     for (nub_size_t i = 0; i < numthreads; ++i) {
5510       nub_thread_t tid = DNBProcessGetThreadAtIndex(pid, i);
5511 
5512       struct DNBThreadStopInfo tid_stop_info;
5513 
5514       const bool stop_info_valid =
5515           DNBThreadGetStopReason(pid, tid, &tid_stop_info);
5516 
5517       // If we are doing stop info only, then we only show threads that have a
5518       // valid stop reason
5519       if (threads_with_valid_stop_info_only) {
5520         if (!stop_info_valid || tid_stop_info.reason == eStopTypeInvalid)
5521           continue;
5522       }
5523 
5524       JSONGenerator::DictionarySP thread_dict_sp(
5525           new JSONGenerator::Dictionary());
5526       thread_dict_sp->AddIntegerItem("tid", tid);
5527 
5528       std::string reason_value("none");
5529 
5530       if (stop_info_valid) {
5531         switch (tid_stop_info.reason) {
5532         case eStopTypeInvalid:
5533           break;
5534 
5535         case eStopTypeSignal:
5536           if (tid_stop_info.details.signal.signo != 0) {
5537             thread_dict_sp->AddIntegerItem("signal",
5538                                            tid_stop_info.details.signal.signo);
5539             reason_value = "signal";
5540           }
5541           break;
5542 
5543         case eStopTypeException:
5544           if (tid_stop_info.details.exception.type != 0) {
5545             reason_value = "exception";
5546             thread_dict_sp->AddIntegerItem(
5547                 "metype", tid_stop_info.details.exception.type);
5548             JSONGenerator::ArraySP medata_array_sp(new JSONGenerator::Array());
5549             for (nub_size_t i = 0;
5550                  i < tid_stop_info.details.exception.data_count; ++i) {
5551               medata_array_sp->AddItem(
5552                   JSONGenerator::IntegerSP(new JSONGenerator::Integer(
5553                       tid_stop_info.details.exception.data[i])));
5554             }
5555             thread_dict_sp->AddItem("medata", medata_array_sp);
5556           }
5557           break;
5558 
5559         case eStopTypeExec:
5560           reason_value = "exec";
5561           break;
5562         }
5563       }
5564 
5565       thread_dict_sp->AddStringItem("reason", reason_value);
5566 
5567       if (!threads_with_valid_stop_info_only) {
5568         const char *thread_name = DNBThreadGetName(pid, tid);
5569         if (thread_name && thread_name[0])
5570           thread_dict_sp->AddStringItem("name", thread_name);
5571 
5572         thread_identifier_info_data_t thread_ident_info;
5573         if (DNBThreadGetIdentifierInfo(pid, tid, &thread_ident_info)) {
5574           if (thread_ident_info.dispatch_qaddr != 0) {
5575             thread_dict_sp->AddIntegerItem("qaddr",
5576                                            thread_ident_info.dispatch_qaddr);
5577 
5578             const DispatchQueueOffsets *dispatch_queue_offsets =
5579                 GetDispatchQueueOffsets();
5580             if (dispatch_queue_offsets) {
5581               std::string queue_name;
5582               uint64_t queue_width = 0;
5583               uint64_t queue_serialnum = 0;
5584               nub_addr_t dispatch_queue_t = INVALID_NUB_ADDRESS;
5585               dispatch_queue_offsets->GetThreadQueueInfo(
5586                   pid, thread_ident_info.dispatch_qaddr, dispatch_queue_t,
5587                   queue_name, queue_width, queue_serialnum);
5588               if (dispatch_queue_t == 0 && queue_name.empty() &&
5589                   queue_serialnum == 0) {
5590                 thread_dict_sp->AddBooleanItem("associated_with_dispatch_queue",
5591                                                false);
5592               } else {
5593                 thread_dict_sp->AddBooleanItem("associated_with_dispatch_queue",
5594                                                true);
5595               }
5596               if (dispatch_queue_t != INVALID_NUB_ADDRESS &&
5597                   dispatch_queue_t != 0)
5598                 thread_dict_sp->AddIntegerItem("dispatch_queue_t",
5599                                                dispatch_queue_t);
5600               if (!queue_name.empty())
5601                 thread_dict_sp->AddStringItem("qname", queue_name);
5602               if (queue_width == 1)
5603                 thread_dict_sp->AddStringItem("qkind", "serial");
5604               else if (queue_width > 1)
5605                 thread_dict_sp->AddStringItem("qkind", "concurrent");
5606               if (queue_serialnum > 0)
5607                 thread_dict_sp->AddIntegerItem("qserialnum", queue_serialnum);
5608             }
5609           }
5610         }
5611 
5612         DNBRegisterValue reg_value;
5613 
5614         if (g_reg_entries != NULL) {
5615           JSONGenerator::DictionarySP registers_dict_sp(
5616               new JSONGenerator::Dictionary());
5617 
5618           for (uint32_t reg = 0; reg < g_num_reg_entries; reg++) {
5619             // Expedite all registers in the first register set that aren't
5620             // contained in other registers
5621             if (g_reg_entries[reg].nub_info.set == 1 &&
5622                 g_reg_entries[reg].nub_info.value_regs == NULL) {
5623               if (!DNBThreadGetRegisterValueByID(
5624                       pid, tid, g_reg_entries[reg].nub_info.set,
5625                       g_reg_entries[reg].nub_info.reg, &reg_value))
5626                 continue;
5627 
5628               std::ostringstream reg_num;
5629               reg_num << std::dec << g_reg_entries[reg].debugserver_regnum;
5630               // Encode native byte ordered bytes as hex ascii
5631               registers_dict_sp->AddBytesAsHexASCIIString(
5632                   reg_num.str(), reg_value.value.v_uint8,
5633                   g_reg_entries[reg].nub_info.size);
5634             }
5635           }
5636           thread_dict_sp->AddItem("registers", registers_dict_sp);
5637         }
5638 
5639         // Add expedited stack memory so stack backtracing doesn't need to read
5640         // anything from the
5641         // frame pointer chain.
5642         StackMemoryMap stack_mmap;
5643         ReadStackMemory(pid, tid, stack_mmap);
5644         if (!stack_mmap.empty()) {
5645           JSONGenerator::ArraySP memory_array_sp(new JSONGenerator::Array());
5646 
5647           for (const auto &stack_memory : stack_mmap) {
5648             JSONGenerator::DictionarySP stack_memory_sp(
5649                 new JSONGenerator::Dictionary());
5650             stack_memory_sp->AddIntegerItem("address", stack_memory.first);
5651             stack_memory_sp->AddBytesAsHexASCIIString(
5652                 "bytes", stack_memory.second.bytes, stack_memory.second.length);
5653             memory_array_sp->AddItem(stack_memory_sp);
5654           }
5655           thread_dict_sp->AddItem("memory", memory_array_sp);
5656         }
5657       }
5658 
5659       threads_array_sp->AddItem(thread_dict_sp);
5660     }
5661   }
5662   return threads_array_sp;
5663 }
5664 
HandlePacket_jThreadsInfo(const char * p)5665 rnb_err_t RNBRemote::HandlePacket_jThreadsInfo(const char *p) {
5666   JSONGenerator::ObjectSP threads_info_sp;
5667   std::ostringstream json;
5668   std::ostringstream reply_strm;
5669   // If we haven't run the process yet, return an error.
5670   if (m_ctx.HasValidProcessID()) {
5671     const bool threads_with_valid_stop_info_only = false;
5672     JSONGenerator::ObjectSP threads_info_sp =
5673         GetJSONThreadsInfo(threads_with_valid_stop_info_only);
5674 
5675     if (threads_info_sp) {
5676       std::ostringstream strm;
5677       threads_info_sp->Dump(strm);
5678       std::string binary_packet = binary_encode_string(strm.str());
5679       if (!binary_packet.empty())
5680         return SendPacket(binary_packet.c_str());
5681     }
5682   }
5683   return SendPacket("E85");
5684 }
5685 
HandlePacket_jThreadExtendedInfo(const char * p)5686 rnb_err_t RNBRemote::HandlePacket_jThreadExtendedInfo(const char *p) {
5687   nub_process_t pid;
5688   std::ostringstream json;
5689   // If we haven't run the process yet, return an error.
5690   if (!m_ctx.HasValidProcessID()) {
5691     return SendPacket("E81");
5692   }
5693 
5694   pid = m_ctx.ProcessID();
5695 
5696   const char thread_extended_info_str[] = {"jThreadExtendedInfo:{"};
5697   if (strncmp(p, thread_extended_info_str,
5698               sizeof(thread_extended_info_str) - 1) == 0) {
5699     p += strlen(thread_extended_info_str);
5700 
5701     uint64_t tid = get_integer_value_for_key_name_from_json("thread", p);
5702     uint64_t plo_pthread_tsd_base_address_offset =
5703         get_integer_value_for_key_name_from_json(
5704             "plo_pthread_tsd_base_address_offset", p);
5705     uint64_t plo_pthread_tsd_base_offset =
5706         get_integer_value_for_key_name_from_json("plo_pthread_tsd_base_offset",
5707                                                  p);
5708     uint64_t plo_pthread_tsd_entry_size =
5709         get_integer_value_for_key_name_from_json("plo_pthread_tsd_entry_size",
5710                                                  p);
5711     uint64_t dti_qos_class_index =
5712         get_integer_value_for_key_name_from_json("dti_qos_class_index", p);
5713 
5714     if (tid != INVALID_NUB_ADDRESS) {
5715       nub_addr_t pthread_t_value = DNBGetPThreadT(pid, tid);
5716 
5717       uint64_t tsd_address = INVALID_NUB_ADDRESS;
5718       if (plo_pthread_tsd_entry_size != INVALID_NUB_ADDRESS &&
5719           plo_pthread_tsd_base_offset != INVALID_NUB_ADDRESS &&
5720           plo_pthread_tsd_entry_size != INVALID_NUB_ADDRESS) {
5721         tsd_address = DNBGetTSDAddressForThread(
5722             pid, tid, plo_pthread_tsd_base_address_offset,
5723             plo_pthread_tsd_base_offset, plo_pthread_tsd_entry_size);
5724       }
5725 
5726       bool timed_out = false;
5727       Genealogy::ThreadActivitySP thread_activity_sp;
5728 
5729       // If the pthread_t value is invalid, or if we were able to fetch the
5730       // thread's TSD base
5731       // and got an invalid value back, then we have a thread in early startup
5732       // or shutdown and
5733       // it's possible that gathering the genealogy information for this thread
5734       // go badly.
5735       // Ideally fetching this info for a thread in these odd states shouldn't
5736       // matter - but
5737       // we've seen some problems with these new SPI and threads in edge-casey
5738       // states.
5739 
5740       double genealogy_fetch_time = 0;
5741       if (pthread_t_value != INVALID_NUB_ADDRESS &&
5742           tsd_address != INVALID_NUB_ADDRESS) {
5743         DNBTimer timer(false);
5744         thread_activity_sp = DNBGetGenealogyInfoForThread(pid, tid, timed_out);
5745         genealogy_fetch_time = timer.ElapsedMicroSeconds(false) / 1000000.0;
5746       }
5747 
5748       std::unordered_set<uint32_t>
5749           process_info_indexes; // an array of the process info #'s seen
5750 
5751       json << "{";
5752 
5753       bool need_to_print_comma = false;
5754 
5755       if (thread_activity_sp && !timed_out) {
5756         const Genealogy::Activity *activity =
5757             &thread_activity_sp->current_activity;
5758         bool need_vouchers_comma_sep = false;
5759         json << "\"activity_query_timed_out\":false,";
5760         if (genealogy_fetch_time != 0) {
5761           //  If we append the floating point value with << we'll get it in
5762           //  scientific
5763           //  notation.
5764           char floating_point_ascii_buffer[64];
5765           floating_point_ascii_buffer[0] = '\0';
5766           snprintf(floating_point_ascii_buffer,
5767                    sizeof(floating_point_ascii_buffer), "%f",
5768                    genealogy_fetch_time);
5769           if (strlen(floating_point_ascii_buffer) > 0) {
5770             if (need_to_print_comma)
5771               json << ",";
5772             need_to_print_comma = true;
5773             json << "\"activity_query_duration\":"
5774                  << floating_point_ascii_buffer;
5775           }
5776         }
5777         if (activity->activity_id != 0) {
5778           if (need_to_print_comma)
5779             json << ",";
5780           need_to_print_comma = true;
5781           need_vouchers_comma_sep = true;
5782           json << "\"activity\":{";
5783           json << "\"start\":" << activity->activity_start << ",";
5784           json << "\"id\":" << activity->activity_id << ",";
5785           json << "\"parent_id\":" << activity->parent_id << ",";
5786           json << "\"name\":\""
5787                << json_string_quote_metachars(activity->activity_name) << "\",";
5788           json << "\"reason\":\""
5789                << json_string_quote_metachars(activity->reason) << "\"";
5790           json << "}";
5791         }
5792         if (thread_activity_sp->messages.size() > 0) {
5793           need_to_print_comma = true;
5794           if (need_vouchers_comma_sep)
5795             json << ",";
5796           need_vouchers_comma_sep = true;
5797           json << "\"trace_messages\":[";
5798           bool printed_one_message = false;
5799           for (auto iter = thread_activity_sp->messages.begin();
5800                iter != thread_activity_sp->messages.end(); ++iter) {
5801             if (printed_one_message)
5802               json << ",";
5803             else
5804               printed_one_message = true;
5805             json << "{";
5806             json << "\"timestamp\":" << iter->timestamp << ",";
5807             json << "\"activity_id\":" << iter->activity_id << ",";
5808             json << "\"trace_id\":" << iter->trace_id << ",";
5809             json << "\"thread\":" << iter->thread << ",";
5810             json << "\"type\":" << (int)iter->type << ",";
5811             json << "\"process_info_index\":" << iter->process_info_index
5812                  << ",";
5813             process_info_indexes.insert(iter->process_info_index);
5814             json << "\"message\":\""
5815                  << json_string_quote_metachars(iter->message) << "\"";
5816             json << "}";
5817           }
5818           json << "]";
5819         }
5820         if (thread_activity_sp->breadcrumbs.size() == 1) {
5821           need_to_print_comma = true;
5822           if (need_vouchers_comma_sep)
5823             json << ",";
5824           need_vouchers_comma_sep = true;
5825           json << "\"breadcrumb\":{";
5826           for (auto iter = thread_activity_sp->breadcrumbs.begin();
5827                iter != thread_activity_sp->breadcrumbs.end(); ++iter) {
5828             json << "\"breadcrumb_id\":" << iter->breadcrumb_id << ",";
5829             json << "\"activity_id\":" << iter->activity_id << ",";
5830             json << "\"timestamp\":" << iter->timestamp << ",";
5831             json << "\"name\":\"" << json_string_quote_metachars(iter->name)
5832                  << "\"";
5833           }
5834           json << "}";
5835         }
5836         if (process_info_indexes.size() > 0) {
5837           need_to_print_comma = true;
5838           if (need_vouchers_comma_sep)
5839             json << ",";
5840           need_vouchers_comma_sep = true;
5841           bool printed_one_process_info = false;
5842           for (auto iter = process_info_indexes.begin();
5843                iter != process_info_indexes.end(); ++iter) {
5844             if (printed_one_process_info)
5845               json << ",";
5846             Genealogy::ProcessExecutableInfoSP image_info_sp;
5847             uint32_t idx = *iter;
5848             image_info_sp = DNBGetGenealogyImageInfo(pid, idx);
5849             if (image_info_sp) {
5850               if (!printed_one_process_info) {
5851                 json << "\"process_infos\":[";
5852                 printed_one_process_info = true;
5853               }
5854 
5855               json << "{";
5856               char uuid_buf[37];
5857               uuid_unparse_upper(image_info_sp->image_uuid, uuid_buf);
5858               json << "\"process_info_index\":" << idx << ",";
5859               json << "\"image_path\":\""
5860                    << json_string_quote_metachars(image_info_sp->image_path)
5861                    << "\",";
5862               json << "\"image_uuid\":\"" << uuid_buf << "\"";
5863               json << "}";
5864             }
5865           }
5866           if (printed_one_process_info)
5867             json << "]";
5868         }
5869       } else {
5870         if (timed_out) {
5871           if (need_to_print_comma)
5872             json << ",";
5873           need_to_print_comma = true;
5874           json << "\"activity_query_timed_out\":true";
5875           if (genealogy_fetch_time != 0) {
5876             //  If we append the floating point value with << we'll get it in
5877             //  scientific
5878             //  notation.
5879             char floating_point_ascii_buffer[64];
5880             floating_point_ascii_buffer[0] = '\0';
5881             snprintf(floating_point_ascii_buffer,
5882                      sizeof(floating_point_ascii_buffer), "%f",
5883                      genealogy_fetch_time);
5884             if (strlen(floating_point_ascii_buffer) > 0) {
5885               json << ",";
5886               json << "\"activity_query_duration\":"
5887                    << floating_point_ascii_buffer;
5888             }
5889           }
5890         }
5891       }
5892 
5893       if (tsd_address != INVALID_NUB_ADDRESS) {
5894         if (need_to_print_comma)
5895           json << ",";
5896         need_to_print_comma = true;
5897         json << "\"tsd_address\":" << tsd_address;
5898 
5899         if (dti_qos_class_index != 0 && dti_qos_class_index != UINT64_MAX) {
5900           ThreadInfo::QoS requested_qos = DNBGetRequestedQoSForThread(
5901               pid, tid, tsd_address, dti_qos_class_index);
5902           if (requested_qos.IsValid()) {
5903             if (need_to_print_comma)
5904               json << ",";
5905             need_to_print_comma = true;
5906             json << "\"requested_qos\":{";
5907             json << "\"enum_value\":" << requested_qos.enum_value << ",";
5908             json << "\"constant_name\":\""
5909                  << json_string_quote_metachars(requested_qos.constant_name)
5910                  << "\",";
5911             json << "\"printable_name\":\""
5912                  << json_string_quote_metachars(requested_qos.printable_name)
5913                  << "\"";
5914             json << "}";
5915           }
5916         }
5917       }
5918 
5919       if (pthread_t_value != INVALID_NUB_ADDRESS) {
5920         if (need_to_print_comma)
5921           json << ",";
5922         need_to_print_comma = true;
5923         json << "\"pthread_t\":" << pthread_t_value;
5924       }
5925 
5926       nub_addr_t dispatch_queue_t_value = DNBGetDispatchQueueT(pid, tid);
5927       if (dispatch_queue_t_value != INVALID_NUB_ADDRESS) {
5928         if (need_to_print_comma)
5929           json << ",";
5930         need_to_print_comma = true;
5931         json << "\"dispatch_queue_t\":" << dispatch_queue_t_value;
5932       }
5933 
5934       json << "}";
5935       std::string json_quoted = binary_encode_string(json.str());
5936       return SendPacket(json_quoted);
5937     }
5938   }
5939   return SendPacket("OK");
5940 }
5941 
5942 //  This packet may be called in one of three ways:
5943 //
5944 //  jGetLoadedDynamicLibrariesInfos:{"image_count":40,"image_list_address":4295244704}
5945 //      Look for an array of the old dyld_all_image_infos style of binary infos
5946 //      at the image_list_address.
5947 //      This an array of {void* load_addr, void* mod_date, void* pathname}
5948 //
5949 //  jGetLoadedDynamicLibrariesInfos:{"fetch_all_solibs":true}
5950 //      Use the new style (macOS 10.12, tvOS 10, iOS 10, watchOS 3) dyld SPI to
5951 //      get a list of all the
5952 //      libraries loaded
5953 //
5954 //  jGetLoadedDynamicLibrariesInfos:{"solib_addresses":[8382824135,3258302053,830202858503]}
5955 //      Use the new style (macOS 10.12, tvOS 10, iOS 10, watchOS 3) dyld SPI to
5956 //      get the information
5957 //      about the libraries loaded at these addresses.
5958 //
5959 rnb_err_t
HandlePacket_jGetLoadedDynamicLibrariesInfos(const char * p)5960 RNBRemote::HandlePacket_jGetLoadedDynamicLibrariesInfos(const char *p) {
5961   nub_process_t pid;
5962   // If we haven't run the process yet, return an error.
5963   if (!m_ctx.HasValidProcessID()) {
5964     return SendPacket("E83");
5965   }
5966 
5967   pid = m_ctx.ProcessID();
5968 
5969   const char get_loaded_dynamic_libraries_infos_str[] = {
5970       "jGetLoadedDynamicLibrariesInfos:{"};
5971   if (strncmp(p, get_loaded_dynamic_libraries_infos_str,
5972               sizeof(get_loaded_dynamic_libraries_infos_str) - 1) == 0) {
5973     p += strlen(get_loaded_dynamic_libraries_infos_str);
5974 
5975     JSONGenerator::ObjectSP json_sp;
5976 
5977     std::vector<uint64_t> macho_addresses;
5978     bool fetch_all_solibs = false;
5979     if (get_boolean_value_for_key_name_from_json("fetch_all_solibs", p,
5980                                                  fetch_all_solibs) &&
5981         fetch_all_solibs) {
5982       json_sp = DNBGetAllLoadedLibrariesInfos(pid);
5983     } else if (get_array_of_ints_value_for_key_name_from_json(
5984                    "solib_addresses", p, macho_addresses)) {
5985       json_sp = DNBGetLibrariesInfoForAddresses(pid, macho_addresses);
5986     } else {
5987       nub_addr_t image_list_address =
5988           get_integer_value_for_key_name_from_json("image_list_address", p);
5989       nub_addr_t image_count =
5990           get_integer_value_for_key_name_from_json("image_count", p);
5991 
5992       if (image_list_address != INVALID_NUB_ADDRESS &&
5993           image_count != INVALID_NUB_ADDRESS) {
5994         json_sp = DNBGetLoadedDynamicLibrariesInfos(pid, image_list_address,
5995                                                     image_count);
5996       }
5997     }
5998 
5999     if (json_sp.get()) {
6000       std::ostringstream json_str;
6001       json_sp->Dump(json_str);
6002       if (json_str.str().size() > 0) {
6003         std::string json_str_quoted = binary_encode_string(json_str.str());
6004         return SendPacket(json_str_quoted.c_str());
6005       } else {
6006         SendPacket("E84");
6007       }
6008     }
6009   }
6010   return SendPacket("OK");
6011 }
6012 
6013 // This packet does not currently take any arguments.  So the behavior is
6014 //    jGetSharedCacheInfo:{}
6015 //         send information about the inferior's shared cache
6016 //    jGetSharedCacheInfo:
6017 //         send "OK" to indicate that this packet is supported
HandlePacket_jGetSharedCacheInfo(const char * p)6018 rnb_err_t RNBRemote::HandlePacket_jGetSharedCacheInfo(const char *p) {
6019   nub_process_t pid;
6020   // If we haven't run the process yet, return an error.
6021   if (!m_ctx.HasValidProcessID()) {
6022     return SendPacket("E85");
6023   }
6024 
6025   pid = m_ctx.ProcessID();
6026 
6027   const char get_shared_cache_info_str[] = {"jGetSharedCacheInfo:{"};
6028   if (strncmp(p, get_shared_cache_info_str,
6029               sizeof(get_shared_cache_info_str) - 1) == 0) {
6030     JSONGenerator::ObjectSP json_sp = DNBGetSharedCacheInfo(pid);
6031 
6032     if (json_sp.get()) {
6033       std::ostringstream json_str;
6034       json_sp->Dump(json_str);
6035       if (json_str.str().size() > 0) {
6036         std::string json_str_quoted = binary_encode_string(json_str.str());
6037         return SendPacket(json_str_quoted.c_str());
6038       } else {
6039         SendPacket("E86");
6040       }
6041     }
6042   }
6043   return SendPacket("OK");
6044 }
6045 
MachHeaderIsMainExecutable(nub_process_t pid,uint32_t addr_size,nub_addr_t mach_header_addr,mach_header & mh)6046 static bool MachHeaderIsMainExecutable(nub_process_t pid, uint32_t addr_size,
6047                                        nub_addr_t mach_header_addr,
6048                                        mach_header &mh) {
6049   DNBLogThreadedIf(LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = %u, "
6050                                  "addr_size = %u, mach_header_addr = "
6051                                  "0x%16.16llx)",
6052                    pid, addr_size, mach_header_addr);
6053   const nub_size_t bytes_read =
6054       DNBProcessMemoryRead(pid, mach_header_addr, sizeof(mh), &mh);
6055   if (bytes_read == sizeof(mh)) {
6056     DNBLogThreadedIf(
6057         LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = %u, addr_size = "
6058                       "%u, mach_header_addr = 0x%16.16llx): mh = {\n  magic = "
6059                       "0x%8.8x\n  cpu = 0x%8.8x\n  sub = 0x%8.8x\n  filetype = "
6060                       "%u\n  ncmds = %u\n  sizeofcmds = 0x%8.8x\n  flags = "
6061                       "0x%8.8x }",
6062         pid, addr_size, mach_header_addr, mh.magic, mh.cputype, mh.cpusubtype,
6063         mh.filetype, mh.ncmds, mh.sizeofcmds, mh.flags);
6064     if ((addr_size == 4 && mh.magic == MH_MAGIC) ||
6065         (addr_size == 8 && mh.magic == MH_MAGIC_64)) {
6066       if (mh.filetype == MH_EXECUTE) {
6067         DNBLogThreadedIf(LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = "
6068                                        "%u, addr_size = %u, mach_header_addr = "
6069                                        "0x%16.16llx) -> this is the "
6070                                        "executable!!!",
6071                          pid, addr_size, mach_header_addr);
6072         return true;
6073       }
6074     }
6075   }
6076   return false;
6077 }
6078 
GetMachHeaderForMainExecutable(const nub_process_t pid,const uint32_t addr_size,mach_header & mh)6079 static nub_addr_t GetMachHeaderForMainExecutable(const nub_process_t pid,
6080                                                  const uint32_t addr_size,
6081                                                  mach_header &mh) {
6082   struct AllImageInfos {
6083     uint32_t version;
6084     uint32_t dylib_info_count;
6085     uint64_t dylib_info_addr;
6086   };
6087 
6088   uint64_t mach_header_addr = 0;
6089 
6090   const nub_addr_t shlib_addr = DNBProcessGetSharedLibraryInfoAddress(pid);
6091   uint8_t bytes[256];
6092   nub_size_t bytes_read = 0;
6093   DNBDataRef data(bytes, sizeof(bytes), false);
6094   DNBDataRef::offset_t offset = 0;
6095   data.SetPointerSize(addr_size);
6096 
6097   // When we are sitting at __dyld_start, the kernel has placed the
6098   // address of the mach header of the main executable on the stack. If we
6099   // read the SP and dereference a pointer, we might find the mach header
6100   // for the executable. We also just make sure there is only 1 thread
6101   // since if we are at __dyld_start we shouldn't have multiple threads.
6102   if (DNBProcessGetNumThreads(pid) == 1) {
6103     nub_thread_t tid = DNBProcessGetThreadAtIndex(pid, 0);
6104     if (tid != INVALID_NUB_THREAD) {
6105       DNBRegisterValue sp_value;
6106       if (DNBThreadGetRegisterValueByID(pid, tid, REGISTER_SET_GENERIC,
6107                                         GENERIC_REGNUM_SP, &sp_value)) {
6108         uint64_t sp =
6109             addr_size == 8 ? sp_value.value.uint64 : sp_value.value.uint32;
6110         bytes_read = DNBProcessMemoryRead(pid, sp, addr_size, bytes);
6111         if (bytes_read == addr_size) {
6112           offset = 0;
6113           mach_header_addr = data.GetPointer(&offset);
6114           if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, mh))
6115             return mach_header_addr;
6116         }
6117       }
6118     }
6119   }
6120 
6121   // Check the dyld_all_image_info structure for a list of mach header
6122   // since it is a very easy thing to check
6123   if (shlib_addr != INVALID_NUB_ADDRESS) {
6124     bytes_read =
6125         DNBProcessMemoryRead(pid, shlib_addr, sizeof(AllImageInfos), bytes);
6126     if (bytes_read > 0) {
6127       AllImageInfos aii;
6128       offset = 0;
6129       aii.version = data.Get32(&offset);
6130       aii.dylib_info_count = data.Get32(&offset);
6131       if (aii.dylib_info_count > 0) {
6132         aii.dylib_info_addr = data.GetPointer(&offset);
6133         if (aii.dylib_info_addr != 0) {
6134           const size_t image_info_byte_size = 3 * addr_size;
6135           for (uint32_t i = 0; i < aii.dylib_info_count; ++i) {
6136             bytes_read = DNBProcessMemoryRead(pid, aii.dylib_info_addr +
6137                                                        i * image_info_byte_size,
6138                                               image_info_byte_size, bytes);
6139             if (bytes_read != image_info_byte_size)
6140               break;
6141             offset = 0;
6142             mach_header_addr = data.GetPointer(&offset);
6143             if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr,
6144                                            mh))
6145               return mach_header_addr;
6146           }
6147         }
6148       }
6149     }
6150   }
6151 
6152   // We failed to find the executable's mach header from the all image
6153   // infos and by dereferencing the stack pointer. Now we fall back to
6154   // enumerating the memory regions and looking for regions that are
6155   // executable.
6156   DNBRegionInfo region_info;
6157   mach_header_addr = 0;
6158   while (DNBProcessMemoryRegionInfo(pid, mach_header_addr, &region_info)) {
6159     if (region_info.size == 0)
6160       break;
6161 
6162     if (region_info.permissions & eMemoryPermissionsExecutable) {
6163       DNBLogThreadedIf(
6164           LOG_RNB_PROC, "[0x%16.16llx - 0x%16.16llx) permissions = %c%c%c: "
6165                         "checking region for executable mach header",
6166           region_info.addr, region_info.addr + region_info.size,
6167           (region_info.permissions & eMemoryPermissionsReadable) ? 'r' : '-',
6168           (region_info.permissions & eMemoryPermissionsWritable) ? 'w' : '-',
6169           (region_info.permissions & eMemoryPermissionsExecutable) ? 'x' : '-');
6170       if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, mh))
6171         return mach_header_addr;
6172     } else {
6173       DNBLogThreadedIf(
6174           LOG_RNB_PROC,
6175           "[0x%16.16llx - 0x%16.16llx): permissions = %c%c%c: skipping region",
6176           region_info.addr, region_info.addr + region_info.size,
6177           (region_info.permissions & eMemoryPermissionsReadable) ? 'r' : '-',
6178           (region_info.permissions & eMemoryPermissionsWritable) ? 'w' : '-',
6179           (region_info.permissions & eMemoryPermissionsExecutable) ? 'x' : '-');
6180     }
6181     // Set the address to the next mapped region
6182     mach_header_addr = region_info.addr + region_info.size;
6183   }
6184   bzero(&mh, sizeof(mh));
6185   return INVALID_NUB_ADDRESS;
6186 }
6187 
HandlePacket_qSymbol(const char * command)6188 rnb_err_t RNBRemote::HandlePacket_qSymbol(const char *command) {
6189   const char *p = command;
6190   p += strlen("qSymbol:");
6191   const char *sep = strchr(p, ':');
6192 
6193   std::string symbol_name;
6194   std::string symbol_value_str;
6195   // Extract the symbol value if there is one
6196   if (sep > p)
6197     symbol_value_str.assign(p, sep - p);
6198   p = sep + 1;
6199 
6200   if (*p) {
6201     // We have a symbol name
6202     symbol_name = decode_hex_ascii_string(p);
6203     if (!symbol_value_str.empty()) {
6204       nub_addr_t symbol_value = decode_uint64(symbol_value_str.c_str(), 16);
6205       if (symbol_name == "dispatch_queue_offsets")
6206         m_dispatch_queue_offsets_addr = symbol_value;
6207     }
6208     ++m_qSymbol_index;
6209   } else {
6210     // No symbol name, set our symbol index to zero so we can
6211     // read any symbols that we need
6212     m_qSymbol_index = 0;
6213   }
6214 
6215   symbol_name.clear();
6216 
6217   if (m_qSymbol_index == 0) {
6218     if (m_dispatch_queue_offsets_addr == INVALID_NUB_ADDRESS)
6219       symbol_name = "dispatch_queue_offsets";
6220     else
6221       ++m_qSymbol_index;
6222   }
6223 
6224   //    // Lookup next symbol when we have one...
6225   //    if (m_qSymbol_index == 1)
6226   //    {
6227   //    }
6228 
6229   if (symbol_name.empty()) {
6230     // Done with symbol lookups
6231     return SendPacket("OK");
6232   } else {
6233     std::ostringstream reply;
6234     reply << "qSymbol:";
6235     for (size_t i = 0; i < symbol_name.size(); ++i)
6236       reply << RAWHEX8(symbol_name[i]);
6237     return SendPacket(reply.str().c_str());
6238   }
6239 }
6240 
6241 // Note that all numeric values returned by qProcessInfo are hex encoded,
6242 // including the pid and the cpu type.
6243 
HandlePacket_qProcessInfo(const char * p)6244 rnb_err_t RNBRemote::HandlePacket_qProcessInfo(const char *p) {
6245   nub_process_t pid;
6246   std::ostringstream rep;
6247 
6248   // If we haven't run the process yet, return an error.
6249   if (!m_ctx.HasValidProcessID())
6250     return SendPacket("E68");
6251 
6252   pid = m_ctx.ProcessID();
6253 
6254   rep << "pid:" << std::hex << pid << ';';
6255 
6256   int procpid_mib[4];
6257   procpid_mib[0] = CTL_KERN;
6258   procpid_mib[1] = KERN_PROC;
6259   procpid_mib[2] = KERN_PROC_PID;
6260   procpid_mib[3] = pid;
6261   struct kinfo_proc proc_kinfo;
6262   size_t proc_kinfo_size = sizeof(struct kinfo_proc);
6263 
6264   if (::sysctl(procpid_mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) {
6265     if (proc_kinfo_size > 0) {
6266       rep << "parent-pid:" << std::hex << proc_kinfo.kp_eproc.e_ppid << ';';
6267       rep << "real-uid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_ruid
6268           << ';';
6269       rep << "real-gid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_rgid
6270           << ';';
6271       rep << "effective-uid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_uid
6272           << ';';
6273       if (proc_kinfo.kp_eproc.e_ucred.cr_ngroups > 0)
6274         rep << "effective-gid:" << std::hex
6275             << proc_kinfo.kp_eproc.e_ucred.cr_groups[0] << ';';
6276     }
6277   }
6278 
6279   cpu_type_t cputype = DNBProcessGetCPUType(pid);
6280   if (cputype == 0) {
6281     DNBLog("Unable to get the process cpu_type, making a best guess.");
6282     cputype = best_guess_cpu_type();
6283   }
6284 
6285   uint32_t addr_size = 0;
6286   if (cputype != 0) {
6287     rep << "cputype:" << std::hex << cputype << ";";
6288     if (cputype & CPU_ARCH_ABI64)
6289       addr_size = 8;
6290     else
6291       addr_size = 4;
6292   }
6293 
6294   bool host_cpu_is_64bit = false;
6295   uint32_t is64bit_capable;
6296   size_t is64bit_capable_len = sizeof(is64bit_capable);
6297   if (sysctlbyname("hw.cpu64bit_capable", &is64bit_capable,
6298                    &is64bit_capable_len, NULL, 0) == 0)
6299     host_cpu_is_64bit = is64bit_capable != 0;
6300 
6301   uint32_t cpusubtype;
6302   size_t cpusubtype_len = sizeof(cpusubtype);
6303   if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &cpusubtype_len, NULL, 0) ==
6304       0) {
6305     // If a process is CPU_TYPE_X86, then ignore the cpusubtype that we detected
6306     // from the host and use CPU_SUBTYPE_I386_ALL because we don't want the
6307     // CPU_SUBTYPE_X86_ARCH1 or CPU_SUBTYPE_X86_64_H to be used as the cpu
6308     // subtype
6309     // for i386...
6310     if (host_cpu_is_64bit) {
6311       if (cputype == CPU_TYPE_X86) {
6312         cpusubtype = 3; // CPU_SUBTYPE_I386_ALL
6313       } else if (cputype == CPU_TYPE_ARM) {
6314         // We can query a process' cputype but we cannot query a process'
6315         // cpusubtype.
6316         // If the process has cputype CPU_TYPE_ARM, then it is an armv7 (32-bit
6317         // process) and we
6318         // need to override the host cpusubtype (which is in the
6319         // CPU_SUBTYPE_ARM64 subtype namespace)
6320         // with a reasonable CPU_SUBTYPE_ARMV7 subtype.
6321         cpusubtype = 12; // CPU_SUBTYPE_ARM_V7K
6322       }
6323     }
6324 #if defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
6325     // on arm64_32 devices, the machine's native cpu type is
6326     // CPU_TYPE_ARM64 and subtype is 2 indicating arm64e.
6327     // But we change the cputype to CPU_TYPE_ARM64_32 because
6328     // the user processes are all ILP32 processes today.
6329     // We also need to rewrite the cpusubtype so we vend
6330     // a valid cputype + cpusubtype combination.
6331     if (cputype == CPU_TYPE_ARM64_32 && cpusubtype == 2)
6332       cpusubtype = CPU_SUBTYPE_ARM64_32_V8;
6333 #endif
6334 
6335     rep << "cpusubtype:" << std::hex << cpusubtype << ';';
6336   }
6337 
6338   bool os_handled = false;
6339   if (addr_size > 0) {
6340     rep << "ptrsize:" << std::dec << addr_size << ';';
6341 
6342 #if defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1
6343     // Try and get the OS type by looking at the load commands in the main
6344     // executable and looking for a LC_VERSION_MIN load command. This is the
6345     // most reliable way to determine the "ostype" value when on desktop.
6346 
6347     mach_header mh;
6348     nub_addr_t exe_mach_header_addr =
6349         GetMachHeaderForMainExecutable(pid, addr_size, mh);
6350     if (exe_mach_header_addr != INVALID_NUB_ADDRESS) {
6351       uint64_t load_command_addr =
6352           exe_mach_header_addr +
6353           ((addr_size == 8) ? sizeof(mach_header_64) : sizeof(mach_header));
6354       load_command lc;
6355       for (uint32_t i = 0; i < mh.ncmds && !os_handled; ++i) {
6356         const nub_size_t bytes_read =
6357             DNBProcessMemoryRead(pid, load_command_addr, sizeof(lc), &lc);
6358         (void)bytes_read;
6359 
6360         bool is_executable = true;
6361         uint32_t major_version, minor_version, patch_version;
6362         auto *platform =
6363             DNBGetDeploymentInfo(pid, is_executable, lc, load_command_addr,
6364                                  major_version, minor_version, patch_version);
6365         if (platform) {
6366           os_handled = true;
6367           rep << "ostype:" << platform << ";";
6368           break;
6369         }
6370         load_command_addr = load_command_addr + lc.cmdsize;
6371       }
6372     }
6373 #endif // TARGET_OS_OSX
6374   }
6375 
6376   // If we weren't able to find the OS in a LC_VERSION_MIN load command, try
6377   // to set it correctly by using the cpu type and other tricks
6378   if (!os_handled) {
6379     // The OS in the triple should be "ios" or "macosx" which doesn't match our
6380     // "Darwin" which gets returned from "kern.ostype", so we need to hardcode
6381     // this for now.
6382     if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64
6383         || cputype == CPU_TYPE_ARM64_32) {
6384 #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
6385       rep << "ostype:tvos;";
6386 #elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
6387       rep << "ostype:watchos;";
6388 #elif defined(TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1
6389       rep << "ostype:bridgeos;";
6390 #elif defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1
6391       rep << "ostype:macosx;";
6392 #else
6393       rep << "ostype:ios;";
6394 #endif
6395     } else {
6396       bool is_ios_simulator = false;
6397       if (cputype == CPU_TYPE_X86 || cputype == CPU_TYPE_X86_64) {
6398         // Check for iOS simulator binaries by getting the process argument
6399         // and environment and checking for SIMULATOR_UDID in the environment
6400         int proc_args_mib[3] = {CTL_KERN, KERN_PROCARGS2, (int)pid};
6401 
6402         uint8_t arg_data[8192];
6403         size_t arg_data_size = sizeof(arg_data);
6404         if (::sysctl(proc_args_mib, 3, arg_data, &arg_data_size, NULL, 0) ==
6405             0) {
6406           DNBDataRef data(arg_data, arg_data_size, false);
6407           DNBDataRef::offset_t offset = 0;
6408           uint32_t argc = data.Get32(&offset);
6409           const char *cstr;
6410 
6411           cstr = data.GetCStr(&offset);
6412           if (cstr) {
6413             // Skip NULLs
6414             while (true) {
6415               const char *p = data.PeekCStr(offset);
6416               if ((p == NULL) || (*p != '\0'))
6417                 break;
6418               ++offset;
6419             }
6420             // Now skip all arguments
6421             for (uint32_t i = 0; i < argc; ++i) {
6422               data.GetCStr(&offset);
6423             }
6424 
6425             // Now iterate across all environment variables
6426             while ((cstr = data.GetCStr(&offset))) {
6427               if (strncmp(cstr, "SIMULATOR_UDID=", strlen("SIMULATOR_UDID=")) ==
6428                   0) {
6429                 is_ios_simulator = true;
6430                 break;
6431               }
6432               if (cstr[0] == '\0')
6433                 break;
6434             }
6435           }
6436         }
6437       }
6438       if (is_ios_simulator) {
6439 #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
6440         rep << "ostype:tvos;";
6441 #elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
6442         rep << "ostype:watchos;";
6443 #elif defined(TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1
6444         rep << "ostype:bridgeos;";
6445 #else
6446         rep << "ostype:ios;";
6447 #endif
6448       } else {
6449         rep << "ostype:macosx;";
6450       }
6451     }
6452   }
6453 
6454   rep << "vendor:apple;";
6455 
6456 #if defined(__LITTLE_ENDIAN__)
6457   rep << "endian:little;";
6458 #elif defined(__BIG_ENDIAN__)
6459   rep << "endian:big;";
6460 #elif defined(__PDP_ENDIAN__)
6461   rep << "endian:pdp;";
6462 #endif
6463 
6464   if (addr_size == 0) {
6465 #if (defined(__x86_64__) || defined(__i386__)) && defined(x86_THREAD_STATE)
6466     nub_thread_t thread = DNBProcessGetCurrentThreadMachPort(pid);
6467     kern_return_t kr;
6468     x86_thread_state_t gp_regs;
6469     mach_msg_type_number_t gp_count = x86_THREAD_STATE_COUNT;
6470     kr = thread_get_state(static_cast<thread_act_t>(thread), x86_THREAD_STATE,
6471                           (thread_state_t)&gp_regs, &gp_count);
6472     if (kr == KERN_SUCCESS) {
6473       if (gp_regs.tsh.flavor == x86_THREAD_STATE64)
6474         rep << "ptrsize:8;";
6475       else
6476         rep << "ptrsize:4;";
6477     }
6478 #elif defined(__arm__)
6479     rep << "ptrsize:4;";
6480 #elif (defined(__arm64__) || defined(__aarch64__)) &&                          \
6481     defined(ARM_UNIFIED_THREAD_STATE)
6482     nub_thread_t thread = DNBProcessGetCurrentThreadMachPort(pid);
6483     kern_return_t kr;
6484     arm_unified_thread_state_t gp_regs;
6485     mach_msg_type_number_t gp_count = ARM_UNIFIED_THREAD_STATE_COUNT;
6486     kr = thread_get_state(thread, ARM_UNIFIED_THREAD_STATE,
6487                           (thread_state_t)&gp_regs, &gp_count);
6488     if (kr == KERN_SUCCESS) {
6489       if (gp_regs.ash.flavor == ARM_THREAD_STATE64)
6490         rep << "ptrsize:8;";
6491       else
6492         rep << "ptrsize:4;";
6493     }
6494 #endif
6495   }
6496 
6497   return SendPacket(rep.str());
6498 }
6499 
GetDispatchQueueOffsets()6500 const RNBRemote::DispatchQueueOffsets *RNBRemote::GetDispatchQueueOffsets() {
6501   if (!m_dispatch_queue_offsets.IsValid() &&
6502       m_dispatch_queue_offsets_addr != INVALID_NUB_ADDRESS &&
6503       m_ctx.HasValidProcessID()) {
6504     nub_process_t pid = m_ctx.ProcessID();
6505     nub_size_t bytes_read = DNBProcessMemoryRead(
6506         pid, m_dispatch_queue_offsets_addr, sizeof(m_dispatch_queue_offsets),
6507         &m_dispatch_queue_offsets);
6508     if (bytes_read != sizeof(m_dispatch_queue_offsets))
6509       m_dispatch_queue_offsets.Clear();
6510   }
6511 
6512   if (m_dispatch_queue_offsets.IsValid())
6513     return &m_dispatch_queue_offsets;
6514   else
6515     return nullptr;
6516 }
6517 
EnableCompressionNextSendPacket(compression_types type)6518 void RNBRemote::EnableCompressionNextSendPacket(compression_types type) {
6519   m_compression_mode = type;
6520   m_enable_compression_next_send_packet = true;
6521 }
6522 
GetCompressionType()6523 compression_types RNBRemote::GetCompressionType() {
6524   // The first packet we send back to the debugger after a QEnableCompression
6525   // request
6526   // should be uncompressed -- so we can indicate whether the compression was
6527   // enabled
6528   // or not via OK / Enn returns.  After that, all packets sent will be using
6529   // the
6530   // compression protocol.
6531 
6532   if (m_enable_compression_next_send_packet) {
6533     // One time, we send back "None" as our compression type
6534     m_enable_compression_next_send_packet = false;
6535     return compression_types::none;
6536   }
6537   return m_compression_mode;
6538 }
6539