remote_gdb.hh revision 10598
1/* 2 * Copyright 2014 Google, Inc. 3 * Copyright (c) 2002-2005 The Regents of The University of Michigan 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer; 10 * redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution; 13 * neither the name of the copyright holders nor the names of its 14 * contributors may be used to endorse or promote products derived from 15 * this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 * Authors: Nathan Binkert 30 */ 31 32#ifndef __REMOTE_GDB_HH__ 33#define __REMOTE_GDB_HH__ 34 35#include <sys/signal.h> 36 37#include <map> 38 39#include "arch/types.hh" 40#include "base/intmath.hh" 41#include "base/pollevent.hh" 42#include "base/socket.hh" 43#include "cpu/pc_event.hh" 44 45class System; 46class ThreadContext; 47 48class GDBListener; 49 50enum GDBCommands 51{ 52 GDBSignal = '?', // last signal 53 GDBSetBaud = 'b', // set baud (depracated) 54 GDBSetBreak = 'B', // set breakpoint (depracated) 55 GDBCont = 'c', // resume 56 GDBAsyncCont = 'C', // continue with signal 57 GDBDebug = 'd', // toggle debug flags (deprecated) 58 GDBDetach = 'D', // detach remote gdb 59 GDBRegR = 'g', // read general registers 60 GDBRegW = 'G', // write general registers 61 GDBSetThread = 'H', // set thread 62 GDBCycleStep = 'i', // step a single cycle 63 GDBSigCycleStep = 'I', // signal then cycle step 64 GDBKill = 'k', // kill program 65 GDBMemR = 'm', // read memory 66 GDBMemW = 'M', // write memory 67 GDBReadReg = 'p', // read register 68 GDBSetReg = 'P', // write register 69 GDBQueryVar = 'q', // query variable 70 GDBSetVar = 'Q', // set variable 71 GDBReset = 'r', // reset system. (Deprecated) 72 GDBStep = 's', // step 73 GDBAsyncStep = 'S', // signal and step 74 GDBThreadAlive = 'T', // find out if the thread is alive 75 GDBTargetExit = 'W', // target exited 76 GDBBinaryDload = 'X', // write memory 77 GDBClrHwBkpt = 'z', // remove breakpoint or watchpoint 78 GDBSetHwBkpt = 'Z' // insert breakpoint or watchpoint 79}; 80 81const char GDBStart = '$'; 82const char GDBEnd = '#'; 83const char GDBGoodP = '+'; 84const char GDBBadP = '-'; 85 86const int GDBPacketBufLen = 1024; 87 88class BaseRemoteGDB 89{ 90 private: 91 friend void debugger(); 92 friend class GDBListener; 93 94 //Helper functions 95 protected: 96 int digit2i(char); 97 char i2digit(int); 98 Addr hex2i(const char **); 99 //Address formats, break types, and gdb commands may change 100 //between architectures, so they're defined as virtual 101 //functions. 102 virtual void mem2hex(void *, const void *, int); 103 virtual const char * hex2mem(void *, const char *, int); 104 virtual const char * break_type(char c); 105 virtual const char * gdb_command(char cmd); 106 107 protected: 108 class InputEvent : public PollEvent 109 { 110 protected: 111 BaseRemoteGDB *gdb; 112 113 public: 114 InputEvent(BaseRemoteGDB *g, int fd, int e); 115 void process(int revent); 116 }; 117 118 class TrapEvent : public Event 119 { 120 protected: 121 int _type; 122 BaseRemoteGDB *gdb; 123 124 public: 125 TrapEvent(BaseRemoteGDB *g) : gdb(g) 126 {} 127 128 void type(int t) { _type = t; } 129 void process(); 130 }; 131 132 friend class InputEvent; 133 InputEvent *inputEvent; 134 TrapEvent trapEvent; 135 GDBListener *listener; 136 int number; 137 138 protected: 139 //The socket commands come in through 140 int fd; 141 142 protected: 143#ifdef notyet 144 label_t recover; 145#endif 146 bool active; 147 bool attached; 148 149 System *system; 150 ThreadContext *context; 151 152 protected: 153 class GdbRegCache 154 { 155 public: 156 GdbRegCache(size_t newSize) : 157 regs64(new uint64_t[divCeil(newSize, sizeof(uint64_t))]), 158 size(newSize) 159 {} 160 ~GdbRegCache() 161 { 162 delete [] regs64; 163 } 164 165 union { 166 uint64_t *regs64; 167 uint32_t *regs32; 168 uint16_t *regs16; 169 uint8_t *regs8; 170 void *regs; 171 }; 172 // Size of cache in bytes. 173 size_t size; 174 size_t bytes() { return size; } 175 }; 176 177 GdbRegCache gdbregs; 178 179 protected: 180 uint8_t getbyte(); 181 void putbyte(uint8_t b); 182 183 int recv(char *data, int len); 184 void send(const char *data); 185 186 protected: 187 // Machine memory 188 virtual bool read(Addr addr, size_t size, char *data); 189 virtual bool write(Addr addr, size_t size, const char *data); 190 191 template <class T> T read(Addr addr); 192 template <class T> void write(Addr addr, T data); 193 194 public: 195 BaseRemoteGDB(System *system, ThreadContext *context, size_t cacheSize); 196 virtual ~BaseRemoteGDB(); 197 198 void replaceThreadContext(ThreadContext *tc) { context = tc; } 199 200 void attach(int fd); 201 void detach(); 202 bool isattached(); 203 204 virtual bool acc(Addr addr, size_t len) = 0; 205 bool trap(int type); 206 virtual bool breakpoint() 207 { 208 return trap(SIGTRAP); 209 } 210 211 protected: 212 virtual void getregs() = 0; 213 virtual void setregs() = 0; 214 215 virtual void clearSingleStep() = 0; 216 virtual void setSingleStep() = 0; 217 218 PCEventQueue *getPcEventQueue(); 219 220 protected: 221 virtual bool checkBpLen(size_t len); 222 223 class HardBreakpoint : public PCEvent 224 { 225 private: 226 BaseRemoteGDB *gdb; 227 228 public: 229 int refcount; 230 231 public: 232 HardBreakpoint(BaseRemoteGDB *_gdb, Addr addr); 233 const std::string name() const { return gdb->name() + ".hwbkpt"; } 234 235 virtual void process(ThreadContext *tc); 236 }; 237 friend class HardBreakpoint; 238 239 typedef std::map<Addr, HardBreakpoint *> break_map_t; 240 typedef break_map_t::iterator break_iter_t; 241 break_map_t hardBreakMap; 242 243 bool insertSoftBreak(Addr addr, size_t len); 244 bool removeSoftBreak(Addr addr, size_t len); 245 virtual bool insertHardBreak(Addr addr, size_t len); 246 bool removeHardBreak(Addr addr, size_t len); 247 248 protected: 249 void clearTempBreakpoint(Addr &bkpt); 250 void setTempBreakpoint(Addr bkpt); 251 252 public: 253 std::string name(); 254}; 255 256template <class T> 257inline T 258BaseRemoteGDB::read(Addr addr) 259{ 260 T temp; 261 read(addr, sizeof(T), (char *)&temp); 262 return temp; 263} 264 265template <class T> 266inline void 267BaseRemoteGDB::write(Addr addr, T data) 268{ write(addr, sizeof(T), (const char *)&data); } 269 270class GDBListener 271{ 272 protected: 273 class InputEvent : public PollEvent 274 { 275 protected: 276 GDBListener *listener; 277 278 public: 279 InputEvent(GDBListener *l, int fd, int e); 280 void process(int revent); 281 }; 282 283 friend class InputEvent; 284 InputEvent *inputEvent; 285 286 protected: 287 ListenSocket listener; 288 BaseRemoteGDB *gdb; 289 int port; 290 291 public: 292 GDBListener(BaseRemoteGDB *g, int p); 293 ~GDBListener(); 294 295 void accept(); 296 void listen(); 297 std::string name(); 298}; 299 300#endif /* __REMOTE_GDB_H__ */ 301