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         DNBLogThreaded ("RNBRemote::HandlePacket_stop_process() sending extra stop reply because DNBProcessInterrupt returned false");
4437         HandlePacket_last_signal (NULL);
4438     }
4439     return rnb_success;
4440 #endif
4441 }
4442 
4443 /* 's'
4444  Step the inferior process.  */
4445 
4446 rnb_err_t
4447 RNBRemote::HandlePacket_s (const char *p)
4448 {
4449     const nub_process_t pid = m_ctx.ProcessID();
4450     if (pid == INVALID_NUB_PROCESS)
4451         return SendPacket ("E32");
4452 
4453     // Hardware supported stepping not supported on arm
4454     nub_thread_t tid = GetContinueThread ();
4455     if (tid == 0 || tid == (nub_thread_t)-1)
4456         tid = GetCurrentThread();
4457 
4458     if (tid == INVALID_NUB_THREAD)
4459         return SendPacket ("E33");
4460 
4461     DNBThreadResumeActions thread_actions;
4462     thread_actions.AppendAction(tid, eStateStepping);
4463 
4464     // Make all other threads stop when we are stepping
4465     thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0);
4466     if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize()))
4467         return SendPacket ("E49");
4468     // Don't send an "OK" packet; response is the stopped/exited message.
4469     return rnb_success;
4470 }
4471 
4472 /* 'S sig [;addr]'
4473  Step with signal sig, optionally at address addr.  */
4474 
4475 rnb_err_t
4476 RNBRemote::HandlePacket_S (const char *p)
4477 {
4478     const nub_process_t pid = m_ctx.ProcessID();
4479     if (pid == INVALID_NUB_PROCESS)
4480         return SendPacket ("E36");
4481 
4482     DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateStepping, 0, INVALID_NUB_ADDRESS };
4483 
4484     if (*(p + 1) != '\0')
4485     {
4486         char *end = NULL;
4487         errno = 0;
4488         action.signal = static_cast<int>(strtoul (p + 1, &end, 16));
4489         if (errno != 0)
4490             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in S packet");
4491         else if (*end == ';')
4492         {
4493             errno = 0;
4494             action.addr = strtoull (end + 1, NULL, 16);
4495             if (errno != 0 && action.addr == 0)
4496             {
4497                 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in S packet");
4498             }
4499         }
4500     }
4501 
4502     action.tid = GetContinueThread ();
4503     if (action.tid == 0 || action.tid == (nub_thread_t)-1)
4504         return SendPacket ("E40");
4505 
4506     nub_state_t tstate = DNBThreadGetState (pid, action.tid);
4507     if (tstate == eStateInvalid || tstate == eStateExited)
4508         return SendPacket ("E37");
4509 
4510 
4511     DNBThreadResumeActions thread_actions;
4512     thread_actions.Append (action);
4513 
4514     // Make all other threads stop when we are stepping
4515     thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
4516     if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize()))
4517         return SendPacket ("E39");
4518 
4519     // Don't send an "OK" packet; response is the stopped/exited message.
4520     return rnb_success;
4521 }
4522 
4523 static const char *
4524 GetArchName (const uint32_t cputype, const uint32_t cpusubtype)
4525 {
4526     switch (cputype)
4527     {
4528     case CPU_TYPE_ARM:
4529         switch (cpusubtype)
4530         {
4531         case 5:     return "armv4";
4532         case 6:     return "armv6";
4533         case 7:     return "armv5t";
4534         case 8:     return "xscale";
4535         case 9:     return "armv7";
4536         case 10:    return "armv7f";
4537         case 11:    return "armv7s";
4538         case 12:    return "armv7k";
4539         case 14:    return "armv6m";
4540         case 15:    return "armv7m";
4541         case 16:    return "armv7em";
4542         default:    return "arm";
4543         }
4544         break;
4545     case CPU_TYPE_ARM64:    return "arm64";
4546     case CPU_TYPE_I386:     return "i386";
4547     case CPU_TYPE_X86_64:
4548         switch (cpusubtype)
4549         {
4550         default:    return "x86_64";
4551         case 8:     return "x86_64h";
4552         }
4553         break;
4554     }
4555     return NULL;
4556 }
4557 
4558 static bool
4559 GetHostCPUType (uint32_t &cputype, uint32_t &cpusubtype, uint32_t &is_64_bit_capable, bool &promoted_to_64)
4560 {
4561     static uint32_t g_host_cputype = 0;
4562     static uint32_t g_host_cpusubtype = 0;
4563     static uint32_t g_is_64_bit_capable = 0;
4564     static bool g_promoted_to_64 = false;
4565 
4566     if (g_host_cputype == 0)
4567     {
4568         g_promoted_to_64 = false;
4569         size_t len = sizeof(uint32_t);
4570         if  (::sysctlbyname("hw.cputype", &g_host_cputype, &len, NULL, 0) == 0)
4571         {
4572             len = sizeof (uint32_t);
4573             if  (::sysctlbyname("hw.cpu64bit_capable", &g_is_64_bit_capable, &len, NULL, 0) == 0)
4574             {
4575                 if (g_is_64_bit_capable && ((g_host_cputype & CPU_ARCH_ABI64) == 0))
4576                 {
4577                     g_promoted_to_64 = true;
4578                     g_host_cputype |= CPU_ARCH_ABI64;
4579                 }
4580             }
4581         }
4582 
4583         len = sizeof(uint32_t);
4584         if (::sysctlbyname("hw.cpusubtype", &g_host_cpusubtype, &len, NULL, 0) == 0)
4585         {
4586             if (g_promoted_to_64 &&
4587                 g_host_cputype == CPU_TYPE_X86_64 && g_host_cpusubtype == CPU_SUBTYPE_486)
4588                 g_host_cpusubtype = CPU_SUBTYPE_X86_64_ALL;
4589         }
4590     }
4591 
4592     cputype = g_host_cputype;
4593     cpusubtype = g_host_cpusubtype;
4594     is_64_bit_capable = g_is_64_bit_capable;
4595     promoted_to_64 = g_promoted_to_64;
4596     return g_host_cputype != 0;
4597 }
4598 
4599 rnb_err_t
4600 RNBRemote::HandlePacket_qHostInfo (const char *p)
4601 {
4602     std::ostringstream strm;
4603 
4604     uint32_t cputype = 0;
4605     uint32_t cpusubtype = 0;
4606     uint32_t is_64_bit_capable = 0;
4607     bool promoted_to_64 = false;
4608     if (GetHostCPUType (cputype, cpusubtype, is_64_bit_capable, promoted_to_64))
4609     {
4610         strm << "cputype:" << std::dec << cputype << ';';
4611         strm << "cpusubtype:" << std::dec << cpusubtype << ';';
4612     }
4613 
4614     // The OS in the triple should be "ios" or "macosx" which doesn't match our
4615     // "Darwin" which gets returned from "kern.ostype", so we need to hardcode
4616     // this for now.
4617     if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64)
4618     {
4619 #if defined (TARGET_OS_TV) && TARGET_OS_TV == 1
4620         strm << "ostype:tvos;";
4621 #elif defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
4622         strm << "ostype:watchos;";
4623 #else
4624         strm << "ostype:ios;";
4625 #endif
4626 
4627         // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes.
4628         strm << "watchpoint_exceptions_received:before;";
4629     }
4630     else
4631     {
4632         strm << "ostype:macosx;";
4633         strm << "watchpoint_exceptions_received:after;";
4634     }
4635 //    char ostype[64];
4636 //    len = sizeof(ostype);
4637 //    if (::sysctlbyname("kern.ostype", &ostype, &len, NULL, 0) == 0)
4638 //    {
4639 //        len = strlen(ostype);
4640 //        std::transform (ostype, ostype + len, ostype, tolower);
4641 //        strm << "ostype:" << std::dec << ostype << ';';
4642 //    }
4643 
4644     strm << "vendor:apple;";
4645 
4646     uint64_t major, minor, patch;
4647     if (DNBGetOSVersionNumbers (&major, &minor, &patch))
4648     {
4649         strm << "os_version:" << major << "." << minor;
4650         if (patch != UINT64_MAX)
4651             strm << "." << patch;
4652         strm << ";";
4653     }
4654 
4655 #if defined (__LITTLE_ENDIAN__)
4656     strm << "endian:little;";
4657 #elif defined (__BIG_ENDIAN__)
4658     strm << "endian:big;";
4659 #elif defined (__PDP_ENDIAN__)
4660     strm << "endian:pdp;";
4661 #endif
4662 
4663     if (promoted_to_64)
4664         strm << "ptrsize:8;";
4665     else
4666         strm << "ptrsize:" << std::dec << sizeof(void *) << ';';
4667 
4668 #if defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
4669     strm << "default_packet_timeout:10;";
4670 #endif
4671 
4672     return SendPacket (strm.str());
4673 }
4674 
4675 void
4676 XMLElementStart (std::ostringstream &s, uint32_t indent, const char *name, bool has_attributes)
4677 {
4678     if (indent)
4679         s << INDENT_WITH_SPACES(indent);
4680     s << '<' << name;
4681     if (!has_attributes)
4682         s << '>' << std::endl;
4683 }
4684 
4685 void
4686 XMLElementStartEndAttributes (std::ostringstream &s, bool empty)
4687 {
4688     if (empty)
4689         s << '/';
4690     s << '>' << std::endl;
4691 }
4692 
4693 void
4694 XMLElementEnd (std::ostringstream &s, uint32_t indent, const char *name)
4695 {
4696     if (indent)
4697         s << INDENT_WITH_SPACES(indent);
4698     s << '<' << '/' << name << '>' << std::endl;
4699 }
4700 
4701 void
4702 XMLElementWithStringValue (std::ostringstream &s, uint32_t indent, const char *name, const char *value, bool close = true)
4703 {
4704     if (value)
4705     {
4706         if (indent)
4707             s << INDENT_WITH_SPACES(indent);
4708         s << '<' << name << '>' << value;
4709         if (close)
4710             XMLElementEnd(s, 0, name);
4711     }
4712 }
4713 
4714 void
4715 XMLElementWithUnsignedValue (std::ostringstream &s, uint32_t indent, const char *name, uint64_t value, bool close = true)
4716 {
4717     if (indent)
4718         s << INDENT_WITH_SPACES(indent);
4719 
4720     s << '<' << name << '>' << DECIMAL << value;
4721     if (close)
4722         XMLElementEnd(s, 0, name);
4723 }
4724 
4725 void
4726 XMLAttributeString (std::ostringstream &s, const char *name, const char *value, const char *default_value = NULL)
4727 {
4728     if (value)
4729     {
4730         if (default_value && strcmp(value, default_value) == 0)
4731             return; // No need to emit the attribute because it matches the default value
4732         s <<' ' << name << "=\"" << value << "\"";
4733     }
4734 }
4735 
4736 void
4737 XMLAttributeUnsignedDecimal (std::ostringstream &s, const char *name, uint64_t value)
4738 {
4739     s <<' ' << name << "=\"" << DECIMAL << value << "\"";
4740 }
4741 
4742 void
4743 GenerateTargetXMLRegister (std::ostringstream &s,
4744                            const uint32_t reg_num,
4745                            nub_size_t num_reg_sets,
4746                            const DNBRegisterSetInfo *reg_set_info,
4747                            const register_map_entry_t &reg)
4748 {
4749     const char *default_lldb_encoding = "uint";
4750     const char *lldb_encoding = default_lldb_encoding;
4751     const char *gdb_group = "general";
4752     const char *default_gdb_type = "int";
4753     const char *gdb_type = default_gdb_type;
4754     const char *default_lldb_format = "hex";
4755     const char *lldb_format = default_lldb_format;
4756     const char *lldb_set = NULL;
4757 
4758     switch (reg.nub_info.type)
4759     {
4760         case Uint:      lldb_encoding = "uint"; break;
4761         case Sint:      lldb_encoding = "sint"; break;
4762         case IEEE754:   lldb_encoding = "ieee754";  if (reg.nub_info.set > 0) gdb_group = "float"; break;
4763         case Vector:    lldb_encoding = "vector"; if (reg.nub_info.set > 0) gdb_group = "vector"; break;
4764     }
4765 
4766     switch (reg.nub_info.format)
4767     {
4768         case Binary:            lldb_format = "binary"; break;
4769         case Decimal:           lldb_format = "decimal"; break;
4770         case Hex:               lldb_format = "hex"; break;
4771         case Float:             gdb_type = "float"; lldb_format = "float"; break;
4772         case VectorOfSInt8:     gdb_type = "float"; lldb_format = "vector-sint8"; break;
4773         case VectorOfUInt8:     gdb_type = "float"; lldb_format = "vector-uint8"; break;
4774         case VectorOfSInt16:    gdb_type = "float"; lldb_format = "vector-sint16"; break;
4775         case VectorOfUInt16:    gdb_type = "float"; lldb_format = "vector-uint16"; break;
4776         case VectorOfSInt32:    gdb_type = "float"; lldb_format = "vector-sint32"; break;
4777         case VectorOfUInt32:    gdb_type = "float"; lldb_format = "vector-uint32"; break;
4778         case VectorOfFloat32:   gdb_type = "float"; lldb_format = "vector-float32"; break;
4779         case VectorOfUInt128:   gdb_type = "float"; lldb_format = "vector-uint128"; break;
4780     };
4781     if (reg_set_info && reg.nub_info.set < num_reg_sets)
4782         lldb_set = reg_set_info[reg.nub_info.set].name;
4783 
4784     uint32_t indent = 2;
4785 
4786     XMLElementStart(s, indent, "reg", true);
4787     XMLAttributeString(s, "name", reg.nub_info.name);
4788     XMLAttributeUnsignedDecimal(s, "regnum", reg_num);
4789     XMLAttributeUnsignedDecimal(s, "offset", reg.offset);
4790     XMLAttributeUnsignedDecimal(s, "bitsize", reg.nub_info.size * 8);
4791     XMLAttributeString(s, "group", gdb_group);
4792     XMLAttributeString(s, "type", gdb_type, default_gdb_type);
4793     XMLAttributeString (s, "altname", reg.nub_info.alt);
4794     XMLAttributeString(s, "encoding", lldb_encoding, default_lldb_encoding);
4795     XMLAttributeString(s, "format", lldb_format, default_lldb_format);
4796     XMLAttributeUnsignedDecimal(s, "group_id", reg.nub_info.set);
4797     if (reg.nub_info.reg_ehframe != INVALID_NUB_REGNUM)
4798         XMLAttributeUnsignedDecimal(s, "ehframe_regnum", reg.nub_info.reg_ehframe);
4799     if (reg.nub_info.reg_dwarf != INVALID_NUB_REGNUM)
4800         XMLAttributeUnsignedDecimal(s, "dwarf_regnum", reg.nub_info.reg_dwarf);
4801 
4802     const char *lldb_generic = NULL;
4803     switch (reg.nub_info.reg_generic)
4804     {
4805         case GENERIC_REGNUM_FP:     lldb_generic = "fp"; break;
4806         case GENERIC_REGNUM_PC:     lldb_generic = "pc"; break;
4807         case GENERIC_REGNUM_SP:     lldb_generic = "sp"; break;
4808         case GENERIC_REGNUM_RA:     lldb_generic = "ra"; break;
4809         case GENERIC_REGNUM_FLAGS:  lldb_generic = "flags"; break;
4810         case GENERIC_REGNUM_ARG1:   lldb_generic = "arg1"; break;
4811         case GENERIC_REGNUM_ARG2:   lldb_generic = "arg2"; break;
4812         case GENERIC_REGNUM_ARG3:   lldb_generic = "arg3"; break;
4813         case GENERIC_REGNUM_ARG4:   lldb_generic = "arg4"; break;
4814         case GENERIC_REGNUM_ARG5:   lldb_generic = "arg5"; break;
4815         case GENERIC_REGNUM_ARG6:   lldb_generic = "arg6"; break;
4816         case GENERIC_REGNUM_ARG7:   lldb_generic = "arg7"; break;
4817         case GENERIC_REGNUM_ARG8:   lldb_generic = "arg8"; break;
4818         default: break;
4819     }
4820     XMLAttributeString(s, "generic", lldb_generic);
4821 
4822 
4823     bool empty = reg.value_regnums.empty() && reg.invalidate_regnums.empty();
4824     if (!empty)
4825     {
4826         if (!reg.value_regnums.empty())
4827         {
4828             std::ostringstream regnums;
4829             bool first = true;
4830             regnums << DECIMAL;
4831             for (auto regnum : reg.value_regnums)
4832             {
4833                 if (!first)
4834                     regnums << ',';
4835                 regnums << regnum;
4836                 first = false;
4837             }
4838             XMLAttributeString(s, "value_regnums", regnums.str().c_str());
4839         }
4840 
4841         if (!reg.invalidate_regnums.empty())
4842         {
4843             std::ostringstream regnums;
4844             bool first = true;
4845             regnums << DECIMAL;
4846             for (auto regnum : reg.invalidate_regnums)
4847             {
4848                 if (!first)
4849                     regnums << ',';
4850                 regnums << regnum;
4851                 first = false;
4852             }
4853             XMLAttributeString(s, "invalidate_regnums", regnums.str().c_str());
4854         }
4855     }
4856     XMLElementStartEndAttributes(s, true);
4857 }
4858 
4859 void
4860 GenerateTargetXMLRegisters (std::ostringstream &s)
4861 {
4862     nub_size_t num_reg_sets = 0;
4863     const DNBRegisterSetInfo *reg_sets = DNBGetRegisterSetInfo (&num_reg_sets);
4864 
4865 
4866     uint32_t cputype = DNBGetRegisterCPUType();
4867     if (cputype)
4868     {
4869         XMLElementStart(s, 0, "feature", true);
4870         std::ostringstream name_strm;
4871         name_strm << "com.apple.debugserver." << GetArchName (cputype, 0);
4872         XMLAttributeString(s, "name", name_strm.str().c_str());
4873         XMLElementStartEndAttributes(s, false);
4874         for (uint32_t reg_num = 0; reg_num < g_num_reg_entries; ++reg_num)
4875 //        for (const auto &reg: g_dynamic_register_map)
4876         {
4877             GenerateTargetXMLRegister(s, reg_num, num_reg_sets, reg_sets, g_reg_entries[reg_num]);
4878         }
4879         XMLElementEnd(s, 0, "feature");
4880 
4881         if (num_reg_sets > 0)
4882         {
4883             XMLElementStart(s, 0, "groups", false);
4884             for (uint32_t set=1; set<num_reg_sets; ++set)
4885             {
4886                 XMLElementStart(s, 2, "group", true);
4887                 XMLAttributeUnsignedDecimal(s, "id", set);
4888                 XMLAttributeString(s, "name", reg_sets[set].name);
4889                 XMLElementStartEndAttributes(s, true);
4890             }
4891             XMLElementEnd(s, 0, "groups");
4892         }
4893     }
4894 }
4895 
4896 static const char *g_target_xml_header = R"(<?xml version="1.0"?>
4897 <target version="1.0">)";
4898 
4899 static const char *g_target_xml_footer = "</target>";
4900 
4901 static std::string g_target_xml;
4902 
4903 void
4904 UpdateTargetXML ()
4905 {
4906     std::ostringstream s;
4907     s << g_target_xml_header << std::endl;
4908 
4909     // Set the architecture
4910     //s << "<architecture>" << arch "</architecture>" << std::endl;
4911 
4912     // Set the OSABI
4913     //s << "<osabi>abi-name</osabi>"
4914 
4915     GenerateTargetXMLRegisters(s);
4916 
4917     s << g_target_xml_footer << std::endl;
4918 
4919     // Save the XML output in case it gets retrieved in chunks
4920     g_target_xml = s.str();
4921 }
4922 
4923 rnb_err_t
4924 RNBRemote::HandlePacket_qXfer (const char *command)
4925 {
4926     const char *p = command;
4927     p += strlen ("qXfer:");
4928     const char *sep = strchr(p, ':');
4929     if (sep)
4930     {
4931         std::string object(p, sep - p);     // "auxv", "backtrace", "features", etc
4932         p = sep + 1;
4933         sep = strchr(p, ':');
4934         if (sep)
4935         {
4936             std::string rw(p, sep - p);    // "read" or "write"
4937             p = sep + 1;
4938             sep = strchr(p, ':');
4939             if (sep)
4940             {
4941                 std::string annex(p, sep - p);    // "read" or "write"
4942 
4943                 p = sep + 1;
4944                 sep = strchr(p, ',');
4945                 if (sep)
4946                 {
4947                     std::string offset_str(p, sep - p); // read the length as a string
4948                     p = sep + 1;
4949                     std::string length_str(p); // read the offset as a string
4950                     char *end = nullptr;
4951                     const uint64_t offset = strtoul(offset_str.c_str(), &end, 16); // convert offset_str to a offset
4952                     if (*end == '\0')
4953                     {
4954                         const uint64_t length = strtoul(length_str.c_str(), &end, 16); // convert length_str to a length
4955                         if (*end == '\0')
4956                         {
4957                             if (object == "features"  &&
4958                                 rw     == "read"      &&
4959                                 annex  == "target.xml")
4960                             {
4961                                 std::ostringstream xml_out;
4962 
4963                                 if (offset == 0)
4964                                 {
4965                                     InitializeRegisters (true);
4966 
4967                                     UpdateTargetXML();
4968                                     if (g_target_xml.empty())
4969                                         return SendPacket("E83");
4970 
4971                                     if (length > g_target_xml.size())
4972                                     {
4973                                         xml_out << 'l'; // No more data
4974                                         xml_out << binary_encode_string(g_target_xml);
4975                                     }
4976                                     else
4977                                     {
4978                                         xml_out << 'm'; // More data needs to be read with a subsequent call
4979                                         xml_out << binary_encode_string(std::string(g_target_xml, offset, length));
4980                                     }
4981                                 }
4982                                 else
4983                                 {
4984                                     // Retrieving target XML in chunks
4985                                     if (offset < g_target_xml.size())
4986                                     {
4987                                         std::string chunk(g_target_xml, offset, length);
4988                                         if (chunk.size() < length)
4989                                             xml_out << 'l'; // No more data
4990                                         else
4991                                             xml_out << 'm'; // More data needs to be read with a subsequent call
4992                                         xml_out << binary_encode_string(chunk.data());
4993                                     }
4994                                 }
4995                                 return SendPacket(xml_out.str());
4996                             }
4997                             // Well formed, put not supported
4998                             return HandlePacket_UNIMPLEMENTED (command);
4999                         }
5000                     }
5001                 }
5002             }
5003             else
5004             {
5005                 SendPacket ("E85");
5006             }
5007         }
5008         else
5009         {
5010             SendPacket ("E86");
5011         }
5012     }
5013     return SendPacket ("E82");
5014 }
5015 
5016 
5017 rnb_err_t
5018 RNBRemote::HandlePacket_qGDBServerVersion (const char *p)
5019 {
5020     std::ostringstream strm;
5021 
5022 #if defined(DEBUGSERVER_PROGRAM_NAME)
5023     strm << "name:" DEBUGSERVER_PROGRAM_NAME ";";
5024 #else
5025     strm << "name:debugserver;";
5026 #endif
5027     strm << "version:" << DEBUGSERVER_VERSION_NUM << ";";
5028 
5029     return SendPacket (strm.str());
5030 }
5031 
5032 // A helper function that retrieves a single integer value from
5033 // a one-level-deep JSON dictionary of key-value pairs.  e.g.
5034 // jThreadExtendedInfo:{"plo_pthread_tsd_base_address_offset":0,"plo_pthread_tsd_base_offset":224,"plo_pthread_tsd_entry_size":8,"thread":144305}]
5035 //
5036 uint64_t
5037 get_integer_value_for_key_name_from_json (const char *key, const char *json_string)
5038 {
5039     uint64_t retval = INVALID_NUB_ADDRESS;
5040     std::string key_with_quotes = "\"";
5041     key_with_quotes += key;
5042     key_with_quotes += "\"";
5043     const char *c = strstr (json_string, key_with_quotes.c_str());
5044     if (c)
5045     {
5046         c += key_with_quotes.size();
5047 
5048         while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5049             c++;
5050 
5051         if (*c == ':')
5052         {
5053             c++;
5054 
5055             while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
5056                 c++;
5057 
5058             errno = 0;
5059             retval = strtoul (c, NULL, 10);
5060             if (errno != 0)
5061             {
5062                 retval = INVALID_NUB_ADDRESS;
5063             }
5064         }
5065     }
5066     return retval;
5067 
5068 }
5069 
5070 JSONGenerator::ObjectSP
5071 RNBRemote::GetJSONThreadsInfo(bool threads_with_valid_stop_info_only)
5072 {
5073     JSONGenerator::ArraySP threads_array_sp;
5074     if (m_ctx.HasValidProcessID())
5075     {
5076         threads_array_sp.reset(new JSONGenerator::Array());
5077 
5078         nub_process_t pid = m_ctx.ProcessID();
5079 
5080         nub_size_t numthreads = DNBProcessGetNumThreads (pid);
5081         for (nub_size_t i = 0; i < numthreads; ++i)
5082         {
5083             nub_thread_t tid = DNBProcessGetThreadAtIndex (pid, i);
5084 
5085             struct DNBThreadStopInfo tid_stop_info;
5086 
5087             const bool stop_info_valid = DNBThreadGetStopReason (pid, tid, &tid_stop_info);
5088 
5089             // If we are doing stop info only, then we only show threads that have a
5090             // valid stop reason
5091             if (threads_with_valid_stop_info_only)
5092             {
5093                 if (!stop_info_valid || tid_stop_info.reason == eStopTypeInvalid)
5094                     continue;
5095             }
5096 
5097             JSONGenerator::DictionarySP thread_dict_sp(new JSONGenerator::Dictionary());
5098             thread_dict_sp->AddIntegerItem("tid", tid);
5099 
5100             std::string reason_value("none");
5101 
5102             if (stop_info_valid)
5103             {
5104                 switch (tid_stop_info.reason)
5105                 {
5106                     case eStopTypeInvalid:
5107                         break;
5108 
5109                     case eStopTypeSignal:
5110                         if (tid_stop_info.details.signal.signo != 0)
5111                         {
5112                             thread_dict_sp->AddIntegerItem("signal", tid_stop_info.details.signal.signo);
5113                             reason_value = "signal";
5114                         }
5115                         break;
5116 
5117                     case eStopTypeException:
5118                         if (tid_stop_info.details.exception.type != 0)
5119                         {
5120                             reason_value = "exception";
5121                             thread_dict_sp->AddIntegerItem("metype", tid_stop_info.details.exception.type);
5122                             JSONGenerator::ArraySP medata_array_sp(new JSONGenerator::Array());
5123                             for (nub_size_t i=0; i<tid_stop_info.details.exception.data_count; ++i)
5124                             {
5125                                 medata_array_sp->AddItem(JSONGenerator::IntegerSP(new JSONGenerator::Integer(tid_stop_info.details.exception.data[i])));
5126                             }
5127                             thread_dict_sp->AddItem("medata", medata_array_sp);
5128                         }
5129                         break;
5130 
5131                     case eStopTypeExec:
5132                         reason_value = "exec";
5133                         break;
5134                 }
5135             }
5136 
5137             thread_dict_sp->AddStringItem("reason", reason_value);
5138 
5139             if (threads_with_valid_stop_info_only == false)
5140             {
5141                 const char *thread_name = DNBThreadGetName (pid, tid);
5142                 if (thread_name && thread_name[0])
5143                     thread_dict_sp->AddStringItem("name", thread_name);
5144 
5145                 thread_identifier_info_data_t thread_ident_info;
5146                 if (DNBThreadGetIdentifierInfo (pid, tid, &thread_ident_info))
5147                 {
5148                     if (thread_ident_info.dispatch_qaddr != 0)
5149                     {
5150                         thread_dict_sp->AddIntegerItem("qaddr", thread_ident_info.dispatch_qaddr);
5151 
5152                         const DispatchQueueOffsets *dispatch_queue_offsets = GetDispatchQueueOffsets();
5153                         if (dispatch_queue_offsets)
5154                         {
5155                             std::string queue_name;
5156                             uint64_t queue_width = 0;
5157                             uint64_t queue_serialnum = 0;
5158                             nub_addr_t dispatch_queue_t = INVALID_NUB_ADDRESS;
5159                             dispatch_queue_offsets->GetThreadQueueInfo(pid, thread_ident_info.dispatch_qaddr, dispatch_queue_t, queue_name, queue_width, queue_serialnum);
5160                             if (dispatch_queue_t == 0 && queue_name.empty() && queue_serialnum == 0)
5161                             {
5162                                 thread_dict_sp->AddBooleanItem ("associated_with_dispatch_queue", false);
5163                             }
5164                             else
5165                             {
5166                                 thread_dict_sp->AddBooleanItem ("associated_with_dispatch_queue", true);
5167                             }
5168                             if (dispatch_queue_t != INVALID_NUB_ADDRESS && dispatch_queue_t != 0)
5169                                 thread_dict_sp->AddIntegerItem("dispatch_queue_t", dispatch_queue_t);
5170                             if (!queue_name.empty())
5171                                 thread_dict_sp->AddStringItem("qname", queue_name);
5172                             if (queue_width == 1)
5173                                 thread_dict_sp->AddStringItem("qkind", "serial");
5174                             else if (queue_width > 1)
5175                                 thread_dict_sp->AddStringItem("qkind", "concurrent");
5176                             if (queue_serialnum > 0)
5177                                 thread_dict_sp->AddIntegerItem("qserialnum", queue_serialnum);
5178                         }
5179                     }
5180                 }
5181 
5182                 DNBRegisterValue reg_value;
5183 
5184                 if (g_reg_entries != NULL)
5185                 {
5186                     JSONGenerator::DictionarySP registers_dict_sp(new JSONGenerator::Dictionary());
5187 
5188                     for (uint32_t reg = 0; reg < g_num_reg_entries; reg++)
5189                     {
5190                         // Expedite all registers in the first register set that aren't
5191                         // contained in other registers
5192                         if (g_reg_entries[reg].nub_info.set == 1 &&
5193                             g_reg_entries[reg].nub_info.value_regs == NULL)
5194                         {
5195                             if (!DNBThreadGetRegisterValueByID (pid, tid, g_reg_entries[reg].nub_info.set, g_reg_entries[reg].nub_info.reg, &reg_value))
5196                                 continue;
5197 
5198                             std::ostringstream reg_num;
5199                             reg_num << std::dec << g_reg_entries[reg].debugserver_regnum;
5200                             // Encode native byte ordered bytes as hex ascii
5201                             registers_dict_sp->AddBytesAsHexASCIIString(reg_num.str(), reg_value.value.v_uint8, g_reg_entries[reg].nub_info.size);
5202                         }
5203                     }
5204                     thread_dict_sp->AddItem("registers", registers_dict_sp);
5205                 }
5206 
5207                 // Add expedited stack memory so stack backtracing doesn't need to read anything from the
5208                 // frame pointer chain.
5209                 StackMemoryMap stack_mmap;
5210                 ReadStackMemory (pid, tid, stack_mmap);
5211                 if (!stack_mmap.empty())
5212                 {
5213                     JSONGenerator::ArraySP memory_array_sp(new JSONGenerator::Array());
5214 
5215                     for (const auto &stack_memory : stack_mmap)
5216                     {
5217                         JSONGenerator::DictionarySP stack_memory_sp(new JSONGenerator::Dictionary());
5218                         stack_memory_sp->AddIntegerItem("address", stack_memory.first);
5219                         stack_memory_sp->AddBytesAsHexASCIIString("bytes", stack_memory.second.bytes, stack_memory.second.length);
5220                         memory_array_sp->AddItem(stack_memory_sp);
5221                     }
5222                     thread_dict_sp->AddItem("memory", memory_array_sp);
5223                 }
5224             }
5225 
5226             threads_array_sp->AddItem(thread_dict_sp);
5227         }
5228     }
5229     return threads_array_sp;
5230 }
5231 
5232 rnb_err_t
5233 RNBRemote::HandlePacket_jThreadsInfo (const char *p)
5234 {
5235     JSONGenerator::ObjectSP threads_info_sp;
5236     std::ostringstream json;
5237     std::ostringstream reply_strm;
5238     // If we haven't run the process yet, return an error.
5239     if (m_ctx.HasValidProcessID())
5240     {
5241         const bool threads_with_valid_stop_info_only = false;
5242         JSONGenerator::ObjectSP threads_info_sp = GetJSONThreadsInfo(threads_with_valid_stop_info_only);
5243 
5244         if (threads_info_sp)
5245         {
5246             std::ostringstream strm;
5247             threads_info_sp->Dump (strm);
5248             std::string binary_packet = binary_encode_string (strm.str());
5249             if (!binary_packet.empty())
5250                 return SendPacket (binary_packet.c_str());
5251         }
5252     }
5253     return SendPacket ("E85");
5254 
5255 }
5256 
5257 rnb_err_t
5258 RNBRemote::HandlePacket_jThreadExtendedInfo (const char *p)
5259 {
5260     nub_process_t pid;
5261     std::ostringstream json;
5262     // If we haven't run the process yet, return an error.
5263     if (!m_ctx.HasValidProcessID())
5264     {
5265         return SendPacket ("E81");
5266     }
5267 
5268     pid = m_ctx.ProcessID();
5269 
5270     const char thread_extended_info_str[] = { "jThreadExtendedInfo:{" };
5271     if (strncmp (p, thread_extended_info_str, sizeof (thread_extended_info_str) - 1) == 0)
5272     {
5273         p += strlen (thread_extended_info_str);
5274 
5275         uint64_t tid = get_integer_value_for_key_name_from_json ("thread", p);
5276         uint64_t plo_pthread_tsd_base_address_offset = get_integer_value_for_key_name_from_json ("plo_pthread_tsd_base_address_offset", p);
5277         uint64_t plo_pthread_tsd_base_offset = get_integer_value_for_key_name_from_json ("plo_pthread_tsd_base_offset", p);
5278         uint64_t plo_pthread_tsd_entry_size = get_integer_value_for_key_name_from_json ("plo_pthread_tsd_entry_size", p);
5279         uint64_t dti_qos_class_index = get_integer_value_for_key_name_from_json ("dti_qos_class_index", p);
5280         // Commented out the two variables below as they are not being used
5281 //        uint64_t dti_queue_index = get_integer_value_for_key_name_from_json ("dti_queue_index", p);
5282 //        uint64_t dti_voucher_index = get_integer_value_for_key_name_from_json ("dti_voucher_index", p);
5283 
5284         if (tid != INVALID_NUB_ADDRESS)
5285         {
5286             nub_addr_t pthread_t_value = DNBGetPThreadT (pid, tid);
5287 
5288             uint64_t tsd_address = INVALID_NUB_ADDRESS;
5289             if (plo_pthread_tsd_entry_size != INVALID_NUB_ADDRESS
5290                 && plo_pthread_tsd_base_offset != INVALID_NUB_ADDRESS
5291                 && plo_pthread_tsd_entry_size != INVALID_NUB_ADDRESS)
5292             {
5293                 tsd_address = DNBGetTSDAddressForThread (pid, tid, plo_pthread_tsd_base_address_offset, plo_pthread_tsd_base_offset, plo_pthread_tsd_entry_size);
5294             }
5295 
5296             bool timed_out = false;
5297             Genealogy::ThreadActivitySP thread_activity_sp;
5298 
5299             // If the pthread_t value is invalid, or if we were able to fetch the thread's TSD base
5300             // and got an invalid value back, then we have a thread in early startup or shutdown and
5301             // it's possible that gathering the genealogy information for this thread go badly.
5302             // Ideally fetching this info for a thread in these odd states shouldn't matter - but
5303             // we've seen some problems with these new SPI and threads in edge-casey states.
5304 
5305             double genealogy_fetch_time = 0;
5306             if (pthread_t_value != INVALID_NUB_ADDRESS && tsd_address != INVALID_NUB_ADDRESS)
5307             {
5308                 DNBTimer timer(false);
5309                 thread_activity_sp = DNBGetGenealogyInfoForThread (pid, tid, timed_out);
5310                 genealogy_fetch_time = timer.ElapsedMicroSeconds(false) / 1000000.0;
5311             }
5312 
5313             std::unordered_set<uint32_t> process_info_indexes; // an array of the process info #'s seen
5314 
5315             json << "{";
5316 
5317             bool need_to_print_comma = false;
5318 
5319             if (thread_activity_sp && timed_out == false)
5320             {
5321                 const Genealogy::Activity *activity = &thread_activity_sp->current_activity;
5322                 bool need_vouchers_comma_sep = false;
5323                 json << "\"activity_query_timed_out\":false,";
5324                 if (genealogy_fetch_time != 0)
5325                 {
5326                     //  If we append the floating point value with << we'll get it in scientific
5327                     //  notation.
5328                     char floating_point_ascii_buffer[64];
5329                     floating_point_ascii_buffer[0] = '\0';
5330                     snprintf (floating_point_ascii_buffer, sizeof (floating_point_ascii_buffer), "%f", genealogy_fetch_time);
5331                     if (strlen (floating_point_ascii_buffer) > 0)
5332                     {
5333                         if (need_to_print_comma)
5334                             json << ",";
5335                         need_to_print_comma = true;
5336                         json << "\"activity_query_duration\":" << floating_point_ascii_buffer;
5337                     }
5338                 }
5339                 if (activity->activity_id != 0)
5340                 {
5341                     if (need_to_print_comma)
5342                         json << ",";
5343                     need_to_print_comma = true;
5344                     need_vouchers_comma_sep = true;
5345                     json << "\"activity\":{";
5346                     json <<    "\"start\":" << activity->activity_start << ",";
5347                     json <<    "\"id\":" << activity->activity_id << ",";
5348                     json <<    "\"parent_id\":" << activity->parent_id << ",";
5349                     json <<    "\"name\":\"" << json_string_quote_metachars (activity->activity_name) << "\",";
5350                     json <<    "\"reason\":\"" << json_string_quote_metachars (activity->reason) << "\"";
5351                     json << "}";
5352                 }
5353                 if (thread_activity_sp->messages.size() > 0)
5354                 {
5355                     need_to_print_comma = true;
5356                     if (need_vouchers_comma_sep)
5357                         json << ",";
5358                     need_vouchers_comma_sep = true;
5359                     json << "\"trace_messages\":[";
5360                     bool printed_one_message = false;
5361                     for (auto iter = thread_activity_sp->messages.begin() ; iter != thread_activity_sp->messages.end(); ++iter)
5362                     {
5363                         if (printed_one_message)
5364                             json << ",";
5365                         else
5366                             printed_one_message = true;
5367                         json << "{";
5368                         json <<   "\"timestamp\":" << iter->timestamp << ",";
5369                         json <<   "\"activity_id\":" << iter->activity_id << ",";
5370                         json <<   "\"trace_id\":" << iter->trace_id << ",";
5371                         json <<   "\"thread\":" << iter->thread << ",";
5372                         json <<   "\"type\":" << (int) iter->type << ",";
5373                         json <<   "\"process_info_index\":" << iter->process_info_index << ",";
5374                         process_info_indexes.insert (iter->process_info_index);
5375                         json <<   "\"message\":\"" << json_string_quote_metachars (iter->message) << "\"";
5376                         json << "}";
5377                     }
5378                     json << "]";
5379                 }
5380                 if (thread_activity_sp->breadcrumbs.size() == 1)
5381                 {
5382                     need_to_print_comma = true;
5383                     if (need_vouchers_comma_sep)
5384                         json << ",";
5385                     need_vouchers_comma_sep = true;
5386                     json << "\"breadcrumb\":{";
5387                     for (auto iter = thread_activity_sp->breadcrumbs.begin() ; iter != thread_activity_sp->breadcrumbs.end(); ++iter)
5388                     {
5389                         json <<   "\"breadcrumb_id\":" << iter->breadcrumb_id << ",";
5390                         json <<   "\"activity_id\":" << iter->activity_id << ",";
5391                         json <<   "\"timestamp\":" << iter->timestamp << ",";
5392                         json <<   "\"name\":\"" << json_string_quote_metachars (iter->name) << "\"";
5393                     }
5394                     json << "}";
5395                 }
5396                 if (process_info_indexes.size() > 0)
5397                 {
5398                     need_to_print_comma = true;
5399                     if (need_vouchers_comma_sep)
5400                         json << ",";
5401                     need_vouchers_comma_sep = true;
5402                     json << "\"process_infos\":[";
5403                     bool printed_one_process_info = false;
5404                     for (auto iter = process_info_indexes.begin(); iter != process_info_indexes.end(); ++iter)
5405                     {
5406                         if (printed_one_process_info)
5407                             json << ",";
5408                         else
5409                             printed_one_process_info = true;
5410                         Genealogy::ProcessExecutableInfoSP image_info_sp;
5411                         uint32_t idx = *iter;
5412                         image_info_sp = DNBGetGenealogyImageInfo (pid, idx);
5413                         json << "{";
5414                         char uuid_buf[37];
5415                         uuid_unparse_upper (image_info_sp->image_uuid, uuid_buf);
5416                         json <<   "\"process_info_index\":" << idx << ",";
5417                         json <<  "\"image_path\":\"" << json_string_quote_metachars (image_info_sp->image_path) << "\",";
5418                         json <<  "\"image_uuid\":\"" << uuid_buf <<"\"";
5419                         json << "}";
5420                     }
5421                     json << "]";
5422                 }
5423             }
5424             else
5425             {
5426                 if (timed_out)
5427                 {
5428                     if (need_to_print_comma)
5429                         json << ",";
5430                     need_to_print_comma = true;
5431                     json << "\"activity_query_timed_out\":true";
5432                     if (genealogy_fetch_time != 0)
5433                     {
5434                         //  If we append the floating point value with << we'll get it in scientific
5435                         //  notation.
5436                         char floating_point_ascii_buffer[64];
5437                         floating_point_ascii_buffer[0] = '\0';
5438                         snprintf (floating_point_ascii_buffer, sizeof (floating_point_ascii_buffer), "%f", genealogy_fetch_time);
5439                         if (strlen (floating_point_ascii_buffer) > 0)
5440                         {
5441                             json << ",";
5442                             json << "\"activity_query_duration\":" << floating_point_ascii_buffer;
5443                         }
5444                     }
5445                 }
5446             }
5447 
5448             if (tsd_address != INVALID_NUB_ADDRESS)
5449             {
5450                 if (need_to_print_comma)
5451                     json << ",";
5452                 need_to_print_comma = true;
5453                 json << "\"tsd_address\":" << tsd_address;
5454 
5455                 if (dti_qos_class_index != 0 && dti_qos_class_index != UINT64_MAX)
5456                 {
5457                     ThreadInfo::QoS requested_qos = DNBGetRequestedQoSForThread (pid, tid, tsd_address, dti_qos_class_index);
5458                     if (requested_qos.IsValid())
5459                     {
5460                         if (need_to_print_comma)
5461                             json << ",";
5462                         need_to_print_comma = true;
5463                         json << "\"requested_qos\":{";
5464                         json <<    "\"enum_value\":" << requested_qos.enum_value << ",";
5465                         json <<    "\"constant_name\":\"" << json_string_quote_metachars (requested_qos.constant_name) << "\",";
5466                         json <<    "\"printable_name\":\"" << json_string_quote_metachars (requested_qos.printable_name) << "\"";
5467                         json << "}";
5468                     }
5469                 }
5470             }
5471 
5472             if (pthread_t_value != INVALID_NUB_ADDRESS)
5473             {
5474                 if (need_to_print_comma)
5475                     json << ",";
5476                 need_to_print_comma = true;
5477                 json << "\"pthread_t\":" << pthread_t_value;
5478             }
5479 
5480             nub_addr_t dispatch_queue_t_value = DNBGetDispatchQueueT (pid, tid);
5481             if (dispatch_queue_t_value != INVALID_NUB_ADDRESS)
5482             {
5483                 if (need_to_print_comma)
5484                     json << ",";
5485                 need_to_print_comma = true;
5486                 json << "\"dispatch_queue_t\":" << dispatch_queue_t_value;
5487             }
5488 
5489             json << "}";
5490             std::string json_quoted = binary_encode_string (json.str());
5491             return SendPacket (json_quoted);
5492         }
5493     }
5494     return SendPacket ("OK");
5495 }
5496 
5497 rnb_err_t
5498 RNBRemote::HandlePacket_jGetLoadedDynamicLibrariesInfos (const char *p)
5499 {
5500     nub_process_t pid;
5501     // If we haven't run the process yet, return an error.
5502     if (!m_ctx.HasValidProcessID())
5503     {
5504         return SendPacket ("E83");
5505     }
5506 
5507     pid = m_ctx.ProcessID();
5508 
5509     const char get_loaded_dynamic_libraries_infos_str[] = { "jGetLoadedDynamicLibrariesInfos:{" };
5510     if (strncmp (p, get_loaded_dynamic_libraries_infos_str, sizeof (get_loaded_dynamic_libraries_infos_str) - 1) == 0)
5511     {
5512         p += strlen (get_loaded_dynamic_libraries_infos_str);
5513 
5514         nub_addr_t image_list_address = get_integer_value_for_key_name_from_json ("image_list_address", p);
5515         nub_addr_t image_count = get_integer_value_for_key_name_from_json ("image_count", p);
5516 
5517         if (image_list_address != INVALID_NUB_ADDRESS && image_count != INVALID_NUB_ADDRESS)
5518         {
5519             JSONGenerator::ObjectSP json_sp;
5520 
5521             json_sp = DNBGetLoadedDynamicLibrariesInfos (pid, image_list_address, image_count);
5522 
5523             if (json_sp.get())
5524             {
5525                 std::ostringstream json_str;
5526                 json_sp->Dump (json_str);
5527                 if (json_str.str().size() > 0)
5528                 {
5529                     std::string json_str_quoted = binary_encode_string (json_str.str());
5530                     return SendPacket (json_str_quoted.c_str());
5531                 }
5532                 else
5533                 {
5534                     SendPacket ("E84");
5535                 }
5536             }
5537         }
5538     }
5539     return SendPacket ("OK");
5540 }
5541 
5542 static bool
5543 MachHeaderIsMainExecutable (nub_process_t pid, uint32_t addr_size, nub_addr_t mach_header_addr, mach_header &mh)
5544 {
5545     DNBLogThreadedIf (LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = %u, addr_size = %u, mach_header_addr = 0x%16.16llx)", pid, addr_size, mach_header_addr);
5546     const nub_size_t bytes_read = DNBProcessMemoryRead(pid, mach_header_addr, sizeof(mh), &mh);
5547     if (bytes_read == sizeof(mh))
5548     {
5549         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);
5550         if ((addr_size == 4 && mh.magic == MH_MAGIC) ||
5551             (addr_size == 8 && mh.magic == MH_MAGIC_64))
5552         {
5553             if (mh.filetype == MH_EXECUTE)
5554             {
5555                 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);
5556                 return true;
5557             }
5558         }
5559     }
5560     return false;
5561 }
5562 
5563 static nub_addr_t
5564 GetMachHeaderForMainExecutable (const nub_process_t pid, const uint32_t addr_size, mach_header &mh)
5565 {
5566     struct AllImageInfos
5567     {
5568         uint32_t version;
5569         uint32_t dylib_info_count;
5570         uint64_t dylib_info_addr;
5571     };
5572 
5573     uint64_t mach_header_addr = 0;
5574 
5575     const nub_addr_t shlib_addr = DNBProcessGetSharedLibraryInfoAddress (pid);
5576     uint8_t bytes[256];
5577     nub_size_t bytes_read = 0;
5578     DNBDataRef data (bytes, sizeof(bytes), false);
5579     DNBDataRef::offset_t offset = 0;
5580     data.SetPointerSize(addr_size);
5581 
5582     //----------------------------------------------------------------------
5583     // When we are sitting at __dyld_start, the kernel has placed the
5584     // address of the mach header of the main executable on the stack. If we
5585     // read the SP and dereference a pointer, we might find the mach header
5586     // for the executable. We also just make sure there is only 1 thread
5587     // since if we are at __dyld_start we shouldn't have multiple threads.
5588     //----------------------------------------------------------------------
5589     if (DNBProcessGetNumThreads(pid) == 1)
5590     {
5591         nub_thread_t tid = DNBProcessGetThreadAtIndex(pid, 0);
5592         if (tid != INVALID_NUB_THREAD)
5593         {
5594             DNBRegisterValue sp_value;
5595             if (DNBThreadGetRegisterValueByID(pid, tid, REGISTER_SET_GENERIC, GENERIC_REGNUM_SP, &sp_value))
5596             {
5597                 uint64_t sp = addr_size == 8 ? sp_value.value.uint64 : sp_value.value.uint32;
5598                 bytes_read = DNBProcessMemoryRead(pid, sp, addr_size, bytes);
5599                 if (bytes_read == addr_size)
5600                 {
5601                     offset = 0;
5602                     mach_header_addr = data.GetPointer(&offset);
5603                     if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, mh))
5604                         return mach_header_addr;
5605                 }
5606             }
5607         }
5608     }
5609 
5610     //----------------------------------------------------------------------
5611     // Check the dyld_all_image_info structure for a list of mach header
5612     // since it is a very easy thing to check
5613     //----------------------------------------------------------------------
5614     if (shlib_addr != INVALID_NUB_ADDRESS)
5615     {
5616         bytes_read = DNBProcessMemoryRead(pid, shlib_addr, sizeof(AllImageInfos), bytes);
5617         if (bytes_read > 0)
5618         {
5619             AllImageInfos aii;
5620             offset = 0;
5621             aii.version = data.Get32(&offset);
5622             aii.dylib_info_count = data.Get32(&offset);
5623             if (aii.dylib_info_count > 0)
5624             {
5625                 aii.dylib_info_addr = data.GetPointer(&offset);
5626                 if (aii.dylib_info_addr != 0)
5627                 {
5628                     const size_t image_info_byte_size = 3 * addr_size;
5629                     for (uint32_t i=0; i<aii.dylib_info_count; ++i)
5630                     {
5631                         bytes_read = DNBProcessMemoryRead(pid, aii.dylib_info_addr + i * image_info_byte_size, image_info_byte_size, bytes);
5632                         if (bytes_read != image_info_byte_size)
5633                             break;
5634                         offset = 0;
5635                         mach_header_addr = data.GetPointer(&offset);
5636                         if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, mh))
5637                             return mach_header_addr;
5638                     }
5639                 }
5640             }
5641         }
5642     }
5643 
5644     //----------------------------------------------------------------------
5645     // We failed to find the executable's mach header from the all image
5646     // infos and by dereferencing the stack pointer. Now we fall back to
5647     // enumerating the memory regions and looking for regions that are
5648     // executable.
5649     //----------------------------------------------------------------------
5650     DNBRegionInfo region_info;
5651     mach_header_addr = 0;
5652     while (DNBProcessMemoryRegionInfo(pid, mach_header_addr, &region_info))
5653     {
5654         if (region_info.size == 0)
5655             break;
5656 
5657         if (region_info.permissions & eMemoryPermissionsExecutable)
5658         {
5659             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' : '-');
5660             if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, mh))
5661                 return mach_header_addr;
5662         }
5663         else
5664         {
5665             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' : '-');
5666         }
5667         // Set the address to the next mapped region
5668         mach_header_addr = region_info.addr + region_info.size;
5669     }
5670     bzero (&mh, sizeof(mh));
5671     return INVALID_NUB_ADDRESS;
5672 }
5673 
5674 rnb_err_t
5675 RNBRemote::HandlePacket_qSymbol (const char *command)
5676 {
5677     const char *p = command;
5678     p += strlen ("qSymbol:");
5679     const char *sep = strchr(p, ':');
5680 
5681     std::string symbol_name;
5682     std::string symbol_value_str;
5683     // Extract the symbol value if there is one
5684     if (sep > p)
5685         symbol_value_str.assign(p, sep - p);
5686     p = sep + 1;
5687 
5688     if (*p)
5689     {
5690         // We have a symbol name
5691         symbol_name = std::move(decode_hex_ascii_string(p));
5692         if (!symbol_value_str.empty())
5693         {
5694             nub_addr_t symbol_value = decode_uint64(symbol_value_str.c_str(), 16);
5695             if (symbol_name == "dispatch_queue_offsets")
5696                 m_dispatch_queue_offsets_addr = symbol_value;
5697         }
5698         ++m_qSymbol_index;
5699     }
5700     else
5701     {
5702         // No symbol name, set our symbol index to zero so we can
5703         // read any symbols that we need
5704         m_qSymbol_index = 0;
5705     }
5706 
5707     symbol_name.clear();
5708 
5709     if (m_qSymbol_index == 0)
5710     {
5711         if (m_dispatch_queue_offsets_addr == INVALID_NUB_ADDRESS)
5712             symbol_name = "dispatch_queue_offsets";
5713         else
5714             ++m_qSymbol_index;
5715     }
5716 
5717 //    // Lookup next symbol when we have one...
5718 //    if (m_qSymbol_index == 1)
5719 //    {
5720 //    }
5721 
5722 
5723     if (symbol_name.empty())
5724     {
5725         // Done with symbol lookups
5726         return SendPacket ("OK");
5727     }
5728     else
5729     {
5730         std::ostringstream reply;
5731         reply << "qSymbol:";
5732         for (size_t i = 0; i < symbol_name.size(); ++i)
5733             reply << RAWHEX8(symbol_name[i]);
5734         return SendPacket (reply.str().c_str());
5735     }
5736 }
5737 
5738 // Note that all numeric values returned by qProcessInfo are hex encoded,
5739 // including the pid and the cpu type.
5740 
5741 rnb_err_t
5742 RNBRemote::HandlePacket_qProcessInfo (const char *p)
5743 {
5744     nub_process_t pid;
5745     std::ostringstream rep;
5746 
5747     // If we haven't run the process yet, return an error.
5748     if (!m_ctx.HasValidProcessID())
5749         return SendPacket ("E68");
5750 
5751     pid = m_ctx.ProcessID();
5752 
5753     rep << "pid:" << std::hex << pid << ';';
5754 
5755     int procpid_mib[4];
5756     procpid_mib[0] = CTL_KERN;
5757     procpid_mib[1] = KERN_PROC;
5758     procpid_mib[2] = KERN_PROC_PID;
5759     procpid_mib[3] = pid;
5760     struct kinfo_proc proc_kinfo;
5761     size_t proc_kinfo_size = sizeof(struct kinfo_proc);
5762 
5763     if (::sysctl (procpid_mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0)
5764     {
5765         if (proc_kinfo_size > 0)
5766         {
5767             rep << "parent-pid:" << std::hex << proc_kinfo.kp_eproc.e_ppid << ';';
5768             rep << "real-uid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_ruid << ';';
5769             rep << "real-gid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_rgid << ';';
5770             rep << "effective-uid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_uid << ';';
5771             if (proc_kinfo.kp_eproc.e_ucred.cr_ngroups > 0)
5772                 rep << "effective-gid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_groups[0] << ';';
5773         }
5774     }
5775 
5776     cpu_type_t cputype = DNBProcessGetCPUType (pid);
5777     if (cputype == 0)
5778     {
5779         DNBLog ("Unable to get the process cpu_type, making a best guess.");
5780         cputype = best_guess_cpu_type();
5781     }
5782 
5783     uint32_t addr_size = 0;
5784     if (cputype != 0)
5785     {
5786         rep << "cputype:" << std::hex << cputype << ";";
5787         if (cputype & CPU_ARCH_ABI64)
5788             addr_size = 8;
5789         else
5790             addr_size = 4;
5791     }
5792 
5793     bool host_cpu_is_64bit = false;
5794     uint32_t is64bit_capable;
5795     size_t is64bit_capable_len = sizeof (is64bit_capable);
5796     if (sysctlbyname("hw.cpu64bit_capable", &is64bit_capable, &is64bit_capable_len, NULL, 0) == 0)
5797         host_cpu_is_64bit = is64bit_capable != 0;
5798 
5799     uint32_t cpusubtype;
5800     size_t cpusubtype_len = sizeof(cpusubtype);
5801     if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &cpusubtype_len, NULL, 0) == 0)
5802     {
5803         // If a process is CPU_TYPE_X86, then ignore the cpusubtype that we detected
5804         // from the host and use CPU_SUBTYPE_I386_ALL because we don't want the
5805         // CPU_SUBTYPE_X86_ARCH1 or CPU_SUBTYPE_X86_64_H to be used as the cpu subtype
5806         // for i386...
5807         if (host_cpu_is_64bit)
5808         {
5809             if (cputype == CPU_TYPE_X86)
5810             {
5811                 cpusubtype = 3; // CPU_SUBTYPE_I386_ALL
5812             }
5813             else if (cputype == CPU_TYPE_ARM)
5814             {
5815                 // We can query a process' cputype but we cannot query a process' cpusubtype.
5816                 // If the process has cputype CPU_TYPE_ARM, then it is an armv7 (32-bit process) and we
5817                 // need to override the host cpusubtype (which is in the CPU_SUBTYPE_ARM64 subtype namespace)
5818                 // with a reasonable CPU_SUBTYPE_ARMV7 subtype.
5819                 cpusubtype = 11; // CPU_SUBTYPE_ARM_V7S
5820             }
5821         }
5822         rep << "cpusubtype:" << std::hex << cpusubtype << ';';
5823     }
5824 
5825     bool os_handled = false;
5826     if (addr_size > 0)
5827     {
5828         rep << "ptrsize:" << std::dec << addr_size << ';';
5829 
5830 #if (defined (__x86_64__) || defined (__i386__))
5831         // Try and get the OS type by looking at the load commands in the main
5832         // executable and looking for a LC_VERSION_MIN load command. This is the
5833         // most reliable way to determine the "ostype" value when on desktop.
5834 
5835         mach_header mh;
5836         nub_addr_t exe_mach_header_addr = GetMachHeaderForMainExecutable (pid, addr_size, mh);
5837         if (exe_mach_header_addr != INVALID_NUB_ADDRESS)
5838         {
5839             uint64_t load_command_addr = exe_mach_header_addr + ((addr_size == 8) ? sizeof(mach_header_64) : sizeof(mach_header));
5840             load_command lc;
5841             for (uint32_t i=0; i<mh.ncmds && !os_handled; ++i)
5842             {
5843                 const nub_size_t bytes_read = DNBProcessMemoryRead (pid, load_command_addr, sizeof(lc), &lc);
5844                 uint32_t raw_cmd = lc.cmd & ~LC_REQ_DYLD;
5845                 if (bytes_read != sizeof(lc))
5846                     break;
5847                 switch (raw_cmd)
5848                 {
5849                 case LC_VERSION_MIN_IPHONEOS:
5850                     os_handled = true;
5851                     rep << "ostype:ios;";
5852                     DNBLogThreadedIf (LOG_RNB_PROC, "LC_VERSION_MIN_IPHONEOS -> 'ostype:ios;'");
5853                     break;
5854 
5855                 case LC_VERSION_MIN_MACOSX:
5856                     os_handled = true;
5857                     rep << "ostype:macosx;";
5858                     DNBLogThreadedIf (LOG_RNB_PROC, "LC_VERSION_MIN_MACOSX -> 'ostype:macosx;'");
5859                     break;
5860 
5861 #if defined (LC_VERSION_MIN_TVOS)
5862                 case LC_VERSION_MIN_TVOS:
5863                     os_handled = true;
5864                     rep << "ostype:tvos;";
5865                     DNBLogThreadedIf (LOG_RNB_PROC, "LC_VERSION_MIN_TVOS -> 'ostype:tvos;'");
5866                     break;
5867 #endif
5868 
5869 #if defined (LC_VERSION_MIN_WATCHOS)
5870                 case LC_VERSION_MIN_WATCHOS:
5871                     os_handled = true;
5872                     rep << "ostype:watchos;";
5873                     DNBLogThreadedIf (LOG_RNB_PROC, "LC_VERSION_MIN_WATCHOS -> 'ostype:watchos;'");
5874                     break;
5875 #endif
5876 
5877                 default:
5878                     break;
5879                 }
5880                 load_command_addr = load_command_addr + lc.cmdsize;
5881             }
5882         }
5883 #endif
5884     }
5885 
5886     // If we weren't able to find the OS in a LC_VERSION_MIN load command, try
5887     // to set it correctly by using the cpu type and other tricks
5888     if (!os_handled)
5889     {
5890         // The OS in the triple should be "ios" or "macosx" which doesn't match our
5891         // "Darwin" which gets returned from "kern.ostype", so we need to hardcode
5892         // this for now.
5893         if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64)
5894         {
5895 #if defined (TARGET_OS_TV) && TARGET_OS_TV == 1
5896             rep << "ostype:tvos;";
5897 #elif defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
5898             rep << "ostype:watchos;";
5899 #else
5900             rep << "ostype:ios;";
5901 #endif
5902         }
5903         else
5904         {
5905             bool is_ios_simulator = false;
5906             if (cputype == CPU_TYPE_X86 || cputype == CPU_TYPE_X86_64)
5907             {
5908                 // Check for iOS simulator binaries by getting the process argument
5909                 // and environment and checking for SIMULATOR_UDID in the environment
5910                 int proc_args_mib[3] = { CTL_KERN, KERN_PROCARGS2, (int)pid };
5911 
5912                 uint8_t arg_data[8192];
5913                 size_t arg_data_size = sizeof(arg_data);
5914                 if (::sysctl (proc_args_mib, 3, arg_data, &arg_data_size , NULL, 0) == 0)
5915                 {
5916                     DNBDataRef data (arg_data, arg_data_size, false);
5917                     DNBDataRef::offset_t offset = 0;
5918                     uint32_t argc = data.Get32 (&offset);
5919                     const char *cstr;
5920 
5921                     cstr = data.GetCStr (&offset);
5922                     if (cstr)
5923                     {
5924                         // Skip NULLs
5925                         while (1)
5926                         {
5927                             const char *p = data.PeekCStr(offset);
5928                             if ((p == NULL) || (*p != '\0'))
5929                                 break;
5930                             ++offset;
5931                         }
5932                         // Now skip all arguments
5933                         for (uint32_t i = 0; i < argc; ++i)
5934                         {
5935                             data.GetCStr(&offset);
5936                         }
5937 
5938                         // Now iterate across all environment variables
5939                         while ((cstr = data.GetCStr(&offset)))
5940                         {
5941                             if (strncmp(cstr, "SIMULATOR_UDID=", strlen("SIMULATOR_UDID=")) == 0)
5942                             {
5943                                 is_ios_simulator = true;
5944                                 break;
5945                             }
5946                             if (cstr[0] == '\0')
5947                                 break;
5948 
5949                         }
5950                     }
5951                 }
5952             }
5953             if (is_ios_simulator)
5954             {
5955 #if defined (TARGET_OS_TV) && TARGET_OS_TV == 1
5956                 rep << "ostype:tvos;";
5957 #elif defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
5958                 rep << "ostype:watchos;";
5959 #else
5960                 rep << "ostype:ios;";
5961 #endif
5962             }
5963             else
5964             {
5965                 rep << "ostype:macosx;";
5966             }
5967         }
5968     }
5969 
5970     rep << "vendor:apple;";
5971 
5972 #if defined (__LITTLE_ENDIAN__)
5973     rep << "endian:little;";
5974 #elif defined (__BIG_ENDIAN__)
5975     rep << "endian:big;";
5976 #elif defined (__PDP_ENDIAN__)
5977     rep << "endian:pdp;";
5978 #endif
5979 
5980     if (addr_size == 0)
5981     {
5982 #if (defined (__x86_64__) || defined (__i386__)) && defined (x86_THREAD_STATE)
5983         nub_thread_t thread = DNBProcessGetCurrentThreadMachPort (pid);
5984         kern_return_t kr;
5985         x86_thread_state_t gp_regs;
5986         mach_msg_type_number_t gp_count = x86_THREAD_STATE_COUNT;
5987         kr = thread_get_state (static_cast<thread_act_t>(thread),
5988                                x86_THREAD_STATE,
5989                                (thread_state_t) &gp_regs,
5990                                &gp_count);
5991         if (kr == KERN_SUCCESS)
5992         {
5993             if (gp_regs.tsh.flavor == x86_THREAD_STATE64)
5994                 rep << "ptrsize:8;";
5995             else
5996                 rep << "ptrsize:4;";
5997         }
5998 #elif defined (__arm__)
5999         rep << "ptrsize:4;";
6000 #elif (defined (__arm64__) || defined (__aarch64__)) && defined (ARM_UNIFIED_THREAD_STATE)
6001         nub_thread_t thread = DNBProcessGetCurrentThreadMachPort (pid);
6002         kern_return_t kr;
6003         arm_unified_thread_state_t gp_regs;
6004         mach_msg_type_number_t gp_count = ARM_UNIFIED_THREAD_STATE_COUNT;
6005         kr = thread_get_state (thread, ARM_UNIFIED_THREAD_STATE,
6006                                (thread_state_t) &gp_regs, &gp_count);
6007         if (kr == KERN_SUCCESS)
6008         {
6009             if (gp_regs.ash.flavor == ARM_THREAD_STATE64)
6010                 rep << "ptrsize:8;";
6011             else
6012                 rep << "ptrsize:4;";
6013         }
6014 #endif
6015     }
6016 
6017     return SendPacket (rep.str());
6018 }
6019 
6020 const RNBRemote::DispatchQueueOffsets *
6021 RNBRemote::GetDispatchQueueOffsets()
6022 {
6023     if (!m_dispatch_queue_offsets.IsValid() && m_dispatch_queue_offsets_addr != INVALID_NUB_ADDRESS && m_ctx.HasValidProcessID())
6024     {
6025         nub_process_t pid = m_ctx.ProcessID();
6026         nub_size_t bytes_read = DNBProcessMemoryRead(pid, m_dispatch_queue_offsets_addr, sizeof(m_dispatch_queue_offsets), &m_dispatch_queue_offsets);
6027         if (bytes_read != sizeof(m_dispatch_queue_offsets))
6028             m_dispatch_queue_offsets.Clear();
6029     }
6030 
6031     if (m_dispatch_queue_offsets.IsValid())
6032         return &m_dispatch_queue_offsets;
6033     else
6034         return nullptr;
6035 }
6036 
6037 void
6038 RNBRemote::EnableCompressionNextSendPacket (compression_types type)
6039 {
6040     m_compression_mode = type;
6041     m_enable_compression_next_send_packet = true;
6042 }
6043 
6044 compression_types
6045 RNBRemote::GetCompressionType ()
6046 {
6047     // The first packet we send back to the debugger after a QEnableCompression request
6048     // should be uncompressed -- so we can indicate whether the compression was enabled
6049     // or not via OK / Enn returns.  After that, all packets sent will be using the
6050     // compression protocol.
6051 
6052     if (m_enable_compression_next_send_packet)
6053     {
6054         // One time, we send back "None" as our compression type
6055         m_enable_compression_next_send_packet = false;
6056         return compression_types::none;
6057     }
6058     return m_compression_mode;
6059 }
6060