135 #include <sys/signal.h> 144 #include "arch/vtophys.hh" 148 #include "config/the_isa.hh" 152 #include "debug/GDBAll.hh" 179 :
PCEvent(s,
"HardBreakpoint Event", pc),
180 gdb(_gdb), refcount(0)
182 DPRINTF(GDBMisc,
"creating hardware breakpoint at %#x\n", evpc);
185 const std::string
name()
const override {
return gdb->
name() +
".hwbkpt"; }
190 DPRINTF(GDBMisc,
"handling hardware breakpoint at %#x\n",
pc());
203 BadClient(
const char *_warning=NULL) : warning(_warning)
211 CmdError(std::string _error) : error(_error)
216 class Unsupported {};
223 if (c >=
'0' && c <=
'9')
225 else if (c >=
'a' && c <=
'f')
226 return (c -
'a' + 10);
227 else if (c >=
'A' && c <=
'F')
228 return (c -
'A' + 10);
237 return (
"0123456789abcdef"[n & 0x0f]);
242 mem2hex(
char *vdst,
const char *vsrc,
int len)
245 const char *src = vsrc;
248 *dst++ = i2digit(*src >> 4);
249 *dst++ = i2digit(*src++);
259 hex2mem(
char *vdst,
const char *src,
int maxlen)
264 while (*src && maxlen--) {
265 msb = digit2i(*src++);
268 lsb = digit2i(*src++);
271 *dst++ = (msb << 4) | lsb;
280 hex2i(
const char **srcp)
282 const char *src = *srcp;
286 while ((nibble = digit2i(*src)) >= 0) {
308 case GdbSoftBp:
return "software breakpoint";
309 case GdbHardBp:
return "hardware breakpoint";
310 case GdbWriteWp:
return "write watchpoint";
311 case GdbReadWp:
return "read watchpoint";
312 case GdbAccWp:
return "access watchpoint";
313 default:
return "unknown breakpoint/watchpoint";
318 std::map<Addr, HardBreakpoint *> hardBreakMap;
323 connectEvent(nullptr), dataEvent(nullptr), _port(_port),
fd(-1),
324 active(false), attached(false), sys(_system), tc(c),
325 trapEvent(this), singleStepEvent(*this)
327 debuggers.push_back(
this);
339 return sys->
name() +
".remote_gdb";
346 warn_once(
"Sockets disabled, not accepting gdb connections");
358 ccprintf(cerr,
"%d: %s: listening for remote gdb on port %d\n",
366 "Cannot accept GDB connections if we're not listening!");
382 "Remote GDB port is unknown until listen() has been called.\n");
455 if (data.size() == 1)
458 cmdCtx.
data = data.data() + 1;
460 cmdCtx.
len = data.size() - 2;
464 DPRINTF(GDBMisc,
"Unknown command: %c(%#x)\n",
468 cmdCtx.
cmd = &(cmdIt->second);
470 if (!(this->*(cmdCtx.
cmd->
func))(cmdCtx))
473 }
catch (BadClient &
e) {
478 }
catch (Unsupported &e) {
480 }
catch (CmdError &e) {
481 send(e.error.c_str());
483 panic(
"Unrecognzied GDB exception.");
494 warn(
"GDB trap event has already been scheduled!");
498 if (revent & POLLIN) {
501 }
else if (revent & POLLNVAL) {
511 if (::
read(
fd, &b,
sizeof(b)) ==
sizeof(b))
514 throw BadClient(
"Couldn't read data from debugger.");
520 if (::
write(
fd, &b,
sizeof(b)) ==
sizeof(b))
523 throw BadClient(
"Couldn't write data to the debugger.");
554 csum -= digit2i(
getbyte()) * 16;
562 if (bp.size() > 2 && bp[2] ==
':') {
565 auto begin = std::begin(bp);
566 bp.erase(begin, std::next(begin, 3));
575 DPRINTF(GDBRecv,
"recv: %s\n", bp.data());
585 DPRINTF(GDBSend,
"send: %s\n", bp);
592 for (csum = 0; (c = *
p); p++) {
604 }
while ((c & 0x7f) ==
GDBBadP);
611 static Addr lastaddr = 0;
612 static size_t lastsize = 0;
615 DPRINTF(GDBRead,
"read: reading memory location zero!\n");
616 vaddr = lastaddr + lastsize;
619 DPRINTF(GDBRead,
"read: addr=%#x, size=%d", vaddr, size);
628 mem2hex(buf, data, size);
642 static Addr lastaddr = 0;
643 static size_t lastsize = 0;
646 DPRINTF(GDBWrite,
"write: writing memory location zero!\n");
647 vaddr = lastaddr + lastsize;
651 DPRINTFN(
"write: addr=%#x, size=%d", vaddr, size);
654 mem2hex(buf, data, size);
690 throw BadClient(
"Invalid breakpoint length\n");
699 throw BadClient(
"Invalid breakpoint length.\n");
708 throw BadClient(
"Invalid breakpoint length\n");
710 DPRINTF(GDBMisc,
"Inserting hardware breakpoint at %#x\n", addr);
723 throw BadClient(
"Invalid breakpoint length\n");
725 DPRINTF(GDBMisc,
"Removing hardware breakpoint at %#x\n", addr);
727 auto i = hardBreakMap.find(addr);
728 if (
i == hardBreakMap.end())
729 throw CmdError(
"E0C");
734 hardBreakMap.erase(
i);
741 DPRINTF(GDBMisc,
"setTempBreakpoint: addr=%#x\n", bkpt);
749 DPRINTF(GDBMisc,
"setTempBreakpoint: addr=%#x\n", bkpt);
850 const char *
p = ctx.
data;
852 Addr newPc = hex2i(&p);
862 const char *
p = ctx.
data;
865 Addr newPc = hex2i(&p);
892 const char *
p = ctx.
data;
894 if (p == NULL || *p !=
'\0')
895 throw CmdError(
"E01");
906 const char *
p = ctx.
data + 1;
908 throw CmdError(
"E01");
916 const char *
p = ctx.
data;
919 throw CmdError(
"E02");
920 size_t len = hex2i(&p);
922 throw CmdError(
"E03");
924 throw CmdError(
"E05");
927 if (!
read(addr, len, buf))
928 throw CmdError(
"E05");
930 char temp[2 * len + 1];
931 temp[2 *
len] =
'\0';
932 mem2hex(temp, buf, len);
940 const char *
p = ctx.
data;
943 throw CmdError(
"E06");
944 size_t len = hex2i(&p);
946 throw CmdError(
"E07");
947 if (len * 2 > ctx.
len - (p - ctx.
data))
948 throw CmdError(
"E08");
950 p = (
char *)hex2mem(buf, p, len);
952 throw CmdError(
"E09");
954 throw CmdError(
"E0A");
955 if (!
write(addr, len, buf))
956 throw CmdError(
"E0B");
965 string xfer_read_prefix =
"Xfer:features:read:";
966 if (s.rfind(
"Supported:", 0) == 0) {
967 std::ostringstream oss;
971 oss <<
"PacketSize=1024";
973 oss <<
';' << feature;
974 send(oss.str().c_str());
975 }
else if (s.rfind(xfer_read_prefix, 0) == 0) {
977 auto value_string = s.substr(xfer_read_prefix.length());
978 auto colon_pos = value_string.find(
':');
979 auto comma_pos = value_string.find(
',');
980 if (colon_pos == std::string::npos || comma_pos == std::string::npos)
981 throw CmdError(
"E00");
984 throw CmdError(
"E00");
986 offset = std::stoull(
987 value_string.substr(colon_pos + 1, comma_pos), NULL, 16);
988 length = std::stoull(
989 value_string.substr(comma_pos + 1), NULL, 16);
990 }
catch (std::invalid_argument&
e) {
991 throw CmdError(
"E00");
992 }
catch (std::out_of_range& e) {
993 throw CmdError(
"E00");
997 send(encoded.c_str());
998 }
else if (s ==
"C") {
1001 throw Unsupported();
1014 const std::string &annex, std::string &
output)
1021 const std::string &unencoded, std::string &encoded)
const 1023 for (
const char&
c : unencoded) {
1024 if (
c ==
'$' ||
c ==
'#' ||
c ==
'}' ||
c ==
'*') {
1026 encoded +=
c ^ 0x20;
1035 std::string &encoded,
size_t offset,
size_t unencoded_length)
const 1037 if (offset + unencoded_length < unencoded.length())
1047 const char *
p = ctx.
data;
1050 Addr newPc = hex2i(&p);
1061 const char *
p = ctx.
data;
1062 Addr newPc = hex2i(&p);
1072 const char *
p = ctx.
data;
1075 throw CmdError(
"E0D");
1078 throw CmdError(
"E0D");
1079 size_t len = hex2i(&p);
1081 DPRINTF(GDBMisc,
"clear %s, addr=%#x, len=%d\n",
1082 break_type(subcmd), addr, len);
1095 throw Unsupported();
1105 const char *
p = ctx.
data;
1108 throw CmdError(
"E0D");
1111 throw CmdError(
"E0D");
1112 size_t len = hex2i(&p);
1114 DPRINTF(GDBMisc,
"set %s, addr=%#x, len=%d\n",
1115 break_type(subcmd), addr, len);
1128 throw Unsupported();
#define panic(...)
This implements a cprintf based panic() function.
friend class HardBreakpoint
virtual bool getXferFeaturesRead(const std::string &annex, std::string &output)
Get an XML target description.
void ccprintf(cp::Print &print)
void removeSoftBreak(Addr addr, size_t len)
void descheduleInstCommitEvent(Event *ev)
Deschedule an instruction count based event.
bool read(Addr addr, size_t size, char *data)
virtual bool listen(int port, bool reuse=true)
static void output(const char *filename)
void insertSoftBreak(Addr addr, size_t len)
void send(const char *data)
void clearTempBreakpoint(Addr &bkpt)
virtual Tick getCurrentInstCount()=0
virtual TheISA::PCState pcState() const =0
ConnectEvent * connectEvent
bool cmd_async_cont(GdbCommand::Context &ctx)
virtual void getRegs(ThreadContext *)=0
Fill the raw buffer from the registers in the ThreadContext.
bool cmd_reg_r(GdbCommand::Context &ctx)
#define DDUMP(x, data, count)
virtual PortProxy & getVirtProxy()=0
void setTempBreakpoint(Addr bkpt)
Overload hash function for BasicBlockRange type.
bool cmd_reg_w(GdbCommand::Context &ctx)
ThreadContext is the external interface to all thread state for anything outside of the CPU...
virtual void setRegs(ThreadContext *) const =0
Set the ThreadContext's registers from the values in the raw buffer.
void schedule(PollEvent *event)
void scheduleInstCommitEvent(Event *ev, int delta)
Schedule an event which will be triggered "delta" instructions later.
void encodeXferResponse(const std::string &unencoded, std::string &encoded, size_t offset, size_t unencoded_length) const
HardBreakpoint(BaseRemoteGDB *_gdb, PCEventScope *s, Addr pc)
virtual void descheduleInstCountEvent(Event *event)=0
EventWrapper< BaseRemoteGDB, &BaseRemoteGDB::singleStep > singleStepEvent
bool cmd_detach(GdbCommand::Context &ctx)
BaseGdbRegCache * regCachePtr
Tick curTick()
The current simulated tick.
std::string csprintf(const char *format, const Args &...args)
static const char GDBGoodP
bool scheduled() const
Determine if the current event is scheduled.
static bool allDisabled()
bool cmd_query_var(GdbCommand::Context &ctx)
BaseRemoteGDB(System *system, ThreadContext *context, int _port)
void writeBlob(Addr addr, const void *p, int size) const
Same as tryWriteBlob, but insists on success.
virtual void scheduleInstCountEvent(Event *event, Tick count)=0
void encodeBinaryData(const std::string &unencoded, std::string &encoded) const
static const char GDBStart
bool cmd_cont(GdbCommand::Context &ctx)
static std::map< char, GdbCommand > command_map
virtual bool acc(Addr addr, size_t len)=0
bool cmd_set_thread(GdbCommand::Context &ctx)
void incomingData(int revent)
bool cmd_set_hw_bkpt(GdbCommand::Context &ctx)
virtual bool checkBpLen(size_t len)
SocketEvent<&BaseRemoteGDB::incomingData > DataEvent
virtual int accept(bool nodelay=false)
BaseRemoteGDB::TrapEvent trapEvent
const std::string name() const override
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
bool write(Addr addr, size_t size, const char *data)
virtual const std::string name() const
virtual BaseGdbRegCache * gdbRegs()=0
static const char GDBBadP
bool cmd_clr_hw_bkpt(GdbCommand::Context &ctx)
void readBlob(Addr addr, void *p, int size) const
Higher level interfaces based on the above.
void recv(std::vector< char > &bp)
This object is a proxy for a port or other object which implements the functional response protocol...
virtual char * data() const =0
Return the pointer to the raw bytes buffer containing the register values.
vector< BaseRemoteGDB * > debuggers
bool cmd_unsupported(GdbCommand::Context &ctx)
bool cmd_mem_w(GdbCommand::Context &ctx)
void remove(PollEvent *event)
bool cmd_mem_r(GdbCommand::Context &ctx)
TranslatingPortProxy Object Declaration for FS.
TranslatingPortProxy Object Declaration for SE.
bool cmd_async_step(GdbCommand::Context &ctx)
virtual std::vector< std::string > availableFeatures() const
bool cmd_signal(GdbCommand::Context &ctx)
bool cmd_step(GdbCommand::Context &ctx)
void removeHardBreak(Addr addr, size_t len)
void process(ThreadContext *tc) override
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
void insertHardBreak(Addr addr, size_t len)
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)...
SocketEvent<&BaseRemoteGDB::connectWrapper > ConnectEvent