X86: Reorganize the native tracing code.
Ignore different values or rcx and r11 after a syscall until either the local or remote value changes. Also change the codes organization somewhat. --HG-- extra : convert_revision : 2c1f69d4e55b443e68bfc7b43e8387b02cf0b6b5
This commit is contained in:
parent
4b29d22386
commit
e42524af02
|
@ -60,119 +60,122 @@ NativeTrace::NativeTrace(const std::string & _name) : InstTracer(_name)
|
|||
}
|
||||
ccprintf(cerr, "Listening for native process on port %d\n", port);
|
||||
fd = native_listener.accept();
|
||||
checkRcx = true;
|
||||
checkR11 = true;
|
||||
}
|
||||
|
||||
bool
|
||||
NativeTraceRecord::checkIntReg(const char * regName, int index, int size)
|
||||
NativeTrace::checkRcxReg(const char * name, uint64_t &mVal, uint64_t &nVal)
|
||||
{
|
||||
uint64_t regVal;
|
||||
int res = read(parent->fd, ®Val, size);
|
||||
if(res < 0)
|
||||
panic("Read call failed! %s\n", strerror(errno));
|
||||
regVal = TheISA::gtoh(regVal);
|
||||
uint64_t realRegVal = thread->readIntReg(index);
|
||||
if(regVal != realRegVal)
|
||||
{
|
||||
DPRINTFN("Register %s should be %#x but is %#x.\n",
|
||||
regName, regVal, realRegVal);
|
||||
return false;
|
||||
}
|
||||
if(!checkRcx)
|
||||
checkRcx = (mVal != oldRcxVal || nVal != oldRealRcxVal);
|
||||
if(checkRcx)
|
||||
return checkReg(name, mVal, nVal);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NativeTraceRecord::checkPC(const char * regName, int size)
|
||||
bool
|
||||
NativeTrace::checkR11Reg(const char * name, uint64_t &mVal, uint64_t &nVal)
|
||||
{
|
||||
uint64_t regVal;
|
||||
int res = read(parent->fd, ®Val, size);
|
||||
if(res < 0)
|
||||
panic("Read call failed! %s\n", strerror(errno));
|
||||
regVal = TheISA::gtoh(regVal);
|
||||
uint64_t realRegVal = thread->readNextPC();
|
||||
if(regVal != realRegVal)
|
||||
{
|
||||
DPRINTFN("%s should be %#x but is %#x.\n",
|
||||
regName, regVal, realRegVal);
|
||||
return false;
|
||||
}
|
||||
if(!checkR11)
|
||||
checkR11 = (mVal != oldR11Val || nVal != oldRealR11Val);
|
||||
if(checkR11)
|
||||
return checkReg(name, mVal, nVal);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Trace::NativeTraceRecord::dump()
|
||||
{
|
||||
// ostream &outs = Trace::output();
|
||||
|
||||
//Don't print what happens for each micro-op, just print out
|
||||
//once at the last op, and for regular instructions.
|
||||
if(!staticInst->isMicroop() || staticInst->isLastMicroop())
|
||||
parent->check(thread, staticInst->isSyscall());
|
||||
}
|
||||
|
||||
void
|
||||
Trace::NativeTrace::check(ThreadContext * tc, bool isSyscall)
|
||||
{
|
||||
// ostream &outs = Trace::output();
|
||||
nState.update(fd);
|
||||
mState.update(tc);
|
||||
|
||||
if(isSyscall)
|
||||
{
|
||||
checkIntReg("rax", INTREG_RAX, sizeof(uint64_t));
|
||||
checkIntReg("rcx", INTREG_RCX, sizeof(uint64_t));
|
||||
checkIntReg("rdx", INTREG_RDX, sizeof(uint64_t));
|
||||
checkIntReg("rbx", INTREG_RBX, sizeof(uint64_t));
|
||||
checkIntReg("rsp", INTREG_RSP, sizeof(uint64_t));
|
||||
checkIntReg("rbp", INTREG_RBP, sizeof(uint64_t));
|
||||
checkIntReg("rsi", INTREG_RSI, sizeof(uint64_t));
|
||||
checkIntReg("rdi", INTREG_RDI, sizeof(uint64_t));
|
||||
checkIntReg("r8", INTREG_R8, sizeof(uint64_t));
|
||||
checkIntReg("r9", INTREG_R9, sizeof(uint64_t));
|
||||
checkIntReg("r10", INTREG_R10, sizeof(uint64_t));
|
||||
checkIntReg("r11", INTREG_R11, sizeof(uint64_t));
|
||||
checkIntReg("r12", INTREG_R12, sizeof(uint64_t));
|
||||
checkIntReg("r13", INTREG_R13, sizeof(uint64_t));
|
||||
checkIntReg("r14", INTREG_R14, sizeof(uint64_t));
|
||||
checkIntReg("r15", INTREG_R15, sizeof(uint64_t));
|
||||
checkPC("rip", sizeof(uint64_t));
|
||||
checkRcx = false;
|
||||
checkR11 = false;
|
||||
oldRcxVal = mState.rcx;
|
||||
oldRealRcxVal = nState.rcx;
|
||||
oldR11Val = mState.r11;
|
||||
oldRealR11Val = nState.r11;
|
||||
}
|
||||
|
||||
checkReg("rax", mState.rax, nState.rax);
|
||||
checkRcxReg("rcx", mState.rcx, nState.rcx);
|
||||
checkReg("rdx", mState.rdx, nState.rdx);
|
||||
checkReg("rbx", mState.rbx, nState.rbx);
|
||||
checkReg("rsp", mState.rsp, nState.rsp);
|
||||
checkReg("rbp", mState.rbp, nState.rbp);
|
||||
checkReg("rsi", mState.rsi, nState.rsi);
|
||||
checkReg("rdi", mState.rdi, nState.rdi);
|
||||
checkReg("r8", mState.r8, nState.r8);
|
||||
checkReg("r9", mState.r9, nState.r9);
|
||||
checkReg("r10", mState.r10, nState.r10);
|
||||
checkR11Reg("r11", mState.r11, nState.r11);
|
||||
checkReg("r12", mState.r12, nState.r12);
|
||||
checkReg("r13", mState.r13, nState.r13);
|
||||
checkReg("r14", mState.r14, nState.r14);
|
||||
checkReg("r15", mState.r15, nState.r15);
|
||||
checkReg("rip", mState.rip, nState.rip);
|
||||
#if THE_ISA == SPARC_ISA
|
||||
/*for(int f = 0; f <= 62; f+=2)
|
||||
{
|
||||
uint64_t regVal;
|
||||
int res = read(fd, ®Val, sizeof(regVal));
|
||||
if(res < 0)
|
||||
panic("First read call failed! %s\n", strerror(errno));
|
||||
regVal = TheISA::gtoh(regVal);
|
||||
uint64_t realRegVal = thread->readFloatRegBits(f, 64);
|
||||
if(regVal != realRegVal)
|
||||
{
|
||||
DPRINTF(ExecRegDelta, "Register f%d should be %#x but is %#x.\n", f, regVal, realRegVal);
|
||||
}
|
||||
}*/
|
||||
/*for(int f = 0; f <= 62; f+=2)
|
||||
{
|
||||
uint64_t regVal;
|
||||
int res = read(fd, ®Val, sizeof(regVal));
|
||||
if(res < 0)
|
||||
panic("First read call failed! %s\n", strerror(errno));
|
||||
regVal = TheISA::gtoh(regVal);
|
||||
uint64_t realRegVal = thread->readNextPC();
|
||||
uint64_t realRegVal = thread->readFloatRegBits(f, 64);
|
||||
if(regVal != realRegVal)
|
||||
{
|
||||
DPRINTF(ExecRegDelta,
|
||||
"Register pc should be %#x but is %#x.\n",
|
||||
regVal, realRegVal);
|
||||
DPRINTF(ExecRegDelta, "Register f%d should be %#x but is %#x.\n", f, regVal, realRegVal);
|
||||
}
|
||||
res = read(fd, ®Val, sizeof(regVal));
|
||||
if(res < 0)
|
||||
panic("First read call failed! %s\n", strerror(errno));
|
||||
regVal = TheISA::gtoh(regVal);
|
||||
realRegVal = thread->readNextNPC();
|
||||
if(regVal != realRegVal)
|
||||
{
|
||||
DPRINTF(ExecRegDelta,
|
||||
"Register npc should be %#x but is %#x.\n",
|
||||
regVal, realRegVal);
|
||||
}
|
||||
res = read(fd, ®Val, sizeof(regVal));
|
||||
if(res < 0)
|
||||
panic("First read call failed! %s\n", strerror(errno));
|
||||
regVal = TheISA::gtoh(regVal);
|
||||
realRegVal = thread->readIntReg(SparcISA::NumIntArchRegs + 2);
|
||||
if((regVal & 0xF) != (realRegVal & 0xF))
|
||||
{
|
||||
DPRINTF(ExecRegDelta,
|
||||
"Register ccr should be %#x but is %#x.\n",
|
||||
regVal, realRegVal);
|
||||
}
|
||||
#endif
|
||||
}*/
|
||||
uint64_t regVal;
|
||||
int res = read(fd, ®Val, sizeof(regVal));
|
||||
if(res < 0)
|
||||
panic("First read call failed! %s\n", strerror(errno));
|
||||
regVal = TheISA::gtoh(regVal);
|
||||
uint64_t realRegVal = thread->readNextPC();
|
||||
if(regVal != realRegVal)
|
||||
{
|
||||
DPRINTF(ExecRegDelta,
|
||||
"Register pc should be %#x but is %#x.\n",
|
||||
regVal, realRegVal);
|
||||
}
|
||||
res = read(fd, ®Val, sizeof(regVal));
|
||||
if(res < 0)
|
||||
panic("First read call failed! %s\n", strerror(errno));
|
||||
regVal = TheISA::gtoh(regVal);
|
||||
realRegVal = thread->readNextNPC();
|
||||
if(regVal != realRegVal)
|
||||
{
|
||||
DPRINTF(ExecRegDelta,
|
||||
"Register npc should be %#x but is %#x.\n",
|
||||
regVal, realRegVal);
|
||||
}
|
||||
res = read(fd, ®Val, sizeof(regVal));
|
||||
if(res < 0)
|
||||
panic("First read call failed! %s\n", strerror(errno));
|
||||
regVal = TheISA::gtoh(regVal);
|
||||
realRegVal = thread->readIntReg(SparcISA::NumIntArchRegs + 2);
|
||||
if((regVal & 0xF) != (realRegVal & 0xF))
|
||||
{
|
||||
DPRINTF(ExecRegDelta,
|
||||
"Register ccr should be %#x but is %#x.\n",
|
||||
regVal, realRegVal);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* namespace Trace */ }
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "cpu/static_inst.hh"
|
||||
#include "sim/host.hh"
|
||||
#include "sim/insttracer.hh"
|
||||
#include "arch/x86/intregs.hh"
|
||||
|
||||
class ThreadContext;
|
||||
|
||||
|
@ -49,12 +50,6 @@ class NativeTraceRecord : public InstRecord
|
|||
protected:
|
||||
NativeTrace * parent;
|
||||
|
||||
bool
|
||||
checkIntReg(const char * regName, int index, int size);
|
||||
|
||||
bool
|
||||
checkPC(const char * regName, int size);
|
||||
|
||||
public:
|
||||
NativeTraceRecord(NativeTrace * _parent,
|
||||
Tick _when, ThreadContext *_thread,
|
||||
|
@ -73,8 +68,109 @@ class NativeTrace : public InstTracer
|
|||
|
||||
ListenSocket native_listener;
|
||||
|
||||
bool checkRcx;
|
||||
bool checkR11;
|
||||
uint64_t oldRcxVal, oldR11Val;
|
||||
uint64_t oldRealRcxVal, oldRealR11Val;
|
||||
|
||||
struct ThreadState {
|
||||
uint64_t rax;
|
||||
uint64_t rcx;
|
||||
uint64_t rdx;
|
||||
uint64_t rbx;
|
||||
uint64_t rsp;
|
||||
uint64_t rbp;
|
||||
uint64_t rsi;
|
||||
uint64_t rdi;
|
||||
uint64_t r8;
|
||||
uint64_t r9;
|
||||
uint64_t r10;
|
||||
uint64_t r11;
|
||||
uint64_t r12;
|
||||
uint64_t r13;
|
||||
uint64_t r14;
|
||||
uint64_t r15;
|
||||
uint64_t rip;
|
||||
|
||||
void update(int fd)
|
||||
{
|
||||
int bytesLeft = sizeof(ThreadState);
|
||||
int bytesRead = 0;
|
||||
do
|
||||
{
|
||||
int res = read(fd, ((char *)this) + bytesRead, bytesLeft);
|
||||
if(res < 0)
|
||||
panic("Read call failed! %s\n", strerror(errno));
|
||||
bytesLeft -= res;
|
||||
bytesRead += res;
|
||||
} while(bytesLeft);
|
||||
rax = TheISA::gtoh(rax);
|
||||
rcx = TheISA::gtoh(rcx);
|
||||
rdx = TheISA::gtoh(rdx);
|
||||
rbx = TheISA::gtoh(rbx);
|
||||
rsp = TheISA::gtoh(rsp);
|
||||
rbp = TheISA::gtoh(rbp);
|
||||
rsi = TheISA::gtoh(rsi);
|
||||
rdi = TheISA::gtoh(rdi);
|
||||
r8 = TheISA::gtoh(r8);
|
||||
r9 = TheISA::gtoh(r9);
|
||||
r10 = TheISA::gtoh(r10);
|
||||
r11 = TheISA::gtoh(r11);
|
||||
r12 = TheISA::gtoh(r12);
|
||||
r13 = TheISA::gtoh(r13);
|
||||
r14 = TheISA::gtoh(r14);
|
||||
r15 = TheISA::gtoh(r15);
|
||||
rip = TheISA::gtoh(rip);
|
||||
}
|
||||
|
||||
void update(ThreadContext * tc)
|
||||
{
|
||||
rax = tc->readIntReg(X86ISA::INTREG_RAX);
|
||||
rcx = tc->readIntReg(X86ISA::INTREG_RCX);
|
||||
rdx = tc->readIntReg(X86ISA::INTREG_RDX);
|
||||
rbx = tc->readIntReg(X86ISA::INTREG_RBX);
|
||||
rsp = tc->readIntReg(X86ISA::INTREG_RSP);
|
||||
rbp = tc->readIntReg(X86ISA::INTREG_RBP);
|
||||
rsi = tc->readIntReg(X86ISA::INTREG_RSI);
|
||||
rdi = tc->readIntReg(X86ISA::INTREG_RDI);
|
||||
r8 = tc->readIntReg(X86ISA::INTREG_R8);
|
||||
r9 = tc->readIntReg(X86ISA::INTREG_R9);
|
||||
r10 = tc->readIntReg(X86ISA::INTREG_R10);
|
||||
r11 = tc->readIntReg(X86ISA::INTREG_R11);
|
||||
r12 = tc->readIntReg(X86ISA::INTREG_R12);
|
||||
r13 = tc->readIntReg(X86ISA::INTREG_R13);
|
||||
r14 = tc->readIntReg(X86ISA::INTREG_R14);
|
||||
r15 = tc->readIntReg(X86ISA::INTREG_R15);
|
||||
rip = tc->readNextPC();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
ThreadState nState;
|
||||
ThreadState mState;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
template<class T>
|
||||
bool
|
||||
checkReg(const char * regName, T &val, T &realVal)
|
||||
{
|
||||
if(val != realVal)
|
||||
{
|
||||
DPRINTFN("Register %s should be %#x but is %#x.\n",
|
||||
regName, realVal, val);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
checkRcxReg(const char * regName, uint64_t &, uint64_t &);
|
||||
|
||||
bool
|
||||
checkR11Reg(const char * regName, uint64_t &, uint64_t &);
|
||||
|
||||
NativeTrace(const std::string & name);
|
||||
|
||||
NativeTraceRecord *
|
||||
|
@ -88,6 +184,9 @@ class NativeTrace : public InstTracer
|
|||
staticInst, pc, tc->misspeculating());
|
||||
}
|
||||
|
||||
void
|
||||
check(ThreadContext *, bool syscall);
|
||||
|
||||
friend class NativeTraceRecord;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue