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