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