Broke remote_gdb into a base class and architecture specific derived classes.

--HG--
extra : convert_revision : 8c528fab56a95b8245ad0f2572d62bb556ce0dde
This commit is contained in:
Gabe Black 2006-11-07 05:39:40 -05:00
parent da24915181
commit 54e22bfe95
6 changed files with 73 additions and 445 deletions

View file

@ -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;
}

View file

@ -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);
}; };
} }

View file

@ -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;
} }

View file

@ -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);
}; };
} }

View file

@ -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)
{ {

View file

@ -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();
}; };