remote_gdb.hh revision 10589:5962812f80fe
19048SAli.Saidi@ARM.com/*
29048SAli.Saidi@ARM.com * Copyright (c) 2002-2005 The Regents of The University of Michigan
311077SCurtis.Dunham@arm.com * All rights reserved.
49048SAli.Saidi@ARM.com *
59048SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without
69048SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are
79048SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright
89048SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer;
99048SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright
109048SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the
119048SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution;
129048SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its
139048SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from
149048SAli.Saidi@ARM.com * this software without specific prior written permission.
159048SAli.Saidi@ARM.com *
169048SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
179048SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
189048SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
199048SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
209048SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
219048SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
229048SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
239048SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
249048SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
259048SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
269048SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
279048SAli.Saidi@ARM.com *
289048SAli.Saidi@ARM.com * Authors: Nathan Binkert
299048SAli.Saidi@ARM.com */
309048SAli.Saidi@ARM.com
319048SAli.Saidi@ARM.com#ifndef __REMOTE_GDB_HH__
329048SAli.Saidi@ARM.com#define __REMOTE_GDB_HH__
339048SAli.Saidi@ARM.com
349048SAli.Saidi@ARM.com#include <sys/signal.h>
359048SAli.Saidi@ARM.com
369048SAli.Saidi@ARM.com#include <map>
379048SAli.Saidi@ARM.com
389048SAli.Saidi@ARM.com#include "arch/types.hh"
3911077SCurtis.Dunham@arm.com#include "base/pollevent.hh"
409048SAli.Saidi@ARM.com#include "base/socket.hh"
419048SAli.Saidi@ARM.com#include "cpu/pc_event.hh"
429056SAli.Saidi@ARM.com
439056SAli.Saidi@ARM.comclass System;
449056SAli.Saidi@ARM.comclass ThreadContext;
459056SAli.Saidi@ARM.com
469056SAli.Saidi@ARM.comclass GDBListener;
479056SAli.Saidi@ARM.com
489056SAli.Saidi@ARM.comenum GDBCommands
4911077SCurtis.Dunham@arm.com{
509056SAli.Saidi@ARM.com    GDBSignal              = '?', // last signal
519056SAli.Saidi@ARM.com    GDBSetBaud             = 'b', // set baud (depracated)
5211077SCurtis.Dunham@arm.com    GDBSetBreak            = 'B', // set breakpoint (depracated)
5311077SCurtis.Dunham@arm.com    GDBCont                = 'c', // resume
5411077SCurtis.Dunham@arm.com    GDBAsyncCont           = 'C', // continue with signal
5511077SCurtis.Dunham@arm.com    GDBDebug               = 'd', // toggle debug flags (deprecated)
5611077SCurtis.Dunham@arm.com    GDBDetach              = 'D', // detach remote gdb
5711077SCurtis.Dunham@arm.com    GDBRegR                = 'g', // read general registers
5811077SCurtis.Dunham@arm.com    GDBRegW                = 'G', // write general registers
599056SAli.Saidi@ARM.com    GDBSetThread           = 'H', // set thread
609056SAli.Saidi@ARM.com    GDBCycleStep           = 'i', // step a single cycle
619048SAli.Saidi@ARM.com    GDBSigCycleStep        = 'I', // signal then cycle step
6211077SCurtis.Dunham@arm.com    GDBKill                = 'k', // kill program
639048SAli.Saidi@ARM.com    GDBMemR                = 'm', // read memory
649048SAli.Saidi@ARM.com    GDBMemW                = 'M', // write memory
659048SAli.Saidi@ARM.com    GDBReadReg             = 'p', // read register
669048SAli.Saidi@ARM.com    GDBSetReg              = 'P', // write register
679048SAli.Saidi@ARM.com    GDBQueryVar            = 'q', // query variable
689048SAli.Saidi@ARM.com    GDBSetVar              = 'Q', // set variable
699048SAli.Saidi@ARM.com    GDBReset               = 'r', // reset system.  (Deprecated)
709048SAli.Saidi@ARM.com    GDBStep                = 's', // step
719048SAli.Saidi@ARM.com    GDBAsyncStep           = 'S', // signal and step
729048SAli.Saidi@ARM.com    GDBThreadAlive         = 'T', // find out if the thread is alive
739048SAli.Saidi@ARM.com    GDBTargetExit          = 'W', // target exited
7411077SCurtis.Dunham@arm.com    GDBBinaryDload         = 'X', // write memory
7511077SCurtis.Dunham@arm.com    GDBClrHwBkpt           = 'z', // remove breakpoint or watchpoint
7611077SCurtis.Dunham@arm.com    GDBSetHwBkpt           = 'Z'  // insert breakpoint or watchpoint
7711077SCurtis.Dunham@arm.com};
7811077SCurtis.Dunham@arm.com
7911077SCurtis.Dunham@arm.comconst char GDBStart = '$';
8011077SCurtis.Dunham@arm.comconst char GDBEnd = '#';
8111077SCurtis.Dunham@arm.comconst char GDBGoodP = '+';
8211077SCurtis.Dunham@arm.comconst char GDBBadP = '-';
8311077SCurtis.Dunham@arm.com
8411077SCurtis.Dunham@arm.comconst int GDBPacketBufLen = 1024;
8511077SCurtis.Dunham@arm.com
8611077SCurtis.Dunham@arm.comclass BaseRemoteGDB
8711077SCurtis.Dunham@arm.com{
8811077SCurtis.Dunham@arm.com  private:
8911077SCurtis.Dunham@arm.com    friend void debugger();
9011077SCurtis.Dunham@arm.com    friend class GDBListener;
9111077SCurtis.Dunham@arm.com
9211077SCurtis.Dunham@arm.com    //Helper functions
9311077SCurtis.Dunham@arm.com  protected:
9411077SCurtis.Dunham@arm.com    int digit2i(char);
9511077SCurtis.Dunham@arm.com    char i2digit(int);
9611077SCurtis.Dunham@arm.com    Addr hex2i(const char **);
9711077SCurtis.Dunham@arm.com    //Address formats, break types, and gdb commands may change
9811077SCurtis.Dunham@arm.com    //between architectures, so they're defined as virtual
9911077SCurtis.Dunham@arm.com    //functions.
10011077SCurtis.Dunham@arm.com    virtual void mem2hex(void *, const void *, int);
10111077SCurtis.Dunham@arm.com    virtual const char * hex2mem(void *, const char *, int);
10211077SCurtis.Dunham@arm.com    virtual const char * break_type(char c);
10311077SCurtis.Dunham@arm.com    virtual const char * gdb_command(char cmd);
10411077SCurtis.Dunham@arm.com
10511077SCurtis.Dunham@arm.com  protected:
10611077SCurtis.Dunham@arm.com    class Event : public PollEvent
10711077SCurtis.Dunham@arm.com    {
10811077SCurtis.Dunham@arm.com      protected:
10911077SCurtis.Dunham@arm.com        BaseRemoteGDB *gdb;
11011077SCurtis.Dunham@arm.com
11111077SCurtis.Dunham@arm.com      public:
11211077SCurtis.Dunham@arm.com        Event(BaseRemoteGDB *g, int fd, int e);
11311077SCurtis.Dunham@arm.com        void process(int revent);
11411077SCurtis.Dunham@arm.com    };
11511077SCurtis.Dunham@arm.com
11611077SCurtis.Dunham@arm.com    friend class Event;
11711077SCurtis.Dunham@arm.com    Event *event;
11811077SCurtis.Dunham@arm.com    GDBListener *listener;
11911077SCurtis.Dunham@arm.com    int number;
12011077SCurtis.Dunham@arm.com
12111077SCurtis.Dunham@arm.com  protected:
12211077SCurtis.Dunham@arm.com    //The socket commands come in through
12311077SCurtis.Dunham@arm.com    int fd;
12411077SCurtis.Dunham@arm.com
12511077SCurtis.Dunham@arm.com  protected:
12611077SCurtis.Dunham@arm.com#ifdef notyet
12711077SCurtis.Dunham@arm.com    label_t recover;
12811077SCurtis.Dunham@arm.com#endif
12911077SCurtis.Dunham@arm.com    bool active;
1309048SAli.Saidi@ARM.com    bool attached;
1319048SAli.Saidi@ARM.com
1329048SAli.Saidi@ARM.com    System *system;
1339048SAli.Saidi@ARM.com    ThreadContext *context;
1349048SAli.Saidi@ARM.com
1359048SAli.Saidi@ARM.com  protected:
1369048SAli.Saidi@ARM.com    class GdbRegCache
1379048SAli.Saidi@ARM.com    {
1389048SAli.Saidi@ARM.com      public:
1399048SAli.Saidi@ARM.com        GdbRegCache(size_t newSize) : regs(new uint64_t[newSize]), size(newSize)
1409048SAli.Saidi@ARM.com        {}
1419048SAli.Saidi@ARM.com        ~GdbRegCache()
1429048SAli.Saidi@ARM.com        {
1439048SAli.Saidi@ARM.com            delete [] regs;
1449048SAli.Saidi@ARM.com        }
1459048SAli.Saidi@ARM.com
1469048SAli.Saidi@ARM.com        uint64_t * regs;
1479048SAli.Saidi@ARM.com        size_t size;
1489048SAli.Saidi@ARM.com        size_t bytes() { return size * sizeof(uint64_t); }
1499048SAli.Saidi@ARM.com    };
1509048SAli.Saidi@ARM.com
15111077SCurtis.Dunham@arm.com    GdbRegCache gdbregs;
15211077SCurtis.Dunham@arm.com
1539048SAli.Saidi@ARM.com  protected:
15411077SCurtis.Dunham@arm.com    uint8_t getbyte();
15511077SCurtis.Dunham@arm.com    void putbyte(uint8_t b);
1569048SAli.Saidi@ARM.com
15711077SCurtis.Dunham@arm.com    int recv(char *data, int len);
15811077SCurtis.Dunham@arm.com    void send(const char *data);
15911077SCurtis.Dunham@arm.com
16011077SCurtis.Dunham@arm.com  protected:
16111077SCurtis.Dunham@arm.com    // Machine memory
16211077SCurtis.Dunham@arm.com    virtual bool read(Addr addr, size_t size, char *data);
16311077SCurtis.Dunham@arm.com    virtual bool write(Addr addr, size_t size, const char *data);
1649048SAli.Saidi@ARM.com
16511077SCurtis.Dunham@arm.com    template <class T> T read(Addr addr);
16611077SCurtis.Dunham@arm.com    template <class T> void write(Addr addr, T data);
16711077SCurtis.Dunham@arm.com
16811077SCurtis.Dunham@arm.com  public:
16911077SCurtis.Dunham@arm.com    BaseRemoteGDB(System *system, ThreadContext *context, size_t cacheSize);
17011077SCurtis.Dunham@arm.com    virtual ~BaseRemoteGDB();
1719048SAli.Saidi@ARM.com
17211077SCurtis.Dunham@arm.com    void replaceThreadContext(ThreadContext *tc) { context = tc; }
17311077SCurtis.Dunham@arm.com
17411077SCurtis.Dunham@arm.com    void attach(int fd);
17511077SCurtis.Dunham@arm.com    void detach();
17611077SCurtis.Dunham@arm.com    bool isattached();
17711077SCurtis.Dunham@arm.com
17811077SCurtis.Dunham@arm.com    virtual bool acc(Addr addr, size_t len) = 0;
17911077SCurtis.Dunham@arm.com    bool trap(int type);
1809048SAli.Saidi@ARM.com    virtual bool breakpoint()
18111077SCurtis.Dunham@arm.com    {
18211077SCurtis.Dunham@arm.com        return trap(SIGTRAP);
18311077SCurtis.Dunham@arm.com    }
18411077SCurtis.Dunham@arm.com
18511077SCurtis.Dunham@arm.com  protected:
18611077SCurtis.Dunham@arm.com    virtual void getregs() = 0;
18711077SCurtis.Dunham@arm.com    virtual void setregs() = 0;
18811077SCurtis.Dunham@arm.com
18911077SCurtis.Dunham@arm.com    virtual void clearSingleStep() = 0;
19011077SCurtis.Dunham@arm.com    virtual void setSingleStep() = 0;
19111077SCurtis.Dunham@arm.com
19211077SCurtis.Dunham@arm.com    PCEventQueue *getPcEventQueue();
19311077SCurtis.Dunham@arm.com
19411077SCurtis.Dunham@arm.com  protected:
19511077SCurtis.Dunham@arm.com    virtual bool checkBpLen(size_t len);
19611077SCurtis.Dunham@arm.com
19711077SCurtis.Dunham@arm.com    class HardBreakpoint : public PCEvent
19811077SCurtis.Dunham@arm.com    {
1999048SAli.Saidi@ARM.com      private:
2009048SAli.Saidi@ARM.com        BaseRemoteGDB *gdb;
20111077SCurtis.Dunham@arm.com
2029048SAli.Saidi@ARM.com      public:
2039048SAli.Saidi@ARM.com        int refcount;
20411077SCurtis.Dunham@arm.com
2059048SAli.Saidi@ARM.com      public:
2069048SAli.Saidi@ARM.com        HardBreakpoint(BaseRemoteGDB *_gdb, Addr addr);
2079048SAli.Saidi@ARM.com        const std::string name() const { return gdb->name() + ".hwbkpt"; }
20811077SCurtis.Dunham@arm.com
2099048SAli.Saidi@ARM.com        virtual void process(ThreadContext *tc);
2109048SAli.Saidi@ARM.com    };
2119048SAli.Saidi@ARM.com    friend class HardBreakpoint;
2129048SAli.Saidi@ARM.com
2139048SAli.Saidi@ARM.com    typedef std::map<Addr, HardBreakpoint *> break_map_t;
2149048SAli.Saidi@ARM.com    typedef break_map_t::iterator break_iter_t;
2159048SAli.Saidi@ARM.com    break_map_t hardBreakMap;
2169048SAli.Saidi@ARM.com
2179048SAli.Saidi@ARM.com    bool insertSoftBreak(Addr addr, size_t len);
21811077SCurtis.Dunham@arm.com    bool removeSoftBreak(Addr addr, size_t len);
21911077SCurtis.Dunham@arm.com    virtual bool insertHardBreak(Addr addr, size_t len);
22011077SCurtis.Dunham@arm.com    bool removeHardBreak(Addr addr, size_t len);
2219048SAli.Saidi@ARM.com
2229048SAli.Saidi@ARM.com  protected:
22311077SCurtis.Dunham@arm.com    void clearTempBreakpoint(Addr &bkpt);
22411077SCurtis.Dunham@arm.com    void setTempBreakpoint(Addr bkpt);
22511077SCurtis.Dunham@arm.com
22611077SCurtis.Dunham@arm.com  public:
22711077SCurtis.Dunham@arm.com    std::string name();
22811077SCurtis.Dunham@arm.com};
22911077SCurtis.Dunham@arm.com
23011077SCurtis.Dunham@arm.comtemplate <class T>
23111077SCurtis.Dunham@arm.cominline T
23211077SCurtis.Dunham@arm.comBaseRemoteGDB::read(Addr addr)
23311077SCurtis.Dunham@arm.com{
23411077SCurtis.Dunham@arm.com    T temp;
23511077SCurtis.Dunham@arm.com    read(addr, sizeof(T), (char *)&temp);
23611077SCurtis.Dunham@arm.com    return temp;
23711077SCurtis.Dunham@arm.com}
2389048SAli.Saidi@ARM.com
2399048SAli.Saidi@ARM.comtemplate <class T>
2409048SAli.Saidi@ARM.cominline void
2419048SAli.Saidi@ARM.comBaseRemoteGDB::write(Addr addr, T data)
2429048SAli.Saidi@ARM.com{ write(addr, sizeof(T), (const char *)&data); }
2439048SAli.Saidi@ARM.com
2449048SAli.Saidi@ARM.comclass GDBListener
2459048SAli.Saidi@ARM.com{
2469048SAli.Saidi@ARM.com  protected:
2479048SAli.Saidi@ARM.com    class Event : public PollEvent
2489048SAli.Saidi@ARM.com    {
2499048SAli.Saidi@ARM.com      protected:
2509048SAli.Saidi@ARM.com        GDBListener *listener;
2519048SAli.Saidi@ARM.com
2529048SAli.Saidi@ARM.com      public:
2539048SAli.Saidi@ARM.com        Event(GDBListener *l, int fd, int e);
2549048SAli.Saidi@ARM.com        void process(int revent);
2559048SAli.Saidi@ARM.com    };
2569048SAli.Saidi@ARM.com
2579048SAli.Saidi@ARM.com    friend class Event;
2589048SAli.Saidi@ARM.com    Event *event;
2599048SAli.Saidi@ARM.com
2609048SAli.Saidi@ARM.com  protected:
2619048SAli.Saidi@ARM.com    ListenSocket listener;
2629048SAli.Saidi@ARM.com    BaseRemoteGDB *gdb;
2639048SAli.Saidi@ARM.com    int port;
2649048SAli.Saidi@ARM.com
2659048SAli.Saidi@ARM.com  public:
2669048SAli.Saidi@ARM.com    GDBListener(BaseRemoteGDB *g, int p);
267    ~GDBListener();
268
269    void accept();
270    void listen();
271    std::string name();
272};
273
274#endif /* __REMOTE_GDB_H__ */
275