remote_gdb.hh revision 10589:5962812f80fe
19048SAli.Saidi@ARM.com/* 29048SAli.Saidi@ARM.com * Copyright (c) 2002-2005 The Regents of The University of Michigan 311077SCurtis.Dunham@arm.com * All rights reserved. 49048SAli.Saidi@ARM.com * 59048SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without 69048SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are 79048SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright 89048SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer; 99048SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright 109048SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the 119048SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution; 129048SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its 139048SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from 149048SAli.Saidi@ARM.com * this software without specific prior written permission. 159048SAli.Saidi@ARM.com * 169048SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 179048SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 189048SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 199048SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 209048SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 219048SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 229048SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 239048SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 249048SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 259048SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 269048SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 279048SAli.Saidi@ARM.com * 289048SAli.Saidi@ARM.com * Authors: Nathan Binkert 299048SAli.Saidi@ARM.com */ 309048SAli.Saidi@ARM.com 319048SAli.Saidi@ARM.com#ifndef __REMOTE_GDB_HH__ 329048SAli.Saidi@ARM.com#define __REMOTE_GDB_HH__ 339048SAli.Saidi@ARM.com 349048SAli.Saidi@ARM.com#include <sys/signal.h> 359048SAli.Saidi@ARM.com 369048SAli.Saidi@ARM.com#include <map> 379048SAli.Saidi@ARM.com 389048SAli.Saidi@ARM.com#include "arch/types.hh" 3911077SCurtis.Dunham@arm.com#include "base/pollevent.hh" 409048SAli.Saidi@ARM.com#include "base/socket.hh" 419048SAli.Saidi@ARM.com#include "cpu/pc_event.hh" 429056SAli.Saidi@ARM.com 439056SAli.Saidi@ARM.comclass System; 449056SAli.Saidi@ARM.comclass ThreadContext; 459056SAli.Saidi@ARM.com 469056SAli.Saidi@ARM.comclass GDBListener; 479056SAli.Saidi@ARM.com 489056SAli.Saidi@ARM.comenum GDBCommands 4911077SCurtis.Dunham@arm.com{ 509056SAli.Saidi@ARM.com GDBSignal = '?', // last signal 519056SAli.Saidi@ARM.com GDBSetBaud = 'b', // set baud (depracated) 5211077SCurtis.Dunham@arm.com GDBSetBreak = 'B', // set breakpoint (depracated) 5311077SCurtis.Dunham@arm.com GDBCont = 'c', // resume 5411077SCurtis.Dunham@arm.com GDBAsyncCont = 'C', // continue with signal 5511077SCurtis.Dunham@arm.com GDBDebug = 'd', // toggle debug flags (deprecated) 5611077SCurtis.Dunham@arm.com GDBDetach = 'D', // detach remote gdb 5711077SCurtis.Dunham@arm.com GDBRegR = 'g', // read general registers 5811077SCurtis.Dunham@arm.com GDBRegW = 'G', // write general registers 599056SAli.Saidi@ARM.com GDBSetThread = 'H', // set thread 609056SAli.Saidi@ARM.com GDBCycleStep = 'i', // step a single cycle 619048SAli.Saidi@ARM.com GDBSigCycleStep = 'I', // signal then cycle step 6211077SCurtis.Dunham@arm.com GDBKill = 'k', // kill program 639048SAli.Saidi@ARM.com GDBMemR = 'm', // read memory 649048SAli.Saidi@ARM.com GDBMemW = 'M', // write memory 659048SAli.Saidi@ARM.com GDBReadReg = 'p', // read register 669048SAli.Saidi@ARM.com GDBSetReg = 'P', // write register 679048SAli.Saidi@ARM.com GDBQueryVar = 'q', // query variable 689048SAli.Saidi@ARM.com GDBSetVar = 'Q', // set variable 699048SAli.Saidi@ARM.com GDBReset = 'r', // reset system. (Deprecated) 709048SAli.Saidi@ARM.com GDBStep = 's', // step 719048SAli.Saidi@ARM.com GDBAsyncStep = 'S', // signal and step 729048SAli.Saidi@ARM.com GDBThreadAlive = 'T', // find out if the thread is alive 739048SAli.Saidi@ARM.com GDBTargetExit = 'W', // target exited 7411077SCurtis.Dunham@arm.com GDBBinaryDload = 'X', // write memory 7511077SCurtis.Dunham@arm.com GDBClrHwBkpt = 'z', // remove breakpoint or watchpoint 7611077SCurtis.Dunham@arm.com GDBSetHwBkpt = 'Z' // insert breakpoint or watchpoint 7711077SCurtis.Dunham@arm.com}; 7811077SCurtis.Dunham@arm.com 7911077SCurtis.Dunham@arm.comconst char GDBStart = '$'; 8011077SCurtis.Dunham@arm.comconst char GDBEnd = '#'; 8111077SCurtis.Dunham@arm.comconst char GDBGoodP = '+'; 8211077SCurtis.Dunham@arm.comconst char GDBBadP = '-'; 8311077SCurtis.Dunham@arm.com 8411077SCurtis.Dunham@arm.comconst int GDBPacketBufLen = 1024; 8511077SCurtis.Dunham@arm.com 8611077SCurtis.Dunham@arm.comclass BaseRemoteGDB 8711077SCurtis.Dunham@arm.com{ 8811077SCurtis.Dunham@arm.com private: 8911077SCurtis.Dunham@arm.com friend void debugger(); 9011077SCurtis.Dunham@arm.com friend class GDBListener; 9111077SCurtis.Dunham@arm.com 9211077SCurtis.Dunham@arm.com //Helper functions 9311077SCurtis.Dunham@arm.com protected: 9411077SCurtis.Dunham@arm.com int digit2i(char); 9511077SCurtis.Dunham@arm.com char i2digit(int); 9611077SCurtis.Dunham@arm.com Addr hex2i(const char **); 9711077SCurtis.Dunham@arm.com //Address formats, break types, and gdb commands may change 9811077SCurtis.Dunham@arm.com //between architectures, so they're defined as virtual 9911077SCurtis.Dunham@arm.com //functions. 10011077SCurtis.Dunham@arm.com virtual void mem2hex(void *, const void *, int); 10111077SCurtis.Dunham@arm.com virtual const char * hex2mem(void *, const char *, int); 10211077SCurtis.Dunham@arm.com virtual const char * break_type(char c); 10311077SCurtis.Dunham@arm.com virtual const char * gdb_command(char cmd); 10411077SCurtis.Dunham@arm.com 10511077SCurtis.Dunham@arm.com protected: 10611077SCurtis.Dunham@arm.com class Event : public PollEvent 10711077SCurtis.Dunham@arm.com { 10811077SCurtis.Dunham@arm.com protected: 10911077SCurtis.Dunham@arm.com BaseRemoteGDB *gdb; 11011077SCurtis.Dunham@arm.com 11111077SCurtis.Dunham@arm.com public: 11211077SCurtis.Dunham@arm.com Event(BaseRemoteGDB *g, int fd, int e); 11311077SCurtis.Dunham@arm.com void process(int revent); 11411077SCurtis.Dunham@arm.com }; 11511077SCurtis.Dunham@arm.com 11611077SCurtis.Dunham@arm.com friend class Event; 11711077SCurtis.Dunham@arm.com Event *event; 11811077SCurtis.Dunham@arm.com GDBListener *listener; 11911077SCurtis.Dunham@arm.com int number; 12011077SCurtis.Dunham@arm.com 12111077SCurtis.Dunham@arm.com protected: 12211077SCurtis.Dunham@arm.com //The socket commands come in through 12311077SCurtis.Dunham@arm.com int fd; 12411077SCurtis.Dunham@arm.com 12511077SCurtis.Dunham@arm.com protected: 12611077SCurtis.Dunham@arm.com#ifdef notyet 12711077SCurtis.Dunham@arm.com label_t recover; 12811077SCurtis.Dunham@arm.com#endif 12911077SCurtis.Dunham@arm.com bool active; 1309048SAli.Saidi@ARM.com bool attached; 1319048SAli.Saidi@ARM.com 1329048SAli.Saidi@ARM.com System *system; 1339048SAli.Saidi@ARM.com ThreadContext *context; 1349048SAli.Saidi@ARM.com 1359048SAli.Saidi@ARM.com protected: 1369048SAli.Saidi@ARM.com class GdbRegCache 1379048SAli.Saidi@ARM.com { 1389048SAli.Saidi@ARM.com public: 1399048SAli.Saidi@ARM.com GdbRegCache(size_t newSize) : regs(new uint64_t[newSize]), size(newSize) 1409048SAli.Saidi@ARM.com {} 1419048SAli.Saidi@ARM.com ~GdbRegCache() 1429048SAli.Saidi@ARM.com { 1439048SAli.Saidi@ARM.com delete [] regs; 1449048SAli.Saidi@ARM.com } 1459048SAli.Saidi@ARM.com 1469048SAli.Saidi@ARM.com uint64_t * regs; 1479048SAli.Saidi@ARM.com size_t size; 1489048SAli.Saidi@ARM.com size_t bytes() { return size * sizeof(uint64_t); } 1499048SAli.Saidi@ARM.com }; 1509048SAli.Saidi@ARM.com 15111077SCurtis.Dunham@arm.com GdbRegCache gdbregs; 15211077SCurtis.Dunham@arm.com 1539048SAli.Saidi@ARM.com protected: 15411077SCurtis.Dunham@arm.com uint8_t getbyte(); 15511077SCurtis.Dunham@arm.com void putbyte(uint8_t b); 1569048SAli.Saidi@ARM.com 15711077SCurtis.Dunham@arm.com int recv(char *data, int len); 15811077SCurtis.Dunham@arm.com void send(const char *data); 15911077SCurtis.Dunham@arm.com 16011077SCurtis.Dunham@arm.com protected: 16111077SCurtis.Dunham@arm.com // Machine memory 16211077SCurtis.Dunham@arm.com virtual bool read(Addr addr, size_t size, char *data); 16311077SCurtis.Dunham@arm.com virtual bool write(Addr addr, size_t size, const char *data); 1649048SAli.Saidi@ARM.com 16511077SCurtis.Dunham@arm.com template <class T> T read(Addr addr); 16611077SCurtis.Dunham@arm.com template <class T> void write(Addr addr, T data); 16711077SCurtis.Dunham@arm.com 16811077SCurtis.Dunham@arm.com public: 16911077SCurtis.Dunham@arm.com BaseRemoteGDB(System *system, ThreadContext *context, size_t cacheSize); 17011077SCurtis.Dunham@arm.com virtual ~BaseRemoteGDB(); 1719048SAli.Saidi@ARM.com 17211077SCurtis.Dunham@arm.com void replaceThreadContext(ThreadContext *tc) { context = tc; } 17311077SCurtis.Dunham@arm.com 17411077SCurtis.Dunham@arm.com void attach(int fd); 17511077SCurtis.Dunham@arm.com void detach(); 17611077SCurtis.Dunham@arm.com bool isattached(); 17711077SCurtis.Dunham@arm.com 17811077SCurtis.Dunham@arm.com virtual bool acc(Addr addr, size_t len) = 0; 17911077SCurtis.Dunham@arm.com bool trap(int type); 1809048SAli.Saidi@ARM.com virtual bool breakpoint() 18111077SCurtis.Dunham@arm.com { 18211077SCurtis.Dunham@arm.com return trap(SIGTRAP); 18311077SCurtis.Dunham@arm.com } 18411077SCurtis.Dunham@arm.com 18511077SCurtis.Dunham@arm.com protected: 18611077SCurtis.Dunham@arm.com virtual void getregs() = 0; 18711077SCurtis.Dunham@arm.com virtual void setregs() = 0; 18811077SCurtis.Dunham@arm.com 18911077SCurtis.Dunham@arm.com virtual void clearSingleStep() = 0; 19011077SCurtis.Dunham@arm.com virtual void setSingleStep() = 0; 19111077SCurtis.Dunham@arm.com 19211077SCurtis.Dunham@arm.com PCEventQueue *getPcEventQueue(); 19311077SCurtis.Dunham@arm.com 19411077SCurtis.Dunham@arm.com protected: 19511077SCurtis.Dunham@arm.com virtual bool checkBpLen(size_t len); 19611077SCurtis.Dunham@arm.com 19711077SCurtis.Dunham@arm.com class HardBreakpoint : public PCEvent 19811077SCurtis.Dunham@arm.com { 1999048SAli.Saidi@ARM.com private: 2009048SAli.Saidi@ARM.com BaseRemoteGDB *gdb; 20111077SCurtis.Dunham@arm.com 2029048SAli.Saidi@ARM.com public: 2039048SAli.Saidi@ARM.com int refcount; 20411077SCurtis.Dunham@arm.com 2059048SAli.Saidi@ARM.com public: 2069048SAli.Saidi@ARM.com HardBreakpoint(BaseRemoteGDB *_gdb, Addr addr); 2079048SAli.Saidi@ARM.com const std::string name() const { return gdb->name() + ".hwbkpt"; } 20811077SCurtis.Dunham@arm.com 2099048SAli.Saidi@ARM.com virtual void process(ThreadContext *tc); 2109048SAli.Saidi@ARM.com }; 2119048SAli.Saidi@ARM.com friend class HardBreakpoint; 2129048SAli.Saidi@ARM.com 2139048SAli.Saidi@ARM.com typedef std::map<Addr, HardBreakpoint *> break_map_t; 2149048SAli.Saidi@ARM.com typedef break_map_t::iterator break_iter_t; 2159048SAli.Saidi@ARM.com break_map_t hardBreakMap; 2169048SAli.Saidi@ARM.com 2179048SAli.Saidi@ARM.com bool insertSoftBreak(Addr addr, size_t len); 21811077SCurtis.Dunham@arm.com bool removeSoftBreak(Addr addr, size_t len); 21911077SCurtis.Dunham@arm.com virtual bool insertHardBreak(Addr addr, size_t len); 22011077SCurtis.Dunham@arm.com bool removeHardBreak(Addr addr, size_t len); 2219048SAli.Saidi@ARM.com 2229048SAli.Saidi@ARM.com protected: 22311077SCurtis.Dunham@arm.com void clearTempBreakpoint(Addr &bkpt); 22411077SCurtis.Dunham@arm.com void setTempBreakpoint(Addr bkpt); 22511077SCurtis.Dunham@arm.com 22611077SCurtis.Dunham@arm.com public: 22711077SCurtis.Dunham@arm.com std::string name(); 22811077SCurtis.Dunham@arm.com}; 22911077SCurtis.Dunham@arm.com 23011077SCurtis.Dunham@arm.comtemplate <class T> 23111077SCurtis.Dunham@arm.cominline T 23211077SCurtis.Dunham@arm.comBaseRemoteGDB::read(Addr addr) 23311077SCurtis.Dunham@arm.com{ 23411077SCurtis.Dunham@arm.com T temp; 23511077SCurtis.Dunham@arm.com read(addr, sizeof(T), (char *)&temp); 23611077SCurtis.Dunham@arm.com return temp; 23711077SCurtis.Dunham@arm.com} 2389048SAli.Saidi@ARM.com 2399048SAli.Saidi@ARM.comtemplate <class T> 2409048SAli.Saidi@ARM.cominline void 2419048SAli.Saidi@ARM.comBaseRemoteGDB::write(Addr addr, T data) 2429048SAli.Saidi@ARM.com{ write(addr, sizeof(T), (const char *)&data); } 2439048SAli.Saidi@ARM.com 2449048SAli.Saidi@ARM.comclass GDBListener 2459048SAli.Saidi@ARM.com{ 2469048SAli.Saidi@ARM.com protected: 2479048SAli.Saidi@ARM.com class Event : public PollEvent 2489048SAli.Saidi@ARM.com { 2499048SAli.Saidi@ARM.com protected: 2509048SAli.Saidi@ARM.com GDBListener *listener; 2519048SAli.Saidi@ARM.com 2529048SAli.Saidi@ARM.com public: 2539048SAli.Saidi@ARM.com Event(GDBListener *l, int fd, int e); 2549048SAli.Saidi@ARM.com void process(int revent); 2559048SAli.Saidi@ARM.com }; 2569048SAli.Saidi@ARM.com 2579048SAli.Saidi@ARM.com friend class Event; 2589048SAli.Saidi@ARM.com Event *event; 2599048SAli.Saidi@ARM.com 2609048SAli.Saidi@ARM.com protected: 2619048SAli.Saidi@ARM.com ListenSocket listener; 2629048SAli.Saidi@ARM.com BaseRemoteGDB *gdb; 2639048SAli.Saidi@ARM.com int port; 2649048SAli.Saidi@ARM.com 2659048SAli.Saidi@ARM.com public: 2669048SAli.Saidi@ARM.com GDBListener(BaseRemoteGDB *g, int p); 267 ~GDBListener(); 268 269 void accept(); 270 void listen(); 271 std::string name(); 272}; 273 274#endif /* __REMOTE_GDB_H__ */ 275