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