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