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