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