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