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