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