remote_gdb.hh revision 10595:25ecfc14f73f
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 Event : public PollEvent 109 { 110 protected: 111 BaseRemoteGDB *gdb; 112 113 public: 114 Event(BaseRemoteGDB *g, int fd, int e); 115 void process(int revent); 116 }; 117 118 friend class Event; 119 Event *event; 120 GDBListener *listener; 121 int number; 122 123 protected: 124 //The socket commands come in through 125 int fd; 126 127 protected: 128#ifdef notyet 129 label_t recover; 130#endif 131 bool active; 132 bool attached; 133 134 System *system; 135 ThreadContext *context; 136 137 protected: 138 class GdbRegCache 139 { 140 public: 141 GdbRegCache(size_t newSize) : 142 regs64(new uint64_t[divCeil(newSize, sizeof(uint64_t))]), 143 size(newSize) 144 {} 145 ~GdbRegCache() 146 { 147 delete [] regs64; 148 } 149 150 union { 151 uint64_t *regs64; 152 uint32_t *regs32; 153 uint16_t *regs16; 154 uint8_t *regs8; 155 void *regs; 156 }; 157 // Size of cache in bytes. 158 size_t size; 159 size_t bytes() { return size; } 160 }; 161 162 GdbRegCache gdbregs; 163 164 protected: 165 uint8_t getbyte(); 166 void putbyte(uint8_t b); 167 168 int recv(char *data, int len); 169 void send(const char *data); 170 171 protected: 172 // Machine memory 173 virtual bool read(Addr addr, size_t size, char *data); 174 virtual bool write(Addr addr, size_t size, const char *data); 175 176 template <class T> T read(Addr addr); 177 template <class T> void write(Addr addr, T data); 178 179 public: 180 BaseRemoteGDB(System *system, ThreadContext *context, size_t cacheSize); 181 virtual ~BaseRemoteGDB(); 182 183 void replaceThreadContext(ThreadContext *tc) { context = tc; } 184 185 void attach(int fd); 186 void detach(); 187 bool isattached(); 188 189 virtual bool acc(Addr addr, size_t len) = 0; 190 bool trap(int type); 191 virtual bool breakpoint() 192 { 193 return trap(SIGTRAP); 194 } 195 196 protected: 197 virtual void getregs() = 0; 198 virtual void setregs() = 0; 199 200 virtual void clearSingleStep() = 0; 201 virtual void setSingleStep() = 0; 202 203 PCEventQueue *getPcEventQueue(); 204 205 protected: 206 virtual bool checkBpLen(size_t len); 207 208 class HardBreakpoint : public PCEvent 209 { 210 private: 211 BaseRemoteGDB *gdb; 212 213 public: 214 int refcount; 215 216 public: 217 HardBreakpoint(BaseRemoteGDB *_gdb, Addr addr); 218 const std::string name() const { return gdb->name() + ".hwbkpt"; } 219 220 virtual void process(ThreadContext *tc); 221 }; 222 friend class HardBreakpoint; 223 224 typedef std::map<Addr, HardBreakpoint *> break_map_t; 225 typedef break_map_t::iterator break_iter_t; 226 break_map_t hardBreakMap; 227 228 bool insertSoftBreak(Addr addr, size_t len); 229 bool removeSoftBreak(Addr addr, size_t len); 230 virtual bool insertHardBreak(Addr addr, size_t len); 231 bool removeHardBreak(Addr addr, size_t len); 232 233 protected: 234 void clearTempBreakpoint(Addr &bkpt); 235 void setTempBreakpoint(Addr bkpt); 236 237 public: 238 std::string name(); 239}; 240 241template <class T> 242inline T 243BaseRemoteGDB::read(Addr addr) 244{ 245 T temp; 246 read(addr, sizeof(T), (char *)&temp); 247 return temp; 248} 249 250template <class T> 251inline void 252BaseRemoteGDB::write(Addr addr, T data) 253{ write(addr, sizeof(T), (const char *)&data); } 254 255class GDBListener 256{ 257 protected: 258 class Event : public PollEvent 259 { 260 protected: 261 GDBListener *listener; 262 263 public: 264 Event(GDBListener *l, int fd, int e); 265 void process(int revent); 266 }; 267 268 friend class Event; 269 Event *event; 270 271 protected: 272 ListenSocket listener; 273 BaseRemoteGDB *gdb; 274 int port; 275 276 public: 277 GDBListener(BaseRemoteGDB *g, int p); 278 ~GDBListener(); 279 280 void accept(); 281 void listen(); 282 std::string name(); 283}; 284 285#endif /* __REMOTE_GDB_H__ */ 286