remote_gdb.hh revision 13470
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 17413470Sciro.santilli@arm.com void recv(std::vector<char> &bp); 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