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