remote_gdb.hh revision 10597
12SN/A/* 210595Sgabeblack@google.com * Copyright 2014 Google, Inc. 31762SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 42SN/A * All rights reserved. 52SN/A * 62SN/A * Redistribution and use in source and binary forms, with or without 72SN/A * modification, are permitted provided that the following conditions are 82SN/A * met: redistributions of source code must retain the above copyright 92SN/A * notice, this list of conditions and the following disclaimer; 102SN/A * redistributions in binary form must reproduce the above copyright 112SN/A * notice, this list of conditions and the following disclaimer in the 122SN/A * documentation and/or other materials provided with the distribution; 132SN/A * neither the name of the copyright holders nor the names of its 142SN/A * contributors may be used to endorse or promote products derived from 152SN/A * this software without specific prior written permission. 162SN/A * 172SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 182SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 192SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 202SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 212SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 222SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 232SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 242SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 252SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 262SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 272SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 282665Ssaidi@eecs.umich.edu * 292665Ssaidi@eecs.umich.edu * Authors: Nathan Binkert 302SN/A */ 312SN/A 322SN/A#ifndef __REMOTE_GDB_HH__ 332SN/A#define __REMOTE_GDB_HH__ 342SN/A 353960Sgblack@eecs.umich.edu#include <sys/signal.h> 3677SN/A 378229Snate@binkert.org#include <map> 388229Snate@binkert.org 392986Sgblack@eecs.umich.edu#include "arch/types.hh" 4010595Sgabeblack@google.com#include "base/intmath.hh" 4156SN/A#include "base/pollevent.hh" 4256SN/A#include "base/socket.hh" 438229Snate@binkert.org#include "cpu/pc_event.hh" 442SN/A 452SN/Aclass System; 462680Sktlim@umich.educlass ThreadContext; 472SN/A 481910SN/Aclass GDBListener; 493536Sgblack@eecs.umich.edu 503536Sgblack@eecs.umich.eduenum GDBCommands 512SN/A{ 523536Sgblack@eecs.umich.edu GDBSignal = '?', // last signal 533536Sgblack@eecs.umich.edu GDBSetBaud = 'b', // set baud (depracated) 543536Sgblack@eecs.umich.edu GDBSetBreak = 'B', // set breakpoint (depracated) 553536Sgblack@eecs.umich.edu GDBCont = 'c', // resume 563536Sgblack@eecs.umich.edu GDBAsyncCont = 'C', // continue with signal 573536Sgblack@eecs.umich.edu GDBDebug = 'd', // toggle debug flags (deprecated) 583536Sgblack@eecs.umich.edu GDBDetach = 'D', // detach remote gdb 593536Sgblack@eecs.umich.edu GDBRegR = 'g', // read general registers 603536Sgblack@eecs.umich.edu GDBRegW = 'G', // write general registers 613536Sgblack@eecs.umich.edu GDBSetThread = 'H', // set thread 623536Sgblack@eecs.umich.edu GDBCycleStep = 'i', // step a single cycle 633536Sgblack@eecs.umich.edu GDBSigCycleStep = 'I', // signal then cycle step 643536Sgblack@eecs.umich.edu GDBKill = 'k', // kill program 653536Sgblack@eecs.umich.edu GDBMemR = 'm', // read memory 663536Sgblack@eecs.umich.edu GDBMemW = 'M', // write memory 673536Sgblack@eecs.umich.edu GDBReadReg = 'p', // read register 683536Sgblack@eecs.umich.edu GDBSetReg = 'P', // write register 693536Sgblack@eecs.umich.edu GDBQueryVar = 'q', // query variable 703536Sgblack@eecs.umich.edu GDBSetVar = 'Q', // set variable 713536Sgblack@eecs.umich.edu GDBReset = 'r', // reset system. (Deprecated) 723536Sgblack@eecs.umich.edu GDBStep = 's', // step 733536Sgblack@eecs.umich.edu GDBAsyncStep = 'S', // signal and step 743536Sgblack@eecs.umich.edu GDBThreadAlive = 'T', // find out if the thread is alive 753536Sgblack@eecs.umich.edu GDBTargetExit = 'W', // target exited 763536Sgblack@eecs.umich.edu GDBBinaryDload = 'X', // write memory 773536Sgblack@eecs.umich.edu GDBClrHwBkpt = 'z', // remove breakpoint or watchpoint 783536Sgblack@eecs.umich.edu GDBSetHwBkpt = 'Z' // insert breakpoint or watchpoint 793536Sgblack@eecs.umich.edu}; 803536Sgblack@eecs.umich.edu 813536Sgblack@eecs.umich.educonst char GDBStart = '$'; 823536Sgblack@eecs.umich.educonst char GDBEnd = '#'; 833536Sgblack@eecs.umich.educonst char GDBGoodP = '+'; 843536Sgblack@eecs.umich.educonst char GDBBadP = '-'; 853536Sgblack@eecs.umich.edu 863536Sgblack@eecs.umich.educonst int GDBPacketBufLen = 1024; 873536Sgblack@eecs.umich.edu 883536Sgblack@eecs.umich.educlass BaseRemoteGDB 893536Sgblack@eecs.umich.edu{ 901910SN/A private: 911910SN/A friend void debugger(); 921910SN/A friend class GDBListener; 931910SN/A 943536Sgblack@eecs.umich.edu //Helper functions 953536Sgblack@eecs.umich.edu protected: 963536Sgblack@eecs.umich.edu int digit2i(char); 973536Sgblack@eecs.umich.edu char i2digit(int); 983536Sgblack@eecs.umich.edu Addr hex2i(const char **); 993536Sgblack@eecs.umich.edu //Address formats, break types, and gdb commands may change 1003536Sgblack@eecs.umich.edu //between architectures, so they're defined as virtual 1013536Sgblack@eecs.umich.edu //functions. 1023536Sgblack@eecs.umich.edu virtual void mem2hex(void *, const void *, int); 1033536Sgblack@eecs.umich.edu virtual const char * hex2mem(void *, const char *, int); 1043536Sgblack@eecs.umich.edu virtual const char * break_type(char c); 1053536Sgblack@eecs.umich.edu virtual const char * gdb_command(char cmd); 1063536Sgblack@eecs.umich.edu 1072SN/A protected: 1082SN/A class Event : public PollEvent 1092SN/A { 1102SN/A protected: 1113536Sgblack@eecs.umich.edu BaseRemoteGDB *gdb; 1122SN/A 1132SN/A public: 1143536Sgblack@eecs.umich.edu Event(BaseRemoteGDB *g, int fd, int e); 1152SN/A void process(int revent); 1162SN/A }; 1172SN/A 11810597Sgabeblack@google.com class TrapEvent : public ::Event 11910597Sgabeblack@google.com { 12010597Sgabeblack@google.com protected: 12110597Sgabeblack@google.com int _type; 12210597Sgabeblack@google.com BaseRemoteGDB *gdb; 12310597Sgabeblack@google.com 12410597Sgabeblack@google.com public: 12510597Sgabeblack@google.com TrapEvent(BaseRemoteGDB *g) : gdb(g) 12610597Sgabeblack@google.com {} 12710597Sgabeblack@google.com 12810597Sgabeblack@google.com void type(int t) { _type = t; } 12910597Sgabeblack@google.com void process(); 13010597Sgabeblack@google.com }; 13110597Sgabeblack@google.com 1322SN/A friend class Event; 1332SN/A Event *event; 13410597Sgabeblack@google.com TrapEvent trapEvent; 1351910SN/A GDBListener *listener; 1361910SN/A int number; 1372SN/A 1382SN/A protected: 1393536Sgblack@eecs.umich.edu //The socket commands come in through 1402SN/A int fd; 1412SN/A 1422SN/A protected: 1432SN/A#ifdef notyet 1442SN/A label_t recover; 1452SN/A#endif 1462SN/A bool active; 1472SN/A bool attached; 1482SN/A 1492SN/A System *system; 1502680Sktlim@umich.edu ThreadContext *context; 1512SN/A 1522SN/A protected: 1533536Sgblack@eecs.umich.edu class GdbRegCache 1543536Sgblack@eecs.umich.edu { 1553536Sgblack@eecs.umich.edu public: 15610595Sgabeblack@google.com GdbRegCache(size_t newSize) : 15710595Sgabeblack@google.com regs64(new uint64_t[divCeil(newSize, sizeof(uint64_t))]), 15810595Sgabeblack@google.com size(newSize) 1593536Sgblack@eecs.umich.edu {} 1603536Sgblack@eecs.umich.edu ~GdbRegCache() 1613536Sgblack@eecs.umich.edu { 16210595Sgabeblack@google.com delete [] regs64; 1633536Sgblack@eecs.umich.edu } 1643536Sgblack@eecs.umich.edu 16510595Sgabeblack@google.com union { 16610595Sgabeblack@google.com uint64_t *regs64; 16710595Sgabeblack@google.com uint32_t *regs32; 16810595Sgabeblack@google.com uint16_t *regs16; 16910595Sgabeblack@google.com uint8_t *regs8; 17010595Sgabeblack@google.com void *regs; 17110595Sgabeblack@google.com }; 17210595Sgabeblack@google.com // Size of cache in bytes. 1733536Sgblack@eecs.umich.edu size_t size; 17410595Sgabeblack@google.com size_t bytes() { return size; } 1753536Sgblack@eecs.umich.edu }; 1763536Sgblack@eecs.umich.edu 1773536Sgblack@eecs.umich.edu GdbRegCache gdbregs; 1783536Sgblack@eecs.umich.edu 1793536Sgblack@eecs.umich.edu protected: 1802SN/A uint8_t getbyte(); 1812SN/A void putbyte(uint8_t b); 1822SN/A 1832SN/A int recv(char *data, int len); 1842SN/A void send(const char *data); 1852SN/A 1862SN/A protected: 1872SN/A // Machine memory 1883536Sgblack@eecs.umich.edu virtual bool read(Addr addr, size_t size, char *data); 1893536Sgblack@eecs.umich.edu virtual bool write(Addr addr, size_t size, const char *data); 1902SN/A 1912SN/A template <class T> T read(Addr addr); 1922SN/A template <class T> void write(Addr addr, T data); 1932SN/A 1942SN/A public: 1953536Sgblack@eecs.umich.edu BaseRemoteGDB(System *system, ThreadContext *context, size_t cacheSize); 1963536Sgblack@eecs.umich.edu virtual ~BaseRemoteGDB(); 1972SN/A 1982680Sktlim@umich.edu void replaceThreadContext(ThreadContext *tc) { context = tc; } 199180SN/A 2002SN/A void attach(int fd); 2012SN/A void detach(); 2022SN/A bool isattached(); 2032SN/A 2043536Sgblack@eecs.umich.edu virtual bool acc(Addr addr, size_t len) = 0; 2052SN/A bool trap(int type); 2063960Sgblack@eecs.umich.edu virtual bool breakpoint() 2073960Sgblack@eecs.umich.edu { 2083960Sgblack@eecs.umich.edu return trap(SIGTRAP); 2093960Sgblack@eecs.umich.edu } 2102SN/A 2112SN/A protected: 2123536Sgblack@eecs.umich.edu virtual void getregs() = 0; 2133536Sgblack@eecs.umich.edu virtual void setregs() = 0; 2142SN/A 2153536Sgblack@eecs.umich.edu virtual void clearSingleStep() = 0; 2163536Sgblack@eecs.umich.edu virtual void setSingleStep() = 0; 2172SN/A 2182SN/A PCEventQueue *getPcEventQueue(); 2192SN/A 2202SN/A protected: 22110589Sgabeblack@google.com virtual bool checkBpLen(size_t len); 22210589Sgabeblack@google.com 2232SN/A class HardBreakpoint : public PCEvent 2242SN/A { 2252SN/A private: 2263536Sgblack@eecs.umich.edu BaseRemoteGDB *gdb; 2272SN/A 2282SN/A public: 229507SN/A int refcount; 230507SN/A 231507SN/A public: 2323536Sgblack@eecs.umich.edu HardBreakpoint(BaseRemoteGDB *_gdb, Addr addr); 2338737Skoansin.tan@gmail.com const std::string name() const { return gdb->name() + ".hwbkpt"; } 2342SN/A 2352680Sktlim@umich.edu virtual void process(ThreadContext *tc); 2362SN/A }; 2372SN/A friend class HardBreakpoint; 2382SN/A 2392SN/A typedef std::map<Addr, HardBreakpoint *> break_map_t; 2402SN/A typedef break_map_t::iterator break_iter_t; 2412SN/A break_map_t hardBreakMap; 2422SN/A 2432SN/A bool insertSoftBreak(Addr addr, size_t len); 2442SN/A bool removeSoftBreak(Addr addr, size_t len); 2458700Ssteve.reinhardt@amd.com virtual bool insertHardBreak(Addr addr, size_t len); 2462SN/A bool removeHardBreak(Addr addr, size_t len); 2472SN/A 2483550Sgblack@eecs.umich.edu protected: 2493550Sgblack@eecs.umich.edu void clearTempBreakpoint(Addr &bkpt); 2503550Sgblack@eecs.umich.edu void setTempBreakpoint(Addr bkpt); 2513550Sgblack@eecs.umich.edu 252507SN/A public: 253507SN/A std::string name(); 2542SN/A}; 2552SN/A 2562SN/Atemplate <class T> 2572SN/Ainline T 2583536Sgblack@eecs.umich.eduBaseRemoteGDB::read(Addr addr) 2592SN/A{ 2602SN/A T temp; 2612SN/A read(addr, sizeof(T), (char *)&temp); 2622SN/A return temp; 2632SN/A} 2642SN/A 2652SN/Atemplate <class T> 2662SN/Ainline void 2673536Sgblack@eecs.umich.eduBaseRemoteGDB::write(Addr addr, T data) 2682SN/A{ write(addr, sizeof(T), (const char *)&data); } 2692SN/A 2702SN/Aclass GDBListener 2712SN/A{ 2722SN/A protected: 2732SN/A class Event : public PollEvent 2742SN/A { 2752SN/A protected: 2762SN/A GDBListener *listener; 2772SN/A 2782SN/A public: 2792SN/A Event(GDBListener *l, int fd, int e); 2802SN/A void process(int revent); 2812SN/A }; 2822SN/A 2832SN/A friend class Event; 2842SN/A Event *event; 2852SN/A 2862SN/A protected: 2872SN/A ListenSocket listener; 2883536Sgblack@eecs.umich.edu BaseRemoteGDB *gdb; 2892SN/A int port; 2902SN/A 2912SN/A public: 2923536Sgblack@eecs.umich.edu GDBListener(BaseRemoteGDB *g, int p); 2932SN/A ~GDBListener(); 2942SN/A 2952SN/A void accept(); 2962SN/A void listen(); 297507SN/A std::string name(); 2982SN/A}; 2992SN/A 3002SN/A#endif /* __REMOTE_GDB_H__ */ 301