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