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