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