remote_gdb.hh revision 12449:2260f4a68210
1/*
2 * Copyright 2015 LabWare
3 * Copyright 2014 Google, Inc.
4 * Copyright (c) 2002-2005 The Regents of The University of Michigan
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met: redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer;
11 * redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution;
14 * neither the name of the copyright holders nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * Authors: Nathan Binkert
31 *          Boris Shingarov
32 */
33
34#ifndef __REMOTE_GDB_HH__
35#define __REMOTE_GDB_HH__
36
37#include <sys/signal.h>
38
39#include <exception>
40#include <map>
41#include <string>
42
43#include "arch/types.hh"
44#include "base/intmath.hh"
45#include "base/pollevent.hh"
46#include "base/socket.hh"
47#include "cpu/pc_event.hh"
48
49class System;
50class ThreadContext;
51
52class BaseRemoteGDB;
53class HardBreakpoint;
54
55/**
56 * Concrete subclasses of this abstract class represent how the
57 * register values are transmitted on the wire.  Usually each
58 * architecture should define one subclass, but there can be more
59 * if there is more than one possible wire format.  For example,
60 * ARM defines both AArch32GdbRegCache and AArch64GdbRegCache.
61 */
62class BaseGdbRegCache
63{
64  public:
65
66    /**
67     * Return the pointer to the raw bytes buffer containing the
68     * register values.  Each byte of this buffer is literally
69     * encoded as two hex digits in the g or G RSP packet.
70     */
71    virtual char *data() const = 0;
72
73    /**
74     * Return the size of the raw buffer, in bytes
75     * (i.e., half of the number of digits in the g/G packet).
76     */
77    virtual size_t size() const = 0;
78
79    /**
80     * Fill the raw buffer from the registers in the ThreadContext.
81     */
82    virtual void getRegs(ThreadContext*) = 0;
83
84    /**
85     * Set the ThreadContext's registers from the values
86     * in the raw buffer.
87     */
88    virtual void setRegs(ThreadContext*) const = 0;
89
90    /**
91     * Return the name to use in places like DPRINTF.
92     * Having each concrete superclass redefine this member
93     * is useful in situations where the class of the regCache
94     * can change on the fly.
95     */
96    virtual const std::string name() const = 0;
97
98    BaseGdbRegCache(BaseRemoteGDB *g) : gdb(g)
99    {}
100    virtual ~BaseGdbRegCache()
101    {}
102
103  protected:
104    BaseRemoteGDB *gdb;
105};
106
107class BaseRemoteGDB
108{
109    friend class HardBreakpoint;
110  public:
111
112    /*
113     * Interface to other parts of the simulator.
114     */
115    BaseRemoteGDB(System *system, ThreadContext *context, int _port);
116    virtual ~BaseRemoteGDB();
117
118    std::string name();
119
120    void listen();
121    void connect();
122
123    int port() const;
124
125    void attach(int fd);
126    void detach();
127    bool isAttached() { return attached; }
128
129    void replaceThreadContext(ThreadContext *_tc) { tc = _tc; }
130
131    bool trap(int type);
132    bool breakpoint() { return trap(SIGTRAP); }
133
134  private:
135    /*
136     * Connection to the external GDB.
137     */
138    void incomingData(int revent);
139    void connectWrapper(int revent) { connect(); }
140
141    template <void (BaseRemoteGDB::*F)(int revent)>
142    class SocketEvent : public PollEvent
143    {
144      protected:
145        BaseRemoteGDB *gdb;
146
147      public:
148        SocketEvent(BaseRemoteGDB *gdb, int fd, int e) :
149            PollEvent(fd, e), gdb(gdb)
150        {}
151
152        void process(int revent) { (gdb->*F)(revent); }
153    };
154
155    typedef SocketEvent<&BaseRemoteGDB::connectWrapper> ConnectEvent;
156    typedef SocketEvent<&BaseRemoteGDB::incomingData> DataEvent;
157
158    friend ConnectEvent;
159    friend DataEvent;
160
161    ConnectEvent *connectEvent;
162    DataEvent *dataEvent;
163
164    ListenSocket listener;
165    int _port;
166
167    // The socket commands come in through.
168    int fd;
169
170    // Transfer data to/from GDB.
171    uint8_t getbyte();
172    void putbyte(uint8_t b);
173
174    int recv(char *data, int len);
175    void send(const char *data);
176
177    /*
178     * Simulator side debugger state.
179     */
180    bool active;
181    bool attached;
182
183    System *sys;
184    ThreadContext *tc;
185
186    BaseGdbRegCache *regCachePtr;
187
188    class TrapEvent : public Event
189    {
190      protected:
191        int _type;
192        BaseRemoteGDB *gdb;
193
194      public:
195        TrapEvent(BaseRemoteGDB *g) : gdb(g)
196        {}
197
198        void type(int t) { _type = t; }
199        void process() { gdb->trap(_type); }
200    } trapEvent;
201
202    /*
203     * The interface to the simulated system.
204     */
205    // Machine memory.
206    bool read(Addr addr, size_t size, char *data);
207    bool write(Addr addr, size_t size, const char *data);
208
209    template <class T> T read(Addr addr);
210    template <class T> void write(Addr addr, T data);
211
212    // Single step.
213    void singleStep();
214    EventWrapper<BaseRemoteGDB, &BaseRemoteGDB::singleStep> singleStepEvent;
215
216    void clearSingleStep();
217    void setSingleStep();
218
219    /// Schedule an event which will be triggered "delta" instructions later.
220    void scheduleInstCommitEvent(Event *ev, int delta);
221    /// Deschedule an instruction count based event.
222    void descheduleInstCommitEvent(Event *ev);
223
224    // Breakpoints.
225    void insertSoftBreak(Addr addr, size_t len);
226    void removeSoftBreak(Addr addr, size_t len);
227    void insertHardBreak(Addr addr, size_t len);
228    void removeHardBreak(Addr addr, size_t len);
229
230    void clearTempBreakpoint(Addr &bkpt);
231    void setTempBreakpoint(Addr bkpt);
232
233    /*
234     * GDB commands.
235     */
236    struct GdbCommand
237    {
238      public:
239        struct Context
240        {
241            const GdbCommand *cmd;
242            char cmd_byte;
243            int type;
244            char *data;
245            int len;
246        };
247
248        typedef bool (BaseRemoteGDB::*Func)(Context &ctx);
249
250        const char * const name;
251        const Func func;
252
253        GdbCommand(const char *_name, Func _func) : name(_name), func(_func) {}
254    };
255
256    static std::map<char, GdbCommand> command_map;
257
258    bool cmd_unsupported(GdbCommand::Context &ctx);
259
260    bool cmd_signal(GdbCommand::Context &ctx);
261    bool cmd_cont(GdbCommand::Context &ctx);
262    bool cmd_async_cont(GdbCommand::Context &ctx);
263    bool cmd_detach(GdbCommand::Context &ctx);
264    bool cmd_reg_r(GdbCommand::Context &ctx);
265    bool cmd_reg_w(GdbCommand::Context &ctx);
266    bool cmd_set_thread(GdbCommand::Context &ctx);
267    bool cmd_mem_r(GdbCommand::Context &ctx);
268    bool cmd_mem_w(GdbCommand::Context &ctx);
269    bool cmd_query_var(GdbCommand::Context &ctx);
270    bool cmd_step(GdbCommand::Context &ctx);
271    bool cmd_async_step(GdbCommand::Context &ctx);
272    bool cmd_clr_hw_bkpt(GdbCommand::Context &ctx);
273    bool cmd_set_hw_bkpt(GdbCommand::Context &ctx);
274
275  protected:
276    ThreadContext *context() { return tc; }
277    System *system() { return sys; }
278
279    // To be implemented by subclasses.
280    virtual bool checkBpLen(size_t len);
281
282    virtual BaseGdbRegCache *gdbRegs() = 0;
283
284    virtual bool acc(Addr addr, size_t len) = 0;
285};
286
287template <class T>
288inline T
289BaseRemoteGDB::read(Addr addr)
290{
291    T temp;
292    read(addr, sizeof(T), (char *)&temp);
293    return temp;
294}
295
296template <class T>
297inline void
298BaseRemoteGDB::write(Addr addr, T data)
299{
300    write(addr, sizeof(T), (const char *)&data);
301}
302
303#endif /* __REMOTE_GDB_H__ */
304