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