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