remote_gdb.hh revision 13575:aafa2c83ab3c
12SN/A/*
21762SN/A * Copyright (c) 2018 ARM Limited
32SN/A *
42SN/A * The license below extends only to copyright in the software and shall
52SN/A * not be construed as granting a license to any other intellectual
62SN/A * property including but not limited to intellectual property relating
72SN/A * to a hardware implementation of the functionality of the software
82SN/A * licensed hereunder.  You may use the software subject to the license
92SN/A * terms below provided that you ensure that this notice is replicated
102SN/A * unmodified and in its entirety in all distributions of the software,
112SN/A * modified or unmodified, in source code or in binary form.
122SN/A *
132SN/A * Copyright 2015 LabWare
142SN/A * Copyright 2014 Google, Inc.
152SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan
162SN/A * All rights reserved.
172SN/A *
182SN/A * Redistribution and use in source and binary forms, with or without
192SN/A * modification, are permitted provided that the following conditions are
202SN/A * met: redistributions of source code must retain the above copyright
212SN/A * notice, this list of conditions and the following disclaimer;
222SN/A * redistributions in binary form must reproduce the above copyright
232SN/A * notice, this list of conditions and the following disclaimer in the
242SN/A * documentation and/or other materials provided with the distribution;
252SN/A * neither the name of the copyright holders nor the names of its
262SN/A * contributors may be used to endorse or promote products derived from
272665Ssaidi@eecs.umich.edu * this software without specific prior written permission.
282665Ssaidi@eecs.umich.edu *
292665Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
302SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
312SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3211793Sbrandon.potter@amd.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3311793Sbrandon.potter@amd.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3411793Sbrandon.potter@amd.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
358229Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
368229Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
378229Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3811354SCurtis.Dunham@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
398229Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
408229Snate@binkert.org *
412SN/A * Authors: Nathan Binkert
422SN/A *          Boris Shingarov
432SN/A */
4411793Sbrandon.potter@amd.com
458229Snate@binkert.org#ifndef __REMOTE_GDB_HH__
469538Satgutier@umich.edu#define __REMOTE_GDB_HH__
478229Snate@binkert.org
488229Snate@binkert.org#include <sys/signal.h>
498229Snate@binkert.org
508229Snate@binkert.org#include <exception>
518706Sandreas.hansson@arm.com#include <map>
522420SN/A#include <string>
532SN/A
542SN/A#include "arch/types.hh"
5510880SCurtis.Dunham@arm.com#include "base/intmath.hh"
56360SN/A#include "base/pollevent.hh"
5711391Sbrandon.potter@amd.com#include "base/socket.hh"
5810880SCurtis.Dunham@arm.com#include "cpu/pc_event.hh"
5911391Sbrandon.potter@amd.com
6010422Sandreas.hansson@arm.comclass System;
6112SN/Aclass ThreadContext;
6212SN/A
632SN/Aclass BaseRemoteGDB;
642SN/Aclass HardBreakpoint;
652SN/A
662SN/A/**
6711391Sbrandon.potter@amd.com * Concrete subclasses of this abstract class represent how the
6811391Sbrandon.potter@amd.com * register values are transmitted on the wire.  Usually each
6911391Sbrandon.potter@amd.com * architecture should define one subclass, but there can be more
7011391Sbrandon.potter@amd.com * if there is more than one possible wire format.  For example,
7112SN/A * ARM defines both AArch32GdbRegCache and AArch64GdbRegCache.
722SN/A */
732SN/Aclass BaseGdbRegCache
742420SN/A{
7511391Sbrandon.potter@amd.com  public:
7611391Sbrandon.potter@amd.com
772420SN/A    /**
782420SN/A     * Return the pointer to the raw bytes buffer containing the
7911391Sbrandon.potter@amd.com     * register values.  Each byte of this buffer is literally
802420SN/A     * encoded as two hex digits in the g or G RSP packet.
8111391Sbrandon.potter@amd.com     */
822420SN/A    virtual char *data() const = 0;
832420SN/A
842420SN/A    /**
8511391Sbrandon.potter@amd.com     * Return the size of the raw buffer, in bytes
862420SN/A     * (i.e., half of the number of digits in the g/G packet).
872420SN/A     */
882420SN/A    virtual size_t size() const = 0;
892420SN/A
902420SN/A    /**
912420SN/A     * Fill the raw buffer from the registers in the ThreadContext.
922420SN/A     */
9311391Sbrandon.potter@amd.com    virtual void getRegs(ThreadContext*) = 0;
942420SN/A
9511391Sbrandon.potter@amd.com    /**
9611391Sbrandon.potter@amd.com     * Set the ThreadContext's registers from the values
9711391Sbrandon.potter@amd.com     * in the raw buffer.
982SN/A     */
992SN/A    virtual void setRegs(ThreadContext*) const = 0;
10011354SCurtis.Dunham@arm.com
10111354SCurtis.Dunham@arm.com    /**
10211354SCurtis.Dunham@arm.com     * Return the name to use in places like DPRINTF.
10311354SCurtis.Dunham@arm.com     * Having each concrete superclass redefine this member
10411354SCurtis.Dunham@arm.com     * is useful in situations where the class of the regCache
10511354SCurtis.Dunham@arm.com     * can change on the fly.
10611354SCurtis.Dunham@arm.com     */
10711354SCurtis.Dunham@arm.com    virtual const std::string name() const = 0;
10811354SCurtis.Dunham@arm.com
10911354SCurtis.Dunham@arm.com    BaseGdbRegCache(BaseRemoteGDB *g) : gdb(g)
11011354SCurtis.Dunham@arm.com    {}
11111354SCurtis.Dunham@arm.com    virtual ~BaseGdbRegCache()
11211354SCurtis.Dunham@arm.com    {}
11311354SCurtis.Dunham@arm.com
11411354SCurtis.Dunham@arm.com  protected:
11511354SCurtis.Dunham@arm.com    BaseRemoteGDB *gdb;
11611354SCurtis.Dunham@arm.com};
11711354SCurtis.Dunham@arm.com
11811354SCurtis.Dunham@arm.comclass BaseRemoteGDB
11911354SCurtis.Dunham@arm.com{
12011354SCurtis.Dunham@arm.com    friend class HardBreakpoint;
12111354SCurtis.Dunham@arm.com  public:
12211354SCurtis.Dunham@arm.com
12311354SCurtis.Dunham@arm.com    /*
12411354SCurtis.Dunham@arm.com     * Interface to other parts of the simulator.
12511354SCurtis.Dunham@arm.com     */
12611354SCurtis.Dunham@arm.com    BaseRemoteGDB(System *system, ThreadContext *context, int _port);
12711354SCurtis.Dunham@arm.com    virtual ~BaseRemoteGDB();
12811354SCurtis.Dunham@arm.com
12911354SCurtis.Dunham@arm.com    std::string name();
13011354SCurtis.Dunham@arm.com
13111354SCurtis.Dunham@arm.com    void listen();
13211354SCurtis.Dunham@arm.com    void connect();
13311354SCurtis.Dunham@arm.com
13411354SCurtis.Dunham@arm.com    int port() const;
13511354SCurtis.Dunham@arm.com
13611354SCurtis.Dunham@arm.com    void attach(int fd);
13711354SCurtis.Dunham@arm.com    void detach();
13811354SCurtis.Dunham@arm.com    bool isAttached() { return attached; }
13911354SCurtis.Dunham@arm.com
14011354SCurtis.Dunham@arm.com    void replaceThreadContext(ThreadContext *_tc) { tc = _tc; }
14111354SCurtis.Dunham@arm.com
14211354SCurtis.Dunham@arm.com    bool trap(int type);
14311354SCurtis.Dunham@arm.com    bool breakpoint() { return trap(SIGTRAP); }
14411354SCurtis.Dunham@arm.com
14511354SCurtis.Dunham@arm.com  private:
14611354SCurtis.Dunham@arm.com    /*
14711354SCurtis.Dunham@arm.com     * Connection to the external GDB.
14811354SCurtis.Dunham@arm.com     */
14911354SCurtis.Dunham@arm.com    void incomingData(int revent);
15011354SCurtis.Dunham@arm.com    void connectWrapper(int revent) { connect(); }
15111354SCurtis.Dunham@arm.com
15211354SCurtis.Dunham@arm.com    template <void (BaseRemoteGDB::*F)(int revent)>
15311354SCurtis.Dunham@arm.com    class SocketEvent : public PollEvent
15411354SCurtis.Dunham@arm.com    {
15512SN/A      protected:
15612SN/A        BaseRemoteGDB *gdb;
1573584Ssaidi@eecs.umich.edu
1582SN/A      public:
15912SN/A        SocketEvent(BaseRemoteGDB *gdb, int fd, int e) :
16012SN/A            PollEvent(fd, e), gdb(gdb)
16112SN/A        {}
16212SN/A
1632SN/A        void process(int revent) { (gdb->*F)(revent); }
1642SN/A    };
16511354SCurtis.Dunham@arm.com
16611354SCurtis.Dunham@arm.com    typedef SocketEvent<&BaseRemoteGDB::connectWrapper> ConnectEvent;
16711354SCurtis.Dunham@arm.com    typedef SocketEvent<&BaseRemoteGDB::incomingData> DataEvent;
16811354SCurtis.Dunham@arm.com
16911354SCurtis.Dunham@arm.com    friend ConnectEvent;
17011354SCurtis.Dunham@arm.com    friend DataEvent;
17111354SCurtis.Dunham@arm.com
17211354SCurtis.Dunham@arm.com    ConnectEvent *connectEvent;
17312SN/A    DataEvent *dataEvent;
17410422Sandreas.hansson@arm.com
17511354SCurtis.Dunham@arm.com    ListenSocket listener;
17611354SCurtis.Dunham@arm.com    int _port;
17711354SCurtis.Dunham@arm.com
17812SN/A    // The socket commands come in through.
17912SN/A    int fd;
18011391Sbrandon.potter@amd.com
18111391Sbrandon.potter@amd.com    // Transfer data to/from GDB.
18210880SCurtis.Dunham@arm.com    uint8_t getbyte();
18311354SCurtis.Dunham@arm.com    void putbyte(uint8_t b);
18411391Sbrandon.potter@amd.com
18512SN/A    void recv(std::vector<char> &bp);
1862SN/A    void send(const char *data);
1872SN/A
18811391Sbrandon.potter@amd.com    /*
1892SN/A     * Simulator side debugger state.
19012SN/A     */
19111391Sbrandon.potter@amd.com    bool active;
19211391Sbrandon.potter@amd.com    bool attached;
1932SN/A
1942SN/A    System *sys;
19511391Sbrandon.potter@amd.com    ThreadContext *tc;
19611391Sbrandon.potter@amd.com
1972SN/A    BaseGdbRegCache *regCachePtr;
1982SN/A
19911391Sbrandon.potter@amd.com    class TrapEvent : public Event
20011391Sbrandon.potter@amd.com    {
2012SN/A      protected:
2022SN/A        int _type;
20311391Sbrandon.potter@amd.com        BaseRemoteGDB *gdb;
20411391Sbrandon.potter@amd.com
2059538Satgutier@umich.edu      public:
2069538Satgutier@umich.edu        TrapEvent(BaseRemoteGDB *g) : gdb(g)
2073584Ssaidi@eecs.umich.edu        {}
20811391Sbrandon.potter@amd.com
2093584Ssaidi@eecs.umich.edu        void type(int t) { _type = t; }
21012SN/A        void process() { gdb->trap(_type); }
21111391Sbrandon.potter@amd.com    } trapEvent;
21212SN/A
2132SN/A    /*
214     * The interface to the simulated system.
215     */
216    // Machine memory.
217    bool read(Addr addr, size_t size, char *data);
218    bool write(Addr addr, size_t size, const char *data);
219
220    template <class T> T read(Addr addr);
221    template <class T> void write(Addr addr, T data);
222
223    // Single step.
224    void singleStep();
225    EventWrapper<BaseRemoteGDB, &BaseRemoteGDB::singleStep> singleStepEvent;
226
227    void clearSingleStep();
228    void setSingleStep();
229
230    /// Schedule an event which will be triggered "delta" instructions later.
231    void scheduleInstCommitEvent(Event *ev, int delta);
232    /// Deschedule an instruction count based event.
233    void descheduleInstCommitEvent(Event *ev);
234
235    // Breakpoints.
236    void insertSoftBreak(Addr addr, size_t len);
237    void removeSoftBreak(Addr addr, size_t len);
238    void insertHardBreak(Addr addr, size_t len);
239    void removeHardBreak(Addr addr, size_t len);
240
241    void clearTempBreakpoint(Addr &bkpt);
242    void setTempBreakpoint(Addr bkpt);
243
244    /*
245     * GDB commands.
246     */
247    struct GdbCommand
248    {
249      public:
250        struct Context
251        {
252            const GdbCommand *cmd;
253            char cmd_byte;
254            int type;
255            char *data;
256            int len;
257        };
258
259        typedef bool (BaseRemoteGDB::*Func)(Context &ctx);
260
261        const char * const name;
262        const Func func;
263
264        GdbCommand(const char *_name, Func _func) : name(_name), func(_func) {}
265    };
266
267    static std::map<char, GdbCommand> command_map;
268
269    bool cmd_unsupported(GdbCommand::Context &ctx);
270
271    bool cmd_signal(GdbCommand::Context &ctx);
272    bool cmd_cont(GdbCommand::Context &ctx);
273    bool cmd_async_cont(GdbCommand::Context &ctx);
274    bool cmd_detach(GdbCommand::Context &ctx);
275    bool cmd_reg_r(GdbCommand::Context &ctx);
276    bool cmd_reg_w(GdbCommand::Context &ctx);
277    bool cmd_set_thread(GdbCommand::Context &ctx);
278    bool cmd_mem_r(GdbCommand::Context &ctx);
279    bool cmd_mem_w(GdbCommand::Context &ctx);
280    bool cmd_query_var(GdbCommand::Context &ctx);
281    bool cmd_step(GdbCommand::Context &ctx);
282    bool cmd_async_step(GdbCommand::Context &ctx);
283    bool cmd_clr_hw_bkpt(GdbCommand::Context &ctx);
284    bool cmd_set_hw_bkpt(GdbCommand::Context &ctx);
285
286  protected:
287    ThreadContext *context() { return tc; }
288    System *system() { return sys; }
289
290    void encodeBinaryData(const std::string &unencoded,
291            std::string &encoded) const;
292
293    void encodeXferResponse(const std::string &unencoded,
294        std::string &encoded, size_t offset, size_t unencoded_length) const;
295
296    // To be implemented by subclasses.
297    virtual bool checkBpLen(size_t len);
298
299    virtual BaseGdbRegCache *gdbRegs() = 0;
300
301    virtual bool acc(Addr addr, size_t len) = 0;
302
303    virtual std::vector<std::string> availableFeatures() const;
304
305    /**
306     * Get an XML target description.
307     *
308     * @param[in] annex the XML filename
309     * @param[out] output set to the decoded XML
310     * @return true if the given annex was found
311     */
312    virtual bool getXferFeaturesRead(const std::string &annex,
313            std::string &output);
314};
315
316template <class T>
317inline T
318BaseRemoteGDB::read(Addr addr)
319{
320    T temp;
321    read(addr, sizeof(T), (char *)&temp);
322    return temp;
323}
324
325template <class T>
326inline void
327BaseRemoteGDB::write(Addr addr, T data)
328{
329    write(addr, sizeof(T), (const char *)&data);
330}
331
332#endif /* __REMOTE_GDB_H__ */
333