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