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