RNBRemote.cpp revision add4b95f40791afddb360ddd4e431c96432ac6f6
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 == ';')
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{
2033    if (reg != NULL)
2034    {
2035        DNBRegisterValue val;
2036        if (DNBThreadGetRegisterValueByID (pid, tid, reg->nub_info.set, reg->nub_info.reg, &val))
2037        {
2038            append_hex_value (ostrm, val.value.v_uint8, reg->gdb_size, false);
2039        }
2040        else
2041        {
2042            // If we fail to read a regiser value, check if it has a default
2043            // fail value. If it does, return this instead in case some of
2044            // the registers are not available on the current system.
2045            if (reg->gdb_size > 0)
2046            {
2047                if (reg->fail_value != NULL)
2048                {
2049                    append_hex_value (ostrm, reg->fail_value, reg->gdb_size, false);
2050                }
2051                else
2052                {
2053                    std::basic_string<uint8_t> zeros(reg->gdb_size, '\0');
2054                    append_hex_value (ostrm, zeros.data(), zeros.size(), false);
2055                }
2056            }
2057        }
2058    }
2059}
2060
2061
2062void
2063gdb_regnum_with_fixed_width_hex_register_value (std::ostream& ostrm,
2064                                                nub_process_t pid,
2065                                                nub_thread_t tid,
2066                                                const register_map_entry_t* reg)
2067{
2068    // Output the register number as 'NN:VVVVVVVV;' where NN is a 2 bytes HEX
2069    // gdb register number, and VVVVVVVV is the correct number of hex bytes
2070    // as ASCII for the register value.
2071    if (reg != NULL)
2072    {
2073        ostrm << RAWHEX8(reg->gdb_regnum) << ':';
2074        register_value_in_hex_fixed_width (ostrm, pid, tid, reg);
2075        ostrm << ';';
2076    }
2077}
2078
2079rnb_err_t
2080RNBRemote::SendStopReplyPacketForThread (nub_thread_t tid)
2081{
2082    const nub_process_t pid = m_ctx.ProcessID();
2083    if (pid == INVALID_NUB_PROCESS)
2084        return SendPacket("E50");
2085
2086    struct DNBThreadStopInfo tid_stop_info;
2087
2088    /* Fill the remaining space in this packet with as many registers
2089     as we can stuff in there.  */
2090
2091    if (DNBThreadGetStopReason (pid, tid, &tid_stop_info))
2092    {
2093        std::ostringstream ostrm;
2094        // Output the T packet with the thread
2095        ostrm << 'T';
2096        int signum = tid_stop_info.details.signal.signo;
2097        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);
2098
2099        // Translate any mach exceptions to gdb versions, unless they are
2100        // common exceptions like a breakpoint or a soft signal.
2101        switch (tid_stop_info.details.exception.type)
2102        {
2103            default:                    signum = 0; break;
2104            case EXC_BREAKPOINT:        signum = SIGTRAP; break;
2105            case EXC_BAD_ACCESS:        signum = TARGET_EXC_BAD_ACCESS; break;
2106            case EXC_BAD_INSTRUCTION:   signum = TARGET_EXC_BAD_INSTRUCTION; break;
2107            case EXC_ARITHMETIC:        signum = TARGET_EXC_ARITHMETIC; break;
2108            case EXC_EMULATION:         signum = TARGET_EXC_EMULATION; break;
2109            case EXC_SOFTWARE:
2110                if (tid_stop_info.details.exception.data_count == 2 &&
2111                    tid_stop_info.details.exception.data[0] == EXC_SOFT_SIGNAL)
2112                    signum = tid_stop_info.details.exception.data[1];
2113                else
2114                    signum = TARGET_EXC_SOFTWARE;
2115                break;
2116        }
2117
2118        ostrm << RAWHEX8(signum & 0xff);
2119
2120        ostrm << std::hex << "thread:" << tid << ';';
2121
2122        const char *thread_name = DNBThreadGetName (pid, tid);
2123        if (thread_name && thread_name[0])
2124        {
2125            size_t thread_name_len = strlen(thread_name);
2126
2127            if (::strcspn (thread_name, "$#+-;:") == thread_name_len)
2128                ostrm << std::hex << "name:" << thread_name << ';';
2129            else
2130            {
2131                // the thread name contains special chars, send as hex bytes
2132                ostrm << std::hex << "hexname:";
2133                uint8_t *u_thread_name = (uint8_t *)thread_name;
2134                for (int i = 0; i < thread_name_len; i++)
2135                    ostrm << RAWHEX8(u_thread_name[i]);
2136                ostrm << ';';
2137            }
2138        }
2139
2140        thread_identifier_info_data_t thread_ident_info;
2141        if (DNBThreadGetIdentifierInfo (pid, tid, &thread_ident_info))
2142        {
2143            if (thread_ident_info.dispatch_qaddr != 0)
2144                ostrm << std::hex << "qaddr:" << thread_ident_info.dispatch_qaddr << ';';
2145        }
2146
2147        // If a 'QListThreadsInStopReply' was sent to enable this feature, we
2148        // will send all thread IDs back in the "threads" key whose value is
2149        // a listc of hex thread IDs separated by commas:
2150        //  "threads:10a,10b,10c;"
2151        // This will save the debugger from having to send a pair of qfThreadInfo
2152        // and qsThreadInfo packets, but it also might take a lot of room in the
2153        // stop reply packet, so it must be enabled only on systems where there
2154        // are no limits on packet lengths.
2155
2156        if (m_list_threads_in_stop_reply)
2157        {
2158            const nub_size_t numthreads = DNBProcessGetNumThreads (pid);
2159            if (numthreads > 0)
2160            {
2161                ostrm << std::hex << "threads:";
2162                for (nub_size_t i = 0; i < numthreads; ++i)
2163                {
2164                    nub_thread_t th = DNBProcessGetThreadAtIndex (pid, i);
2165                    if (i > 0)
2166                        ostrm << ',';
2167                    ostrm << std::hex << th;
2168                }
2169                ostrm << ';';
2170            }
2171        }
2172
2173        if (g_num_reg_entries == 0)
2174            InitializeRegisters ();
2175
2176        DNBRegisterValue reg_value;
2177        for (uint32_t reg = 0; reg < g_num_reg_entries; reg++)
2178        {
2179            if (g_reg_entries[reg].expedite)
2180            {
2181                if (!DNBThreadGetRegisterValueByID (pid, tid, g_reg_entries[reg].nub_info.set, g_reg_entries[reg].nub_info.reg, &reg_value))
2182                    continue;
2183
2184                gdb_regnum_with_fixed_width_hex_register_value (ostrm, pid, tid, &g_reg_entries[reg]);
2185            }
2186        }
2187
2188        if (tid_stop_info.details.exception.type)
2189        {
2190            ostrm << "metype:" << std::hex << tid_stop_info.details.exception.type << ";";
2191            ostrm << "mecount:" << std::hex << tid_stop_info.details.exception.data_count << ";";
2192            for (int i = 0; i < tid_stop_info.details.exception.data_count; ++i)
2193                ostrm << "medata:" << std::hex << tid_stop_info.details.exception.data[i] << ";";
2194        }
2195        return SendPacket (ostrm.str ());
2196    }
2197    return SendPacket("E51");
2198}
2199
2200/* '?'
2201 The stop reply packet - tell gdb what the status of the inferior is.
2202 Often called the questionmark_packet.  */
2203
2204rnb_err_t
2205RNBRemote::HandlePacket_last_signal (const char *unused)
2206{
2207    if (!m_ctx.HasValidProcessID())
2208    {
2209        // Inferior is not yet specified/running
2210        return SendPacket ("E02");
2211    }
2212
2213    nub_process_t pid = m_ctx.ProcessID();
2214    nub_state_t pid_state = DNBProcessGetState (pid);
2215
2216    switch (pid_state)
2217    {
2218        case eStateAttaching:
2219        case eStateLaunching:
2220        case eStateRunning:
2221        case eStateStepping:
2222        case eStateDetached:
2223            return rnb_success;  // Ignore
2224
2225        case eStateSuspended:
2226        case eStateStopped:
2227        case eStateCrashed:
2228            {
2229                nub_thread_t tid = DNBProcessGetCurrentThread (pid);
2230                // Make sure we set the current thread so g and p packets return
2231                // the data the gdb will expect.
2232                SetCurrentThread (tid);
2233
2234                SendStopReplyPacketForThread (tid);
2235            }
2236            break;
2237
2238        case eStateInvalid:
2239        case eStateUnloaded:
2240        case eStateExited:
2241            {
2242                char pid_exited_packet[16] = "";
2243                int pid_status = 0;
2244                // Process exited with exit status
2245                if (!DNBProcessGetExitStatus(pid, &pid_status))
2246                    pid_status = 0;
2247
2248                if (pid_status)
2249                {
2250                    if (WIFEXITED (pid_status))
2251                        snprintf (pid_exited_packet, sizeof(pid_exited_packet), "W%02x", WEXITSTATUS (pid_status));
2252                    else if (WIFSIGNALED (pid_status))
2253                        snprintf (pid_exited_packet, sizeof(pid_exited_packet), "X%02x", WEXITSTATUS (pid_status));
2254                    else if (WIFSTOPPED (pid_status))
2255                        snprintf (pid_exited_packet, sizeof(pid_exited_packet), "S%02x", WSTOPSIG (pid_status));
2256                }
2257
2258                // If we have an empty exit packet, lets fill one in to be safe.
2259                if (!pid_exited_packet[0])
2260                {
2261                    strncpy (pid_exited_packet, "W00", sizeof(pid_exited_packet)-1);
2262                    pid_exited_packet[sizeof(pid_exited_packet)-1] = '\0';
2263                }
2264
2265                return SendPacket (pid_exited_packet);
2266            }
2267            break;
2268    }
2269    return rnb_success;
2270}
2271
2272rnb_err_t
2273RNBRemote::HandlePacket_M (const char *p)
2274{
2275    if (p == NULL || p[0] == '\0' || strlen (p) < 3)
2276    {
2277        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Too short M packet");
2278    }
2279
2280    char *c;
2281    p++;
2282    errno = 0;
2283    nub_addr_t addr = strtoull (p, &c, 16);
2284    if (errno != 0 && addr == 0)
2285    {
2286        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in M packet");
2287    }
2288    if (*c != ',')
2289    {
2290        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in M packet");
2291    }
2292
2293    /* Advance 'p' to the length part of the packet.  */
2294    p += (c - p) + 1;
2295
2296    errno = 0;
2297    uint32_t length = strtoul (p, &c, 16);
2298    if (errno != 0 && length == 0)
2299    {
2300        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in M packet");
2301    }
2302    if (length == 0)
2303    {
2304        return SendPacket ("OK");
2305    }
2306
2307    if (*c != ':')
2308    {
2309        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Missing colon in M packet");
2310    }
2311    /* Advance 'p' to the data part of the packet.  */
2312    p += (c - p) + 1;
2313
2314    int datalen = strlen (p);
2315    if (datalen & 0x1)
2316    {
2317        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Uneven # of hex chars for data in M packet");
2318    }
2319    if (datalen == 0)
2320    {
2321        return SendPacket ("OK");
2322    }
2323
2324    uint8_t *buf = (uint8_t *) alloca (datalen / 2);
2325    uint8_t *i = buf;
2326
2327    while (*p != '\0' && *(p + 1) != '\0')
2328    {
2329        char hexbuf[3];
2330        hexbuf[0] = *p;
2331        hexbuf[1] = *(p + 1);
2332        hexbuf[2] = '\0';
2333        errno = 0;
2334        uint8_t byte = strtoul (hexbuf, NULL, 16);
2335        if (errno != 0 && byte == 0)
2336        {
2337            return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid hex byte in M packet");
2338        }
2339        *i++ = byte;
2340        p += 2;
2341    }
2342
2343    nub_size_t wrote = DNBProcessMemoryWrite (m_ctx.ProcessID(), addr, length, buf);
2344    if (wrote != length)
2345        return SendPacket ("E09");
2346    else
2347        return SendPacket ("OK");
2348}
2349
2350
2351rnb_err_t
2352RNBRemote::HandlePacket_m (const char *p)
2353{
2354    if (p == NULL || p[0] == '\0' || strlen (p) < 3)
2355    {
2356        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Too short m packet");
2357    }
2358
2359    char *c;
2360    p++;
2361    errno = 0;
2362    nub_addr_t addr = strtoull (p, &c, 16);
2363    if (errno != 0 && addr == 0)
2364    {
2365        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in m packet");
2366    }
2367    if (*c != ',')
2368    {
2369        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in m packet");
2370    }
2371
2372    /* Advance 'p' to the length part of the packet.  */
2373    p += (c - p) + 1;
2374
2375    errno = 0;
2376    uint32_t length = strtoul (p, NULL, 16);
2377    if (errno != 0 && length == 0)
2378    {
2379        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in m packet");
2380    }
2381    if (length == 0)
2382    {
2383        return SendPacket ("");
2384    }
2385
2386    uint8_t buf[length];
2387    int bytes_read = DNBProcessMemoryRead (m_ctx.ProcessID(), addr, length, buf);
2388    if (bytes_read == 0)
2389    {
2390        return SendPacket ("E08");
2391    }
2392
2393    // "The reply may contain fewer bytes than requested if the server was able
2394    //  to read only part of the region of memory."
2395    length = bytes_read;
2396
2397    std::ostringstream ostrm;
2398    for (int i = 0; i < length; i++)
2399        ostrm << RAWHEX8(buf[i]);
2400    return SendPacket (ostrm.str ());
2401}
2402
2403rnb_err_t
2404RNBRemote::HandlePacket_X (const char *p)
2405{
2406    if (p == NULL || p[0] == '\0' || strlen (p) < 3)
2407    {
2408        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Too short X packet");
2409    }
2410
2411    char *c;
2412    p++;
2413    errno = 0;
2414    nub_addr_t addr = strtoull (p, &c, 16);
2415    if (errno != 0 && addr == 0)
2416    {
2417        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in X packet");
2418    }
2419    if (*c != ',')
2420    {
2421        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in X packet");
2422    }
2423
2424    /* Advance 'p' to the length part of the packet.  */
2425    p += (c - p) + 1;
2426
2427    errno = 0;
2428    int length = strtoul (p, NULL, 16);
2429    if (errno != 0 && length == 0)
2430    {
2431        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in m packet");
2432    }
2433
2434    // I think gdb sends a zero length write request to test whether this
2435    // packet is accepted.
2436    if (length == 0)
2437    {
2438        return SendPacket ("OK");
2439    }
2440
2441    std::vector<uint8_t> data = decode_binary_data (c, -1);
2442    std::vector<uint8_t>::const_iterator it;
2443    uint8_t *buf = (uint8_t *) alloca (data.size ());
2444    uint8_t *i = buf;
2445    for (it = data.begin (); it != data.end (); ++it)
2446    {
2447        *i++ = *it;
2448    }
2449
2450    nub_size_t wrote = DNBProcessMemoryWrite (m_ctx.ProcessID(), addr, data.size(), buf);
2451    if (wrote != data.size ())
2452        return SendPacket ("E08");
2453    return SendPacket ("OK");
2454}
2455
2456/* 'g' -- read registers
2457 Get the contents of the registers for the current thread,
2458 send them to gdb.
2459 Should the setting of the Hg packet determine which thread's registers
2460 are returned?  */
2461
2462rnb_err_t
2463RNBRemote::HandlePacket_g (const char *p)
2464{
2465    std::ostringstream ostrm;
2466    if (!m_ctx.HasValidProcessID())
2467    {
2468        return SendPacket ("E11");
2469    }
2470
2471    if (g_num_reg_entries == 0)
2472        InitializeRegisters ();
2473
2474    nub_process_t pid = m_ctx.ProcessID ();
2475    nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p + 1);
2476    if (tid == INVALID_NUB_THREAD)
2477        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
2478
2479    if (m_use_native_regs)
2480    {
2481        // Get the register context size first by calling with NULL buffer
2482        nub_size_t reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, NULL, 0);
2483        if (reg_ctx_size)
2484        {
2485            // Now allocate enough space for the entire register context
2486            std::vector<uint8_t> reg_ctx;
2487            reg_ctx.resize(reg_ctx_size);
2488            // Now read the register context
2489            reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, &reg_ctx[0], reg_ctx.size());
2490            if (reg_ctx_size)
2491            {
2492                append_hex_value (ostrm, reg_ctx.data(), reg_ctx.size(), false);
2493                return SendPacket (ostrm.str ());
2494            }
2495        }
2496    }
2497
2498    for (uint32_t reg = 0; reg < g_num_reg_entries; reg++)
2499        register_value_in_hex_fixed_width (ostrm, pid, tid, &g_reg_entries[reg]);
2500
2501    return SendPacket (ostrm.str ());
2502}
2503
2504/* 'G XXX...' -- write registers
2505 How is the thread for these specified, beyond "the current thread"?
2506 Does gdb actually use the Hg packet to set this?  */
2507
2508rnb_err_t
2509RNBRemote::HandlePacket_G (const char *p)
2510{
2511    if (!m_ctx.HasValidProcessID())
2512    {
2513        return SendPacket ("E11");
2514    }
2515
2516    if (g_num_reg_entries == 0)
2517        InitializeRegisters ();
2518
2519    StringExtractor packet(p);
2520    packet.SetFilePos(1); // Skip the 'G'
2521
2522    nub_process_t pid = m_ctx.ProcessID();
2523    nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p);
2524    if (tid == INVALID_NUB_THREAD)
2525        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
2526
2527    if (m_use_native_regs)
2528    {
2529        // Get the register context size first by calling with NULL buffer
2530        nub_size_t reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, NULL, 0);
2531        if (reg_ctx_size)
2532        {
2533            // Now allocate enough space for the entire register context
2534            std::vector<uint8_t> reg_ctx;
2535            reg_ctx.resize(reg_ctx_size);
2536
2537            const nub_size_t bytes_extracted = packet.GetHexBytes (&reg_ctx[0], reg_ctx.size(), 0xcc);
2538            if (bytes_extracted == reg_ctx.size())
2539            {
2540                // Now write the register context
2541                reg_ctx_size = DNBThreadSetRegisterContext(pid, tid, reg_ctx.data(), reg_ctx.size());
2542                if (reg_ctx_size == reg_ctx.size())
2543                    return SendPacket ("OK");
2544                else
2545                    return SendPacket ("E55");
2546            }
2547            else
2548            {
2549                DNBLogError("RNBRemote::HandlePacket_G(%s): extracted %zu of %zu bytes, size mismatch\n", p, bytes_extracted, reg_ctx_size);
2550                return SendPacket ("E64");
2551            }
2552        }
2553        else
2554            return SendPacket ("E65");
2555    }
2556
2557
2558    DNBRegisterValue reg_value;
2559    for (uint32_t reg = 0; reg < g_num_reg_entries; reg++)
2560    {
2561        const register_map_entry_t *reg_entry = &g_reg_entries[reg];
2562
2563        reg_value.info = reg_entry->nub_info;
2564        if (packet.GetHexBytes (reg_value.value.v_sint8, reg_entry->gdb_size, 0xcc) != reg_entry->gdb_size)
2565            break;
2566
2567        if (reg_entry->fail_value == NULL)
2568        {
2569            if (!DNBThreadSetRegisterValueByID (pid, tid, reg_entry->nub_info.set, reg_entry->nub_info.reg, &reg_value))
2570                return SendPacket ("E15");
2571        }
2572    }
2573    return SendPacket ("OK");
2574}
2575
2576static bool
2577RNBRemoteShouldCancelCallback (void *not_used)
2578{
2579    RNBRemoteSP remoteSP(g_remoteSP);
2580    if (remoteSP.get() != NULL)
2581    {
2582        RNBRemote* remote = remoteSP.get();
2583        if (remote->Comm().IsConnected())
2584            return false;
2585        else
2586            return true;
2587    }
2588    return true;
2589}
2590
2591
2592// FORMAT: _MXXXXXX,PPP
2593//      XXXXXX: big endian hex chars
2594//      PPP: permissions can be any combo of r w x chars
2595//
2596// RESPONSE: XXXXXX
2597//      XXXXXX: hex address of the newly allocated memory
2598//      EXX: error code
2599//
2600// EXAMPLES:
2601//      _M123000,rw
2602//      _M123000,rwx
2603//      _M123000,xw
2604
2605rnb_err_t
2606RNBRemote::HandlePacket_AllocateMemory (const char *p)
2607{
2608    StringExtractor packet (p);
2609    packet.SetFilePos(2); // Skip the "_M"
2610
2611    nub_addr_t size = packet.GetHexMaxU64 (StringExtractor::BigEndian, 0);
2612    if (size != 0)
2613    {
2614        if (packet.GetChar() == ',')
2615        {
2616            uint32_t permissions = 0;
2617            char ch;
2618            bool success = true;
2619            while (success && (ch = packet.GetChar()) != '\0')
2620            {
2621                switch (ch)
2622                {
2623                case 'r':   permissions |= eMemoryPermissionsReadable; break;
2624                case 'w':   permissions |= eMemoryPermissionsWritable; break;
2625                case 'x':   permissions |= eMemoryPermissionsExecutable; break;
2626                default:    success = false; break;
2627                }
2628            }
2629
2630            if (success)
2631            {
2632                nub_addr_t addr = DNBProcessMemoryAllocate (m_ctx.ProcessID(), size, permissions);
2633                if (addr != INVALID_NUB_ADDRESS)
2634                {
2635                    std::ostringstream ostrm;
2636                    ostrm << RAW_HEXBASE << addr;
2637                    return SendPacket (ostrm.str ());
2638                }
2639            }
2640        }
2641    }
2642    return SendPacket ("E53");
2643}
2644
2645// FORMAT: _mXXXXXX
2646//      XXXXXX: address that was previosly allocated
2647//
2648// RESPONSE: XXXXXX
2649//      OK: address was deallocated
2650//      EXX: error code
2651//
2652// EXAMPLES:
2653//      _m123000
2654
2655rnb_err_t
2656RNBRemote::HandlePacket_DeallocateMemory (const char *p)
2657{
2658    StringExtractor packet (p);
2659    packet.SetFilePos(2); // Skip the "_m"
2660    nub_addr_t addr = packet.GetHexMaxU64 (StringExtractor::BigEndian, INVALID_NUB_ADDRESS);
2661
2662    if (addr != INVALID_NUB_ADDRESS)
2663    {
2664        if (DNBProcessMemoryDeallocate (m_ctx.ProcessID(), addr))
2665            return SendPacket ("OK");
2666    }
2667    return SendPacket ("E54");
2668}
2669
2670/*
2671 vAttach;pid
2672
2673 Attach to a new process with the specified process ID. pid is a hexadecimal integer
2674 identifying the process. If the stub is currently controlling a process, it is
2675 killed. The attached process is stopped.This packet is only available in extended
2676 mode (see extended mode).
2677
2678 Reply:
2679 "ENN"                      for an error
2680 "Any Stop Reply Packet"     for success
2681 */
2682
2683rnb_err_t
2684RNBRemote::HandlePacket_v (const char *p)
2685{
2686    if (strcmp (p, "vCont;c") == 0)
2687    {
2688        // Simple continue
2689        return RNBRemote::HandlePacket_c("c");
2690    }
2691    else if (strcmp (p, "vCont;s") == 0)
2692    {
2693        // Simple step
2694        return RNBRemote::HandlePacket_s("s");
2695    }
2696    else if (strstr (p, "vCont") == p)
2697    {
2698        rnb_err_t rnb_err = rnb_success;
2699        typedef struct
2700        {
2701            nub_thread_t tid;
2702            char action;
2703            int signal;
2704        } vcont_action_t;
2705
2706        DNBThreadResumeActions thread_actions;
2707        char *c = (char *)(p += strlen("vCont"));
2708        char *c_end = c + strlen(c);
2709        if (*c == '?')
2710            return SendPacket ("vCont;c;C;s;S");
2711
2712        while (c < c_end && *c == ';')
2713        {
2714            ++c;    // Skip the semi-colon
2715            DNBThreadResumeAction thread_action;
2716            thread_action.tid = INVALID_NUB_THREAD;
2717            thread_action.state = eStateInvalid;
2718            thread_action.signal = 0;
2719            thread_action.addr = INVALID_NUB_ADDRESS;
2720
2721            char action = *c++;
2722
2723            switch (action)
2724            {
2725                case 'C':
2726                    errno = 0;
2727                    thread_action.signal = strtoul (c, &c, 16);
2728                    if (errno != 0)
2729                        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in vCont packet");
2730                    // Fall through to next case...
2731
2732                case 'c':
2733                    // Continue
2734                    thread_action.state = eStateRunning;
2735                    break;
2736
2737                case 'S':
2738                    errno = 0;
2739                    thread_action.signal = strtoul (c, &c, 16);
2740                    if (errno != 0)
2741                        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in vCont packet");
2742                    // Fall through to next case...
2743
2744                case 's':
2745                    // Step
2746                    thread_action.state = eStateStepping;
2747                    break;
2748
2749                default:
2750                    rnb_err = HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Unsupported action in vCont packet");
2751                    break;
2752            }
2753            if (*c == ':')
2754            {
2755                errno = 0;
2756                thread_action.tid = strtoul (++c, &c, 16);
2757                if (errno != 0)
2758                    return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse thread number in vCont packet");
2759            }
2760
2761            thread_actions.Append (thread_action);
2762        }
2763
2764        // If a default action for all other threads wasn't mentioned
2765        // then we should stop the threads
2766        thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0);
2767        DNBProcessResume(m_ctx.ProcessID(), thread_actions.GetFirst (), thread_actions.GetSize());
2768        return rnb_success;
2769    }
2770    else if (strstr (p, "vAttach") == p)
2771    {
2772        nub_process_t attach_pid = INVALID_NUB_PROCESS;
2773        char err_str[1024]={'\0'};
2774        if (strstr (p, "vAttachWait;") == p)
2775        {
2776            p += strlen("vAttachWait;");
2777            std::string attach_name;
2778            while (*p != '\0')
2779            {
2780                char smallbuf[3];
2781                smallbuf[0] = *p;
2782                smallbuf[1] = *(p + 1);
2783                smallbuf[2] = '\0';
2784
2785                errno = 0;
2786                int ch = strtoul (smallbuf, NULL, 16);
2787                if (errno != 0 && ch == 0)
2788                {
2789                    return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachWait' pkt");
2790                }
2791
2792                attach_name.push_back(ch);
2793                p += 2;
2794            }
2795
2796            attach_pid = DNBProcessAttachWait(attach_name.c_str (), m_ctx.LaunchFlavor(), NULL, 1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback);
2797
2798        }
2799        else if (strstr (p, "vAttachName;") == p)
2800        {
2801            p += strlen("vAttachName;");
2802            std::string attach_name;
2803            while (*p != '\0')
2804            {
2805                char smallbuf[3];
2806                smallbuf[0] = *p;
2807                smallbuf[1] = *(p + 1);
2808                smallbuf[2] = '\0';
2809
2810                errno = 0;
2811                int ch = strtoul (smallbuf, NULL, 16);
2812                if (errno != 0 && ch == 0)
2813                {
2814                    return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachWait' pkt");
2815                }
2816
2817                attach_name.push_back(ch);
2818                p += 2;
2819            }
2820
2821            attach_pid = DNBProcessAttachByName (attach_name.c_str(), NULL, err_str, sizeof(err_str));
2822
2823        }
2824        else if (strstr (p, "vAttach;") == p)
2825        {
2826            p += strlen("vAttach;");
2827            char *end = NULL;
2828            attach_pid = strtoul (p, &end, 16);    // PID will be in hex, so use base 16 to decode
2829            if (p != end && *end == '\0')
2830            {
2831                // Wait at most 30 second for attach
2832                struct timespec attach_timeout_abstime;
2833                DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, 30, 0);
2834                attach_pid = DNBProcessAttach(attach_pid, &attach_timeout_abstime, err_str, sizeof(err_str));
2835            }
2836        }
2837        else
2838            return HandlePacket_UNIMPLEMENTED(p);
2839
2840
2841        if (attach_pid != INVALID_NUB_PROCESS)
2842        {
2843            if (m_ctx.ProcessID() != attach_pid)
2844                m_ctx.SetProcessID(attach_pid);
2845            // Send a stop reply packet to indicate we successfully attached!
2846            NotifyThatProcessStopped ();
2847            return rnb_success;
2848        }
2849        else
2850        {
2851            m_ctx.LaunchStatus().SetError(-1, DNBError::Generic);
2852            if (err_str[0])
2853                m_ctx.LaunchStatus().SetErrorString(err_str);
2854            else
2855                m_ctx.LaunchStatus().SetErrorString("attach failed");
2856            return SendPacket ("E01");  // E01 is our magic error value for attach failed.
2857        }
2858    }
2859
2860    // All other failures come through here
2861    return HandlePacket_UNIMPLEMENTED(p);
2862}
2863
2864/* 'T XX' -- status of thread
2865 Check if the specified thread is alive.
2866 The thread number is in hex?  */
2867
2868rnb_err_t
2869RNBRemote::HandlePacket_T (const char *p)
2870{
2871    p++;
2872    if (p == NULL || *p == '\0')
2873    {
2874        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in T packet");
2875    }
2876    if (!m_ctx.HasValidProcessID())
2877    {
2878        return SendPacket ("E15");
2879    }
2880    errno = 0;
2881    nub_thread_t tid = strtoul (p, NULL, 16);
2882    if (errno != 0 && tid == 0)
2883    {
2884        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse thread number in T packet");
2885    }
2886
2887    nub_state_t state = DNBThreadGetState (m_ctx.ProcessID(), tid);
2888    if (state == eStateInvalid || state == eStateExited || state == eStateCrashed)
2889    {
2890        return SendPacket ("E16");
2891    }
2892
2893    return SendPacket ("OK");
2894}
2895
2896
2897rnb_err_t
2898RNBRemote::HandlePacket_z (const char *p)
2899{
2900    if (p == NULL || *p == '\0')
2901        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in z packet");
2902
2903    if (!m_ctx.HasValidProcessID())
2904        return SendPacket ("E15");
2905
2906    char packet_cmd = *p++;
2907    char break_type = *p++;
2908
2909    if (*p++ != ',')
2910        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma separator missing in z packet");
2911
2912    char *c = NULL;
2913    nub_process_t pid = m_ctx.ProcessID();
2914    errno = 0;
2915    nub_addr_t addr = strtoull (p, &c, 16);
2916    if (errno != 0 && addr == 0)
2917        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in z packet");
2918    p = c;
2919    if (*p++ != ',')
2920        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma separator missing in z packet");
2921
2922    errno = 0;
2923    uint32_t byte_size = strtoul (p, &c, 16);
2924    if (errno != 0 && byte_size == 0)
2925        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in z packet");
2926
2927    if (packet_cmd == 'Z')
2928    {
2929        // set
2930        switch (break_type)
2931        {
2932            case '0':   // set software breakpoint
2933            case '1':   // set hardware breakpoint
2934            {
2935                // gdb can send multiple Z packets for the same address and
2936                // these calls must be ref counted.
2937                bool hardware = (break_type == '1');
2938
2939                // Check if we currently have a breakpoint already set at this address
2940                BreakpointMapIter pos = m_breakpoints.find(addr);
2941                if (pos != m_breakpoints.end())
2942                {
2943                    // We do already have a breakpoint at this address, increment
2944                    // its reference count and return OK
2945                    pos->second.Retain();
2946                    return SendPacket ("OK");
2947                }
2948                else
2949                {
2950                    // We do NOT already have a breakpoint at this address, So lets
2951                    // create one.
2952                    nub_break_t break_id = DNBBreakpointSet (pid, addr, byte_size, hardware);
2953                    if (NUB_BREAK_ID_IS_VALID(break_id))
2954                    {
2955                        // We successfully created a breakpoint, now lets full out
2956                        // a ref count structure with the breakID and add it to our
2957                        // map.
2958                        Breakpoint rnbBreakpoint(break_id);
2959                        m_breakpoints[addr] = rnbBreakpoint;
2960                        return SendPacket ("OK");
2961                    }
2962                    else
2963                    {
2964                        // We failed to set the software breakpoint
2965                        return SendPacket ("E09");
2966                    }
2967                }
2968            }
2969                break;
2970
2971            case '2':   // set write watchpoint
2972            case '3':   // set read watchpoint
2973            case '4':   // set access watchpoint
2974            {
2975                bool hardware = true;
2976                uint32_t watch_flags = 0;
2977                if (break_type == '2')
2978                    watch_flags = WATCH_TYPE_WRITE;
2979                else if (break_type == '3')
2980                    watch_flags = WATCH_TYPE_READ;
2981                else
2982                    watch_flags = WATCH_TYPE_READ | WATCH_TYPE_WRITE;
2983
2984                // Check if we currently have a watchpoint already set at this address
2985                BreakpointMapIter pos = m_watchpoints.find(addr);
2986                if (pos != m_watchpoints.end())
2987                {
2988                    // We do already have a watchpoint at this address, increment
2989                    // its reference count and return OK
2990                    pos->second.Retain();
2991                    return SendPacket ("OK");
2992                }
2993                else
2994                {
2995                    // We do NOT already have a watchpoint at this address, So lets
2996                    // create one.
2997                    nub_watch_t watch_id = DNBWatchpointSet (pid, addr, byte_size, watch_flags, hardware);
2998                    if (NUB_WATCH_ID_IS_VALID(watch_id))
2999                    {
3000                        // We successfully created a watchpoint, now lets full out
3001                        // a ref count structure with the watch_id and add it to our
3002                        // map.
3003                        Breakpoint rnbWatchpoint(watch_id);
3004                        m_watchpoints[addr] = rnbWatchpoint;
3005                        return SendPacket ("OK");
3006                    }
3007                    else
3008                    {
3009                        // We failed to set the watchpoint
3010                        return SendPacket ("E09");
3011                    }
3012                }
3013            }
3014                break;
3015
3016            default:
3017                break;
3018        }
3019    }
3020    else if (packet_cmd == 'z')
3021    {
3022        // remove
3023        switch (break_type)
3024        {
3025            case '0':   // remove software breakpoint
3026            case '1':   // remove hardware breakpoint
3027            {
3028                // gdb can send multiple z packets for the same address and
3029                // these calls must be ref counted.
3030                BreakpointMapIter pos = m_breakpoints.find(addr);
3031                if (pos != m_breakpoints.end())
3032                {
3033                    // We currently have a breakpoint at address ADDR. Decrement
3034                    // its reference count, and it that count is now zero we
3035                    // can clear the breakpoint.
3036                    pos->second.Release();
3037                    if (pos->second.RefCount() == 0)
3038                    {
3039                        if (DNBBreakpointClear (pid, pos->second.BreakID()))
3040                        {
3041                            m_breakpoints.erase(pos);
3042                            return SendPacket ("OK");
3043                        }
3044                        else
3045                        {
3046                            return SendPacket ("E08");
3047                        }
3048                    }
3049                    else
3050                    {
3051                        // We still have references to this breakpoint don't
3052                        // delete it, just decrementing the reference count
3053                        // is enough.
3054                        return SendPacket ("OK");
3055                    }
3056                }
3057                else
3058                {
3059                    // We don't know about any breakpoints at this address
3060                    return SendPacket ("E08");
3061                }
3062            }
3063                break;
3064
3065            case '2':   // remove write watchpoint
3066            case '3':   // remove read watchpoint
3067            case '4':   // remove access watchpoint
3068            {
3069                // gdb can send multiple z packets for the same address and
3070                // these calls must be ref counted.
3071                BreakpointMapIter pos = m_watchpoints.find(addr);
3072                if (pos != m_watchpoints.end())
3073                {
3074                    // We currently have a watchpoint at address ADDR. Decrement
3075                    // its reference count, and it that count is now zero we
3076                    // can clear the watchpoint.
3077                    pos->second.Release();
3078                    if (pos->second.RefCount() == 0)
3079                    {
3080                        if (DNBWatchpointClear (pid, pos->second.BreakID()))
3081                        {
3082                            m_watchpoints.erase(pos);
3083                            return SendPacket ("OK");
3084                        }
3085                        else
3086                        {
3087                            return SendPacket ("E08");
3088                        }
3089                    }
3090                    else
3091                    {
3092                        // We still have references to this watchpoint don't
3093                        // delete it, just decrementing the reference count
3094                        // is enough.
3095                        return SendPacket ("OK");
3096                    }
3097                }
3098                else
3099                {
3100                    // We don't know about any watchpoints at this address
3101                    return SendPacket ("E08");
3102                }
3103            }
3104                break;
3105
3106            default:
3107                break;
3108        }
3109    }
3110    return HandlePacket_UNIMPLEMENTED(p);
3111}
3112
3113// Extract the thread number from the thread suffix that might be appended to
3114// thread specific packets. This will only be enabled if m_thread_suffix_supported
3115// is true.
3116nub_thread_t
3117RNBRemote::ExtractThreadIDFromThreadSuffix (const char *p)
3118{
3119    if (m_thread_suffix_supported)
3120    {
3121        nub_thread_t tid = INVALID_NUB_THREAD;
3122        if (p)
3123        {
3124            const char *tid_cstr = strstr (p, "thread:");
3125            if (tid_cstr)
3126            {
3127                tid_cstr += strlen ("thread:");
3128                tid = strtoul(tid_cstr, NULL, 16);
3129            }
3130        }
3131        return tid;
3132    }
3133    return GetCurrentThread();
3134
3135}
3136
3137/* 'p XX'
3138 print the contents of register X */
3139
3140rnb_err_t
3141RNBRemote::HandlePacket_p (const char *p)
3142{
3143    if (g_num_reg_entries == 0)
3144        InitializeRegisters ();
3145
3146    if (p == NULL || *p == '\0')
3147    {
3148        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
3149    }
3150    if (!m_ctx.HasValidProcessID())
3151    {
3152        return SendPacket ("E15");
3153    }
3154    nub_process_t pid = m_ctx.ProcessID();
3155    errno = 0;
3156    char *tid_cstr = NULL;
3157    uint32_t reg = strtoul (p + 1, &tid_cstr, 16);
3158    if (errno != 0 && reg == 0)
3159    {
3160        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse register number in p packet");
3161    }
3162
3163    nub_thread_t tid = ExtractThreadIDFromThreadSuffix (tid_cstr);
3164    if (tid == INVALID_NUB_THREAD)
3165        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
3166
3167    const register_map_entry_t *reg_entry;
3168
3169    if (reg < g_num_reg_entries)
3170        reg_entry = &g_reg_entries[reg];
3171    else
3172        reg_entry = NULL;
3173
3174    std::ostringstream ostrm;
3175    if (reg_entry == NULL)
3176    {
3177        DNBLogError("RNBRemote::HandlePacket_p(%s): unknown register number %u requested\n", p, reg);
3178        ostrm << "00000000";
3179    }
3180    else if (reg_entry->nub_info.reg == -1)
3181    {
3182        if (reg_entry->gdb_size > 0)
3183        {
3184            if (reg_entry->fail_value != NULL)
3185            {
3186                append_hex_value(ostrm, reg_entry->fail_value, reg_entry->gdb_size, false);
3187            }
3188            else
3189            {
3190                std::basic_string<uint8_t> zeros(reg_entry->gdb_size, '\0');
3191                append_hex_value(ostrm, zeros.data(), zeros.size(), false);
3192            }
3193        }
3194    }
3195    else
3196    {
3197        register_value_in_hex_fixed_width (ostrm, pid, tid, reg_entry);
3198    }
3199    return SendPacket (ostrm.str());
3200}
3201
3202/* 'Pnn=rrrrr'
3203 Set register number n to value r.
3204 n and r are hex strings.  */
3205
3206rnb_err_t
3207RNBRemote::HandlePacket_P (const char *p)
3208{
3209    if (g_num_reg_entries == 0)
3210        InitializeRegisters ();
3211
3212    if (p == NULL || *p == '\0')
3213    {
3214        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Empty P packet");
3215    }
3216    if (!m_ctx.HasValidProcessID())
3217    {
3218        return SendPacket ("E28");
3219    }
3220
3221    nub_process_t pid = m_ctx.ProcessID();
3222
3223    StringExtractor packet (p);
3224
3225    const char cmd_char = packet.GetChar();
3226    // Register ID is always in big endian
3227    const uint32_t reg = packet.GetHexMaxU32 (false, UINT32_MAX);
3228    const char equal_char = packet.GetChar();
3229
3230    if (cmd_char != 'P')
3231        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Improperly formed P packet");
3232
3233    if (reg == UINT32_MAX)
3234        return SendPacket ("E29");
3235
3236    if (equal_char != '=')
3237        return SendPacket ("E30");
3238
3239    const register_map_entry_t *reg_entry;
3240
3241    if (reg >= g_num_reg_entries)
3242        return SendPacket("E47");
3243
3244    reg_entry = &g_reg_entries[reg];
3245
3246    if (reg_entry->nub_info.set == -1 && reg_entry->nub_info.reg == -1)
3247    {
3248        DNBLogError("RNBRemote::HandlePacket_P(%s): unknown register number %u requested\n", p, reg);
3249        return SendPacket("E48");
3250    }
3251
3252    DNBRegisterValue reg_value;
3253    reg_value.info = reg_entry->nub_info;
3254    packet.GetHexBytes (reg_value.value.v_sint8, reg_entry->gdb_size, 0xcc);
3255
3256    nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p);
3257    if (tid == INVALID_NUB_THREAD)
3258        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
3259
3260    if (!DNBThreadSetRegisterValueByID (pid, tid, reg_entry->nub_info.set, reg_entry->nub_info.reg, &reg_value))
3261    {
3262        return SendPacket ("E32");
3263    }
3264    return SendPacket ("OK");
3265}
3266
3267/* 'c [addr]'
3268 Continue, optionally from a specified address. */
3269
3270rnb_err_t
3271RNBRemote::HandlePacket_c (const char *p)
3272{
3273    const nub_process_t pid = m_ctx.ProcessID();
3274
3275    if (pid == INVALID_NUB_PROCESS)
3276        return SendPacket ("E23");
3277
3278    DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateRunning, 0, INVALID_NUB_ADDRESS };
3279
3280    if (*(p + 1) != '\0')
3281    {
3282        action.tid = GetContinueThread();
3283        errno = 0;
3284        action.addr = strtoull (p + 1, NULL, 16);
3285        if (errno != 0 && action.addr == 0)
3286            return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in c packet");
3287    }
3288
3289    DNBThreadResumeActions thread_actions;
3290    thread_actions.Append(action);
3291    thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, 0);
3292    if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize()))
3293        return SendPacket ("E25");
3294    // Don't send an "OK" packet; response is the stopped/exited message.
3295    return rnb_success;
3296}
3297
3298rnb_err_t
3299RNBRemote::HandlePacket_MemoryRegionInfo (const char *p)
3300{
3301    /* This packet will find memory attributes (e.g. readable, writable, executable, stack, jitted code)
3302       for the memory region containing a given address and return that information.
3303
3304       Users of this packet must be prepared for three results:
3305
3306           Region information is returned
3307           Region information is unavailable for this address because the address is in unmapped memory
3308           Region lookup cannot be performed on this platform or process is not yet launched
3309           This packet isn't implemented
3310
3311       Examples of use:
3312          qMemoryRegionInfo:3a55140
3313          start:3a50000,size:100000,permissions:rwx
3314
3315          qMemoryRegionInfo:0
3316          error:address in unmapped region
3317
3318          qMemoryRegionInfo:3a551140   (on a different platform)
3319          error:region lookup cannot be performed
3320
3321          qMemoryRegionInfo
3322          OK                   // this packet is implemented by the remote nub
3323    */
3324
3325    p += sizeof ("qMemoryRegionInfo") - 1;
3326    if (*p == '\0')
3327       return SendPacket ("OK");
3328    if (*p++ != ':')
3329       return SendPacket ("E67");
3330    if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X'))
3331       p += 2;
3332
3333    errno = 0;
3334    uint64_t address = strtoul (p, NULL, 16);
3335    if (errno != 0 && address == 0)
3336    {
3337        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in qMemoryRegionInfo packet");
3338    }
3339
3340    DNBRegionInfo region_info = { 0, 0, 0 };
3341    DNBProcessMemoryRegionInfo (m_ctx.ProcessID(), address, &region_info);
3342    std::ostringstream ostrm;
3343
3344        // start:3a50000,size:100000,permissions:rwx
3345    ostrm << "start:" << std::hex << region_info.addr << ';';
3346
3347    if (region_info.size > 0)
3348        ostrm << "size:"  << std::hex << region_info.size << ';';
3349
3350    if (region_info.permissions)
3351    {
3352        ostrm << "permissions:";
3353
3354        if (region_info.permissions & eMemoryPermissionsReadable)
3355            ostrm << 'r';
3356        if (region_info.permissions & eMemoryPermissionsWritable)
3357            ostrm << 'w';
3358        if (region_info.permissions & eMemoryPermissionsExecutable)
3359            ostrm << 'x';
3360        ostrm << ';';
3361    }
3362    return SendPacket (ostrm.str());
3363}
3364
3365rnb_err_t
3366RNBRemote::HandlePacket_WatchpointSupportInfo (const char *p)
3367{
3368    /* This packet simply returns the number of supported hardware watchpoints.
3369
3370       Examples of use:
3371          qWatchpointSupportInfo:
3372          num:4
3373
3374          qWatchpointSupportInfo
3375          OK                   // this packet is implemented by the remote nub
3376    */
3377
3378    p += sizeof ("qWatchpointSupportInfo") - 1;
3379    if (*p == '\0')
3380       return SendPacket ("OK");
3381    if (*p++ != ':')
3382       return SendPacket ("E67");
3383
3384    errno = 0;
3385    uint32_t num = DNBWatchpointGetNumSupportedHWP (m_ctx.ProcessID());
3386    std::ostringstream ostrm;
3387
3388    // size:4
3389    ostrm << "num:" << std::dec << num << ';';
3390    return SendPacket (ostrm.str());
3391}
3392
3393/* 'C sig [;addr]'
3394 Resume with signal sig, optionally at address addr.  */
3395
3396rnb_err_t
3397RNBRemote::HandlePacket_C (const char *p)
3398{
3399    const nub_process_t pid = m_ctx.ProcessID();
3400
3401    if (pid == INVALID_NUB_PROCESS)
3402        return SendPacket ("E36");
3403
3404    DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateRunning, 0, INVALID_NUB_ADDRESS };
3405    int process_signo = -1;
3406    if (*(p + 1) != '\0')
3407    {
3408        action.tid = GetContinueThread();
3409        char *end = NULL;
3410        errno = 0;
3411        process_signo = strtoul (p + 1, &end, 16);
3412        if (errno != 0)
3413            return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in C packet");
3414        else if (*end == ';')
3415        {
3416            errno = 0;
3417            action.addr = strtoull (end + 1, NULL, 16);
3418            if (errno != 0 && action.addr == 0)
3419                return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in C packet");
3420        }
3421    }
3422
3423    DNBThreadResumeActions thread_actions;
3424    thread_actions.Append (action);
3425    thread_actions.SetDefaultThreadActionIfNeeded (eStateRunning, action.signal);
3426    if (!DNBProcessSignal(pid, process_signo))
3427        return SendPacket ("E52");
3428    if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize()))
3429        return SendPacket ("E38");
3430    /* Don't send an "OK" packet; response is the stopped/exited message.  */
3431    return rnb_success;
3432}
3433
3434//----------------------------------------------------------------------
3435// 'D' packet
3436// Detach from gdb.
3437//----------------------------------------------------------------------
3438rnb_err_t
3439RNBRemote::HandlePacket_D (const char *p)
3440{
3441    SendPacket ("OK");
3442    if (m_ctx.HasValidProcessID())
3443        DNBProcessDetach(m_ctx.ProcessID());
3444    return rnb_success;
3445}
3446
3447/* 'k'
3448 Kill the inferior process.  */
3449
3450rnb_err_t
3451RNBRemote::HandlePacket_k (const char *p)
3452{
3453    // No response to should be sent to the kill packet
3454    if (m_ctx.HasValidProcessID())
3455        DNBProcessKill (m_ctx.ProcessID());
3456    SendPacket ("W09");
3457    return rnb_success;
3458}
3459
3460rnb_err_t
3461RNBRemote::HandlePacket_stop_process (const char *p)
3462{
3463    DNBProcessSignal (m_ctx.ProcessID(), SIGSTOP);
3464    //DNBProcessSignal (m_ctx.ProcessID(), SIGINT);
3465    // Do not send any response packet! Wait for the stop reply packet to naturally happen
3466    return rnb_success;
3467}
3468
3469/* 's'
3470 Step the inferior process.  */
3471
3472rnb_err_t
3473RNBRemote::HandlePacket_s (const char *p)
3474{
3475    const nub_process_t pid = m_ctx.ProcessID();
3476    if (pid == INVALID_NUB_PROCESS)
3477        return SendPacket ("E32");
3478
3479    // Hardware supported stepping not supported on arm
3480    nub_thread_t tid = GetContinueThread ();
3481    if (tid == 0 || tid == -1)
3482        tid = GetCurrentThread();
3483
3484    if (tid == INVALID_NUB_THREAD)
3485        return SendPacket ("E33");
3486
3487    DNBThreadResumeActions thread_actions;
3488    thread_actions.AppendAction(tid, eStateStepping);
3489
3490    // Make all other threads stop when we are stepping
3491    thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0);
3492    if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize()))
3493        return SendPacket ("E49");
3494    // Don't send an "OK" packet; response is the stopped/exited message.
3495    return rnb_success;
3496}
3497
3498/* 'S sig [;addr]'
3499 Step with signal sig, optionally at address addr.  */
3500
3501rnb_err_t
3502RNBRemote::HandlePacket_S (const char *p)
3503{
3504    const nub_process_t pid = m_ctx.ProcessID();
3505    if (pid == INVALID_NUB_PROCESS)
3506        return SendPacket ("E36");
3507
3508    DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateStepping, 0, INVALID_NUB_ADDRESS };
3509
3510    if (*(p + 1) != '\0')
3511    {
3512        char *end = NULL;
3513        errno = 0;
3514        action.signal = strtoul (p + 1, &end, 16);
3515        if (errno != 0)
3516            return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in S packet");
3517        else if (*end == ';')
3518        {
3519            errno = 0;
3520            action.addr = strtoull (end + 1, NULL, 16);
3521            if (errno != 0 && action.addr == 0)
3522            {
3523                return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in S packet");
3524            }
3525        }
3526    }
3527
3528    action.tid = GetContinueThread ();
3529    if (action.tid == 0 || action.tid == -1)
3530        return SendPacket ("E40");
3531
3532    nub_state_t tstate = DNBThreadGetState (pid, action.tid);
3533    if (tstate == eStateInvalid || tstate == eStateExited)
3534        return SendPacket ("E37");
3535
3536
3537    DNBThreadResumeActions thread_actions;
3538    thread_actions.Append (action);
3539
3540    // Make all other threads stop when we are stepping
3541    thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
3542    if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize()))
3543        return SendPacket ("E39");
3544
3545    // Don't send an "OK" packet; response is the stopped/exited message.
3546    return rnb_success;
3547}
3548
3549rnb_err_t
3550RNBRemote::HandlePacket_qHostInfo (const char *p)
3551{
3552    std::ostringstream strm;
3553
3554    uint32_t cputype, is_64_bit_capable;
3555    size_t len = sizeof(cputype);
3556    bool promoted_to_64 = false;
3557    if  (::sysctlbyname("hw.cputype", &cputype, &len, NULL, 0) == 0)
3558    {
3559        len = sizeof (is_64_bit_capable);
3560        if  (::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0) == 0)
3561        {
3562            if (is_64_bit_capable && ((cputype & CPU_ARCH_ABI64) == 0))
3563            {
3564                promoted_to_64 = true;
3565                cputype |= CPU_ARCH_ABI64;
3566            }
3567        }
3568
3569        strm << "cputype:" << std::dec << cputype << ';';
3570    }
3571
3572    uint32_t cpusubtype;
3573    len = sizeof(cpusubtype);
3574    if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0)
3575    {
3576        if (promoted_to_64 &&
3577            cputype == CPU_TYPE_X86_64 &&
3578            cpusubtype == CPU_SUBTYPE_486)
3579            cpusubtype = CPU_SUBTYPE_X86_64_ALL;
3580
3581        strm << "cpusubtype:" << std::dec << cpusubtype << ';';
3582    }
3583
3584    // The OS in the triple should be "ios" or "macosx" which doesn't match our
3585    // "Darwin" which gets returned from "kern.ostype", so we need to hardcode
3586    // this for now.
3587    if (cputype == CPU_TYPE_ARM)
3588    {
3589        strm << "ostype:ios;";
3590        // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes.
3591        strm << "watchpoint_exceptions_received:before;";
3592    }
3593    else
3594    {
3595        strm << "ostype:macosx;";
3596        strm << "watchpoint_exceptions_received:after;";
3597    }
3598//    char ostype[64];
3599//    len = sizeof(ostype);
3600//    if (::sysctlbyname("kern.ostype", &ostype, &len, NULL, 0) == 0)
3601//    {
3602//        len = strlen(ostype);
3603//        std::transform (ostype, ostype + len, ostype, tolower);
3604//        strm << "ostype:" << std::dec << ostype << ';';
3605//    }
3606
3607    strm << "vendor:apple;";
3608
3609#if defined (__LITTLE_ENDIAN__)
3610    strm << "endian:little;";
3611#elif defined (__BIG_ENDIAN__)
3612    strm << "endian:big;";
3613#elif defined (__PDP_ENDIAN__)
3614    strm << "endian:pdp;";
3615#endif
3616
3617    if (promoted_to_64)
3618        strm << "ptrsize:8;";
3619    else
3620        strm << "ptrsize:" << std::dec << sizeof(void *) << ';';
3621    return SendPacket (strm.str());
3622}
3623