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