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