remote_gdb.hh revision 10595:25ecfc14f73f
112855Sgabeblack@google.com/*
212855Sgabeblack@google.com * Copyright 2014 Google, Inc.
312855Sgabeblack@google.com * Copyright (c) 2002-2005 The Regents of The University of Michigan
412855Sgabeblack@google.com * All rights reserved.
512855Sgabeblack@google.com *
612855Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
712855Sgabeblack@google.com * modification, are permitted provided that the following conditions are
812855Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
912855Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
1012855Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
1112855Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
1212855Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
1312855Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
1412855Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
1512855Sgabeblack@google.com * this software without specific prior written permission.
1612855Sgabeblack@google.com *
1712855Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1812855Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1912855Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2012855Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2112855Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2212855Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2312855Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2412855Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2512855Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2612855Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2712855Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2812855Sgabeblack@google.com *
2912855Sgabeblack@google.com * Authors: Nathan Binkert
3012855Sgabeblack@google.com */
3112855Sgabeblack@google.com
3212855Sgabeblack@google.com#ifndef __REMOTE_GDB_HH__
33#define __REMOTE_GDB_HH__
34
35#include <sys/signal.h>
36
37#include <map>
38
39#include "arch/types.hh"
40#include "base/intmath.hh"
41#include "base/pollevent.hh"
42#include "base/socket.hh"
43#include "cpu/pc_event.hh"
44
45class System;
46class ThreadContext;
47
48class GDBListener;
49
50enum GDBCommands
51{
52    GDBSignal              = '?', // last signal
53    GDBSetBaud             = 'b', // set baud (depracated)
54    GDBSetBreak            = 'B', // set breakpoint (depracated)
55    GDBCont                = 'c', // resume
56    GDBAsyncCont           = 'C', // continue with signal
57    GDBDebug               = 'd', // toggle debug flags (deprecated)
58    GDBDetach              = 'D', // detach remote gdb
59    GDBRegR                = 'g', // read general registers
60    GDBRegW                = 'G', // write general registers
61    GDBSetThread           = 'H', // set thread
62    GDBCycleStep           = 'i', // step a single cycle
63    GDBSigCycleStep        = 'I', // signal then cycle step
64    GDBKill                = 'k', // kill program
65    GDBMemR                = 'm', // read memory
66    GDBMemW                = 'M', // write memory
67    GDBReadReg             = 'p', // read register
68    GDBSetReg              = 'P', // write register
69    GDBQueryVar            = 'q', // query variable
70    GDBSetVar              = 'Q', // set variable
71    GDBReset               = 'r', // reset system.  (Deprecated)
72    GDBStep                = 's', // step
73    GDBAsyncStep           = 'S', // signal and step
74    GDBThreadAlive         = 'T', // find out if the thread is alive
75    GDBTargetExit          = 'W', // target exited
76    GDBBinaryDload         = 'X', // write memory
77    GDBClrHwBkpt           = 'z', // remove breakpoint or watchpoint
78    GDBSetHwBkpt           = 'Z'  // insert breakpoint or watchpoint
79};
80
81const char GDBStart = '$';
82const char GDBEnd = '#';
83const char GDBGoodP = '+';
84const char GDBBadP = '-';
85
86const int GDBPacketBufLen = 1024;
87
88class BaseRemoteGDB
89{
90  private:
91    friend void debugger();
92    friend class GDBListener;
93
94    //Helper functions
95  protected:
96    int digit2i(char);
97    char i2digit(int);
98    Addr hex2i(const char **);
99    //Address formats, break types, and gdb commands may change
100    //between architectures, so they're defined as virtual
101    //functions.
102    virtual void mem2hex(void *, const void *, int);
103    virtual const char * hex2mem(void *, const char *, int);
104    virtual const char * break_type(char c);
105    virtual const char * gdb_command(char cmd);
106
107  protected:
108    class Event : public PollEvent
109    {
110      protected:
111        BaseRemoteGDB *gdb;
112
113      public:
114        Event(BaseRemoteGDB *g, int fd, int e);
115        void process(int revent);
116    };
117
118    friend class Event;
119    Event *event;
120    GDBListener *listener;
121    int number;
122
123  protected:
124    //The socket commands come in through
125    int fd;
126
127  protected:
128#ifdef notyet
129    label_t recover;
130#endif
131    bool active;
132    bool attached;
133
134    System *system;
135    ThreadContext *context;
136
137  protected:
138    class GdbRegCache
139    {
140      public:
141        GdbRegCache(size_t newSize) :
142            regs64(new uint64_t[divCeil(newSize, sizeof(uint64_t))]),
143            size(newSize)
144        {}
145        ~GdbRegCache()
146        {
147            delete [] regs64;
148        }
149
150        union {
151            uint64_t *regs64;
152            uint32_t *regs32;
153            uint16_t *regs16;
154            uint8_t *regs8;
155            void *regs;
156        };
157        // Size of cache in bytes.
158        size_t size;
159        size_t bytes() { return size; }
160    };
161
162    GdbRegCache gdbregs;
163
164  protected:
165    uint8_t getbyte();
166    void putbyte(uint8_t b);
167
168    int recv(char *data, int len);
169    void send(const char *data);
170
171  protected:
172    // Machine memory
173    virtual bool read(Addr addr, size_t size, char *data);
174    virtual bool write(Addr addr, size_t size, const char *data);
175
176    template <class T> T read(Addr addr);
177    template <class T> void write(Addr addr, T data);
178
179  public:
180    BaseRemoteGDB(System *system, ThreadContext *context, size_t cacheSize);
181    virtual ~BaseRemoteGDB();
182
183    void replaceThreadContext(ThreadContext *tc) { context = tc; }
184
185    void attach(int fd);
186    void detach();
187    bool isattached();
188
189    virtual bool acc(Addr addr, size_t len) = 0;
190    bool trap(int type);
191    virtual bool breakpoint()
192    {
193        return trap(SIGTRAP);
194    }
195
196  protected:
197    virtual void getregs() = 0;
198    virtual void setregs() = 0;
199
200    virtual void clearSingleStep() = 0;
201    virtual void setSingleStep() = 0;
202
203    PCEventQueue *getPcEventQueue();
204
205  protected:
206    virtual bool checkBpLen(size_t len);
207
208    class HardBreakpoint : public PCEvent
209    {
210      private:
211        BaseRemoteGDB *gdb;
212
213      public:
214        int refcount;
215
216      public:
217        HardBreakpoint(BaseRemoteGDB *_gdb, Addr addr);
218        const std::string name() const { return gdb->name() + ".hwbkpt"; }
219
220        virtual void process(ThreadContext *tc);
221    };
222    friend class HardBreakpoint;
223
224    typedef std::map<Addr, HardBreakpoint *> break_map_t;
225    typedef break_map_t::iterator break_iter_t;
226    break_map_t hardBreakMap;
227
228    bool insertSoftBreak(Addr addr, size_t len);
229    bool removeSoftBreak(Addr addr, size_t len);
230    virtual bool insertHardBreak(Addr addr, size_t len);
231    bool removeHardBreak(Addr addr, size_t len);
232
233  protected:
234    void clearTempBreakpoint(Addr &bkpt);
235    void setTempBreakpoint(Addr bkpt);
236
237  public:
238    std::string name();
239};
240
241template <class T>
242inline T
243BaseRemoteGDB::read(Addr addr)
244{
245    T temp;
246    read(addr, sizeof(T), (char *)&temp);
247    return temp;
248}
249
250template <class T>
251inline void
252BaseRemoteGDB::write(Addr addr, T data)
253{ write(addr, sizeof(T), (const char *)&data); }
254
255class GDBListener
256{
257  protected:
258    class Event : public PollEvent
259    {
260      protected:
261        GDBListener *listener;
262
263      public:
264        Event(GDBListener *l, int fd, int e);
265        void process(int revent);
266    };
267
268    friend class Event;
269    Event *event;
270
271  protected:
272    ListenSocket listener;
273    BaseRemoteGDB *gdb;
274    int port;
275
276  public:
277    GDBListener(BaseRemoteGDB *g, int p);
278    ~GDBListener();
279
280    void accept();
281    void listen();
282    std::string name();
283};
284
285#endif /* __REMOTE_GDB_H__ */
286