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

View file

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

View file

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

View file

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

View file

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

View file

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