1/* 2 * Copyright 2015 LabWare 3 * Copyright 2014 Google, Inc. 4 * Copyright (c) 2002-2005 The Regents of The University of Michigan 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are 9 * met: redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer; 11 * redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution; 14 * neither the name of the copyright holders nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * Authors: Nathan Binkert 31 * Boris Shingarov 32 */ 33 34#ifndef __REMOTE_GDB_HH__ 35#define __REMOTE_GDB_HH__ 36 37#include <sys/signal.h> 38 39#include <exception> 40#include <map> 41#include <string> 42 43#include "arch/types.hh" 44#include "base/intmath.hh" 45#include "base/pollevent.hh" 46#include "base/socket.hh" 47#include "cpu/pc_event.hh" 48 49class System; 50class ThreadContext; 51
|
52class GDBListener;
53
|
52class BaseRemoteGDB;
|
53class HardBreakpoint; |
54
|
56struct GdbCommand
|
55/** 56 * Concrete subclasses of this abstract class represent how the 57 * register values are transmitted on the wire. Usually each 58 * architecture should define one subclass, but there can be more 59 * if there is more than one possible wire format. For example, 60 * ARM defines both AArch32GdbRegCache and AArch64GdbRegCache. 61 */ 62class BaseGdbRegCache |
63{ 64 public:
|
59 struct Context
60 {
61 const GdbCommand *cmd;
62 char cmd_byte;
63 int type;
64 char *data;
65 int len;
66 };
|
65
|
68 typedef bool (BaseRemoteGDB::*Func)(Context &ctx);
|
66 /** 67 * Return the pointer to the raw bytes buffer containing the 68 * register values. Each byte of this buffer is literally 69 * encoded as two hex digits in the g or G RSP packet. 70 */ 71 virtual char *data() const = 0; |
72
|
70 const char * const name;
71 const Func func;
|
73 /** 74 * Return the size of the raw buffer, in bytes 75 * (i.e., half of the number of digits in the g/G packet). 76 */ 77 virtual size_t size() const = 0; |
78
|
73 GdbCommand(const char *_name, Func _func) : name(_name), func(_func)
|
79 /** 80 * Fill the raw buffer from the registers in the ThreadContext. 81 */ 82 virtual void getRegs(ThreadContext*) = 0; 83 84 /** 85 * Set the ThreadContext's registers from the values 86 * in the raw buffer. 87 */ 88 virtual void setRegs(ThreadContext*) const = 0; 89 90 /** 91 * Return the name to use in places like DPRINTF. 92 * Having each concrete superclass redefine this member 93 * is useful in situations where the class of the regCache 94 * can change on the fly. 95 */ 96 virtual const std::string name() const = 0; 97 98 BaseGdbRegCache(BaseRemoteGDB *g) : gdb(g) |
99 {}
|
100 virtual ~BaseGdbRegCache() 101 {} 102 103 protected: 104 BaseRemoteGDB *gdb; |
105}; 106 107class BaseRemoteGDB 108{
|
79 private:
80 friend void debugger();
81 friend class GDBListener;
|
109 friend class HardBreakpoint; 110 public: |
111
|
83 protected:
84 /// Exception to throw when the connection to the client is broken.
85 struct BadClient
86 {
87 const char *warning;
88 BadClient(const char *_warning=NULL) : warning(_warning)
89 {}
90 };
91 /// Exception to throw when an error needs to be reported to the client.
92 struct CmdError
93 {
94 std::string error;
95 CmdError(std::string _error) : error(_error)
96 {}
97 };
98 /// Exception to throw when something isn't supported.
99 class Unsupported {};
|
112 /* 113 * Interface to other parts of the simulator. 114 */ 115 BaseRemoteGDB(System *system, ThreadContext *context, int _port); 116 virtual ~BaseRemoteGDB(); |
117
|
101 // Helper functions
102 protected:
103 int digit2i(char);
104 char i2digit(int);
105 Addr hex2i(const char **);
106 // Address formats, break types, and gdb commands may change
107 // between architectures, so they're defined as virtual
108 // functions.
109 virtual void mem2hex(char *, const char *, int);
110 virtual const char * hex2mem(char *, const char *, int);
111 virtual const char * break_type(char c);
|
118 std::string name(); |
119
|
113 protected:
114 static std::map<char, GdbCommand> command_map;
|
120 void listen(); 121 void connect(); |
122
|
116 bool cmd_unsupported(GdbCommand::Context &ctx);
|
123 int port() const; |
124
|
118 bool cmd_signal(GdbCommand::Context &ctx);
119 bool cmd_cont(GdbCommand::Context &ctx);
120 bool cmd_async_cont(GdbCommand::Context &ctx);
121 bool cmd_detach(GdbCommand::Context &ctx);
122 bool cmd_reg_r(GdbCommand::Context &ctx);
123 bool cmd_reg_w(GdbCommand::Context &ctx);
124 bool cmd_set_thread(GdbCommand::Context &ctx);
125 bool cmd_mem_r(GdbCommand::Context &ctx);
126 bool cmd_mem_w(GdbCommand::Context &ctx);
127 bool cmd_query_var(GdbCommand::Context &ctx);
128 bool cmd_step(GdbCommand::Context &ctx);
129 bool cmd_async_step(GdbCommand::Context &ctx);
130 bool cmd_clr_hw_bkpt(GdbCommand::Context &ctx);
131 bool cmd_set_hw_bkpt(GdbCommand::Context &ctx);
|
125 void attach(int fd); 126 void detach(); 127 bool isAttached() { return attached; } |
128
|
133 protected:
134 class InputEvent : public PollEvent
135 {
136 protected:
137 BaseRemoteGDB *gdb;
|
129 void replaceThreadContext(ThreadContext *_tc) { tc = _tc; } |
130
|
139 public:
140 InputEvent(BaseRemoteGDB *g, int fd, int e);
141 void process(int revent);
142 };
|
131 bool trap(int type); 132 bool breakpoint() { return trap(SIGTRAP); } |
133
|
144 class TrapEvent : public Event
|
134 private: 135 /* 136 * Connection to the external GDB. 137 */ 138 void incomingData(int revent); 139 void connectWrapper(int revent) { connect(); } 140 141 template <void (BaseRemoteGDB::*F)(int revent)> 142 class SocketEvent : public PollEvent |
143 { 144 protected:
|
147 int _type;
|
145 BaseRemoteGDB *gdb; 146 147 public:
|
151 TrapEvent(BaseRemoteGDB *g) : gdb(g)
|
148 SocketEvent(BaseRemoteGDB *gdb, int fd, int e) : 149 PollEvent(fd, e), gdb(gdb) |
150 {} 151
|
154 void type(int t) { _type = t; }
155 void process();
|
152 void process(int revent) { (gdb->*F)(revent); } |
153 }; 154
|
158 friend class InputEvent;
159 InputEvent *inputEvent;
160 TrapEvent trapEvent;
161 GDBListener *listener;
162 int number;
|
155 typedef SocketEvent<&BaseRemoteGDB::connectWrapper> ConnectEvent; 156 typedef SocketEvent<&BaseRemoteGDB::incomingData> DataEvent; |
157
|
164 protected:
165 // The socket commands come in through
166 int fd;
|
158 friend ConnectEvent; 159 friend DataEvent; |
160
|
168 protected:
169 bool active;
170 bool attached;
|
161 ConnectEvent *connectEvent; 162 DataEvent *dataEvent; |
163
|
172 System *system;
173 ThreadContext *context;
|
164 ListenSocket listener; 165 int _port; |
166
|
175 protected:
176 /**
177 * Concrete subclasses of this abstract class represent how the
178 * register values are transmitted on the wire. Usually each
179 * architecture should define one subclass, but there can be more
180 * if there is more than one possible wire format. For example,
181 * ARM defines both AArch32GdbRegCache and AArch64GdbRegCache.
182 */
183 class BaseGdbRegCache
184 {
185 public:
|
167 // The socket commands come in through. 168 int fd; |
169
|
187 /**
188 * Return the pointer to the raw bytes buffer containing the
189 * register values. Each byte of this buffer is literally
190 * encoded as two hex digits in the g or G RSP packet.
191 */
192 virtual char *data() const = 0;
|
170 // Transfer data to/from GDB. 171 uint8_t getbyte(); 172 void putbyte(uint8_t b); |
173
|
194 /**
195 * Return the size of the raw buffer, in bytes
196 * (i.e., half of the number of digits in the g/G packet).
197 */
198 virtual size_t size() const = 0;
|
174 int recv(char *data, int len); 175 void send(const char *data); |
176
|
200 /**
201 * Fill the raw buffer from the registers in the ThreadContext.
202 */
203 virtual void getRegs(ThreadContext*) = 0;
|
177 /* 178 * Simulator side debugger state. 179 */ 180 bool active; 181 bool attached; |
182
|
205 /**
206 * Set the ThreadContext's registers from the values
207 * in the raw buffer.
208 */
209 virtual void setRegs(ThreadContext*) const = 0;
|
183 System *sys; 184 ThreadContext *tc; |
185
|
211 /**
212 * Return the name to use in places like DPRINTF.
213 * Having each concrete superclass redefine this member
214 * is useful in situations where the class of the regCache
215 * can change on the fly.
216 */
217 virtual const std::string name() const = 0;
|
186 BaseGdbRegCache *regCachePtr; |
187
|
219 BaseGdbRegCache(BaseRemoteGDB *g) : gdb(g)
220 {}
221 virtual ~BaseGdbRegCache()
222 {}
223
|
188 class TrapEvent : public Event 189 { |
190 protected:
|
191 int _type; |
192 BaseRemoteGDB *gdb;
|
226 };
|
193
|
228 BaseGdbRegCache *regCachePtr;
|
194 public: 195 TrapEvent(BaseRemoteGDB *g) : gdb(g) 196 {} |
197
|
230 protected:
231 uint8_t getbyte();
232 void putbyte(uint8_t b);
|
198 void type(int t) { _type = t; } 199 void process() { gdb->trap(_type); } 200 } trapEvent; |
201
|
234 int recv(char *data, int len);
235 void send(const char *data);
|
202 /* 203 * The interface to the simulated system. 204 */ 205 // Machine memory. 206 bool read(Addr addr, size_t size, char *data); 207 bool write(Addr addr, size_t size, const char *data); |
208
|
237 protected:
238 // Machine memory
239 virtual bool read(Addr addr, size_t size, char *data);
240 virtual bool write(Addr addr, size_t size, const char *data);
241
|
209 template <class T> T read(Addr addr); 210 template <class T> void write(Addr addr, T data); 211
|
245 public:
246 BaseRemoteGDB(System *system, ThreadContext *context);
247 virtual ~BaseRemoteGDB();
248 virtual BaseGdbRegCache *gdbRegs() = 0;
|
212 // Single step. 213 void singleStep(); 214 EventWrapper<BaseRemoteGDB, &BaseRemoteGDB::singleStep> singleStepEvent; |
215
|
250 void replaceThreadContext(ThreadContext *tc) { context = tc; }
251
252 void attach(int fd);
253 void detach();
254 bool isattached();
255
256 virtual bool acc(Addr addr, size_t len) = 0;
257 bool trap(int type);
258 virtual bool breakpoint()
259 {
260 return trap(SIGTRAP);
261 }
262
263 void processSingleStepEvent();
264 EventFunctionWrapper singleStepEvent;
265
|
216 void clearSingleStep(); 217 void setSingleStep(); 218
|
269 PCEventQueue *getPcEventQueue();
270 EventQueue *getComInstEventQueue();
271
|
219 /// Schedule an event which will be triggered "delta" instructions later. 220 void scheduleInstCommitEvent(Event *ev, int delta); 221 /// Deschedule an instruction count based event. 222 void descheduleInstCommitEvent(Event *ev); 223
|
277 protected:
278 virtual bool checkBpLen(size_t len);
|
224 // Breakpoints. 225 void insertSoftBreak(Addr addr, size_t len); 226 void removeSoftBreak(Addr addr, size_t len); 227 void insertHardBreak(Addr addr, size_t len); 228 void removeHardBreak(Addr addr, size_t len); |
229
|
280 class HardBreakpoint : public PCEvent
281 {
282 private:
283 BaseRemoteGDB *gdb;
|
230 void clearTempBreakpoint(Addr &bkpt); 231 void setTempBreakpoint(Addr bkpt); |
232
|
233 /* 234 * GDB commands. 235 */ 236 struct GdbCommand 237 { |
238 public:
|
286 int refcount;
|
239 struct Context 240 { 241 const GdbCommand *cmd; 242 char cmd_byte; 243 int type; 244 char *data; 245 int len; 246 }; |
247
|
288 public:
289 HardBreakpoint(BaseRemoteGDB *_gdb, Addr addr);
290 const std::string name() const { return gdb->name() + ".hwbkpt"; }
|
248 typedef bool (BaseRemoteGDB::*Func)(Context &ctx); |
249
|
292 virtual void process(ThreadContext *tc);
|
250 const char * const name; 251 const Func func; 252 253 GdbCommand(const char *_name, Func _func) : name(_name), func(_func) {} |
254 };
|
294 friend class HardBreakpoint;
|
255
|
296 typedef std::map<Addr, HardBreakpoint *> break_map_t;
297 typedef break_map_t::iterator break_iter_t;
298 break_map_t hardBreakMap;
|
256 static std::map<char, GdbCommand> command_map; |
257
|
300 void insertSoftBreak(Addr addr, size_t len);
301 void removeSoftBreak(Addr addr, size_t len);
302 virtual void insertHardBreak(Addr addr, size_t len);
303 void removeHardBreak(Addr addr, size_t len);
|
258 bool cmd_unsupported(GdbCommand::Context &ctx); |
259
|
260 bool cmd_signal(GdbCommand::Context &ctx); 261 bool cmd_cont(GdbCommand::Context &ctx); 262 bool cmd_async_cont(GdbCommand::Context &ctx); 263 bool cmd_detach(GdbCommand::Context &ctx); 264 bool cmd_reg_r(GdbCommand::Context &ctx); 265 bool cmd_reg_w(GdbCommand::Context &ctx); 266 bool cmd_set_thread(GdbCommand::Context &ctx); 267 bool cmd_mem_r(GdbCommand::Context &ctx); 268 bool cmd_mem_w(GdbCommand::Context &ctx); 269 bool cmd_query_var(GdbCommand::Context &ctx); 270 bool cmd_step(GdbCommand::Context &ctx); 271 bool cmd_async_step(GdbCommand::Context &ctx); 272 bool cmd_clr_hw_bkpt(GdbCommand::Context &ctx); 273 bool cmd_set_hw_bkpt(GdbCommand::Context &ctx); 274 |
275 protected:
|
306 void clearTempBreakpoint(Addr &bkpt);
307 void setTempBreakpoint(Addr bkpt);
|
276 ThreadContext *context() { return tc; } 277 System *system() { return sys; } |
278
|
309 public:
310 std::string name();
|
279 // To be implemented by subclasses. 280 virtual bool checkBpLen(size_t len); 281 282 virtual BaseGdbRegCache *gdbRegs() = 0; 283 284 virtual bool acc(Addr addr, size_t len) = 0; |
285}; 286 287template <class T> 288inline T 289BaseRemoteGDB::read(Addr addr) 290{ 291 T temp; 292 read(addr, sizeof(T), (char *)&temp); 293 return temp; 294} 295 296template <class T> 297inline void 298BaseRemoteGDB::write(Addr addr, T data)
|
325{ write(addr, sizeof(T), (const char *)&data); }
326
327class GDBListener
|
299{
|
329 protected:
330 class InputEvent : public PollEvent
331 {
332 protected:
333 GDBListener *listener;
|
300 write(addr, sizeof(T), (const char *)&data); 301} |
302
|
335 public:
336 InputEvent(GDBListener *l, int fd, int e);
337 void process(int revent);
338 };
339
340 friend class InputEvent;
341 InputEvent *inputEvent;
342
343 protected:
344 ListenSocket listener;
345 BaseRemoteGDB *gdb;
346 int port;
347
348 public:
349 GDBListener(BaseRemoteGDB *g, int p);
350 ~GDBListener();
351
352 void accept();
353 void listen();
354 std::string name();
355
356 int getPort() const;
357};
358
|
303#endif /* __REMOTE_GDB_H__ */
|