52,53d51
< class GDBListener;
<
54a53
> class HardBreakpoint;
56c55,62
< struct GdbCommand
---
> /**
> * 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
59,66d64
< struct Context
< {
< const GdbCommand *cmd;
< char cmd_byte;
< int type;
< char *data;
< int len;
< };
68c66,71
< 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;
70,71c73,77
< const char * const name;
< const Func func;
---
> /**
> * 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;
73c79,98
< GdbCommand(const char *_name, Func _func) : name(_name), func(_func)
---
> /**
> * 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)
74a100,104
> virtual ~BaseGdbRegCache()
> {}
>
> protected:
> BaseRemoteGDB *gdb;
79,81c109,110
< private:
< friend void debugger();
< friend class GDBListener;
---
> friend class HardBreakpoint;
> public:
83,99c112,116
< 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();
101,111c118
< // 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();
113,114c120,121
< protected:
< static std::map<char, GdbCommand> command_map;
---
> void listen();
> void connect();
116c123
< bool cmd_unsupported(GdbCommand::Context &ctx);
---
> int port() const;
118,131c125,127
< 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; }
133,137c129
< protected:
< class InputEvent : public PollEvent
< {
< protected:
< BaseRemoteGDB *gdb;
---
> void replaceThreadContext(ThreadContext *_tc) { tc = _tc; }
139,142c131,132
< public:
< InputEvent(BaseRemoteGDB *g, int fd, int e);
< void process(int revent);
< };
---
> bool trap(int type);
> bool breakpoint() { return trap(SIGTRAP); }
144c134,142
< 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
147d144
< int _type;
151c148,149
< TrapEvent(BaseRemoteGDB *g) : gdb(g)
---
> SocketEvent(BaseRemoteGDB *gdb, int fd, int e) :
> PollEvent(fd, e), gdb(gdb)
154,155c152
< void type(int t) { _type = t; }
< void process();
---
> void process(int revent) { (gdb->*F)(revent); }
158,162c155,156
< friend class InputEvent;
< InputEvent *inputEvent;
< TrapEvent trapEvent;
< GDBListener *listener;
< int number;
---
> typedef SocketEvent<&BaseRemoteGDB::connectWrapper> ConnectEvent;
> typedef SocketEvent<&BaseRemoteGDB::incomingData> DataEvent;
164,166c158,159
< protected:
< // The socket commands come in through
< int fd;
---
> friend ConnectEvent;
> friend DataEvent;
168,170c161,162
< protected:
< bool active;
< bool attached;
---
> ConnectEvent *connectEvent;
> DataEvent *dataEvent;
172,173c164,165
< System *system;
< ThreadContext *context;
---
> ListenSocket listener;
> int _port;
175,185c167,168
< 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:
---
> // The socket commands come in through.
> int fd;
187,192c170,172
< /**
< * 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;
---
> // Transfer data to/from GDB.
> uint8_t getbyte();
> void putbyte(uint8_t b);
194,198c174,175
< /**
< * 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;
---
> int recv(char *data, int len);
> void send(const char *data);
200,203c177,181
< /**
< * Fill the raw buffer from the registers in the ThreadContext.
< */
< virtual void getRegs(ThreadContext*) = 0;
---
> /*
> * Simulator side debugger state.
> */
> bool active;
> bool attached;
205,209c183,184
< /**
< * Set the ThreadContext's registers from the values
< * in the raw buffer.
< */
< virtual void setRegs(ThreadContext*) const = 0;
---
> System *sys;
> ThreadContext *tc;
211,217c186
< /**
< * 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 *regCachePtr;
219,223c188,189
< BaseGdbRegCache(BaseRemoteGDB *g) : gdb(g)
< {}
< virtual ~BaseGdbRegCache()
< {}
<
---
> class TrapEvent : public Event
> {
224a191
> int _type;
226d192
< };
228c194,196
< BaseGdbRegCache *regCachePtr;
---
> public:
> TrapEvent(BaseRemoteGDB *g) : gdb(g)
> {}
230,232c198,200
< protected:
< uint8_t getbyte();
< void putbyte(uint8_t b);
---
> void type(int t) { _type = t; }
> void process() { gdb->trap(_type); }
> } trapEvent;
234,235c202,207
< int recv(char *data, int len);
< void send(const char *data);
---
> /*
> * 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);
237,241d208
< protected:
< // Machine memory
< virtual bool read(Addr addr, size_t size, char *data);
< virtual bool write(Addr addr, size_t size, const char *data);
<
245,248c212,214
< public:
< BaseRemoteGDB(System *system, ThreadContext *context);
< virtual ~BaseRemoteGDB();
< virtual BaseGdbRegCache *gdbRegs() = 0;
---
> // Single step.
> void singleStep();
> EventWrapper<BaseRemoteGDB, &BaseRemoteGDB::singleStep> singleStepEvent;
250,265d215
< void replaceThreadContext(ThreadContext *tc) { context = tc; }
<
< void attach(int fd);
< void detach();
< bool isattached();
<
< virtual bool acc(Addr addr, size_t len) = 0;
< bool trap(int type);
< virtual bool breakpoint()
< {
< return trap(SIGTRAP);
< }
<
< void processSingleStepEvent();
< EventFunctionWrapper singleStepEvent;
<
269,271d218
< PCEventQueue *getPcEventQueue();
< EventQueue *getComInstEventQueue();
<
277,278c224,228
< 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);
280,283c230,231
< class HardBreakpoint : public PCEvent
< {
< private:
< BaseRemoteGDB *gdb;
---
> void clearTempBreakpoint(Addr &bkpt);
> void setTempBreakpoint(Addr bkpt);
284a233,237
> /*
> * GDB commands.
> */
> struct GdbCommand
> {
286c239,246
< int refcount;
---
> struct Context
> {
> const GdbCommand *cmd;
> char cmd_byte;
> int type;
> char *data;
> int len;
> };
288,290c248
< public:
< HardBreakpoint(BaseRemoteGDB *_gdb, Addr addr);
< const std::string name() const { return gdb->name() + ".hwbkpt"; }
---
> typedef bool (BaseRemoteGDB::*Func)(Context &ctx);
292c250,253
< virtual void process(ThreadContext *tc);
---
> const char * const name;
> const Func func;
>
> GdbCommand(const char *_name, Func _func) : name(_name), func(_func) {}
294d254
< friend class HardBreakpoint;
296,298c256
< 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;
300,303c258
< 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);
304a260,274
> 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);
>
306,307c276,277
< void clearTempBreakpoint(Addr &bkpt);
< void setTempBreakpoint(Addr bkpt);
---
> ThreadContext *context() { return tc; }
> System *system() { return sys; }
309,310c279,284
< 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;
325,327d298
< { write(addr, sizeof(T), (const char *)&data); }
<
< class GDBListener
329,333c300,301
< protected:
< class InputEvent : public PollEvent
< {
< protected:
< GDBListener *listener;
---
> write(addr, sizeof(T), (const char *)&data);
> }
335,358d302
< 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;
< };
<