remote_gdb.hh (12125:0066d9926c1a) | remote_gdb.hh (12449:2260f4a68210) |
---|---|
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 --- 35 unchanged lines hidden (view full) --- 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 | 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 --- 35 unchanged lines hidden (view full) --- 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 | |
54class BaseRemoteGDB; | 52class BaseRemoteGDB; |
53class HardBreakpoint; |
|
55 | 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 |
57{ 58 public: | 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 }; | |
67 | 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; |
69 | 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; |
72 | 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) |
74 {} | 99 {} |
100 virtual ~BaseGdbRegCache() 101 {} 102 103 protected: 104 BaseRemoteGDB *gdb; |
|
75}; 76 77class BaseRemoteGDB 78{ | 105}; 106 107class BaseRemoteGDB 108{ |
79 private: 80 friend void debugger(); 81 friend class GDBListener; | 109 friend class HardBreakpoint; 110 public: |
82 | 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(); |
100 | 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(); |
112 | 119 |
113 protected: 114 static std::map<char, GdbCommand> command_map; | 120 void listen(); 121 void connect(); |
115 | 122 |
116 bool cmd_unsupported(GdbCommand::Context &ctx); | 123 int port() const; |
117 | 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; } |
132 | 128 |
133 protected: 134 class InputEvent : public PollEvent 135 { 136 protected: 137 BaseRemoteGDB *gdb; | 129 void replaceThreadContext(ThreadContext *_tc) { tc = _tc; } |
138 | 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); } |
143 | 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 |
145 { 146 protected: | 143 { 144 protected: |
147 int _type; | |
148 BaseRemoteGDB *gdb; 149 150 public: | 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) |
152 {} 153 | 150 {} 151 |
154 void type(int t) { _type = t; } 155 void process(); | 152 void process(int revent) { (gdb->*F)(revent); } |
156 }; 157 | 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; |
163 | 157 |
164 protected: 165 // The socket commands come in through 166 int fd; | 158 friend ConnectEvent; 159 friend DataEvent; |
167 | 160 |
168 protected: 169 bool active; 170 bool attached; | 161 ConnectEvent *connectEvent; 162 DataEvent *dataEvent; |
171 | 163 |
172 System *system; 173 ThreadContext *context; | 164 ListenSocket listener; 165 int _port; |
174 | 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; |
186 | 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); |
193 | 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); |
199 | 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; |
204 | 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; |
210 | 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; |
218 | 187 |
219 BaseGdbRegCache(BaseRemoteGDB *g) : gdb(g) 220 {} 221 virtual ~BaseGdbRegCache() 222 {} 223 | 188 class TrapEvent : public Event 189 { |
224 protected: | 190 protected: |
191 int _type; |
|
225 BaseRemoteGDB *gdb; | 192 BaseRemoteGDB *gdb; |
226 }; | |
227 | 193 |
228 BaseGdbRegCache *regCachePtr; | 194 public: 195 TrapEvent(BaseRemoteGDB *g) : gdb(g) 196 {} |
229 | 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; |
233 | 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); |
236 | 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 | |
242 template <class T> T read(Addr addr); 243 template <class T> void write(Addr addr, T data); 244 | 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; |
249 | 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 | |
266 void clearSingleStep(); 267 void setSingleStep(); 268 | 216 void clearSingleStep(); 217 void setSingleStep(); 218 |
269 PCEventQueue *getPcEventQueue(); 270 EventQueue *getComInstEventQueue(); 271 | |
272 /// Schedule an event which will be triggered "delta" instructions later. 273 void scheduleInstCommitEvent(Event *ev, int delta); 274 /// Deschedule an instruction count based event. 275 void descheduleInstCommitEvent(Event *ev); 276 | 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); |
279 | 229 |
280 class HardBreakpoint : public PCEvent 281 { 282 private: 283 BaseRemoteGDB *gdb; | 230 void clearTempBreakpoint(Addr &bkpt); 231 void setTempBreakpoint(Addr bkpt); |
284 | 232 |
233 /* 234 * GDB commands. 235 */ 236 struct GdbCommand 237 { |
|
285 public: | 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 }; |
287 | 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); |
291 | 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) {} |
293 }; | 254 }; |
294 friend class HardBreakpoint; | |
295 | 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; |
299 | 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); |
304 | 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 |
|
305 protected: | 275 protected: |
306 void clearTempBreakpoint(Addr &bkpt); 307 void setTempBreakpoint(Addr bkpt); | 276 ThreadContext *context() { return tc; } 277 System *system() { return sys; } |
308 | 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; |
311}; 312 313template <class T> 314inline T 315BaseRemoteGDB::read(Addr addr) 316{ 317 T temp; 318 read(addr, sizeof(T), (char *)&temp); 319 return temp; 320} 321 322template <class T> 323inline void 324BaseRemoteGDB::write(Addr addr, T data) | 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 | |
328{ | 299{ |
329 protected: 330 class InputEvent : public PollEvent 331 { 332 protected: 333 GDBListener *listener; | 300 write(addr, sizeof(T), (const char *)&data); 301} |
334 | 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 | |
359#endif /* __REMOTE_GDB_H__ */ | 303#endif /* __REMOTE_GDB_H__ */ |