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