remote_gdb.hh revision 11274:d9a0136ab8cc
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 <map> 40 41#include "arch/types.hh" 42#include "base/intmath.hh" 43#include "base/pollevent.hh" 44#include "base/socket.hh" 45#include "cpu/pc_event.hh" 46 47class System; 48class ThreadContext; 49 50class GDBListener; 51 52enum GDBCommands 53{ 54 GDBSignal = '?', // last signal 55 GDBSetBaud = 'b', // set baud (depracated) 56 GDBSetBreak = 'B', // set breakpoint (depracated) 57 GDBCont = 'c', // resume 58 GDBAsyncCont = 'C', // continue with signal 59 GDBDebug = 'd', // toggle debug flags (deprecated) 60 GDBDetach = 'D', // detach remote gdb 61 GDBRegR = 'g', // read general registers 62 GDBRegW = 'G', // write general registers 63 GDBSetThread = 'H', // set thread 64 GDBCycleStep = 'i', // step a single cycle 65 GDBSigCycleStep = 'I', // signal then cycle step 66 GDBKill = 'k', // kill program 67 GDBMemR = 'm', // read memory 68 GDBMemW = 'M', // write memory 69 GDBReadReg = 'p', // read register 70 GDBSetReg = 'P', // write register 71 GDBQueryVar = 'q', // query variable 72 GDBSetVar = 'Q', // set variable 73 GDBReset = 'r', // reset system. (Deprecated) 74 GDBStep = 's', // step 75 GDBAsyncStep = 'S', // signal and step 76 GDBThreadAlive = 'T', // find out if the thread is alive 77 GDBTargetExit = 'W', // target exited 78 GDBBinaryDload = 'X', // write memory 79 GDBClrHwBkpt = 'z', // remove breakpoint or watchpoint 80 GDBSetHwBkpt = 'Z' // insert breakpoint or watchpoint 81}; 82 83const char GDBStart = '$'; 84const char GDBEnd = '#'; 85const char GDBGoodP = '+'; 86const char GDBBadP = '-'; 87 88const int GDBPacketBufLen = 1024; 89 90class BaseRemoteGDB 91{ 92 private: 93 friend void debugger(); 94 friend class GDBListener; 95 96 //Helper functions 97 protected: 98 int digit2i(char); 99 char i2digit(int); 100 Addr hex2i(const char **); 101 //Address formats, break types, and gdb commands may change 102 //between architectures, so they're defined as virtual 103 //functions. 104 virtual void mem2hex(char *, const char *, int); 105 virtual const char * hex2mem(char *, const char *, int); 106 virtual const char * break_type(char c); 107 virtual const char * gdb_command(char cmd); 108 109 protected: 110 class InputEvent : public PollEvent 111 { 112 protected: 113 BaseRemoteGDB *gdb; 114 115 public: 116 InputEvent(BaseRemoteGDB *g, int fd, int e); 117 void process(int revent); 118 }; 119 120 class TrapEvent : public Event 121 { 122 protected: 123 int _type; 124 BaseRemoteGDB *gdb; 125 126 public: 127 TrapEvent(BaseRemoteGDB *g) : gdb(g) 128 {} 129 130 void type(int t) { _type = t; } 131 void process(); 132 }; 133 134 friend class InputEvent; 135 InputEvent *inputEvent; 136 TrapEvent trapEvent; 137 GDBListener *listener; 138 int number; 139 140 protected: 141 //The socket commands come in through 142 int fd; 143 144 protected: 145#ifdef notyet 146 label_t recover; 147#endif 148 bool active; 149 bool attached; 150 151 System *system; 152 ThreadContext *context; 153 154 protected: 155 /** 156 * Concrete subclasses of this abstract class represent how the 157 * register values are transmitted on the wire. Usually each 158 * architecture should define one subclass, but there can be more 159 * if there is more than one possible wire format. For example, 160 * ARM defines both AArch32GdbRegCache and AArch64GdbRegCache. 161 */ 162 class BaseGdbRegCache 163 { 164 public: 165 166 /** 167 * Return the pointer to the raw bytes buffer containing the 168 * register values. Each byte of this buffer is literally 169 * encoded as two hex digits in the g or G RSP packet. 170 */ 171 virtual char *data() const = 0; 172 173 /** 174 * Return the size of the raw buffer, in bytes 175 * (i.e., half of the number of digits in the g/G packet). 176 */ 177 virtual size_t size() const = 0; 178 179 /** 180 * Fill the raw buffer from the registers in the ThreadContext. 181 */ 182 virtual void getRegs(ThreadContext*) = 0; 183 184 /** 185 * Set the ThreadContext's registers from the values 186 * in the raw buffer. 187 */ 188 virtual void setRegs(ThreadContext*) const = 0; 189 190 /** 191 * Return the name to use in places like DPRINTF. 192 * Having each concrete superclass redefine this member 193 * is useful in situations where the class of the regCache 194 * can change on the fly. 195 */ 196 virtual const std::string name() const = 0; 197 198 BaseGdbRegCache(BaseRemoteGDB *g) : gdb(g) 199 {} 200 201 protected: 202 BaseRemoteGDB *gdb; 203 }; 204 205 protected: 206 uint8_t getbyte(); 207 void putbyte(uint8_t b); 208 209 int recv(char *data, int len); 210 void send(const char *data); 211 212 protected: 213 // Machine memory 214 virtual bool read(Addr addr, size_t size, char *data); 215 virtual bool write(Addr addr, size_t size, const char *data); 216 217 template <class T> T read(Addr addr); 218 template <class T> void write(Addr addr, T data); 219 220 public: 221 BaseRemoteGDB(System *system, ThreadContext *context); 222 virtual ~BaseRemoteGDB(); 223 virtual BaseGdbRegCache *gdbRegs() = 0; 224 225 void replaceThreadContext(ThreadContext *tc) { context = tc; } 226 227 void attach(int fd); 228 void detach(); 229 bool isattached(); 230 231 virtual bool acc(Addr addr, size_t len) = 0; 232 bool trap(int type); 233 virtual bool breakpoint() 234 { 235 return trap(SIGTRAP); 236 } 237 238 protected: 239 class SingleStepEvent : public Event 240 { 241 protected: 242 BaseRemoteGDB *gdb; 243 244 public: 245 SingleStepEvent(BaseRemoteGDB *g) : gdb(g) 246 {} 247 248 void process(); 249 }; 250 251 SingleStepEvent singleStepEvent; 252 253 void clearSingleStep(); 254 void setSingleStep(); 255 256 PCEventQueue *getPcEventQueue(); 257 EventQueue *getComInstEventQueue(); 258 259 /// Schedule an event which will be triggered "delta" instructions later. 260 void scheduleInstCommitEvent(Event *ev, int delta); 261 /// Deschedule an instruction count based event. 262 void descheduleInstCommitEvent(Event *ev); 263 264 protected: 265 virtual bool checkBpLen(size_t len); 266 267 class HardBreakpoint : public PCEvent 268 { 269 private: 270 BaseRemoteGDB *gdb; 271 272 public: 273 int refcount; 274 275 public: 276 HardBreakpoint(BaseRemoteGDB *_gdb, Addr addr); 277 const std::string name() const { return gdb->name() + ".hwbkpt"; } 278 279 virtual void process(ThreadContext *tc); 280 }; 281 friend class HardBreakpoint; 282 283 typedef std::map<Addr, HardBreakpoint *> break_map_t; 284 typedef break_map_t::iterator break_iter_t; 285 break_map_t hardBreakMap; 286 287 bool insertSoftBreak(Addr addr, size_t len); 288 bool removeSoftBreak(Addr addr, size_t len); 289 virtual bool insertHardBreak(Addr addr, size_t len); 290 bool removeHardBreak(Addr addr, size_t len); 291 292 protected: 293 void clearTempBreakpoint(Addr &bkpt); 294 void setTempBreakpoint(Addr bkpt); 295 296 public: 297 std::string name(); 298}; 299 300template <class T> 301inline T 302BaseRemoteGDB::read(Addr addr) 303{ 304 T temp; 305 read(addr, sizeof(T), (char *)&temp); 306 return temp; 307} 308 309template <class T> 310inline void 311BaseRemoteGDB::write(Addr addr, T data) 312{ write(addr, sizeof(T), (const char *)&data); } 313 314class GDBListener 315{ 316 protected: 317 class InputEvent : public PollEvent 318 { 319 protected: 320 GDBListener *listener; 321 322 public: 323 InputEvent(GDBListener *l, int fd, int e); 324 void process(int revent); 325 }; 326 327 friend class InputEvent; 328 InputEvent *inputEvent; 329 330 protected: 331 ListenSocket listener; 332 BaseRemoteGDB *gdb; 333 int port; 334 335 public: 336 GDBListener(BaseRemoteGDB *g, int p); 337 ~GDBListener(); 338 339 void accept(); 340 void listen(); 341 std::string name(); 342}; 343 344#endif /* __REMOTE_GDB_H__ */ 345