remote_gdb.hh revision 11274
12SN/A/* 211274Sshingarov@labware.com * Copyright 2015 LabWare 310595Sgabeblack@google.com * Copyright 2014 Google, Inc. 41762SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 52SN/A * All rights reserved. 62SN/A * 72SN/A * Redistribution and use in source and binary forms, with or without 82SN/A * modification, are permitted provided that the following conditions are 92SN/A * met: redistributions of source code must retain the above copyright 102SN/A * notice, this list of conditions and the following disclaimer; 112SN/A * redistributions in binary form must reproduce the above copyright 122SN/A * notice, this list of conditions and the following disclaimer in the 132SN/A * documentation and/or other materials provided with the distribution; 142SN/A * neither the name of the copyright holders nor the names of its 152SN/A * contributors may be used to endorse or promote products derived from 162SN/A * this software without specific prior written permission. 172SN/A * 182SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 192SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 202SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 212SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 222SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 232SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 242SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 252SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 262SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 272SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 282SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 292665Ssaidi@eecs.umich.edu * 302665Ssaidi@eecs.umich.edu * Authors: Nathan Binkert 3111274Sshingarov@labware.com * Boris Shingarov 322SN/A */ 332SN/A 342SN/A#ifndef __REMOTE_GDB_HH__ 352SN/A#define __REMOTE_GDB_HH__ 362SN/A 373960Sgblack@eecs.umich.edu#include <sys/signal.h> 3877SN/A 398229Snate@binkert.org#include <map> 408229Snate@binkert.org 412986Sgblack@eecs.umich.edu#include "arch/types.hh" 4210595Sgabeblack@google.com#include "base/intmath.hh" 4356SN/A#include "base/pollevent.hh" 4456SN/A#include "base/socket.hh" 458229Snate@binkert.org#include "cpu/pc_event.hh" 462SN/A 472SN/Aclass System; 482680Sktlim@umich.educlass ThreadContext; 492SN/A 501910SN/Aclass GDBListener; 513536Sgblack@eecs.umich.edu 523536Sgblack@eecs.umich.eduenum GDBCommands 532SN/A{ 543536Sgblack@eecs.umich.edu GDBSignal = '?', // last signal 553536Sgblack@eecs.umich.edu GDBSetBaud = 'b', // set baud (depracated) 563536Sgblack@eecs.umich.edu GDBSetBreak = 'B', // set breakpoint (depracated) 573536Sgblack@eecs.umich.edu GDBCont = 'c', // resume 583536Sgblack@eecs.umich.edu GDBAsyncCont = 'C', // continue with signal 593536Sgblack@eecs.umich.edu GDBDebug = 'd', // toggle debug flags (deprecated) 603536Sgblack@eecs.umich.edu GDBDetach = 'D', // detach remote gdb 613536Sgblack@eecs.umich.edu GDBRegR = 'g', // read general registers 623536Sgblack@eecs.umich.edu GDBRegW = 'G', // write general registers 633536Sgblack@eecs.umich.edu GDBSetThread = 'H', // set thread 643536Sgblack@eecs.umich.edu GDBCycleStep = 'i', // step a single cycle 653536Sgblack@eecs.umich.edu GDBSigCycleStep = 'I', // signal then cycle step 663536Sgblack@eecs.umich.edu GDBKill = 'k', // kill program 673536Sgblack@eecs.umich.edu GDBMemR = 'm', // read memory 683536Sgblack@eecs.umich.edu GDBMemW = 'M', // write memory 693536Sgblack@eecs.umich.edu GDBReadReg = 'p', // read register 703536Sgblack@eecs.umich.edu GDBSetReg = 'P', // write register 713536Sgblack@eecs.umich.edu GDBQueryVar = 'q', // query variable 723536Sgblack@eecs.umich.edu GDBSetVar = 'Q', // set variable 733536Sgblack@eecs.umich.edu GDBReset = 'r', // reset system. (Deprecated) 743536Sgblack@eecs.umich.edu GDBStep = 's', // step 753536Sgblack@eecs.umich.edu GDBAsyncStep = 'S', // signal and step 763536Sgblack@eecs.umich.edu GDBThreadAlive = 'T', // find out if the thread is alive 773536Sgblack@eecs.umich.edu GDBTargetExit = 'W', // target exited 783536Sgblack@eecs.umich.edu GDBBinaryDload = 'X', // write memory 793536Sgblack@eecs.umich.edu GDBClrHwBkpt = 'z', // remove breakpoint or watchpoint 803536Sgblack@eecs.umich.edu GDBSetHwBkpt = 'Z' // insert breakpoint or watchpoint 813536Sgblack@eecs.umich.edu}; 823536Sgblack@eecs.umich.edu 833536Sgblack@eecs.umich.educonst char GDBStart = '$'; 843536Sgblack@eecs.umich.educonst char GDBEnd = '#'; 853536Sgblack@eecs.umich.educonst char GDBGoodP = '+'; 863536Sgblack@eecs.umich.educonst char GDBBadP = '-'; 873536Sgblack@eecs.umich.edu 883536Sgblack@eecs.umich.educonst int GDBPacketBufLen = 1024; 893536Sgblack@eecs.umich.edu 903536Sgblack@eecs.umich.educlass BaseRemoteGDB 913536Sgblack@eecs.umich.edu{ 921910SN/A private: 931910SN/A friend void debugger(); 941910SN/A friend class GDBListener; 951910SN/A 963536Sgblack@eecs.umich.edu //Helper functions 973536Sgblack@eecs.umich.edu protected: 983536Sgblack@eecs.umich.edu int digit2i(char); 993536Sgblack@eecs.umich.edu char i2digit(int); 1003536Sgblack@eecs.umich.edu Addr hex2i(const char **); 1013536Sgblack@eecs.umich.edu //Address formats, break types, and gdb commands may change 1023536Sgblack@eecs.umich.edu //between architectures, so they're defined as virtual 1033536Sgblack@eecs.umich.edu //functions. 10411274Sshingarov@labware.com virtual void mem2hex(char *, const char *, int); 10511274Sshingarov@labware.com virtual const char * hex2mem(char *, const char *, int); 1063536Sgblack@eecs.umich.edu virtual const char * break_type(char c); 1073536Sgblack@eecs.umich.edu virtual const char * gdb_command(char cmd); 1083536Sgblack@eecs.umich.edu 1092SN/A protected: 11010598Sgabeblack@google.com class InputEvent : public PollEvent 1112SN/A { 1122SN/A protected: 1133536Sgblack@eecs.umich.edu BaseRemoteGDB *gdb; 1142SN/A 1152SN/A public: 11610598Sgabeblack@google.com InputEvent(BaseRemoteGDB *g, int fd, int e); 1172SN/A void process(int revent); 1182SN/A }; 1192SN/A 12010598Sgabeblack@google.com class TrapEvent : public Event 12110597Sgabeblack@google.com { 12210597Sgabeblack@google.com protected: 12310597Sgabeblack@google.com int _type; 12410597Sgabeblack@google.com BaseRemoteGDB *gdb; 12510597Sgabeblack@google.com 12610597Sgabeblack@google.com public: 12710597Sgabeblack@google.com TrapEvent(BaseRemoteGDB *g) : gdb(g) 12810597Sgabeblack@google.com {} 12910597Sgabeblack@google.com 13010597Sgabeblack@google.com void type(int t) { _type = t; } 13110597Sgabeblack@google.com void process(); 13210597Sgabeblack@google.com }; 13310597Sgabeblack@google.com 13410598Sgabeblack@google.com friend class InputEvent; 13510598Sgabeblack@google.com InputEvent *inputEvent; 13610597Sgabeblack@google.com TrapEvent trapEvent; 1371910SN/A GDBListener *listener; 1381910SN/A int number; 1392SN/A 1402SN/A protected: 1413536Sgblack@eecs.umich.edu //The socket commands come in through 1422SN/A int fd; 1432SN/A 1442SN/A protected: 1452SN/A#ifdef notyet 1462SN/A label_t recover; 1472SN/A#endif 1482SN/A bool active; 1492SN/A bool attached; 1502SN/A 1512SN/A System *system; 1522680Sktlim@umich.edu ThreadContext *context; 1532SN/A 1542SN/A protected: 15511274Sshingarov@labware.com /** 15611274Sshingarov@labware.com * Concrete subclasses of this abstract class represent how the 15711274Sshingarov@labware.com * register values are transmitted on the wire. Usually each 15811274Sshingarov@labware.com * architecture should define one subclass, but there can be more 15911274Sshingarov@labware.com * if there is more than one possible wire format. For example, 16011274Sshingarov@labware.com * ARM defines both AArch32GdbRegCache and AArch64GdbRegCache. 16111274Sshingarov@labware.com */ 16211274Sshingarov@labware.com class BaseGdbRegCache 1633536Sgblack@eecs.umich.edu { 1643536Sgblack@eecs.umich.edu public: 16511274Sshingarov@labware.com 16611274Sshingarov@labware.com /** 16711274Sshingarov@labware.com * Return the pointer to the raw bytes buffer containing the 16811274Sshingarov@labware.com * register values. Each byte of this buffer is literally 16911274Sshingarov@labware.com * encoded as two hex digits in the g or G RSP packet. 17011274Sshingarov@labware.com */ 17111274Sshingarov@labware.com virtual char *data() const = 0; 17211274Sshingarov@labware.com 17311274Sshingarov@labware.com /** 17411274Sshingarov@labware.com * Return the size of the raw buffer, in bytes 17511274Sshingarov@labware.com * (i.e., half of the number of digits in the g/G packet). 17611274Sshingarov@labware.com */ 17711274Sshingarov@labware.com virtual size_t size() const = 0; 17811274Sshingarov@labware.com 17911274Sshingarov@labware.com /** 18011274Sshingarov@labware.com * Fill the raw buffer from the registers in the ThreadContext. 18111274Sshingarov@labware.com */ 18211274Sshingarov@labware.com virtual void getRegs(ThreadContext*) = 0; 18311274Sshingarov@labware.com 18411274Sshingarov@labware.com /** 18511274Sshingarov@labware.com * Set the ThreadContext's registers from the values 18611274Sshingarov@labware.com * in the raw buffer. 18711274Sshingarov@labware.com */ 18811274Sshingarov@labware.com virtual void setRegs(ThreadContext*) const = 0; 18911274Sshingarov@labware.com 19011274Sshingarov@labware.com /** 19111274Sshingarov@labware.com * Return the name to use in places like DPRINTF. 19211274Sshingarov@labware.com * Having each concrete superclass redefine this member 19311274Sshingarov@labware.com * is useful in situations where the class of the regCache 19411274Sshingarov@labware.com * can change on the fly. 19511274Sshingarov@labware.com */ 19611274Sshingarov@labware.com virtual const std::string name() const = 0; 19711274Sshingarov@labware.com 19811274Sshingarov@labware.com BaseGdbRegCache(BaseRemoteGDB *g) : gdb(g) 1993536Sgblack@eecs.umich.edu {} 2003536Sgblack@eecs.umich.edu 20111274Sshingarov@labware.com protected: 20211274Sshingarov@labware.com BaseRemoteGDB *gdb; 2033536Sgblack@eecs.umich.edu }; 2043536Sgblack@eecs.umich.edu 2053536Sgblack@eecs.umich.edu protected: 2062SN/A uint8_t getbyte(); 2072SN/A void putbyte(uint8_t b); 2082SN/A 2092SN/A int recv(char *data, int len); 2102SN/A void send(const char *data); 2112SN/A 2122SN/A protected: 2132SN/A // Machine memory 2143536Sgblack@eecs.umich.edu virtual bool read(Addr addr, size_t size, char *data); 2153536Sgblack@eecs.umich.edu virtual bool write(Addr addr, size_t size, const char *data); 2162SN/A 2172SN/A template <class T> T read(Addr addr); 2182SN/A template <class T> void write(Addr addr, T data); 2192SN/A 2202SN/A public: 22111274Sshingarov@labware.com BaseRemoteGDB(System *system, ThreadContext *context); 2223536Sgblack@eecs.umich.edu virtual ~BaseRemoteGDB(); 22311274Sshingarov@labware.com virtual BaseGdbRegCache *gdbRegs() = 0; 2242SN/A 2252680Sktlim@umich.edu void replaceThreadContext(ThreadContext *tc) { context = tc; } 226180SN/A 2272SN/A void attach(int fd); 2282SN/A void detach(); 2292SN/A bool isattached(); 2302SN/A 2313536Sgblack@eecs.umich.edu virtual bool acc(Addr addr, size_t len) = 0; 2322SN/A bool trap(int type); 2333960Sgblack@eecs.umich.edu virtual bool breakpoint() 2343960Sgblack@eecs.umich.edu { 2353960Sgblack@eecs.umich.edu return trap(SIGTRAP); 2363960Sgblack@eecs.umich.edu } 2372SN/A 2382SN/A protected: 23910601Sgabeblack@google.com class SingleStepEvent : public Event 24010601Sgabeblack@google.com { 24110601Sgabeblack@google.com protected: 24210601Sgabeblack@google.com BaseRemoteGDB *gdb; 24310601Sgabeblack@google.com 24410601Sgabeblack@google.com public: 24510601Sgabeblack@google.com SingleStepEvent(BaseRemoteGDB *g) : gdb(g) 24610601Sgabeblack@google.com {} 24710601Sgabeblack@google.com 24810601Sgabeblack@google.com void process(); 24910601Sgabeblack@google.com }; 25010601Sgabeblack@google.com 25110601Sgabeblack@google.com SingleStepEvent singleStepEvent; 25210601Sgabeblack@google.com 25310601Sgabeblack@google.com void clearSingleStep(); 25410601Sgabeblack@google.com void setSingleStep(); 2552SN/A 2562SN/A PCEventQueue *getPcEventQueue(); 25710599Sgabeblack@google.com EventQueue *getComInstEventQueue(); 25810599Sgabeblack@google.com 25910599Sgabeblack@google.com /// Schedule an event which will be triggered "delta" instructions later. 26010599Sgabeblack@google.com void scheduleInstCommitEvent(Event *ev, int delta); 26110599Sgabeblack@google.com /// Deschedule an instruction count based event. 26210599Sgabeblack@google.com void descheduleInstCommitEvent(Event *ev); 2632SN/A 2642SN/A protected: 26510589Sgabeblack@google.com virtual bool checkBpLen(size_t len); 26610589Sgabeblack@google.com 2672SN/A class HardBreakpoint : public PCEvent 2682SN/A { 2692SN/A private: 2703536Sgblack@eecs.umich.edu BaseRemoteGDB *gdb; 2712SN/A 2722SN/A public: 273507SN/A int refcount; 274507SN/A 275507SN/A public: 2763536Sgblack@eecs.umich.edu HardBreakpoint(BaseRemoteGDB *_gdb, Addr addr); 2778737Skoansin.tan@gmail.com const std::string name() const { return gdb->name() + ".hwbkpt"; } 2782SN/A 2792680Sktlim@umich.edu virtual void process(ThreadContext *tc); 2802SN/A }; 2812SN/A friend class HardBreakpoint; 2822SN/A 2832SN/A typedef std::map<Addr, HardBreakpoint *> break_map_t; 2842SN/A typedef break_map_t::iterator break_iter_t; 2852SN/A break_map_t hardBreakMap; 2862SN/A 2872SN/A bool insertSoftBreak(Addr addr, size_t len); 2882SN/A bool removeSoftBreak(Addr addr, size_t len); 2898700Ssteve.reinhardt@amd.com virtual bool insertHardBreak(Addr addr, size_t len); 2902SN/A bool removeHardBreak(Addr addr, size_t len); 2912SN/A 2923550Sgblack@eecs.umich.edu protected: 2933550Sgblack@eecs.umich.edu void clearTempBreakpoint(Addr &bkpt); 2943550Sgblack@eecs.umich.edu void setTempBreakpoint(Addr bkpt); 2953550Sgblack@eecs.umich.edu 296507SN/A public: 297507SN/A std::string name(); 2982SN/A}; 2992SN/A 3002SN/Atemplate <class T> 3012SN/Ainline T 3023536Sgblack@eecs.umich.eduBaseRemoteGDB::read(Addr addr) 3032SN/A{ 3042SN/A T temp; 3052SN/A read(addr, sizeof(T), (char *)&temp); 3062SN/A return temp; 3072SN/A} 3082SN/A 3092SN/Atemplate <class T> 3102SN/Ainline void 3113536Sgblack@eecs.umich.eduBaseRemoteGDB::write(Addr addr, T data) 3122SN/A{ write(addr, sizeof(T), (const char *)&data); } 3132SN/A 3142SN/Aclass GDBListener 3152SN/A{ 3162SN/A protected: 31710598Sgabeblack@google.com class InputEvent : public PollEvent 3182SN/A { 3192SN/A protected: 3202SN/A GDBListener *listener; 3212SN/A 3222SN/A public: 32310598Sgabeblack@google.com InputEvent(GDBListener *l, int fd, int e); 3242SN/A void process(int revent); 3252SN/A }; 3262SN/A 32710598Sgabeblack@google.com friend class InputEvent; 32810598Sgabeblack@google.com InputEvent *inputEvent; 3292SN/A 3302SN/A protected: 3312SN/A ListenSocket listener; 3323536Sgblack@eecs.umich.edu BaseRemoteGDB *gdb; 3332SN/A int port; 3342SN/A 3352SN/A public: 3363536Sgblack@eecs.umich.edu GDBListener(BaseRemoteGDB *g, int p); 3372SN/A ~GDBListener(); 3382SN/A 3392SN/A void accept(); 3402SN/A void listen(); 341507SN/A std::string name(); 3422SN/A}; 3432SN/A 3442SN/A#endif /* __REMOTE_GDB_H__ */ 345