Go to the documentation of this file.
132 #include <sys/signal.h>
152 #include "debug/GDBAll.hh"
180 DPRINTF(GDBMisc,
"creating hardware breakpoint at %#x\n",
evpc);
183 const std::string
name()
const override {
return gdb->
name() +
".hwbkpt"; }
188 DPRINTF(GDBMisc,
"handling hardware breakpoint at %#x\n",
pc());
201 BadClient(
const char *_warning=NULL) :
warning(_warning)
209 CmdError(std::string _error) :
error(_error)
214 class Unsupported {};
221 if (
c >=
'0' &&
c <=
'9')
223 else if (
c >=
'a' &&
c <=
'f')
224 return (
c -
'a' + 10);
225 else if (
c >=
'A' &&
c <=
'F')
226 return (
c -
'A' + 10);
235 return "0123456789abcdef"[
n & 0x0f];
240 mem2hex(
char *vdst,
const char *vsrc,
int len)
243 const char *src = vsrc;
246 *dst++ = i2digit(*src >> 4);
247 *dst++ = i2digit(*src++);
257 hex2mem(
char *vdst,
const char *src,
int max_len)
262 while (*src && max_len--) {
263 msb = digit2i(*src++);
266 lsb = digit2i(*src++);
269 *dst++ = (msb << 4) | lsb;
278 hex2i(
const char **srcp)
280 const char *src = *srcp;
284 while ((nibble = digit2i(*src)) >= 0) {
294 parseThreadId(
const char **srcp,
bool &all,
bool &any,
ContextID &tid)
298 const char *src = *srcp;
330 enum GdbBreakpointType
343 case GdbSoftBp:
return "software breakpoint";
344 case GdbHardBp:
return "hardware breakpoint";
345 case GdbWriteWp:
return "write watchpoint";
346 case GdbReadWp:
return "read watchpoint";
347 case GdbAccWp:
return "access watchpoint";
348 default:
return "unknown breakpoint/watchpoint";
352 std::map<Addr, HardBreakpoint *> hardBreakMap;
357 connectEvent(nullptr), dataEvent(nullptr), _port(_port),
fd(-1),
358 sys(_system), trapEvent(this), singleStepEvent(*this)
370 return sys->
name() +
".remote_gdb";
377 warn_once(
"Sockets disabled, not accepting gdb connections");
389 ccprintf(std::cerr,
"%d: %s: listening for remote gdb on port %d\n",
397 "Can't accept GDB connections without any threads!");
413 "Remote GDB port is unknown until listen() has been called.\n");
446 assert(it_success.second);
524 GdbCommand::Context cmd_ctx;
531 if (
data.size() == 1)
533 cmd_ctx.cmdByte =
data[0];
534 cmd_ctx.data =
data.data() + 1;
536 cmd_ctx.len =
data.size() - 2;
538 auto cmd_it =
commandMap.find(cmd_ctx.cmdByte);
540 DPRINTF(GDBMisc,
"Unknown command: %c(%#x)\n",
541 cmd_ctx.cmdByte, cmd_ctx.cmdByte);
544 cmd_ctx.cmd = &(cmd_it->second);
546 if (!(this->*(cmd_ctx.cmd->func))(cmd_ctx))
549 }
catch (BadClient &
e) {
554 }
catch (Unsupported &
e) {
556 }
catch (CmdError &
e) {
559 panic(
"Unrecognzied GDB exception.");
570 warn(
"GDB trap event has already been scheduled!");
574 if (revent & POLLIN) {
578 }
else if (revent & POLLNVAL) {
588 if (::
read(
fd, &
b,
sizeof(
b)) ==
sizeof(
b))
591 throw BadClient(
"Couldn't read data from debugger.");
600 throw BadClient(
"Couldn't write data to the debugger.");
631 csum -= digit2i(
getbyte()) * 16;
639 if (bp.size() > 2 && bp[2] ==
':') {
642 auto begin = std::begin(bp);
643 bp.erase(begin, std::next(begin, 3));
652 DPRINTF(GDBRecv,
"recv: %s\n", bp.data());
662 DPRINTF(GDBSend,
"send: %s\n", bp);
669 for (csum = 0; (
c = *
p);
p++) {
688 DPRINTF(GDBRead,
"read: addr=%#x, size=%d",
vaddr, size);
694 if (debug::GDBRead) {
695 if (debug::GDBExtra) {
697 mem2hex(buf,
data, size);
711 if (debug::GDBWrite) {
713 if (debug::GDBExtra) {
715 mem2hex(buf,
data, size);
751 throw BadClient(
"Invalid breakpoint length\n");
760 throw BadClient(
"Invalid breakpoint length.\n");
769 throw BadClient(
"Invalid breakpoint length\n");
771 DPRINTF(GDBMisc,
"Inserting hardware breakpoint at %#x\n",
addr);
784 throw BadClient(
"Invalid breakpoint length\n");
786 DPRINTF(GDBMisc,
"Removing hardware breakpoint at %#x\n",
addr);
788 auto i = hardBreakMap.find(
addr);
789 if (
i == hardBreakMap.end())
790 throw CmdError(
"E0C");
795 hardBreakMap.erase(
i);
905 const char *
p = ctx.
data;
907 Addr new_pc = hex2i(&
p);
917 const char *
p = ctx.
data;
920 Addr new_pc = hex2i(&
p);
947 const char *
p = ctx.
data;
949 if (
p == NULL || *
p !=
'\0')
950 throw CmdError(
"E01");
961 const char *
p = ctx.
data;
962 char subcommand = *
p++;
965 if (!parseThreadId(&
p, all, any, tid))
966 throw CmdError(
"E01");
968 if (subcommand ==
'c') {
972 throw CmdError(
"E02");
973 }
else if (subcommand ==
'g') {
978 throw CmdError(
"E03");
984 throw CmdError(
"E04");
992 throw CmdError(
"E05");
1002 const char *
p = ctx.
data;
1005 throw CmdError(
"E02");
1006 size_t len = hex2i(&
p);
1008 throw CmdError(
"E03");
1010 throw CmdError(
"E05");
1014 throw CmdError(
"E05");
1016 char temp[2 *
len + 1];
1017 temp[2 *
len] =
'\0';
1018 mem2hex(temp, buf,
len);
1026 const char *
p = ctx.
data;
1029 throw CmdError(
"E06");
1030 size_t len = hex2i(&
p);
1032 throw CmdError(
"E07");
1034 throw CmdError(
"E08");
1036 p = (
char *)hex2mem(buf,
p,
len);
1038 throw CmdError(
"E09");
1040 throw CmdError(
"E0A");
1042 throw CmdError(
"E0B");
1050 splitAt(std::string str,
const char *
const delim)
1052 size_t pos = str.find_first_of(delim);
1053 if (pos == std::string::npos)
1057 str.substr(0, pos), str.substr(pos + 1));
1062 std::map<std::string, BaseRemoteGDB::QuerySetCommand>
1080 std::ostringstream oss;
1084 oss <<
"PacketSize=1024";
1086 oss <<
';' << feature;
1093 auto split = splitAt(ctx.
args.at(0),
":");
1094 auto object = split.first;
1096 split = splitAt(split.second,
":");
1097 auto operation = split.first;
1100 if (
object !=
"features" || operation !=
"read")
1101 throw Unsupported();
1104 split = splitAt(split.second,
":");
1105 auto annex = split.first;
1108 std::string content;
1110 throw CmdError(
"E00");
1113 split = splitAt(split.second,
",");
1114 auto offset_str = split.first;
1115 auto length_str = split.second;
1117 const char *offset_ptr = offset_str.c_str();
1118 const char *length_ptr = length_str.c_str();
1119 auto offset = hex2i(&offset_ptr);
1120 auto length = hex2i(&length_ptr);
1121 if (offset_ptr != offset_str.c_str() + offset_str.length() ||
1122 length_ptr != length_str.c_str() + length_str.length()) {
1123 throw CmdError(
"E00");
1126 std::string encoded;
1147 send(
"m%x", encodeThreadId(it->second->contextId()));
1156 auto query_split = splitAt({ ctx.
data, (size_t)ctx.
len },
":");
1157 const auto &query_str = query_split.first;
1160 auto query_it =
queryMap.find(query_str);
1162 DPRINTF(GDBMisc,
"Unknown query %s\n",
s);
1163 throw Unsupported();
1169 const auto &query = query_it->second;
1170 auto remaining = std::move(query_split.second);
1171 if (!query.argSep) {
1172 qctx.
args.emplace_back(std::move(remaining));
1174 while (remaining !=
"") {
1175 auto arg_split = splitAt(remaining, query.argSep);
1176 qctx.
args.emplace_back(std::move(arg_split.first));
1177 remaining = std::move(arg_split.second);
1181 (this->*(query.func))(qctx);
1194 const std::string &annex, std::string &
output)
1201 const std::string &unencoded, std::string &encoded)
const
1203 for (
const char&
c : unencoded) {
1204 if (
c ==
'$' ||
c ==
'#' ||
c ==
'}' ||
c ==
'*') {
1206 encoded +=
c ^ 0x20;
1215 std::string &encoded,
size_t offset,
size_t unencoded_length)
const
1217 if (
offset + unencoded_length < unencoded.length())
1234 const char *
p = ctx.
data;
1237 Addr new_pc = hex2i(&
p);
1248 const char *
p = ctx.
data;
1249 Addr new_pc = hex2i(&
p);
1259 const char *
p = ctx.
data;
1260 char sub_cmd = *
p++;
1262 throw CmdError(
"E0D");
1265 throw CmdError(
"E0D");
1266 size_t len = hex2i(&
p);
1268 DPRINTF(GDBMisc,
"clear %s, addr=%#x, len=%d\n",
1269 breakType(sub_cmd),
addr,
len);
1282 throw Unsupported();
1292 const char *
p = ctx.
data;
1293 char sub_cmd = *
p++;
1295 throw CmdError(
"E0D");
1298 throw CmdError(
"E0D");
1299 size_t len = hex2i(&
p);
1301 DPRINTF(GDBMisc,
"set %s, addr=%#x, len=%d\n",
1302 breakType(sub_cmd),
addr,
len);
1315 throw Unsupported();
void incomingData(int revent)
void queryXfer(QuerySetCommand::Context &ctx)
Tick curTick()
The universal simulation clock.
bool cmdUnsupported(GdbCommand::Context &ctx)
static const char GDBStart
bool cmdDumpPageTable(GdbCommand::Context &ctx)
const std::string name() const override
void writeBlob(Addr addr, const void *p, int size) const
Same as tryWriteBlob, but insists on success.
friend class HardBreakpoint
bool cmdSetThread(GdbCommand::Context &ctx)
void insertSoftBreak(Addr addr, size_t len)
EventWrapper< BaseRemoteGDB, &BaseRemoteGDB::singleStep > singleStepEvent
virtual BaseGdbRegCache * gdbRegs()=0
bool cmdRegR(GdbCommand::Context &ctx)
static void output(const char *filename)
void encodeBinaryData(const std::string &unencoded, std::string &encoded) const
void scheduleInstCommitEvent(Event *ev, int delta)
Schedule an event which will be triggered "delta" instructions later.
const std::string externalize() const
Dump all items in the pTable, to a concatenation of strings of the form Addr:Entry;.
static std::map< char, GdbCommand > commandMap
void queryC(QuerySetCommand::Context &ctx)
virtual ContextID contextId() const =0
virtual bool acc(Addr addr, size_t len)=0
SocketEvent<&BaseRemoteGDB::incomingData > DataEvent
bool cmdMemW(GdbCommand::Context &ctx)
bool cmdStep(GdbCommand::Context &ctx)
void remove(PollEvent *event)
void ccprintf(cp::Print &print)
BaseRemoteGDB(System *system, int _port)
Interface to other parts of the simulator.
virtual Status status() const =0
virtual void getRegs(ThreadContext *)=0
Fill the raw buffer from the registers in the ThreadContext.
virtual Tick getCurrentInstCount()=0
void removeHardBreak(Addr addr, size_t len)
void encodeXferResponse(const std::string &unencoded, std::string &encoded, size_t offset, size_t unencoded_length) const
virtual std::vector< std::string > availableFeatures() const
ThreadContext is the external interface to all thread state for anything outside of the CPU.
virtual std::string name() const
virtual PortProxy & getVirtProxy()=0
void removeSoftBreak(Addr addr, size_t len)
bool cmdSignal(GdbCommand::Context &ctx)
EmulationPageTable * pTable
void process(ThreadContext *tc) override
virtual bool listen(int port, bool reuse=true)
HardBreakpoint(BaseRemoteGDB *_gdb, PCEventScope *s, Addr pc)
bool cmdAsyncCont(GdbCommand::Context &ctx)
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).
This object is a proxy for a port or other object which implements the functional response protocol,...
static const char GDBGoodP
virtual char * data() const =0
Return the pointer to the raw bytes buffer containing the register values.
void querySupported(QuerySetCommand::Context &ctx)
void schedule(PollEvent *event)
gem5::BaseRemoteGDB::TrapEvent trapEvent
void readBlob(Addr addr, void *p, int size) const
Higher level interfaces based on the above.
virtual TheISA::PCState pcState() const =0
void replaceThreadContext(ThreadContext *tc)
bool cmdRegW(GdbCommand::Context &ctx)
static bool allDisabled()
virtual bool getXferFeaturesRead(const std::string &annex, std::string &output)
Get an XML target description.
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)
#define DDUMP(x, data, count)
DPRINTF is a debugging trace facility that allows one to selectively enable tracing statements.
virtual void scheduleInstCountEvent(Event *event, Tick count)=0
virtual Process * getProcessPtr()=0
SocketEvent<&BaseRemoteGDB::connectWrapper > ConnectEvent
BaseGdbRegCache * regCachePtr
bool selectThreadContext(ContextID id)
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
bool trap(ContextID id, int type)
bool cmdClrHwBkpt(GdbCommand::Context &ctx)
bool cmdSetHwBkpt(GdbCommand::Context &ctx)
ConnectEvent * connectEvent
virtual void setRegs(ThreadContext *) const =0
Set the ThreadContext's registers from the values in the raw buffer.
void send(const char *data)
virtual void descheduleInstCountEvent(Event *event)=0
bool read(Addr addr, size_t size, char *data)
void descheduleInstCommitEvent(Event *ev)
Deschedule an instruction count based event.
static std::map< std::string, QuerySetCommand > queryMap
void recv(std::vector< char > &bp)
bool cmdDetach(GdbCommand::Context &ctx)
int ContextID
Globally unique thread context ID.
void addThreadContext(ThreadContext *_tc)
std::vector< std::string > args
virtual bool checkBpLen(size_t len)
bool cmdMemR(GdbCommand::Context &ctx)
void queryFThreadInfo(QuerySetCommand::Context &ctx)
bool cmdCont(GdbCommand::Context &ctx)
std::map< ContextID, ThreadContext * > threads
virtual int accept(bool nodelay=false)
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
void insertHardBreak(Addr addr, size_t len)
bool cmdAsyncStep(GdbCommand::Context &ctx)
bool cmdQueryVar(GdbCommand::Context &ctx)
static const char GDBBadP
void querySThreadInfo(QuerySetCommand::Context &ctx)
bool scheduled() const
Determine if the current event is scheduled.
#define panic(...)
This implements a cprintf based panic() function.
Generated on Tue Sep 21 2021 12:24:42 for gem5 by doxygen 1.8.17