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 <unistd.h>
|
||||
|
||||
#include "arch/vtophys.hh"
|
||||
#include "arch/alpha/kgdb.h"
|
||||
#include "arch/alpha/remote_gdb.hh"
|
||||
#include "arch/vtophys.hh"
|
||||
#include "base/intmath.hh"
|
||||
#include "base/remote_gdb.hh"
|
||||
#include "base/socket.hh"
|
||||
|
@ -135,30 +136,12 @@
|
|||
#include "sim/system.hh"
|
||||
|
||||
using namespace std;
|
||||
using namespace AlphaISA;
|
||||
|
||||
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();
|
||||
}
|
||||
using namespace TheISA;
|
||||
|
||||
RemoteGDB::RemoteGDB(System *_system, ThreadContext *c)
|
||||
: BaseRemoteGDB(_system, c, KGDB_NUMREGS),
|
||||
event(NULL)
|
||||
{}
|
||||
|
||||
RemoteGDB::~RemoteGDB()
|
||||
: BaseRemoteGDB(_system, c, KGDB_NUMREGS)
|
||||
{
|
||||
if (event)
|
||||
delete event;
|
||||
memset(gdbregs.regs, 0, gdbregs.size);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
|
@ -268,36 +251,16 @@ RemoteGDB::setregs()
|
|||
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
|
||||
RemoteGDB::clearSingleStep()
|
||||
{
|
||||
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);
|
||||
|
||||
if (notTakenBkpt.address != 0)
|
||||
if (notTakenBkpt != 0)
|
||||
clearTempBreakpoint(notTakenBkpt);
|
||||
}
|
||||
|
||||
|
@ -322,12 +285,12 @@ RemoteGDB::setSingleStep()
|
|||
}
|
||||
|
||||
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)
|
||||
setTempBreakpoint(takenBkpt, bpc);
|
||||
setTempBreakpoint(takenBkpt = bpc);
|
||||
}
|
||||
|
||||
// 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
|
||||
{
|
||||
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:
|
||||
// Machine memory
|
||||
bool write(Addr addr, size_t size, const char *data);
|
||||
|
||||
public:
|
||||
RemoteGDB(System *system, ThreadContext *context);
|
||||
~RemoteGDB();
|
||||
|
||||
bool acc(Addr addr, size_t len);
|
||||
|
||||
|
@ -83,47 +64,10 @@ namespace AlphaISA
|
|||
void clearSingleStep();
|
||||
void setSingleStep();
|
||||
|
||||
PCEventQueue *getPcEventQueue();
|
||||
|
||||
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);
|
||||
Addr notTakenBkpt;
|
||||
Addr takenBkpt;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -124,7 +124,6 @@
|
|||
#include "arch/vtophys.hh"
|
||||
#include "arch/sparc/remote_gdb.hh"
|
||||
#include "base/intmath.hh"
|
||||
#include "base/kgdb.h"
|
||||
#include "base/remote_gdb.hh"
|
||||
#include "base/socket.hh"
|
||||
#include "base/trace.hh"
|
||||
|
@ -138,30 +137,10 @@
|
|||
using namespace std;
|
||||
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)
|
||||
: BaseRemoteGDB(_system, c, KGDB_NUMREGS),
|
||||
event(NULL)
|
||||
: BaseRemoteGDB(_system, c, NumGDBRegs)
|
||||
{}
|
||||
|
||||
RemoteGDB::~RemoteGDB()
|
||||
{
|
||||
if (event)
|
||||
delete event;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// RemoteGDB::acc
|
||||
//
|
||||
|
@ -170,6 +149,7 @@ RemoteGDB::~RemoteGDB()
|
|||
bool
|
||||
RemoteGDB::acc(Addr va, size_t len)
|
||||
{
|
||||
#if 0
|
||||
Addr last_va;
|
||||
|
||||
va = TheISA::TruncPage(va);
|
||||
|
@ -208,40 +188,10 @@ RemoteGDB::acc(Addr va, size_t len)
|
|||
} while (va < last_va);
|
||||
|
||||
DPRINTF(GDBAcc, "acc: %#x mapping is valid\n", va);
|
||||
#endif
|
||||
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
|
||||
//
|
||||
|
@ -252,24 +202,14 @@ RemoteGDB::getregs()
|
|||
{
|
||||
memset(gdbregs.regs, 0, gdbregs.size);
|
||||
|
||||
gdbregs.regs[KGDB_REG_PC] = context->readPC();
|
||||
|
||||
// @todo: Currently this is very Alpha specific.
|
||||
if (AlphaISA::PcPAL(gdbregs.regs[KGDB_REG_PC])) {
|
||||
for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
|
||||
gdbregs.regs[i] = context->readIntReg(AlphaISA::reg_redir[i]);
|
||||
}
|
||||
} else {
|
||||
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
|
||||
gdbregs.regs[RegPc] = context->readPC();
|
||||
gdbregs.regs[RegNpc] = context->readNextPC();
|
||||
for(int x = RegG0; x <= RegI7; x++)
|
||||
gdbregs.regs[x] = context->readIntReg(x - RegG0);
|
||||
for(int x = RegF0; x <= RegF31; x++)
|
||||
gdbregs.regs[x] = context->readFloatRegBits(x - RegF0);
|
||||
gdbregs.regs[RegY] = context->readMiscReg(MISCREG_Y);
|
||||
//XXX need to also load up Psr, Wim, Tbr, Fpsr, and Cpsr
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
|
@ -281,48 +221,20 @@ RemoteGDB::getregs()
|
|||
void
|
||||
RemoteGDB::setregs()
|
||||
{
|
||||
// @todo: Currently this is very Alpha specific.
|
||||
if (AlphaISA::PcPAL(gdbregs.regs[KGDB_REG_PC])) {
|
||||
for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
|
||||
context->setIntReg(AlphaISA::reg_redir[i], gdbregs.regs[i]);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
|
||||
context->setIntReg(i, gdbregs.regs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#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;
|
||||
context->setPC(gdbregs.regs[RegPc]);
|
||||
context->setNextPC(gdbregs.regs[RegNpc]);
|
||||
for(int x = RegG0; x <= RegI7; x++)
|
||||
context->setIntReg(x - RegG0, gdbregs.regs[x]);
|
||||
for(int x = RegF0; x <= RegF31; x++)
|
||||
context->setFloatRegBits(x - RegF0, gdbregs.regs[x]);
|
||||
context->setMiscRegWithEffect(MISCREG_Y, gdbregs.regs[RegY]);
|
||||
//XXX need to also set Psr, Wim, Tbr, Fpsr, and Cpsr
|
||||
}
|
||||
|
||||
void
|
||||
RemoteGDB::clearSingleStep()
|
||||
{
|
||||
#if 0
|
||||
DPRINTF(GDBMisc, "clearSingleStep bt_addr=%#x nt_addr=%#x\n",
|
||||
takenBkpt.address, notTakenBkpt.address);
|
||||
|
||||
|
@ -331,11 +243,13 @@ RemoteGDB::clearSingleStep()
|
|||
|
||||
if (notTakenBkpt.address != 0)
|
||||
clearTempBreakpoint(notTakenBkpt);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
RemoteGDB::setSingleStep()
|
||||
{
|
||||
#if 0
|
||||
Addr pc = context->readPC();
|
||||
Addr npc, bpc;
|
||||
bool set_bt = false;
|
||||
|
@ -360,97 +274,5 @@ RemoteGDB::setSingleStep()
|
|||
|
||||
if (set_bt)
|
||||
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
|
||||
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
|
||||
{
|
||||
private:
|
||||
friend void debugger();
|
||||
friend class GDBListener;
|
||||
|
||||
protected:
|
||||
class Event : public PollEvent
|
||||
enum RegisterConstants
|
||||
{
|
||||
protected:
|
||||
RemoteGDB *gdb;
|
||||
|
||||
public:
|
||||
Event(RemoteGDB *g, int fd, int e);
|
||||
void process(int revent);
|
||||
RegG0, RegG1, RegG2, RegG3, RegG4, RegG5, RegG6, RegG7,
|
||||
RegO0, RegO1, RegO2, RegO3, RegO4, RegO5, RegO6, RegO7,
|
||||
RegL0, RegL1, RegL2, RegL3, RegL4, RegL5, RegL6, RegL7,
|
||||
RegI0, RegI1, RegI2, RegI3, RegI4, RegI5, RegI6, RegI7,
|
||||
RegF0, RegF1, RegF2, RegF3, RegF4, RegF5, RegF6, RegF7,
|
||||
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:
|
||||
RemoteGDB(System *system, ThreadContext *context);
|
||||
~RemoteGDB();
|
||||
|
||||
bool acc(Addr addr, size_t len);
|
||||
int signal(int type);
|
||||
|
||||
protected:
|
||||
void getregs();
|
||||
|
@ -82,47 +80,7 @@ namespace SparcISA
|
|||
void clearSingleStep();
|
||||
void setSingleStep();
|
||||
|
||||
PCEventQueue *getPcEventQueue();
|
||||
|
||||
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);
|
||||
Addr singleStepBreaks[2];
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -571,6 +571,21 @@ BaseRemoteGDB::removeHardBreak(Addr addr, size_t len)
|
|||
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 *
|
||||
BaseRemoteGDB::break_type(char c)
|
||||
{
|
||||
|
|
|
@ -212,6 +212,10 @@ class BaseRemoteGDB
|
|||
bool insertHardBreak(Addr addr, size_t len);
|
||||
bool removeHardBreak(Addr addr, size_t len);
|
||||
|
||||
protected:
|
||||
void clearTempBreakpoint(Addr &bkpt);
|
||||
void setTempBreakpoint(Addr bkpt);
|
||||
|
||||
public:
|
||||
std::string name();
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue