Go to the documentation of this file.
132 #include <sys/signal.h>
144 #include "config/the_isa.hh"
148 #include "debug/GDBAll.hh"
175 gdb(_gdb), refcount(0)
177 DPRINTF(GDBMisc,
"creating hardware breakpoint at %#x\n", evpc);
180 const std::string
name()
const override {
return gdb->
name() +
".hwbkpt"; }
185 DPRINTF(GDBMisc,
"handling hardware breakpoint at %#x\n",
pc());
198 BadClient(
const char *_warning=NULL) : warning(_warning)
206 CmdError(std::string _error) : error(_error)
211 class Unsupported {};
218 if (
c >=
'0' &&
c <=
'9')
220 else if (
c >=
'a' &&
c <=
'f')
221 return (
c -
'a' + 10);
222 else if (
c >=
'A' &&
c <=
'F')
223 return (
c -
'A' + 10);
232 return (
"0123456789abcdef"[
n & 0x0f]);
237 mem2hex(
char *vdst,
const char *vsrc,
int len)
240 const char *src = vsrc;
243 *dst++ = i2digit(*src >> 4);
244 *dst++ = i2digit(*src++);
254 hex2mem(
char *vdst,
const char *src,
int maxlen)
259 while (*src && maxlen--) {
260 msb = digit2i(*src++);
263 lsb = digit2i(*src++);
266 *dst++ = (msb << 4) | lsb;
275 hex2i(
const char **srcp)
277 const char *src = *srcp;
281 while ((nibble = digit2i(*src)) >= 0) {
290 enum GdbBreakpointType {
303 case GdbSoftBp:
return "software breakpoint";
304 case GdbHardBp:
return "hardware breakpoint";
305 case GdbWriteWp:
return "write watchpoint";
306 case GdbReadWp:
return "read watchpoint";
307 case GdbAccWp:
return "access watchpoint";
308 default:
return "unknown breakpoint/watchpoint";
313 std::map<Addr, HardBreakpoint *> hardBreakMap;
318 connectEvent(nullptr), dataEvent(nullptr), _port(_port),
fd(-1),
319 active(false), attached(false), sys(_system), tc(
c),
320 trapEvent(this), singleStepEvent(*this)
334 return sys->
name() +
".remote_gdb";
341 warn_once(
"Sockets disabled, not accepting gdb connections");
353 ccprintf(cerr,
"%d: %s: listening for remote gdb on port %d\n",
361 "Cannot accept GDB connections if we're not listening!");
377 "Remote GDB port is unknown until listen() has been called.\n");
450 if (
data.size() == 1)
459 DPRINTF(GDBMisc,
"Unknown command: %c(%#x)\n",
463 cmdCtx.
cmd = &(cmdIt->second);
465 if (!(this->*(cmdCtx.
cmd->
func))(cmdCtx))
468 }
catch (BadClient &
e) {
473 }
catch (Unsupported &
e) {
475 }
catch (CmdError &
e) {
476 send(
e.error.c_str());
478 panic(
"Unrecognzied GDB exception.");
489 warn(
"GDB trap event has already been scheduled!");
493 if (revent & POLLIN) {
496 }
else if (revent & POLLNVAL) {
506 if (::
read(
fd, &
b,
sizeof(
b)) ==
sizeof(
b))
509 throw BadClient(
"Couldn't read data from debugger.");
518 throw BadClient(
"Couldn't write data to the debugger.");
549 csum -= digit2i(
getbyte()) * 16;
557 if (bp.size() > 2 && bp[2] ==
':') {
560 auto begin = std::begin(bp);
561 bp.erase(begin, std::next(begin, 3));
570 DPRINTF(GDBRecv,
"recv: %s\n", bp.data());
580 DPRINTF(GDBSend,
"send: %s\n", bp);
587 for (csum = 0; (
c = *
p);
p++) {
606 DPRINTF(GDBRead,
"read: addr=%#x, size=%d",
vaddr, size);
615 mem2hex(buf,
data, size);
633 mem2hex(buf,
data, size);
669 throw BadClient(
"Invalid breakpoint length\n");
678 throw BadClient(
"Invalid breakpoint length.\n");
687 throw BadClient(
"Invalid breakpoint length\n");
689 DPRINTF(GDBMisc,
"Inserting hardware breakpoint at %#x\n",
addr);
702 throw BadClient(
"Invalid breakpoint length\n");
704 DPRINTF(GDBMisc,
"Removing hardware breakpoint at %#x\n",
addr);
706 auto i = hardBreakMap.find(
addr);
707 if (
i == hardBreakMap.end())
708 throw CmdError(
"E0C");
713 hardBreakMap.erase(
i);
720 DPRINTF(GDBMisc,
"setTempBreakpoint: addr=%#x\n", bkpt);
728 DPRINTF(GDBMisc,
"setTempBreakpoint: addr=%#x\n", bkpt);
829 const char *
p = ctx.
data;
831 Addr newPc = hex2i(&
p);
841 const char *
p = ctx.
data;
844 Addr newPc = hex2i(&
p);
871 const char *
p = ctx.
data;
873 if (
p == NULL || *
p !=
'\0')
874 throw CmdError(
"E01");
885 const char *
p = ctx.
data + 1;
887 throw CmdError(
"E01");
895 const char *
p = ctx.
data;
898 throw CmdError(
"E02");
899 size_t len = hex2i(&
p);
901 throw CmdError(
"E03");
903 throw CmdError(
"E05");
907 throw CmdError(
"E05");
909 char temp[2 *
len + 1];
910 temp[2 *
len] =
'\0';
911 mem2hex(temp, buf,
len);
919 const char *
p = ctx.
data;
922 throw CmdError(
"E06");
923 size_t len = hex2i(&
p);
925 throw CmdError(
"E07");
927 throw CmdError(
"E08");
929 p = (
char *)hex2mem(buf,
p,
len);
931 throw CmdError(
"E09");
933 throw CmdError(
"E0A");
935 throw CmdError(
"E0B");
944 string xfer_read_prefix =
"Xfer:features:read:";
945 if (
s.rfind(
"Supported:", 0) == 0) {
946 std::ostringstream oss;
950 oss <<
"PacketSize=1024";
952 oss <<
';' << feature;
953 send(oss.str().c_str());
954 }
else if (
s.rfind(xfer_read_prefix, 0) == 0) {
956 auto value_string =
s.substr(xfer_read_prefix.length());
957 auto colon_pos = value_string.find(
':');
958 auto comma_pos = value_string.find(
',');
959 if (colon_pos == std::string::npos || comma_pos == std::string::npos)
960 throw CmdError(
"E00");
963 throw CmdError(
"E00");
966 value_string.substr(colon_pos + 1, comma_pos), NULL, 16);
968 value_string.substr(comma_pos + 1), NULL, 16);
969 }
catch (std::invalid_argument&
e) {
970 throw CmdError(
"E00");
971 }
catch (std::out_of_range&
e) {
972 throw CmdError(
"E00");
976 send(encoded.c_str());
977 }
else if (
s ==
"C") {
993 const std::string &annex, std::string &
output)
1000 const std::string &unencoded, std::string &encoded)
const
1002 for (
const char&
c : unencoded) {
1003 if (
c ==
'$' ||
c ==
'#' ||
c ==
'}' ||
c ==
'*') {
1005 encoded +=
c ^ 0x20;
1014 std::string &encoded,
size_t offset,
size_t unencoded_length)
const
1016 if (
offset + unencoded_length < unencoded.length())
1026 const char *
p = ctx.
data;
1029 Addr newPc = hex2i(&
p);
1040 const char *
p = ctx.
data;
1041 Addr newPc = hex2i(&
p);
1051 const char *
p = ctx.
data;
1054 throw CmdError(
"E0D");
1057 throw CmdError(
"E0D");
1058 size_t len = hex2i(&
p);
1060 DPRINTF(GDBMisc,
"clear %s, addr=%#x, len=%d\n",
1061 break_type(subcmd),
addr,
len);
1074 throw Unsupported();
1084 const char *
p = ctx.
data;
1087 throw CmdError(
"E0D");
1090 throw CmdError(
"E0D");
1091 size_t len = hex2i(&
p);
1093 DPRINTF(GDBMisc,
"set %s, addr=%#x, len=%d\n",
1094 break_type(subcmd),
addr,
len);
1107 throw Unsupported();
static std::map< char, GdbCommand > command_map
static void output(const char *filename)
virtual void descheduleInstCountEvent(Event *event)=0
bool scheduled() const
Determine if the current event is scheduled.
virtual size_t size() const =0
Return the size of the raw buffer, in bytes (i.e., half of the number of digits in the g/G packet).
bool cmd_set_hw_bkpt(GdbCommand::Context &ctx)
void encodeXferResponse(const std::string &unencoded, std::string &encoded, size_t offset, size_t unencoded_length) const
virtual bool listen(int port, bool reuse=true)
virtual Tick getCurrentInstCount()=0
bool cmd_async_step(GdbCommand::Context &ctx)
bool cmd_signal(GdbCommand::Context &ctx)
void encodeBinaryData(const std::string &unencoded, std::string &encoded) const
HardBreakpoint(BaseRemoteGDB *_gdb, PCEventScope *s, Addr pc)
bool cmd_cont(GdbCommand::Context &ctx)
bool cmd_unsupported(GdbCommand::Context &ctx)
virtual int accept(bool nodelay=false)
static const char GDBStart
void removeHardBreak(Addr addr, size_t len)
bool cmd_set_thread(GdbCommand::Context &ctx)
void incomingData(int revent)
SocketEvent<&BaseRemoteGDB::incomingData > DataEvent
EventWrapper< BaseRemoteGDB, &BaseRemoteGDB::singleStep > singleStepEvent
void schedule(PollEvent *event)
bool cmd_mem_r(GdbCommand::Context &ctx)
void writeBlob(Addr addr, const void *p, int size) const
Same as tryWriteBlob, but insists on success.
void insertSoftBreak(Addr addr, size_t len)
static const char GDBBadP
void clearTempBreakpoint(Addr &bkpt)
ThreadContext is the external interface to all thread state for anything outside of the CPU.
void scheduleInstCommitEvent(Event *ev, int delta)
Schedule an event which will be triggered "delta" instructions later.
bool write(Addr addr, size_t size, const char *data)
virtual BaseGdbRegCache * gdbRegs()=0
friend class HardBreakpoint
void process(ThreadContext *tc) override
void descheduleInstCommitEvent(Event *ev)
Deschedule an instruction count based event.
virtual char * data() const =0
Return the pointer to the raw bytes buffer containing the register values.
bool cmd_mem_w(GdbCommand::Context &ctx)
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
virtual bool acc(Addr addr, size_t len)=0
ConnectEvent * connectEvent
#define DDUMP(x, data, count)
DPRINTF is a debugging trace facility that allows one to selectively enable tracing statements.
virtual void setRegs(ThreadContext *) const =0
Set the ThreadContext's registers from the values in the raw buffer.
bool cmd_async_cont(GdbCommand::Context &ctx)
virtual TheISA::PCState pcState() const =0
virtual const std::string name() const
bool cmd_detach(GdbCommand::Context &ctx)
virtual PortProxy & getVirtProxy()=0
virtual bool getXferFeaturesRead(const std::string &annex, std::string &output)
Get an XML target description.
virtual void scheduleInstCountEvent(Event *event, Tick count)=0
static bool allDisabled()
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
void removeSoftBreak(Addr addr, size_t len)
virtual std::vector< std::string > availableFeatures() const
This object is a proxy for a port or other object which implements the functional response protocol,...
bool cmd_query_var(GdbCommand::Context &ctx)
void remove(PollEvent *event)
bool cmd_clr_hw_bkpt(GdbCommand::Context &ctx)
Overload hash function for BasicBlockRange type.
bool cmd_step(GdbCommand::Context &ctx)
void ccprintf(cp::Print &print)
void insertHardBreak(Addr addr, size_t len)
static const char GDBGoodP
virtual bool checkBpLen(size_t len)
SocketEvent<&BaseRemoteGDB::connectWrapper > ConnectEvent
const std::string name() const override
bool cmd_reg_r(GdbCommand::Context &ctx)
BaseRemoteGDB::TrapEvent trapEvent
BaseGdbRegCache * regCachePtr
void setTempBreakpoint(Addr bkpt)
void readBlob(Addr addr, void *p, int size) const
Higher level interfaces based on the above.
bool read(Addr addr, size_t size, char *data)
std::string csprintf(const char *format, const Args &...args)
void recv(std::vector< char > &bp)
bool cmd_reg_w(GdbCommand::Context &ctx)
#define panic(...)
This implements a cprintf based panic() function.
vector< BaseRemoteGDB * > debuggers
BaseRemoteGDB(System *system, ThreadContext *context, int _port)
Interface to other parts of the simulator.
virtual void getRegs(ThreadContext *)=0
Fill the raw buffer from the registers in the ThreadContext.
Tick curTick()
The current simulated tick.
void send(const char *data)
Generated on Wed Sep 30 2020 14:02:01 for gem5 by doxygen 1.8.17