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