diff options
author | Gabe Black <gabeblack@google.com> | 2014-12-05 22:37:03 -0800 |
---|---|---|
committer | Gabe Black <gabeblack@google.com> | 2014-12-05 22:37:03 -0800 |
commit | 4a8a0a07982b7896127d0cb723fde08b3825bb48 (patch) | |
tree | 32274c02ae9dca6d6ebad156e559c9afcc44cabb /src/base | |
parent | fb07d43b1a4a903fb2e51b41685eb5814d9f9e11 (diff) | |
download | gem5-4a8a0a07982b7896127d0cb723fde08b3825bb48.tar.xz |
misc: Generalize GDB single stepping.
The new single stepping implementation for x86 doesn't rely on any ISA
specific properties or functionality. This change pulls out the per ISA
implementation of those functions and promotes the X86 implementation to the
base class.
One drawback of that implementation is that the CPU might stop on an
instruction twice if it's affected by both breakpoints and single stepping.
While that might be a little surprising, it's harmless and would only happen
under somewhat unlikely circumstances.
Diffstat (limited to 'src/base')
-rw-r--r-- | src/base/remote_gdb.cc | 30 | ||||
-rw-r--r-- | src/base/remote_gdb.hh | 18 |
2 files changed, 41 insertions, 7 deletions
diff --git a/src/base/remote_gdb.cc b/src/base/remote_gdb.cc index 97d763803..e603fb90f 100644 --- a/src/base/remote_gdb.cc +++ b/src/base/remote_gdb.cc @@ -262,11 +262,18 @@ BaseRemoteGDB::TrapEvent::process() gdb->trap(_type); } -BaseRemoteGDB::BaseRemoteGDB(System *_system, ThreadContext *c, size_t cacheSize) - : inputEvent(NULL), trapEvent(this), listener(NULL), number(-1), fd(-1), - active(false), attached(false), - system(_system), context(c), - gdbregs(cacheSize) +void +BaseRemoteGDB::SingleStepEvent::process() +{ + if (!gdb->singleStepEvent.scheduled()) + gdb->scheduleInstCommitEvent(&gdb->singleStepEvent, 1); + gdb->trap(SIGTRAP); +} + +BaseRemoteGDB::BaseRemoteGDB(System *_system, ThreadContext *c, + size_t cacheSize) : inputEvent(NULL), trapEvent(this), listener(NULL), + number(-1), fd(-1), active(false), attached(false), system(_system), + context(c), gdbregs(cacheSize), singleStepEvent(this) { memset(gdbregs.regs, 0, gdbregs.bytes()); } @@ -525,6 +532,19 @@ BaseRemoteGDB::write(Addr vaddr, size_t size, const char *data) return true; } +void +BaseRemoteGDB::clearSingleStep() +{ + descheduleInstCommitEvent(&singleStepEvent); +} + +void +BaseRemoteGDB::setSingleStep() +{ + if (!singleStepEvent.scheduled()) + scheduleInstCommitEvent(&singleStepEvent, 1); +} + PCEventQueue *BaseRemoteGDB::getPcEventQueue() { return &system->pcEventQueue; diff --git a/src/base/remote_gdb.hh b/src/base/remote_gdb.hh index 62f98f29a..6cca485e3 100644 --- a/src/base/remote_gdb.hh +++ b/src/base/remote_gdb.hh @@ -209,11 +209,25 @@ class BaseRemoteGDB } protected: + class SingleStepEvent : public Event + { + protected: + BaseRemoteGDB *gdb; + + public: + SingleStepEvent(BaseRemoteGDB *g) : gdb(g) + {} + + void process(); + }; + + SingleStepEvent singleStepEvent; + virtual void getregs() = 0; virtual void setregs() = 0; - virtual void clearSingleStep() = 0; - virtual void setSingleStep() = 0; + void clearSingleStep(); + void setSingleStep(); PCEventQueue *getPcEventQueue(); EventQueue *getComInstEventQueue(); |