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