remote_gdb.hh revision 10599
12SN/A/* 21762SN/A * Copyright 2014 Google, Inc. 32SN/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 272665Ssaidi@eecs.umich.edu * 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 321112SN/A#ifndef __REMOTE_GDB_HH__ 331112SN/A#define __REMOTE_GDB_HH__ 342SN/A 353386Sgblack@eecs.umich.edu#include <sys/signal.h> 362SN/A 372SN/A#include <map> 382SN/A 392SN/A#include "arch/types.hh" 402SN/A#include "base/intmath.hh" 412SN/A#include "base/pollevent.hh" 422SN/A#include "base/socket.hh" 432SN/A#include "cpu/pc_event.hh" 442SN/A 452SN/Aclass System; 462SN/Aclass ThreadContext; 474070Ssaidi@eecs.umich.edu 482SN/Aclass GDBListener; 492SN/A 502SN/Aenum GDBCommands 512SN/A{ 522SN/A GDBSignal = '?', // last signal 532SN/A GDBSetBaud = 'b', // set baud (depracated) 542SN/A GDBSetBreak = 'B', // set breakpoint (depracated) 552SN/A GDBCont = 'c', // resume 562SN/A GDBAsyncCont = 'C', // continue with signal 572SN/A GDBDebug = 'd', // toggle debug flags (deprecated) 582SN/A GDBDetach = 'D', // detach remote gdb 592SN/A GDBRegR = 'g', // read general registers 602SN/A GDBRegW = 'G', // write general registers 612SN/A GDBSetThread = 'H', // set thread 623814Ssaidi@eecs.umich.edu GDBCycleStep = 'i', // step a single cycle 633814Ssaidi@eecs.umich.edu GDBSigCycleStep = 'I', // signal then cycle step 643814Ssaidi@eecs.umich.edu GDBKill = 'k', // kill program 653814Ssaidi@eecs.umich.edu GDBMemR = 'm', // read memory 663814Ssaidi@eecs.umich.edu GDBMemW = 'M', // write memory 673814Ssaidi@eecs.umich.edu GDBReadReg = 'p', // read register 683814Ssaidi@eecs.umich.edu GDBSetReg = 'P', // write register 693814Ssaidi@eecs.umich.edu GDBQueryVar = 'q', // query variable 703814Ssaidi@eecs.umich.edu GDBSetVar = 'Q', // set variable 713814Ssaidi@eecs.umich.edu GDBReset = 'r', // reset system. (Deprecated) 723814Ssaidi@eecs.umich.edu GDBStep = 's', // step 734070Ssaidi@eecs.umich.edu GDBAsyncStep = 'S', // signal and step 744070Ssaidi@eecs.umich.edu GDBThreadAlive = 'T', // find out if the thread is alive 754070Ssaidi@eecs.umich.edu GDBTargetExit = 'W', // target exited 764070Ssaidi@eecs.umich.edu GDBBinaryDload = 'X', // write memory 774070Ssaidi@eecs.umich.edu GDBClrHwBkpt = 'z', // remove breakpoint or watchpoint 784070Ssaidi@eecs.umich.edu GDBSetHwBkpt = 'Z' // insert breakpoint or watchpoint 793814Ssaidi@eecs.umich.edu}; 802SN/A 812SN/Aconst char GDBStart = '$'; 822SN/Aconst char GDBEnd = '#'; 832SN/Aconst char GDBGoodP = '+'; 842SN/Aconst char GDBBadP = '-'; 852SN/A 862SN/Aconst int GDBPacketBufLen = 1024; 872SN/A 882SN/Aclass BaseRemoteGDB 892SN/A{ 902SN/A private: 913422Sgblack@eecs.umich.edu friend void debugger(); 923422Sgblack@eecs.umich.edu friend class GDBListener; 933422Sgblack@eecs.umich.edu 943422Sgblack@eecs.umich.edu //Helper functions 953422Sgblack@eecs.umich.edu protected: 963422Sgblack@eecs.umich.edu int digit2i(char); 973422Sgblack@eecs.umich.edu char i2digit(int); 983422Sgblack@eecs.umich.edu Addr hex2i(const char **); 993422Sgblack@eecs.umich.edu //Address formats, break types, and gdb commands may change 1003422Sgblack@eecs.umich.edu //between architectures, so they're defined as virtual 1013422Sgblack@eecs.umich.edu //functions. 1023422Sgblack@eecs.umich.edu virtual void mem2hex(void *, const void *, int); 1033422Sgblack@eecs.umich.edu virtual const char * hex2mem(void *, const char *, int); 1043422Sgblack@eecs.umich.edu virtual const char * break_type(char c); 1053422Sgblack@eecs.umich.edu virtual const char * gdb_command(char cmd); 1063422Sgblack@eecs.umich.edu 1073422Sgblack@eecs.umich.edu protected: 1083422Sgblack@eecs.umich.edu class InputEvent : public PollEvent 1093422Sgblack@eecs.umich.edu { 1103422Sgblack@eecs.umich.edu protected: 1113422Sgblack@eecs.umich.edu BaseRemoteGDB *gdb; 1123422Sgblack@eecs.umich.edu 1133422Sgblack@eecs.umich.edu public: 1143422Sgblack@eecs.umich.edu InputEvent(BaseRemoteGDB *g, int fd, int e); 1154103Ssaidi@eecs.umich.edu void process(int revent); 1164103Ssaidi@eecs.umich.edu }; 1174103Ssaidi@eecs.umich.edu 1184103Ssaidi@eecs.umich.edu class TrapEvent : public Event 1194103Ssaidi@eecs.umich.edu { 1204103Ssaidi@eecs.umich.edu protected: 1214103Ssaidi@eecs.umich.edu int _type; 1224103Ssaidi@eecs.umich.edu BaseRemoteGDB *gdb; 1234103Ssaidi@eecs.umich.edu 1244244Ssaidi@eecs.umich.edu public: 1254244Ssaidi@eecs.umich.edu TrapEvent(BaseRemoteGDB *g) : gdb(g) 1264244Ssaidi@eecs.umich.edu {} 1274244Ssaidi@eecs.umich.edu 1284244Ssaidi@eecs.umich.edu void type(int t) { _type = t; } 1294244Ssaidi@eecs.umich.edu void process(); 1304103Ssaidi@eecs.umich.edu }; 1314103Ssaidi@eecs.umich.edu 1324103Ssaidi@eecs.umich.edu friend class InputEvent; 1334259Sgblack@eecs.umich.edu InputEvent *inputEvent; 1344259Sgblack@eecs.umich.edu TrapEvent trapEvent; 1354259Sgblack@eecs.umich.edu GDBListener *listener; 1364259Sgblack@eecs.umich.edu int number; 1374259Sgblack@eecs.umich.edu 1384259Sgblack@eecs.umich.edu protected: 1394259Sgblack@eecs.umich.edu //The socket commands come in through 1404259Sgblack@eecs.umich.edu int fd; 1414259Sgblack@eecs.umich.edu 1424259Sgblack@eecs.umich.edu protected: 1434258Sgblack@eecs.umich.edu#ifdef notyet 1444257Sgblack@eecs.umich.edu label_t recover; 1454259Sgblack@eecs.umich.edu#endif 1464259Sgblack@eecs.umich.edu bool active; 1474259Sgblack@eecs.umich.edu bool attached; 1484258Sgblack@eecs.umich.edu 1494258Sgblack@eecs.umich.edu System *system; 1504258Sgblack@eecs.umich.edu ThreadContext *context; 1514258Sgblack@eecs.umich.edu 1524258Sgblack@eecs.umich.edu protected: 1534103Ssaidi@eecs.umich.edu class GdbRegCache 1544259Sgblack@eecs.umich.edu { 1554259Sgblack@eecs.umich.edu public: 1564259Sgblack@eecs.umich.edu GdbRegCache(size_t newSize) : 1574259Sgblack@eecs.umich.edu regs64(new uint64_t[divCeil(newSize, sizeof(uint64_t))]), 1584258Sgblack@eecs.umich.edu size(newSize) 1594258Sgblack@eecs.umich.edu {} 1604258Sgblack@eecs.umich.edu ~GdbRegCache() 1614258Sgblack@eecs.umich.edu { 1624258Sgblack@eecs.umich.edu delete [] regs64; 1634258Sgblack@eecs.umich.edu } 1644259Sgblack@eecs.umich.edu 1654258Sgblack@eecs.umich.edu union { 1664258Sgblack@eecs.umich.edu uint64_t *regs64; 1674258Sgblack@eecs.umich.edu uint32_t *regs32; 1684258Sgblack@eecs.umich.edu uint16_t *regs16; 1694258Sgblack@eecs.umich.edu uint8_t *regs8; 1704258Sgblack@eecs.umich.edu void *regs; 1714258Sgblack@eecs.umich.edu }; 1724259Sgblack@eecs.umich.edu // Size of cache in bytes. 1734259Sgblack@eecs.umich.edu size_t size; 1744261Sgblack@eecs.umich.edu size_t bytes() { return size; } 1754258Sgblack@eecs.umich.edu }; 1764258Sgblack@eecs.umich.edu 1774257Sgblack@eecs.umich.edu GdbRegCache gdbregs; 1784261Sgblack@eecs.umich.edu 1794261Sgblack@eecs.umich.edu protected: 1804261Sgblack@eecs.umich.edu uint8_t getbyte(); 1814261Sgblack@eecs.umich.edu void putbyte(uint8_t b); 1824258Sgblack@eecs.umich.edu 1834258Sgblack@eecs.umich.edu int recv(char *data, int len); 1844258Sgblack@eecs.umich.edu void send(const char *data); 1854258Sgblack@eecs.umich.edu 1864258Sgblack@eecs.umich.edu protected: 1874258Sgblack@eecs.umich.edu // Machine memory 1884257Sgblack@eecs.umich.edu virtual bool read(Addr addr, size_t size, char *data); 1894259Sgblack@eecs.umich.edu virtual bool write(Addr addr, size_t size, const char *data); 1904258Sgblack@eecs.umich.edu 1914258Sgblack@eecs.umich.edu template <class T> T read(Addr addr); 1924257Sgblack@eecs.umich.edu template <class T> void write(Addr addr, T data); 1934261Sgblack@eecs.umich.edu 1944261Sgblack@eecs.umich.edu public: 1954261Sgblack@eecs.umich.edu BaseRemoteGDB(System *system, ThreadContext *context, size_t cacheSize); 1964258Sgblack@eecs.umich.edu virtual ~BaseRemoteGDB(); 1974260Sgblack@eecs.umich.edu 1984258Sgblack@eecs.umich.edu void replaceThreadContext(ThreadContext *tc) { context = tc; } 1994258Sgblack@eecs.umich.edu 2004258Sgblack@eecs.umich.edu void attach(int fd); 2014258Sgblack@eecs.umich.edu void detach(); 2024258Sgblack@eecs.umich.edu bool isattached(); 2034257Sgblack@eecs.umich.edu 2044259Sgblack@eecs.umich.edu virtual bool acc(Addr addr, size_t len) = 0; 2054259Sgblack@eecs.umich.edu bool trap(int type); 2064258Sgblack@eecs.umich.edu virtual bool breakpoint() 2074258Sgblack@eecs.umich.edu { 2084258Sgblack@eecs.umich.edu return trap(SIGTRAP); 2094258Sgblack@eecs.umich.edu } 2104258Sgblack@eecs.umich.edu 2114258Sgblack@eecs.umich.edu protected: 2124258Sgblack@eecs.umich.edu virtual void getregs() = 0; 2134258Sgblack@eecs.umich.edu virtual void setregs() = 0; 2144257Sgblack@eecs.umich.edu 2154258Sgblack@eecs.umich.edu virtual void clearSingleStep() = 0; 2164260Sgblack@eecs.umich.edu virtual void setSingleStep() = 0; 2174258Sgblack@eecs.umich.edu 2184258Sgblack@eecs.umich.edu PCEventQueue *getPcEventQueue(); 2194258Sgblack@eecs.umich.edu EventQueue *getComInstEventQueue(); 2204258Sgblack@eecs.umich.edu 2214258Sgblack@eecs.umich.edu /// Schedule an event which will be triggered "delta" instructions later. 2224258Sgblack@eecs.umich.edu void scheduleInstCommitEvent(Event *ev, int delta); 2234259Sgblack@eecs.umich.edu /// Deschedule an instruction count based event. 2244259Sgblack@eecs.umich.edu void descheduleInstCommitEvent(Event *ev); 2254259Sgblack@eecs.umich.edu 2264259Sgblack@eecs.umich.edu protected: 2274259Sgblack@eecs.umich.edu virtual bool checkBpLen(size_t len); 2284259Sgblack@eecs.umich.edu 2294258Sgblack@eecs.umich.edu class HardBreakpoint : public PCEvent 2304258Sgblack@eecs.umich.edu { 2314257Sgblack@eecs.umich.edu private: 2324258Sgblack@eecs.umich.edu BaseRemoteGDB *gdb; 2334258Sgblack@eecs.umich.edu 2344258Sgblack@eecs.umich.edu public: 2354258Sgblack@eecs.umich.edu int refcount; 2364258Sgblack@eecs.umich.edu 2374257Sgblack@eecs.umich.edu public: 2384258Sgblack@eecs.umich.edu HardBreakpoint(BaseRemoteGDB *_gdb, Addr addr); 2394260Sgblack@eecs.umich.edu const std::string name() const { return gdb->name() + ".hwbkpt"; } 2404258Sgblack@eecs.umich.edu 2414258Sgblack@eecs.umich.edu virtual void process(ThreadContext *tc); 2424258Sgblack@eecs.umich.edu }; 2434257Sgblack@eecs.umich.edu friend class HardBreakpoint; 2444258Sgblack@eecs.umich.edu 2454260Sgblack@eecs.umich.edu typedef std::map<Addr, HardBreakpoint *> break_map_t; 2464258Sgblack@eecs.umich.edu typedef break_map_t::iterator break_iter_t; 2474258Sgblack@eecs.umich.edu break_map_t hardBreakMap; 2484258Sgblack@eecs.umich.edu 2494257Sgblack@eecs.umich.edu bool insertSoftBreak(Addr addr, size_t len); 2504258Sgblack@eecs.umich.edu bool removeSoftBreak(Addr addr, size_t len); 2514260Sgblack@eecs.umich.edu virtual bool insertHardBreak(Addr addr, size_t len); 2524258Sgblack@eecs.umich.edu bool removeHardBreak(Addr addr, size_t len); 2534258Sgblack@eecs.umich.edu 2544258Sgblack@eecs.umich.edu protected: 2554258Sgblack@eecs.umich.edu void clearTempBreakpoint(Addr &bkpt); 2564258Sgblack@eecs.umich.edu void setTempBreakpoint(Addr bkpt); 2574257Sgblack@eecs.umich.edu 2584259Sgblack@eecs.umich.edu public: 2594259Sgblack@eecs.umich.edu std::string name(); 2604259Sgblack@eecs.umich.edu}; 2614259Sgblack@eecs.umich.edu 2624259Sgblack@eecs.umich.edutemplate <class T> 2634259Sgblack@eecs.umich.eduinline T 2644259Sgblack@eecs.umich.eduBaseRemoteGDB::read(Addr addr) 2654259Sgblack@eecs.umich.edu{ 2664259Sgblack@eecs.umich.edu T temp; 2674259Sgblack@eecs.umich.edu read(addr, sizeof(T), (char *)&temp); 2684259Sgblack@eecs.umich.edu return temp; 2694259Sgblack@eecs.umich.edu} 2704259Sgblack@eecs.umich.edu 2714259Sgblack@eecs.umich.edutemplate <class T> 2724259Sgblack@eecs.umich.eduinline void 2734257Sgblack@eecs.umich.eduBaseRemoteGDB::write(Addr addr, T data) 2744258Sgblack@eecs.umich.edu{ write(addr, sizeof(T), (const char *)&data); } 2754258Sgblack@eecs.umich.edu 2764258Sgblack@eecs.umich.educlass GDBListener 2774258Sgblack@eecs.umich.edu{ 2784258Sgblack@eecs.umich.edu protected: 2794257Sgblack@eecs.umich.edu class InputEvent : public PollEvent 2804257Sgblack@eecs.umich.edu { 2814257Sgblack@eecs.umich.edu protected: 2824257Sgblack@eecs.umich.edu GDBListener *listener; 2834257Sgblack@eecs.umich.edu 2844259Sgblack@eecs.umich.edu public: 2854259Sgblack@eecs.umich.edu InputEvent(GDBListener *l, int fd, int e); 2864259Sgblack@eecs.umich.edu void process(int revent); 2874259Sgblack@eecs.umich.edu }; 2884257Sgblack@eecs.umich.edu 2894257Sgblack@eecs.umich.edu friend class InputEvent; 2904257Sgblack@eecs.umich.edu InputEvent *inputEvent; 2914258Sgblack@eecs.umich.edu 2924258Sgblack@eecs.umich.edu protected: 2934258Sgblack@eecs.umich.edu ListenSocket listener; 2944257Sgblack@eecs.umich.edu BaseRemoteGDB *gdb; 2954259Sgblack@eecs.umich.edu int port; 2964259Sgblack@eecs.umich.edu 2974259Sgblack@eecs.umich.edu public: 2984259Sgblack@eecs.umich.edu GDBListener(BaseRemoteGDB *g, int p); 2994259Sgblack@eecs.umich.edu ~GDBListener(); 3004259Sgblack@eecs.umich.edu 3014259Sgblack@eecs.umich.edu void accept(); 3024257Sgblack@eecs.umich.edu void listen(); 3034257Sgblack@eecs.umich.edu std::string name(); 3044257Sgblack@eecs.umich.edu}; 3054257Sgblack@eecs.umich.edu 3064257Sgblack@eecs.umich.edu#endif /* __REMOTE_GDB_H__ */ 3074257Sgblack@eecs.umich.edu