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