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_z,             NULL, "Z2", "Insert write watchpoint"));
151     t.push_back (Packet (remove_write_watch_bp,         &RNBRemote::HandlePacket_z,             NULL, "z2", "Remove write watchpoint"));
152     t.push_back (Packet (insert_read_watch_bp,          &RNBRemote::HandlePacket_z,             NULL, "Z3", "Insert read watchpoint"));
153     t.push_back (Packet (remove_read_watch_bp,          &RNBRemote::HandlePacket_z,             NULL, "z3", "Remove read watchpoint"));
154     t.push_back (Packet (insert_access_watch_bp,        &RNBRemote::HandlePacket_z,             NULL, "Z4", "Insert access watchpoint"));
155     t.push_back (Packet (remove_access_watch_bp,        &RNBRemote::HandlePacket_z,             NULL, "z4", "Remove access watchpoint"));
156     t.push_back (Packet (query_current_thread_id,       &RNBRemote::HandlePacket_qC,            NULL, "qC", "Query current thread ID"));
157     t.push_back (Packet (query_get_pid,                 &RNBRemote::HandlePacket_qGetPid,       NULL, "qGetPid", "Query process id"));
158 //  t.push_back (Packet (query_memory_crc,              &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "qCRC:", "Compute CRC of memory region"));
159     t.push_back (Packet (query_thread_ids_first,        &RNBRemote::HandlePacket_qThreadInfo,   NULL, "qfThreadInfo", "Get list of active threads (first req)"));
160     t.push_back (Packet (query_thread_ids_subsequent,   &RNBRemote::HandlePacket_qThreadInfo,   NULL, "qsThreadInfo", "Get list of active threads (subsequent req)"));
161     // APPLE LOCAL: qThreadStopInfo
162     // syntax: qThreadStopInfoTTTT
163     //  TTTT is hex thread ID
164     t.push_back (Packet (query_thread_stop_info,        &RNBRemote::HandlePacket_qThreadStopInfo,   NULL, "qThreadStopInfo", "Get detailed info on why the specified thread stopped"));
165     t.push_back (Packet (query_thread_extra_info,       &RNBRemote::HandlePacket_qThreadExtraInfo,NULL, "qThreadExtraInfo", "Get printable status of a thread"));
166 //  t.push_back (Packet (query_image_offsets,           &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "qOffsets", "Report offset of loaded program"));
167     t.push_back (Packet (query_launch_success,          &RNBRemote::HandlePacket_qLaunchSuccess,NULL, "qLaunchSuccess", "Report the success or failure of the launch attempt"));
168     t.push_back (Packet (query_register_info,           &RNBRemote::HandlePacket_qRegisterInfo, NULL, "qRegisterInfo", "Dynamically discover remote register context information."));
169     t.push_back (Packet (query_shlib_notify_info_addr,  &RNBRemote::HandlePacket_qShlibInfoAddr,NULL, "qShlibInfoAddr", "Returns the address that contains info needed for getting shared library notifications"));
170     t.push_back (Packet (query_step_packet_supported,   &RNBRemote::HandlePacket_qStepPacketSupported,NULL, "qStepPacketSupported", "Replys with OK if the 's' packet is supported."));
171     t.push_back (Packet (query_host_info,               &RNBRemote::HandlePacket_qHostInfo,     NULL, "qHostInfo", "Replies with multiple 'key:value;' tuples appended to each other."));
172 //  t.push_back (Packet (query_symbol_lookup,           &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "qSymbol", "Notify that host debugger is ready to do symbol lookups"));
173     t.push_back (Packet (start_noack_mode,              &RNBRemote::HandlePacket_QStartNoAckMode        , NULL, "QStartNoAckMode", "Request that " DEBUGSERVER_PROGRAM_NAME " stop acking remote protocol packets"));
174     t.push_back (Packet (prefix_reg_packets_with_tid,   &RNBRemote::HandlePacket_QThreadSuffixSupported , NULL, "QThreadSuffixSupported", "Check if thread specifc packets (register packets 'g', 'G', 'p', and 'P') support having the thread ID appended to the end of the command"));
175     t.push_back (Packet (set_logging_mode,              &RNBRemote::HandlePacket_QSetLogging            , NULL, "QSetLogging:", "Check if register packets ('g', 'G', 'p', and 'P' support having the thread ID prefix"));
176     t.push_back (Packet (set_max_packet_size,           &RNBRemote::HandlePacket_QSetMaxPacketSize      , NULL, "QSetMaxPacketSize:", "Tell " DEBUGSERVER_PROGRAM_NAME " the max sized packet gdb can handle"));
177     t.push_back (Packet (set_max_payload_size,          &RNBRemote::HandlePacket_QSetMaxPayloadSize     , NULL, "QSetMaxPayloadSize:", "Tell " DEBUGSERVER_PROGRAM_NAME " the max sized payload gdb can handle"));
178     t.push_back (Packet (set_environment_variable,      &RNBRemote::HandlePacket_QEnvironment           , NULL, "QEnvironment:", "Add an environment variable to the inferior's environment"));
179     t.push_back (Packet (set_environment_variable_hex,  &RNBRemote::HandlePacket_QEnvironmentHexEncoded , NULL, "QEnvironmentHexEncoded:", "Add an environment variable to the inferior's environment"));
180     t.push_back (Packet (set_launch_arch,               &RNBRemote::HandlePacket_QLaunchArch            , NULL, "QLaunchArch:", "Set the architecture to use when launching a process for hosts that can run multiple architecture slices from universal files."));
181     t.push_back (Packet (set_disable_aslr,              &RNBRemote::HandlePacket_QSetDisableASLR        , NULL, "QSetDisableASLR:", "Set wether to disable ASLR when launching the process with the set argv ('A') packet"));
182     t.push_back (Packet (set_stdin,                     &RNBRemote::HandlePacket_QSetSTDIO              , NULL, "QSetSTDIN:", "Set the standard input for a process to be launched with the 'A' packet"));
183     t.push_back (Packet (set_stdout,                    &RNBRemote::HandlePacket_QSetSTDIO              , NULL, "QSetSTDOUT:", "Set the standard output for a process to be launched with the 'A' packet"));
184     t.push_back (Packet (set_stderr,                    &RNBRemote::HandlePacket_QSetSTDIO              , NULL, "QSetSTDERR:", "Set the standard error for a process to be launched with the 'A' packet"));
185     t.push_back (Packet (set_working_dir,               &RNBRemote::HandlePacket_QSetWorkingDir         , NULL, "QSetWorkingDir:", "Set the working directory for a process to be launched with the 'A' packet"));
186 //  t.push_back (Packet (pass_signals_to_inferior,      &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "QPassSignals:", "Specify which signals are passed to the inferior"));
187     t.push_back (Packet (allocate_memory,               &RNBRemote::HandlePacket_AllocateMemory, NULL, "_M", "Allocate memory in the inferior process."));
188     t.push_back (Packet (deallocate_memory,             &RNBRemote::HandlePacket_DeallocateMemory, NULL, "_m", "Deallocate memory in the inferior process."));
189 }
190 
191 
192 void
193 RNBRemote::FlushSTDIO ()
194 {
195     if (m_ctx.HasValidProcessID())
196     {
197         nub_process_t pid = m_ctx.ProcessID();
198         char buf[256];
199         nub_size_t count;
200         do
201         {
202             count = DNBProcessGetAvailableSTDOUT(pid, buf, sizeof(buf));
203             if (count > 0)
204             {
205                 SendSTDOUTPacket (buf, count);
206             }
207         } while (count > 0);
208 
209         do
210         {
211             count = DNBProcessGetAvailableSTDERR(pid, buf, sizeof(buf));
212             if (count > 0)
213             {
214                 SendSTDERRPacket (buf, count);
215             }
216         } while (count > 0);
217     }
218 }
219 
220 rnb_err_t
221 RNBRemote::SendHexEncodedBytePacket (const char *header, const void *buf, size_t buf_len, const char *footer)
222 {
223     std::ostringstream packet_sstrm;
224     // Append the header cstr if there was one
225     if (header && header[0])
226         packet_sstrm << header;
227     nub_size_t i;
228     const uint8_t *ubuf8 = (const uint8_t *)buf;
229     for (i=0; i<buf_len; i++)
230     {
231         packet_sstrm << RAWHEX8(ubuf8[i]);
232     }
233     // Append the footer cstr if there was one
234     if (footer && footer[0])
235         packet_sstrm << footer;
236 
237     return SendPacket(packet_sstrm.str());
238 }
239 
240 rnb_err_t
241 RNBRemote::SendSTDOUTPacket (char *buf, nub_size_t buf_size)
242 {
243     if (buf_size == 0)
244         return rnb_success;
245     return SendHexEncodedBytePacket("O", buf, buf_size, NULL);
246 }
247 
248 rnb_err_t
249 RNBRemote::SendSTDERRPacket (char *buf, nub_size_t buf_size)
250 {
251     if (buf_size == 0)
252         return rnb_success;
253     return SendHexEncodedBytePacket("O", buf, buf_size, NULL);
254 }
255 
256 rnb_err_t
257 RNBRemote::SendPacket (const std::string &s)
258 {
259     DNBLogThreadedIf (LOG_RNB_MAX, "%8d RNBRemote::%s (%s) called", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, s.c_str());
260     std::string sendpacket = "$" + s + "#";
261     int cksum = 0;
262     char hexbuf[5];
263 
264     if (m_noack_mode)
265     {
266         sendpacket += "00";
267     }
268     else
269     {
270         for (int i = 0; i != s.size(); ++i)
271             cksum += s[i];
272         snprintf (hexbuf, sizeof hexbuf, "%02x", cksum & 0xff);
273         sendpacket += hexbuf;
274     }
275 
276     rnb_err_t err = m_comm.Write (sendpacket.c_str(), sendpacket.size());
277     if (err != rnb_success)
278         return err;
279 
280     if (m_noack_mode)
281         return rnb_success;
282 
283     std::string reply;
284     RNBRemote::Packet packet;
285     err = GetPacket (reply, packet, true);
286 
287     if (err != rnb_success)
288     {
289         DNBLogThreadedIf (LOG_RNB_REMOTE, "%8d RNBRemote::%s (%s) got error trying to get reply...", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, sendpacket.c_str());
290         return err;
291     }
292 
293     DNBLogThreadedIf (LOG_RNB_MAX, "%8d RNBRemote::%s (%s) got reply: '%s'", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, sendpacket.c_str(), reply.c_str());
294 
295     if (packet.type == ack)
296         return rnb_success;
297 
298     // Should we try to resend the packet at this layer?
299     //  if (packet.command == nack)
300     return rnb_err;
301 }
302 
303 /* Get a packet via gdb remote protocol.
304  Strip off the prefix/suffix, verify the checksum to make sure
305  a valid packet was received, send an ACK if they match.  */
306 
307 rnb_err_t
308 RNBRemote::GetPacketPayload (std::string &return_packet)
309 {
310     //DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s called", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
311 
312     PThreadMutex::Locker locker(m_mutex);
313     if (m_rx_packets.empty())
314     {
315         // Only reset the remote command available event if we have no more packets
316         m_ctx.Events().ResetEvents ( RNBContext::event_read_packet_available );
317         //DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s error: no packets available...", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
318         return rnb_err;
319     }
320 
321     //DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s has %u queued packets", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, m_rx_packets.size());
322     return_packet.swap(m_rx_packets.front());
323     m_rx_packets.pop_front();
324     locker.Reset(); // Release our lock on the mutex
325 
326     if (m_rx_packets.empty())
327     {
328         // Reset the remote command available event if we have no more packets
329         m_ctx.Events().ResetEvents ( RNBContext::event_read_packet_available );
330     }
331 
332     //DNBLogThreadedIf (LOG_RNB_MEDIUM, "%8u RNBRemote::%s: '%s'", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, return_packet.c_str());
333 
334     switch (return_packet[0])
335     {
336         case '+':
337         case '-':
338         case '\x03':
339             break;
340 
341         case '$':
342         {
343             int packet_checksum = 0;
344             if (!m_noack_mode)
345             {
346                 for (int i = return_packet.size() - 2; i < return_packet.size(); ++i)
347                 {
348                     char checksum_char = tolower (return_packet[i]);
349                     if (!isxdigit (checksum_char))
350                     {
351                         m_comm.Write ("-", 1);
352                         DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s error: packet with invalid checksum characters: %s", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, return_packet.c_str());
353                         return rnb_err;
354                     }
355                 }
356                 packet_checksum = strtol (&return_packet[return_packet.size() - 2], NULL, 16);
357             }
358 
359             return_packet.erase(0,1);           // Strip the leading '$'
360             return_packet.erase(return_packet.size() - 3);// Strip the #XX checksum
361 
362             if (!m_noack_mode)
363             {
364                 // Compute the checksum
365                 int computed_checksum = 0;
366                 for (std::string::iterator it = return_packet.begin ();
367                      it != return_packet.end ();
368                      ++it)
369                 {
370                     computed_checksum += *it;
371                 }
372 
373                 if (packet_checksum == (computed_checksum & 0xff))
374                 {
375                     //DNBLogThreadedIf (LOG_RNB_MEDIUM, "%8u RNBRemote::%s sending ACK for '%s'", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, return_packet.c_str());
376                     m_comm.Write ("+", 1);
377                 }
378                 else
379                 {
380                     DNBLogThreadedIf (LOG_RNB_MEDIUM, "%8u RNBRemote::%s sending ACK for '%s' (error: packet checksum mismatch  (0x%2.2x != 0x%2.2x))",
381                                       (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
382                                       __FUNCTION__,
383                                       return_packet.c_str(),
384                                       packet_checksum,
385                                       computed_checksum);
386                     m_comm.Write ("-", 1);
387                     return rnb_err;
388                 }
389             }
390         }
391         break;
392 
393         default:
394             DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s tossing unexpected packet???? %s", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, return_packet.c_str());
395             if (!m_noack_mode)
396                 m_comm.Write ("-", 1);
397             return rnb_err;
398     }
399 
400     return rnb_success;
401 }
402 
403 rnb_err_t
404 RNBRemote::HandlePacket_UNIMPLEMENTED (const char* p)
405 {
406     DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s(\"%s\")", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, p ? p : "NULL");
407     return SendPacket ("");
408 }
409 
410 rnb_err_t
411 RNBRemote::HandlePacket_ILLFORMED (const char *file, int line, const char *p, const char *description)
412 {
413     DNBLogThreadedIf (LOG_RNB_PACKETS, "%8u %s:%i ILLFORMED: '%s' (%s)", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), file, line, __FUNCTION__, p);
414     return SendPacket ("E03");
415 }
416 
417 rnb_err_t
418 RNBRemote::GetPacket (std::string &packet_payload, RNBRemote::Packet& packet_info, bool wait)
419 {
420     std::string payload;
421     rnb_err_t err = GetPacketPayload (payload);
422     if (err != rnb_success)
423     {
424         PThreadEvent& events = m_ctx.Events();
425         nub_event_t set_events = events.GetEventBits();
426         // TODO: add timeout version of GetPacket?? We would then need to pass
427         // that timeout value along to DNBProcessTimedWaitForEvent.
428         if (!wait || ((set_events & RNBContext::event_read_thread_running) == 0))
429             return err;
430 
431         const nub_event_t events_to_wait_for = RNBContext::event_read_packet_available | RNBContext::event_read_thread_exiting;
432 
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_qGetPid (const char *p)
1398 {
1399     nub_process_t pid;
1400     std::ostringstream rep;
1401     // If we haven't run the process yet, we tell the debugger the
1402     // pid is 0.  That way it can know to tell use to run later on.
1403     if (m_ctx.HasValidProcessID())
1404         pid = m_ctx.ProcessID();
1405     else
1406         pid = 0;
1407     rep << std::hex << pid;
1408     return SendPacket (rep.str());
1409 }
1410 
1411 rnb_err_t
1412 RNBRemote::HandlePacket_qRegisterInfo (const char *p)
1413 {
1414     if (g_num_reg_entries == 0)
1415         InitializeRegisters ();
1416 
1417     p += strlen ("qRegisterInfo");
1418 
1419     nub_size_t num_reg_sets = 0;
1420     const DNBRegisterSetInfo *reg_set_info = DNBGetRegisterSetInfo (&num_reg_sets);
1421     uint32_t reg_num = strtoul(p, 0, 16);
1422 
1423     if (reg_num < g_num_reg_entries)
1424     {
1425         const register_map_entry_t *reg_entry = &g_reg_entries[reg_num];
1426         std::ostringstream ostrm;
1427         ostrm << "name:" << reg_entry->gdb_name << ';';
1428 
1429         if (reg_entry->nub_info.name && ::strcmp (reg_entry->gdb_name, reg_entry->nub_info.name))
1430             ostrm << "alt-name:" << reg_entry->nub_info.name << ';';
1431         else if (reg_entry->nub_info.alt && ::strcmp (reg_entry->gdb_name, reg_entry->nub_info.alt))
1432             ostrm << "alt-name:" << reg_entry->nub_info.alt << ';';
1433 
1434         ostrm << "bitsize:" << std::dec << reg_entry->gdb_size * 8 << ';';
1435         ostrm << "offset:" << std::dec << reg_entry->nub_info.offset << ';';
1436 
1437         switch (reg_entry->nub_info.type)
1438         {
1439             case Uint:      ostrm << "encoding:uint;"; break;
1440             case Sint:      ostrm << "encoding:sint;"; break;
1441             case IEEE754:   ostrm << "encoding:ieee754;"; break;
1442             case Vector:    ostrm << "encoding:vector;"; break;
1443         }
1444 
1445         switch (reg_entry->nub_info.format)
1446         {
1447             case Binary:            ostrm << "format:binary;"; break;
1448             case Decimal:           ostrm << "format:decimal;"; break;
1449             case Hex:               ostrm << "format:hex;"; break;
1450             case Float:             ostrm << "format:float;"; break;
1451             case VectorOfSInt8:     ostrm << "format:vector-sint8;"; break;
1452             case VectorOfUInt8:     ostrm << "format:vector-uint8;"; break;
1453             case VectorOfSInt16:    ostrm << "format:vector-sint16;"; break;
1454             case VectorOfUInt16:    ostrm << "format:vector-uint16;"; break;
1455             case VectorOfSInt32:    ostrm << "format:vector-sint32;"; break;
1456             case VectorOfUInt32:    ostrm << "format:vector-uint32;"; break;
1457             case VectorOfFloat32:   ostrm << "format:vector-float32;"; break;
1458             case VectorOfUInt128:   ostrm << "format:vector-uint128;"; break;
1459         };
1460 
1461         if (reg_set_info && reg_entry->nub_info.set < num_reg_sets)
1462             ostrm << "set:" << reg_set_info[reg_entry->nub_info.set].name << ';';
1463 
1464 
1465         if (g_reg_entries != g_dynamic_register_map.data())
1466         {
1467             if (reg_entry->nub_info.reg_gdb != INVALID_NUB_REGNUM && reg_entry->nub_info.reg_gdb != reg_num)
1468             {
1469                 printf("register %s is getting gdb reg_num of %u when the register info says %u\n",
1470                        reg_entry->gdb_name, reg_num, reg_entry->nub_info.reg_gdb);
1471             }
1472         }
1473 
1474         if (reg_entry->nub_info.reg_gcc != INVALID_NUB_REGNUM)
1475             ostrm << "gcc:" << std::dec << reg_entry->nub_info.reg_gcc << ';';
1476 
1477         if (reg_entry->nub_info.reg_dwarf != INVALID_NUB_REGNUM)
1478             ostrm << "dwarf:" << std::dec << reg_entry->nub_info.reg_dwarf << ';';
1479 
1480 
1481         switch (reg_entry->nub_info.reg_generic)
1482         {
1483             case GENERIC_REGNUM_FP:     ostrm << "generic:fp;"; break;
1484             case GENERIC_REGNUM_PC:     ostrm << "generic:pc;"; break;
1485             case GENERIC_REGNUM_SP:     ostrm << "generic:sp;"; break;
1486             case GENERIC_REGNUM_RA:     ostrm << "generic:ra;"; break;
1487             case GENERIC_REGNUM_FLAGS:  ostrm << "generic:flags;"; break;
1488             case GENERIC_REGNUM_ARG1:   ostrm << "generic:arg1;"; break;
1489             case GENERIC_REGNUM_ARG2:   ostrm << "generic:arg2;"; break;
1490             case GENERIC_REGNUM_ARG3:   ostrm << "generic:arg3;"; break;
1491             case GENERIC_REGNUM_ARG4:   ostrm << "generic:arg4;"; break;
1492             case GENERIC_REGNUM_ARG5:   ostrm << "generic:arg5;"; break;
1493             case GENERIC_REGNUM_ARG6:   ostrm << "generic:arg6;"; break;
1494             case GENERIC_REGNUM_ARG7:   ostrm << "generic:arg7;"; break;
1495             case GENERIC_REGNUM_ARG8:   ostrm << "generic:arg8;"; break;
1496             default: break;
1497         }
1498 
1499         return SendPacket (ostrm.str ());
1500     }
1501     return SendPacket ("E45");
1502 }
1503 
1504 
1505 /* This expects a packet formatted like
1506 
1507  QSetLogging:bitmask=LOG_ALL|LOG_RNB_REMOTE;
1508 
1509  with the "QSetLogging:" already removed from the start.  Maybe in the
1510  future this packet will include other keyvalue pairs like
1511 
1512  QSetLogging:bitmask=LOG_ALL;mode=asl;
1513  */
1514 
1515 rnb_err_t
1516 set_logging (const char *p)
1517 {
1518     int bitmask = 0;
1519     while (p && *p != '\0')
1520     {
1521         if (strncmp (p, "bitmask=", sizeof ("bitmask=") - 1) == 0)
1522         {
1523             p += sizeof ("bitmask=") - 1;
1524             while (p && *p != '\0' && *p != ';')
1525             {
1526                 if (*p == '|')
1527                     p++;
1528                 if (strncmp (p, "LOG_VERBOSE", sizeof ("LOG_VERBOSE") - 1) == 0)
1529                 {
1530                     p += sizeof ("LOG_VERBOSE") - 1;
1531                     bitmask |= LOG_VERBOSE;
1532                 }
1533                 else if (strncmp (p, "LOG_PROCESS", sizeof ("LOG_PROCESS") - 1) == 0)
1534                 {
1535                     p += sizeof ("LOG_PROCESS") - 1;
1536                     bitmask |= LOG_PROCESS;
1537                 }
1538                 else if (strncmp (p, "LOG_THREAD", sizeof ("LOG_THREAD") - 1) == 0)
1539                 {
1540                     p += sizeof ("LOG_THREAD") - 1;
1541                     bitmask |= LOG_THREAD;
1542                 }
1543                 else if (strncmp (p, "LOG_EXCEPTIONS", sizeof ("LOG_EXCEPTIONS") - 1) == 0)
1544                 {
1545                     p += sizeof ("LOG_EXCEPTIONS") - 1;
1546                     bitmask |= LOG_EXCEPTIONS;
1547                 }
1548                 else if (strncmp (p, "LOG_SHLIB", sizeof ("LOG_SHLIB") - 1) == 0)
1549                 {
1550                     p += sizeof ("LOG_SHLIB") - 1;
1551                     bitmask |= LOG_SHLIB;
1552                 }
1553                 else if (strncmp (p, "LOG_MEMORY", sizeof ("LOG_MEMORY") - 1) == 0)
1554                 {
1555                     p += sizeof ("LOG_MEMORY") - 1;
1556                     bitmask |= LOG_MEMORY;
1557                 }
1558                 else if (strncmp (p, "LOG_MEMORY_DATA_SHORT", sizeof ("LOG_MEMORY_DATA_SHORT") - 1) == 0)
1559                 {
1560                     p += sizeof ("LOG_MEMORY_DATA_SHORT") - 1;
1561                     bitmask |= LOG_MEMORY_DATA_SHORT;
1562                 }
1563                 else if (strncmp (p, "LOG_MEMORY_DATA_LONG", sizeof ("LOG_MEMORY_DATA_LONG") - 1) == 0)
1564                 {
1565                     p += sizeof ("LOG_MEMORY_DATA_LONG") - 1;
1566                     bitmask |= LOG_MEMORY_DATA_LONG;
1567                 }
1568                 else if (strncmp (p, "LOG_BREAKPOINTS", sizeof ("LOG_BREAKPOINTS") - 1) == 0)
1569                 {
1570                     p += sizeof ("LOG_BREAKPOINTS") - 1;
1571                     bitmask |= LOG_BREAKPOINTS;
1572                 }
1573                 else if (strncmp (p, "LOG_ALL", sizeof ("LOG_ALL") - 1) == 0)
1574                 {
1575                     p += sizeof ("LOG_ALL") - 1;
1576                     bitmask |= LOG_ALL;
1577                 }
1578                 else if (strncmp (p, "LOG_EVENTS", sizeof ("LOG_EVENTS") - 1) == 0)
1579                 {
1580                     p += sizeof ("LOG_EVENTS") - 1;
1581                     bitmask |= LOG_EVENTS;
1582                 }
1583                 else if (strncmp (p, "LOG_DEFAULT", sizeof ("LOG_DEFAULT") - 1) == 0)
1584                 {
1585                     p += sizeof ("LOG_DEFAULT") - 1;
1586                     bitmask |= LOG_DEFAULT;
1587                 }
1588                 else if (strncmp (p, "LOG_NONE", sizeof ("LOG_NONE") - 1) == 0)
1589                 {
1590                     p += sizeof ("LOG_NONE") - 1;
1591                     bitmask = 0;
1592                 }
1593                 else if (strncmp (p, "LOG_RNB_MINIMAL", sizeof ("LOG_RNB_MINIMAL") - 1) == 0)
1594                 {
1595                     p += sizeof ("LOG_RNB_MINIMAL") - 1;
1596                     bitmask |= LOG_RNB_MINIMAL;
1597                 }
1598                 else if (strncmp (p, "LOG_RNB_MEDIUM", sizeof ("LOG_RNB_MEDIUM") - 1) == 0)
1599                 {
1600                     p += sizeof ("LOG_RNB_MEDIUM") - 1;
1601                     bitmask |= LOG_RNB_MEDIUM;
1602                 }
1603                 else if (strncmp (p, "LOG_RNB_MAX", sizeof ("LOG_RNB_MAX") - 1) == 0)
1604                 {
1605                     p += sizeof ("LOG_RNB_MAX") - 1;
1606                     bitmask |= LOG_RNB_MAX;
1607                 }
1608                 else if (strncmp (p, "LOG_RNB_COMM", sizeof ("LOG_RNB_COMM") - 1) == 0)
1609                 {
1610                     p += sizeof ("LOG_RNB_COMM") - 1;
1611                     bitmask |= LOG_RNB_COMM;
1612                 }
1613                 else if (strncmp (p, "LOG_RNB_REMOTE", sizeof ("LOG_RNB_REMOTE") - 1) == 0)
1614                 {
1615                     p += sizeof ("LOG_RNB_REMOTE") - 1;
1616                     bitmask |= LOG_RNB_REMOTE;
1617                 }
1618                 else if (strncmp (p, "LOG_RNB_EVENTS", sizeof ("LOG_RNB_EVENTS") - 1) == 0)
1619                 {
1620                     p += sizeof ("LOG_RNB_EVENTS") - 1;
1621                     bitmask |= LOG_RNB_EVENTS;
1622                 }
1623                 else if (strncmp (p, "LOG_RNB_PROC", sizeof ("LOG_RNB_PROC") - 1) == 0)
1624                 {
1625                     p += sizeof ("LOG_RNB_PROC") - 1;
1626                     bitmask |= LOG_RNB_PROC;
1627                 }
1628                 else if (strncmp (p, "LOG_RNB_PACKETS", sizeof ("LOG_RNB_PACKETS") - 1) == 0)
1629                 {
1630                     p += sizeof ("LOG_RNB_PACKETS") - 1;
1631                     bitmask |= LOG_RNB_PACKETS;
1632                 }
1633                 else if (strncmp (p, "LOG_RNB_ALL", sizeof ("LOG_RNB_ALL") - 1) == 0)
1634                 {
1635                     p += sizeof ("LOG_RNB_ALL") - 1;
1636                     bitmask |= LOG_RNB_ALL;
1637                 }
1638                 else if (strncmp (p, "LOG_RNB_DEFAULT", sizeof ("LOG_RNB_DEFAULT") - 1) == 0)
1639                 {
1640                     p += sizeof ("LOG_RNB_DEFAULT") - 1;
1641                     bitmask |= LOG_RNB_DEFAULT;
1642                 }
1643                 else if (strncmp (p, "LOG_RNB_NONE", sizeof ("LOG_RNB_NONE") - 1) == 0)
1644                 {
1645                     p += sizeof ("LOG_RNB_NONE") - 1;
1646                     bitmask = 0;
1647                 }
1648                 else
1649                 {
1650                     /* Unrecognized logging bit; ignore it.  */
1651                     const char *c = strchr (p, '|');
1652                     if (c)
1653                     {
1654                         p = c;
1655                     }
1656                     else
1657                     {
1658                         c = strchr (p, ';');
1659                         if (c)
1660                         {
1661                             p = c;
1662                         }
1663                         else
1664                         {
1665                             // Improperly terminated word; just go to end of str
1666                             p = strchr (p, '\0');
1667                         }
1668                     }
1669                 }
1670             }
1671             // Did we get a properly formatted logging bitmask?
1672             if (*p == ';')
1673             {
1674                 // Enable DNB logging
1675                 DNBLogSetLogCallback(ASLLogCallback, NULL);
1676                 DNBLogSetLogMask (bitmask);
1677                 p++;
1678             }
1679         }
1680         // We're not going to support logging to a file for now.  All logging
1681         // goes through ASL.
1682 #if 0
1683         else if (strncmp (p, "mode=", sizeof ("mode=") - 1) == 0)
1684         {
1685             p += sizeof ("mode=") - 1;
1686             if (strncmp (p, "asl;", sizeof ("asl;") - 1) == 0)
1687             {
1688                 DNBLogToASL ();
1689                 p += sizeof ("asl;") - 1;
1690             }
1691             else if (strncmp (p, "file;", sizeof ("file;") - 1) == 0)
1692             {
1693                 DNBLogToFile ();
1694                 p += sizeof ("file;") - 1;
1695             }
1696             else
1697             {
1698                 // Ignore unknown argument
1699                 const char *c = strchr (p, ';');
1700                 if (c)
1701                     p = c + 1;
1702                 else
1703                     p = strchr (p, '\0');
1704             }
1705         }
1706         else if (strncmp (p, "filename=", sizeof ("filename=") - 1) == 0)
1707         {
1708             p += sizeof ("filename=") - 1;
1709             const char *c = strchr (p, ';');
1710             if (c == NULL)
1711             {
1712                 c = strchr (p, '\0');
1713                 continue;
1714             }
1715             char *fn = (char *) alloca (c - p + 1);
1716             strncpy (fn, p, c - p);
1717             fn[c - p] = '\0';
1718 
1719             // A file name of "asl" is special and is another way to indicate
1720             // that logging should be done via ASL, not by file.
1721             if (strcmp (fn, "asl") == 0)
1722             {
1723                 DNBLogToASL ();
1724             }
1725             else
1726             {
1727                 FILE *f = fopen (fn, "w");
1728                 if (f)
1729                 {
1730                     DNBLogSetLogFile (f);
1731                     DNBEnableLogging (f, DNBLogGetLogMask ());
1732                     DNBLogToFile ();
1733                 }
1734             }
1735             p = c + 1;
1736         }
1737 #endif /* #if 0 to enforce ASL logging only.  */
1738         else
1739         {
1740             // Ignore unknown argument
1741             const char *c = strchr (p, ';');
1742             if (c)
1743                 p = c + 1;
1744             else
1745                 p = strchr (p, '\0');
1746         }
1747     }
1748 
1749     return rnb_success;
1750 }
1751 
1752 rnb_err_t
1753 RNBRemote::HandlePacket_QThreadSuffixSupported (const char *p)
1754 {
1755     m_thread_suffix_supported = true;
1756     return SendPacket ("OK");
1757 }
1758 
1759 rnb_err_t
1760 RNBRemote::HandlePacket_QStartNoAckMode (const char *p)
1761 {
1762     // Send the OK packet first so the correct checksum is appended...
1763     rnb_err_t result = SendPacket ("OK");
1764     m_noack_mode = true;
1765     return result;
1766 }
1767 
1768 
1769 rnb_err_t
1770 RNBRemote::HandlePacket_QSetLogging (const char *p)
1771 {
1772     p += sizeof ("QSetLogging:") - 1;
1773     rnb_err_t result = set_logging (p);
1774     if (result == rnb_success)
1775         return SendPacket ("OK");
1776     else
1777         return SendPacket ("E35");
1778 }
1779 
1780 rnb_err_t
1781 RNBRemote::HandlePacket_QSetDisableASLR (const char *p)
1782 {
1783     extern int g_disable_aslr;
1784     p += sizeof ("QSetDisableASLR:") - 1;
1785     switch (*p)
1786     {
1787     case '0': g_disable_aslr = 0; break;
1788     case '1': g_disable_aslr = 1; break;
1789     default:
1790         return SendPacket ("E56");
1791     }
1792     return SendPacket ("OK");
1793 }
1794 
1795 rnb_err_t
1796 RNBRemote::HandlePacket_QSetSTDIO (const char *p)
1797 {
1798     // Only set stdin/out/err if we don't already have a process
1799     if (!m_ctx.HasValidProcessID())
1800     {
1801         bool success = false;
1802         // Check the seventh character since the packet will be one of:
1803         // QSetSTDIN
1804         // QSetSTDOUT
1805         // QSetSTDERR
1806         StringExtractor packet(p);
1807         packet.SetFilePos (7);
1808         char ch = packet.GetChar();
1809         while (packet.GetChar() != ':')
1810             /* Do nothing. */;
1811 
1812         switch (ch)
1813         {
1814             case 'I': // STDIN
1815                 packet.GetHexByteString (m_ctx.GetSTDIN());
1816                 success = !m_ctx.GetSTDIN().empty();
1817                 break;
1818 
1819             case 'O': // STDOUT
1820                 packet.GetHexByteString (m_ctx.GetSTDOUT());
1821                 success = !m_ctx.GetSTDOUT().empty();
1822                 break;
1823 
1824             case 'E': // STDERR
1825                 packet.GetHexByteString (m_ctx.GetSTDERR());
1826                 success = !m_ctx.GetSTDERR().empty();
1827                 break;
1828 
1829             default:
1830                 break;
1831         }
1832         if (success)
1833             return SendPacket ("OK");
1834         return SendPacket ("E57");
1835     }
1836     return SendPacket ("E58");
1837 }
1838 
1839 rnb_err_t
1840 RNBRemote::HandlePacket_QSetWorkingDir (const char *p)
1841 {
1842     // Only set the working directory if we don't already have a process
1843     if (!m_ctx.HasValidProcessID())
1844     {
1845         StringExtractor packet(p += sizeof ("QSetWorkingDir:") - 1);
1846         if (packet.GetHexByteString (m_ctx.GetWorkingDir()))
1847         {
1848             struct stat working_dir_stat;
1849             if (::stat(m_ctx.GetWorkingDirPath(), &working_dir_stat) == -1)
1850             {
1851                 m_ctx.GetWorkingDir().clear();
1852                 return SendPacket ("E61");    // Working directory doesn't exist...
1853             }
1854             else if ((working_dir_stat.st_mode & S_IFMT) == S_IFDIR)
1855             {
1856                 return SendPacket ("OK");
1857             }
1858             else
1859             {
1860                 m_ctx.GetWorkingDir().clear();
1861                 return SendPacket ("E62");    // Working directory isn't a directory...
1862             }
1863         }
1864         return SendPacket ("E59");  // Invalid path
1865     }
1866     return SendPacket ("E60"); // Already had a process, too late to set working dir
1867 }
1868 
1869 
1870 rnb_err_t
1871 RNBRemote::HandlePacket_QSetMaxPayloadSize (const char *p)
1872 {
1873     /* The number of characters in a packet payload that gdb is
1874      prepared to accept.  The packet-start char, packet-end char,
1875      2 checksum chars and terminating null character are not included
1876      in this size.  */
1877     p += sizeof ("QSetMaxPayloadSize:") - 1;
1878     errno = 0;
1879     uint32_t size = strtoul (p, NULL, 16);
1880     if (errno != 0 && size == 0)
1881     {
1882         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in QSetMaxPayloadSize packet");
1883     }
1884     m_max_payload_size = size;
1885     return SendPacket ("OK");
1886 }
1887 
1888 rnb_err_t
1889 RNBRemote::HandlePacket_QSetMaxPacketSize (const char *p)
1890 {
1891     /* This tells us the largest packet that gdb can handle.
1892      i.e. the size of gdb's packet-reading buffer.
1893      QSetMaxPayloadSize is preferred because it is less ambiguous.  */
1894     p += sizeof ("QSetMaxPacketSize:") - 1;
1895     errno = 0;
1896     uint32_t size = strtoul (p, NULL, 16);
1897     if (errno != 0 && size == 0)
1898     {
1899         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in QSetMaxPacketSize packet");
1900     }
1901     m_max_payload_size = size - 5;
1902     return SendPacket ("OK");
1903 }
1904 
1905 
1906 
1907 
1908 rnb_err_t
1909 RNBRemote::HandlePacket_QEnvironment (const char *p)
1910 {
1911     /* This sets the environment for the target program.  The packet is of the form:
1912 
1913      QEnvironment:VARIABLE=VALUE
1914 
1915      */
1916 
1917     DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s Handling QEnvironment: \"%s\"",
1918                       (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, p);
1919 
1920     p += sizeof ("QEnvironment:") - 1;
1921     RNBContext& ctx = Context();
1922 
1923     ctx.PushEnvironment (p);
1924     return SendPacket ("OK");
1925 }
1926 
1927 rnb_err_t
1928 RNBRemote::HandlePacket_QEnvironmentHexEncoded (const char *p)
1929 {
1930     /* This sets the environment for the target program.  The packet is of the form:
1931 
1932         QEnvironmentHexEncoded:VARIABLE=VALUE
1933 
1934         The VARIABLE=VALUE part is sent hex-encoded so chracters like '#' with special
1935         meaning in the remote protocol won't break it.
1936     */
1937 
1938     DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s Handling QEnvironmentHexEncoded: \"%s\"",
1939         (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, p);
1940 
1941     p += sizeof ("QEnvironmentHexEncoded:") - 1;
1942 
1943     std::string arg;
1944     const char *c;
1945     c = p;
1946     while (*c != '\0')
1947       {
1948         if (*(c + 1) == '\0')
1949         {
1950             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'QEnvironmentHexEncoded' pkt");
1951         }
1952         char smallbuf[3];
1953         smallbuf[0] = *c;
1954         smallbuf[1] = *(c + 1);
1955         smallbuf[2] = '\0';
1956         errno = 0;
1957         int ch = strtoul (smallbuf, NULL, 16);
1958         if (errno != 0 && ch == 0)
1959           {
1960             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'QEnvironmentHexEncoded' pkt");
1961           }
1962         arg.push_back(ch);
1963         c += 2;
1964       }
1965 
1966     RNBContext& ctx = Context();
1967     if (arg.length() > 0)
1968       ctx.PushEnvironment (arg.c_str());
1969 
1970     return SendPacket ("OK");
1971 }
1972 
1973 
1974 rnb_err_t
1975 RNBRemote::HandlePacket_QLaunchArch (const char *p)
1976 {
1977     p += sizeof ("QLaunchArch:") - 1;
1978     if (DNBSetArchitecture(p))
1979         return SendPacket ("OK");
1980     return SendPacket ("E63");
1981 }
1982 
1983 void
1984 append_hex_value (std::ostream& ostrm, const uint8_t* buf, size_t buf_size, bool swap)
1985 {
1986     int i;
1987     if (swap)
1988     {
1989         for (i = buf_size-1; i >= 0; i--)
1990             ostrm << RAWHEX8(buf[i]);
1991     }
1992     else
1993     {
1994         for (i = 0; i < buf_size; i++)
1995             ostrm << RAWHEX8(buf[i]);
1996     }
1997 }
1998 
1999 
2000 void
2001 register_value_in_hex_fixed_width (std::ostream& ostrm,
2002                                    nub_process_t pid,
2003                                    nub_thread_t tid,
2004                                    const register_map_entry_t* reg)
2005 {
2006     if (reg != NULL)
2007     {
2008         DNBRegisterValue val;
2009         if (DNBThreadGetRegisterValueByID (pid, tid, reg->nub_info.set, reg->nub_info.reg, &val))
2010         {
2011             append_hex_value (ostrm, val.value.v_uint8, reg->gdb_size, false);
2012         }
2013         else
2014         {
2015             // If we fail to read a regiser value, check if it has a default
2016             // fail value. If it does, return this instead in case some of
2017             // the registers are not available on the current system.
2018             if (reg->gdb_size > 0)
2019             {
2020                 if (reg->fail_value != NULL)
2021                 {
2022                     append_hex_value (ostrm, reg->fail_value, reg->gdb_size, false);
2023                 }
2024                 else
2025                 {
2026                     std::basic_string<uint8_t> zeros(reg->gdb_size, '\0');
2027                     append_hex_value (ostrm, zeros.data(), zeros.size(), false);
2028                 }
2029             }
2030         }
2031     }
2032 }
2033 
2034 
2035 void
2036 gdb_regnum_with_fixed_width_hex_register_value (std::ostream& ostrm,
2037                                                 nub_process_t pid,
2038                                                 nub_thread_t tid,
2039                                                 const register_map_entry_t* reg)
2040 {
2041     // Output the register number as 'NN:VVVVVVVV;' where NN is a 2 bytes HEX
2042     // gdb register number, and VVVVVVVV is the correct number of hex bytes
2043     // as ASCII for the register value.
2044     if (reg != NULL)
2045     {
2046         ostrm << RAWHEX8(reg->gdb_regnum) << ':';
2047         register_value_in_hex_fixed_width (ostrm, pid, tid, reg);
2048         ostrm << ';';
2049     }
2050 }
2051 
2052 rnb_err_t
2053 RNBRemote::SendStopReplyPacketForThread (nub_thread_t tid)
2054 {
2055     const nub_process_t pid = m_ctx.ProcessID();
2056     if (pid == INVALID_NUB_PROCESS)
2057         return SendPacket("E50");
2058 
2059     struct DNBThreadStopInfo tid_stop_info;
2060 
2061     /* Fill the remaining space in this packet with as many registers
2062      as we can stuff in there.  */
2063 
2064     if (DNBThreadGetStopReason (pid, tid, &tid_stop_info))
2065     {
2066         std::ostringstream ostrm;
2067         // Output the T packet with the thread
2068         ostrm << 'T';
2069         int signum = tid_stop_info.details.signal.signo;
2070         DNBLogThreadedIf (LOG_RNB_PROC, "%8d %s got signal signo = %u, exc_type = %u", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, signum, tid_stop_info.details.exception.type);
2071 
2072         // Translate any mach exceptions to gdb versions, unless they are
2073         // common exceptions like a breakpoint or a soft signal.
2074         switch (tid_stop_info.details.exception.type)
2075         {
2076             default:                    signum = 0; break;
2077             case EXC_BREAKPOINT:        signum = SIGTRAP; break;
2078             case EXC_BAD_ACCESS:        signum = TARGET_EXC_BAD_ACCESS; break;
2079             case EXC_BAD_INSTRUCTION:   signum = TARGET_EXC_BAD_INSTRUCTION; break;
2080             case EXC_ARITHMETIC:        signum = TARGET_EXC_ARITHMETIC; break;
2081             case EXC_EMULATION:         signum = TARGET_EXC_EMULATION; break;
2082             case EXC_SOFTWARE:
2083                 if (tid_stop_info.details.exception.data_count == 2 &&
2084                     tid_stop_info.details.exception.data[0] == EXC_SOFT_SIGNAL)
2085                     signum = tid_stop_info.details.exception.data[1];
2086                 else
2087                     signum = TARGET_EXC_SOFTWARE;
2088                 break;
2089         }
2090 
2091         ostrm << RAWHEX8(signum & 0xff);
2092 
2093         ostrm << std::hex << "thread:" << tid << ';';
2094 
2095         const char *thread_name = DNBThreadGetName (pid, tid);
2096         if (thread_name && thread_name[0])
2097         {
2098             size_t thread_name_len = strlen(thread_name);
2099 
2100             if (::strcspn (thread_name, "$#+-;:") == thread_name_len)
2101                 ostrm << std::hex << "name:" << thread_name << ';';
2102             else
2103             {
2104                 // the thread name contains special chars, send as hex bytes
2105                 ostrm << std::hex << "hexname:";
2106                 uint8_t *u_thread_name = (uint8_t *)thread_name;
2107                 for (int i = 0; i < thread_name_len; i++)
2108                     ostrm << RAWHEX8(u_thread_name[i]);
2109                 ostrm << ';';
2110             }
2111         }
2112 
2113         thread_identifier_info_data_t thread_ident_info;
2114         if (DNBThreadGetIdentifierInfo (pid, tid, &thread_ident_info))
2115         {
2116             if (thread_ident_info.dispatch_qaddr != 0)
2117                 ostrm << std::hex << "qaddr:" << thread_ident_info.dispatch_qaddr << ';';
2118         }
2119         if (g_num_reg_entries == 0)
2120             InitializeRegisters ();
2121 
2122         DNBRegisterValue reg_value;
2123         for (uint32_t reg = 0; reg < g_num_reg_entries; reg++)
2124         {
2125             if (g_reg_entries[reg].expedite)
2126             {
2127                 if (!DNBThreadGetRegisterValueByID (pid, tid, g_reg_entries[reg].nub_info.set, g_reg_entries[reg].nub_info.reg, &reg_value))
2128                     continue;
2129 
2130                 gdb_regnum_with_fixed_width_hex_register_value (ostrm, pid, tid, &g_reg_entries[reg]);
2131             }
2132         }
2133 
2134         if (tid_stop_info.details.exception.type)
2135         {
2136             ostrm << "metype:" << std::hex << tid_stop_info.details.exception.type << ";";
2137             ostrm << "mecount:" << std::hex << tid_stop_info.details.exception.data_count << ";";
2138             for (int i = 0; i < tid_stop_info.details.exception.data_count; ++i)
2139                 ostrm << "medata:" << std::hex << tid_stop_info.details.exception.data[i] << ";";
2140         }
2141         return SendPacket (ostrm.str ());
2142     }
2143     return SendPacket("E51");
2144 }
2145 
2146 /* `?'
2147  The stop reply packet - tell gdb what the status of the inferior is.
2148  Often called the questionmark_packet.  */
2149 
2150 rnb_err_t
2151 RNBRemote::HandlePacket_last_signal (const char *unused)
2152 {
2153     if (!m_ctx.HasValidProcessID())
2154     {
2155         // Inferior is not yet specified/running
2156         return SendPacket ("E02");
2157     }
2158 
2159     nub_process_t pid = m_ctx.ProcessID();
2160     nub_state_t pid_state = DNBProcessGetState (pid);
2161 
2162     switch (pid_state)
2163     {
2164         case eStateAttaching:
2165         case eStateLaunching:
2166         case eStateRunning:
2167         case eStateStepping:
2168         case eStateDetached:
2169             return rnb_success;  // Ignore
2170 
2171         case eStateSuspended:
2172         case eStateStopped:
2173         case eStateCrashed:
2174             {
2175                 nub_thread_t tid = DNBProcessGetCurrentThread (pid);
2176                 // Make sure we set the current thread so g and p packets return
2177                 // the data the gdb will expect.
2178                 SetCurrentThread (tid);
2179 
2180                 SendStopReplyPacketForThread (tid);
2181             }
2182             break;
2183 
2184         case eStateInvalid:
2185         case eStateUnloaded:
2186         case eStateExited:
2187             {
2188                 char pid_exited_packet[16] = "";
2189                 int pid_status = 0;
2190                 // Process exited with exit status
2191                 if (!DNBProcessGetExitStatus(pid, &pid_status))
2192                     pid_status = 0;
2193 
2194                 if (pid_status)
2195                 {
2196                     if (WIFEXITED (pid_status))
2197                         snprintf (pid_exited_packet, sizeof(pid_exited_packet), "W%02x", WEXITSTATUS (pid_status));
2198                     else if (WIFSIGNALED (pid_status))
2199                         snprintf (pid_exited_packet, sizeof(pid_exited_packet), "X%02x", WEXITSTATUS (pid_status));
2200                     else if (WIFSTOPPED (pid_status))
2201                         snprintf (pid_exited_packet, sizeof(pid_exited_packet), "S%02x", WSTOPSIG (pid_status));
2202                 }
2203 
2204                 // If we have an empty exit packet, lets fill one in to be safe.
2205                 if (!pid_exited_packet[0])
2206                 {
2207                     strncpy (pid_exited_packet, "W00", sizeof(pid_exited_packet)-1);
2208                     pid_exited_packet[sizeof(pid_exited_packet)-1] = '\0';
2209                 }
2210 
2211                 return SendPacket (pid_exited_packet);
2212             }
2213             break;
2214     }
2215     return rnb_success;
2216 }
2217 
2218 rnb_err_t
2219 RNBRemote::HandlePacket_M (const char *p)
2220 {
2221     if (p == NULL || p[0] == '\0' || strlen (p) < 3)
2222     {
2223         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Too short M packet");
2224     }
2225 
2226     char *c;
2227     p++;
2228     errno = 0;
2229     nub_addr_t addr = strtoull (p, &c, 16);
2230     if (errno != 0 && addr == 0)
2231     {
2232         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in M packet");
2233     }
2234     if (*c != ',')
2235     {
2236         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in M packet");
2237     }
2238 
2239     /* Advance 'p' to the length part of the packet.  */
2240     p += (c - p) + 1;
2241 
2242     errno = 0;
2243     uint32_t length = strtoul (p, &c, 16);
2244     if (errno != 0 && length == 0)
2245     {
2246         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in M packet");
2247     }
2248     if (length == 0)
2249     {
2250         return SendPacket ("OK");
2251     }
2252 
2253     if (*c != ':')
2254     {
2255         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Missing colon in M packet");
2256     }
2257     /* Advance 'p' to the data part of the packet.  */
2258     p += (c - p) + 1;
2259 
2260     int datalen = strlen (p);
2261     if (datalen & 0x1)
2262     {
2263         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Uneven # of hex chars for data in M packet");
2264     }
2265     if (datalen == 0)
2266     {
2267         return SendPacket ("OK");
2268     }
2269 
2270     uint8_t *buf = (uint8_t *) alloca (datalen / 2);
2271     uint8_t *i = buf;
2272 
2273     while (*p != '\0' && *(p + 1) != '\0')
2274     {
2275         char hexbuf[3];
2276         hexbuf[0] = *p;
2277         hexbuf[1] = *(p + 1);
2278         hexbuf[2] = '\0';
2279         errno = 0;
2280         uint8_t byte = strtoul (hexbuf, NULL, 16);
2281         if (errno != 0 && byte == 0)
2282         {
2283             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid hex byte in M packet");
2284         }
2285         *i++ = byte;
2286         p += 2;
2287     }
2288 
2289     nub_size_t wrote = DNBProcessMemoryWrite (m_ctx.ProcessID(), addr, length, buf);
2290     if (wrote != length)
2291         return SendPacket ("E09");
2292     else
2293         return SendPacket ("OK");
2294 }
2295 
2296 
2297 rnb_err_t
2298 RNBRemote::HandlePacket_m (const char *p)
2299 {
2300     if (p == NULL || p[0] == '\0' || strlen (p) < 3)
2301     {
2302         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Too short m packet");
2303     }
2304 
2305     char *c;
2306     p++;
2307     errno = 0;
2308     nub_addr_t addr = strtoull (p, &c, 16);
2309     if (errno != 0 && addr == 0)
2310     {
2311         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in m packet");
2312     }
2313     if (*c != ',')
2314     {
2315         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in m packet");
2316     }
2317 
2318     /* Advance 'p' to the length part of the packet.  */
2319     p += (c - p) + 1;
2320 
2321     errno = 0;
2322     uint32_t length = strtoul (p, NULL, 16);
2323     if (errno != 0 && length == 0)
2324     {
2325         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in m packet");
2326     }
2327     if (length == 0)
2328     {
2329         return SendPacket ("");
2330     }
2331 
2332     uint8_t buf[length];
2333     int bytes_read = DNBProcessMemoryRead (m_ctx.ProcessID(), addr, length, buf);
2334     if (bytes_read == 0)
2335     {
2336         return SendPacket ("E08");
2337     }
2338 
2339     // "The reply may contain fewer bytes than requested if the server was able
2340     //  to read only part of the region of memory."
2341     length = bytes_read;
2342 
2343     std::ostringstream ostrm;
2344     for (int i = 0; i < length; i++)
2345         ostrm << RAWHEX8(buf[i]);
2346     return SendPacket (ostrm.str ());
2347 }
2348 
2349 rnb_err_t
2350 RNBRemote::HandlePacket_X (const char *p)
2351 {
2352     if (p == NULL || p[0] == '\0' || strlen (p) < 3)
2353     {
2354         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Too short X packet");
2355     }
2356 
2357     char *c;
2358     p++;
2359     errno = 0;
2360     nub_addr_t addr = strtoull (p, &c, 16);
2361     if (errno != 0 && addr == 0)
2362     {
2363         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in X packet");
2364     }
2365     if (*c != ',')
2366     {
2367         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in X packet");
2368     }
2369 
2370     /* Advance 'p' to the length part of the packet.  */
2371     p += (c - p) + 1;
2372 
2373     errno = 0;
2374     int length = strtoul (p, NULL, 16);
2375     if (errno != 0 && length == 0)
2376     {
2377         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in m packet");
2378     }
2379 
2380     // I think gdb sends a zero length write request to test whether this
2381     // packet is accepted.
2382     if (length == 0)
2383     {
2384         return SendPacket ("OK");
2385     }
2386 
2387     std::vector<uint8_t> data = decode_binary_data (c, -1);
2388     std::vector<uint8_t>::const_iterator it;
2389     uint8_t *buf = (uint8_t *) alloca (data.size ());
2390     uint8_t *i = buf;
2391     for (it = data.begin (); it != data.end (); ++it)
2392     {
2393         *i++ = *it;
2394     }
2395 
2396     nub_size_t wrote = DNBProcessMemoryWrite (m_ctx.ProcessID(), addr, data.size(), buf);
2397     if (wrote != data.size ())
2398         return SendPacket ("E08");
2399     return SendPacket ("OK");
2400 }
2401 
2402 /* `g' -- read registers
2403  Get the contents of the registers for the current thread,
2404  send them to gdb.
2405  Should the setting of the Hg packet determine which thread's registers
2406  are returned?  */
2407 
2408 rnb_err_t
2409 RNBRemote::HandlePacket_g (const char *p)
2410 {
2411     std::ostringstream ostrm;
2412     if (!m_ctx.HasValidProcessID())
2413     {
2414         return SendPacket ("E11");
2415     }
2416 
2417     if (g_num_reg_entries == 0)
2418         InitializeRegisters ();
2419 
2420     nub_process_t pid = m_ctx.ProcessID ();
2421     nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p + 1);
2422     if (tid == INVALID_NUB_THREAD)
2423         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
2424 
2425     if (m_use_native_regs)
2426     {
2427         // Get the register context size first by calling with NULL buffer
2428         nub_size_t reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, NULL, 0);
2429         if (reg_ctx_size)
2430         {
2431             // Now allocate enough space for the entire register context
2432             std::vector<uint8_t> reg_ctx;
2433             reg_ctx.resize(reg_ctx_size);
2434             // Now read the register context
2435             reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, &reg_ctx[0], reg_ctx.size());
2436             if (reg_ctx_size)
2437             {
2438                 append_hex_value (ostrm, reg_ctx.data(), reg_ctx.size(), false);
2439                 return SendPacket (ostrm.str ());
2440             }
2441         }
2442     }
2443 
2444     for (uint32_t reg = 0; reg < g_num_reg_entries; reg++)
2445         register_value_in_hex_fixed_width (ostrm, pid, tid, &g_reg_entries[reg]);
2446 
2447     return SendPacket (ostrm.str ());
2448 }
2449 
2450 /* `G XXX...' -- write registers
2451  How is the thread for these specified, beyond "the current thread"?
2452  Does gdb actually use the Hg packet to set this?  */
2453 
2454 rnb_err_t
2455 RNBRemote::HandlePacket_G (const char *p)
2456 {
2457     if (!m_ctx.HasValidProcessID())
2458     {
2459         return SendPacket ("E11");
2460     }
2461 
2462     if (g_num_reg_entries == 0)
2463         InitializeRegisters ();
2464 
2465     StringExtractor packet(p);
2466     packet.SetFilePos(1); // Skip the 'G'
2467 
2468     nub_process_t pid = m_ctx.ProcessID();
2469     nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p);
2470     if (tid == INVALID_NUB_THREAD)
2471         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
2472 
2473     if (m_use_native_regs)
2474     {
2475         // Get the register context size first by calling with NULL buffer
2476         nub_size_t reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, NULL, 0);
2477         if (reg_ctx_size)
2478         {
2479             // Now allocate enough space for the entire register context
2480             std::vector<uint8_t> reg_ctx;
2481             reg_ctx.resize(reg_ctx_size);
2482 
2483             if (packet.GetHexBytes (&reg_ctx[0], reg_ctx.size(), 0xcc) == reg_ctx.size())
2484             {
2485                 // Now write the register context
2486                 reg_ctx_size = DNBThreadSetRegisterContext(pid, tid, reg_ctx.data(), reg_ctx.size());
2487                 if (reg_ctx_size == reg_ctx.size())
2488                     return SendPacket ("OK");
2489                 else
2490                     return SendPacket ("E55");
2491             }
2492         }
2493     }
2494 
2495 
2496     DNBRegisterValue reg_value;
2497     for (uint32_t reg = 0; reg < g_num_reg_entries; reg++)
2498     {
2499         const register_map_entry_t *reg_entry = &g_reg_entries[reg];
2500 
2501         reg_value.info = reg_entry->nub_info;
2502         if (packet.GetHexBytes (reg_value.value.v_sint8, reg_entry->gdb_size, 0xcc) != reg_entry->gdb_size)
2503             break;
2504 
2505         if (!DNBThreadSetRegisterValueByID (pid, tid, reg_entry->nub_info.set, reg_entry->nub_info.reg, &reg_value))
2506             return SendPacket ("E15");
2507     }
2508     return SendPacket ("OK");
2509 }
2510 
2511 static bool
2512 RNBRemoteShouldCancelCallback (void *not_used)
2513 {
2514     RNBRemoteSP remoteSP(g_remoteSP);
2515     if (remoteSP.get() != NULL)
2516     {
2517         RNBRemote* remote = remoteSP.get();
2518         if (remote->Comm().IsConnected())
2519             return false;
2520         else
2521             return true;
2522     }
2523     return true;
2524 }
2525 
2526 
2527 // FORMAT: _MXXXXXX,PPP
2528 //      XXXXXX: big endian hex chars
2529 //      PPP: permissions can be any combo of r w x chars
2530 //
2531 // RESPONSE: XXXXXX
2532 //      XXXXXX: hex address of the newly allocated memory
2533 //      EXX: error code
2534 //
2535 // EXAMPLES:
2536 //      _M123000,rw
2537 //      _M123000,rwx
2538 //      _M123000,xw
2539 
2540 rnb_err_t
2541 RNBRemote::HandlePacket_AllocateMemory (const char *p)
2542 {
2543     StringExtractor packet (p);
2544     packet.SetFilePos(2); // Skip the "_M"
2545 
2546     nub_addr_t size = packet.GetHexMaxU64 (StringExtractor::BigEndian, 0);
2547     if (size != 0)
2548     {
2549         if (packet.GetChar() == ',')
2550         {
2551             uint32_t permissions = 0;
2552             char ch;
2553             bool success = true;
2554             while (success && (ch = packet.GetChar()) != '\0')
2555             {
2556                 switch (ch)
2557                 {
2558                 case 'r':   permissions |= eMemoryPermissionsReadable; break;
2559                 case 'w':   permissions |= eMemoryPermissionsWritable; break;
2560                 case 'x':   permissions |= eMemoryPermissionsExecutable; break;
2561                 default:    success = false; break;
2562                 }
2563             }
2564 
2565             if (success)
2566             {
2567                 nub_addr_t addr = DNBProcessMemoryAllocate (m_ctx.ProcessID(), size, permissions);
2568                 if (addr != INVALID_NUB_ADDRESS)
2569                 {
2570                     std::ostringstream ostrm;
2571                     ostrm << RAW_HEXBASE << addr;
2572                     return SendPacket (ostrm.str ());
2573                 }
2574             }
2575         }
2576     }
2577     return SendPacket ("E53");
2578 }
2579 
2580 // FORMAT: _mXXXXXX
2581 //      XXXXXX: address that was previosly allocated
2582 //
2583 // RESPONSE: XXXXXX
2584 //      OK: address was deallocated
2585 //      EXX: error code
2586 //
2587 // EXAMPLES:
2588 //      _m123000
2589 
2590 rnb_err_t
2591 RNBRemote::HandlePacket_DeallocateMemory (const char *p)
2592 {
2593     StringExtractor packet (p);
2594     packet.SetFilePos(2); // Skip the "_m"
2595     nub_addr_t addr = packet.GetHexMaxU64 (StringExtractor::BigEndian, INVALID_NUB_ADDRESS);
2596 
2597     if (addr != INVALID_NUB_ADDRESS)
2598     {
2599         if (DNBProcessMemoryDeallocate (m_ctx.ProcessID(), addr))
2600             return SendPacket ("OK");
2601     }
2602     return SendPacket ("E54");
2603 }
2604 
2605 /*
2606  vAttach;pid
2607 
2608  Attach to a new process with the specified process ID. pid is a hexadecimal integer
2609  identifying the process. If the stub is currently controlling a process, it is
2610  killed. The attached process is stopped.This packet is only available in extended
2611  mode (see extended mode).
2612 
2613  Reply:
2614  "ENN"                      for an error
2615  "Any Stop Reply Packet"     for success
2616  */
2617 
2618 rnb_err_t
2619 RNBRemote::HandlePacket_v (const char *p)
2620 {
2621     if (strcmp (p, "vCont;c") == 0)
2622     {
2623         // Simple continue
2624         return RNBRemote::HandlePacket_c("c");
2625     }
2626     else if (strcmp (p, "vCont;s") == 0)
2627     {
2628         // Simple step
2629         return RNBRemote::HandlePacket_s("s");
2630     }
2631     else if (strstr (p, "vCont") == p)
2632     {
2633         rnb_err_t rnb_err = rnb_success;
2634         typedef struct
2635         {
2636             nub_thread_t tid;
2637             char action;
2638             int signal;
2639         } vcont_action_t;
2640 
2641         DNBThreadResumeActions thread_actions;
2642         char *c = (char *)(p += strlen("vCont"));
2643         char *c_end = c + strlen(c);
2644         if (*c == '?')
2645             return SendPacket ("vCont;c;C;s;S");
2646 
2647         while (c < c_end && *c == ';')
2648         {
2649             ++c;    // Skip the semi-colon
2650             DNBThreadResumeAction thread_action;
2651             thread_action.tid = INVALID_NUB_THREAD;
2652             thread_action.state = eStateInvalid;
2653             thread_action.signal = 0;
2654             thread_action.addr = INVALID_NUB_ADDRESS;
2655 
2656             char action = *c++;
2657 
2658             switch (action)
2659             {
2660                 case 'C':
2661                     errno = 0;
2662                     thread_action.signal = strtoul (c, &c, 16);
2663                     if (errno != 0)
2664                         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in vCont packet");
2665                     // Fall through to next case...
2666 
2667                 case 'c':
2668                     // Continue
2669                     thread_action.state = eStateRunning;
2670                     break;
2671 
2672                 case 'S':
2673                     errno = 0;
2674                     thread_action.signal = strtoul (c, &c, 16);
2675                     if (errno != 0)
2676                         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in vCont packet");
2677                     // Fall through to next case...
2678 
2679                 case 's':
2680                     // Step
2681                     thread_action.state = eStateStepping;
2682                     break;
2683 
2684                 default:
2685                     rnb_err = HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Unsupported action in vCont packet");
2686                     break;
2687             }
2688             if (*c == ':')
2689             {
2690                 errno = 0;
2691                 thread_action.tid = strtoul (++c, &c, 16);
2692                 if (errno != 0)
2693                     return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse thread number in vCont packet");
2694             }
2695 
2696             thread_actions.Append (thread_action);
2697         }
2698 
2699         // If a default action for all other threads wasn't mentioned
2700         // then we should stop the threads
2701         thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0);
2702         DNBProcessResume(m_ctx.ProcessID(), thread_actions.GetFirst (), thread_actions.GetSize());
2703         return rnb_success;
2704     }
2705     else if (strstr (p, "vAttach") == p)
2706     {
2707         nub_process_t attach_pid = INVALID_NUB_PROCESS;
2708         char err_str[1024]={'\0'};
2709         if (strstr (p, "vAttachWait;") == p)
2710         {
2711             p += strlen("vAttachWait;");
2712             std::string attach_name;
2713             while (*p != '\0')
2714             {
2715                 char smallbuf[3];
2716                 smallbuf[0] = *p;
2717                 smallbuf[1] = *(p + 1);
2718                 smallbuf[2] = '\0';
2719 
2720                 errno = 0;
2721                 int ch = strtoul (smallbuf, NULL, 16);
2722                 if (errno != 0 && ch == 0)
2723                 {
2724                     return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachWait' pkt");
2725                 }
2726 
2727                 attach_name.push_back(ch);
2728                 p += 2;
2729             }
2730 
2731             attach_pid = DNBProcessAttachWait(attach_name.c_str (), m_ctx.LaunchFlavor(), NULL, 1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback);
2732 
2733         }
2734         else if (strstr (p, "vAttachName;") == p)
2735         {
2736             p += strlen("vAttachName;");
2737             std::string attach_name;
2738             while (*p != '\0')
2739             {
2740                 char smallbuf[3];
2741                 smallbuf[0] = *p;
2742                 smallbuf[1] = *(p + 1);
2743                 smallbuf[2] = '\0';
2744 
2745                 errno = 0;
2746                 int ch = strtoul (smallbuf, NULL, 16);
2747                 if (errno != 0 && ch == 0)
2748                 {
2749                     return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachWait' pkt");
2750                 }
2751 
2752                 attach_name.push_back(ch);
2753                 p += 2;
2754             }
2755 
2756             attach_pid = DNBProcessAttachByName (attach_name.c_str(), NULL, err_str, sizeof(err_str));
2757 
2758         }
2759         else if (strstr (p, "vAttach;") == p)
2760         {
2761             p += strlen("vAttach;");
2762             char *end = NULL;
2763             attach_pid = strtoul (p, &end, 16);    // PID will be in hex, so use base 16 to decode
2764             if (p != end && *end == '\0')
2765             {
2766                 // Wait at most 30 second for attach
2767                 struct timespec attach_timeout_abstime;
2768                 DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, 30, 0);
2769                 attach_pid = DNBProcessAttach(attach_pid, &attach_timeout_abstime, err_str, sizeof(err_str));
2770             }
2771         }
2772         else
2773             return HandlePacket_UNIMPLEMENTED(p);
2774 
2775 
2776         if (attach_pid != INVALID_NUB_PROCESS)
2777         {
2778             if (m_ctx.ProcessID() != attach_pid)
2779                 m_ctx.SetProcessID(attach_pid);
2780             // Send a stop reply packet to indicate we successfully attached!
2781             NotifyThatProcessStopped ();
2782             return rnb_success;
2783         }
2784         else
2785         {
2786             m_ctx.LaunchStatus().SetError(-1, DNBError::Generic);
2787             if (err_str[0])
2788                 m_ctx.LaunchStatus().SetErrorString(err_str);
2789             else
2790                 m_ctx.LaunchStatus().SetErrorString("attach failed");
2791             return SendPacket ("E01");  // E01 is our magic error value for attach failed.
2792         }
2793     }
2794 
2795     // All other failures come through here
2796     return HandlePacket_UNIMPLEMENTED(p);
2797 }
2798 
2799 /* `T XX' -- status of thread
2800  Check if the specified thread is alive.
2801  The thread number is in hex?  */
2802 
2803 rnb_err_t
2804 RNBRemote::HandlePacket_T (const char *p)
2805 {
2806     p++;
2807     if (p == NULL || *p == '\0')
2808     {
2809         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in T packet");
2810     }
2811     if (!m_ctx.HasValidProcessID())
2812     {
2813         return SendPacket ("E15");
2814     }
2815     errno = 0;
2816     nub_thread_t tid = strtoul (p, NULL, 16);
2817     if (errno != 0 && tid == 0)
2818     {
2819         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse thread number in T packet");
2820     }
2821 
2822     nub_state_t state = DNBThreadGetState (m_ctx.ProcessID(), tid);
2823     if (state == eStateInvalid || state == eStateExited || state == eStateCrashed)
2824     {
2825         return SendPacket ("E16");
2826     }
2827 
2828     return SendPacket ("OK");
2829 }
2830 
2831 
2832 rnb_err_t
2833 RNBRemote::HandlePacket_z (const char *p)
2834 {
2835     if (p == NULL || *p == '\0')
2836         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in z packet");
2837 
2838     if (!m_ctx.HasValidProcessID())
2839         return SendPacket ("E15");
2840 
2841     char packet_cmd = *p++;
2842     char break_type = *p++;
2843 
2844     if (*p++ != ',')
2845         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma separator missing in z packet");
2846 
2847     char *c = NULL;
2848     nub_process_t pid = m_ctx.ProcessID();
2849     errno = 0;
2850     nub_addr_t addr = strtoull (p, &c, 16);
2851     if (errno != 0 && addr == 0)
2852         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in z packet");
2853     p = c;
2854     if (*p++ != ',')
2855         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma separator missing in z packet");
2856 
2857     errno = 0;
2858     uint32_t byte_size = strtoul (p, &c, 16);
2859     if (errno != 0 && byte_size == 0)
2860         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in z packet");
2861 
2862     if (packet_cmd == 'Z')
2863     {
2864         // set
2865         switch (break_type)
2866         {
2867             case '0':   // set software breakpoint
2868             case '1':   // set hardware breakpoint
2869             {
2870                 // gdb can send multiple Z packets for the same address and
2871                 // these calls must be ref counted.
2872                 bool hardware = (break_type == '1');
2873 
2874                 // Check if we currently have a breakpoint already set at this address
2875                 BreakpointMapIter pos = m_breakpoints.find(addr);
2876                 if (pos != m_breakpoints.end())
2877                 {
2878                     // We do already have a breakpoint at this address, increment
2879                     // its reference count and return OK
2880                     pos->second.Retain();
2881                     return SendPacket ("OK");
2882                 }
2883                 else
2884                 {
2885                     // We do NOT already have a breakpoint at this address, So lets
2886                     // create one.
2887                     nub_break_t break_id = DNBBreakpointSet (pid, addr, byte_size, hardware);
2888                     if (NUB_BREAK_ID_IS_VALID(break_id))
2889                     {
2890                         // We successfully created a breakpoint, now lets full out
2891                         // a ref count structure with the breakID and add it to our
2892                         // map.
2893                         Breakpoint rnbBreakpoint(break_id);
2894                         m_breakpoints[addr] = rnbBreakpoint;
2895                         return SendPacket ("OK");
2896                     }
2897                     else
2898                     {
2899                         // We failed to set the software breakpoint
2900                         return SendPacket ("E09");
2901                     }
2902                 }
2903             }
2904                 break;
2905 
2906             case '2':   // set write watchpoint
2907             case '3':   // set read watchpoint
2908             case '4':   // set access watchpoint
2909             {
2910                 bool hardware = true;
2911                 uint32_t watch_flags = 0;
2912                 if (break_type == '2')
2913                     watch_flags = WATCH_TYPE_WRITE;
2914                 else if (break_type == '3')
2915                     watch_flags = WATCH_TYPE_READ;
2916                 else
2917                     watch_flags = WATCH_TYPE_READ | WATCH_TYPE_WRITE;
2918 
2919                 // Check if we currently have a watchpoint already set at this address
2920                 BreakpointMapIter pos = m_watchpoints.find(addr);
2921                 if (pos != m_watchpoints.end())
2922                 {
2923                     // We do already have a watchpoint at this address, increment
2924                     // its reference count and return OK
2925                     pos->second.Retain();
2926                     return SendPacket ("OK");
2927                 }
2928                 else
2929                 {
2930                     // We do NOT already have a watchpoint at this address, So lets
2931                     // create one.
2932                     nub_watch_t watch_id = DNBWatchpointSet (pid, addr, byte_size, watch_flags, hardware);
2933                     if (NUB_WATCH_ID_IS_VALID(watch_id))
2934                     {
2935                         // We successfully created a watchpoint, now lets full out
2936                         // a ref count structure with the watch_id and add it to our
2937                         // map.
2938                         Breakpoint rnbWatchpoint(watch_id);
2939                         m_watchpoints[addr] = rnbWatchpoint;
2940                         return SendPacket ("OK");
2941                     }
2942                     else
2943                     {
2944                         // We failed to set the watchpoint
2945                         return SendPacket ("E09");
2946                     }
2947                 }
2948             }
2949                 break;
2950 
2951             default:
2952                 break;
2953         }
2954     }
2955     else if (packet_cmd == 'z')
2956     {
2957         // remove
2958         switch (break_type)
2959         {
2960             case '0':   // remove software breakpoint
2961             case '1':   // remove hardware breakpoint
2962             {
2963                 // gdb can send multiple z packets for the same address and
2964                 // these calls must be ref counted.
2965                 BreakpointMapIter pos = m_breakpoints.find(addr);
2966                 if (pos != m_breakpoints.end())
2967                 {
2968                     // We currently have a breakpoint at address ADDR. Decrement
2969                     // its reference count, and it that count is now zero we
2970                     // can clear the breakpoint.
2971                     pos->second.Release();
2972                     if (pos->second.RefCount() == 0)
2973                     {
2974                         if (DNBBreakpointClear (pid, pos->second.BreakID()))
2975                         {
2976                             m_breakpoints.erase(pos);
2977                             return SendPacket ("OK");
2978                         }
2979                         else
2980                         {
2981                             return SendPacket ("E08");
2982                         }
2983                     }
2984                     else
2985                     {
2986                         // We still have references to this breakpoint don't
2987                         // delete it, just decrementing the reference count
2988                         // is enough.
2989                         return SendPacket ("OK");
2990                     }
2991                 }
2992                 else
2993                 {
2994                     // We don't know about any breakpoints at this address
2995                     return SendPacket ("E08");
2996                 }
2997             }
2998                 break;
2999 
3000             case '2':   // remove write watchpoint
3001             case '3':   // remove read watchpoint
3002             case '4':   // remove access watchpoint
3003             {
3004                 // gdb can send multiple z packets for the same address and
3005                 // these calls must be ref counted.
3006                 BreakpointMapIter pos = m_watchpoints.find(addr);
3007                 if (pos != m_watchpoints.end())
3008                 {
3009                     // We currently have a watchpoint at address ADDR. Decrement
3010                     // its reference count, and it that count is now zero we
3011                     // can clear the watchpoint.
3012                     pos->second.Release();
3013                     if (pos->second.RefCount() == 0)
3014                     {
3015                         if (DNBWatchpointClear (pid, pos->second.BreakID()))
3016                         {
3017                             m_watchpoints.erase(pos);
3018                             return SendPacket ("OK");
3019                         }
3020                         else
3021                         {
3022                             return SendPacket ("E08");
3023                         }
3024                     }
3025                     else
3026                     {
3027                         // We still have references to this watchpoint don't
3028                         // delete it, just decrementing the reference count
3029                         // is enough.
3030                         return SendPacket ("OK");
3031                     }
3032                 }
3033                 else
3034                 {
3035                     // We don't know about any watchpoints at this address
3036                     return SendPacket ("E08");
3037                 }
3038             }
3039                 break;
3040 
3041             default:
3042                 break;
3043         }
3044     }
3045     return HandlePacket_UNIMPLEMENTED(p);
3046 }
3047 
3048 // Extract the thread number from the thread suffix that might be appended to
3049 // thread specific packets. This will only be enabled if m_thread_suffix_supported
3050 // is true.
3051 nub_thread_t
3052 RNBRemote::ExtractThreadIDFromThreadSuffix (const char *p)
3053 {
3054     if (m_thread_suffix_supported)
3055     {
3056         nub_thread_t tid = INVALID_NUB_THREAD;
3057         if (p)
3058         {
3059             const char *tid_cstr = strstr (p, "thread:");
3060             if (tid_cstr)
3061             {
3062                 tid_cstr += strlen ("thread:");
3063                 tid = strtoul(tid_cstr, NULL, 16);
3064             }
3065         }
3066         return tid;
3067     }
3068     return GetCurrentThread();
3069 
3070 }
3071 
3072 /* `p XX'
3073  print the contents of register X */
3074 
3075 rnb_err_t
3076 RNBRemote::HandlePacket_p (const char *p)
3077 {
3078     if (g_num_reg_entries == 0)
3079         InitializeRegisters ();
3080 
3081     if (p == NULL || *p == '\0')
3082     {
3083         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
3084     }
3085     if (!m_ctx.HasValidProcessID())
3086     {
3087         return SendPacket ("E15");
3088     }
3089     nub_process_t pid = m_ctx.ProcessID();
3090     errno = 0;
3091     char *tid_cstr = NULL;
3092     uint32_t reg = strtoul (p + 1, &tid_cstr, 16);
3093     if (errno != 0 && reg == 0)
3094     {
3095         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse register number in p packet");
3096     }
3097 
3098     nub_thread_t tid = ExtractThreadIDFromThreadSuffix (tid_cstr);
3099     if (tid == INVALID_NUB_THREAD)
3100         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
3101 
3102     const register_map_entry_t *reg_entry;
3103 
3104     if (reg < g_num_reg_entries)
3105         reg_entry = &g_reg_entries[reg];
3106     else
3107         reg_entry = NULL;
3108 
3109     std::ostringstream ostrm;
3110     if (reg_entry == NULL)
3111     {
3112         DNBLogError("RNBRemote::HandlePacket_p(%s): unknown register number %u requested\n", p, reg);
3113         ostrm << "00000000";
3114     }
3115     else if (reg_entry->nub_info.reg == -1)
3116     {
3117         if (reg_entry->gdb_size > 0)
3118         {
3119             if (reg_entry->fail_value != NULL)
3120             {
3121                 append_hex_value(ostrm, reg_entry->fail_value, reg_entry->gdb_size, false);
3122             }
3123             else
3124             {
3125                 std::basic_string<uint8_t> zeros(reg_entry->gdb_size, '\0');
3126                 append_hex_value(ostrm, zeros.data(), zeros.size(), false);
3127             }
3128         }
3129     }
3130     else
3131     {
3132         register_value_in_hex_fixed_width (ostrm, pid, tid, reg_entry);
3133     }
3134     return SendPacket (ostrm.str());
3135 }
3136 
3137 /* `Pnn=rrrrr'
3138  Set register number n to value r.
3139  n and r are hex strings.  */
3140 
3141 rnb_err_t
3142 RNBRemote::HandlePacket_P (const char *p)
3143 {
3144     if (g_num_reg_entries == 0)
3145         InitializeRegisters ();
3146 
3147     if (p == NULL || *p == '\0')
3148     {
3149         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Empty P packet");
3150     }
3151     if (!m_ctx.HasValidProcessID())
3152     {
3153         return SendPacket ("E28");
3154     }
3155 
3156     nub_process_t pid = m_ctx.ProcessID();
3157 
3158     StringExtractor packet (p);
3159 
3160     const char cmd_char = packet.GetChar();
3161     // Register ID is always in big endian
3162     const uint32_t reg = packet.GetHexMaxU32 (false, UINT32_MAX);
3163     const char equal_char = packet.GetChar();
3164 
3165     if (cmd_char != 'P')
3166         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Improperly formed P packet");
3167 
3168     if (reg == UINT32_MAX)
3169         return SendPacket ("E29");
3170 
3171     if (equal_char != '=')
3172         return SendPacket ("E30");
3173 
3174     const register_map_entry_t *reg_entry;
3175 
3176     if (reg >= g_num_reg_entries)
3177         return SendPacket("E47");
3178 
3179     reg_entry = &g_reg_entries[reg];
3180 
3181     if (reg_entry->nub_info.set == -1 && reg_entry->nub_info.reg == -1)
3182     {
3183         DNBLogError("RNBRemote::HandlePacket_P(%s): unknown register number %u requested\n", p, reg);
3184         return SendPacket("E48");
3185     }
3186 
3187     DNBRegisterValue reg_value;
3188     reg_value.info = reg_entry->nub_info;
3189     packet.GetHexBytes (reg_value.value.v_sint8, reg_entry->gdb_size, 0xcc);
3190 
3191     nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p);
3192     if (tid == INVALID_NUB_THREAD)
3193         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
3194 
3195     if (!DNBThreadSetRegisterValueByID (pid, tid, reg_entry->nub_info.set, reg_entry->nub_info.reg, &reg_value))
3196     {
3197         return SendPacket ("E32");
3198     }
3199     return SendPacket ("OK");
3200 }
3201 
3202 /* `c [addr]'
3203  Continue, optionally from a specified address. */
3204 
3205 rnb_err_t
3206 RNBRemote::HandlePacket_c (const char *p)
3207 {
3208     const nub_process_t pid = m_ctx.ProcessID();
3209 
3210     if (pid == INVALID_NUB_PROCESS)
3211         return SendPacket ("E23");
3212 
3213     DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateRunning, 0, INVALID_NUB_ADDRESS };
3214 
3215     if (*(p + 1) != '\0')
3216     {
3217         action.tid = GetContinueThread();
3218         errno = 0;
3219         action.addr = strtoull (p + 1, NULL, 16);
3220         if (errno != 0 && action.addr == 0)
3221             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in c packet");
3222     }
3223 
3224     DNBThreadResumeActions thread_actions;
3225     thread_actions.Append(action);
3226     thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, 0);
3227     if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize()))
3228         return SendPacket ("E25");
3229     // Don't send an "OK" packet; response is the stopped/exited message.
3230     return rnb_success;
3231 }
3232 
3233 /* `C sig [;addr]'
3234  Resume with signal sig, optionally at address addr.  */
3235 
3236 rnb_err_t
3237 RNBRemote::HandlePacket_C (const char *p)
3238 {
3239     const nub_process_t pid = m_ctx.ProcessID();
3240 
3241     if (pid == INVALID_NUB_PROCESS)
3242         return SendPacket ("E36");
3243 
3244     DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateRunning, 0, INVALID_NUB_ADDRESS };
3245     int process_signo = -1;
3246     if (*(p + 1) != '\0')
3247     {
3248         action.tid = GetContinueThread();
3249         char *end = NULL;
3250         errno = 0;
3251         process_signo = strtoul (p + 1, &end, 16);
3252         if (errno != 0)
3253             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in C packet");
3254         else if (*end == ';')
3255         {
3256             errno = 0;
3257             action.addr = strtoull (end + 1, NULL, 16);
3258             if (errno != 0 && action.addr == 0)
3259                 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in C packet");
3260         }
3261     }
3262 
3263     DNBThreadResumeActions thread_actions;
3264     thread_actions.Append (action);
3265     thread_actions.SetDefaultThreadActionIfNeeded (eStateRunning, action.signal);
3266     if (!DNBProcessSignal(pid, process_signo))
3267         return SendPacket ("E52");
3268     if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize()))
3269         return SendPacket ("E38");
3270     /* Don't send an "OK" packet; response is the stopped/exited message.  */
3271     return rnb_success;
3272 }
3273 
3274 //----------------------------------------------------------------------
3275 // 'D' packet
3276 // Detach from gdb.
3277 //----------------------------------------------------------------------
3278 rnb_err_t
3279 RNBRemote::HandlePacket_D (const char *p)
3280 {
3281     // We are not supposed to send a response for deatch.
3282     //SendPacket ("OK");
3283     if (m_ctx.HasValidProcessID())
3284         DNBProcessDetach(m_ctx.ProcessID());
3285     return rnb_success;
3286 }
3287 
3288 /* `k'
3289  Kill the inferior process.  */
3290 
3291 rnb_err_t
3292 RNBRemote::HandlePacket_k (const char *p)
3293 {
3294     // No response to should be sent to the kill packet
3295     if (m_ctx.HasValidProcessID())
3296         DNBProcessKill (m_ctx.ProcessID());
3297     SendPacket ("W09");
3298     return rnb_success;
3299 }
3300 
3301 rnb_err_t
3302 RNBRemote::HandlePacket_stop_process (const char *p)
3303 {
3304     DNBProcessSignal (m_ctx.ProcessID(), SIGSTOP);
3305     //DNBProcessSignal (m_ctx.ProcessID(), SIGINT);
3306     // Do not send any response packet! Wait for the stop reply packet to naturally happen
3307     return rnb_success;
3308 }
3309 
3310 /* `s'
3311  Step the inferior process.  */
3312 
3313 rnb_err_t
3314 RNBRemote::HandlePacket_s (const char *p)
3315 {
3316     const nub_process_t pid = m_ctx.ProcessID();
3317     if (pid == INVALID_NUB_PROCESS)
3318         return SendPacket ("E32");
3319 
3320     // Hardware supported stepping not supported on arm
3321     nub_thread_t tid = GetContinueThread ();
3322     if (tid == 0 || tid == -1)
3323         tid = GetCurrentThread();
3324 
3325     if (tid == INVALID_NUB_THREAD)
3326         return SendPacket ("E33");
3327 
3328     DNBThreadResumeActions thread_actions;
3329     thread_actions.AppendAction(tid, eStateStepping);
3330 
3331     // Make all other threads stop when we are stepping
3332     thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0);
3333     if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize()))
3334         return SendPacket ("E49");
3335     // Don't send an "OK" packet; response is the stopped/exited message.
3336     return rnb_success;
3337 }
3338 
3339 /* `S sig [;addr]'
3340  Step with signal sig, optionally at address addr.  */
3341 
3342 rnb_err_t
3343 RNBRemote::HandlePacket_S (const char *p)
3344 {
3345     const nub_process_t pid = m_ctx.ProcessID();
3346     if (pid == INVALID_NUB_PROCESS)
3347         return SendPacket ("E36");
3348 
3349     DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateStepping, 0, INVALID_NUB_ADDRESS };
3350 
3351     if (*(p + 1) != '\0')
3352     {
3353         char *end = NULL;
3354         errno = 0;
3355         action.signal = strtoul (p + 1, &end, 16);
3356         if (errno != 0)
3357             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in S packet");
3358         else if (*end == ';')
3359         {
3360             errno = 0;
3361             action.addr = strtoull (end + 1, NULL, 16);
3362             if (errno != 0 && action.addr == 0)
3363             {
3364                 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in S packet");
3365             }
3366         }
3367     }
3368 
3369     action.tid = GetContinueThread ();
3370     if (action.tid == 0 || action.tid == -1)
3371         return SendPacket ("E40");
3372 
3373     nub_state_t tstate = DNBThreadGetState (pid, action.tid);
3374     if (tstate == eStateInvalid || tstate == eStateExited)
3375         return SendPacket ("E37");
3376 
3377 
3378     DNBThreadResumeActions thread_actions;
3379     thread_actions.Append (action);
3380 
3381     // Make all other threads stop when we are stepping
3382     thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
3383     if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize()))
3384         return SendPacket ("E39");
3385 
3386     // Don't send an "OK" packet; response is the stopped/exited message.
3387     return rnb_success;
3388 }
3389 
3390 rnb_err_t
3391 RNBRemote::HandlePacket_qHostInfo (const char *p)
3392 {
3393     std::ostringstream strm;
3394 
3395     uint32_t cputype, is_64_bit_capable;
3396     size_t len = sizeof(cputype);
3397     bool promoted_to_64 = false;
3398     if  (::sysctlbyname("hw.cputype", &cputype, &len, NULL, 0) == 0)
3399     {
3400         len = sizeof (is_64_bit_capable);
3401         if  (::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0) == 0)
3402         {
3403             if (is_64_bit_capable && ((cputype & CPU_ARCH_ABI64) == 0))
3404             {
3405                 promoted_to_64 = true;
3406                 cputype |= CPU_ARCH_ABI64;
3407             }
3408         }
3409 
3410         strm << "cputype:" << std::dec << cputype << ';';
3411     }
3412 
3413     uint32_t cpusubtype;
3414     len = sizeof(cpusubtype);
3415     if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0)
3416     {
3417         if (promoted_to_64 &&
3418             cputype == CPU_TYPE_X86_64 &&
3419             cpusubtype == CPU_SUBTYPE_486)
3420             cpusubtype = CPU_SUBTYPE_X86_64_ALL;
3421 
3422         strm << "cpusubtype:" << std::dec << cpusubtype << ';';
3423     }
3424 
3425     char ostype[64];
3426     len = sizeof(ostype);
3427     if (::sysctlbyname("kern.ostype", &ostype, &len, NULL, 0) == 0)
3428     {
3429         len = strlen(ostype);
3430         std::transform (ostype, ostype + len, ostype, tolower);
3431         strm << "ostype:" << std::dec << ostype << ';';
3432     }
3433 
3434     strm << "vendor:apple;";
3435 
3436 #if defined (__LITTLE_ENDIAN__)
3437     strm << "endian:little;";
3438 #elif defined (__BIG_ENDIAN__)
3439     strm << "endian:big;";
3440 #elif defined (__PDP_ENDIAN__)
3441     strm << "endian:pdp;";
3442 #endif
3443 
3444     if (promoted_to_64)
3445         strm << "ptrsize:8;";
3446     else
3447         strm << "ptrsize:" << std::dec << sizeof(void *) << ';';
3448     return SendPacket (strm.str());
3449 }
3450