summaryrefslogtreecommitdiffstats
path: root/lldb/tools/debugserver/source/RNBRemote.h
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/tools/debugserver/source/RNBRemote.h')
-rw-r--r--lldb/tools/debugserver/source/RNBRemote.h309
1 files changed, 309 insertions, 0 deletions
diff --git a/lldb/tools/debugserver/source/RNBRemote.h b/lldb/tools/debugserver/source/RNBRemote.h
new file mode 100644
index 00000000000..bec9d1812d0
--- /dev/null
+++ b/lldb/tools/debugserver/source/RNBRemote.h
@@ -0,0 +1,309 @@
+//===-- RNBRemote.h ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Created by Greg Clayton on 12/12/07.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __RNBRemote_h__
+#define __RNBRemote_h__
+
+#include "RNBDefs.h"
+#include "DNB.h"
+#include "RNBContext.h"
+#include "RNBSocket.h"
+#include "PThreadMutex.h"
+#include <string>
+#include <vector>
+#include <deque>
+#include <map>
+
+class RNBSocket;
+class RNBContext;
+class PThreadEvents;
+
+enum event_loop_mode { debug_nub, gdb_remote_protocol, done };
+
+class RNBRemote
+{
+public:
+
+ typedef enum {
+ invalid_packet = 0,
+ ack, // '+'
+ nack, // '-'
+ halt, // ^C (async halt)
+ use_extended_mode, // '!'
+ why_halted, // '?'
+ set_argv, // 'A'
+ set_bp, // 'B'
+ cont, // 'c'
+ continue_with_sig, // 'C'
+ detach, // 'D'
+ read_general_regs, // 'g'
+ write_general_regs, // 'G'
+ set_thread, // 'H'
+ step_inferior_one_cycle, // 'i'
+ signal_and_step_inf_one_cycle, // 'I'
+ kill, // 'k'
+ read_memory, // 'm'
+ write_memory, // 'M'
+ read_register, // 'p'
+ write_register, // 'P'
+ restart, // 'R'
+ single_step, // 's'
+ single_step_with_sig, // 'S'
+ search_mem_backwards, // 't'
+ thread_alive_p, // 'T'
+ vattach, // 'vAttach'
+ vattachwait, // 'vAttachWait'
+ vcont, // 'vCont'
+ vcont_list_actions, // 'vCont?'
+ write_data_to_memory, // 'X'
+ insert_mem_bp, // 'Z0'
+ remove_mem_bp, // 'z0'
+ insert_hardware_bp, // 'Z1'
+ remove_hardware_bp, // 'z1'
+ insert_write_watch_bp, // 'Z2'
+ remove_write_watch_bp, // 'z2'
+ insert_read_watch_bp, // 'Z3'
+ remove_read_watch_bp, // 'z3'
+ insert_access_watch_bp, // 'Z4'
+ remove_access_watch_bp, // 'z4'
+
+ query_current_thread_id, // 'qC'
+ query_memory_crc, // 'qCRC:'
+ query_thread_ids_first, // 'qfThreadInfo'
+ query_thread_ids_subsequent, // 'qsThreadInfo'
+ query_thread_extra_info, // 'qThreadExtraInfo'
+ query_thread_stop_info, // 'qThreadStopInfo'
+ query_image_offsets, // 'qOffsets'
+ query_symbol_lookup, // 'gSymbols'
+ query_launch_success, // 'qLaunchSuccess'
+ query_register_info, // 'qRegisterInfo'
+ query_shlib_notify_info_addr, // 'qShlibInfoAddr'
+ query_step_packet_supported, // 'qStepPacketSupported'
+ query_host_info, // 'qHostInfo'
+ pass_signals_to_inferior, // 'QPassSignals'
+ start_noack_mode, // 'QStartNoAckMode'
+ set_logging_mode, // 'QSetLogging:'
+ set_max_packet_size, // 'QSetMaxPacketSize:'
+ set_max_payload_size, // 'QSetMaxPayloadSize:'
+ set_environment_variable, // 'QEnvironment:'
+ allocate_memory, // '_M'
+ deallocate_memory, // '_m'
+
+ unknown_type,
+ } PacketEnum;
+
+ typedef rnb_err_t (RNBRemote::*HandlePacketCallback)(const char *p);
+
+ RNBRemote(bool use_native_regs);
+ ~RNBRemote();
+
+ static void InitializeRegisters (int use_native);
+
+ rnb_err_t HandleAsyncPacket(PacketEnum *type = NULL);
+ rnb_err_t HandleReceivedPacket(PacketEnum *type = NULL);
+
+ nub_thread_t GetContinueThread () const
+ {
+ return m_continue_thread;
+ }
+
+ void SetContinueThread (nub_thread_t tid)
+ {
+ m_continue_thread = tid;
+ }
+
+ nub_thread_t GetCurrentThread () const
+ {
+ if (m_thread == 0 || m_thread == -1)
+ return DNBProcessGetCurrentThread (m_ctx.ProcessID());
+ return m_thread;
+ }
+
+ void SetCurrentThread (nub_thread_t tid)
+ {
+ DNBProcessSetCurrentThread (m_ctx.ProcessID(), tid);
+ m_thread = tid;
+ }
+
+ static void* ThreadFunctionReadRemoteData(void *arg);
+ void StartReadRemoteDataThread ();
+ void StopReadRemoteDataThread ();
+
+ void NotifyThatProcessStopped (void);
+
+ rnb_err_t HandlePacket_A (const char *p);
+ rnb_err_t HandlePacket_H (const char *p);
+ rnb_err_t HandlePacket_qC (const char *p);
+ rnb_err_t HandlePacket_qLaunchSuccess (const char *p);
+ rnb_err_t HandlePacket_qRegisterInfo (const char *p);
+ rnb_err_t HandlePacket_qShlibInfoAddr (const char *p);
+ rnb_err_t HandlePacket_qStepPacketSupported (const char *p);
+ rnb_err_t HandlePacket_qThreadInfo (const char *p);
+ rnb_err_t HandlePacket_qThreadExtraInfo (const char *p);
+ rnb_err_t HandlePacket_qThreadStopInfo (const char *p);
+ rnb_err_t HandlePacket_qHostInfo (const char *p);
+ rnb_err_t HandlePacket_Q (const char *p);
+ rnb_err_t HandlePacket_last_signal (const char *p);
+ rnb_err_t HandlePacket_m (const char *p);
+ rnb_err_t HandlePacket_M (const char *p);
+ rnb_err_t HandlePacket_X (const char *p);
+ rnb_err_t HandlePacket_g (const char *p);
+ rnb_err_t HandlePacket_G (const char *p);
+ rnb_err_t HandlePacket_z (const char *p);
+ rnb_err_t HandlePacket_T (const char *p);
+ rnb_err_t HandlePacket_p (const char *p);
+ rnb_err_t HandlePacket_P (const char *p);
+ rnb_err_t HandlePacket_c (const char *p);
+ rnb_err_t HandlePacket_C (const char *p);
+ rnb_err_t HandlePacket_D (const char *p);
+ rnb_err_t HandlePacket_k (const char *p);
+ rnb_err_t HandlePacket_s (const char *p);
+ rnb_err_t HandlePacket_S (const char *p);
+ rnb_err_t HandlePacket_v (const char *p);
+ rnb_err_t HandlePacket_UNIMPLEMENTED (const char *p);
+ rnb_err_t HandlePacket_ILLFORMED (const char *description);
+ rnb_err_t HandlePacket_AllocateMemory (const char *p);
+ rnb_err_t HandlePacket_DeallocateMemory (const char *p);
+
+ rnb_err_t HandlePacket_stop_process (const char *p);
+
+ rnb_err_t SendStopReplyPacketForThread (nub_thread_t tid);
+ rnb_err_t SendHexEncodedBytePacket (const char *header, const void *buf, size_t buf_len, const char *footer);
+ rnb_err_t SendSTDOUTPacket (char *buf, nub_size_t buf_size);
+ rnb_err_t SendSTDERRPacket (char *buf, nub_size_t buf_size);
+ void FlushSTDIO ();
+
+ RNBContext& Context() { return m_ctx; }
+ RNBSocket& Comm() { return m_comm; }
+
+private:
+ // Outlaw some contructors
+ RNBRemote (const RNBRemote &);
+
+protected:
+
+ static void
+ InitializeNativeRegisters ();
+
+ rnb_err_t GetCommData ();
+ void CommDataReceived(const std::string& data);
+ struct Packet
+ {
+ typedef std::vector<Packet> collection;
+ typedef collection::iterator iterator;
+ typedef collection::const_iterator const_iterator;
+ PacketEnum type;
+ HandlePacketCallback normal; // Function to call when inferior is halted
+ HandlePacketCallback async; // Function to call when inferior is running
+ std::string abbrev;
+ std::string printable_name;
+ Packet() :
+ type(invalid_packet),
+ normal (NULL),
+ async (NULL),
+ abbrev (),
+ printable_name ()
+ {
+ }
+
+ Packet( PacketEnum in_type,
+ HandlePacketCallback in_normal,
+ HandlePacketCallback in_async,
+ const char *in_abbrev,
+ const char *in_printable_name) :
+ type (in_type),
+ normal (in_normal),
+ async (in_async),
+ abbrev (in_abbrev),
+ printable_name (in_printable_name)
+ {
+ }
+ };
+
+ rnb_err_t GetPacket (std::string &packet_data, RNBRemote::Packet& packet_info, bool wait);
+ rnb_err_t SendPacket (const std::string &);
+
+ void CreatePacketTable ();
+ rnb_err_t GetPacketPayload (std::string &);
+
+ // gdb can send multiple Z/z packets for the same address and
+ // these calls must be ref counted.
+ typedef struct Breakpoint
+ {
+ Breakpoint(nub_break_t breakID) :
+ m_breakID(breakID),
+ m_refCount(1)
+ {
+ }
+
+ Breakpoint() :
+ m_breakID(INVALID_NUB_BREAK_ID),
+ m_refCount(0)
+ {
+ }
+
+ Breakpoint(const Breakpoint& rhs) :
+ m_breakID(rhs.m_breakID),
+ m_refCount(rhs.m_refCount)
+ {
+ }
+
+ nub_break_t BreakID() const { return m_breakID; }
+ uint32_t RefCount() const { return m_refCount; }
+ void Release() { if (m_refCount > 0) --m_refCount; }
+ void Retain() { ++m_refCount; }
+
+ nub_break_t m_breakID;
+ uint32_t m_refCount;
+ };
+ typedef std::map<nub_addr_t, Breakpoint> BreakpointMap;
+ typedef BreakpointMap::iterator BreakpointMapIter;
+ typedef BreakpointMap::const_iterator BreakpointMapConstIter;
+ RNBContext m_ctx; // process context
+ RNBSocket m_comm; // communication port
+ bool m_extended_mode; // are we in extended mode?
+ bool m_noack_mode; // are we in no-ack mode?
+ nub_thread_t m_continue_thread; // thread to continue; 0 for any, -1 for all
+ nub_thread_t m_thread; // thread for other ops; 0 for any, -1 for all
+ PThreadMutex m_mutex; // Mutex that protects
+ uint32_t m_packets_recvd;
+ Packet::collection m_packets;
+ std::deque<std::string> m_rx_packets;
+ std::string m_rx_partial_data; // For packets that may come in more than one batch, anything left over can be left here
+ pthread_t m_rx_pthread;
+ BreakpointMap m_breakpoints;
+ BreakpointMap m_watchpoints;
+ uint32_t m_max_payload_size; // the maximum sized payload we should send to gdb
+ bool m_use_native_regs;
+};
+
+/* We translate the /usr/include/mach/exception_types.h exception types
+ (e.g. EXC_BAD_ACCESS) to the fake BSD signal numbers that gdb uses
+ in include/gdb/signals.h (e.g. TARGET_EXC_BAD_ACCESS). These hard
+ coded values for TARGET_EXC_BAD_ACCESS et al must match the gdb
+ values in its include/gdb/signals.h. */
+
+#define TARGET_EXC_BAD_ACCESS 0x91
+#define TARGET_EXC_BAD_INSTRUCTION 0x92
+#define TARGET_EXC_ARITHMETIC 0x93
+#define TARGET_EXC_EMULATION 0x94
+#define TARGET_EXC_SOFTWARE 0x95
+#define TARGET_EXC_BREAKPOINT 0x96
+
+/* Generally speaking, you can't assume gdb can receive more than 399 bytes
+ at a time with a random gdb. This bufsize constant is only specifying
+ how many bytes gdb can *receive* from debugserver -- it tells us nothing
+ about how many bytes gdb might try to send in a single packet. */
+#define DEFAULT_GDB_REMOTE_PROTOCOL_BUFSIZE 399
+
+#endif // #ifndef __RNBRemote_h__
OpenPOWER on IntegriCloud