remote_gdb.hh revision 12449
12SN/A/*
211274Sshingarov@labware.com * Copyright 2015 LabWare
310595Sgabeblack@google.com * Copyright 2014 Google, Inc.
41762SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan
52SN/A * All rights reserved.
62SN/A *
72SN/A * Redistribution and use in source and binary forms, with or without
82SN/A * modification, are permitted provided that the following conditions are
92SN/A * met: redistributions of source code must retain the above copyright
102SN/A * notice, this list of conditions and the following disclaimer;
112SN/A * redistributions in binary form must reproduce the above copyright
122SN/A * notice, this list of conditions and the following disclaimer in the
132SN/A * documentation and/or other materials provided with the distribution;
142SN/A * neither the name of the copyright holders nor the names of its
152SN/A * contributors may be used to endorse or promote products derived from
162SN/A * this software without specific prior written permission.
172SN/A *
182SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
192SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
202SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
212SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
222SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
232SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
242SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
252SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
262SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
272SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
282SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
292665Ssaidi@eecs.umich.edu *
302665Ssaidi@eecs.umich.edu * Authors: Nathan Binkert
3111274Sshingarov@labware.com *          Boris Shingarov
322SN/A */
332SN/A
342SN/A#ifndef __REMOTE_GDB_HH__
352SN/A#define __REMOTE_GDB_HH__
362SN/A
373960Sgblack@eecs.umich.edu#include <sys/signal.h>
3877SN/A
3912031Sgabeblack@google.com#include <exception>
408229Snate@binkert.org#include <map>
4112031Sgabeblack@google.com#include <string>
428229Snate@binkert.org
432986Sgblack@eecs.umich.edu#include "arch/types.hh"
4410595Sgabeblack@google.com#include "base/intmath.hh"
4556SN/A#include "base/pollevent.hh"
4656SN/A#include "base/socket.hh"
478229Snate@binkert.org#include "cpu/pc_event.hh"
482SN/A
492SN/Aclass System;
502680Sktlim@umich.educlass ThreadContext;
512SN/A
5212449Sgabeblack@google.comclass BaseRemoteGDB;
5312449Sgabeblack@google.comclass HardBreakpoint;
543536Sgblack@eecs.umich.edu
5512449Sgabeblack@google.com/**
5612449Sgabeblack@google.com * Concrete subclasses of this abstract class represent how the
5712449Sgabeblack@google.com * register values are transmitted on the wire.  Usually each
5812449Sgabeblack@google.com * architecture should define one subclass, but there can be more
5912449Sgabeblack@google.com * if there is more than one possible wire format.  For example,
6012449Sgabeblack@google.com * ARM defines both AArch32GdbRegCache and AArch64GdbRegCache.
6112449Sgabeblack@google.com */
6212449Sgabeblack@google.comclass BaseGdbRegCache
632SN/A{
6412031Sgabeblack@google.com  public:
6512031Sgabeblack@google.com
6612449Sgabeblack@google.com    /**
6712449Sgabeblack@google.com     * Return the pointer to the raw bytes buffer containing the
6812449Sgabeblack@google.com     * register values.  Each byte of this buffer is literally
6912449Sgabeblack@google.com     * encoded as two hex digits in the g or G RSP packet.
7012449Sgabeblack@google.com     */
7112449Sgabeblack@google.com    virtual char *data() const = 0;
7212031Sgabeblack@google.com
7312449Sgabeblack@google.com    /**
7412449Sgabeblack@google.com     * Return the size of the raw buffer, in bytes
7512449Sgabeblack@google.com     * (i.e., half of the number of digits in the g/G packet).
7612449Sgabeblack@google.com     */
7712449Sgabeblack@google.com    virtual size_t size() const = 0;
7812031Sgabeblack@google.com
7912449Sgabeblack@google.com    /**
8012449Sgabeblack@google.com     * Fill the raw buffer from the registers in the ThreadContext.
8112449Sgabeblack@google.com     */
8212449Sgabeblack@google.com    virtual void getRegs(ThreadContext*) = 0;
8312449Sgabeblack@google.com
8412449Sgabeblack@google.com    /**
8512449Sgabeblack@google.com     * Set the ThreadContext's registers from the values
8612449Sgabeblack@google.com     * in the raw buffer.
8712449Sgabeblack@google.com     */
8812449Sgabeblack@google.com    virtual void setRegs(ThreadContext*) const = 0;
8912449Sgabeblack@google.com
9012449Sgabeblack@google.com    /**
9112449Sgabeblack@google.com     * Return the name to use in places like DPRINTF.
9212449Sgabeblack@google.com     * Having each concrete superclass redefine this member
9312449Sgabeblack@google.com     * is useful in situations where the class of the regCache
9412449Sgabeblack@google.com     * can change on the fly.
9512449Sgabeblack@google.com     */
9612449Sgabeblack@google.com    virtual const std::string name() const = 0;
9712449Sgabeblack@google.com
9812449Sgabeblack@google.com    BaseGdbRegCache(BaseRemoteGDB *g) : gdb(g)
9912031Sgabeblack@google.com    {}
10012449Sgabeblack@google.com    virtual ~BaseGdbRegCache()
10112449Sgabeblack@google.com    {}
10212449Sgabeblack@google.com
10312449Sgabeblack@google.com  protected:
10412449Sgabeblack@google.com    BaseRemoteGDB *gdb;
1053536Sgblack@eecs.umich.edu};
1063536Sgblack@eecs.umich.edu
1073536Sgblack@eecs.umich.educlass BaseRemoteGDB
1083536Sgblack@eecs.umich.edu{
10912449Sgabeblack@google.com    friend class HardBreakpoint;
11012449Sgabeblack@google.com  public:
11112449Sgabeblack@google.com
11212449Sgabeblack@google.com    /*
11312449Sgabeblack@google.com     * Interface to other parts of the simulator.
11412449Sgabeblack@google.com     */
11512449Sgabeblack@google.com    BaseRemoteGDB(System *system, ThreadContext *context, int _port);
11612449Sgabeblack@google.com    virtual ~BaseRemoteGDB();
11712449Sgabeblack@google.com
11812449Sgabeblack@google.com    std::string name();
11912449Sgabeblack@google.com
12012449Sgabeblack@google.com    void listen();
12112449Sgabeblack@google.com    void connect();
12212449Sgabeblack@google.com
12312449Sgabeblack@google.com    int port() const;
12412449Sgabeblack@google.com
12512449Sgabeblack@google.com    void attach(int fd);
12612449Sgabeblack@google.com    void detach();
12712449Sgabeblack@google.com    bool isAttached() { return attached; }
12812449Sgabeblack@google.com
12912449Sgabeblack@google.com    void replaceThreadContext(ThreadContext *_tc) { tc = _tc; }
13012449Sgabeblack@google.com
13112449Sgabeblack@google.com    bool trap(int type);
13212449Sgabeblack@google.com    bool breakpoint() { return trap(SIGTRAP); }
13312449Sgabeblack@google.com
1341910SN/A  private:
13512449Sgabeblack@google.com    /*
13612449Sgabeblack@google.com     * Connection to the external GDB.
13712449Sgabeblack@google.com     */
13812449Sgabeblack@google.com    void incomingData(int revent);
13912449Sgabeblack@google.com    void connectWrapper(int revent) { connect(); }
1401910SN/A
14112449Sgabeblack@google.com    template <void (BaseRemoteGDB::*F)(int revent)>
14212449Sgabeblack@google.com    class SocketEvent : public PollEvent
14312031Sgabeblack@google.com    {
14412449Sgabeblack@google.com      protected:
14512449Sgabeblack@google.com        BaseRemoteGDB *gdb;
14612449Sgabeblack@google.com
14712449Sgabeblack@google.com      public:
14812449Sgabeblack@google.com        SocketEvent(BaseRemoteGDB *gdb, int fd, int e) :
14912449Sgabeblack@google.com            PollEvent(fd, e), gdb(gdb)
15012031Sgabeblack@google.com        {}
15112449Sgabeblack@google.com
15212449Sgabeblack@google.com        void process(int revent) { (gdb->*F)(revent); }
15312031Sgabeblack@google.com    };
15412449Sgabeblack@google.com
15512449Sgabeblack@google.com    typedef SocketEvent<&BaseRemoteGDB::connectWrapper> ConnectEvent;
15612449Sgabeblack@google.com    typedef SocketEvent<&BaseRemoteGDB::incomingData> DataEvent;
15712449Sgabeblack@google.com
15812449Sgabeblack@google.com    friend ConnectEvent;
15912449Sgabeblack@google.com    friend DataEvent;
16012449Sgabeblack@google.com
16112449Sgabeblack@google.com    ConnectEvent *connectEvent;
16212449Sgabeblack@google.com    DataEvent *dataEvent;
16312449Sgabeblack@google.com
16412449Sgabeblack@google.com    ListenSocket listener;
16512449Sgabeblack@google.com    int _port;
16612449Sgabeblack@google.com
16712449Sgabeblack@google.com    // The socket commands come in through.
16812449Sgabeblack@google.com    int fd;
16912449Sgabeblack@google.com
17012449Sgabeblack@google.com    // Transfer data to/from GDB.
17112449Sgabeblack@google.com    uint8_t getbyte();
17212449Sgabeblack@google.com    void putbyte(uint8_t b);
17312449Sgabeblack@google.com
17412449Sgabeblack@google.com    int recv(char *data, int len);
17512449Sgabeblack@google.com    void send(const char *data);
17612449Sgabeblack@google.com
17712449Sgabeblack@google.com    /*
17812449Sgabeblack@google.com     * Simulator side debugger state.
17912449Sgabeblack@google.com     */
18012449Sgabeblack@google.com    bool active;
18112449Sgabeblack@google.com    bool attached;
18212449Sgabeblack@google.com
18312449Sgabeblack@google.com    System *sys;
18412449Sgabeblack@google.com    ThreadContext *tc;
18512449Sgabeblack@google.com
18612449Sgabeblack@google.com    BaseGdbRegCache *regCachePtr;
18712449Sgabeblack@google.com
18812449Sgabeblack@google.com    class TrapEvent : public Event
18912031Sgabeblack@google.com    {
19012449Sgabeblack@google.com      protected:
19112449Sgabeblack@google.com        int _type;
19212449Sgabeblack@google.com        BaseRemoteGDB *gdb;
19312449Sgabeblack@google.com
19412449Sgabeblack@google.com      public:
19512449Sgabeblack@google.com        TrapEvent(BaseRemoteGDB *g) : gdb(g)
19612031Sgabeblack@google.com        {}
19712449Sgabeblack@google.com
19812449Sgabeblack@google.com        void type(int t) { _type = t; }
19912449Sgabeblack@google.com        void process() { gdb->trap(_type); }
20012449Sgabeblack@google.com    } trapEvent;
20112449Sgabeblack@google.com
20212449Sgabeblack@google.com    /*
20312449Sgabeblack@google.com     * The interface to the simulated system.
20412449Sgabeblack@google.com     */
20512449Sgabeblack@google.com    // Machine memory.
20612449Sgabeblack@google.com    bool read(Addr addr, size_t size, char *data);
20712449Sgabeblack@google.com    bool write(Addr addr, size_t size, const char *data);
20812449Sgabeblack@google.com
20912449Sgabeblack@google.com    template <class T> T read(Addr addr);
21012449Sgabeblack@google.com    template <class T> void write(Addr addr, T data);
21112449Sgabeblack@google.com
21212449Sgabeblack@google.com    // Single step.
21312449Sgabeblack@google.com    void singleStep();
21412449Sgabeblack@google.com    EventWrapper<BaseRemoteGDB, &BaseRemoteGDB::singleStep> singleStepEvent;
21512449Sgabeblack@google.com
21612449Sgabeblack@google.com    void clearSingleStep();
21712449Sgabeblack@google.com    void setSingleStep();
21812449Sgabeblack@google.com
21912449Sgabeblack@google.com    /// Schedule an event which will be triggered "delta" instructions later.
22012449Sgabeblack@google.com    void scheduleInstCommitEvent(Event *ev, int delta);
22112449Sgabeblack@google.com    /// Deschedule an instruction count based event.
22212449Sgabeblack@google.com    void descheduleInstCommitEvent(Event *ev);
22312449Sgabeblack@google.com
22412449Sgabeblack@google.com    // Breakpoints.
22512449Sgabeblack@google.com    void insertSoftBreak(Addr addr, size_t len);
22612449Sgabeblack@google.com    void removeSoftBreak(Addr addr, size_t len);
22712449Sgabeblack@google.com    void insertHardBreak(Addr addr, size_t len);
22812449Sgabeblack@google.com    void removeHardBreak(Addr addr, size_t len);
22912449Sgabeblack@google.com
23012449Sgabeblack@google.com    void clearTempBreakpoint(Addr &bkpt);
23112449Sgabeblack@google.com    void setTempBreakpoint(Addr bkpt);
23212449Sgabeblack@google.com
23312449Sgabeblack@google.com    /*
23412449Sgabeblack@google.com     * GDB commands.
23512449Sgabeblack@google.com     */
23612449Sgabeblack@google.com    struct GdbCommand
23712449Sgabeblack@google.com    {
23812449Sgabeblack@google.com      public:
23912449Sgabeblack@google.com        struct Context
24012449Sgabeblack@google.com        {
24112449Sgabeblack@google.com            const GdbCommand *cmd;
24212449Sgabeblack@google.com            char cmd_byte;
24312449Sgabeblack@google.com            int type;
24412449Sgabeblack@google.com            char *data;
24512449Sgabeblack@google.com            int len;
24612449Sgabeblack@google.com        };
24712449Sgabeblack@google.com
24812449Sgabeblack@google.com        typedef bool (BaseRemoteGDB::*Func)(Context &ctx);
24912449Sgabeblack@google.com
25012449Sgabeblack@google.com        const char * const name;
25112449Sgabeblack@google.com        const Func func;
25212449Sgabeblack@google.com
25312449Sgabeblack@google.com        GdbCommand(const char *_name, Func _func) : name(_name), func(_func) {}
25412031Sgabeblack@google.com    };
25512031Sgabeblack@google.com
25612031Sgabeblack@google.com    static std::map<char, GdbCommand> command_map;
25712031Sgabeblack@google.com
25812031Sgabeblack@google.com    bool cmd_unsupported(GdbCommand::Context &ctx);
25912031Sgabeblack@google.com
26012031Sgabeblack@google.com    bool cmd_signal(GdbCommand::Context &ctx);
26112031Sgabeblack@google.com    bool cmd_cont(GdbCommand::Context &ctx);
26212031Sgabeblack@google.com    bool cmd_async_cont(GdbCommand::Context &ctx);
26312031Sgabeblack@google.com    bool cmd_detach(GdbCommand::Context &ctx);
26412031Sgabeblack@google.com    bool cmd_reg_r(GdbCommand::Context &ctx);
26512031Sgabeblack@google.com    bool cmd_reg_w(GdbCommand::Context &ctx);
26612031Sgabeblack@google.com    bool cmd_set_thread(GdbCommand::Context &ctx);
26712031Sgabeblack@google.com    bool cmd_mem_r(GdbCommand::Context &ctx);
26812031Sgabeblack@google.com    bool cmd_mem_w(GdbCommand::Context &ctx);
26912031Sgabeblack@google.com    bool cmd_query_var(GdbCommand::Context &ctx);
27012031Sgabeblack@google.com    bool cmd_step(GdbCommand::Context &ctx);
27112031Sgabeblack@google.com    bool cmd_async_step(GdbCommand::Context &ctx);
27212031Sgabeblack@google.com    bool cmd_clr_hw_bkpt(GdbCommand::Context &ctx);
27312031Sgabeblack@google.com    bool cmd_set_hw_bkpt(GdbCommand::Context &ctx);
2743536Sgblack@eecs.umich.edu
2752SN/A  protected:
27612449Sgabeblack@google.com    ThreadContext *context() { return tc; }
27712449Sgabeblack@google.com    System *system() { return sys; }
2782SN/A
27912449Sgabeblack@google.com    // To be implemented by subclasses.
28012449Sgabeblack@google.com    virtual bool checkBpLen(size_t len);
2812SN/A
28211274Sshingarov@labware.com    virtual BaseGdbRegCache *gdbRegs() = 0;
2832SN/A
2843536Sgblack@eecs.umich.edu    virtual bool acc(Addr addr, size_t len) = 0;
2852SN/A};
2862SN/A
2872SN/Atemplate <class T>
2882SN/Ainline T
2893536Sgblack@eecs.umich.eduBaseRemoteGDB::read(Addr addr)
2902SN/A{
2912SN/A    T temp;
2922SN/A    read(addr, sizeof(T), (char *)&temp);
2932SN/A    return temp;
2942SN/A}
2952SN/A
2962SN/Atemplate <class T>
2972SN/Ainline void
2983536Sgblack@eecs.umich.eduBaseRemoteGDB::write(Addr addr, T data)
2992SN/A{
30012449Sgabeblack@google.com    write(addr, sizeof(T), (const char *)&data);
30112449Sgabeblack@google.com}
3022SN/A
3032SN/A#endif /* __REMOTE_GDB_H__ */
304