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