Go to the documentation of this file.
132 #include <sys/signal.h>
152 #include "debug/GDBAll.hh"
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 max_len)
264 while (*src && max_len--) {
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) {
296 parseThreadId(
const char **srcp,
bool &all,
bool &any,
ContextID &tid)
300 const char *src = *srcp;
332 enum GdbBreakpointType
345 case GdbSoftBp:
return "software breakpoint";
346 case GdbHardBp:
return "hardware breakpoint";
347 case GdbWriteWp:
return "write watchpoint";
348 case GdbReadWp:
return "read watchpoint";
349 case GdbAccWp:
return "access watchpoint";
350 default:
return "unknown breakpoint/watchpoint";
354 std::map<Addr, HardBreakpoint *> hardBreakMap;
359 incomingConnectionEvent(nullptr), incomingDataEvent(nullptr),
360 _port(_port),
fd(-1), sys(_system),
361 connectEvent(this), disconnectEvent(this), trapEvent(this),
362 singleStepEvent(*this)
374 return sys->
name() +
".remote_gdb";
381 warn_once(
"Sockets disabled, not accepting gdb connections");
394 ccprintf(std::cerr,
"%d: %s: listening for remote gdb on port %d\n",
402 "Can't accept GDB connections without any threads!");
420 "Remote GDB port is unknown until listen() has been called.\n");
478 assert(it_success.second);
537 send(
"S%02x", signum);
547 warn(
"GDB connect event has already been scheduled!");
551 if (revent & POLLIN) {
560 warn(
"GDB trap event has already been scheduled!");
564 if (revent & POLLIN) {
568 }
else if (revent & POLLNVAL) {
578 if (::
read(
fd, &
b,
sizeof(
b)) ==
sizeof(
b))
581 throw BadClient(
"Couldn't read data from debugger.");
590 throw BadClient(
"Couldn't write data to the debugger.");
621 csum -= digit2i(
getbyte()) * 16;
629 if (bp.size() > 2 && bp[2] ==
':') {
632 auto begin = std::begin(bp);
633 bp.erase(begin, std::next(begin, 3));
642 DPRINTF(GDBRecv,
"recv: %s\n", bp.data());
652 DPRINTF(GDBSend,
"send: %s\n", bp);
659 for (csum = 0; (
c = *
p);
p++) {
682 cmd_ctx.
type = signum;
688 if (
data.size() == 1)
697 DPRINTF(GDBMisc,
"Unknown command: %c(%#x)\n",
701 cmd_ctx.
cmd = &(cmd_it->second);
703 if (!(this->*(cmd_ctx.
cmd->
func))(cmd_ctx))
706 }
catch (BadClient &
e) {
711 }
catch (Unsupported &
e) {
713 }
catch (CmdError &
e) {
715 }
catch (std::exception &
e) {
716 panic(
"Unrecognized GDB exception: %s",
e.what());
718 panic(
"Unrecognized GDB exception.");
727 DPRINTF(GDBRead,
"read: addr=%#x, size=%d",
vaddr, size);
733 if (debug::GDBRead) {
734 if (debug::GDBExtra) {
736 mem2hex(buf,
data, size);
750 if (debug::GDBWrite) {
752 if (debug::GDBExtra) {
754 mem2hex(buf,
data, size);
790 throw BadClient(
"Invalid breakpoint length\n");
799 throw BadClient(
"Invalid breakpoint length.\n");
808 throw BadClient(
"Invalid breakpoint length\n");
810 DPRINTF(GDBMisc,
"Inserting hardware breakpoint at %#x\n",
addr);
823 throw BadClient(
"Invalid breakpoint length\n");
825 DPRINTF(GDBMisc,
"Removing hardware breakpoint at %#x\n",
addr);
827 auto i = hardBreakMap.find(
addr);
828 if (
i == hardBreakMap.end())
829 throw CmdError(
"E0C");
834 hardBreakMap.erase(
i);
944 const char *
p = ctx.
data;
946 Addr new_pc = hex2i(&
p);
956 const char *
p = ctx.
data;
959 Addr new_pc = hex2i(&
p);
986 const char *
p = ctx.
data;
988 if (
p == NULL || *
p !=
'\0')
989 throw CmdError(
"E01");
1000 const char *
p = ctx.
data;
1001 char subcommand = *
p++;
1004 if (!parseThreadId(&
p, all, any, tid))
1005 throw CmdError(
"E01");
1007 if (subcommand ==
'c') {
1011 throw CmdError(
"E02");
1012 }
else if (subcommand ==
'g') {
1017 throw CmdError(
"E03");
1023 throw CmdError(
"E04");
1031 throw CmdError(
"E05");
1041 const char *
p = ctx.
data;
1044 throw CmdError(
"E02");
1045 size_t len = hex2i(&
p);
1047 throw CmdError(
"E03");
1049 throw CmdError(
"E05");
1053 throw CmdError(
"E05");
1055 char temp[2 *
len + 1];
1056 temp[2 *
len] =
'\0';
1057 mem2hex(temp, buf,
len);
1065 const char *
p = ctx.
data;
1068 throw CmdError(
"E06");
1069 size_t len = hex2i(&
p);
1071 throw CmdError(
"E07");
1073 throw CmdError(
"E08");
1075 p = (
char *)hex2mem(buf,
p,
len);
1077 throw CmdError(
"E09");
1079 throw CmdError(
"E0A");
1081 throw CmdError(
"E0B");
1089 splitAt(std::string str,
const char *
const delim)
1091 size_t pos = str.find_first_of(delim);
1092 if (pos == std::string::npos)
1096 str.substr(0, pos), str.substr(pos + 1));
1101 std::map<std::string, BaseRemoteGDB::QuerySetCommand>
1119 std::ostringstream oss;
1123 oss <<
"PacketSize=1024";
1125 oss <<
';' << feature;
1132 auto split = splitAt(ctx.
args.at(0),
":");
1133 auto object = split.first;
1135 split = splitAt(split.second,
":");
1136 auto operation = split.first;
1139 if (
object !=
"features" || operation !=
"read")
1140 throw Unsupported();
1143 split = splitAt(split.second,
":");
1144 auto annex = split.first;
1147 std::string content;
1149 throw CmdError(
"E00");
1152 split = splitAt(split.second,
",");
1153 auto offset_str = split.first;
1154 auto length_str = split.second;
1156 const char *offset_ptr = offset_str.c_str();
1157 const char *length_ptr = length_str.c_str();
1158 auto offset = hex2i(&offset_ptr);
1159 auto length = hex2i(&length_ptr);
1160 if (offset_ptr != offset_str.c_str() + offset_str.length() ||
1161 length_ptr != length_str.c_str() + length_str.length()) {
1162 throw CmdError(
"E00");
1165 std::string encoded;
1186 send(
"m%x", encodeThreadId(it->second->contextId()));
1195 auto query_split = splitAt({ ctx.
data, (size_t)ctx.
len },
":");
1196 const auto &query_str = query_split.first;
1199 auto query_it =
queryMap.find(query_str);
1201 DPRINTF(GDBMisc,
"Unknown query %s\n",
s);
1202 throw Unsupported();
1208 const auto &query = query_it->second;
1209 auto remaining = std::move(query_split.second);
1210 if (!query.argSep) {
1211 qctx.
args.emplace_back(std::move(remaining));
1213 while (remaining !=
"") {
1214 auto arg_split = splitAt(remaining, query.argSep);
1215 qctx.
args.emplace_back(std::move(arg_split.first));
1216 remaining = std::move(arg_split.second);
1220 (this->*(query.func))(qctx);
1233 const std::string &annex, std::string &
output)
1240 const std::string &unencoded, std::string &encoded)
const
1242 for (
const char&
c : unencoded) {
1243 if (
c ==
'$' ||
c ==
'#' ||
c ==
'}' ||
c ==
'*') {
1245 encoded +=
c ^ 0x20;
1254 std::string &encoded,
size_t offset,
size_t unencoded_length)
const
1256 if (
offset + unencoded_length < unencoded.length())
1273 const char *
p = ctx.
data;
1276 Addr new_pc = hex2i(&
p);
1287 const char *
p = ctx.
data;
1288 Addr new_pc = hex2i(&
p);
1298 const char *
p = ctx.
data;
1299 char sub_cmd = *
p++;
1301 throw CmdError(
"E0D");
1304 throw CmdError(
"E0D");
1305 size_t len = hex2i(&
p);
1307 DPRINTF(GDBMisc,
"clear %s, addr=%#x, len=%d\n",
1308 breakType(sub_cmd),
addr,
len);
1321 throw Unsupported();
1331 const char *
p = ctx.
data;
1332 char sub_cmd = *
p++;
1334 throw CmdError(
"E0D");
1337 throw CmdError(
"E0D");
1338 size_t len = hex2i(&
p);
1340 DPRINTF(GDBMisc,
"set %s, addr=%#x, len=%d\n",
1341 breakType(sub_cmd),
addr,
len);
1354 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
friend class HardBreakpoint
bool cmdSetThread(GdbCommand::Context &ctx)
void insertSoftBreak(Addr addr, size_t len)
EventWrapper< BaseRemoteGDB, &BaseRemoteGDB::connect > connectEvent
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.
virtual const PCStateBase & pcState() const =0
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
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
This proxy attempts to translate virtual addresses using the TLBs.
virtual void getRegs(ThreadContext *)=0
Fill the raw buffer from the registers in the ThreadContext.
virtual Tick getCurrentInstCount()=0
IncomingDataEvent * incomingDataEvent
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
IncomingConnectionEvent * incomingConnectionEvent
ThreadContext is the external interface to all thread state for anything outside of the CPU.
virtual std::string name() const
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).
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 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)
SocketEvent<&BaseRemoteGDB::incomingData > IncomingDataEvent
EventWrapper< BaseRemoteGDB, &BaseRemoteGDB::detach > disconnectEvent
#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
SocketEvent<&BaseRemoteGDB::incomingConnection > IncomingConnectionEvent
virtual Process * getProcessPtr()=0
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
BaseGdbRegCache * regCachePtr
void processCommands(int signum=0)
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 cmdClrHwBkpt(GdbCommand::Context &ctx)
bool cmdSetHwBkpt(GdbCommand::Context &ctx)
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 incomingConnection(int revent)
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
bool trap(ContextID id, int type)
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 Feb 8 2022 11:46:58 for gem5 by doxygen 1.8.17