remote_gdb.hh revision 12031
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 521910SN/Aclass GDBListener; 533536Sgblack@eecs.umich.edu 5412031Sgabeblack@google.comclass BaseRemoteGDB; 5512031Sgabeblack@google.com 5612031Sgabeblack@google.comstruct GdbCommand 572SN/A{ 5812031Sgabeblack@google.com public: 5912031Sgabeblack@google.com struct Context 6012031Sgabeblack@google.com { 6112031Sgabeblack@google.com const GdbCommand *cmd; 6212031Sgabeblack@google.com char cmd_byte; 6312031Sgabeblack@google.com int type; 6412031Sgabeblack@google.com char *data; 6512031Sgabeblack@google.com int len; 6612031Sgabeblack@google.com }; 6712031Sgabeblack@google.com 6812031Sgabeblack@google.com typedef bool (BaseRemoteGDB::*Func)(Context &ctx); 6912031Sgabeblack@google.com 7012031Sgabeblack@google.com const char * const name; 7112031Sgabeblack@google.com const Func func; 7212031Sgabeblack@google.com 7312031Sgabeblack@google.com GdbCommand(const char *_name, Func _func) : name(_name), func(_func) 7412031Sgabeblack@google.com {} 753536Sgblack@eecs.umich.edu}; 763536Sgblack@eecs.umich.edu 773536Sgblack@eecs.umich.educlass BaseRemoteGDB 783536Sgblack@eecs.umich.edu{ 791910SN/A private: 801910SN/A friend void debugger(); 811910SN/A friend class GDBListener; 821910SN/A 8312031Sgabeblack@google.com protected: 8412031Sgabeblack@google.com /// Exception to throw when the connection to the client is broken. 8512031Sgabeblack@google.com struct BadClient 8612031Sgabeblack@google.com { 8712031Sgabeblack@google.com const char *warning; 8812031Sgabeblack@google.com BadClient(const char *_warning=NULL) : warning(_warning) 8912031Sgabeblack@google.com {} 9012031Sgabeblack@google.com }; 9112031Sgabeblack@google.com /// Exception to throw when an error needs to be reported to the client. 9212031Sgabeblack@google.com struct CmdError 9312031Sgabeblack@google.com { 9412031Sgabeblack@google.com std::string error; 9512031Sgabeblack@google.com CmdError(std::string _error) : error(_error) 9612031Sgabeblack@google.com {} 9712031Sgabeblack@google.com }; 9812031Sgabeblack@google.com /// Exception to throw when something isn't supported. 9912031Sgabeblack@google.com class Unsupported {}; 10012031Sgabeblack@google.com 10112031Sgabeblack@google.com // Helper functions 1023536Sgblack@eecs.umich.edu protected: 1033536Sgblack@eecs.umich.edu int digit2i(char); 1043536Sgblack@eecs.umich.edu char i2digit(int); 1053536Sgblack@eecs.umich.edu Addr hex2i(const char **); 10612031Sgabeblack@google.com // Address formats, break types, and gdb commands may change 10712031Sgabeblack@google.com // between architectures, so they're defined as virtual 10812031Sgabeblack@google.com // functions. 10911274Sshingarov@labware.com virtual void mem2hex(char *, const char *, int); 11011274Sshingarov@labware.com virtual const char * hex2mem(char *, const char *, int); 1113536Sgblack@eecs.umich.edu virtual const char * break_type(char c); 11212031Sgabeblack@google.com 11312031Sgabeblack@google.com protected: 11412031Sgabeblack@google.com static std::map<char, GdbCommand> command_map; 11512031Sgabeblack@google.com 11612031Sgabeblack@google.com bool cmd_unsupported(GdbCommand::Context &ctx); 11712031Sgabeblack@google.com 11812031Sgabeblack@google.com bool cmd_signal(GdbCommand::Context &ctx); 11912031Sgabeblack@google.com bool cmd_cont(GdbCommand::Context &ctx); 12012031Sgabeblack@google.com bool cmd_async_cont(GdbCommand::Context &ctx); 12112031Sgabeblack@google.com bool cmd_detach(GdbCommand::Context &ctx); 12212031Sgabeblack@google.com bool cmd_reg_r(GdbCommand::Context &ctx); 12312031Sgabeblack@google.com bool cmd_reg_w(GdbCommand::Context &ctx); 12412031Sgabeblack@google.com bool cmd_set_thread(GdbCommand::Context &ctx); 12512031Sgabeblack@google.com bool cmd_mem_r(GdbCommand::Context &ctx); 12612031Sgabeblack@google.com bool cmd_mem_w(GdbCommand::Context &ctx); 12712031Sgabeblack@google.com bool cmd_query_var(GdbCommand::Context &ctx); 12812031Sgabeblack@google.com bool cmd_step(GdbCommand::Context &ctx); 12912031Sgabeblack@google.com bool cmd_async_step(GdbCommand::Context &ctx); 13012031Sgabeblack@google.com bool cmd_clr_hw_bkpt(GdbCommand::Context &ctx); 13112031Sgabeblack@google.com bool cmd_set_hw_bkpt(GdbCommand::Context &ctx); 1323536Sgblack@eecs.umich.edu 1332SN/A protected: 13410598Sgabeblack@google.com class InputEvent : public PollEvent 1352SN/A { 1362SN/A protected: 1373536Sgblack@eecs.umich.edu BaseRemoteGDB *gdb; 1382SN/A 1392SN/A public: 14010598Sgabeblack@google.com InputEvent(BaseRemoteGDB *g, int fd, int e); 1412SN/A void process(int revent); 1422SN/A }; 1432SN/A 14410598Sgabeblack@google.com class TrapEvent : public Event 14510597Sgabeblack@google.com { 14610597Sgabeblack@google.com protected: 14710597Sgabeblack@google.com int _type; 14810597Sgabeblack@google.com BaseRemoteGDB *gdb; 14910597Sgabeblack@google.com 15010597Sgabeblack@google.com public: 15110597Sgabeblack@google.com TrapEvent(BaseRemoteGDB *g) : gdb(g) 15210597Sgabeblack@google.com {} 15310597Sgabeblack@google.com 15410597Sgabeblack@google.com void type(int t) { _type = t; } 15510597Sgabeblack@google.com void process(); 15610597Sgabeblack@google.com }; 15710597Sgabeblack@google.com 15810598Sgabeblack@google.com friend class InputEvent; 15910598Sgabeblack@google.com InputEvent *inputEvent; 16010597Sgabeblack@google.com TrapEvent trapEvent; 1611910SN/A GDBListener *listener; 1621910SN/A int number; 1632SN/A 1642SN/A protected: 16512031Sgabeblack@google.com // The socket commands come in through 1662SN/A int fd; 1672SN/A 1682SN/A protected: 1692SN/A bool active; 1702SN/A bool attached; 1712SN/A 1722SN/A System *system; 1732680Sktlim@umich.edu ThreadContext *context; 1742SN/A 1752SN/A protected: 17611274Sshingarov@labware.com /** 17711274Sshingarov@labware.com * Concrete subclasses of this abstract class represent how the 17811274Sshingarov@labware.com * register values are transmitted on the wire. Usually each 17911274Sshingarov@labware.com * architecture should define one subclass, but there can be more 18011274Sshingarov@labware.com * if there is more than one possible wire format. For example, 18111274Sshingarov@labware.com * ARM defines both AArch32GdbRegCache and AArch64GdbRegCache. 18211274Sshingarov@labware.com */ 18311274Sshingarov@labware.com class BaseGdbRegCache 1843536Sgblack@eecs.umich.edu { 1853536Sgblack@eecs.umich.edu public: 18611274Sshingarov@labware.com 18711274Sshingarov@labware.com /** 18811274Sshingarov@labware.com * Return the pointer to the raw bytes buffer containing the 18911274Sshingarov@labware.com * register values. Each byte of this buffer is literally 19011274Sshingarov@labware.com * encoded as two hex digits in the g or G RSP packet. 19111274Sshingarov@labware.com */ 19211274Sshingarov@labware.com virtual char *data() const = 0; 19311274Sshingarov@labware.com 19411274Sshingarov@labware.com /** 19511274Sshingarov@labware.com * Return the size of the raw buffer, in bytes 19611274Sshingarov@labware.com * (i.e., half of the number of digits in the g/G packet). 19711274Sshingarov@labware.com */ 19811274Sshingarov@labware.com virtual size_t size() const = 0; 19911274Sshingarov@labware.com 20011274Sshingarov@labware.com /** 20111274Sshingarov@labware.com * Fill the raw buffer from the registers in the ThreadContext. 20211274Sshingarov@labware.com */ 20311274Sshingarov@labware.com virtual void getRegs(ThreadContext*) = 0; 20411274Sshingarov@labware.com 20511274Sshingarov@labware.com /** 20611274Sshingarov@labware.com * Set the ThreadContext's registers from the values 20711274Sshingarov@labware.com * in the raw buffer. 20811274Sshingarov@labware.com */ 20911274Sshingarov@labware.com virtual void setRegs(ThreadContext*) const = 0; 21011274Sshingarov@labware.com 21111274Sshingarov@labware.com /** 21211274Sshingarov@labware.com * Return the name to use in places like DPRINTF. 21311274Sshingarov@labware.com * Having each concrete superclass redefine this member 21411274Sshingarov@labware.com * is useful in situations where the class of the regCache 21511274Sshingarov@labware.com * can change on the fly. 21611274Sshingarov@labware.com */ 21711274Sshingarov@labware.com virtual const std::string name() const = 0; 21811274Sshingarov@labware.com 21911274Sshingarov@labware.com BaseGdbRegCache(BaseRemoteGDB *g) : gdb(g) 2203536Sgblack@eecs.umich.edu {} 22112031Sgabeblack@google.com virtual ~BaseGdbRegCache() 22212031Sgabeblack@google.com {} 2233536Sgblack@eecs.umich.edu 22411274Sshingarov@labware.com protected: 22511274Sshingarov@labware.com BaseRemoteGDB *gdb; 2263536Sgblack@eecs.umich.edu }; 2273536Sgblack@eecs.umich.edu 22812031Sgabeblack@google.com BaseGdbRegCache *regCachePtr; 22912031Sgabeblack@google.com 2303536Sgblack@eecs.umich.edu protected: 23112031Sgabeblack@google.com uint8_t getbyte(); 23212031Sgabeblack@google.com void putbyte(uint8_t b); 2332SN/A 2342SN/A int recv(char *data, int len); 23512031Sgabeblack@google.com void send(const char *data); 2362SN/A 2372SN/A protected: 2382SN/A // Machine memory 2393536Sgblack@eecs.umich.edu virtual bool read(Addr addr, size_t size, char *data); 2403536Sgblack@eecs.umich.edu virtual bool write(Addr addr, size_t size, const char *data); 2412SN/A 2422SN/A template <class T> T read(Addr addr); 2432SN/A template <class T> void write(Addr addr, T data); 2442SN/A 2452SN/A public: 24611274Sshingarov@labware.com BaseRemoteGDB(System *system, ThreadContext *context); 2473536Sgblack@eecs.umich.edu virtual ~BaseRemoteGDB(); 24811274Sshingarov@labware.com virtual BaseGdbRegCache *gdbRegs() = 0; 2492SN/A 2502680Sktlim@umich.edu void replaceThreadContext(ThreadContext *tc) { context = tc; } 251180SN/A 2522SN/A void attach(int fd); 2532SN/A void detach(); 2542SN/A bool isattached(); 2552SN/A 2563536Sgblack@eecs.umich.edu virtual bool acc(Addr addr, size_t len) = 0; 2572SN/A bool trap(int type); 2583960Sgblack@eecs.umich.edu virtual bool breakpoint() 2593960Sgblack@eecs.umich.edu { 2603960Sgblack@eecs.umich.edu return trap(SIGTRAP); 2613960Sgblack@eecs.umich.edu } 2622SN/A 2632SN/A protected: 26410601Sgabeblack@google.com class SingleStepEvent : public Event 26510601Sgabeblack@google.com { 26610601Sgabeblack@google.com protected: 26710601Sgabeblack@google.com BaseRemoteGDB *gdb; 26810601Sgabeblack@google.com 26910601Sgabeblack@google.com public: 27010601Sgabeblack@google.com SingleStepEvent(BaseRemoteGDB *g) : gdb(g) 27110601Sgabeblack@google.com {} 27210601Sgabeblack@google.com 27310601Sgabeblack@google.com void process(); 27410601Sgabeblack@google.com }; 27510601Sgabeblack@google.com 27610601Sgabeblack@google.com SingleStepEvent singleStepEvent; 27710601Sgabeblack@google.com 27810601Sgabeblack@google.com void clearSingleStep(); 27910601Sgabeblack@google.com void setSingleStep(); 2802SN/A 2812SN/A PCEventQueue *getPcEventQueue(); 28210599Sgabeblack@google.com EventQueue *getComInstEventQueue(); 28310599Sgabeblack@google.com 28410599Sgabeblack@google.com /// Schedule an event which will be triggered "delta" instructions later. 28510599Sgabeblack@google.com void scheduleInstCommitEvent(Event *ev, int delta); 28610599Sgabeblack@google.com /// Deschedule an instruction count based event. 28710599Sgabeblack@google.com void descheduleInstCommitEvent(Event *ev); 2882SN/A 2892SN/A protected: 29010589Sgabeblack@google.com virtual bool checkBpLen(size_t len); 29110589Sgabeblack@google.com 2922SN/A class HardBreakpoint : public PCEvent 2932SN/A { 2942SN/A private: 2953536Sgblack@eecs.umich.edu BaseRemoteGDB *gdb; 2962SN/A 2972SN/A public: 298507SN/A int refcount; 299507SN/A 300507SN/A public: 3013536Sgblack@eecs.umich.edu HardBreakpoint(BaseRemoteGDB *_gdb, Addr addr); 3028737Skoansin.tan@gmail.com const std::string name() const { return gdb->name() + ".hwbkpt"; } 3032SN/A 3042680Sktlim@umich.edu virtual void process(ThreadContext *tc); 3052SN/A }; 3062SN/A friend class HardBreakpoint; 3072SN/A 3082SN/A typedef std::map<Addr, HardBreakpoint *> break_map_t; 3092SN/A typedef break_map_t::iterator break_iter_t; 3102SN/A break_map_t hardBreakMap; 3112SN/A 31212031Sgabeblack@google.com void insertSoftBreak(Addr addr, size_t len); 31312031Sgabeblack@google.com void removeSoftBreak(Addr addr, size_t len); 31412031Sgabeblack@google.com virtual void insertHardBreak(Addr addr, size_t len); 31512031Sgabeblack@google.com void removeHardBreak(Addr addr, size_t len); 3162SN/A 3173550Sgblack@eecs.umich.edu protected: 3183550Sgblack@eecs.umich.edu void clearTempBreakpoint(Addr &bkpt); 3193550Sgblack@eecs.umich.edu void setTempBreakpoint(Addr bkpt); 3203550Sgblack@eecs.umich.edu 321507SN/A public: 322507SN/A std::string name(); 3232SN/A}; 3242SN/A 3252SN/Atemplate <class T> 3262SN/Ainline T 3273536Sgblack@eecs.umich.eduBaseRemoteGDB::read(Addr addr) 3282SN/A{ 3292SN/A T temp; 3302SN/A read(addr, sizeof(T), (char *)&temp); 3312SN/A return temp; 3322SN/A} 3332SN/A 3342SN/Atemplate <class T> 3352SN/Ainline void 3363536Sgblack@eecs.umich.eduBaseRemoteGDB::write(Addr addr, T data) 3372SN/A{ write(addr, sizeof(T), (const char *)&data); } 3382SN/A 3392SN/Aclass GDBListener 3402SN/A{ 3412SN/A protected: 34210598Sgabeblack@google.com class InputEvent : public PollEvent 3432SN/A { 3442SN/A protected: 3452SN/A GDBListener *listener; 3462SN/A 3472SN/A public: 34810598Sgabeblack@google.com InputEvent(GDBListener *l, int fd, int e); 3492SN/A void process(int revent); 3502SN/A }; 3512SN/A 35210598Sgabeblack@google.com friend class InputEvent; 35310598Sgabeblack@google.com InputEvent *inputEvent; 3542SN/A 3552SN/A protected: 3562SN/A ListenSocket listener; 3573536Sgblack@eecs.umich.edu BaseRemoteGDB *gdb; 3582SN/A int port; 3592SN/A 3602SN/A public: 3613536Sgblack@eecs.umich.edu GDBListener(BaseRemoteGDB *g, int p); 3622SN/A ~GDBListener(); 3632SN/A 3642SN/A void accept(); 3652SN/A void listen(); 366507SN/A std::string name(); 3672SN/A}; 3682SN/A 3692SN/A#endif /* __REMOTE_GDB_H__ */ 370