remote_gdb.hh revision 10589
12623SN/A/*
210596Sgabeblack@google.com * Copyright (c) 2002-2005 The Regents of The University of Michigan
312276Sanouk.vanlaer@arm.com * All rights reserved.
47725SAli.Saidi@ARM.com *
57725SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without
67725SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are
77725SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright
87725SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer;
97725SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright
107725SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the
117725SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution;
127725SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its
137725SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from
147725SAli.Saidi@ARM.com * this software without specific prior written permission.
152623SN/A *
162623SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172623SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182623SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192623SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202623SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212623SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222623SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232623SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242623SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252623SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262623SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272623SN/A *
282623SN/A * Authors: Nathan Binkert
292623SN/A */
302623SN/A
312623SN/A#ifndef __REMOTE_GDB_HH__
322623SN/A#define __REMOTE_GDB_HH__
332623SN/A
342623SN/A#include <sys/signal.h>
352623SN/A
362623SN/A#include <map>
372623SN/A
382623SN/A#include "arch/types.hh"
392623SN/A#include "base/pollevent.hh"
402665Ssaidi@eecs.umich.edu#include "base/socket.hh"
412665Ssaidi@eecs.umich.edu#include "cpu/pc_event.hh"
422623SN/A
432623SN/Aclass System;
4411793Sbrandon.potter@amd.comclass ThreadContext;
4511793Sbrandon.potter@amd.com
463170Sstever@eecs.umich.educlass GDBListener;
478105Sgblack@eecs.umich.edu
482623SN/Aenum GDBCommands
496658Snate@binkert.org{
502623SN/A    GDBSignal              = '?', // last signal
518232Snate@binkert.org    GDBSetBaud             = 'b', // set baud (depracated)
529152Satgutier@umich.edu    GDBSetBreak            = 'B', // set breakpoint (depracated)
538232Snate@binkert.org    GDBCont                = 'c', // resume
5411793Sbrandon.potter@amd.com    GDBAsyncCont           = 'C', // continue with signal
558232Snate@binkert.org    GDBDebug               = 'd', // toggle debug flags (deprecated)
563348Sbinkertn@umich.edu    GDBDetach              = 'D', // detach remote gdb
573348Sbinkertn@umich.edu    GDBRegR                = 'g', // read general registers
584762Snate@binkert.org    GDBRegW                = 'G', // write general registers
597678Sgblack@eecs.umich.edu    GDBSetThread           = 'H', // set thread
608779Sgblack@eecs.umich.edu    GDBCycleStep           = 'i', // step a single cycle
612901Ssaidi@eecs.umich.edu    GDBSigCycleStep        = 'I', // signal then cycle step
622623SN/A    GDBKill                = 'k', // kill program
632623SN/A    GDBMemR                = 'm', // read memory
642623SN/A    GDBMemW                = 'M', // write memory
652623SN/A    GDBReadReg             = 'p', // read register
662623SN/A    GDBSetReg              = 'P', // write register
672623SN/A    GDBQueryVar            = 'q', // query variable
682623SN/A    GDBSetVar              = 'Q', // set variable
6911147Smitch.hayenga@arm.com    GDBReset               = 'r', // reset system.  (Deprecated)
702623SN/A    GDBStep                = 's', // step
712623SN/A    GDBAsyncStep           = 'S', // signal and step
722623SN/A    GDBThreadAlive         = 'T', // find out if the thread is alive
738707Sandreas.hansson@arm.com    GDBTargetExit          = 'W', // target exited
742948Ssaidi@eecs.umich.edu    GDBBinaryDload         = 'X', // write memory
752948Ssaidi@eecs.umich.edu    GDBClrHwBkpt           = 'z', // remove breakpoint or watchpoint
765606Snate@binkert.org    GDBSetHwBkpt           = 'Z'  // insert breakpoint or watchpoint
772948Ssaidi@eecs.umich.edu};
782948Ssaidi@eecs.umich.edu
795529Snate@binkert.orgconst char GDBStart = '$';
808707Sandreas.hansson@arm.comconst char GDBEnd = '#';
819179Sandreas.hansson@arm.comconst char GDBGoodP = '+';
8212085Sspwilson2@wisc.educonst char GDBBadP = '-';
832623SN/A
842623SN/Aconst int GDBPacketBufLen = 1024;
852623SN/A
862623SN/Aclass BaseRemoteGDB
872623SN/A{
8810030SAli.Saidi@ARM.com  private:
892623SN/A    friend void debugger();
902623SN/A    friend class GDBListener;
912623SN/A
922623SN/A    //Helper functions
9310913Sandreas.sandberg@arm.com  protected:
9410913Sandreas.sandberg@arm.com    int digit2i(char);
952798Sktlim@umich.edu    char i2digit(int);
9612276Sanouk.vanlaer@arm.com    Addr hex2i(const char **);
9712276Sanouk.vanlaer@arm.com    //Address formats, break types, and gdb commands may change
9812276Sanouk.vanlaer@arm.com    //between architectures, so they're defined as virtual
999448SAndreas.Sandberg@ARM.com    //functions.
10010913Sandreas.sandberg@arm.com    virtual void mem2hex(void *, const void *, int);
1019448SAndreas.Sandberg@ARM.com    virtual const char * hex2mem(void *, const char *, int);
1029342SAndreas.Sandberg@arm.com    virtual const char * break_type(char c);
1039448SAndreas.Sandberg@ARM.com    virtual const char * gdb_command(char cmd);
1049442SAndreas.Sandberg@ARM.com
10511147Smitch.hayenga@arm.com  protected:
10610913Sandreas.sandberg@arm.com    class Event : public PollEvent
1072798Sktlim@umich.edu    {
10811147Smitch.hayenga@arm.com      protected:
1099442SAndreas.Sandberg@ARM.com        BaseRemoteGDB *gdb;
1109442SAndreas.Sandberg@ARM.com
1119442SAndreas.Sandberg@ARM.com      public:
1129442SAndreas.Sandberg@ARM.com        Event(BaseRemoteGDB *g, int fd, int e);
1139448SAndreas.Sandberg@ARM.com        void process(int revent);
1149648Sdam.sunwoo@arm.com    };
1159442SAndreas.Sandberg@ARM.com
11610913Sandreas.sandberg@arm.com    friend class Event;
1172798Sktlim@umich.edu    Event *event;
1182623SN/A    GDBListener *listener;
1192623SN/A    int number;
1202623SN/A
1219342SAndreas.Sandberg@arm.com  protected:
1222623SN/A    //The socket commands come in through
1239442SAndreas.Sandberg@ARM.com    int fd;
1249448SAndreas.Sandberg@ARM.com
1259448SAndreas.Sandberg@ARM.com  protected:
1269442SAndreas.Sandberg@ARM.com#ifdef notyet
1275221Ssaidi@eecs.umich.edu    label_t recover;
1289523SAndreas.Sandberg@ARM.com#endif
1293201Shsul@eecs.umich.edu    bool active;
1309448SAndreas.Sandberg@ARM.com    bool attached;
1319448SAndreas.Sandberg@ARM.com
13211147Smitch.hayenga@arm.com    System *system;
13311147Smitch.hayenga@arm.com    ThreadContext *context;
13411147Smitch.hayenga@arm.com
13511147Smitch.hayenga@arm.com  protected:
13611147Smitch.hayenga@arm.com    class GdbRegCache
13711147Smitch.hayenga@arm.com    {
13811147Smitch.hayenga@arm.com      public:
13911147Smitch.hayenga@arm.com        GdbRegCache(size_t newSize) : regs(new uint64_t[newSize]), size(newSize)
14011147Smitch.hayenga@arm.com        {}
14111147Smitch.hayenga@arm.com        ~GdbRegCache()
14211147Smitch.hayenga@arm.com        {
14311147Smitch.hayenga@arm.com            delete [] regs;
14411147Smitch.hayenga@arm.com        }
14511147Smitch.hayenga@arm.com
14611147Smitch.hayenga@arm.com        uint64_t * regs;
14711147Smitch.hayenga@arm.com        size_t size;
14811147Smitch.hayenga@arm.com        size_t bytes() { return size * sizeof(uint64_t); }
1492623SN/A    };
15011147Smitch.hayenga@arm.com
15112276Sanouk.vanlaer@arm.com    GdbRegCache gdbregs;
15212276Sanouk.vanlaer@arm.com
15312276Sanouk.vanlaer@arm.com  protected:
15411147Smitch.hayenga@arm.com    uint8_t getbyte();
1559442SAndreas.Sandberg@ARM.com    void putbyte(uint8_t b);
1562798Sktlim@umich.edu
1579442SAndreas.Sandberg@ARM.com    int recv(char *data, int len);
1589442SAndreas.Sandberg@ARM.com    void send(const char *data);
1599442SAndreas.Sandberg@ARM.com
16010913Sandreas.sandberg@arm.com  protected:
1619442SAndreas.Sandberg@ARM.com    // Machine memory
1629442SAndreas.Sandberg@ARM.com    virtual bool read(Addr addr, size_t size, char *data);
16311147Smitch.hayenga@arm.com    virtual bool write(Addr addr, size_t size, const char *data);
1649442SAndreas.Sandberg@ARM.com
1659442SAndreas.Sandberg@ARM.com    template <class T> T read(Addr addr);
1669442SAndreas.Sandberg@ARM.com    template <class T> void write(Addr addr, T data);
1679442SAndreas.Sandberg@ARM.com
16810913Sandreas.sandberg@arm.com  public:
1699442SAndreas.Sandberg@ARM.com    BaseRemoteGDB(System *system, ThreadContext *context, size_t cacheSize);
1709442SAndreas.Sandberg@ARM.com    virtual ~BaseRemoteGDB();
1712798Sktlim@umich.edu
1722798Sktlim@umich.edu    void replaceThreadContext(ThreadContext *tc) { context = tc; }
1732798Sktlim@umich.edu
1742798Sktlim@umich.edu    void attach(int fd);
1752798Sktlim@umich.edu    void detach();
17611147Smitch.hayenga@arm.com    bool isattached();
17711147Smitch.hayenga@arm.com
17811147Smitch.hayenga@arm.com    virtual bool acc(Addr addr, size_t len) = 0;
1799429SAndreas.Sandberg@ARM.com    bool trap(int type);
1809429SAndreas.Sandberg@ARM.com    virtual bool breakpoint()
1819442SAndreas.Sandberg@ARM.com    {
1829342SAndreas.Sandberg@arm.com        return trap(SIGTRAP);
18311147Smitch.hayenga@arm.com    }
18411147Smitch.hayenga@arm.com
1859442SAndreas.Sandberg@ARM.com  protected:
18610464SAndreas.Sandberg@ARM.com    virtual void getregs() = 0;
18712284Sjose.marinho@arm.com    virtual void setregs() = 0;
1882623SN/A
1892623SN/A    virtual void clearSingleStep() = 0;
1902623SN/A    virtual void setSingleStep() = 0;
1912623SN/A
1922623SN/A    PCEventQueue *getPcEventQueue();
1932623SN/A
1949429SAndreas.Sandberg@ARM.com  protected:
1952623SN/A    virtual bool checkBpLen(size_t len);
1969179Sandreas.hansson@arm.com
1972623SN/A    class HardBreakpoint : public PCEvent
1982623SN/A    {
1999523SAndreas.Sandberg@ARM.com      private:
2009523SAndreas.Sandberg@ARM.com        BaseRemoteGDB *gdb;
2019523SAndreas.Sandberg@ARM.com
2029524SAndreas.Sandberg@ARM.com      public:
2039523SAndreas.Sandberg@ARM.com        int refcount;
2049523SAndreas.Sandberg@ARM.com
2059523SAndreas.Sandberg@ARM.com      public:
2069523SAndreas.Sandberg@ARM.com        HardBreakpoint(BaseRemoteGDB *_gdb, Addr addr);
2072623SN/A        const std::string name() const { return gdb->name() + ".hwbkpt"; }
2082623SN/A
20910407Smitch.hayenga@arm.com        virtual void process(ThreadContext *tc);
2102623SN/A    };
21110407Smitch.hayenga@arm.com    friend class HardBreakpoint;
2125221Ssaidi@eecs.umich.edu
21311147Smitch.hayenga@arm.com    typedef std::map<Addr, HardBreakpoint *> break_map_t;
2142623SN/A    typedef break_map_t::iterator break_iter_t;
21511147Smitch.hayenga@arm.com    break_map_t hardBreakMap;
21611147Smitch.hayenga@arm.com
21711147Smitch.hayenga@arm.com    bool insertSoftBreak(Addr addr, size_t len);
2183686Sktlim@umich.edu    bool removeSoftBreak(Addr addr, size_t len);
2192623SN/A    virtual bool insertHardBreak(Addr addr, size_t len);
22011147Smitch.hayenga@arm.com    bool removeHardBreak(Addr addr, size_t len);
22111147Smitch.hayenga@arm.com
22211147Smitch.hayenga@arm.com  protected:
22311147Smitch.hayenga@arm.com    void clearTempBreakpoint(Addr &bkpt);
22411147Smitch.hayenga@arm.com    void setTempBreakpoint(Addr bkpt);
22511147Smitch.hayenga@arm.com
22611147Smitch.hayenga@arm.com  public:
22711526Sdavid.guillen@arm.com    std::string name();
22811526Sdavid.guillen@arm.com};
2292623SN/A
2302623SN/Atemplate <class T>
2312623SN/Ainline T
2322623SN/ABaseRemoteGDB::read(Addr addr)
2338737Skoansin.tan@gmail.com{
2342623SN/A    T temp;
2355221Ssaidi@eecs.umich.edu    read(addr, sizeof(T), (char *)&temp);
2365221Ssaidi@eecs.umich.edu    return temp;
23711147Smitch.hayenga@arm.com}
23811147Smitch.hayenga@arm.com
2392623SN/Atemplate <class T>
2406043Sgblack@eecs.umich.eduinline void
2416043Sgblack@eecs.umich.eduBaseRemoteGDB::write(Addr addr, T data)
2426043Sgblack@eecs.umich.edu{ write(addr, sizeof(T), (const char *)&data); }
2439342SAndreas.Sandberg@arm.com
2442623SN/Aclass GDBListener
24511147Smitch.hayenga@arm.com{
2462623SN/A  protected:
24711147Smitch.hayenga@arm.com    class Event : public PollEvent
24811147Smitch.hayenga@arm.com    {
24911147Smitch.hayenga@arm.com      protected:
25011147Smitch.hayenga@arm.com        GDBListener *listener;
25111147Smitch.hayenga@arm.com
25211147Smitch.hayenga@arm.com      public:
25311147Smitch.hayenga@arm.com        Event(GDBListener *l, int fd, int e);
25411526Sdavid.guillen@arm.com        void process(int revent);
25511526Sdavid.guillen@arm.com    };
2562623SN/A
2572623SN/A    friend class Event;
2585728Sgblack@eecs.umich.edu    Event *event;
2595728Sgblack@eecs.umich.edu
2605728Sgblack@eecs.umich.edu  protected:
26111147Smitch.hayenga@arm.com    ListenSocket listener;
26211147Smitch.hayenga@arm.com    BaseRemoteGDB *gdb;
26311147Smitch.hayenga@arm.com    int port;
26412749Sgiacomo.travaglini@arm.com
26510533Sali.saidi@arm.com  public:
26610533Sali.saidi@arm.com    GDBListener(BaseRemoteGDB *g, int p);
26710533Sali.saidi@arm.com    ~GDBListener();
26810533Sali.saidi@arm.com
26910533Sali.saidi@arm.com    void accept();
27010533Sali.saidi@arm.com    void listen();
2718105Sgblack@eecs.umich.edu    std::string name();
2729180Sandreas.hansson@arm.com};
2739179Sandreas.hansson@arm.com
2745728Sgblack@eecs.umich.edu#endif /* __REMOTE_GDB_H__ */
2755728Sgblack@eecs.umich.edu