Go to the documentation of this file.
132 #include <sys/signal.h>
147 #include "debug/GDBAll.hh"
173 DPRINTF(GDBMisc,
"creating hardware breakpoint at %#x\n",
evpc);
176 const std::string
name()
const override {
return gdb->
name() +
".hwbkpt"; }
181 DPRINTF(GDBMisc,
"handling hardware breakpoint at %#x\n",
pc());
194 BadClient(
const char *_warning=NULL) : warning(_warning)
202 CmdError(std::string _error) : error(_error)
207 class Unsupported {};
214 if (
c >=
'0' &&
c <=
'9')
216 else if (
c >=
'a' &&
c <=
'f')
217 return (
c -
'a' + 10);
218 else if (
c >=
'A' &&
c <=
'F')
219 return (
c -
'A' + 10);
228 return (
"0123456789abcdef"[
n & 0x0f]);
233 mem2hex(
char *vdst,
const char *vsrc,
int len)
236 const char *src = vsrc;
239 *dst++ = i2digit(*src >> 4);
240 *dst++ = i2digit(*src++);
250 hex2mem(
char *vdst,
const char *src,
int maxlen)
255 while (*src && maxlen--) {
256 msb = digit2i(*src++);
259 lsb = digit2i(*src++);
262 *dst++ = (msb << 4) | lsb;
271 hex2i(
const char **srcp)
273 const char *src = *srcp;
277 while ((nibble = digit2i(*src)) >= 0) {
286 enum GdbBreakpointType {
299 case GdbSoftBp:
return "software breakpoint";
300 case GdbHardBp:
return "hardware breakpoint";
301 case GdbWriteWp:
return "write watchpoint";
302 case GdbReadWp:
return "read watchpoint";
303 case GdbAccWp:
return "access watchpoint";
304 default:
return "unknown breakpoint/watchpoint";
309 std::map<Addr, HardBreakpoint *> hardBreakMap;
314 connectEvent(nullptr), dataEvent(nullptr), _port(_port),
fd(-1),
315 active(false), attached(false), sys(_system), tc(
c),
316 trapEvent(this), singleStepEvent(*this)
330 return sys->
name() +
".remote_gdb";
337 warn_once(
"Sockets disabled, not accepting gdb connections");
349 ccprintf(std::cerr,
"%d: %s: listening for remote gdb on port %d\n",
357 "Cannot accept GDB connections if we're not listening!");
373 "Remote GDB port is unknown until listen() has been called.\n");
446 if (
data.size() == 1)
455 DPRINTF(GDBMisc,
"Unknown command: %c(%#x)\n",
459 cmdCtx.
cmd = &(cmdIt->second);
461 if (!(this->*(cmdCtx.
cmd->
func))(cmdCtx))
464 }
catch (BadClient &
e) {
469 }
catch (Unsupported &
e) {
471 }
catch (CmdError &
e) {
472 send(
e.error.c_str());
474 panic(
"Unrecognzied GDB exception.");
485 warn(
"GDB trap event has already been scheduled!");
489 if (revent & POLLIN) {
492 }
else if (revent & POLLNVAL) {
502 if (::
read(
fd, &
b,
sizeof(
b)) ==
sizeof(
b))
505 throw BadClient(
"Couldn't read data from debugger.");
514 throw BadClient(
"Couldn't write data to the debugger.");
545 csum -= digit2i(
getbyte()) * 16;
553 if (bp.size() > 2 && bp[2] ==
':') {
556 auto begin = std::begin(bp);
557 bp.erase(begin, std::next(begin, 3));
566 DPRINTF(GDBRecv,
"recv: %s\n", bp.data());
576 DPRINTF(GDBSend,
"send: %s\n", bp);
583 for (csum = 0; (
c = *
p);
p++) {
602 DPRINTF(GDBRead,
"read: addr=%#x, size=%d",
vaddr, size);
611 mem2hex(buf,
data, size);
629 mem2hex(buf,
data, size);
665 throw BadClient(
"Invalid breakpoint length\n");
674 throw BadClient(
"Invalid breakpoint length.\n");
683 throw BadClient(
"Invalid breakpoint length\n");
685 DPRINTF(GDBMisc,
"Inserting hardware breakpoint at %#x\n",
addr);
698 throw BadClient(
"Invalid breakpoint length\n");
700 DPRINTF(GDBMisc,
"Removing hardware breakpoint at %#x\n",
addr);
702 auto i = hardBreakMap.find(
addr);
703 if (
i == hardBreakMap.end())
704 throw CmdError(
"E0C");
709 hardBreakMap.erase(
i);
810 const char *
p = ctx.
data;
812 Addr newPc = hex2i(&
p);
822 const char *
p = ctx.
data;
825 Addr newPc = hex2i(&
p);
852 const char *
p = ctx.
data;
854 if (
p == NULL || *
p !=
'\0')
855 throw CmdError(
"E01");
866 const char *
p = ctx.
data + 1;
868 throw CmdError(
"E01");
876 const char *
p = ctx.
data;
879 throw CmdError(
"E02");
880 size_t len = hex2i(&
p);
882 throw CmdError(
"E03");
884 throw CmdError(
"E05");
888 throw CmdError(
"E05");
890 char temp[2 *
len + 1];
891 temp[2 *
len] =
'\0';
892 mem2hex(temp, buf,
len);
900 const char *
p = ctx.
data;
903 throw CmdError(
"E06");
904 size_t len = hex2i(&
p);
906 throw CmdError(
"E07");
908 throw CmdError(
"E08");
910 p = (
char *)hex2mem(buf,
p,
len);
912 throw CmdError(
"E09");
914 throw CmdError(
"E0A");
916 throw CmdError(
"E0B");
924 std::string
s(ctx.
data, ctx.
len - 1);
925 std::string xfer_read_prefix =
"Xfer:features:read:";
926 if (
s.rfind(
"Supported:", 0) == 0) {
927 std::ostringstream oss;
931 oss <<
"PacketSize=1024";
933 oss <<
';' << feature;
934 send(oss.str().c_str());
935 }
else if (
s.rfind(xfer_read_prefix, 0) == 0) {
937 auto value_string =
s.substr(xfer_read_prefix.length());
938 auto colon_pos = value_string.find(
':');
939 auto comma_pos = value_string.find(
',');
940 if (colon_pos == std::string::npos || comma_pos == std::string::npos)
941 throw CmdError(
"E00");
944 throw CmdError(
"E00");
947 value_string.substr(colon_pos + 1, comma_pos), NULL, 16);
948 length = std::stoull(
949 value_string.substr(comma_pos + 1), NULL, 16);
950 }
catch (std::invalid_argument&
e) {
951 throw CmdError(
"E00");
952 }
catch (std::out_of_range&
e) {
953 throw CmdError(
"E00");
957 send(encoded.c_str());
958 }
else if (
s ==
"C") {
974 const std::string &annex, std::string &
output)
981 const std::string &unencoded, std::string &encoded)
const
983 for (
const char&
c : unencoded) {
984 if (
c ==
'$' ||
c ==
'#' ||
c ==
'}' ||
c ==
'*') {
995 std::string &encoded,
size_t offset,
size_t unencoded_length)
const
997 if (
offset + unencoded_length < unencoded.length())
1007 const char *
p = ctx.
data;
1010 Addr newPc = hex2i(&
p);
1021 const char *
p = ctx.
data;
1022 Addr newPc = hex2i(&
p);
1032 const char *
p = ctx.
data;
1035 throw CmdError(
"E0D");
1038 throw CmdError(
"E0D");
1039 size_t len = hex2i(&
p);
1041 DPRINTF(GDBMisc,
"clear %s, addr=%#x, len=%d\n",
1042 break_type(subcmd),
addr,
len);
1055 throw Unsupported();
1065 const char *
p = ctx.
data;
1068 throw CmdError(
"E0D");
1071 throw CmdError(
"E0D");
1072 size_t len = hex2i(&
p);
1074 DPRINTF(GDBMisc,
"set %s, addr=%#x, len=%d\n",
1075 break_type(subcmd),
addr,
len);
1088 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)
std::vector< BaseRemoteGDB * > debuggers
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
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)
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)
Tick curTick()
The universal simulation clock.
SocketEvent<&BaseRemoteGDB::connectWrapper > ConnectEvent
const std::string name() const override
bool cmd_reg_r(GdbCommand::Context &ctx)
BaseRemoteGDB::TrapEvent trapEvent
BaseGdbRegCache * regCachePtr
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.
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.
void send(const char *data)
Generated on Tue Jun 22 2021 15:28:21 for gem5 by doxygen 1.8.17