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