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