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