summaryrefslogtreecommitdiff
path: root/src/base/remote_gdb.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/base/remote_gdb.hh')
-rw-r--r--src/base/remote_gdb.hh396
1 files changed, 170 insertions, 226 deletions
diff --git a/src/base/remote_gdb.hh b/src/base/remote_gdb.hh
index 121faaf2e..27b4ab488 100644
--- a/src/base/remote_gdb.hh
+++ b/src/base/remote_gdb.hh
@@ -49,265 +49,239 @@
class System;
class ThreadContext;
-class GDBListener;
-
class BaseRemoteGDB;
-
-struct GdbCommand
+class HardBreakpoint;
+
+/**
+ * Concrete subclasses of this abstract class represent how the
+ * register values are transmitted on the wire. Usually each
+ * architecture should define one subclass, but there can be more
+ * if there is more than one possible wire format. For example,
+ * ARM defines both AArch32GdbRegCache and AArch64GdbRegCache.
+ */
+class BaseGdbRegCache
{
public:
- struct Context
- {
- const GdbCommand *cmd;
- char cmd_byte;
- int type;
- char *data;
- int len;
- };
- typedef bool (BaseRemoteGDB::*Func)(Context &ctx);
+ /**
+ * Return the pointer to the raw bytes buffer containing the
+ * register values. Each byte of this buffer is literally
+ * encoded as two hex digits in the g or G RSP packet.
+ */
+ virtual char *data() const = 0;
+
+ /**
+ * Return the size of the raw buffer, in bytes
+ * (i.e., half of the number of digits in the g/G packet).
+ */
+ virtual size_t size() const = 0;
+
+ /**
+ * Fill the raw buffer from the registers in the ThreadContext.
+ */
+ virtual void getRegs(ThreadContext*) = 0;
+
+ /**
+ * Set the ThreadContext's registers from the values
+ * in the raw buffer.
+ */
+ virtual void setRegs(ThreadContext*) const = 0;
- const char * const name;
- const Func func;
+ /**
+ * Return the name to use in places like DPRINTF.
+ * Having each concrete superclass redefine this member
+ * is useful in situations where the class of the regCache
+ * can change on the fly.
+ */
+ virtual const std::string name() const = 0;
- GdbCommand(const char *_name, Func _func) : name(_name), func(_func)
+ BaseGdbRegCache(BaseRemoteGDB *g) : gdb(g)
{}
+ virtual ~BaseGdbRegCache()
+ {}
+
+ protected:
+ BaseRemoteGDB *gdb;
};
class BaseRemoteGDB
{
- private:
- friend void debugger();
- friend class GDBListener;
+ friend class HardBreakpoint;
+ public:
- protected:
- /// Exception to throw when the connection to the client is broken.
- struct BadClient
- {
- const char *warning;
- BadClient(const char *_warning=NULL) : warning(_warning)
- {}
- };
- /// Exception to throw when an error needs to be reported to the client.
- struct CmdError
- {
- std::string error;
- CmdError(std::string _error) : error(_error)
- {}
- };
- /// Exception to throw when something isn't supported.
- class Unsupported {};
+ /*
+ * Interface to other parts of the simulator.
+ */
+ BaseRemoteGDB(System *system, ThreadContext *context, int _port);
+ virtual ~BaseRemoteGDB();
- // Helper functions
- protected:
- int digit2i(char);
- char i2digit(int);
- Addr hex2i(const char **);
- // Address formats, break types, and gdb commands may change
- // between architectures, so they're defined as virtual
- // functions.
- virtual void mem2hex(char *, const char *, int);
- virtual const char * hex2mem(char *, const char *, int);
- virtual const char * break_type(char c);
+ std::string name();
- protected:
- static std::map<char, GdbCommand> command_map;
+ void listen();
+ void connect();
- bool cmd_unsupported(GdbCommand::Context &ctx);
+ int port() const;
- bool cmd_signal(GdbCommand::Context &ctx);
- bool cmd_cont(GdbCommand::Context &ctx);
- bool cmd_async_cont(GdbCommand::Context &ctx);
- bool cmd_detach(GdbCommand::Context &ctx);
- bool cmd_reg_r(GdbCommand::Context &ctx);
- bool cmd_reg_w(GdbCommand::Context &ctx);
- bool cmd_set_thread(GdbCommand::Context &ctx);
- bool cmd_mem_r(GdbCommand::Context &ctx);
- bool cmd_mem_w(GdbCommand::Context &ctx);
- bool cmd_query_var(GdbCommand::Context &ctx);
- bool cmd_step(GdbCommand::Context &ctx);
- bool cmd_async_step(GdbCommand::Context &ctx);
- bool cmd_clr_hw_bkpt(GdbCommand::Context &ctx);
- bool cmd_set_hw_bkpt(GdbCommand::Context &ctx);
+ void attach(int fd);
+ void detach();
+ bool isAttached() { return attached; }
- protected:
- class InputEvent : public PollEvent
- {
- protected:
- BaseRemoteGDB *gdb;
+ void replaceThreadContext(ThreadContext *_tc) { tc = _tc; }
- public:
- InputEvent(BaseRemoteGDB *g, int fd, int e);
- void process(int revent);
- };
+ bool trap(int type);
+ bool breakpoint() { return trap(SIGTRAP); }
- class TrapEvent : public Event
+ private:
+ /*
+ * Connection to the external GDB.
+ */
+ void incomingData(int revent);
+ void connectWrapper(int revent) { connect(); }
+
+ template <void (BaseRemoteGDB::*F)(int revent)>
+ class SocketEvent : public PollEvent
{
protected:
- int _type;
BaseRemoteGDB *gdb;
public:
- TrapEvent(BaseRemoteGDB *g) : gdb(g)
+ SocketEvent(BaseRemoteGDB *gdb, int fd, int e) :
+ PollEvent(fd, e), gdb(gdb)
{}
- void type(int t) { _type = t; }
- void process();
+ void process(int revent) { (gdb->*F)(revent); }
};
- friend class InputEvent;
- InputEvent *inputEvent;
- TrapEvent trapEvent;
- GDBListener *listener;
- int number;
+ typedef SocketEvent<&BaseRemoteGDB::connectWrapper> ConnectEvent;
+ typedef SocketEvent<&BaseRemoteGDB::incomingData> DataEvent;
- protected:
- // The socket commands come in through
- int fd;
-
- protected:
- bool active;
- bool attached;
+ friend ConnectEvent;
+ friend DataEvent;
- System *system;
- ThreadContext *context;
-
- protected:
- /**
- * Concrete subclasses of this abstract class represent how the
- * register values are transmitted on the wire. Usually each
- * architecture should define one subclass, but there can be more
- * if there is more than one possible wire format. For example,
- * ARM defines both AArch32GdbRegCache and AArch64GdbRegCache.
- */
- class BaseGdbRegCache
- {
- public:
+ ConnectEvent *connectEvent;
+ DataEvent *dataEvent;
- /**
- * Return the pointer to the raw bytes buffer containing the
- * register values. Each byte of this buffer is literally
- * encoded as two hex digits in the g or G RSP packet.
- */
- virtual char *data() const = 0;
-
- /**
- * Return the size of the raw buffer, in bytes
- * (i.e., half of the number of digits in the g/G packet).
- */
- virtual size_t size() const = 0;
-
- /**
- * Fill the raw buffer from the registers in the ThreadContext.
- */
- virtual void getRegs(ThreadContext*) = 0;
-
- /**
- * Set the ThreadContext's registers from the values
- * in the raw buffer.
- */
- virtual void setRegs(ThreadContext*) const = 0;
-
- /**
- * Return the name to use in places like DPRINTF.
- * Having each concrete superclass redefine this member
- * is useful in situations where the class of the regCache
- * can change on the fly.
- */
- virtual const std::string name() const = 0;
-
- BaseGdbRegCache(BaseRemoteGDB *g) : gdb(g)
- {}
- virtual ~BaseGdbRegCache()
- {}
-
- protected:
- BaseRemoteGDB *gdb;
- };
+ ListenSocket listener;
+ int _port;
- BaseGdbRegCache *regCachePtr;
+ // The socket commands come in through.
+ int fd;
- protected:
+ // Transfer data to/from GDB.
uint8_t getbyte();
void putbyte(uint8_t b);
int recv(char *data, int len);
void send(const char *data);
- protected:
- // Machine memory
- virtual bool read(Addr addr, size_t size, char *data);
- virtual bool write(Addr addr, size_t size, const char *data);
+ /*
+ * Simulator side debugger state.
+ */
+ bool active;
+ bool attached;
- template <class T> T read(Addr addr);
- template <class T> void write(Addr addr, T data);
+ System *sys;
+ ThreadContext *tc;
- public:
- BaseRemoteGDB(System *system, ThreadContext *context);
- virtual ~BaseRemoteGDB();
- virtual BaseGdbRegCache *gdbRegs() = 0;
+ BaseGdbRegCache *regCachePtr;
- void replaceThreadContext(ThreadContext *tc) { context = tc; }
+ class TrapEvent : public Event
+ {
+ protected:
+ int _type;
+ BaseRemoteGDB *gdb;
- void attach(int fd);
- void detach();
- bool isattached();
+ public:
+ TrapEvent(BaseRemoteGDB *g) : gdb(g)
+ {}
- virtual bool acc(Addr addr, size_t len) = 0;
- bool trap(int type);
- virtual bool breakpoint()
- {
- return trap(SIGTRAP);
- }
+ void type(int t) { _type = t; }
+ void process() { gdb->trap(_type); }
+ } trapEvent;
- void processSingleStepEvent();
- EventFunctionWrapper singleStepEvent;
+ /*
+ * The interface to the simulated system.
+ */
+ // Machine memory.
+ bool read(Addr addr, size_t size, char *data);
+ bool write(Addr addr, size_t size, const char *data);
+
+ template <class T> T read(Addr addr);
+ template <class T> void write(Addr addr, T data);
+
+ // Single step.
+ void singleStep();
+ EventWrapper<BaseRemoteGDB, &BaseRemoteGDB::singleStep> singleStepEvent;
void clearSingleStep();
void setSingleStep();
- PCEventQueue *getPcEventQueue();
- EventQueue *getComInstEventQueue();
-
/// Schedule an event which will be triggered "delta" instructions later.
void scheduleInstCommitEvent(Event *ev, int delta);
/// Deschedule an instruction count based event.
void descheduleInstCommitEvent(Event *ev);
- protected:
- virtual bool checkBpLen(size_t len);
+ // Breakpoints.
+ void insertSoftBreak(Addr addr, size_t len);
+ void removeSoftBreak(Addr addr, size_t len);
+ void insertHardBreak(Addr addr, size_t len);
+ void removeHardBreak(Addr addr, size_t len);
- class HardBreakpoint : public PCEvent
- {
- private:
- BaseRemoteGDB *gdb;
+ void clearTempBreakpoint(Addr &bkpt);
+ void setTempBreakpoint(Addr bkpt);
+ /*
+ * GDB commands.
+ */
+ struct GdbCommand
+ {
public:
- int refcount;
+ struct Context
+ {
+ const GdbCommand *cmd;
+ char cmd_byte;
+ int type;
+ char *data;
+ int len;
+ };
- public:
- HardBreakpoint(BaseRemoteGDB *_gdb, Addr addr);
- const std::string name() const { return gdb->name() + ".hwbkpt"; }
+ typedef bool (BaseRemoteGDB::*Func)(Context &ctx);
- virtual void process(ThreadContext *tc);
+ const char * const name;
+ const Func func;
+
+ GdbCommand(const char *_name, Func _func) : name(_name), func(_func) {}
};
- friend class HardBreakpoint;
- typedef std::map<Addr, HardBreakpoint *> break_map_t;
- typedef break_map_t::iterator break_iter_t;
- break_map_t hardBreakMap;
+ static std::map<char, GdbCommand> command_map;
- void insertSoftBreak(Addr addr, size_t len);
- void removeSoftBreak(Addr addr, size_t len);
- virtual void insertHardBreak(Addr addr, size_t len);
- void removeHardBreak(Addr addr, size_t len);
+ bool cmd_unsupported(GdbCommand::Context &ctx);
+
+ bool cmd_signal(GdbCommand::Context &ctx);
+ bool cmd_cont(GdbCommand::Context &ctx);
+ bool cmd_async_cont(GdbCommand::Context &ctx);
+ bool cmd_detach(GdbCommand::Context &ctx);
+ bool cmd_reg_r(GdbCommand::Context &ctx);
+ bool cmd_reg_w(GdbCommand::Context &ctx);
+ bool cmd_set_thread(GdbCommand::Context &ctx);
+ bool cmd_mem_r(GdbCommand::Context &ctx);
+ bool cmd_mem_w(GdbCommand::Context &ctx);
+ bool cmd_query_var(GdbCommand::Context &ctx);
+ bool cmd_step(GdbCommand::Context &ctx);
+ bool cmd_async_step(GdbCommand::Context &ctx);
+ bool cmd_clr_hw_bkpt(GdbCommand::Context &ctx);
+ bool cmd_set_hw_bkpt(GdbCommand::Context &ctx);
protected:
- void clearTempBreakpoint(Addr &bkpt);
- void setTempBreakpoint(Addr bkpt);
+ ThreadContext *context() { return tc; }
+ System *system() { return sys; }
- public:
- std::string name();
+ // To be implemented by subclasses.
+ virtual bool checkBpLen(size_t len);
+
+ virtual BaseGdbRegCache *gdbRegs() = 0;
+
+ virtual bool acc(Addr addr, size_t len) = 0;
};
template <class T>
@@ -322,38 +296,8 @@ BaseRemoteGDB::read(Addr addr)
template <class T>
inline void
BaseRemoteGDB::write(Addr addr, T data)
-{ write(addr, sizeof(T), (const char *)&data); }
-
-class GDBListener
{
- protected:
- class InputEvent : public PollEvent
- {
- protected:
- GDBListener *listener;
-
- public:
- InputEvent(GDBListener *l, int fd, int e);
- void process(int revent);
- };
-
- friend class InputEvent;
- InputEvent *inputEvent;
-
- protected:
- ListenSocket listener;
- BaseRemoteGDB *gdb;
- int port;
-
- public:
- GDBListener(BaseRemoteGDB *g, int p);
- ~GDBListener();
-
- void accept();
- void listen();
- std::string name();
-
- int getPort() const;
-};
+ write(addr, sizeof(T), (const char *)&data);
+}
#endif /* __REMOTE_GDB_H__ */