remote_gdb.hh revision 10598
1/*
2 * Copyright 2014 Google, Inc.
3 * Copyright (c) 2002-2005 The Regents of The University of Michigan
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Authors: Nathan Binkert
30 */
31
32#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 InputEvent : public PollEvent
109    {
110      protected:
111        BaseRemoteGDB *gdb;
112
113      public:
114        InputEvent(BaseRemoteGDB *g, int fd, int e);
115        void process(int revent);
116    };
117
118    class TrapEvent : public Event
119    {
120      protected:
121        int _type;
122        BaseRemoteGDB *gdb;
123
124      public:
125        TrapEvent(BaseRemoteGDB *g) : gdb(g)
126        {}
127
128        void type(int t) { _type = t; }
129        void process();
130    };
131
132    friend class InputEvent;
133    InputEvent *inputEvent;
134    TrapEvent trapEvent;
135    GDBListener *listener;
136    int number;
137
138  protected:
139    //The socket commands come in through
140    int fd;
141
142  protected:
143#ifdef notyet
144    label_t recover;
145#endif
146    bool active;
147    bool attached;
148
149    System *system;
150    ThreadContext *context;
151
152  protected:
153    class GdbRegCache
154    {
155      public:
156        GdbRegCache(size_t newSize) :
157            regs64(new uint64_t[divCeil(newSize, sizeof(uint64_t))]),
158            size(newSize)
159        {}
160        ~GdbRegCache()
161        {
162            delete [] regs64;
163        }
164
165        union {
166            uint64_t *regs64;
167            uint32_t *regs32;
168            uint16_t *regs16;
169            uint8_t *regs8;
170            void *regs;
171        };
172        // Size of cache in bytes.
173        size_t size;
174        size_t bytes() { return size; }
175    };
176
177    GdbRegCache gdbregs;
178
179  protected:
180    uint8_t getbyte();
181    void putbyte(uint8_t b);
182
183    int recv(char *data, int len);
184    void send(const char *data);
185
186  protected:
187    // Machine memory
188    virtual bool read(Addr addr, size_t size, char *data);
189    virtual bool write(Addr addr, size_t size, const char *data);
190
191    template <class T> T read(Addr addr);
192    template <class T> void write(Addr addr, T data);
193
194  public:
195    BaseRemoteGDB(System *system, ThreadContext *context, size_t cacheSize);
196    virtual ~BaseRemoteGDB();
197
198    void replaceThreadContext(ThreadContext *tc) { context = tc; }
199
200    void attach(int fd);
201    void detach();
202    bool isattached();
203
204    virtual bool acc(Addr addr, size_t len) = 0;
205    bool trap(int type);
206    virtual bool breakpoint()
207    {
208        return trap(SIGTRAP);
209    }
210
211  protected:
212    virtual void getregs() = 0;
213    virtual void setregs() = 0;
214
215    virtual void clearSingleStep() = 0;
216    virtual void setSingleStep() = 0;
217
218    PCEventQueue *getPcEventQueue();
219
220  protected:
221    virtual bool checkBpLen(size_t len);
222
223    class HardBreakpoint : public PCEvent
224    {
225      private:
226        BaseRemoteGDB *gdb;
227
228      public:
229        int refcount;
230
231      public:
232        HardBreakpoint(BaseRemoteGDB *_gdb, Addr addr);
233        const std::string name() const { return gdb->name() + ".hwbkpt"; }
234
235        virtual void process(ThreadContext *tc);
236    };
237    friend class HardBreakpoint;
238
239    typedef std::map<Addr, HardBreakpoint *> break_map_t;
240    typedef break_map_t::iterator break_iter_t;
241    break_map_t hardBreakMap;
242
243    bool insertSoftBreak(Addr addr, size_t len);
244    bool removeSoftBreak(Addr addr, size_t len);
245    virtual bool insertHardBreak(Addr addr, size_t len);
246    bool removeHardBreak(Addr addr, size_t len);
247
248  protected:
249    void clearTempBreakpoint(Addr &bkpt);
250    void setTempBreakpoint(Addr bkpt);
251
252  public:
253    std::string name();
254};
255
256template <class T>
257inline T
258BaseRemoteGDB::read(Addr addr)
259{
260    T temp;
261    read(addr, sizeof(T), (char *)&temp);
262    return temp;
263}
264
265template <class T>
266inline void
267BaseRemoteGDB::write(Addr addr, T data)
268{ write(addr, sizeof(T), (const char *)&data); }
269
270class GDBListener
271{
272  protected:
273    class InputEvent : public PollEvent
274    {
275      protected:
276        GDBListener *listener;
277
278      public:
279        InputEvent(GDBListener *l, int fd, int e);
280        void process(int revent);
281    };
282
283    friend class InputEvent;
284    InputEvent *inputEvent;
285
286  protected:
287    ListenSocket listener;
288    BaseRemoteGDB *gdb;
289    int port;
290
291  public:
292    GDBListener(BaseRemoteGDB *g, int p);
293    ~GDBListener();
294
295    void accept();
296    void listen();
297    std::string name();
298};
299
300#endif /* __REMOTE_GDB_H__ */
301