12SN/A/*
213575Sciro.santilli@arm.com * Copyright (c) 2018 ARM Limited
313575Sciro.santilli@arm.com *
413575Sciro.santilli@arm.com * The license below extends only to copyright in the software and shall
513575Sciro.santilli@arm.com * not be construed as granting a license to any other intellectual
613575Sciro.santilli@arm.com * property including but not limited to intellectual property relating
713575Sciro.santilli@arm.com * to a hardware implementation of the functionality of the software
813575Sciro.santilli@arm.com * licensed hereunder.  You may use the software subject to the license
913575Sciro.santilli@arm.com * terms below provided that you ensure that this notice is replicated
1013575Sciro.santilli@arm.com * unmodified and in its entirety in all distributions of the software,
1113575Sciro.santilli@arm.com * modified or unmodified, in source code or in binary form.
1213575Sciro.santilli@arm.com *
1311274Sshingarov@labware.com * Copyright 2015 LabWare
1410595Sgabeblack@google.com * Copyright 2014 Google, Inc.
151762SN/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
272SN/A * this software without specific prior written permission.
282SN/A *
292SN/A * 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
322SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
332SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
342SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
352SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
362SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
372SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
382SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
392SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
402665Ssaidi@eecs.umich.edu *
412665Ssaidi@eecs.umich.edu * Authors: Nathan Binkert
4211274Sshingarov@labware.com *          Boris Shingarov
432SN/A */
442SN/A
452SN/A#ifndef __REMOTE_GDB_HH__
462SN/A#define __REMOTE_GDB_HH__
472SN/A
483960Sgblack@eecs.umich.edu#include <sys/signal.h>
4977SN/A
5012031Sgabeblack@google.com#include <exception>
518229Snate@binkert.org#include <map>
5212031Sgabeblack@google.com#include <string>
538229Snate@binkert.org
542986Sgblack@eecs.umich.edu#include "arch/types.hh"
5510595Sgabeblack@google.com#include "base/intmath.hh"
5656SN/A#include "base/pollevent.hh"
5756SN/A#include "base/socket.hh"
588229Snate@binkert.org#include "cpu/pc_event.hh"
592SN/A
602SN/Aclass System;
612680Sktlim@umich.educlass ThreadContext;
622SN/A
6312449Sgabeblack@google.comclass BaseRemoteGDB;
6412449Sgabeblack@google.comclass HardBreakpoint;
653536Sgblack@eecs.umich.edu
6612449Sgabeblack@google.com/**
6712449Sgabeblack@google.com * Concrete subclasses of this abstract class represent how the
6812449Sgabeblack@google.com * register values are transmitted on the wire.  Usually each
6912449Sgabeblack@google.com * architecture should define one subclass, but there can be more
7012449Sgabeblack@google.com * if there is more than one possible wire format.  For example,
7112449Sgabeblack@google.com * ARM defines both AArch32GdbRegCache and AArch64GdbRegCache.
7212449Sgabeblack@google.com */
7312449Sgabeblack@google.comclass BaseGdbRegCache
742SN/A{
7512031Sgabeblack@google.com  public:
7612031Sgabeblack@google.com
7712449Sgabeblack@google.com    /**
7812449Sgabeblack@google.com     * Return the pointer to the raw bytes buffer containing the
7912449Sgabeblack@google.com     * register values.  Each byte of this buffer is literally
8012449Sgabeblack@google.com     * encoded as two hex digits in the g or G RSP packet.
8112449Sgabeblack@google.com     */
8212449Sgabeblack@google.com    virtual char *data() const = 0;
8312031Sgabeblack@google.com
8412449Sgabeblack@google.com    /**
8512449Sgabeblack@google.com     * Return the size of the raw buffer, in bytes
8612449Sgabeblack@google.com     * (i.e., half of the number of digits in the g/G packet).
8712449Sgabeblack@google.com     */
8812449Sgabeblack@google.com    virtual size_t size() const = 0;
8912031Sgabeblack@google.com
9012449Sgabeblack@google.com    /**
9112449Sgabeblack@google.com     * Fill the raw buffer from the registers in the ThreadContext.
9212449Sgabeblack@google.com     */
9312449Sgabeblack@google.com    virtual void getRegs(ThreadContext*) = 0;
9412449Sgabeblack@google.com
9512449Sgabeblack@google.com    /**
9612449Sgabeblack@google.com     * Set the ThreadContext's registers from the values
9712449Sgabeblack@google.com     * in the raw buffer.
9812449Sgabeblack@google.com     */
9912449Sgabeblack@google.com    virtual void setRegs(ThreadContext*) const = 0;
10012449Sgabeblack@google.com
10112449Sgabeblack@google.com    /**
10212449Sgabeblack@google.com     * Return the name to use in places like DPRINTF.
10312449Sgabeblack@google.com     * Having each concrete superclass redefine this member
10412449Sgabeblack@google.com     * is useful in situations where the class of the regCache
10512449Sgabeblack@google.com     * can change on the fly.
10612449Sgabeblack@google.com     */
10712449Sgabeblack@google.com    virtual const std::string name() const = 0;
10812449Sgabeblack@google.com
10912449Sgabeblack@google.com    BaseGdbRegCache(BaseRemoteGDB *g) : gdb(g)
11012031Sgabeblack@google.com    {}
11112449Sgabeblack@google.com    virtual ~BaseGdbRegCache()
11212449Sgabeblack@google.com    {}
11312449Sgabeblack@google.com
11412449Sgabeblack@google.com  protected:
11512449Sgabeblack@google.com    BaseRemoteGDB *gdb;
1163536Sgblack@eecs.umich.edu};
1173536Sgblack@eecs.umich.edu
1183536Sgblack@eecs.umich.educlass BaseRemoteGDB
1193536Sgblack@eecs.umich.edu{
12012449Sgabeblack@google.com    friend class HardBreakpoint;
12112449Sgabeblack@google.com  public:
12212449Sgabeblack@google.com
12312449Sgabeblack@google.com    /*
12412449Sgabeblack@google.com     * Interface to other parts of the simulator.
12512449Sgabeblack@google.com     */
12612449Sgabeblack@google.com    BaseRemoteGDB(System *system, ThreadContext *context, int _port);
12712449Sgabeblack@google.com    virtual ~BaseRemoteGDB();
12812449Sgabeblack@google.com
12912449Sgabeblack@google.com    std::string name();
13012449Sgabeblack@google.com
13112449Sgabeblack@google.com    void listen();
13212449Sgabeblack@google.com    void connect();
13312449Sgabeblack@google.com
13412449Sgabeblack@google.com    int port() const;
13512449Sgabeblack@google.com
13612449Sgabeblack@google.com    void attach(int fd);
13712449Sgabeblack@google.com    void detach();
13812449Sgabeblack@google.com    bool isAttached() { return attached; }
13912449Sgabeblack@google.com
14012449Sgabeblack@google.com    void replaceThreadContext(ThreadContext *_tc) { tc = _tc; }
14112449Sgabeblack@google.com
14212449Sgabeblack@google.com    bool trap(int type);
14312449Sgabeblack@google.com    bool breakpoint() { return trap(SIGTRAP); }
14412449Sgabeblack@google.com
1451910SN/A  private:
14612449Sgabeblack@google.com    /*
14712449Sgabeblack@google.com     * Connection to the external GDB.
14812449Sgabeblack@google.com     */
14912449Sgabeblack@google.com    void incomingData(int revent);
15012449Sgabeblack@google.com    void connectWrapper(int revent) { connect(); }
1511910SN/A
15212449Sgabeblack@google.com    template <void (BaseRemoteGDB::*F)(int revent)>
15312449Sgabeblack@google.com    class SocketEvent : public PollEvent
15412031Sgabeblack@google.com    {
15512449Sgabeblack@google.com      protected:
15612449Sgabeblack@google.com        BaseRemoteGDB *gdb;
15712449Sgabeblack@google.com
15812449Sgabeblack@google.com      public:
15912449Sgabeblack@google.com        SocketEvent(BaseRemoteGDB *gdb, int fd, int e) :
16012449Sgabeblack@google.com            PollEvent(fd, e), gdb(gdb)
16112031Sgabeblack@google.com        {}
16212449Sgabeblack@google.com
16312449Sgabeblack@google.com        void process(int revent) { (gdb->*F)(revent); }
16412031Sgabeblack@google.com    };
16512449Sgabeblack@google.com
16612449Sgabeblack@google.com    typedef SocketEvent<&BaseRemoteGDB::connectWrapper> ConnectEvent;
16712449Sgabeblack@google.com    typedef SocketEvent<&BaseRemoteGDB::incomingData> DataEvent;
16812449Sgabeblack@google.com
16912449Sgabeblack@google.com    friend ConnectEvent;
17012449Sgabeblack@google.com    friend DataEvent;
17112449Sgabeblack@google.com
17212449Sgabeblack@google.com    ConnectEvent *connectEvent;
17312449Sgabeblack@google.com    DataEvent *dataEvent;
17412449Sgabeblack@google.com
17512449Sgabeblack@google.com    ListenSocket listener;
17612449Sgabeblack@google.com    int _port;
17712449Sgabeblack@google.com
17812449Sgabeblack@google.com    // The socket commands come in through.
17912449Sgabeblack@google.com    int fd;
18012449Sgabeblack@google.com
18112449Sgabeblack@google.com    // Transfer data to/from GDB.
18212449Sgabeblack@google.com    uint8_t getbyte();
18312449Sgabeblack@google.com    void putbyte(uint8_t b);
18412449Sgabeblack@google.com
18513470Sciro.santilli@arm.com    void recv(std::vector<char> &bp);
18612449Sgabeblack@google.com    void send(const char *data);
18712449Sgabeblack@google.com
18812449Sgabeblack@google.com    /*
18912449Sgabeblack@google.com     * Simulator side debugger state.
19012449Sgabeblack@google.com     */
19112449Sgabeblack@google.com    bool active;
19212449Sgabeblack@google.com    bool attached;
19312449Sgabeblack@google.com
19412449Sgabeblack@google.com    System *sys;
19512449Sgabeblack@google.com    ThreadContext *tc;
19612449Sgabeblack@google.com
19712449Sgabeblack@google.com    BaseGdbRegCache *regCachePtr;
19812449Sgabeblack@google.com
19912449Sgabeblack@google.com    class TrapEvent : public Event
20012031Sgabeblack@google.com    {
20112449Sgabeblack@google.com      protected:
20212449Sgabeblack@google.com        int _type;
20312449Sgabeblack@google.com        BaseRemoteGDB *gdb;
20412449Sgabeblack@google.com
20512449Sgabeblack@google.com      public:
20612449Sgabeblack@google.com        TrapEvent(BaseRemoteGDB *g) : gdb(g)
20712031Sgabeblack@google.com        {}
20812449Sgabeblack@google.com
20912449Sgabeblack@google.com        void type(int t) { _type = t; }
21012449Sgabeblack@google.com        void process() { gdb->trap(_type); }
21112449Sgabeblack@google.com    } trapEvent;
21212449Sgabeblack@google.com
21312449Sgabeblack@google.com    /*
21412449Sgabeblack@google.com     * The interface to the simulated system.
21512449Sgabeblack@google.com     */
21612449Sgabeblack@google.com    // Machine memory.
21712449Sgabeblack@google.com    bool read(Addr addr, size_t size, char *data);
21812449Sgabeblack@google.com    bool write(Addr addr, size_t size, const char *data);
21912449Sgabeblack@google.com
22012449Sgabeblack@google.com    template <class T> T read(Addr addr);
22112449Sgabeblack@google.com    template <class T> void write(Addr addr, T data);
22212449Sgabeblack@google.com
22312449Sgabeblack@google.com    // Single step.
22412449Sgabeblack@google.com    void singleStep();
22512449Sgabeblack@google.com    EventWrapper<BaseRemoteGDB, &BaseRemoteGDB::singleStep> singleStepEvent;
22612449Sgabeblack@google.com
22712449Sgabeblack@google.com    void clearSingleStep();
22812449Sgabeblack@google.com    void setSingleStep();
22912449Sgabeblack@google.com
23012449Sgabeblack@google.com    /// Schedule an event which will be triggered "delta" instructions later.
23112449Sgabeblack@google.com    void scheduleInstCommitEvent(Event *ev, int delta);
23212449Sgabeblack@google.com    /// Deschedule an instruction count based event.
23312449Sgabeblack@google.com    void descheduleInstCommitEvent(Event *ev);
23412449Sgabeblack@google.com
23512449Sgabeblack@google.com    // Breakpoints.
23612449Sgabeblack@google.com    void insertSoftBreak(Addr addr, size_t len);
23712449Sgabeblack@google.com    void removeSoftBreak(Addr addr, size_t len);
23812449Sgabeblack@google.com    void insertHardBreak(Addr addr, size_t len);
23912449Sgabeblack@google.com    void removeHardBreak(Addr addr, size_t len);
24012449Sgabeblack@google.com
24112449Sgabeblack@google.com    void clearTempBreakpoint(Addr &bkpt);
24212449Sgabeblack@google.com    void setTempBreakpoint(Addr bkpt);
24312449Sgabeblack@google.com
24412449Sgabeblack@google.com    /*
24512449Sgabeblack@google.com     * GDB commands.
24612449Sgabeblack@google.com     */
24712449Sgabeblack@google.com    struct GdbCommand
24812449Sgabeblack@google.com    {
24912449Sgabeblack@google.com      public:
25012449Sgabeblack@google.com        struct Context
25112449Sgabeblack@google.com        {
25212449Sgabeblack@google.com            const GdbCommand *cmd;
25312449Sgabeblack@google.com            char cmd_byte;
25412449Sgabeblack@google.com            int type;
25512449Sgabeblack@google.com            char *data;
25612449Sgabeblack@google.com            int len;
25712449Sgabeblack@google.com        };
25812449Sgabeblack@google.com
25912449Sgabeblack@google.com        typedef bool (BaseRemoteGDB::*Func)(Context &ctx);
26012449Sgabeblack@google.com
26112449Sgabeblack@google.com        const char * const name;
26212449Sgabeblack@google.com        const Func func;
26312449Sgabeblack@google.com
26412449Sgabeblack@google.com        GdbCommand(const char *_name, Func _func) : name(_name), func(_func) {}
26512031Sgabeblack@google.com    };
26612031Sgabeblack@google.com
26712031Sgabeblack@google.com    static std::map<char, GdbCommand> command_map;
26812031Sgabeblack@google.com
26912031Sgabeblack@google.com    bool cmd_unsupported(GdbCommand::Context &ctx);
27012031Sgabeblack@google.com
27112031Sgabeblack@google.com    bool cmd_signal(GdbCommand::Context &ctx);
27212031Sgabeblack@google.com    bool cmd_cont(GdbCommand::Context &ctx);
27312031Sgabeblack@google.com    bool cmd_async_cont(GdbCommand::Context &ctx);
27412031Sgabeblack@google.com    bool cmd_detach(GdbCommand::Context &ctx);
27512031Sgabeblack@google.com    bool cmd_reg_r(GdbCommand::Context &ctx);
27612031Sgabeblack@google.com    bool cmd_reg_w(GdbCommand::Context &ctx);
27712031Sgabeblack@google.com    bool cmd_set_thread(GdbCommand::Context &ctx);
27812031Sgabeblack@google.com    bool cmd_mem_r(GdbCommand::Context &ctx);
27912031Sgabeblack@google.com    bool cmd_mem_w(GdbCommand::Context &ctx);
28012031Sgabeblack@google.com    bool cmd_query_var(GdbCommand::Context &ctx);
28112031Sgabeblack@google.com    bool cmd_step(GdbCommand::Context &ctx);
28212031Sgabeblack@google.com    bool cmd_async_step(GdbCommand::Context &ctx);
28312031Sgabeblack@google.com    bool cmd_clr_hw_bkpt(GdbCommand::Context &ctx);
28412031Sgabeblack@google.com    bool cmd_set_hw_bkpt(GdbCommand::Context &ctx);
2853536Sgblack@eecs.umich.edu
2862SN/A  protected:
28712449Sgabeblack@google.com    ThreadContext *context() { return tc; }
28812449Sgabeblack@google.com    System *system() { return sys; }
2892SN/A
29013575Sciro.santilli@arm.com    void encodeBinaryData(const std::string &unencoded,
29113575Sciro.santilli@arm.com            std::string &encoded) const;
29213575Sciro.santilli@arm.com
29313575Sciro.santilli@arm.com    void encodeXferResponse(const std::string &unencoded,
29413575Sciro.santilli@arm.com        std::string &encoded, size_t offset, size_t unencoded_length) const;
29513575Sciro.santilli@arm.com
29612449Sgabeblack@google.com    // To be implemented by subclasses.
29712449Sgabeblack@google.com    virtual bool checkBpLen(size_t len);
2982SN/A
29911274Sshingarov@labware.com    virtual BaseGdbRegCache *gdbRegs() = 0;
3002SN/A
3013536Sgblack@eecs.umich.edu    virtual bool acc(Addr addr, size_t len) = 0;
30213575Sciro.santilli@arm.com
30313575Sciro.santilli@arm.com    virtual std::vector<std::string> availableFeatures() const;
30413575Sciro.santilli@arm.com
30513575Sciro.santilli@arm.com    /**
30613575Sciro.santilli@arm.com     * Get an XML target description.
30713575Sciro.santilli@arm.com     *
30813575Sciro.santilli@arm.com     * @param[in] annex the XML filename
30913575Sciro.santilli@arm.com     * @param[out] output set to the decoded XML
31013575Sciro.santilli@arm.com     * @return true if the given annex was found
31113575Sciro.santilli@arm.com     */
31213575Sciro.santilli@arm.com    virtual bool getXferFeaturesRead(const std::string &annex,
31313575Sciro.santilli@arm.com            std::string &output);
3142SN/A};
3152SN/A
3162SN/Atemplate <class T>
3172SN/Ainline T
3183536Sgblack@eecs.umich.eduBaseRemoteGDB::read(Addr addr)
3192SN/A{
3202SN/A    T temp;
3212SN/A    read(addr, sizeof(T), (char *)&temp);
3222SN/A    return temp;
3232SN/A}
3242SN/A
3252SN/Atemplate <class T>
3262SN/Ainline void
3273536Sgblack@eecs.umich.eduBaseRemoteGDB::write(Addr addr, T data)
3282SN/A{
32912449Sgabeblack@google.com    write(addr, sizeof(T), (const char *)&data);
33012449Sgabeblack@google.com}
3312SN/A
3322SN/A#endif /* __REMOTE_GDB_H__ */
333