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_qCmd,          NULL, "qCmd", "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, 12,  "f0",    {0}, k_zero_bytes, 0},
882     { 17, 12,  "f1",    {0}, k_zero_bytes, 0},
883     { 18, 12,  "f2",    {0}, k_zero_bytes, 0},
884     { 19, 12,  "f3",    {0}, k_zero_bytes, 0},
885     { 20, 12,  "f4",    {0}, k_zero_bytes, 0},
886     { 21, 12,  "f5",    {0}, k_zero_bytes, 0},
887     { 22, 12,  "f6",    {0}, k_zero_bytes, 0},
888     { 23, 12,  "f7",    {0}, k_zero_bytes, 0},
889     { 24,  4, "fps",    {0}, k_zero_bytes, 0},
890     { 25,  4,"cpsr",    {0}, NULL, 1},
891     { 26,  4,  "s0",    {0}, NULL, 0},
892     { 27,  4,  "s1",    {0}, NULL, 0},
893     { 28,  4,  "s2",    {0}, NULL, 0},
894     { 29,  4,  "s3",    {0}, NULL, 0},
895     { 30,  4,  "s4",    {0}, NULL, 0},
896     { 31,  4,  "s5",    {0}, NULL, 0},
897     { 32,  4,  "s6",    {0}, NULL, 0},
898     { 33,  4,  "s7",    {0}, NULL, 0},
899     { 34,  4,  "s8",    {0}, NULL, 0},
900     { 35,  4,  "s9",    {0}, NULL, 0},
901     { 36,  4, "s10",    {0}, NULL, 0},
902     { 37,  4, "s11",    {0}, NULL, 0},
903     { 38,  4, "s12",    {0}, NULL, 0},
904     { 39,  4, "s13",    {0}, NULL, 0},
905     { 40,  4, "s14",    {0}, NULL, 0},
906     { 41,  4, "s15",    {0}, NULL, 0},
907     { 42,  4, "s16",    {0}, NULL, 0},
908     { 43,  4, "s17",    {0}, NULL, 0},
909     { 44,  4, "s18",    {0}, NULL, 0},
910     { 45,  4, "s19",    {0}, NULL, 0},
911     { 46,  4, "s20",    {0}, NULL, 0},
912     { 47,  4, "s21",    {0}, NULL, 0},
913     { 48,  4, "s22",    {0}, NULL, 0},
914     { 49,  4, "s23",    {0}, NULL, 0},
915     { 50,  4, "s24",    {0}, NULL, 0},
916     { 51,  4, "s25",    {0}, NULL, 0},
917     { 52,  4, "s26",    {0}, NULL, 0},
918     { 53,  4, "s27",    {0}, NULL, 0},
919     { 54,  4, "s28",    {0}, NULL, 0},
920     { 55,  4, "s29",    {0}, NULL, 0},
921     { 56,  4, "s30",    {0}, NULL, 0},
922     { 57,  4, "s31",    {0}, NULL, 0},
923     { 58,  4, "fpscr",  {0}, NULL, 0},
924     { 59,  8, "d16",    {0}, NULL, 0},
925     { 60,  8, "d17",    {0}, NULL, 0},
926     { 61,  8, "d18",    {0}, NULL, 0},
927     { 62,  8, "d19",    {0}, NULL, 0},
928     { 63,  8, "d20",    {0}, NULL, 0},
929     { 64,  8, "d21",    {0}, NULL, 0},
930     { 65,  8, "d22",    {0}, NULL, 0},
931     { 66,  8, "d23",    {0}, NULL, 0},
932     { 67,  8, "d24",    {0}, NULL, 0},
933     { 68,  8, "d25",    {0}, NULL, 0},
934     { 69,  8, "d26",    {0}, NULL, 0},
935     { 70,  8, "d27",    {0}, NULL, 0},
936     { 71,  8, "d28",    {0}, NULL, 0},
937     { 72,  8, "d29",    {0}, NULL, 0},
938     { 73,  8, "d30",    {0}, NULL, 0},
939     { 74,  8, "d31",    {0}, NULL, 0}
940 };
941 
942 register_map_entry_t
943 g_gdb_register_map_i386[] =
944 {
945     {  0,   4, "eax"    , {0}, NULL, 0 },
946     {  1,   4, "ecx"    , {0}, NULL, 0 },
947     {  2,   4, "edx"    , {0}, NULL, 0 },
948     {  3,   4, "ebx"    , {0}, NULL, 0 },
949     {  4,   4, "esp"    , {0}, NULL, 1 },
950     {  5,   4, "ebp"    , {0}, NULL, 1 },
951     {  6,   4, "esi"    , {0}, NULL, 0 },
952     {  7,   4, "edi"    , {0}, NULL, 0 },
953     {  8,   4, "eip"    , {0}, NULL, 1 },
954     {  9,   4, "eflags" , {0}, NULL, 0 },
955     { 10,   4, "cs"     , {0}, NULL, 0 },
956     { 11,   4, "ss"     , {0}, NULL, 0 },
957     { 12,   4, "ds"     , {0}, NULL, 0 },
958     { 13,   4, "es"     , {0}, NULL, 0 },
959     { 14,   4, "fs"     , {0}, NULL, 0 },
960     { 15,   4, "gs"     , {0}, NULL, 0 },
961     { 16,  10, "stmm0"  , {0}, NULL, 0 },
962     { 17,  10, "stmm1"  , {0}, NULL, 0 },
963     { 18,  10, "stmm2"  , {0}, NULL, 0 },
964     { 19,  10, "stmm3"  , {0}, NULL, 0 },
965     { 20,  10, "stmm4"  , {0}, NULL, 0 },
966     { 21,  10, "stmm5"  , {0}, NULL, 0 },
967     { 22,  10, "stmm6"  , {0}, NULL, 0 },
968     { 23,  10, "stmm7"  , {0}, NULL, 0 },
969     { 24,   4, "fctrl"  , {0}, NULL, 0 },
970     { 25,   4, "fstat"  , {0}, NULL, 0 },
971     { 26,   4, "ftag"   , {0}, NULL, 0 },
972     { 27,   4, "fiseg"  , {0}, NULL, 0 },
973     { 28,   4, "fioff"  , {0}, NULL, 0 },
974     { 29,   4, "foseg"  , {0}, NULL, 0 },
975     { 30,   4, "fooff"  , {0}, NULL, 0 },
976     { 31,   4, "fop"    , {0}, NULL, 0 },
977     { 32,  16, "xmm0"   , {0}, NULL, 0 },
978     { 33,  16, "xmm1"   , {0}, NULL, 0 },
979     { 34,  16, "xmm2"   , {0}, NULL, 0 },
980     { 35,  16, "xmm3"   , {0}, NULL, 0 },
981     { 36,  16, "xmm4"   , {0}, NULL, 0 },
982     { 37,  16, "xmm5"   , {0}, NULL, 0 },
983     { 38,  16, "xmm6"   , {0}, NULL, 0 },
984     { 39,  16, "xmm7"   , {0}, NULL, 0 },
985     { 40,   4, "mxcsr"  , {0}, NULL, 0 },
986 };
987 
988 register_map_entry_t
989 g_gdb_register_map_x86_64[] =
990 {
991     {  0,   8, "rax"   , {0}, NULL, 0 },
992     {  1,   8, "rbx"   , {0}, NULL, 0 },
993     {  2,   8, "rcx"   , {0}, NULL, 0 },
994     {  3,   8, "rdx"   , {0}, NULL, 0 },
995     {  4,   8, "rsi"   , {0}, NULL, 0 },
996     {  5,   8, "rdi"   , {0}, NULL, 0 },
997     {  6,   8, "rbp"   , {0}, NULL, 1 },
998     {  7,   8, "rsp"   , {0}, NULL, 1 },
999     {  8,   8, "r8"    , {0}, NULL, 0 },
1000     {  9,   8, "r9"    , {0}, NULL, 0 },
1001     { 10,   8, "r10"   , {0}, NULL, 0 },
1002     { 11,   8, "r11"   , {0}, NULL, 0 },
1003     { 12,   8, "r12"   , {0}, NULL, 0 },
1004     { 13,   8, "r13"   , {0}, NULL, 0 },
1005     { 14,   8, "r14"   , {0}, NULL, 0 },
1006     { 15,   8, "r15"   , {0}, NULL, 0 },
1007     { 16,   8, "rip"   , {0}, NULL, 1 },
1008     { 17,   4, "rflags", {0}, NULL, 0 },
1009     { 18,   4, "cs"    , {0}, NULL, 0 },
1010     { 19,   4, "ss"    , {0}, NULL, 0 },
1011     { 20,   4, "ds"    , {0}, NULL, 0 },
1012     { 21,   4, "es"    , {0}, NULL, 0 },
1013     { 22,   4, "fs"    , {0}, NULL, 0 },
1014     { 23,   4, "gs"    , {0}, NULL, 0 },
1015     { 24,  10, "stmm0" , {0}, NULL, 0 },
1016     { 25,  10, "stmm1" , {0}, NULL, 0 },
1017     { 26,  10, "stmm2" , {0}, NULL, 0 },
1018     { 27,  10, "stmm3" , {0}, NULL, 0 },
1019     { 28,  10, "stmm4" , {0}, NULL, 0 },
1020     { 29,  10, "stmm5" , {0}, NULL, 0 },
1021     { 30,  10, "stmm6" , {0}, NULL, 0 },
1022     { 31,  10, "stmm7" , {0}, NULL, 0 },
1023     { 32,   4, "fctrl" , {0}, NULL, 0 },
1024     { 33,   4, "fstat" , {0}, NULL, 0 },
1025     { 34,   4, "ftag"  , {0}, NULL, 0 },
1026     { 35,   4, "fiseg" , {0}, NULL, 0 },
1027     { 36,   4, "fioff" , {0}, NULL, 0 },
1028     { 37,   4, "foseg" , {0}, NULL, 0 },
1029     { 38,   4, "fooff" , {0}, NULL, 0 },
1030     { 39,   4, "fop"   , {0}, NULL, 0 },
1031     { 40,  16, "xmm0"  , {0}, NULL, 0 },
1032     { 41,  16, "xmm1"  , {0}, NULL, 0 },
1033     { 42,  16, "xmm2"  , {0}, NULL, 0 },
1034     { 43,  16, "xmm3"  , {0}, NULL, 0 },
1035     { 44,  16, "xmm4"  , {0}, NULL, 0 },
1036     { 45,  16, "xmm5"  , {0}, NULL, 0 },
1037     { 46,  16, "xmm6"  , {0}, NULL, 0 },
1038     { 47,  16, "xmm7"  , {0}, NULL, 0 },
1039     { 48,  16, "xmm8"  , {0}, NULL, 0 },
1040     { 49,  16, "xmm9"  , {0}, NULL, 0 },
1041     { 50,  16, "xmm10" , {0}, NULL, 0 },
1042     { 51,  16, "xmm11" , {0}, NULL, 0 },
1043     { 52,  16, "xmm12" , {0}, NULL, 0 },
1044     { 53,  16, "xmm13" , {0}, NULL, 0 },
1045     { 54,  16, "xmm14" , {0}, NULL, 0 },
1046     { 55,  16, "xmm15" , {0}, NULL, 0 },
1047     { 56,   4, "mxcsr" , {0}, NULL, 0 }
1048 };
1049 
1050 
1051 void
1052 RNBRemote::Initialize()
1053 {
1054     DNBInitialize();
1055 }
1056 
1057 
1058 bool
1059 RNBRemote::InitializeRegisters ()
1060 {
1061     pid_t pid = m_ctx.ProcessID();
1062     if (pid == INVALID_NUB_PROCESS)
1063         return false;
1064 
1065     if (m_use_native_regs)
1066     {
1067         DNBLogThreadedIf (LOG_RNB_PROC, "RNBRemote::%s() getting native registers from DNB interface", __FUNCTION__);
1068         // Discover the registers by querying the DNB interface and letting it
1069         // state the registers that it would like to export. This allows the
1070         // registers to be discovered using multiple qRegisterInfo calls to get
1071         // all register information after the architecture for the process is
1072         // determined.
1073         if (g_dynamic_register_map.empty())
1074         {
1075             nub_size_t num_reg_sets = 0;
1076             const DNBRegisterSetInfo *reg_sets = DNBGetRegisterSetInfo (&num_reg_sets);
1077 
1078             assert (num_reg_sets > 0 && reg_sets != NULL);
1079 
1080             uint32_t regnum = 0;
1081             for (nub_size_t set = 0; set < num_reg_sets; ++set)
1082             {
1083                 if (reg_sets[set].registers == NULL)
1084                     continue;
1085 
1086                 for (uint32_t reg=0; reg < reg_sets[set].num_registers; ++reg)
1087                 {
1088                     register_map_entry_t reg_entry = {
1089                         regnum++,                           // register number starts at zero and goes up with no gaps
1090                         reg_sets[set].registers[reg].size,  // register size in bytes
1091                         reg_sets[set].registers[reg].name,  // register name
1092                         reg_sets[set].registers[reg],       // DNBRegisterInfo
1093                         NULL,                               // Value to print if case we fail to reg this register (if this is NULL, we will return an error)
1094                         reg_sets[set].registers[reg].reg_generic != INVALID_NUB_REGNUM};
1095 
1096                     g_dynamic_register_map.push_back (reg_entry);
1097                 }
1098             }
1099             g_reg_entries = g_dynamic_register_map.data();
1100             g_num_reg_entries = g_dynamic_register_map.size();
1101         }
1102         return true;
1103     }
1104     else
1105     {
1106         uint32_t cpu_type = DNBProcessGetCPUType (pid);
1107         DNBLogThreadedIf (LOG_RNB_PROC, "RNBRemote::%s() getting gdb registers(%s)", __FUNCTION__, m_arch.c_str());
1108 #if defined (__i386__) || defined (__x86_64__)
1109         if (cpu_type == CPU_TYPE_X86_64)
1110         {
1111             const size_t num_regs = sizeof (g_gdb_register_map_x86_64) / sizeof (register_map_entry_t);
1112             for (uint32_t i=0; i<num_regs; ++i)
1113             {
1114                 if (!DNBGetRegisterInfoByName (g_gdb_register_map_x86_64[i].gdb_name, &g_gdb_register_map_x86_64[i].nub_info))
1115                 {
1116                     RegisterEntryNotAvailable (&g_gdb_register_map_x86_64[i]);
1117                     assert (g_gdb_register_map_x86_64[i].gdb_size < MAX_REGISTER_BYTE_SIZE);
1118                 }
1119             }
1120             g_reg_entries = g_gdb_register_map_x86_64;
1121             g_num_reg_entries = sizeof (g_gdb_register_map_x86_64) / sizeof (register_map_entry_t);
1122             return true;
1123         }
1124         else if (cpu_type == CPU_TYPE_I386)
1125         {
1126             const size_t num_regs = sizeof (g_gdb_register_map_i386) / sizeof (register_map_entry_t);
1127             for (uint32_t i=0; i<num_regs; ++i)
1128             {
1129                 if (!DNBGetRegisterInfoByName (g_gdb_register_map_i386[i].gdb_name, &g_gdb_register_map_i386[i].nub_info))
1130                 {
1131                     RegisterEntryNotAvailable (&g_gdb_register_map_i386[i]);
1132                     assert (g_gdb_register_map_i386[i].gdb_size <= MAX_REGISTER_BYTE_SIZE);
1133                 }
1134             }
1135             g_reg_entries = g_gdb_register_map_i386;
1136             g_num_reg_entries = sizeof (g_gdb_register_map_i386) / sizeof (register_map_entry_t);
1137             return true;
1138         }
1139 #elif defined (__arm__)
1140         if (cpu_type == CPU_TYPE_ARM)
1141         {
1142             const size_t num_regs = sizeof (g_gdb_register_map_arm) / sizeof (register_map_entry_t);
1143             for (uint32_t i=0; i<num_regs; ++i)
1144             {
1145                 if (!DNBGetRegisterInfoByName (g_gdb_register_map_arm[i].gdb_name, &g_gdb_register_map_arm[i].nub_info))
1146                 {
1147                     RegisterEntryNotAvailable (&g_gdb_register_map_arm[i]);
1148                     assert (g_gdb_register_map_arm[i].gdb_size <= MAX_REGISTER_BYTE_SIZE);
1149                 }
1150             }
1151             g_reg_entries = g_gdb_register_map_arm;
1152             g_num_reg_entries = sizeof (g_gdb_register_map_arm) / sizeof (register_map_entry_t);
1153             return true;
1154         }
1155 #endif
1156     }
1157     return false;
1158 }
1159 
1160 /* The inferior has stopped executing; send a packet
1161  to gdb to let it know.  */
1162 
1163 void
1164 RNBRemote::NotifyThatProcessStopped (void)
1165 {
1166     RNBRemote::HandlePacket_last_signal (NULL);
1167     return;
1168 }
1169 
1170 
1171 /* 'A arglen,argnum,arg,...'
1172  Update the inferior context CTX with the program name and arg
1173  list.
1174  The documentation for this packet is underwhelming but my best reading
1175  of this is that it is a series of (len, position #, arg)'s, one for
1176  each argument with "arg" hex encoded (two 0-9a-f chars?).
1177  Why we need BOTH a "len" and a hex encoded "arg" is beyond me - either
1178  is sufficient to get around the "," position separator escape issue.
1179 
1180  e.g. our best guess for a valid 'A' packet for "gdb -q a.out" is
1181 
1182  6,0,676462,4,1,2d71,10,2,612e6f7574
1183 
1184  Note that "argnum" and "arglen" are numbers in base 10.  Again, that's
1185  not documented either way but I'm assuming it's so.  */
1186 
1187 rnb_err_t
1188 RNBRemote::HandlePacket_A (const char *p)
1189 {
1190     if (p == NULL || *p == '\0')
1191     {
1192         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Null packet for 'A' pkt");
1193     }
1194     p++;
1195     if (p == '\0' || !isdigit (*p))
1196     {
1197         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "arglen not specified on 'A' pkt");
1198     }
1199 
1200     /* I promise I don't modify it anywhere in this function.  strtoul()'s
1201      2nd arg has to be non-const which makes it problematic to step
1202      through the string easily.  */
1203     char *buf = const_cast<char *>(p);
1204 
1205     RNBContext& ctx = Context();
1206 
1207     while (*buf != '\0')
1208     {
1209         int arglen, argnum;
1210         std::string arg;
1211         char *c;
1212 
1213         errno = 0;
1214         arglen = strtoul (buf, &c, 10);
1215         if (errno != 0 && arglen == 0)
1216         {
1217             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "arglen not a number on 'A' pkt");
1218         }
1219         if (*c != ',')
1220         {
1221             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "arglen not followed by comma on 'A' pkt");
1222         }
1223         buf = c + 1;
1224 
1225         errno = 0;
1226         argnum = strtoul (buf, &c, 10);
1227         if (errno != 0 && argnum == 0)
1228         {
1229             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "argnum not a number on 'A' pkt");
1230         }
1231         if (*c != ',')
1232         {
1233             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "arglen not followed by comma on 'A' pkt");
1234         }
1235         buf = c + 1;
1236 
1237         c = buf;
1238         buf = buf + arglen;
1239         while (c < buf && *c != '\0' && c + 1 < buf && *(c + 1) != '\0')
1240         {
1241             char smallbuf[3];
1242             smallbuf[0] = *c;
1243             smallbuf[1] = *(c + 1);
1244             smallbuf[2] = '\0';
1245 
1246             errno = 0;
1247             int ch = strtoul (smallbuf, NULL, 16);
1248             if (errno != 0 && ch == 0)
1249             {
1250                 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'A' pkt");
1251             }
1252 
1253             arg.push_back(ch);
1254             c += 2;
1255         }
1256 
1257         ctx.PushArgument (arg.c_str());
1258         if (*buf == ',')
1259             buf++;
1260     }
1261     SendPacket ("OK");
1262 
1263     return rnb_success;
1264 }
1265 
1266 /* 'H c t'
1267  Set the thread for subsequent actions; 'c' for step/continue ops,
1268  'g' for other ops.  -1 means all threads, 0 means any thread.  */
1269 
1270 rnb_err_t
1271 RNBRemote::HandlePacket_H (const char *p)
1272 {
1273     p++;  // skip 'H'
1274     if (*p != 'c' && *p != 'g')
1275     {
1276         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Missing 'c' or 'g' type in H packet");
1277     }
1278 
1279     if (!m_ctx.HasValidProcessID())
1280     {
1281         // We allow gdb to connect to a server that hasn't started running
1282         // the target yet.  gdb still wants to ask questions about it and
1283         // freaks out if it gets an error.  So just return OK here.
1284     }
1285 
1286     errno = 0;
1287     nub_thread_t tid = strtoul (p + 1, NULL, 16);
1288     if (errno != 0 && tid == 0)
1289     {
1290         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid thread number in H packet");
1291     }
1292     if (*p == 'c')
1293         SetContinueThread (tid);
1294     if (*p == 'g')
1295         SetCurrentThread (tid);
1296 
1297     return SendPacket ("OK");
1298 }
1299 
1300 
1301 rnb_err_t
1302 RNBRemote::HandlePacket_qLaunchSuccess (const char *p)
1303 {
1304     if (m_ctx.HasValidProcessID() || m_ctx.LaunchStatus().Error() == 0)
1305         return SendPacket("OK");
1306     std::ostringstream ret_str;
1307     std::string status_str;
1308     ret_str << "E" << m_ctx.LaunchStatusAsString(status_str);
1309 
1310     return SendPacket (ret_str.str());
1311 }
1312 
1313 rnb_err_t
1314 RNBRemote::HandlePacket_qShlibInfoAddr (const char *p)
1315 {
1316     if (m_ctx.HasValidProcessID())
1317     {
1318         nub_addr_t shlib_info_addr = DNBProcessGetSharedLibraryInfoAddress(m_ctx.ProcessID());
1319         if (shlib_info_addr != INVALID_NUB_ADDRESS)
1320         {
1321             std::ostringstream ostrm;
1322             ostrm << RAW_HEXBASE << shlib_info_addr;
1323             return SendPacket (ostrm.str ());
1324         }
1325     }
1326     return SendPacket ("E44");
1327 }
1328 
1329 rnb_err_t
1330 RNBRemote::HandlePacket_qStepPacketSupported (const char *p)
1331 {
1332     // Normally the "s" packet is mandatory, yet in gdb when using ARM, they
1333     // get around the need for this packet by implementing software single
1334     // stepping from gdb. Current versions of debugserver do support the "s"
1335     // packet, yet some older versions do not. We need a way to tell if this
1336     // packet is supported so we can disable software single stepping in gdb
1337     // for remote targets (so the "s" packet will get used).
1338     return SendPacket("OK");
1339 }
1340 
1341 rnb_err_t
1342 RNBRemote::HandlePacket_qSyncThreadStateSupported (const char *p)
1343 {
1344     // We support attachOrWait meaning attach if the process exists, otherwise wait to attach.
1345     return SendPacket("OK");
1346 }
1347 
1348 rnb_err_t
1349 RNBRemote::HandlePacket_qVAttachOrWaitSupported (const char *p)
1350 {
1351     // We support attachOrWait meaning attach if the process exists, otherwise wait to attach.
1352     return SendPacket("OK");
1353 }
1354 
1355 rnb_err_t
1356 RNBRemote::HandlePacket_qThreadStopInfo (const char *p)
1357 {
1358     p += strlen ("qThreadStopInfo");
1359     nub_thread_t tid = strtoul(p, 0, 16);
1360     return SendStopReplyPacketForThread (tid);
1361 }
1362 
1363 rnb_err_t
1364 RNBRemote::HandlePacket_qThreadInfo (const char *p)
1365 {
1366     // We allow gdb to connect to a server that hasn't started running
1367     // the target yet.  gdb still wants to ask questions about it and
1368     // freaks out if it gets an error.  So just return OK here.
1369     nub_process_t pid = m_ctx.ProcessID();
1370     if (pid == INVALID_NUB_PROCESS)
1371         return SendPacket ("OK");
1372 
1373     // Only "qfThreadInfo" and "qsThreadInfo" get into this function so
1374     // we only need to check the second byte to tell which is which
1375     if (p[1] == 'f')
1376     {
1377         nub_size_t numthreads = DNBProcessGetNumThreads (pid);
1378         std::ostringstream ostrm;
1379         ostrm << "m";
1380         bool first = true;
1381         for (nub_size_t i = 0; i < numthreads; ++i)
1382         {
1383             if (first)
1384                 first = false;
1385             else
1386                 ostrm << ",";
1387             nub_thread_t th = DNBProcessGetThreadAtIndex (pid, i);
1388             ostrm << std::hex << th;
1389         }
1390         return SendPacket (ostrm.str ());
1391     }
1392     else
1393     {
1394         return SendPacket ("l");
1395     }
1396 }
1397 
1398 rnb_err_t
1399 RNBRemote::HandlePacket_qThreadExtraInfo (const char *p)
1400 {
1401     // We allow gdb to connect to a server that hasn't started running
1402     // the target yet.  gdb still wants to ask questions about it and
1403     // freaks out if it gets an error.  So just return OK here.
1404     nub_process_t pid = m_ctx.ProcessID();
1405     if (pid == INVALID_NUB_PROCESS)
1406         return SendPacket ("OK");
1407 
1408     /* This is supposed to return a string like 'Runnable' or
1409      'Blocked on Mutex'.
1410      The returned string is formatted like the "A" packet - a
1411      sequence of letters encoded in as 2-hex-chars-per-letter.  */
1412     p += strlen ("qThreadExtraInfo");
1413     if (*p++ != ',')
1414         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Illformed qThreadExtraInfo packet");
1415     errno = 0;
1416     nub_thread_t tid = strtoul (p, NULL, 16);
1417     if (errno != 0 && tid == 0)
1418     {
1419         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid thread number in qThreadExtraInfo packet");
1420     }
1421 
1422     const char * threadInfo = DNBThreadGetInfo(pid, tid);
1423     if (threadInfo != NULL && threadInfo[0])
1424     {
1425         return SendHexEncodedBytePacket(NULL, threadInfo, strlen(threadInfo), NULL);
1426     }
1427     else
1428     {
1429         // "OK" == 4f6b
1430         // Return "OK" as a ASCII hex byte stream if things go wrong
1431         return SendPacket ("4f6b");
1432     }
1433 
1434     return SendPacket ("");
1435 }
1436 
1437 
1438 const char *k_space_delimiters = " \t";
1439 static void
1440 skip_spaces (std::string &line)
1441 {
1442     if (!line.empty())
1443     {
1444         size_t space_pos = line.find_first_not_of (k_space_delimiters);
1445         if (space_pos > 0)
1446             line.erase(0, space_pos);
1447     }
1448 }
1449 
1450 static std::string
1451 get_identifier (std::string &line)
1452 {
1453     std::string word;
1454     skip_spaces (line);
1455     const size_t line_size = line.size();
1456     size_t end_pos;
1457     for (end_pos = 0; end_pos < line_size; ++end_pos)
1458     {
1459         if (end_pos == 0)
1460         {
1461             if (isalpha(line[end_pos]) || line[end_pos] == '_')
1462                 continue;
1463         }
1464         else if (isalnum(line[end_pos]) || line[end_pos] == '_')
1465             continue;
1466         break;
1467     }
1468     word.assign (line, 0, end_pos);
1469     line.erase(0, end_pos);
1470     return word;
1471 }
1472 
1473 static std::string
1474 get_operator (std::string &line)
1475 {
1476     std::string op;
1477     skip_spaces (line);
1478     if (!line.empty())
1479     {
1480         if (line[0] == '=')
1481         {
1482             op = '=';
1483             line.erase(0,1);
1484         }
1485     }
1486     return op;
1487 }
1488 
1489 static std::string
1490 get_value (std::string &line)
1491 {
1492     std::string value;
1493     skip_spaces (line);
1494     if (!line.empty())
1495     {
1496         value.swap(line);
1497     }
1498     return value;
1499 }
1500 
1501 
1502 extern void FileLogCallback(void *baton, uint32_t flags, const char *format, va_list args);
1503 extern void ASLLogCallback(void *baton, uint32_t flags, const char *format, va_list args);
1504 
1505 rnb_err_t
1506 RNBRemote::HandlePacket_qCmd (const char *p)
1507 {
1508     const char *c = p + strlen("qCmd,");
1509     std::string line;
1510     while (c[0] && c[1])
1511     {
1512         char smallbuf[3] = { c[0], c[1], '\0' };
1513         errno = 0;
1514         int ch = strtoul (smallbuf, NULL, 16);
1515         if (errno != 0 && ch == 0)
1516             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in payload of qCmd packet");
1517         line.push_back(ch);
1518         c += 2;
1519     }
1520     if (*c == '\0')
1521     {
1522         std::string command = get_identifier(line);
1523         if (command.compare("set") == 0)
1524         {
1525             std::string variable = get_identifier (line);
1526             std::string op = get_operator (line);
1527             std::string value = get_value (line);
1528             if (variable.compare("logfile") == 0)
1529             {
1530                 FILE *log_file = fopen(value.c_str(), "w");
1531                 if (log_file)
1532                 {
1533                     DNBLogSetLogCallback(FileLogCallback, log_file);
1534                     return SendPacket ("OK");
1535                 }
1536                 return SendPacket ("E71");
1537             }
1538             else if (variable.compare("logmask") == 0)
1539             {
1540                 char *end;
1541                 errno = 0;
1542                 uint32_t logmask = strtoul (value.c_str(), &end, 0);
1543                 if (errno == 0 && end && *end == '\0')
1544                 {
1545                     DNBLogSetLogMask (logmask);
1546                     if (!DNBLogGetLogCallback())
1547                         DNBLogSetLogCallback(ASLLogCallback, NULL);
1548                     return SendPacket ("OK");
1549                 }
1550                 errno = 0;
1551                 logmask = strtoul (value.c_str(), &end, 16);
1552                 if (errno == 0 && end && *end == '\0')
1553                 {
1554                     DNBLogSetLogMask (logmask);
1555                     return SendPacket ("OK");
1556                 }
1557                 return SendPacket ("E72");
1558             }
1559             return SendPacket ("E70");
1560         }
1561         return SendPacket ("E69");
1562     }
1563     return SendPacket ("E73");
1564 }
1565 
1566 rnb_err_t
1567 RNBRemote::HandlePacket_qC (const char *p)
1568 {
1569     nub_process_t pid;
1570     std::ostringstream rep;
1571     // If we haven't run the process yet, we tell the debugger the
1572     // pid is 0.  That way it can know to tell use to run later on.
1573     if (m_ctx.HasValidProcessID())
1574         pid = m_ctx.ProcessID();
1575     else
1576         pid = 0;
1577     rep << "QC" << std::hex << pid;
1578     return SendPacket (rep.str());
1579 }
1580 
1581 rnb_err_t
1582 RNBRemote::HandlePacket_qGetPid (const char *p)
1583 {
1584     nub_process_t pid;
1585     std::ostringstream rep;
1586     // If we haven't run the process yet, we tell the debugger the
1587     // pid is 0.  That way it can know to tell use to run later on.
1588     if (m_ctx.HasValidProcessID())
1589         pid = m_ctx.ProcessID();
1590     else
1591         pid = 0;
1592     rep << std::hex << pid;
1593     return SendPacket (rep.str());
1594 }
1595 
1596 rnb_err_t
1597 RNBRemote::HandlePacket_qRegisterInfo (const char *p)
1598 {
1599     if (g_num_reg_entries == 0)
1600         InitializeRegisters ();
1601 
1602     p += strlen ("qRegisterInfo");
1603 
1604     nub_size_t num_reg_sets = 0;
1605     const DNBRegisterSetInfo *reg_set_info = DNBGetRegisterSetInfo (&num_reg_sets);
1606     uint32_t reg_num = strtoul(p, 0, 16);
1607 
1608     if (reg_num < g_num_reg_entries)
1609     {
1610         const register_map_entry_t *reg_entry = &g_reg_entries[reg_num];
1611         std::ostringstream ostrm;
1612         ostrm << "name:" << reg_entry->gdb_name << ';';
1613 
1614         if (reg_entry->nub_info.name && ::strcmp (reg_entry->gdb_name, reg_entry->nub_info.name))
1615             ostrm << "alt-name:" << reg_entry->nub_info.name << ';';
1616         else if (reg_entry->nub_info.alt && ::strcmp (reg_entry->gdb_name, reg_entry->nub_info.alt))
1617             ostrm << "alt-name:" << reg_entry->nub_info.alt << ';';
1618 
1619         ostrm << "bitsize:" << std::dec << reg_entry->gdb_size * 8 << ';';
1620         ostrm << "offset:" << std::dec << reg_entry->nub_info.offset << ';';
1621 
1622         switch (reg_entry->nub_info.type)
1623         {
1624             case Uint:      ostrm << "encoding:uint;"; break;
1625             case Sint:      ostrm << "encoding:sint;"; break;
1626             case IEEE754:   ostrm << "encoding:ieee754;"; break;
1627             case Vector:    ostrm << "encoding:vector;"; break;
1628         }
1629 
1630         switch (reg_entry->nub_info.format)
1631         {
1632             case Binary:            ostrm << "format:binary;"; break;
1633             case Decimal:           ostrm << "format:decimal;"; break;
1634             case Hex:               ostrm << "format:hex;"; break;
1635             case Float:             ostrm << "format:float;"; break;
1636             case VectorOfSInt8:     ostrm << "format:vector-sint8;"; break;
1637             case VectorOfUInt8:     ostrm << "format:vector-uint8;"; break;
1638             case VectorOfSInt16:    ostrm << "format:vector-sint16;"; break;
1639             case VectorOfUInt16:    ostrm << "format:vector-uint16;"; break;
1640             case VectorOfSInt32:    ostrm << "format:vector-sint32;"; break;
1641             case VectorOfUInt32:    ostrm << "format:vector-uint32;"; break;
1642             case VectorOfFloat32:   ostrm << "format:vector-float32;"; break;
1643             case VectorOfUInt128:   ostrm << "format:vector-uint128;"; break;
1644         };
1645 
1646         if (reg_set_info && reg_entry->nub_info.set < num_reg_sets)
1647             ostrm << "set:" << reg_set_info[reg_entry->nub_info.set].name << ';';
1648 
1649 
1650         if (g_reg_entries != g_dynamic_register_map.data())
1651         {
1652             if (reg_entry->nub_info.reg_gdb != INVALID_NUB_REGNUM && reg_entry->nub_info.reg_gdb != reg_num)
1653             {
1654                 printf("register %s is getting gdb reg_num of %u when the register info says %u\n",
1655                        reg_entry->gdb_name, reg_num, reg_entry->nub_info.reg_gdb);
1656             }
1657         }
1658 
1659         if (reg_entry->nub_info.reg_gcc != INVALID_NUB_REGNUM)
1660             ostrm << "gcc:" << std::dec << reg_entry->nub_info.reg_gcc << ';';
1661 
1662         if (reg_entry->nub_info.reg_dwarf != INVALID_NUB_REGNUM)
1663             ostrm << "dwarf:" << std::dec << reg_entry->nub_info.reg_dwarf << ';';
1664 
1665 
1666         switch (reg_entry->nub_info.reg_generic)
1667         {
1668             case GENERIC_REGNUM_FP:     ostrm << "generic:fp;"; break;
1669             case GENERIC_REGNUM_PC:     ostrm << "generic:pc;"; break;
1670             case GENERIC_REGNUM_SP:     ostrm << "generic:sp;"; break;
1671             case GENERIC_REGNUM_RA:     ostrm << "generic:ra;"; break;
1672             case GENERIC_REGNUM_FLAGS:  ostrm << "generic:flags;"; break;
1673             case GENERIC_REGNUM_ARG1:   ostrm << "generic:arg1;"; break;
1674             case GENERIC_REGNUM_ARG2:   ostrm << "generic:arg2;"; break;
1675             case GENERIC_REGNUM_ARG3:   ostrm << "generic:arg3;"; break;
1676             case GENERIC_REGNUM_ARG4:   ostrm << "generic:arg4;"; break;
1677             case GENERIC_REGNUM_ARG5:   ostrm << "generic:arg5;"; break;
1678             case GENERIC_REGNUM_ARG6:   ostrm << "generic:arg6;"; break;
1679             case GENERIC_REGNUM_ARG7:   ostrm << "generic:arg7;"; break;
1680             case GENERIC_REGNUM_ARG8:   ostrm << "generic:arg8;"; break;
1681             default: break;
1682         }
1683 
1684         if (reg_entry->nub_info.pseudo_regs && reg_entry->nub_info.pseudo_regs[0] != INVALID_NUB_REGNUM)
1685         {
1686             ostrm << "container-regs:";
1687             for (unsigned i=0; reg_entry->nub_info.pseudo_regs[i] != INVALID_NUB_REGNUM; ++i)
1688             {
1689                 if (i > 0)
1690                     ostrm << ',';
1691                 ostrm << RAW_HEXBASE << reg_entry->nub_info.pseudo_regs[i];
1692             }
1693             ostrm << ';';
1694         }
1695 
1696         if (reg_entry->nub_info.update_regs && reg_entry->nub_info.update_regs[0] != INVALID_NUB_REGNUM)
1697         {
1698             ostrm << "invalidate-regs:";
1699             for (unsigned i=0; reg_entry->nub_info.update_regs[i] != INVALID_NUB_REGNUM; ++i)
1700             {
1701                 if (i > 0)
1702                     ostrm << ',';
1703                 ostrm << RAW_HEXBASE << reg_entry->nub_info.update_regs[i];
1704             }
1705             ostrm << ';';
1706         }
1707 
1708         return SendPacket (ostrm.str ());
1709     }
1710     return SendPacket ("E45");
1711 }
1712 
1713 
1714 /* This expects a packet formatted like
1715 
1716  QSetLogging:bitmask=LOG_ALL|LOG_RNB_REMOTE;
1717 
1718  with the "QSetLogging:" already removed from the start.  Maybe in the
1719  future this packet will include other keyvalue pairs like
1720 
1721  QSetLogging:bitmask=LOG_ALL;mode=asl;
1722  */
1723 
1724 rnb_err_t
1725 set_logging (const char *p)
1726 {
1727     int bitmask = 0;
1728     while (p && *p != '\0')
1729     {
1730         if (strncmp (p, "bitmask=", sizeof ("bitmask=") - 1) == 0)
1731         {
1732             p += sizeof ("bitmask=") - 1;
1733             while (p && *p != '\0' && *p != ';')
1734             {
1735                 if (*p == '|')
1736                     p++;
1737 
1738 // to regenerate the LOG_ entries (not including the LOG_RNB entries)
1739 // $ for logname in `grep '^#define LOG_' DNBDefs.h | egrep -v 'LOG_HI|LOG_LO' | awk '{print $2}'`
1740 // do
1741 //   echo "                else if (strncmp (p, \"$logname\", sizeof (\"$logname\") - 1) == 0)"
1742 //   echo "                {"
1743 //   echo "                    p += sizeof (\"$logname\") - 1;"
1744 //   echo "                    bitmask |= $logname;"
1745 //   echo "                }"
1746 // done
1747                 if (strncmp (p, "LOG_VERBOSE", sizeof ("LOG_VERBOSE") - 1) == 0)
1748                 {
1749                     p += sizeof ("LOG_VERBOSE") - 1;
1750                     bitmask |= LOG_VERBOSE;
1751                 }
1752                 else if (strncmp (p, "LOG_PROCESS", sizeof ("LOG_PROCESS") - 1) == 0)
1753                 {
1754                     p += sizeof ("LOG_PROCESS") - 1;
1755                     bitmask |= LOG_PROCESS;
1756                 }
1757                 else if (strncmp (p, "LOG_THREAD", sizeof ("LOG_THREAD") - 1) == 0)
1758                 {
1759                     p += sizeof ("LOG_THREAD") - 1;
1760                     bitmask |= LOG_THREAD;
1761                 }
1762                 else if (strncmp (p, "LOG_EXCEPTIONS", sizeof ("LOG_EXCEPTIONS") - 1) == 0)
1763                 {
1764                     p += sizeof ("LOG_EXCEPTIONS") - 1;
1765                     bitmask |= LOG_EXCEPTIONS;
1766                 }
1767                 else if (strncmp (p, "LOG_SHLIB", sizeof ("LOG_SHLIB") - 1) == 0)
1768                 {
1769                     p += sizeof ("LOG_SHLIB") - 1;
1770                     bitmask |= LOG_SHLIB;
1771                 }
1772                 else if (strncmp (p, "LOG_MEMORY", sizeof ("LOG_MEMORY") - 1) == 0)
1773                 {
1774                     p += sizeof ("LOG_MEMORY") - 1;
1775                     bitmask |= LOG_MEMORY;
1776                 }
1777                 else if (strncmp (p, "LOG_MEMORY_DATA_SHORT", sizeof ("LOG_MEMORY_DATA_SHORT") - 1) == 0)
1778                 {
1779                     p += sizeof ("LOG_MEMORY_DATA_SHORT") - 1;
1780                     bitmask |= LOG_MEMORY_DATA_SHORT;
1781                 }
1782                 else if (strncmp (p, "LOG_MEMORY_DATA_LONG", sizeof ("LOG_MEMORY_DATA_LONG") - 1) == 0)
1783                 {
1784                     p += sizeof ("LOG_MEMORY_DATA_LONG") - 1;
1785                     bitmask |= LOG_MEMORY_DATA_LONG;
1786                 }
1787                 else if (strncmp (p, "LOG_MEMORY_PROTECTIONS", sizeof ("LOG_MEMORY_PROTECTIONS") - 1) == 0)
1788                 {
1789                     p += sizeof ("LOG_MEMORY_PROTECTIONS") - 1;
1790                     bitmask |= LOG_MEMORY_PROTECTIONS;
1791                 }
1792                 else if (strncmp (p, "LOG_BREAKPOINTS", sizeof ("LOG_BREAKPOINTS") - 1) == 0)
1793                 {
1794                     p += sizeof ("LOG_BREAKPOINTS") - 1;
1795                     bitmask |= LOG_BREAKPOINTS;
1796                 }
1797                 else if (strncmp (p, "LOG_EVENTS", sizeof ("LOG_EVENTS") - 1) == 0)
1798                 {
1799                     p += sizeof ("LOG_EVENTS") - 1;
1800                     bitmask |= LOG_EVENTS;
1801                 }
1802                 else if (strncmp (p, "LOG_WATCHPOINTS", sizeof ("LOG_WATCHPOINTS") - 1) == 0)
1803                 {
1804                     p += sizeof ("LOG_WATCHPOINTS") - 1;
1805                     bitmask |= LOG_WATCHPOINTS;
1806                 }
1807                 else if (strncmp (p, "LOG_STEP", sizeof ("LOG_STEP") - 1) == 0)
1808                 {
1809                     p += sizeof ("LOG_STEP") - 1;
1810                     bitmask |= LOG_STEP;
1811                 }
1812                 else if (strncmp (p, "LOG_TASK", sizeof ("LOG_TASK") - 1) == 0)
1813                 {
1814                     p += sizeof ("LOG_TASK") - 1;
1815                     bitmask |= LOG_TASK;
1816                 }
1817                 else if (strncmp (p, "LOG_ALL", sizeof ("LOG_ALL") - 1) == 0)
1818                 {
1819                     p += sizeof ("LOG_ALL") - 1;
1820                     bitmask |= LOG_ALL;
1821                 }
1822                 else if (strncmp (p, "LOG_DEFAULT", sizeof ("LOG_DEFAULT") - 1) == 0)
1823                 {
1824                     p += sizeof ("LOG_DEFAULT") - 1;
1825                     bitmask |= LOG_DEFAULT;
1826                 }
1827 // end of auto-generated entries
1828 
1829                 else if (strncmp (p, "LOG_NONE", sizeof ("LOG_NONE") - 1) == 0)
1830                 {
1831                     p += sizeof ("LOG_NONE") - 1;
1832                     bitmask = 0;
1833                 }
1834                 else if (strncmp (p, "LOG_RNB_MINIMAL", sizeof ("LOG_RNB_MINIMAL") - 1) == 0)
1835                 {
1836                     p += sizeof ("LOG_RNB_MINIMAL") - 1;
1837                     bitmask |= LOG_RNB_MINIMAL;
1838                 }
1839                 else if (strncmp (p, "LOG_RNB_MEDIUM", sizeof ("LOG_RNB_MEDIUM") - 1) == 0)
1840                 {
1841                     p += sizeof ("LOG_RNB_MEDIUM") - 1;
1842                     bitmask |= LOG_RNB_MEDIUM;
1843                 }
1844                 else if (strncmp (p, "LOG_RNB_MAX", sizeof ("LOG_RNB_MAX") - 1) == 0)
1845                 {
1846                     p += sizeof ("LOG_RNB_MAX") - 1;
1847                     bitmask |= LOG_RNB_MAX;
1848                 }
1849                 else if (strncmp (p, "LOG_RNB_COMM", sizeof ("LOG_RNB_COMM") - 1) == 0)
1850                 {
1851                     p += sizeof ("LOG_RNB_COMM") - 1;
1852                     bitmask |= LOG_RNB_COMM;
1853                 }
1854                 else if (strncmp (p, "LOG_RNB_REMOTE", sizeof ("LOG_RNB_REMOTE") - 1) == 0)
1855                 {
1856                     p += sizeof ("LOG_RNB_REMOTE") - 1;
1857                     bitmask |= LOG_RNB_REMOTE;
1858                 }
1859                 else if (strncmp (p, "LOG_RNB_EVENTS", sizeof ("LOG_RNB_EVENTS") - 1) == 0)
1860                 {
1861                     p += sizeof ("LOG_RNB_EVENTS") - 1;
1862                     bitmask |= LOG_RNB_EVENTS;
1863                 }
1864                 else if (strncmp (p, "LOG_RNB_PROC", sizeof ("LOG_RNB_PROC") - 1) == 0)
1865                 {
1866                     p += sizeof ("LOG_RNB_PROC") - 1;
1867                     bitmask |= LOG_RNB_PROC;
1868                 }
1869                 else if (strncmp (p, "LOG_RNB_PACKETS", sizeof ("LOG_RNB_PACKETS") - 1) == 0)
1870                 {
1871                     p += sizeof ("LOG_RNB_PACKETS") - 1;
1872                     bitmask |= LOG_RNB_PACKETS;
1873                 }
1874                 else if (strncmp (p, "LOG_RNB_ALL", sizeof ("LOG_RNB_ALL") - 1) == 0)
1875                 {
1876                     p += sizeof ("LOG_RNB_ALL") - 1;
1877                     bitmask |= LOG_RNB_ALL;
1878                 }
1879                 else if (strncmp (p, "LOG_RNB_DEFAULT", sizeof ("LOG_RNB_DEFAULT") - 1) == 0)
1880                 {
1881                     p += sizeof ("LOG_RNB_DEFAULT") - 1;
1882                     bitmask |= LOG_RNB_DEFAULT;
1883                 }
1884                 else if (strncmp (p, "LOG_RNB_NONE", sizeof ("LOG_RNB_NONE") - 1) == 0)
1885                 {
1886                     p += sizeof ("LOG_RNB_NONE") - 1;
1887                     bitmask = 0;
1888                 }
1889                 else
1890                 {
1891                     /* Unrecognized logging bit; ignore it.  */
1892                     const char *c = strchr (p, '|');
1893                     if (c)
1894                     {
1895                         p = c;
1896                     }
1897                     else
1898                     {
1899                         c = strchr (p, ';');
1900                         if (c)
1901                         {
1902                             p = c;
1903                         }
1904                         else
1905                         {
1906                             // Improperly terminated word; just go to end of str
1907                             p = strchr (p, '\0');
1908                         }
1909                     }
1910                 }
1911             }
1912             // Did we get a properly formatted logging bitmask?
1913             if (p && *p == ';')
1914             {
1915                 // Enable DNB logging
1916                 DNBLogSetLogCallback(ASLLogCallback, NULL);
1917                 DNBLogSetLogMask (bitmask);
1918                 p++;
1919             }
1920         }
1921         // We're not going to support logging to a file for now.  All logging
1922         // goes through ASL.
1923 #if 0
1924         else if (strncmp (p, "mode=", sizeof ("mode=") - 1) == 0)
1925         {
1926             p += sizeof ("mode=") - 1;
1927             if (strncmp (p, "asl;", sizeof ("asl;") - 1) == 0)
1928             {
1929                 DNBLogToASL ();
1930                 p += sizeof ("asl;") - 1;
1931             }
1932             else if (strncmp (p, "file;", sizeof ("file;") - 1) == 0)
1933             {
1934                 DNBLogToFile ();
1935                 p += sizeof ("file;") - 1;
1936             }
1937             else
1938             {
1939                 // Ignore unknown argument
1940                 const char *c = strchr (p, ';');
1941                 if (c)
1942                     p = c + 1;
1943                 else
1944                     p = strchr (p, '\0');
1945             }
1946         }
1947         else if (strncmp (p, "filename=", sizeof ("filename=") - 1) == 0)
1948         {
1949             p += sizeof ("filename=") - 1;
1950             const char *c = strchr (p, ';');
1951             if (c == NULL)
1952             {
1953                 c = strchr (p, '\0');
1954                 continue;
1955             }
1956             char *fn = (char *) alloca (c - p + 1);
1957             strncpy (fn, p, c - p);
1958             fn[c - p] = '\0';
1959 
1960             // A file name of "asl" is special and is another way to indicate
1961             // that logging should be done via ASL, not by file.
1962             if (strcmp (fn, "asl") == 0)
1963             {
1964                 DNBLogToASL ();
1965             }
1966             else
1967             {
1968                 FILE *f = fopen (fn, "w");
1969                 if (f)
1970                 {
1971                     DNBLogSetLogFile (f);
1972                     DNBEnableLogging (f, DNBLogGetLogMask ());
1973                     DNBLogToFile ();
1974                 }
1975             }
1976             p = c + 1;
1977         }
1978 #endif /* #if 0 to enforce ASL logging only.  */
1979         else
1980         {
1981             // Ignore unknown argument
1982             const char *c = strchr (p, ';');
1983             if (c)
1984                 p = c + 1;
1985             else
1986                 p = strchr (p, '\0');
1987         }
1988     }
1989 
1990     return rnb_success;
1991 }
1992 
1993 rnb_err_t
1994 RNBRemote::HandlePacket_QThreadSuffixSupported (const char *p)
1995 {
1996     m_thread_suffix_supported = true;
1997     return SendPacket ("OK");
1998 }
1999 
2000 rnb_err_t
2001 RNBRemote::HandlePacket_QStartNoAckMode (const char *p)
2002 {
2003     // Send the OK packet first so the correct checksum is appended...
2004     rnb_err_t result = SendPacket ("OK");
2005     m_noack_mode = true;
2006     return result;
2007 }
2008 
2009 
2010 rnb_err_t
2011 RNBRemote::HandlePacket_QSetLogging (const char *p)
2012 {
2013     p += sizeof ("QSetLogging:") - 1;
2014     rnb_err_t result = set_logging (p);
2015     if (result == rnb_success)
2016         return SendPacket ("OK");
2017     else
2018         return SendPacket ("E35");
2019 }
2020 
2021 rnb_err_t
2022 RNBRemote::HandlePacket_QSetDisableASLR (const char *p)
2023 {
2024     extern int g_disable_aslr;
2025     p += sizeof ("QSetDisableASLR:") - 1;
2026     switch (*p)
2027     {
2028     case '0': g_disable_aslr = 0; break;
2029     case '1': g_disable_aslr = 1; break;
2030     default:
2031         return SendPacket ("E56");
2032     }
2033     return SendPacket ("OK");
2034 }
2035 
2036 rnb_err_t
2037 RNBRemote::HandlePacket_QSetSTDIO (const char *p)
2038 {
2039     // Only set stdin/out/err if we don't already have a process
2040     if (!m_ctx.HasValidProcessID())
2041     {
2042         bool success = false;
2043         // Check the seventh character since the packet will be one of:
2044         // QSetSTDIN
2045         // QSetSTDOUT
2046         // QSetSTDERR
2047         StringExtractor packet(p);
2048         packet.SetFilePos (7);
2049         char ch = packet.GetChar();
2050         while (packet.GetChar() != ':')
2051             /* Do nothing. */;
2052 
2053         switch (ch)
2054         {
2055             case 'I': // STDIN
2056                 packet.GetHexByteString (m_ctx.GetSTDIN());
2057                 success = !m_ctx.GetSTDIN().empty();
2058                 break;
2059 
2060             case 'O': // STDOUT
2061                 packet.GetHexByteString (m_ctx.GetSTDOUT());
2062                 success = !m_ctx.GetSTDOUT().empty();
2063                 break;
2064 
2065             case 'E': // STDERR
2066                 packet.GetHexByteString (m_ctx.GetSTDERR());
2067                 success = !m_ctx.GetSTDERR().empty();
2068                 break;
2069 
2070             default:
2071                 break;
2072         }
2073         if (success)
2074             return SendPacket ("OK");
2075         return SendPacket ("E57");
2076     }
2077     return SendPacket ("E58");
2078 }
2079 
2080 rnb_err_t
2081 RNBRemote::HandlePacket_QSetWorkingDir (const char *p)
2082 {
2083     // Only set the working directory if we don't already have a process
2084     if (!m_ctx.HasValidProcessID())
2085     {
2086         StringExtractor packet(p += sizeof ("QSetWorkingDir:") - 1);
2087         if (packet.GetHexByteString (m_ctx.GetWorkingDir()))
2088         {
2089             struct stat working_dir_stat;
2090             if (::stat(m_ctx.GetWorkingDirPath(), &working_dir_stat) == -1)
2091             {
2092                 m_ctx.GetWorkingDir().clear();
2093                 return SendPacket ("E61");    // Working directory doesn't exist...
2094             }
2095             else if ((working_dir_stat.st_mode & S_IFMT) == S_IFDIR)
2096             {
2097                 return SendPacket ("OK");
2098             }
2099             else
2100             {
2101                 m_ctx.GetWorkingDir().clear();
2102                 return SendPacket ("E62");    // Working directory isn't a directory...
2103             }
2104         }
2105         return SendPacket ("E59");  // Invalid path
2106     }
2107     return SendPacket ("E60"); // Already had a process, too late to set working dir
2108 }
2109 
2110 rnb_err_t
2111 RNBRemote::HandlePacket_QSyncThreadState (const char *p)
2112 {
2113     if (!m_ctx.HasValidProcessID())
2114     {
2115         // We allow gdb to connect to a server that hasn't started running
2116         // the target yet.  gdb still wants to ask questions about it and
2117         // freaks out if it gets an error.  So just return OK here.
2118         return SendPacket ("OK");
2119     }
2120 
2121     errno = 0;
2122     p += strlen("QSyncThreadState:");
2123     nub_thread_t tid = strtoul (p, NULL, 16);
2124     if (errno != 0 && tid == 0)
2125     {
2126         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid thread number in QSyncThreadState packet");
2127     }
2128     if (DNBProcessSyncThreadState(m_ctx.ProcessID(), tid))
2129         return SendPacket("OK");
2130     else
2131         return SendPacket ("E61");
2132 }
2133 
2134 rnb_err_t
2135 RNBRemote::HandlePacket_QListThreadsInStopReply (const char *p)
2136 {
2137     // If this packet is received, it allows us to send an extra key/value
2138     // pair in the stop reply packets where we will list all of the thread IDs
2139     // separated by commas:
2140     //
2141     //  "threads:10a,10b,10c;"
2142     //
2143     // This will get included in the stop reply packet as something like:
2144     //
2145     //  "T11thread:10a;00:00000000;01:00010203:threads:10a,10b,10c;"
2146     //
2147     // This can save two packets on each stop: qfThreadInfo/qsThreadInfo and
2148     // speed things up a bit.
2149     //
2150     // Send the OK packet first so the correct checksum is appended...
2151     rnb_err_t result = SendPacket ("OK");
2152     m_list_threads_in_stop_reply = true;
2153     return result;
2154 }
2155 
2156 
2157 rnb_err_t
2158 RNBRemote::HandlePacket_QSetMaxPayloadSize (const char *p)
2159 {
2160     /* The number of characters in a packet payload that gdb is
2161      prepared to accept.  The packet-start char, packet-end char,
2162      2 checksum chars and terminating null character are not included
2163      in this size.  */
2164     p += sizeof ("QSetMaxPayloadSize:") - 1;
2165     errno = 0;
2166     uint32_t size = strtoul (p, NULL, 16);
2167     if (errno != 0 && size == 0)
2168     {
2169         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in QSetMaxPayloadSize packet");
2170     }
2171     m_max_payload_size = size;
2172     return SendPacket ("OK");
2173 }
2174 
2175 rnb_err_t
2176 RNBRemote::HandlePacket_QSetMaxPacketSize (const char *p)
2177 {
2178     /* This tells us the largest packet that gdb can handle.
2179      i.e. the size of gdb's packet-reading buffer.
2180      QSetMaxPayloadSize is preferred because it is less ambiguous.  */
2181     p += sizeof ("QSetMaxPacketSize:") - 1;
2182     errno = 0;
2183     uint32_t size = strtoul (p, NULL, 16);
2184     if (errno != 0 && size == 0)
2185     {
2186         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in QSetMaxPacketSize packet");
2187     }
2188     m_max_payload_size = size - 5;
2189     return SendPacket ("OK");
2190 }
2191 
2192 
2193 
2194 
2195 rnb_err_t
2196 RNBRemote::HandlePacket_QEnvironment (const char *p)
2197 {
2198     /* This sets the environment for the target program.  The packet is of the form:
2199 
2200      QEnvironment:VARIABLE=VALUE
2201 
2202      */
2203 
2204     DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s Handling QEnvironment: \"%s\"",
2205                       (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, p);
2206 
2207     p += sizeof ("QEnvironment:") - 1;
2208     RNBContext& ctx = Context();
2209 
2210     ctx.PushEnvironment (p);
2211     return SendPacket ("OK");
2212 }
2213 
2214 rnb_err_t
2215 RNBRemote::HandlePacket_QEnvironmentHexEncoded (const char *p)
2216 {
2217     /* This sets the environment for the target program.  The packet is of the form:
2218 
2219         QEnvironmentHexEncoded:VARIABLE=VALUE
2220 
2221         The VARIABLE=VALUE part is sent hex-encoded so chracters like '#' with special
2222         meaning in the remote protocol won't break it.
2223     */
2224 
2225     DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s Handling QEnvironmentHexEncoded: \"%s\"",
2226         (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, p);
2227 
2228     p += sizeof ("QEnvironmentHexEncoded:") - 1;
2229 
2230     std::string arg;
2231     const char *c;
2232     c = p;
2233     while (*c != '\0')
2234       {
2235         if (*(c + 1) == '\0')
2236         {
2237             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'QEnvironmentHexEncoded' pkt");
2238         }
2239         char smallbuf[3];
2240         smallbuf[0] = *c;
2241         smallbuf[1] = *(c + 1);
2242         smallbuf[2] = '\0';
2243         errno = 0;
2244         int ch = strtoul (smallbuf, NULL, 16);
2245         if (errno != 0 && ch == 0)
2246           {
2247             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'QEnvironmentHexEncoded' pkt");
2248           }
2249         arg.push_back(ch);
2250         c += 2;
2251       }
2252 
2253     RNBContext& ctx = Context();
2254     if (arg.length() > 0)
2255       ctx.PushEnvironment (arg.c_str());
2256 
2257     return SendPacket ("OK");
2258 }
2259 
2260 
2261 rnb_err_t
2262 RNBRemote::HandlePacket_QLaunchArch (const char *p)
2263 {
2264     p += sizeof ("QLaunchArch:") - 1;
2265     if (DNBSetArchitecture(p))
2266         return SendPacket ("OK");
2267     return SendPacket ("E63");
2268 }
2269 
2270 void
2271 append_hex_value (std::ostream& ostrm, const uint8_t* buf, size_t buf_size, bool swap)
2272 {
2273     int i;
2274     if (swap)
2275     {
2276         for (i = buf_size-1; i >= 0; i--)
2277             ostrm << RAWHEX8(buf[i]);
2278     }
2279     else
2280     {
2281         for (i = 0; i < buf_size; i++)
2282             ostrm << RAWHEX8(buf[i]);
2283     }
2284 }
2285 
2286 
2287 void
2288 register_value_in_hex_fixed_width (std::ostream& ostrm,
2289                                    nub_process_t pid,
2290                                    nub_thread_t tid,
2291                                    const register_map_entry_t* reg,
2292                                    const DNBRegisterValue *reg_value_ptr)
2293 {
2294     if (reg != NULL)
2295     {
2296         DNBRegisterValue reg_value;
2297         if (reg_value_ptr == NULL)
2298         {
2299             if (DNBThreadGetRegisterValueByID (pid, tid, reg->nub_info.set, reg->nub_info.reg, &reg_value))
2300                 reg_value_ptr = &reg_value;
2301         }
2302 
2303         if (reg_value_ptr)
2304         {
2305             append_hex_value (ostrm, reg_value_ptr->value.v_uint8, reg->gdb_size, false);
2306         }
2307         else
2308         {
2309             // If we fail to read a regiser value, check if it has a default
2310             // fail value. If it does, return this instead in case some of
2311             // the registers are not available on the current system.
2312             if (reg->gdb_size > 0)
2313             {
2314                 if (reg->fail_value != NULL)
2315                 {
2316                     append_hex_value (ostrm, reg->fail_value, reg->gdb_size, false);
2317                 }
2318                 else
2319                 {
2320                     std::basic_string<uint8_t> zeros(reg->gdb_size, '\0');
2321                     append_hex_value (ostrm, zeros.data(), zeros.size(), false);
2322                 }
2323             }
2324         }
2325     }
2326 }
2327 
2328 
2329 void
2330 gdb_regnum_with_fixed_width_hex_register_value (std::ostream& ostrm,
2331                                                 nub_process_t pid,
2332                                                 nub_thread_t tid,
2333                                                 const register_map_entry_t* reg,
2334                                                 const DNBRegisterValue *reg_value_ptr)
2335 {
2336     // Output the register number as 'NN:VVVVVVVV;' where NN is a 2 bytes HEX
2337     // gdb register number, and VVVVVVVV is the correct number of hex bytes
2338     // as ASCII for the register value.
2339     if (reg != NULL)
2340     {
2341         ostrm << RAWHEX8(reg->gdb_regnum) << ':';
2342         register_value_in_hex_fixed_width (ostrm, pid, tid, reg, reg_value_ptr);
2343         ostrm << ';';
2344     }
2345 }
2346 
2347 rnb_err_t
2348 RNBRemote::SendStopReplyPacketForThread (nub_thread_t tid)
2349 {
2350     const nub_process_t pid = m_ctx.ProcessID();
2351     if (pid == INVALID_NUB_PROCESS)
2352         return SendPacket("E50");
2353 
2354     struct DNBThreadStopInfo tid_stop_info;
2355 
2356     /* Fill the remaining space in this packet with as many registers
2357      as we can stuff in there.  */
2358 
2359     if (DNBThreadGetStopReason (pid, tid, &tid_stop_info))
2360     {
2361         std::ostringstream ostrm;
2362         // Output the T packet with the thread
2363         ostrm << 'T';
2364         int signum = tid_stop_info.details.signal.signo;
2365         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);
2366 
2367         // Translate any mach exceptions to gdb versions, unless they are
2368         // common exceptions like a breakpoint or a soft signal.
2369         switch (tid_stop_info.details.exception.type)
2370         {
2371             default:                    signum = 0; break;
2372             case EXC_BREAKPOINT:        signum = SIGTRAP; break;
2373             case EXC_BAD_ACCESS:        signum = TARGET_EXC_BAD_ACCESS; break;
2374             case EXC_BAD_INSTRUCTION:   signum = TARGET_EXC_BAD_INSTRUCTION; break;
2375             case EXC_ARITHMETIC:        signum = TARGET_EXC_ARITHMETIC; break;
2376             case EXC_EMULATION:         signum = TARGET_EXC_EMULATION; break;
2377             case EXC_SOFTWARE:
2378                 if (tid_stop_info.details.exception.data_count == 2 &&
2379                     tid_stop_info.details.exception.data[0] == EXC_SOFT_SIGNAL)
2380                     signum = tid_stop_info.details.exception.data[1];
2381                 else
2382                     signum = TARGET_EXC_SOFTWARE;
2383                 break;
2384         }
2385 
2386         ostrm << RAWHEX8(signum & 0xff);
2387 
2388         ostrm << std::hex << "thread:" << tid << ';';
2389 
2390         const char *thread_name = DNBThreadGetName (pid, tid);
2391         if (thread_name && thread_name[0])
2392         {
2393             size_t thread_name_len = strlen(thread_name);
2394 
2395             if (::strcspn (thread_name, "$#+-;:") == thread_name_len)
2396                 ostrm << std::hex << "name:" << thread_name << ';';
2397             else
2398             {
2399                 // the thread name contains special chars, send as hex bytes
2400                 ostrm << std::hex << "hexname:";
2401                 uint8_t *u_thread_name = (uint8_t *)thread_name;
2402                 for (int i = 0; i < thread_name_len; i++)
2403                     ostrm << RAWHEX8(u_thread_name[i]);
2404                 ostrm << ';';
2405             }
2406         }
2407 
2408         thread_identifier_info_data_t thread_ident_info;
2409         if (DNBThreadGetIdentifierInfo (pid, tid, &thread_ident_info))
2410         {
2411             if (thread_ident_info.dispatch_qaddr != 0)
2412                 ostrm << std::hex << "qaddr:" << thread_ident_info.dispatch_qaddr << ';';
2413         }
2414 
2415         // If a 'QListThreadsInStopReply' was sent to enable this feature, we
2416         // will send all thread IDs back in the "threads" key whose value is
2417         // a listc of hex thread IDs separated by commas:
2418         //  "threads:10a,10b,10c;"
2419         // This will save the debugger from having to send a pair of qfThreadInfo
2420         // and qsThreadInfo packets, but it also might take a lot of room in the
2421         // stop reply packet, so it must be enabled only on systems where there
2422         // are no limits on packet lengths.
2423 
2424         if (m_list_threads_in_stop_reply)
2425         {
2426             const nub_size_t numthreads = DNBProcessGetNumThreads (pid);
2427             if (numthreads > 0)
2428             {
2429                 ostrm << std::hex << "threads:";
2430                 for (nub_size_t i = 0; i < numthreads; ++i)
2431                 {
2432                     nub_thread_t th = DNBProcessGetThreadAtIndex (pid, i);
2433                     if (i > 0)
2434                         ostrm << ',';
2435                     ostrm << std::hex << th;
2436                 }
2437                 ostrm << ';';
2438             }
2439         }
2440 
2441         if (g_num_reg_entries == 0)
2442             InitializeRegisters ();
2443 
2444         if (g_reg_entries != NULL)
2445         {
2446             DNBRegisterValue reg_value;
2447             for (uint32_t reg = 0; reg < g_num_reg_entries; reg++)
2448             {
2449                 if (g_reg_entries[reg].expedite)
2450                 {
2451                     if (!DNBThreadGetRegisterValueByID (pid, tid, g_reg_entries[reg].nub_info.set, g_reg_entries[reg].nub_info.reg, &reg_value))
2452                         continue;
2453 
2454                     gdb_regnum_with_fixed_width_hex_register_value (ostrm, pid, tid, &g_reg_entries[reg], &reg_value);
2455                 }
2456             }
2457         }
2458 
2459         if (tid_stop_info.details.exception.type)
2460         {
2461             ostrm << "metype:" << std::hex << tid_stop_info.details.exception.type << ";";
2462             ostrm << "mecount:" << std::hex << tid_stop_info.details.exception.data_count << ";";
2463             for (int i = 0; i < tid_stop_info.details.exception.data_count; ++i)
2464                 ostrm << "medata:" << std::hex << tid_stop_info.details.exception.data[i] << ";";
2465         }
2466         return SendPacket (ostrm.str ());
2467     }
2468     return SendPacket("E51");
2469 }
2470 
2471 /* '?'
2472  The stop reply packet - tell gdb what the status of the inferior is.
2473  Often called the questionmark_packet.  */
2474 
2475 rnb_err_t
2476 RNBRemote::HandlePacket_last_signal (const char *unused)
2477 {
2478     if (!m_ctx.HasValidProcessID())
2479     {
2480         // Inferior is not yet specified/running
2481         return SendPacket ("E02");
2482     }
2483 
2484     nub_process_t pid = m_ctx.ProcessID();
2485     nub_state_t pid_state = DNBProcessGetState (pid);
2486 
2487     switch (pid_state)
2488     {
2489         case eStateAttaching:
2490         case eStateLaunching:
2491         case eStateRunning:
2492         case eStateStepping:
2493         case eStateDetached:
2494             return rnb_success;  // Ignore
2495 
2496         case eStateSuspended:
2497         case eStateStopped:
2498         case eStateCrashed:
2499             {
2500                 nub_thread_t tid = DNBProcessGetCurrentThread (pid);
2501                 // Make sure we set the current thread so g and p packets return
2502                 // the data the gdb will expect.
2503                 SetCurrentThread (tid);
2504 
2505                 SendStopReplyPacketForThread (tid);
2506             }
2507             break;
2508 
2509         case eStateInvalid:
2510         case eStateUnloaded:
2511         case eStateExited:
2512             {
2513                 char pid_exited_packet[16] = "";
2514                 int pid_status = 0;
2515                 // Process exited with exit status
2516                 if (!DNBProcessGetExitStatus(pid, &pid_status))
2517                     pid_status = 0;
2518 
2519                 if (pid_status)
2520                 {
2521                     if (WIFEXITED (pid_status))
2522                         snprintf (pid_exited_packet, sizeof(pid_exited_packet), "W%02x", WEXITSTATUS (pid_status));
2523                     else if (WIFSIGNALED (pid_status))
2524                         snprintf (pid_exited_packet, sizeof(pid_exited_packet), "X%02x", WEXITSTATUS (pid_status));
2525                     else if (WIFSTOPPED (pid_status))
2526                         snprintf (pid_exited_packet, sizeof(pid_exited_packet), "S%02x", WSTOPSIG (pid_status));
2527                 }
2528 
2529                 // If we have an empty exit packet, lets fill one in to be safe.
2530                 if (!pid_exited_packet[0])
2531                 {
2532                     strncpy (pid_exited_packet, "W00", sizeof(pid_exited_packet)-1);
2533                     pid_exited_packet[sizeof(pid_exited_packet)-1] = '\0';
2534                 }
2535 
2536                 return SendPacket (pid_exited_packet);
2537             }
2538             break;
2539     }
2540     return rnb_success;
2541 }
2542 
2543 rnb_err_t
2544 RNBRemote::HandlePacket_M (const char *p)
2545 {
2546     if (p == NULL || p[0] == '\0' || strlen (p) < 3)
2547     {
2548         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Too short M packet");
2549     }
2550 
2551     char *c;
2552     p++;
2553     errno = 0;
2554     nub_addr_t addr = strtoull (p, &c, 16);
2555     if (errno != 0 && addr == 0)
2556     {
2557         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in M packet");
2558     }
2559     if (*c != ',')
2560     {
2561         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in M packet");
2562     }
2563 
2564     /* Advance 'p' to the length part of the packet.  */
2565     p += (c - p) + 1;
2566 
2567     errno = 0;
2568     uint32_t length = strtoul (p, &c, 16);
2569     if (errno != 0 && length == 0)
2570     {
2571         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in M packet");
2572     }
2573     if (length == 0)
2574     {
2575         return SendPacket ("OK");
2576     }
2577 
2578     if (*c != ':')
2579     {
2580         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Missing colon in M packet");
2581     }
2582     /* Advance 'p' to the data part of the packet.  */
2583     p += (c - p) + 1;
2584 
2585     int datalen = strlen (p);
2586     if (datalen & 0x1)
2587     {
2588         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Uneven # of hex chars for data in M packet");
2589     }
2590     if (datalen == 0)
2591     {
2592         return SendPacket ("OK");
2593     }
2594 
2595     uint8_t *buf = (uint8_t *) alloca (datalen / 2);
2596     uint8_t *i = buf;
2597 
2598     while (*p != '\0' && *(p + 1) != '\0')
2599     {
2600         char hexbuf[3];
2601         hexbuf[0] = *p;
2602         hexbuf[1] = *(p + 1);
2603         hexbuf[2] = '\0';
2604         errno = 0;
2605         uint8_t byte = strtoul (hexbuf, NULL, 16);
2606         if (errno != 0 && byte == 0)
2607         {
2608             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid hex byte in M packet");
2609         }
2610         *i++ = byte;
2611         p += 2;
2612     }
2613 
2614     nub_size_t wrote = DNBProcessMemoryWrite (m_ctx.ProcessID(), addr, length, buf);
2615     if (wrote != length)
2616         return SendPacket ("E09");
2617     else
2618         return SendPacket ("OK");
2619 }
2620 
2621 
2622 rnb_err_t
2623 RNBRemote::HandlePacket_m (const char *p)
2624 {
2625     if (p == NULL || p[0] == '\0' || strlen (p) < 3)
2626     {
2627         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Too short m packet");
2628     }
2629 
2630     char *c;
2631     p++;
2632     errno = 0;
2633     nub_addr_t addr = strtoull (p, &c, 16);
2634     if (errno != 0 && addr == 0)
2635     {
2636         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in m packet");
2637     }
2638     if (*c != ',')
2639     {
2640         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in m packet");
2641     }
2642 
2643     /* Advance 'p' to the length part of the packet.  */
2644     p += (c - p) + 1;
2645 
2646     errno = 0;
2647     uint32_t length = strtoul (p, NULL, 16);
2648     if (errno != 0 && length == 0)
2649     {
2650         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in m packet");
2651     }
2652     if (length == 0)
2653     {
2654         return SendPacket ("");
2655     }
2656 
2657     uint8_t buf[length];
2658     int bytes_read = DNBProcessMemoryRead (m_ctx.ProcessID(), addr, length, buf);
2659     if (bytes_read == 0)
2660     {
2661         return SendPacket ("E08");
2662     }
2663 
2664     // "The reply may contain fewer bytes than requested if the server was able
2665     //  to read only part of the region of memory."
2666     length = bytes_read;
2667 
2668     std::ostringstream ostrm;
2669     for (int i = 0; i < length; i++)
2670         ostrm << RAWHEX8(buf[i]);
2671     return SendPacket (ostrm.str ());
2672 }
2673 
2674 rnb_err_t
2675 RNBRemote::HandlePacket_X (const char *p)
2676 {
2677     if (p == NULL || p[0] == '\0' || strlen (p) < 3)
2678     {
2679         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Too short X packet");
2680     }
2681 
2682     char *c;
2683     p++;
2684     errno = 0;
2685     nub_addr_t addr = strtoull (p, &c, 16);
2686     if (errno != 0 && addr == 0)
2687     {
2688         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in X packet");
2689     }
2690     if (*c != ',')
2691     {
2692         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in X packet");
2693     }
2694 
2695     /* Advance 'p' to the length part of the packet.  */
2696     p += (c - p) + 1;
2697 
2698     errno = 0;
2699     int length = strtoul (p, NULL, 16);
2700     if (errno != 0 && length == 0)
2701     {
2702         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in m packet");
2703     }
2704 
2705     // I think gdb sends a zero length write request to test whether this
2706     // packet is accepted.
2707     if (length == 0)
2708     {
2709         return SendPacket ("OK");
2710     }
2711 
2712     std::vector<uint8_t> data = decode_binary_data (c, -1);
2713     std::vector<uint8_t>::const_iterator it;
2714     uint8_t *buf = (uint8_t *) alloca (data.size ());
2715     uint8_t *i = buf;
2716     for (it = data.begin (); it != data.end (); ++it)
2717     {
2718         *i++ = *it;
2719     }
2720 
2721     nub_size_t wrote = DNBProcessMemoryWrite (m_ctx.ProcessID(), addr, data.size(), buf);
2722     if (wrote != data.size ())
2723         return SendPacket ("E08");
2724     return SendPacket ("OK");
2725 }
2726 
2727 /* 'g' -- read registers
2728  Get the contents of the registers for the current thread,
2729  send them to gdb.
2730  Should the setting of the Hg packet determine which thread's registers
2731  are returned?  */
2732 
2733 rnb_err_t
2734 RNBRemote::HandlePacket_g (const char *p)
2735 {
2736     std::ostringstream ostrm;
2737     if (!m_ctx.HasValidProcessID())
2738     {
2739         return SendPacket ("E11");
2740     }
2741 
2742     if (g_num_reg_entries == 0)
2743         InitializeRegisters ();
2744 
2745     nub_process_t pid = m_ctx.ProcessID ();
2746     nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p + 1);
2747     if (tid == INVALID_NUB_THREAD)
2748         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
2749 
2750     if (m_use_native_regs)
2751     {
2752         // Get the register context size first by calling with NULL buffer
2753         nub_size_t reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, NULL, 0);
2754         if (reg_ctx_size)
2755         {
2756             // Now allocate enough space for the entire register context
2757             std::vector<uint8_t> reg_ctx;
2758             reg_ctx.resize(reg_ctx_size);
2759             // Now read the register context
2760             reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, &reg_ctx[0], reg_ctx.size());
2761             if (reg_ctx_size)
2762             {
2763                 append_hex_value (ostrm, reg_ctx.data(), reg_ctx.size(), false);
2764                 return SendPacket (ostrm.str ());
2765             }
2766         }
2767     }
2768 
2769     for (uint32_t reg = 0; reg < g_num_reg_entries; reg++)
2770         register_value_in_hex_fixed_width (ostrm, pid, tid, &g_reg_entries[reg], NULL);
2771 
2772     return SendPacket (ostrm.str ());
2773 }
2774 
2775 /* 'G XXX...' -- write registers
2776  How is the thread for these specified, beyond "the current thread"?
2777  Does gdb actually use the Hg packet to set this?  */
2778 
2779 rnb_err_t
2780 RNBRemote::HandlePacket_G (const char *p)
2781 {
2782     if (!m_ctx.HasValidProcessID())
2783     {
2784         return SendPacket ("E11");
2785     }
2786 
2787     if (g_num_reg_entries == 0)
2788         InitializeRegisters ();
2789 
2790     StringExtractor packet(p);
2791     packet.SetFilePos(1); // Skip the 'G'
2792 
2793     nub_process_t pid = m_ctx.ProcessID();
2794     nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p);
2795     if (tid == INVALID_NUB_THREAD)
2796         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
2797 
2798     if (m_use_native_regs)
2799     {
2800         // Get the register context size first by calling with NULL buffer
2801         nub_size_t reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, NULL, 0);
2802         if (reg_ctx_size)
2803         {
2804             // Now allocate enough space for the entire register context
2805             std::vector<uint8_t> reg_ctx;
2806             reg_ctx.resize(reg_ctx_size);
2807 
2808             const nub_size_t bytes_extracted = packet.GetHexBytes (&reg_ctx[0], reg_ctx.size(), 0xcc);
2809             if (bytes_extracted == reg_ctx.size())
2810             {
2811                 // Now write the register context
2812                 reg_ctx_size = DNBThreadSetRegisterContext(pid, tid, reg_ctx.data(), reg_ctx.size());
2813                 if (reg_ctx_size == reg_ctx.size())
2814                     return SendPacket ("OK");
2815                 else
2816                     return SendPacket ("E55");
2817             }
2818             else
2819             {
2820                 DNBLogError("RNBRemote::HandlePacket_G(%s): extracted %llu of %llu bytes, size mismatch\n", p, (uint64_t)bytes_extracted, (uint64_t)reg_ctx_size);
2821                 return SendPacket ("E64");
2822             }
2823         }
2824         else
2825             return SendPacket ("E65");
2826     }
2827 
2828 
2829     DNBRegisterValue reg_value;
2830     for (uint32_t reg = 0; reg < g_num_reg_entries; reg++)
2831     {
2832         const register_map_entry_t *reg_entry = &g_reg_entries[reg];
2833 
2834         reg_value.info = reg_entry->nub_info;
2835         if (packet.GetHexBytes (reg_value.value.v_sint8, reg_entry->gdb_size, 0xcc) != reg_entry->gdb_size)
2836             break;
2837 
2838         if (reg_entry->fail_value == NULL)
2839         {
2840             if (!DNBThreadSetRegisterValueByID (pid, tid, reg_entry->nub_info.set, reg_entry->nub_info.reg, &reg_value))
2841                 return SendPacket ("E15");
2842         }
2843     }
2844     return SendPacket ("OK");
2845 }
2846 
2847 static bool
2848 RNBRemoteShouldCancelCallback (void *not_used)
2849 {
2850     RNBRemoteSP remoteSP(g_remoteSP);
2851     if (remoteSP.get() != NULL)
2852     {
2853         RNBRemote* remote = remoteSP.get();
2854         if (remote->Comm().IsConnected())
2855             return false;
2856         else
2857             return true;
2858     }
2859     return true;
2860 }
2861 
2862 
2863 // FORMAT: _MXXXXXX,PPP
2864 //      XXXXXX: big endian hex chars
2865 //      PPP: permissions can be any combo of r w x chars
2866 //
2867 // RESPONSE: XXXXXX
2868 //      XXXXXX: hex address of the newly allocated memory
2869 //      EXX: error code
2870 //
2871 // EXAMPLES:
2872 //      _M123000,rw
2873 //      _M123000,rwx
2874 //      _M123000,xw
2875 
2876 rnb_err_t
2877 RNBRemote::HandlePacket_AllocateMemory (const char *p)
2878 {
2879     StringExtractor packet (p);
2880     packet.SetFilePos(2); // Skip the "_M"
2881 
2882     nub_addr_t size = packet.GetHexMaxU64 (StringExtractor::BigEndian, 0);
2883     if (size != 0)
2884     {
2885         if (packet.GetChar() == ',')
2886         {
2887             uint32_t permissions = 0;
2888             char ch;
2889             bool success = true;
2890             while (success && (ch = packet.GetChar()) != '\0')
2891             {
2892                 switch (ch)
2893                 {
2894                 case 'r':   permissions |= eMemoryPermissionsReadable; break;
2895                 case 'w':   permissions |= eMemoryPermissionsWritable; break;
2896                 case 'x':   permissions |= eMemoryPermissionsExecutable; break;
2897                 default:    success = false; break;
2898                 }
2899             }
2900 
2901             if (success)
2902             {
2903                 nub_addr_t addr = DNBProcessMemoryAllocate (m_ctx.ProcessID(), size, permissions);
2904                 if (addr != INVALID_NUB_ADDRESS)
2905                 {
2906                     std::ostringstream ostrm;
2907                     ostrm << RAW_HEXBASE << addr;
2908                     return SendPacket (ostrm.str ());
2909                 }
2910             }
2911         }
2912     }
2913     return SendPacket ("E53");
2914 }
2915 
2916 // FORMAT: _mXXXXXX
2917 //      XXXXXX: address that was previosly allocated
2918 //
2919 // RESPONSE: XXXXXX
2920 //      OK: address was deallocated
2921 //      EXX: error code
2922 //
2923 // EXAMPLES:
2924 //      _m123000
2925 
2926 rnb_err_t
2927 RNBRemote::HandlePacket_DeallocateMemory (const char *p)
2928 {
2929     StringExtractor packet (p);
2930     packet.SetFilePos(2); // Skip the "_m"
2931     nub_addr_t addr = packet.GetHexMaxU64 (StringExtractor::BigEndian, INVALID_NUB_ADDRESS);
2932 
2933     if (addr != INVALID_NUB_ADDRESS)
2934     {
2935         if (DNBProcessMemoryDeallocate (m_ctx.ProcessID(), addr))
2936             return SendPacket ("OK");
2937     }
2938     return SendPacket ("E54");
2939 }
2940 
2941 static bool
2942 GetProcessNameFrom_vAttach (const char *&p, std::string &attach_name)
2943 {
2944     bool return_val = true;
2945     while (*p != '\0')
2946     {
2947         char smallbuf[3];
2948         smallbuf[0] = *p;
2949         smallbuf[1] = *(p + 1);
2950         smallbuf[2] = '\0';
2951 
2952         errno = 0;
2953         int ch = strtoul (smallbuf, NULL, 16);
2954         if (errno != 0 && ch == 0)
2955         {
2956             return_val = false;
2957             break;
2958         }
2959 
2960         attach_name.push_back(ch);
2961         p += 2;
2962     }
2963     return return_val;
2964 }
2965 
2966 /*
2967  vAttach;pid
2968 
2969  Attach to a new process with the specified process ID. pid is a hexadecimal integer
2970  identifying the process. If the stub is currently controlling a process, it is
2971  killed. The attached process is stopped.This packet is only available in extended
2972  mode (see extended mode).
2973 
2974  Reply:
2975  "ENN"                      for an error
2976  "Any Stop Reply Packet"     for success
2977  */
2978 
2979 rnb_err_t
2980 RNBRemote::HandlePacket_v (const char *p)
2981 {
2982     if (strcmp (p, "vCont;c") == 0)
2983     {
2984         // Simple continue
2985         return RNBRemote::HandlePacket_c("c");
2986     }
2987     else if (strcmp (p, "vCont;s") == 0)
2988     {
2989         // Simple step
2990         return RNBRemote::HandlePacket_s("s");
2991     }
2992     else if (strstr (p, "vCont") == p)
2993     {
2994         typedef struct
2995         {
2996             nub_thread_t tid;
2997             char action;
2998             int signal;
2999         } vcont_action_t;
3000 
3001         DNBThreadResumeActions thread_actions;
3002         char *c = (char *)(p += strlen("vCont"));
3003         char *c_end = c + strlen(c);
3004         if (*c == '?')
3005             return SendPacket ("vCont;c;C;s;S");
3006 
3007         while (c < c_end && *c == ';')
3008         {
3009             ++c;    // Skip the semi-colon
3010             DNBThreadResumeAction thread_action;
3011             thread_action.tid = INVALID_NUB_THREAD;
3012             thread_action.state = eStateInvalid;
3013             thread_action.signal = 0;
3014             thread_action.addr = INVALID_NUB_ADDRESS;
3015 
3016             char action = *c++;
3017 
3018             switch (action)
3019             {
3020                 case 'C':
3021                     errno = 0;
3022                     thread_action.signal = strtoul (c, &c, 16);
3023                     if (errno != 0)
3024                         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in vCont packet");
3025                     // Fall through to next case...
3026 
3027                 case 'c':
3028                     // Continue
3029                     thread_action.state = eStateRunning;
3030                     break;
3031 
3032                 case 'S':
3033                     errno = 0;
3034                     thread_action.signal = strtoul (c, &c, 16);
3035                     if (errno != 0)
3036                         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in vCont packet");
3037                     // Fall through to next case...
3038 
3039                 case 's':
3040                     // Step
3041                     thread_action.state = eStateStepping;
3042                     break;
3043 
3044                 default:
3045                     HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Unsupported action in vCont packet");
3046                     break;
3047             }
3048             if (*c == ':')
3049             {
3050                 errno = 0;
3051                 thread_action.tid = strtoul (++c, &c, 16);
3052                 if (errno != 0)
3053                     return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse thread number in vCont packet");
3054             }
3055 
3056             thread_actions.Append (thread_action);
3057         }
3058 
3059         // If a default action for all other threads wasn't mentioned
3060         // then we should stop the threads
3061         thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0);
3062         DNBProcessResume(m_ctx.ProcessID(), thread_actions.GetFirst (), thread_actions.GetSize());
3063         return rnb_success;
3064     }
3065     else if (strstr (p, "vAttach") == p)
3066     {
3067         nub_process_t attach_pid = INVALID_NUB_PROCESS;
3068         char err_str[1024]={'\0'};
3069 
3070         if (strstr (p, "vAttachWait;") == p)
3071         {
3072             p += strlen("vAttachWait;");
3073             std::string attach_name;
3074             if (!GetProcessNameFrom_vAttach(p, attach_name))
3075             {
3076                 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachWait' pkt");
3077             }
3078             const bool ignore_existing = true;
3079             attach_pid = DNBProcessAttachWait(attach_name.c_str (), m_ctx.LaunchFlavor(), ignore_existing, NULL, 1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback);
3080 
3081         }
3082         else if (strstr (p, "vAttachOrWait;") == p)
3083         {
3084             p += strlen("vAttachOrWait;");
3085             std::string attach_name;
3086             if (!GetProcessNameFrom_vAttach(p, attach_name))
3087             {
3088                 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachOrWait' pkt");
3089             }
3090             const bool ignore_existing = false;
3091             attach_pid = DNBProcessAttachWait(attach_name.c_str (), m_ctx.LaunchFlavor(), ignore_existing, NULL, 1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback);
3092         }
3093         else if (strstr (p, "vAttachName;") == p)
3094         {
3095             p += strlen("vAttachName;");
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 'vAttachName' pkt");
3100             }
3101 
3102             attach_pid = DNBProcessAttachByName (attach_name.c_str(), NULL, err_str, sizeof(err_str));
3103 
3104         }
3105         else if (strstr (p, "vAttach;") == p)
3106         {
3107             p += strlen("vAttach;");
3108             char *end = NULL;
3109             attach_pid = strtoul (p, &end, 16);    // PID will be in hex, so use base 16 to decode
3110             if (p != end && *end == '\0')
3111             {
3112                 // Wait at most 30 second for attach
3113                 struct timespec attach_timeout_abstime;
3114                 DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, 30, 0);
3115                 attach_pid = DNBProcessAttach(attach_pid, &attach_timeout_abstime, err_str, sizeof(err_str));
3116             }
3117         }
3118         else
3119         {
3120             return HandlePacket_UNIMPLEMENTED(p);
3121         }
3122 
3123 
3124         if (attach_pid != INVALID_NUB_PROCESS)
3125         {
3126             if (m_ctx.ProcessID() != attach_pid)
3127                 m_ctx.SetProcessID(attach_pid);
3128             // Send a stop reply packet to indicate we successfully attached!
3129             NotifyThatProcessStopped ();
3130             return rnb_success;
3131         }
3132         else
3133         {
3134             m_ctx.LaunchStatus().SetError(-1, DNBError::Generic);
3135             if (err_str[0])
3136                 m_ctx.LaunchStatus().SetErrorString(err_str);
3137             else
3138                 m_ctx.LaunchStatus().SetErrorString("attach failed");
3139             return SendPacket ("E01");  // E01 is our magic error value for attach failed.
3140         }
3141     }
3142 
3143     // All other failures come through here
3144     return HandlePacket_UNIMPLEMENTED(p);
3145 }
3146 
3147 /* 'T XX' -- status of thread
3148  Check if the specified thread is alive.
3149  The thread number is in hex?  */
3150 
3151 rnb_err_t
3152 RNBRemote::HandlePacket_T (const char *p)
3153 {
3154     p++;
3155     if (p == NULL || *p == '\0')
3156     {
3157         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in T packet");
3158     }
3159     if (!m_ctx.HasValidProcessID())
3160     {
3161         return SendPacket ("E15");
3162     }
3163     errno = 0;
3164     nub_thread_t tid = strtoul (p, NULL, 16);
3165     if (errno != 0 && tid == 0)
3166     {
3167         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse thread number in T packet");
3168     }
3169 
3170     nub_state_t state = DNBThreadGetState (m_ctx.ProcessID(), tid);
3171     if (state == eStateInvalid || state == eStateExited || state == eStateCrashed)
3172     {
3173         return SendPacket ("E16");
3174     }
3175 
3176     return SendPacket ("OK");
3177 }
3178 
3179 
3180 rnb_err_t
3181 RNBRemote::HandlePacket_z (const char *p)
3182 {
3183     if (p == NULL || *p == '\0')
3184         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in z packet");
3185 
3186     if (!m_ctx.HasValidProcessID())
3187         return SendPacket ("E15");
3188 
3189     char packet_cmd = *p++;
3190     char break_type = *p++;
3191 
3192     if (*p++ != ',')
3193         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma separator missing in z packet");
3194 
3195     char *c = NULL;
3196     nub_process_t pid = m_ctx.ProcessID();
3197     errno = 0;
3198     nub_addr_t addr = strtoull (p, &c, 16);
3199     if (errno != 0 && addr == 0)
3200         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in z packet");
3201     p = c;
3202     if (*p++ != ',')
3203         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma separator missing in z packet");
3204 
3205     errno = 0;
3206     uint32_t byte_size = strtoul (p, &c, 16);
3207     if (errno != 0 && byte_size == 0)
3208         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in z packet");
3209 
3210     if (packet_cmd == 'Z')
3211     {
3212         // set
3213         switch (break_type)
3214         {
3215             case '0':   // set software breakpoint
3216             case '1':   // set hardware breakpoint
3217             {
3218                 // gdb can send multiple Z packets for the same address and
3219                 // these calls must be ref counted.
3220                 bool hardware = (break_type == '1');
3221 
3222                 // Check if we currently have a breakpoint already set at this address
3223                 BreakpointMapIter pos = m_breakpoints.find(addr);
3224                 if (pos != m_breakpoints.end())
3225                 {
3226                     // We do already have a breakpoint at this address, increment
3227                     // its reference count and return OK
3228                     pos->second.Retain();
3229                     return SendPacket ("OK");
3230                 }
3231                 else
3232                 {
3233                     // We do NOT already have a breakpoint at this address, So lets
3234                     // create one.
3235                     nub_break_t break_id = DNBBreakpointSet (pid, addr, byte_size, hardware);
3236                     if (NUB_BREAK_ID_IS_VALID(break_id))
3237                     {
3238                         // We successfully created a breakpoint, now lets full out
3239                         // a ref count structure with the breakID and add it to our
3240                         // map.
3241                         Breakpoint rnbBreakpoint(break_id);
3242                         m_breakpoints[addr] = rnbBreakpoint;
3243                         return SendPacket ("OK");
3244                     }
3245                     else
3246                     {
3247                         // We failed to set the software breakpoint
3248                         return SendPacket ("E09");
3249                     }
3250                 }
3251             }
3252                 break;
3253 
3254             case '2':   // set write watchpoint
3255             case '3':   // set read watchpoint
3256             case '4':   // set access watchpoint
3257             {
3258                 bool hardware = true;
3259                 uint32_t watch_flags = 0;
3260                 if (break_type == '2')
3261                     watch_flags = WATCH_TYPE_WRITE;
3262                 else if (break_type == '3')
3263                     watch_flags = WATCH_TYPE_READ;
3264                 else
3265                     watch_flags = WATCH_TYPE_READ | WATCH_TYPE_WRITE;
3266 
3267                 // Check if we currently have a watchpoint already set at this address
3268                 BreakpointMapIter pos = m_watchpoints.find(addr);
3269                 if (pos != m_watchpoints.end())
3270                 {
3271                     // We do already have a watchpoint at this address, increment
3272                     // its reference count and return OK
3273                     pos->second.Retain();
3274                     return SendPacket ("OK");
3275                 }
3276                 else
3277                 {
3278                     // We do NOT already have a watchpoint at this address, So lets
3279                     // create one.
3280                     nub_watch_t watch_id = DNBWatchpointSet (pid, addr, byte_size, watch_flags, hardware);
3281                     if (NUB_WATCH_ID_IS_VALID(watch_id))
3282                     {
3283                         // We successfully created a watchpoint, now lets full out
3284                         // a ref count structure with the watch_id and add it to our
3285                         // map.
3286                         Breakpoint rnbWatchpoint(watch_id);
3287                         m_watchpoints[addr] = rnbWatchpoint;
3288                         return SendPacket ("OK");
3289                     }
3290                     else
3291                     {
3292                         // We failed to set the watchpoint
3293                         return SendPacket ("E09");
3294                     }
3295                 }
3296             }
3297                 break;
3298 
3299             default:
3300                 break;
3301         }
3302     }
3303     else if (packet_cmd == 'z')
3304     {
3305         // remove
3306         switch (break_type)
3307         {
3308             case '0':   // remove software breakpoint
3309             case '1':   // remove hardware breakpoint
3310             {
3311                 // gdb can send multiple z packets for the same address and
3312                 // these calls must be ref counted.
3313                 BreakpointMapIter pos = m_breakpoints.find(addr);
3314                 if (pos != m_breakpoints.end())
3315                 {
3316                     // We currently have a breakpoint at address ADDR. Decrement
3317                     // its reference count, and it that count is now zero we
3318                     // can clear the breakpoint.
3319                     pos->second.Release();
3320                     if (pos->second.RefCount() == 0)
3321                     {
3322                         if (DNBBreakpointClear (pid, pos->second.BreakID()))
3323                         {
3324                             m_breakpoints.erase(pos);
3325                             return SendPacket ("OK");
3326                         }
3327                         else
3328                         {
3329                             return SendPacket ("E08");
3330                         }
3331                     }
3332                     else
3333                     {
3334                         // We still have references to this breakpoint don't
3335                         // delete it, just decrementing the reference count
3336                         // is enough.
3337                         return SendPacket ("OK");
3338                     }
3339                 }
3340                 else
3341                 {
3342                     // We don't know about any breakpoints at this address
3343                     return SendPacket ("E08");
3344                 }
3345             }
3346                 break;
3347 
3348             case '2':   // remove write watchpoint
3349             case '3':   // remove read watchpoint
3350             case '4':   // remove access watchpoint
3351             {
3352                 // gdb can send multiple z packets for the same address and
3353                 // these calls must be ref counted.
3354                 BreakpointMapIter pos = m_watchpoints.find(addr);
3355                 if (pos != m_watchpoints.end())
3356                 {
3357                     // We currently have a watchpoint at address ADDR. Decrement
3358                     // its reference count, and it that count is now zero we
3359                     // can clear the watchpoint.
3360                     pos->second.Release();
3361                     if (pos->second.RefCount() == 0)
3362                     {
3363                         if (DNBWatchpointClear (pid, pos->second.BreakID()))
3364                         {
3365                             m_watchpoints.erase(pos);
3366                             return SendPacket ("OK");
3367                         }
3368                         else
3369                         {
3370                             return SendPacket ("E08");
3371                         }
3372                     }
3373                     else
3374                     {
3375                         // We still have references to this watchpoint don't
3376                         // delete it, just decrementing the reference count
3377                         // is enough.
3378                         return SendPacket ("OK");
3379                     }
3380                 }
3381                 else
3382                 {
3383                     // We don't know about any watchpoints at this address
3384                     return SendPacket ("E08");
3385                 }
3386             }
3387                 break;
3388 
3389             default:
3390                 break;
3391         }
3392     }
3393     return HandlePacket_UNIMPLEMENTED(p);
3394 }
3395 
3396 // Extract the thread number from the thread suffix that might be appended to
3397 // thread specific packets. This will only be enabled if m_thread_suffix_supported
3398 // is true.
3399 nub_thread_t
3400 RNBRemote::ExtractThreadIDFromThreadSuffix (const char *p)
3401 {
3402     if (m_thread_suffix_supported)
3403     {
3404         nub_thread_t tid = INVALID_NUB_THREAD;
3405         if (p)
3406         {
3407             const char *tid_cstr = strstr (p, "thread:");
3408             if (tid_cstr)
3409             {
3410                 tid_cstr += strlen ("thread:");
3411                 tid = strtoul(tid_cstr, NULL, 16);
3412             }
3413         }
3414         return tid;
3415     }
3416     return GetCurrentThread();
3417 
3418 }
3419 
3420 /* 'p XX'
3421  print the contents of register X */
3422 
3423 rnb_err_t
3424 RNBRemote::HandlePacket_p (const char *p)
3425 {
3426     if (g_num_reg_entries == 0)
3427         InitializeRegisters ();
3428 
3429     if (p == NULL || *p == '\0')
3430     {
3431         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
3432     }
3433     if (!m_ctx.HasValidProcessID())
3434     {
3435         return SendPacket ("E15");
3436     }
3437     nub_process_t pid = m_ctx.ProcessID();
3438     errno = 0;
3439     char *tid_cstr = NULL;
3440     uint32_t reg = strtoul (p + 1, &tid_cstr, 16);
3441     if (errno != 0 && reg == 0)
3442     {
3443         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse register number in p packet");
3444     }
3445 
3446     nub_thread_t tid = ExtractThreadIDFromThreadSuffix (tid_cstr);
3447     if (tid == INVALID_NUB_THREAD)
3448         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
3449 
3450     const register_map_entry_t *reg_entry;
3451 
3452     if (reg < g_num_reg_entries)
3453         reg_entry = &g_reg_entries[reg];
3454     else
3455         reg_entry = NULL;
3456 
3457     std::ostringstream ostrm;
3458     if (reg_entry == NULL)
3459     {
3460         DNBLogError("RNBRemote::HandlePacket_p(%s): unknown register number %u requested\n", p, reg);
3461         ostrm << "00000000";
3462     }
3463     else if (reg_entry->nub_info.reg == -1)
3464     {
3465         if (reg_entry->gdb_size > 0)
3466         {
3467             if (reg_entry->fail_value != NULL)
3468             {
3469                 append_hex_value(ostrm, reg_entry->fail_value, reg_entry->gdb_size, false);
3470             }
3471             else
3472             {
3473                 std::basic_string<uint8_t> zeros(reg_entry->gdb_size, '\0');
3474                 append_hex_value(ostrm, zeros.data(), zeros.size(), false);
3475             }
3476         }
3477     }
3478     else
3479     {
3480         register_value_in_hex_fixed_width (ostrm, pid, tid, reg_entry, NULL);
3481     }
3482     return SendPacket (ostrm.str());
3483 }
3484 
3485 /* 'Pnn=rrrrr'
3486  Set register number n to value r.
3487  n and r are hex strings.  */
3488 
3489 rnb_err_t
3490 RNBRemote::HandlePacket_P (const char *p)
3491 {
3492     if (g_num_reg_entries == 0)
3493         InitializeRegisters ();
3494 
3495     if (p == NULL || *p == '\0')
3496     {
3497         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Empty P packet");
3498     }
3499     if (!m_ctx.HasValidProcessID())
3500     {
3501         return SendPacket ("E28");
3502     }
3503 
3504     nub_process_t pid = m_ctx.ProcessID();
3505 
3506     StringExtractor packet (p);
3507 
3508     const char cmd_char = packet.GetChar();
3509     // Register ID is always in big endian
3510     const uint32_t reg = packet.GetHexMaxU32 (false, UINT32_MAX);
3511     const char equal_char = packet.GetChar();
3512 
3513     if (cmd_char != 'P')
3514         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Improperly formed P packet");
3515 
3516     if (reg == UINT32_MAX)
3517         return SendPacket ("E29");
3518 
3519     if (equal_char != '=')
3520         return SendPacket ("E30");
3521 
3522     const register_map_entry_t *reg_entry;
3523 
3524     if (reg >= g_num_reg_entries)
3525         return SendPacket("E47");
3526 
3527     reg_entry = &g_reg_entries[reg];
3528 
3529     if (reg_entry->nub_info.set == -1 && reg_entry->nub_info.reg == -1)
3530     {
3531         DNBLogError("RNBRemote::HandlePacket_P(%s): unknown register number %u requested\n", p, reg);
3532         return SendPacket("E48");
3533     }
3534 
3535     DNBRegisterValue reg_value;
3536     reg_value.info = reg_entry->nub_info;
3537     packet.GetHexBytes (reg_value.value.v_sint8, reg_entry->gdb_size, 0xcc);
3538 
3539     nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p);
3540     if (tid == INVALID_NUB_THREAD)
3541         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
3542 
3543     if (!DNBThreadSetRegisterValueByID (pid, tid, reg_entry->nub_info.set, reg_entry->nub_info.reg, &reg_value))
3544     {
3545         return SendPacket ("E32");
3546     }
3547     return SendPacket ("OK");
3548 }
3549 
3550 /* 'c [addr]'
3551  Continue, optionally from a specified address. */
3552 
3553 rnb_err_t
3554 RNBRemote::HandlePacket_c (const char *p)
3555 {
3556     const nub_process_t pid = m_ctx.ProcessID();
3557 
3558     if (pid == INVALID_NUB_PROCESS)
3559         return SendPacket ("E23");
3560 
3561     DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateRunning, 0, INVALID_NUB_ADDRESS };
3562 
3563     if (*(p + 1) != '\0')
3564     {
3565         action.tid = GetContinueThread();
3566         errno = 0;
3567         action.addr = strtoull (p + 1, NULL, 16);
3568         if (errno != 0 && action.addr == 0)
3569             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in c packet");
3570     }
3571 
3572     DNBThreadResumeActions thread_actions;
3573     thread_actions.Append(action);
3574     thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, 0);
3575     if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize()))
3576         return SendPacket ("E25");
3577     // Don't send an "OK" packet; response is the stopped/exited message.
3578     return rnb_success;
3579 }
3580 
3581 rnb_err_t
3582 RNBRemote::HandlePacket_MemoryRegionInfo (const char *p)
3583 {
3584     /* This packet will find memory attributes (e.g. readable, writable, executable, stack, jitted code)
3585        for the memory region containing a given address and return that information.
3586 
3587        Users of this packet must be prepared for three results:
3588 
3589            Region information is returned
3590            Region information is unavailable for this address because the address is in unmapped memory
3591            Region lookup cannot be performed on this platform or process is not yet launched
3592            This packet isn't implemented
3593 
3594        Examples of use:
3595           qMemoryRegionInfo:3a55140
3596           start:3a50000,size:100000,permissions:rwx
3597 
3598           qMemoryRegionInfo:0
3599           error:address in unmapped region
3600 
3601           qMemoryRegionInfo:3a551140   (on a different platform)
3602           error:region lookup cannot be performed
3603 
3604           qMemoryRegionInfo
3605           OK                   // this packet is implemented by the remote nub
3606     */
3607 
3608     p += sizeof ("qMemoryRegionInfo") - 1;
3609     if (*p == '\0')
3610        return SendPacket ("OK");
3611     if (*p++ != ':')
3612        return SendPacket ("E67");
3613     if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X'))
3614        p += 2;
3615 
3616     errno = 0;
3617     uint64_t address = strtoul (p, NULL, 16);
3618     if (errno != 0 && address == 0)
3619     {
3620         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in qMemoryRegionInfo packet");
3621     }
3622 
3623     DNBRegionInfo region_info = { 0, 0, 0 };
3624     DNBProcessMemoryRegionInfo (m_ctx.ProcessID(), address, &region_info);
3625     std::ostringstream ostrm;
3626 
3627         // start:3a50000,size:100000,permissions:rwx
3628     ostrm << "start:" << std::hex << region_info.addr << ';';
3629 
3630     if (region_info.size > 0)
3631         ostrm << "size:"  << std::hex << region_info.size << ';';
3632 
3633     if (region_info.permissions)
3634     {
3635         ostrm << "permissions:";
3636 
3637         if (region_info.permissions & eMemoryPermissionsReadable)
3638             ostrm << 'r';
3639         if (region_info.permissions & eMemoryPermissionsWritable)
3640             ostrm << 'w';
3641         if (region_info.permissions & eMemoryPermissionsExecutable)
3642             ostrm << 'x';
3643         ostrm << ';';
3644     }
3645     return SendPacket (ostrm.str());
3646 }
3647 
3648 rnb_err_t
3649 RNBRemote::HandlePacket_GetProfileData (const char *p)
3650 {
3651     nub_process_t pid = m_ctx.ProcessID();
3652     if (pid == INVALID_NUB_PROCESS)
3653         return SendPacket ("OK");
3654 
3655     std::string data = DNBProcessGetProfileData(pid);
3656     if (!data.empty())
3657     {
3658         return SendPacket (data.c_str());
3659     }
3660     else
3661     {
3662         return SendPacket ("OK");
3663     }
3664 }
3665 
3666 
3667 // QSetEnableAsyncProfiling;enable:[0|1]:interval_usec:XXXXXX;
3668 rnb_err_t
3669 RNBRemote::HandlePacket_SetEnableAsyncProfiling (const char *p)
3670 {
3671     nub_process_t pid = m_ctx.ProcessID();
3672     if (pid == INVALID_NUB_PROCESS)
3673         return SendPacket ("");
3674 
3675     StringExtractor packet(p += sizeof ("QSetEnableAsyncProfiling:") - 1);
3676     bool enable = false;
3677     uint64_t interval_usec = 0;
3678     std::string name;
3679     std::string value;
3680     while (packet.GetNameColonValue(name, value))
3681     {
3682         if (name.compare ("enable") == 0)
3683         {
3684             enable  = strtoul(value.c_str(), NULL, 10) > 0;
3685         }
3686         else if (name.compare ("interval_usec") == 0)
3687         {
3688             interval_usec  = strtoul(value.c_str(), NULL, 10);
3689         }
3690     }
3691 
3692     if (interval_usec == 0)
3693     {
3694         enable = 0;
3695     }
3696     DNBProcessSetEnableAsyncProfiling(pid, enable, interval_usec);
3697     return SendPacket ("OK");
3698 }
3699 
3700 rnb_err_t
3701 RNBRemote::HandlePacket_WatchpointSupportInfo (const char *p)
3702 {
3703     /* This packet simply returns the number of supported hardware watchpoints.
3704 
3705        Examples of use:
3706           qWatchpointSupportInfo:
3707           num:4
3708 
3709           qWatchpointSupportInfo
3710           OK                   // this packet is implemented by the remote nub
3711     */
3712 
3713     p += sizeof ("qWatchpointSupportInfo") - 1;
3714     if (*p == '\0')
3715        return SendPacket ("OK");
3716     if (*p++ != ':')
3717        return SendPacket ("E67");
3718 
3719     errno = 0;
3720     uint32_t num = DNBWatchpointGetNumSupportedHWP (m_ctx.ProcessID());
3721     std::ostringstream ostrm;
3722 
3723     // size:4
3724     ostrm << "num:" << std::dec << num << ';';
3725     return SendPacket (ostrm.str());
3726 }
3727 
3728 /* 'C sig [;addr]'
3729  Resume with signal sig, optionally at address addr.  */
3730 
3731 rnb_err_t
3732 RNBRemote::HandlePacket_C (const char *p)
3733 {
3734     const nub_process_t pid = m_ctx.ProcessID();
3735 
3736     if (pid == INVALID_NUB_PROCESS)
3737         return SendPacket ("E36");
3738 
3739     DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateRunning, 0, INVALID_NUB_ADDRESS };
3740     int process_signo = -1;
3741     if (*(p + 1) != '\0')
3742     {
3743         action.tid = GetContinueThread();
3744         char *end = NULL;
3745         errno = 0;
3746         process_signo = strtoul (p + 1, &end, 16);
3747         if (errno != 0)
3748             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in C packet");
3749         else if (*end == ';')
3750         {
3751             errno = 0;
3752             action.addr = strtoull (end + 1, NULL, 16);
3753             if (errno != 0 && action.addr == 0)
3754                 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in C packet");
3755         }
3756     }
3757 
3758     DNBThreadResumeActions thread_actions;
3759     thread_actions.Append (action);
3760     thread_actions.SetDefaultThreadActionIfNeeded (eStateRunning, action.signal);
3761     if (!DNBProcessSignal(pid, process_signo))
3762         return SendPacket ("E52");
3763     if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize()))
3764         return SendPacket ("E38");
3765     /* Don't send an "OK" packet; response is the stopped/exited message.  */
3766     return rnb_success;
3767 }
3768 
3769 //----------------------------------------------------------------------
3770 // 'D' packet
3771 // Detach from gdb.
3772 //----------------------------------------------------------------------
3773 rnb_err_t
3774 RNBRemote::HandlePacket_D (const char *p)
3775 {
3776     SendPacket ("OK");
3777     if (m_ctx.HasValidProcessID())
3778         DNBProcessDetach(m_ctx.ProcessID());
3779     return rnb_success;
3780 }
3781 
3782 /* 'k'
3783  Kill the inferior process.  */
3784 
3785 rnb_err_t
3786 RNBRemote::HandlePacket_k (const char *p)
3787 {
3788     // No response to should be sent to the kill packet
3789     if (m_ctx.HasValidProcessID())
3790         DNBProcessKill (m_ctx.ProcessID());
3791     SendPacket ("W09");
3792     return rnb_success;
3793 }
3794 
3795 rnb_err_t
3796 RNBRemote::HandlePacket_stop_process (const char *p)
3797 {
3798 //#define TEST_EXIT_ON_INTERRUPT // This should only be uncommented to test exiting on interrupt
3799 #if defined(TEST_EXIT_ON_INTERRUPT)
3800     rnb_err_t err = HandlePacket_k (p);
3801     m_comm.Disconnect(true);
3802     return err;
3803 #else
3804     DNBProcessSignal (m_ctx.ProcessID(), SIGSTOP);
3805     //DNBProcessSignal (m_ctx.ProcessID(), SIGINT);
3806     // Do not send any response packet! Wait for the stop reply packet to naturally happen
3807     return rnb_success;
3808 #endif
3809 }
3810 
3811 /* 's'
3812  Step the inferior process.  */
3813 
3814 rnb_err_t
3815 RNBRemote::HandlePacket_s (const char *p)
3816 {
3817     const nub_process_t pid = m_ctx.ProcessID();
3818     if (pid == INVALID_NUB_PROCESS)
3819         return SendPacket ("E32");
3820 
3821     // Hardware supported stepping not supported on arm
3822     nub_thread_t tid = GetContinueThread ();
3823     if (tid == 0 || tid == -1)
3824         tid = GetCurrentThread();
3825 
3826     if (tid == INVALID_NUB_THREAD)
3827         return SendPacket ("E33");
3828 
3829     DNBThreadResumeActions thread_actions;
3830     thread_actions.AppendAction(tid, eStateStepping);
3831 
3832     // Make all other threads stop when we are stepping
3833     thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0);
3834     if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize()))
3835         return SendPacket ("E49");
3836     // Don't send an "OK" packet; response is the stopped/exited message.
3837     return rnb_success;
3838 }
3839 
3840 /* 'S sig [;addr]'
3841  Step with signal sig, optionally at address addr.  */
3842 
3843 rnb_err_t
3844 RNBRemote::HandlePacket_S (const char *p)
3845 {
3846     const nub_process_t pid = m_ctx.ProcessID();
3847     if (pid == INVALID_NUB_PROCESS)
3848         return SendPacket ("E36");
3849 
3850     DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateStepping, 0, INVALID_NUB_ADDRESS };
3851 
3852     if (*(p + 1) != '\0')
3853     {
3854         char *end = NULL;
3855         errno = 0;
3856         action.signal = strtoul (p + 1, &end, 16);
3857         if (errno != 0)
3858             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in S packet");
3859         else if (*end == ';')
3860         {
3861             errno = 0;
3862             action.addr = strtoull (end + 1, NULL, 16);
3863             if (errno != 0 && action.addr == 0)
3864             {
3865                 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in S packet");
3866             }
3867         }
3868     }
3869 
3870     action.tid = GetContinueThread ();
3871     if (action.tid == 0 || action.tid == -1)
3872         return SendPacket ("E40");
3873 
3874     nub_state_t tstate = DNBThreadGetState (pid, action.tid);
3875     if (tstate == eStateInvalid || tstate == eStateExited)
3876         return SendPacket ("E37");
3877 
3878 
3879     DNBThreadResumeActions thread_actions;
3880     thread_actions.Append (action);
3881 
3882     // Make all other threads stop when we are stepping
3883     thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
3884     if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize()))
3885         return SendPacket ("E39");
3886 
3887     // Don't send an "OK" packet; response is the stopped/exited message.
3888     return rnb_success;
3889 }
3890 
3891 rnb_err_t
3892 RNBRemote::HandlePacket_qHostInfo (const char *p)
3893 {
3894     std::ostringstream strm;
3895 
3896     uint32_t cputype, is_64_bit_capable;
3897     size_t len = sizeof(cputype);
3898     bool promoted_to_64 = false;
3899     if  (::sysctlbyname("hw.cputype", &cputype, &len, NULL, 0) == 0)
3900     {
3901         len = sizeof (is_64_bit_capable);
3902         if  (::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0) == 0)
3903         {
3904             if (is_64_bit_capable && ((cputype & CPU_ARCH_ABI64) == 0))
3905             {
3906                 promoted_to_64 = true;
3907                 cputype |= CPU_ARCH_ABI64;
3908             }
3909         }
3910 
3911         strm << "cputype:" << std::dec << cputype << ';';
3912     }
3913 
3914     uint32_t cpusubtype;
3915     len = sizeof(cpusubtype);
3916     if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0)
3917     {
3918         if (promoted_to_64 &&
3919             cputype == CPU_TYPE_X86_64 &&
3920             cpusubtype == CPU_SUBTYPE_486)
3921             cpusubtype = CPU_SUBTYPE_X86_64_ALL;
3922 
3923         strm << "cpusubtype:" << std::dec << cpusubtype << ';';
3924     }
3925 
3926     // The OS in the triple should be "ios" or "macosx" which doesn't match our
3927     // "Darwin" which gets returned from "kern.ostype", so we need to hardcode
3928     // this for now.
3929     if (cputype == CPU_TYPE_ARM)
3930     {
3931         strm << "ostype:ios;";
3932         // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes.
3933         strm << "watchpoint_exceptions_received:before;";
3934     }
3935     else
3936     {
3937         strm << "ostype:macosx;";
3938         strm << "watchpoint_exceptions_received:after;";
3939     }
3940 //    char ostype[64];
3941 //    len = sizeof(ostype);
3942 //    if (::sysctlbyname("kern.ostype", &ostype, &len, NULL, 0) == 0)
3943 //    {
3944 //        len = strlen(ostype);
3945 //        std::transform (ostype, ostype + len, ostype, tolower);
3946 //        strm << "ostype:" << std::dec << ostype << ';';
3947 //    }
3948 
3949     strm << "vendor:apple;";
3950 
3951 #if defined (__LITTLE_ENDIAN__)
3952     strm << "endian:little;";
3953 #elif defined (__BIG_ENDIAN__)
3954     strm << "endian:big;";
3955 #elif defined (__PDP_ENDIAN__)
3956     strm << "endian:pdp;";
3957 #endif
3958 
3959     if (promoted_to_64)
3960         strm << "ptrsize:8;";
3961     else
3962         strm << "ptrsize:" << std::dec << sizeof(void *) << ';';
3963     return SendPacket (strm.str());
3964 }
3965 
3966 
3967 // Note that all numeric values returned by qProcessInfo are hex encoded,
3968 // including the pid and the cpu type.
3969 
3970 rnb_err_t
3971 RNBRemote::HandlePacket_qProcessInfo (const char *p)
3972 {
3973     nub_process_t pid;
3974     std::ostringstream rep;
3975 
3976     // If we haven't run the process yet, return an error.
3977     if (!m_ctx.HasValidProcessID())
3978         return SendPacket ("E68");
3979 
3980     pid = m_ctx.ProcessID();
3981 
3982     rep << "pid:" << std::hex << pid << ";";
3983 
3984     int procpid_mib[4];
3985     procpid_mib[0] = CTL_KERN;
3986     procpid_mib[1] = KERN_PROC;
3987     procpid_mib[2] = KERN_PROC_PID;
3988     procpid_mib[3] = pid;
3989     struct kinfo_proc proc_kinfo;
3990     size_t proc_kinfo_size = sizeof(struct kinfo_proc);
3991 
3992     if (::sysctl (procpid_mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0)
3993     {
3994         if (proc_kinfo_size > 0)
3995         {
3996             rep << "parent-pid:" << std::hex << proc_kinfo.kp_eproc.e_ppid << ";";
3997             rep << "real-uid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_ruid << ";";
3998             rep << "real-gid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_rgid << ";";
3999             rep << "effective-uid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_uid << ";";
4000             if (proc_kinfo.kp_eproc.e_ucred.cr_ngroups > 0)
4001                 rep << "effective-gid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_groups[0] << ";";
4002         }
4003     }
4004 
4005     int cputype_mib[CTL_MAXNAME]={0,};
4006     size_t cputype_mib_len = CTL_MAXNAME;
4007     cpu_type_t cputype = -1;
4008     if (::sysctlnametomib("sysctl.proc_cputype", cputype_mib, &cputype_mib_len) == 0)
4009     {
4010         cputype_mib[cputype_mib_len] = pid;
4011         cputype_mib_len++;
4012         size_t len = sizeof(cputype);
4013         if (::sysctl (cputype_mib, cputype_mib_len, &cputype, &len, 0, 0) == 0)
4014         {
4015             rep << "cputype:" << std::hex << cputype << ";";
4016         }
4017     }
4018 
4019     uint32_t cpusubtype;
4020     size_t cpusubtype_len = sizeof(cpusubtype);
4021     if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &cpusubtype_len, NULL, 0) == 0)
4022     {
4023         if (cputype == CPU_TYPE_X86_64 && cpusubtype == CPU_SUBTYPE_486)
4024         {
4025             cpusubtype = CPU_SUBTYPE_X86_64_ALL;
4026         }
4027 
4028         rep << "cpusubtype:" << std::hex << cpusubtype << ';';
4029     }
4030 
4031     // The OS in the triple should be "ios" or "macosx" which doesn't match our
4032     // "Darwin" which gets returned from "kern.ostype", so we need to hardcode
4033     // this for now.
4034     if (cputype == CPU_TYPE_ARM)
4035         rep << "ostype:ios;";
4036     else
4037         rep << "ostype:macosx;";
4038 
4039     rep << "vendor:apple;";
4040 
4041 #if defined (__LITTLE_ENDIAN__)
4042     rep << "endian:little;";
4043 #elif defined (__BIG_ENDIAN__)
4044     rep << "endian:big;";
4045 #elif defined (__PDP_ENDIAN__)
4046     rep << "endian:pdp;";
4047 #endif
4048 
4049 #if (defined (__x86_64__) || defined (__i386__)) && defined (x86_THREAD_STATE)
4050     nub_thread_t thread = DNBProcessGetCurrentThread (pid);
4051     kern_return_t kr;
4052     x86_thread_state_t gp_regs;
4053     mach_msg_type_number_t gp_count = x86_THREAD_STATE_COUNT;
4054     kr = thread_get_state (thread, x86_THREAD_STATE,
4055                            (thread_state_t) &gp_regs, &gp_count);
4056     if (kr == KERN_SUCCESS)
4057     {
4058         if (gp_regs.tsh.flavor == x86_THREAD_STATE64)
4059             rep << "ptrsize:8;";
4060         else
4061             rep << "ptrsize:4;";
4062     }
4063 #elif defined (__arm__)
4064     rep << "ptrsize:4;";
4065 #endif
4066 
4067     return SendPacket (rep.str());
4068 }
4069 
4070