Broke remote_gdb into a base class and architecture specific derived classes.
--HG-- extra : convert_revision : 8c528fab56a95b8245ad0f2572d62bb556ce0dde
This commit is contained in:
parent
da24915181
commit
54e22bfe95
6 changed files with 73 additions and 445 deletions
|
@ -121,8 +121,9 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "arch/vtophys.hh"
|
#include "arch/alpha/kgdb.h"
|
||||||
#include "arch/alpha/remote_gdb.hh"
|
#include "arch/alpha/remote_gdb.hh"
|
||||||
|
#include "arch/vtophys.hh"
|
||||||
#include "base/intmath.hh"
|
#include "base/intmath.hh"
|
||||||
#include "base/remote_gdb.hh"
|
#include "base/remote_gdb.hh"
|
||||||
#include "base/socket.hh"
|
#include "base/socket.hh"
|
||||||
|
@ -135,30 +136,12 @@
|
||||||
#include "sim/system.hh"
|
#include "sim/system.hh"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace AlphaISA;
|
using namespace TheISA;
|
||||||
|
|
||||||
RemoteGDB::Event::Event(RemoteGDB *g, int fd, int e)
|
|
||||||
: PollEvent(fd, e), gdb(g)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void
|
|
||||||
RemoteGDB::Event::process(int revent)
|
|
||||||
{
|
|
||||||
if (revent & POLLIN)
|
|
||||||
gdb->trap(ALPHA_KENTRY_IF);
|
|
||||||
else if (revent & POLLNVAL)
|
|
||||||
gdb->detach();
|
|
||||||
}
|
|
||||||
|
|
||||||
RemoteGDB::RemoteGDB(System *_system, ThreadContext *c)
|
RemoteGDB::RemoteGDB(System *_system, ThreadContext *c)
|
||||||
: BaseRemoteGDB(_system, c, KGDB_NUMREGS),
|
: BaseRemoteGDB(_system, c, KGDB_NUMREGS)
|
||||||
event(NULL)
|
|
||||||
{}
|
|
||||||
|
|
||||||
RemoteGDB::~RemoteGDB()
|
|
||||||
{
|
{
|
||||||
if (event)
|
memset(gdbregs.regs, 0, gdbregs.size);
|
||||||
delete event;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
|
@ -268,36 +251,16 @@ RemoteGDB::setregs()
|
||||||
context->setPC(gdbregs.regs[KGDB_REG_PC]);
|
context->setPC(gdbregs.regs[KGDB_REG_PC]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
RemoteGDB::setTempBreakpoint(TempBreakpoint &bkpt, Addr addr)
|
|
||||||
{
|
|
||||||
DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", addr);
|
|
||||||
|
|
||||||
bkpt.address = addr;
|
|
||||||
insertHardBreak(addr, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
RemoteGDB::clearTempBreakpoint(TempBreakpoint &bkpt)
|
|
||||||
{
|
|
||||||
DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n",
|
|
||||||
bkpt.address);
|
|
||||||
|
|
||||||
|
|
||||||
removeHardBreak(bkpt.address, 4);
|
|
||||||
bkpt.address = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
RemoteGDB::clearSingleStep()
|
RemoteGDB::clearSingleStep()
|
||||||
{
|
{
|
||||||
DPRINTF(GDBMisc, "clearSingleStep bt_addr=%#x nt_addr=%#x\n",
|
DPRINTF(GDBMisc, "clearSingleStep bt_addr=%#x nt_addr=%#x\n",
|
||||||
takenBkpt.address, notTakenBkpt.address);
|
takenBkpt, notTakenBkpt);
|
||||||
|
|
||||||
if (takenBkpt.address != 0)
|
if (takenBkpt != 0)
|
||||||
clearTempBreakpoint(takenBkpt);
|
clearTempBreakpoint(takenBkpt);
|
||||||
|
|
||||||
if (notTakenBkpt.address != 0)
|
if (notTakenBkpt != 0)
|
||||||
clearTempBreakpoint(notTakenBkpt);
|
clearTempBreakpoint(notTakenBkpt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,12 +285,12 @@ RemoteGDB::setSingleStep()
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINTF(GDBMisc, "setSingleStep bt_addr=%#x nt_addr=%#x\n",
|
DPRINTF(GDBMisc, "setSingleStep bt_addr=%#x nt_addr=%#x\n",
|
||||||
takenBkpt.address, notTakenBkpt.address);
|
takenBkpt, notTakenBkpt);
|
||||||
|
|
||||||
setTempBreakpoint(notTakenBkpt, npc);
|
setTempBreakpoint(notTakenBkpt = npc);
|
||||||
|
|
||||||
if (set_bt)
|
if (set_bt)
|
||||||
setTempBreakpoint(takenBkpt, bpc);
|
setTempBreakpoint(takenBkpt = bpc);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write bytes to kernel address space for debugger.
|
// Write bytes to kernel address space for debugger.
|
||||||
|
@ -344,81 +307,3 @@ RemoteGDB::write(Addr vaddr, size_t size, const char *data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PCEventQueue *RemoteGDB::getPcEventQueue()
|
|
||||||
{
|
|
||||||
return &system->pcEventQueue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RemoteGDB::HardBreakpoint::HardBreakpoint(RemoteGDB *_gdb, Addr pc)
|
|
||||||
: PCEvent(_gdb->getPcEventQueue(), "HardBreakpoint Event", pc),
|
|
||||||
gdb(_gdb), refcount(0)
|
|
||||||
{
|
|
||||||
DPRINTF(GDBMisc, "creating hardware breakpoint at %#x\n", evpc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
RemoteGDB::HardBreakpoint::process(ThreadContext *tc)
|
|
||||||
{
|
|
||||||
DPRINTF(GDBMisc, "handling hardware breakpoint at %#x\n", pc());
|
|
||||||
|
|
||||||
if (tc == gdb->context)
|
|
||||||
gdb->trap(ALPHA_KENTRY_INT);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
RemoteGDB::insertSoftBreak(Addr addr, size_t len)
|
|
||||||
{
|
|
||||||
if (len != sizeof(MachInst))
|
|
||||||
panic("invalid length\n");
|
|
||||||
|
|
||||||
return insertHardBreak(addr, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
RemoteGDB::removeSoftBreak(Addr addr, size_t len)
|
|
||||||
{
|
|
||||||
if (len != sizeof(MachInst))
|
|
||||||
panic("invalid length\n");
|
|
||||||
|
|
||||||
return removeHardBreak(addr, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
RemoteGDB::insertHardBreak(Addr addr, size_t len)
|
|
||||||
{
|
|
||||||
if (len != sizeof(MachInst))
|
|
||||||
panic("invalid length\n");
|
|
||||||
|
|
||||||
DPRINTF(GDBMisc, "inserting hardware breakpoint at %#x\n", addr);
|
|
||||||
|
|
||||||
HardBreakpoint *&bkpt = hardBreakMap[addr];
|
|
||||||
if (bkpt == 0)
|
|
||||||
bkpt = new HardBreakpoint(this, addr);
|
|
||||||
|
|
||||||
bkpt->refcount++;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
RemoteGDB::removeHardBreak(Addr addr, size_t len)
|
|
||||||
{
|
|
||||||
if (len != sizeof(MachInst))
|
|
||||||
panic("invalid length\n");
|
|
||||||
|
|
||||||
DPRINTF(GDBMisc, "removing hardware breakpoint at %#x\n", addr);
|
|
||||||
|
|
||||||
break_iter_t i = hardBreakMap.find(addr);
|
|
||||||
if (i == hardBreakMap.end())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
HardBreakpoint *hbp = (*i).second;
|
|
||||||
if (--hbp->refcount == 0) {
|
|
||||||
delete hbp;
|
|
||||||
hardBreakMap.erase(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
|
@ -48,31 +48,12 @@ namespace AlphaISA
|
||||||
{
|
{
|
||||||
class RemoteGDB : public BaseRemoteGDB
|
class RemoteGDB : public BaseRemoteGDB
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
friend void debugger();
|
|
||||||
friend class GDBListener;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
class Event : public PollEvent
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
RemoteGDB *gdb;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Event(RemoteGDB *g, int fd, int e);
|
|
||||||
void process(int revent);
|
|
||||||
};
|
|
||||||
|
|
||||||
friend class Event;
|
|
||||||
Event *event;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Machine memory
|
// Machine memory
|
||||||
bool write(Addr addr, size_t size, const char *data);
|
bool write(Addr addr, size_t size, const char *data);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RemoteGDB(System *system, ThreadContext *context);
|
RemoteGDB(System *system, ThreadContext *context);
|
||||||
~RemoteGDB();
|
|
||||||
|
|
||||||
bool acc(Addr addr, size_t len);
|
bool acc(Addr addr, size_t len);
|
||||||
|
|
||||||
|
@ -83,47 +64,10 @@ namespace AlphaISA
|
||||||
void clearSingleStep();
|
void clearSingleStep();
|
||||||
void setSingleStep();
|
void setSingleStep();
|
||||||
|
|
||||||
PCEventQueue *getPcEventQueue();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
class HardBreakpoint : public PCEvent
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
RemoteGDB *gdb;
|
|
||||||
|
|
||||||
public:
|
Addr notTakenBkpt;
|
||||||
int refcount;
|
Addr takenBkpt;
|
||||||
|
|
||||||
public:
|
|
||||||
HardBreakpoint(RemoteGDB *_gdb, Addr addr);
|
|
||||||
std::string name() { return gdb->name() + ".hwbkpt"; }
|
|
||||||
|
|
||||||
virtual void process(ThreadContext *tc);
|
|
||||||
};
|
|
||||||
friend class HardBreakpoint;
|
|
||||||
|
|
||||||
typedef std::map<Addr, HardBreakpoint *> break_map_t;
|
|
||||||
typedef break_map_t::iterator break_iter_t;
|
|
||||||
break_map_t hardBreakMap;
|
|
||||||
|
|
||||||
bool insertSoftBreak(Addr addr, size_t len);
|
|
||||||
bool removeSoftBreak(Addr addr, size_t len);
|
|
||||||
bool insertHardBreak(Addr addr, size_t len);
|
|
||||||
bool removeHardBreak(Addr addr, size_t len);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
struct TempBreakpoint {
|
|
||||||
Addr address; // set here
|
|
||||||
MachInst bkpt_inst; // saved instruction at bkpt
|
|
||||||
int init_count; // number of times to skip bkpt
|
|
||||||
int count; // current count
|
|
||||||
};
|
|
||||||
|
|
||||||
TempBreakpoint notTakenBkpt;
|
|
||||||
TempBreakpoint takenBkpt;
|
|
||||||
|
|
||||||
void clearTempBreakpoint(TempBreakpoint &bkpt);
|
|
||||||
void setTempBreakpoint(TempBreakpoint &bkpt, Addr addr);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -124,7 +124,6 @@
|
||||||
#include "arch/vtophys.hh"
|
#include "arch/vtophys.hh"
|
||||||
#include "arch/sparc/remote_gdb.hh"
|
#include "arch/sparc/remote_gdb.hh"
|
||||||
#include "base/intmath.hh"
|
#include "base/intmath.hh"
|
||||||
#include "base/kgdb.h"
|
|
||||||
#include "base/remote_gdb.hh"
|
#include "base/remote_gdb.hh"
|
||||||
#include "base/socket.hh"
|
#include "base/socket.hh"
|
||||||
#include "base/trace.hh"
|
#include "base/trace.hh"
|
||||||
|
@ -138,30 +137,10 @@
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace TheISA;
|
using namespace TheISA;
|
||||||
|
|
||||||
RemoteGDB::Event::Event(RemoteGDB *g, int fd, int e)
|
|
||||||
: PollEvent(fd, e), gdb(g)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void
|
|
||||||
RemoteGDB::Event::process(int revent)
|
|
||||||
{
|
|
||||||
if (revent & POLLIN)
|
|
||||||
gdb->trap(ALPHA_KENTRY_IF);
|
|
||||||
else if (revent & POLLNVAL)
|
|
||||||
gdb->detach();
|
|
||||||
}
|
|
||||||
|
|
||||||
RemoteGDB::RemoteGDB(System *_system, ThreadContext *c)
|
RemoteGDB::RemoteGDB(System *_system, ThreadContext *c)
|
||||||
: BaseRemoteGDB(_system, c, KGDB_NUMREGS),
|
: BaseRemoteGDB(_system, c, NumGDBRegs)
|
||||||
event(NULL)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
RemoteGDB::~RemoteGDB()
|
|
||||||
{
|
|
||||||
if (event)
|
|
||||||
delete event;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
// RemoteGDB::acc
|
// RemoteGDB::acc
|
||||||
//
|
//
|
||||||
|
@ -170,6 +149,7 @@ RemoteGDB::~RemoteGDB()
|
||||||
bool
|
bool
|
||||||
RemoteGDB::acc(Addr va, size_t len)
|
RemoteGDB::acc(Addr va, size_t len)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
Addr last_va;
|
Addr last_va;
|
||||||
|
|
||||||
va = TheISA::TruncPage(va);
|
va = TheISA::TruncPage(va);
|
||||||
|
@ -208,40 +188,10 @@ RemoteGDB::acc(Addr va, size_t len)
|
||||||
} while (va < last_va);
|
} while (va < last_va);
|
||||||
|
|
||||||
DPRINTF(GDBAcc, "acc: %#x mapping is valid\n", va);
|
DPRINTF(GDBAcc, "acc: %#x mapping is valid\n", va);
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
|
||||||
// RemoteGDB::signal
|
|
||||||
//
|
|
||||||
// Translate a trap number into a Unix-compatible signal number.
|
|
||||||
// (GDB only understands Unix signal numbers.)
|
|
||||||
//
|
|
||||||
int
|
|
||||||
RemoteGDB::signal(int type)
|
|
||||||
{
|
|
||||||
switch (type) {
|
|
||||||
case ALPHA_KENTRY_INT:
|
|
||||||
return (SIGTRAP);
|
|
||||||
|
|
||||||
case ALPHA_KENTRY_UNA:
|
|
||||||
return (SIGBUS);
|
|
||||||
|
|
||||||
case ALPHA_KENTRY_ARITH:
|
|
||||||
return (SIGFPE);
|
|
||||||
|
|
||||||
case ALPHA_KENTRY_IF:
|
|
||||||
return (SIGILL);
|
|
||||||
|
|
||||||
case ALPHA_KENTRY_MM:
|
|
||||||
return (SIGSEGV);
|
|
||||||
|
|
||||||
default:
|
|
||||||
panic("unknown signal type");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
// RemoteGDB::getregs
|
// RemoteGDB::getregs
|
||||||
//
|
//
|
||||||
|
@ -252,24 +202,14 @@ RemoteGDB::getregs()
|
||||||
{
|
{
|
||||||
memset(gdbregs.regs, 0, gdbregs.size);
|
memset(gdbregs.regs, 0, gdbregs.size);
|
||||||
|
|
||||||
gdbregs.regs[KGDB_REG_PC] = context->readPC();
|
gdbregs.regs[RegPc] = context->readPC();
|
||||||
|
gdbregs.regs[RegNpc] = context->readNextPC();
|
||||||
// @todo: Currently this is very Alpha specific.
|
for(int x = RegG0; x <= RegI7; x++)
|
||||||
if (AlphaISA::PcPAL(gdbregs.regs[KGDB_REG_PC])) {
|
gdbregs.regs[x] = context->readIntReg(x - RegG0);
|
||||||
for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
|
for(int x = RegF0; x <= RegF31; x++)
|
||||||
gdbregs.regs[i] = context->readIntReg(AlphaISA::reg_redir[i]);
|
gdbregs.regs[x] = context->readFloatRegBits(x - RegF0);
|
||||||
}
|
gdbregs.regs[RegY] = context->readMiscReg(MISCREG_Y);
|
||||||
} else {
|
//XXX need to also load up Psr, Wim, Tbr, Fpsr, and Cpsr
|
||||||
for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
|
|
||||||
gdbregs.regs[i] = context->readIntReg(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef KGDB_FP_REGS
|
|
||||||
for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) {
|
|
||||||
gdbregs.regs[i + KGDB_REG_F0] = context->readFloatRegBits(i);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
|
@ -281,48 +221,20 @@ RemoteGDB::getregs()
|
||||||
void
|
void
|
||||||
RemoteGDB::setregs()
|
RemoteGDB::setregs()
|
||||||
{
|
{
|
||||||
// @todo: Currently this is very Alpha specific.
|
context->setPC(gdbregs.regs[RegPc]);
|
||||||
if (AlphaISA::PcPAL(gdbregs.regs[KGDB_REG_PC])) {
|
context->setNextPC(gdbregs.regs[RegNpc]);
|
||||||
for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
|
for(int x = RegG0; x <= RegI7; x++)
|
||||||
context->setIntReg(AlphaISA::reg_redir[i], gdbregs.regs[i]);
|
context->setIntReg(x - RegG0, gdbregs.regs[x]);
|
||||||
}
|
for(int x = RegF0; x <= RegF31; x++)
|
||||||
} else {
|
context->setFloatRegBits(x - RegF0, gdbregs.regs[x]);
|
||||||
for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
|
context->setMiscRegWithEffect(MISCREG_Y, gdbregs.regs[RegY]);
|
||||||
context->setIntReg(i, gdbregs.regs[i]);
|
//XXX need to also set Psr, Wim, Tbr, Fpsr, and Cpsr
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef KGDB_FP_REGS
|
|
||||||
for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) {
|
|
||||||
context->setFloatRegBits(i, gdbregs.regs[i + KGDB_REG_F0]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
context->setPC(gdbregs.regs[KGDB_REG_PC]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
RemoteGDB::setTempBreakpoint(TempBreakpoint &bkpt, Addr addr)
|
|
||||||
{
|
|
||||||
DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", addr);
|
|
||||||
|
|
||||||
bkpt.address = addr;
|
|
||||||
insertHardBreak(addr, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
RemoteGDB::clearTempBreakpoint(TempBreakpoint &bkpt)
|
|
||||||
{
|
|
||||||
DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n",
|
|
||||||
bkpt.address);
|
|
||||||
|
|
||||||
|
|
||||||
removeHardBreak(bkpt.address, 4);
|
|
||||||
bkpt.address = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RemoteGDB::clearSingleStep()
|
RemoteGDB::clearSingleStep()
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
DPRINTF(GDBMisc, "clearSingleStep bt_addr=%#x nt_addr=%#x\n",
|
DPRINTF(GDBMisc, "clearSingleStep bt_addr=%#x nt_addr=%#x\n",
|
||||||
takenBkpt.address, notTakenBkpt.address);
|
takenBkpt.address, notTakenBkpt.address);
|
||||||
|
|
||||||
|
@ -331,11 +243,13 @@ RemoteGDB::clearSingleStep()
|
||||||
|
|
||||||
if (notTakenBkpt.address != 0)
|
if (notTakenBkpt.address != 0)
|
||||||
clearTempBreakpoint(notTakenBkpt);
|
clearTempBreakpoint(notTakenBkpt);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RemoteGDB::setSingleStep()
|
RemoteGDB::setSingleStep()
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
Addr pc = context->readPC();
|
Addr pc = context->readPC();
|
||||||
Addr npc, bpc;
|
Addr npc, bpc;
|
||||||
bool set_bt = false;
|
bool set_bt = false;
|
||||||
|
@ -360,97 +274,5 @@ RemoteGDB::setSingleStep()
|
||||||
|
|
||||||
if (set_bt)
|
if (set_bt)
|
||||||
setTempBreakpoint(takenBkpt, bpc);
|
setTempBreakpoint(takenBkpt, bpc);
|
||||||
}
|
|
||||||
|
|
||||||
// Write bytes to kernel address space for debugger.
|
|
||||||
bool
|
|
||||||
RemoteGDB::write(Addr vaddr, size_t size, const char *data)
|
|
||||||
{
|
|
||||||
if (BaseRemoteGDB::write(vaddr, size, data)) {
|
|
||||||
#ifdef IMB
|
|
||||||
alpha_pal_imb();
|
|
||||||
#endif
|
#endif
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PCEventQueue *RemoteGDB::getPcEventQueue()
|
|
||||||
{
|
|
||||||
return &system->pcEventQueue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RemoteGDB::HardBreakpoint::HardBreakpoint(RemoteGDB *_gdb, Addr pc)
|
|
||||||
: PCEvent(_gdb->getPcEventQueue(), "HardBreakpoint Event", pc),
|
|
||||||
gdb(_gdb), refcount(0)
|
|
||||||
{
|
|
||||||
DPRINTF(GDBMisc, "creating hardware breakpoint at %#x\n", evpc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
RemoteGDB::HardBreakpoint::process(ThreadContext *tc)
|
|
||||||
{
|
|
||||||
DPRINTF(GDBMisc, "handling hardware breakpoint at %#x\n", pc());
|
|
||||||
|
|
||||||
if (tc == gdb->context)
|
|
||||||
gdb->trap(ALPHA_KENTRY_INT);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
RemoteGDB::insertSoftBreak(Addr addr, size_t len)
|
|
||||||
{
|
|
||||||
if (len != sizeof(MachInst))
|
|
||||||
panic("invalid length\n");
|
|
||||||
|
|
||||||
return insertHardBreak(addr, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
RemoteGDB::removeSoftBreak(Addr addr, size_t len)
|
|
||||||
{
|
|
||||||
if (len != sizeof(MachInst))
|
|
||||||
panic("invalid length\n");
|
|
||||||
|
|
||||||
return removeHardBreak(addr, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
RemoteGDB::insertHardBreak(Addr addr, size_t len)
|
|
||||||
{
|
|
||||||
if (len != sizeof(MachInst))
|
|
||||||
panic("invalid length\n");
|
|
||||||
|
|
||||||
DPRINTF(GDBMisc, "inserting hardware breakpoint at %#x\n", addr);
|
|
||||||
|
|
||||||
HardBreakpoint *&bkpt = hardBreakMap[addr];
|
|
||||||
if (bkpt == 0)
|
|
||||||
bkpt = new HardBreakpoint(this, addr);
|
|
||||||
|
|
||||||
bkpt->refcount++;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
RemoteGDB::removeHardBreak(Addr addr, size_t len)
|
|
||||||
{
|
|
||||||
if (len != sizeof(MachInst))
|
|
||||||
panic("invalid length\n");
|
|
||||||
|
|
||||||
DPRINTF(GDBMisc, "removing hardware breakpoint at %#x\n", addr);
|
|
||||||
|
|
||||||
break_iter_t i = hardBreakMap.find(addr);
|
|
||||||
if (i == hardBreakMap.end())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
HardBreakpoint *hbp = (*i).second;
|
|
||||||
if (--hbp->refcount == 0) {
|
|
||||||
delete hbp;
|
|
||||||
hardBreakMap.erase(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,34 +46,32 @@ namespace SparcISA
|
||||||
{
|
{
|
||||||
class RemoteGDB : public BaseRemoteGDB
|
class RemoteGDB : public BaseRemoteGDB
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
friend void debugger();
|
|
||||||
friend class GDBListener;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
class Event : public PollEvent
|
enum RegisterConstants
|
||||||
{
|
{
|
||||||
protected:
|
RegG0, RegG1, RegG2, RegG3, RegG4, RegG5, RegG6, RegG7,
|
||||||
RemoteGDB *gdb;
|
RegO0, RegO1, RegO2, RegO3, RegO4, RegO5, RegO6, RegO7,
|
||||||
|
RegL0, RegL1, RegL2, RegL3, RegL4, RegL5, RegL6, RegL7,
|
||||||
public:
|
RegI0, RegI1, RegI2, RegI3, RegI4, RegI5, RegI6, RegI7,
|
||||||
Event(RemoteGDB *g, int fd, int e);
|
RegF0, RegF1, RegF2, RegF3, RegF4, RegF5, RegF6, RegF7,
|
||||||
void process(int revent);
|
RegF8, RegF9, RegF10, RegF11, RegF12, RegF13, RegF14, RegF15,
|
||||||
|
RegF16, RegF17, RegF18, RegF19, RegF20, RegF21, RegF22, RegF23,
|
||||||
|
RegF24, RegF25, RegF26, RegF27, RegF28, RegF29, RegF30, RegF31,
|
||||||
|
RegY,
|
||||||
|
RegPsr,
|
||||||
|
RegWim,
|
||||||
|
RegTbr,
|
||||||
|
RegPc,
|
||||||
|
RegNpc,
|
||||||
|
RegFpsr,
|
||||||
|
RegCpsr,
|
||||||
|
NumGDBRegs
|
||||||
};
|
};
|
||||||
|
|
||||||
friend class Event;
|
|
||||||
Event *event;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// Machine memory
|
|
||||||
bool write(Addr addr, size_t size, const char *data);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RemoteGDB(System *system, ThreadContext *context);
|
RemoteGDB(System *system, ThreadContext *context);
|
||||||
~RemoteGDB();
|
|
||||||
|
|
||||||
bool acc(Addr addr, size_t len);
|
bool acc(Addr addr, size_t len);
|
||||||
int signal(int type);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void getregs();
|
void getregs();
|
||||||
|
@ -82,47 +80,7 @@ namespace SparcISA
|
||||||
void clearSingleStep();
|
void clearSingleStep();
|
||||||
void setSingleStep();
|
void setSingleStep();
|
||||||
|
|
||||||
PCEventQueue *getPcEventQueue();
|
Addr singleStepBreaks[2];
|
||||||
|
|
||||||
protected:
|
|
||||||
class HardBreakpoint : public PCEvent
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
RemoteGDB *gdb;
|
|
||||||
|
|
||||||
public:
|
|
||||||
int refcount;
|
|
||||||
|
|
||||||
public:
|
|
||||||
HardBreakpoint(RemoteGDB *_gdb, Addr addr);
|
|
||||||
std::string name() { return gdb->name() + ".hwbkpt"; }
|
|
||||||
|
|
||||||
virtual void process(ThreadContext *tc);
|
|
||||||
};
|
|
||||||
friend class HardBreakpoint;
|
|
||||||
|
|
||||||
typedef std::map<Addr, HardBreakpoint *> break_map_t;
|
|
||||||
typedef break_map_t::iterator break_iter_t;
|
|
||||||
break_map_t hardBreakMap;
|
|
||||||
|
|
||||||
bool insertSoftBreak(Addr addr, size_t len);
|
|
||||||
bool removeSoftBreak(Addr addr, size_t len);
|
|
||||||
bool insertHardBreak(Addr addr, size_t len);
|
|
||||||
bool removeHardBreak(Addr addr, size_t len);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
struct TempBreakpoint {
|
|
||||||
Addr address; // set here
|
|
||||||
MachInst bkpt_inst; // saved instruction at bkpt
|
|
||||||
int init_count; // number of times to skip bkpt
|
|
||||||
int count; // current count
|
|
||||||
};
|
|
||||||
|
|
||||||
TempBreakpoint notTakenBkpt;
|
|
||||||
TempBreakpoint takenBkpt;
|
|
||||||
|
|
||||||
void clearTempBreakpoint(TempBreakpoint &bkpt);
|
|
||||||
void setTempBreakpoint(TempBreakpoint &bkpt, Addr addr);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -571,6 +571,21 @@ BaseRemoteGDB::removeHardBreak(Addr addr, size_t len)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BaseRemoteGDB::setTempBreakpoint(Addr bkpt)
|
||||||
|
{
|
||||||
|
DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", bkpt);
|
||||||
|
insertHardBreak(bkpt, sizeof(TheISA::MachInst));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BaseRemoteGDB::clearTempBreakpoint(Addr &bkpt)
|
||||||
|
{
|
||||||
|
DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", bkpt);
|
||||||
|
removeHardBreak(bkpt, sizeof(TheISA::MachInst));
|
||||||
|
bkpt = 0;
|
||||||
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
BaseRemoteGDB::break_type(char c)
|
BaseRemoteGDB::break_type(char c)
|
||||||
{
|
{
|
||||||
|
|
|
@ -212,6 +212,10 @@ class BaseRemoteGDB
|
||||||
bool insertHardBreak(Addr addr, size_t len);
|
bool insertHardBreak(Addr addr, size_t len);
|
||||||
bool removeHardBreak(Addr addr, size_t len);
|
bool removeHardBreak(Addr addr, size_t len);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void clearTempBreakpoint(Addr &bkpt);
|
||||||
|
void setTempBreakpoint(Addr bkpt);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::string name();
|
std::string name();
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue