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