Statetrace: Clean up style.
This commit is contained in:
parent
07b507d278
commit
3df970f0de
16 changed files with 856 additions and 917 deletions
|
@ -55,14 +55,10 @@ const char * AMD64TraceChild::regNames[numregs] = {
|
||||||
//Flags
|
//Flags
|
||||||
"eflags",
|
"eflags",
|
||||||
//MMX
|
//MMX
|
||||||
"mmx0_0", "mmx0_1",
|
"mmx0_0", "mmx0_1", "mmx1_0", "mmx1_1",
|
||||||
"mmx1_0", "mmx1_1",
|
"mmx2_0", "mmx2_1", "mmx3_0", "mmx3_1",
|
||||||
"mmx2_0", "mmx2_1",
|
"mmx4_0", "mmx4_1", "mmx5_0", "mmx5_1",
|
||||||
"mmx3_0", "mmx3_1",
|
"mmx6_0", "mmx6_1", "mmx7_0", "mmx7_1",
|
||||||
"mmx4_0", "mmx4_1",
|
|
||||||
"mmx5_0", "mmx5_1",
|
|
||||||
"mmx6_0", "mmx6_1",
|
|
||||||
"mmx7_0", "mmx7_1",
|
|
||||||
//XMM
|
//XMM
|
||||||
"xmm0_0", "xmm0_1", "xmm0_2", "xmm0_3",
|
"xmm0_0", "xmm0_1", "xmm0_2", "xmm0_3",
|
||||||
"xmm1_0", "xmm1_1", "xmm1_2", "xmm1_3",
|
"xmm1_0", "xmm1_1", "xmm1_2", "xmm1_3",
|
||||||
|
@ -81,42 +77,36 @@ const char * AMD64TraceChild::regNames[numregs] = {
|
||||||
"xmm14_0", "xmm14_1", "xmm14_2", "xmm14_3",
|
"xmm14_0", "xmm14_1", "xmm14_2", "xmm14_3",
|
||||||
"xmm15_0", "xmm15_1", "xmm15_2", "xmm15_3"};
|
"xmm15_0", "xmm15_1", "xmm15_2", "xmm15_3"};
|
||||||
|
|
||||||
bool AMD64TraceChild::sendState(int socket)
|
bool
|
||||||
|
AMD64TraceChild::sendState(int socket)
|
||||||
{
|
{
|
||||||
uint64_t regVal64 = 0;
|
uint64_t regVal64 = 0;
|
||||||
uint32_t regVal32 = 0;
|
uint32_t regVal32 = 0;
|
||||||
for(int x = 0; x <= R15; x++)
|
for (int x = 0; x <= R15; x++) {
|
||||||
{
|
|
||||||
regVal64 = getRegVal(x);
|
regVal64 = getRegVal(x);
|
||||||
if(write(socket, ®Val64, sizeof(regVal64)) == -1)
|
if (write(socket, ®Val64, sizeof(regVal64)) == -1) {
|
||||||
{
|
|
||||||
cerr << "Write failed! " << strerror(errno) << endl;
|
cerr << "Write failed! " << strerror(errno) << endl;
|
||||||
tracing = false;
|
tracing = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
regVal64 = getRegVal(RIP);
|
regVal64 = getRegVal(RIP);
|
||||||
if(write(socket, ®Val64, sizeof(regVal64)) == -1)
|
if (write(socket, ®Val64, sizeof(regVal64)) == -1) {
|
||||||
{
|
|
||||||
cerr << "Write failed! " << strerror(errno) << endl;
|
cerr << "Write failed! " << strerror(errno) << endl;
|
||||||
tracing = false;
|
tracing = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for(int x = MMX0_0; x <= MMX7_1; x++)
|
for (int x = MMX0_0; x <= MMX7_1; x++) {
|
||||||
{
|
|
||||||
regVal32 = getRegVal(x);
|
regVal32 = getRegVal(x);
|
||||||
if(write(socket, ®Val32, sizeof(regVal32)) == -1)
|
if (write(socket, ®Val32, sizeof(regVal32)) == -1) {
|
||||||
{
|
|
||||||
cerr << "Write failed! " << strerror(errno) << endl;
|
cerr << "Write failed! " << strerror(errno) << endl;
|
||||||
tracing = false;
|
tracing = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(int x = XMM0_0; x <= XMM15_3; x++)
|
for (int x = XMM0_0; x <= XMM15_3; x++) {
|
||||||
{
|
|
||||||
regVal32 = getRegVal(x);
|
regVal32 = getRegVal(x);
|
||||||
if(write(socket, ®Val32, sizeof(regVal32)) == -1)
|
if (write(socket, ®Val32, sizeof(regVal32)) == -1) {
|
||||||
{
|
|
||||||
cerr << "Write failed! " << strerror(errno) << endl;
|
cerr << "Write failed! " << strerror(errno) << endl;
|
||||||
tracing = false;
|
tracing = false;
|
||||||
return false;
|
return false;
|
||||||
|
@ -125,12 +115,12 @@ bool AMD64TraceChild::sendState(int socket)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t AMD64TraceChild::getRegs(user_regs_struct & myregs,
|
int64_t
|
||||||
|
AMD64TraceChild::getRegs(user_regs_struct & myregs,
|
||||||
user_fpregs_struct & myfpregs, int num)
|
user_fpregs_struct & myfpregs, int num)
|
||||||
{
|
{
|
||||||
assert(num < numregs && num >= 0);
|
assert(num < numregs && num >= 0);
|
||||||
switch(num)
|
switch (num) {
|
||||||
{
|
|
||||||
//GPRs
|
//GPRs
|
||||||
case RAX: return myregs.rax;
|
case RAX: return myregs.rax;
|
||||||
case RBX: return myregs.rbx;
|
case RBX: return myregs.rbx;
|
||||||
|
@ -252,48 +242,51 @@ int64_t AMD64TraceChild::getRegs(user_regs_struct & myregs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AMD64TraceChild::update(int pid)
|
bool
|
||||||
|
AMD64TraceChild::update(int pid)
|
||||||
{
|
{
|
||||||
oldregs = regs;
|
oldregs = regs;
|
||||||
oldfpregs = fpregs;
|
oldfpregs = fpregs;
|
||||||
if(ptrace(PTRACE_GETREGS, pid, 0, ®s) != 0)
|
if (ptrace(PTRACE_GETREGS, pid, 0, ®s) != 0) {
|
||||||
{
|
|
||||||
cerr << "update: " << strerror(errno) << endl;
|
cerr << "update: " << strerror(errno) << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(ptrace(PTRACE_GETFPREGS, pid, 0, &fpregs) != 0)
|
if (ptrace(PTRACE_GETFPREGS, pid, 0, &fpregs) != 0) {
|
||||||
{
|
|
||||||
cerr << "update: " << strerror(errno) << endl;
|
cerr << "update: " << strerror(errno) << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for(unsigned int x = 0; x < numregs; x++)
|
for (unsigned int x = 0; x < numregs; x++)
|
||||||
regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x));
|
regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
AMD64TraceChild::AMD64TraceChild()
|
AMD64TraceChild::AMD64TraceChild()
|
||||||
{
|
{
|
||||||
for(unsigned int x = 0; x < numregs; x++)
|
for (unsigned int x = 0; x < numregs; x++)
|
||||||
regDiffSinceUpdate[x] = false;
|
regDiffSinceUpdate[x] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t AMD64TraceChild::getRegVal(int num)
|
int64_t
|
||||||
|
AMD64TraceChild::getRegVal(int num)
|
||||||
{
|
{
|
||||||
return getRegs(regs, fpregs, num);
|
return getRegs(regs, fpregs, num);
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t AMD64TraceChild::getOldRegVal(int num)
|
int64_t
|
||||||
|
AMD64TraceChild::getOldRegVal(int num)
|
||||||
{
|
{
|
||||||
return getRegs(oldregs, oldfpregs, num);
|
return getRegs(oldregs, oldfpregs, num);
|
||||||
}
|
}
|
||||||
|
|
||||||
char * AMD64TraceChild::printReg(int num)
|
char *
|
||||||
|
AMD64TraceChild::printReg(int num)
|
||||||
{
|
{
|
||||||
sprintf(printBuffer, "0x%016lX", getRegVal(num));
|
sprintf(printBuffer, "0x%016lX", getRegVal(num));
|
||||||
return printBuffer;
|
return printBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
ostream & AMD64TraceChild::outputStartState(ostream & os)
|
ostream &
|
||||||
|
AMD64TraceChild::outputStartState(ostream & os)
|
||||||
{
|
{
|
||||||
uint64_t sp = getSP();
|
uint64_t sp = getSP();
|
||||||
uint64_t pc = getPC();
|
uint64_t pc = getPC();
|
||||||
|
@ -313,13 +306,12 @@ ostream & AMD64TraceChild::outputStartState(ostream & os)
|
||||||
//Output argv pointers
|
//Output argv pointers
|
||||||
int argCount = 0;
|
int argCount = 0;
|
||||||
uint64_t cargv;
|
uint64_t cargv;
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
cargv = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
cargv = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||||
sprintf(obuf, "0x%016lx: argv[%d] = 0x%016lx\n",
|
sprintf(obuf, "0x%016lx: argv[%d] = 0x%016lx\n",
|
||||||
sp, argCount++, cargv);
|
sp, argCount++, cargv);
|
||||||
if(cargv)
|
if (cargv)
|
||||||
if(highestInfo < cargv)
|
if (highestInfo < cargv)
|
||||||
highestInfo = cargv;
|
highestInfo = cargv;
|
||||||
os << obuf;
|
os << obuf;
|
||||||
sp += 8;
|
sp += 8;
|
||||||
|
@ -328,8 +320,7 @@ ostream & AMD64TraceChild::outputStartState(ostream & os)
|
||||||
//Output the envp pointers
|
//Output the envp pointers
|
||||||
int envCount = 0;
|
int envCount = 0;
|
||||||
uint64_t cenvp;
|
uint64_t cenvp;
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
cenvp = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
cenvp = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||||
sprintf(obuf, "0x%016lx: envp[%d] = 0x%016lx\n",
|
sprintf(obuf, "0x%016lx: envp[%d] = 0x%016lx\n",
|
||||||
sp, envCount++, cenvp);
|
sp, envCount++, cenvp);
|
||||||
|
@ -337,8 +328,7 @@ ostream & AMD64TraceChild::outputStartState(ostream & os)
|
||||||
sp += 8;
|
sp += 8;
|
||||||
} while(cenvp);
|
} while(cenvp);
|
||||||
uint64_t auxType, auxVal;
|
uint64_t auxType, auxVal;
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
auxType = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
auxType = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||||
sp += 8;
|
sp += 8;
|
||||||
auxVal = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
auxVal = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||||
|
@ -352,16 +342,13 @@ ostream & AMD64TraceChild::outputStartState(ostream & os)
|
||||||
uint64_t buf;
|
uint64_t buf;
|
||||||
uint64_t currentStart = sp;
|
uint64_t currentStart = sp;
|
||||||
bool clearedInitialPadding = false;
|
bool clearedInitialPadding = false;
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
buf = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
buf = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||||
char * cbuf = (char *)&buf;
|
char * cbuf = (char *)&buf;
|
||||||
for(int x = 0; x < sizeof(uint64_t); x++)
|
for (int x = 0; x < sizeof(uint64_t); x++) {
|
||||||
{
|
if (cbuf[x])
|
||||||
if(cbuf[x])
|
|
||||||
current += cbuf[x];
|
current += cbuf[x];
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
sprintf(obuf, "0x%016lx: \"%s\"\n",
|
sprintf(obuf, "0x%016lx: \"%s\"\n",
|
||||||
currentStart, current.c_str());
|
currentStart, current.c_str());
|
||||||
os << obuf;
|
os << obuf;
|
||||||
|
@ -371,23 +358,21 @@ ostream & AMD64TraceChild::outputStartState(ostream & os)
|
||||||
}
|
}
|
||||||
sp += 8;
|
sp += 8;
|
||||||
clearedInitialPadding = clearedInitialPadding || buf != 0;
|
clearedInitialPadding = clearedInitialPadding || buf != 0;
|
||||||
} while(!clearedInitialPadding || buf != 0 || sp <= highestInfo);
|
} while (!clearedInitialPadding || buf != 0 || sp <= highestInfo);
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t AMD64TraceChild::findSyscall()
|
uint64_t
|
||||||
|
AMD64TraceChild::findSyscall()
|
||||||
{
|
{
|
||||||
uint64_t rip = getPC();
|
uint64_t rip = getPC();
|
||||||
bool foundOpcode = false;
|
bool foundOpcode = false;
|
||||||
bool twoByteOpcode = false;
|
bool twoByteOpcode = false;
|
||||||
for(;;)
|
for (;;) {
|
||||||
{
|
|
||||||
uint64_t buf = ptrace(PTRACE_PEEKDATA, pid, rip, 0);
|
uint64_t buf = ptrace(PTRACE_PEEKDATA, pid, rip, 0);
|
||||||
for(int i = 0; i < sizeof(uint64_t); i++)
|
for (int i = 0; i < sizeof(uint64_t); i++) {
|
||||||
{
|
|
||||||
unsigned char byte = buf & 0xFF;
|
unsigned char byte = buf & 0xFF;
|
||||||
if(!foundOpcode)
|
if (!foundOpcode) {
|
||||||
{
|
|
||||||
if(!(byte == 0x66 || //operand override
|
if(!(byte == 0x66 || //operand override
|
||||||
byte == 0x67 || //address override
|
byte == 0x67 || //address override
|
||||||
byte == 0x2E || //cs
|
byte == 0x2E || //cs
|
||||||
|
@ -400,28 +385,24 @@ uint64_t AMD64TraceChild::findSyscall()
|
||||||
byte == 0xF2 || //repe
|
byte == 0xF2 || //repe
|
||||||
byte == 0xF3 || //repne
|
byte == 0xF3 || //repne
|
||||||
(byte >= 0x40 && byte <= 0x4F) // REX
|
(byte >= 0x40 && byte <= 0x4F) // REX
|
||||||
))
|
)) {
|
||||||
{
|
|
||||||
foundOpcode = true;
|
foundOpcode = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(foundOpcode)
|
if (foundOpcode) {
|
||||||
{
|
if (twoByteOpcode) {
|
||||||
if(twoByteOpcode)
|
|
||||||
{
|
|
||||||
//SYSCALL or SYSENTER
|
//SYSCALL or SYSENTER
|
||||||
if(byte == 0x05 || byte == 0x34)
|
if (byte == 0x05 || byte == 0x34)
|
||||||
return rip + 1;
|
return rip + 1;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(!twoByteOpcode)
|
if (!twoByteOpcode) {
|
||||||
{
|
if (byte == 0xCC) // INT3
|
||||||
if(byte == 0xCC) // INT3
|
|
||||||
return rip + 1;
|
return rip + 1;
|
||||||
else if(byte == 0xCD) // INT with byte immediate
|
else if (byte == 0xCD) // INT with byte immediate
|
||||||
return rip + 2;
|
return rip + 2;
|
||||||
else if(byte == 0x0F) // two byte opcode prefix
|
else if (byte == 0x0F) // two byte opcode prefix
|
||||||
twoByteOpcode = true;
|
twoByteOpcode = true;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -433,11 +414,11 @@ uint64_t AMD64TraceChild::findSyscall()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AMD64TraceChild::step()
|
bool
|
||||||
|
AMD64TraceChild::step()
|
||||||
{
|
{
|
||||||
uint64_t ripAfterSyscall = findSyscall();
|
uint64_t ripAfterSyscall = findSyscall();
|
||||||
if(ripAfterSyscall)
|
if (ripAfterSyscall) {
|
||||||
{
|
|
||||||
//Get the original contents of memory
|
//Get the original contents of memory
|
||||||
uint64_t buf = ptrace(PTRACE_PEEKDATA, pid, ripAfterSyscall, 0);
|
uint64_t buf = ptrace(PTRACE_PEEKDATA, pid, ripAfterSyscall, 0);
|
||||||
//Patch the first two bytes of the memory immediately after this with
|
//Patch the first two bytes of the memory immediately after this with
|
||||||
|
@ -452,13 +433,10 @@ bool AMD64TraceChild::step()
|
||||||
ptraceSingleStep();
|
ptraceSingleStep();
|
||||||
//Put things back to the way they started
|
//Put things back to the way they started
|
||||||
ptrace(PTRACE_POKEDATA, pid, ripAfterSyscall, buf);
|
ptrace(PTRACE_POKEDATA, pid, ripAfterSyscall, buf);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
//Get all the way past repe and repne string instructions in one shot.
|
//Get all the way past repe and repne string instructions in one shot.
|
||||||
uint64_t newPC, origPC = getPC();
|
uint64_t newPC, origPC = getPC();
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
ptraceSingleStep();
|
ptraceSingleStep();
|
||||||
newPC = getPC();
|
newPC = getPC();
|
||||||
} while(newPC == origPC);
|
} while(newPC == origPC);
|
||||||
|
|
|
@ -108,18 +108,21 @@ class AMD64TraceChild : public TraceChild
|
||||||
|
|
||||||
bool sendState(int socket);
|
bool sendState(int socket);
|
||||||
|
|
||||||
int getNumRegs()
|
int
|
||||||
|
getNumRegs()
|
||||||
{
|
{
|
||||||
return numregs;
|
return numregs;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool diffSinceUpdate(int num)
|
bool
|
||||||
|
diffSinceUpdate(int num)
|
||||||
{
|
{
|
||||||
assert(num < numregs && num >= 0);
|
assert(num < numregs && num >= 0);
|
||||||
return regDiffSinceUpdate[num];
|
return regDiffSinceUpdate[num];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getRegName(int num)
|
std::string
|
||||||
|
getRegName(int num)
|
||||||
{
|
{
|
||||||
assert(num < numregs && num >= 0);
|
assert(num < numregs && num >= 0);
|
||||||
return regNames[num];
|
return regNames[num];
|
||||||
|
|
|
@ -68,7 +68,8 @@ ARMTraceChild::ARMTraceChild()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ARMTraceChild::sendState(int socket)
|
bool
|
||||||
|
ARMTraceChild::sendState(int socket)
|
||||||
{
|
{
|
||||||
uint32_t regVal = 0;
|
uint32_t regVal = 0;
|
||||||
uint32_t message[numregs + 1];
|
uint32_t message[numregs + 1];
|
||||||
|
@ -98,43 +99,48 @@ bool ARMTraceChild::sendState(int socket)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ARMTraceChild::getRegs(user_regs &myregs, int num)
|
uint32_t
|
||||||
|
ARMTraceChild::getRegs(user_regs &myregs, int num)
|
||||||
{
|
{
|
||||||
assert(num < numregs && num >= 0);
|
assert(num < numregs && num >= 0);
|
||||||
return myregs.uregs[num];
|
return myregs.uregs[num];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ARMTraceChild::update(int pid)
|
bool
|
||||||
|
ARMTraceChild::update(int pid)
|
||||||
{
|
{
|
||||||
oldregs = regs;
|
oldregs = regs;
|
||||||
if(ptrace(PTRACE_GETREGS, pid, 0, ®s) != 0)
|
if (ptrace(PTRACE_GETREGS, pid, 0, ®s) != 0) {
|
||||||
{
|
|
||||||
cerr << "update: " << strerror(errno) << endl;
|
cerr << "update: " << strerror(errno) << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned int x = 0; x < numregs; x++)
|
for (unsigned int x = 0; x < numregs; x++)
|
||||||
regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x));
|
regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t ARMTraceChild::getRegVal(int num)
|
int64_t
|
||||||
|
ARMTraceChild::getRegVal(int num)
|
||||||
{
|
{
|
||||||
return getRegs(regs, num);
|
return getRegs(regs, num);
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t ARMTraceChild::getOldRegVal(int num)
|
int64_t
|
||||||
|
ARMTraceChild::getOldRegVal(int num)
|
||||||
{
|
{
|
||||||
return getRegs(oldregs, num);
|
return getRegs(oldregs, num);
|
||||||
}
|
}
|
||||||
|
|
||||||
char * ARMTraceChild::printReg(int num)
|
char *
|
||||||
|
ARMTraceChild::printReg(int num)
|
||||||
{
|
{
|
||||||
sprintf(printBuffer, "0x%08X", (uint32_t)getRegVal(num));
|
sprintf(printBuffer, "0x%08X", (uint32_t)getRegVal(num));
|
||||||
return printBuffer;
|
return printBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
ostream & ARMTraceChild::outputStartState(ostream & os)
|
ostream &
|
||||||
|
ARMTraceChild::outputStartState(ostream & os)
|
||||||
{
|
{
|
||||||
uint32_t sp = getSP();
|
uint32_t sp = getSP();
|
||||||
uint32_t pc = getPC();
|
uint32_t pc = getPC();
|
||||||
|
@ -154,8 +160,7 @@ ostream & ARMTraceChild::outputStartState(ostream & os)
|
||||||
//Output argv pointers
|
//Output argv pointers
|
||||||
int argCount = 0;
|
int argCount = 0;
|
||||||
int32_t cargv;
|
int32_t cargv;
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
cargv = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
cargv = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||||
sprintf(obuf, "0x%08x: argv[%d] = 0x%08x\n",
|
sprintf(obuf, "0x%08x: argv[%d] = 0x%08x\n",
|
||||||
sp, argCount++, cargv);
|
sp, argCount++, cargv);
|
||||||
|
@ -169,8 +174,7 @@ ostream & ARMTraceChild::outputStartState(ostream & os)
|
||||||
//Output the envp pointers
|
//Output the envp pointers
|
||||||
int envCount = 0;
|
int envCount = 0;
|
||||||
uint32_t cenvp;
|
uint32_t cenvp;
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
cenvp = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
cenvp = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||||
sprintf(obuf, "0x%08x: envp[%d] = 0x%08x\n",
|
sprintf(obuf, "0x%08x: envp[%d] = 0x%08x\n",
|
||||||
sp, envCount++, cenvp);
|
sp, envCount++, cenvp);
|
||||||
|
@ -178,8 +182,7 @@ ostream & ARMTraceChild::outputStartState(ostream & os)
|
||||||
sp += 4;
|
sp += 4;
|
||||||
} while(cenvp);
|
} while(cenvp);
|
||||||
uint32_t auxType, auxVal;
|
uint32_t auxType, auxVal;
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
auxType = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
auxType = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||||
sp += 4;
|
sp += 4;
|
||||||
auxVal = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
auxVal = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||||
|
@ -193,16 +196,13 @@ ostream & ARMTraceChild::outputStartState(ostream & os)
|
||||||
uint32_t buf;
|
uint32_t buf;
|
||||||
uint32_t currentStart = sp;
|
uint32_t currentStart = sp;
|
||||||
bool clearedInitialPadding = false;
|
bool clearedInitialPadding = false;
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
buf = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
buf = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||||
char * cbuf = (char *)&buf;
|
char * cbuf = (char *)&buf;
|
||||||
for(int x = 0; x < sizeof(uint32_t); x++)
|
for (int x = 0; x < sizeof(uint32_t); x++) {
|
||||||
{
|
if (cbuf[x])
|
||||||
if(cbuf[x])
|
|
||||||
current += cbuf[x];
|
current += cbuf[x];
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
sprintf(obuf, "0x%08x: \"%s\"\n",
|
sprintf(obuf, "0x%08x: \"%s\"\n",
|
||||||
currentStart, current.c_str());
|
currentStart, current.c_str());
|
||||||
os << obuf;
|
os << obuf;
|
||||||
|
@ -216,7 +216,8 @@ ostream & ARMTraceChild::outputStartState(ostream & os)
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ARMTraceChild::step()
|
bool
|
||||||
|
ARMTraceChild::step()
|
||||||
{
|
{
|
||||||
const uint32_t bkpt_inst = 0xe7f001f0;
|
const uint32_t bkpt_inst = 0xe7f001f0;
|
||||||
|
|
||||||
|
@ -258,7 +259,8 @@ bool ARMTraceChild::step()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TraceChild * genTraceChild()
|
TraceChild *
|
||||||
|
genTraceChild()
|
||||||
{
|
{
|
||||||
return new ARMTraceChild;
|
return new ARMTraceChild;
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,18 +84,21 @@ class ARMTraceChild : public TraceChild
|
||||||
ARMTraceChild();
|
ARMTraceChild();
|
||||||
bool sendState(int socket);
|
bool sendState(int socket);
|
||||||
|
|
||||||
int getNumRegs()
|
int
|
||||||
|
getNumRegs()
|
||||||
{
|
{
|
||||||
return numregs;
|
return numregs;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool diffSinceUpdate(int num)
|
bool
|
||||||
|
diffSinceUpdate(int num)
|
||||||
{
|
{
|
||||||
assert(num < numregs && num >= 0);
|
assert(num < numregs && num >= 0);
|
||||||
return regDiffSinceUpdate[num];
|
return regDiffSinceUpdate[num];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getRegName(int num)
|
std::string
|
||||||
|
getRegName(int num)
|
||||||
{
|
{
|
||||||
assert(num < numregs && num >= 0);
|
assert(num < numregs && num >= 0);
|
||||||
return regNames[num];
|
return regNames[num];
|
||||||
|
@ -106,12 +109,14 @@ class ARMTraceChild : public TraceChild
|
||||||
|
|
||||||
bool step();
|
bool step();
|
||||||
|
|
||||||
uint64_t getPC()
|
uint64_t
|
||||||
|
getPC()
|
||||||
{
|
{
|
||||||
return getRegVal(PC);
|
return getRegVal(PC);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t getSP()
|
uint64_t
|
||||||
|
getSP()
|
||||||
{
|
{
|
||||||
return getRegVal(SP);
|
return getRegVal(SP);
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,11 +49,11 @@ char * I386TraceChild::regNames[numregs] = {
|
||||||
//PC
|
//PC
|
||||||
"eip"};
|
"eip"};
|
||||||
|
|
||||||
int64_t I386TraceChild::getRegs(user_regs_struct & myregs, int num)
|
int64_t
|
||||||
|
I386TraceChild::getRegs(user_regs_struct & myregs, int num)
|
||||||
{
|
{
|
||||||
assert(num < numregs && num >= 0);
|
assert(num < numregs && num >= 0);
|
||||||
switch(num)
|
switch (num) {
|
||||||
{
|
|
||||||
//GPRs
|
//GPRs
|
||||||
case EAX: return myregs.eax;
|
case EAX: return myregs.eax;
|
||||||
case EBX: return myregs.ebx;
|
case EBX: return myregs.ebx;
|
||||||
|
@ -80,41 +80,44 @@ int64_t I386TraceChild::getRegs(user_regs_struct & myregs, int num)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool I386TraceChild::update(int pid)
|
bool
|
||||||
|
I386TraceChild::update(int pid)
|
||||||
{
|
{
|
||||||
oldregs = regs;
|
oldregs = regs;
|
||||||
if(ptrace(PTRACE_GETREGS, pid, 0, ®s) != 0)
|
if (ptrace(PTRACE_GETREGS, pid, 0, ®s) != 0)
|
||||||
return false;
|
return false;
|
||||||
for(unsigned int x = 0; x < numregs; x++)
|
for (unsigned int x = 0; x < numregs; x++) {
|
||||||
{
|
regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x));
|
||||||
regDiffSinceUpdate[x] =
|
|
||||||
(getRegVal(x) != getOldRegVal(x));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
I386TraceChild::I386TraceChild()
|
I386TraceChild::I386TraceChild()
|
||||||
{
|
{
|
||||||
for(unsigned int x = 0; x < numregs; x++)
|
for (unsigned int x = 0; x < numregs; x++)
|
||||||
regDiffSinceUpdate[x] = false;
|
regDiffSinceUpdate[x] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t I386TraceChild::getRegVal(int num)
|
int64_t
|
||||||
|
I386TraceChild::getRegVal(int num)
|
||||||
{
|
{
|
||||||
return getRegs(regs, num);
|
return getRegs(regs, num);
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t I386TraceChild::getOldRegVal(int num)
|
int64_t
|
||||||
|
I386TraceChild::getOldRegVal(int num)
|
||||||
{
|
{
|
||||||
return getRegs(oldregs, num);
|
return getRegs(oldregs, num);
|
||||||
}
|
}
|
||||||
|
|
||||||
char * I386TraceChild::printReg(int num)
|
char *
|
||||||
|
I386TraceChild::printReg(int num)
|
||||||
{
|
{
|
||||||
sprintf(printBuffer, "0x%08X", getRegVal(num));
|
sprintf(printBuffer, "0x%08X", getRegVal(num));
|
||||||
return printBuffer;
|
return printBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
TraceChild * genTraceChild()
|
TraceChild *
|
||||||
|
genTraceChild()
|
||||||
{
|
{
|
||||||
return new I386TraceChild;
|
return new I386TraceChild;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
|
|
||||||
class I386TraceChild : public TraceChild
|
class I386TraceChild : public TraceChild
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum RegNum
|
enum RegNum
|
||||||
{
|
{
|
||||||
//GPRs
|
//GPRs
|
||||||
|
@ -56,7 +56,7 @@ public:
|
||||||
EIP,
|
EIP,
|
||||||
numregs
|
numregs
|
||||||
};
|
};
|
||||||
private:
|
private:
|
||||||
char printBuffer [256];
|
char printBuffer [256];
|
||||||
static char * regNames[numregs];
|
static char * regNames[numregs];
|
||||||
int64_t getRegs(user_regs_struct & myregs, int num);
|
int64_t getRegs(user_regs_struct & myregs, int num);
|
||||||
|
@ -64,25 +64,28 @@ private:
|
||||||
user_regs_struct oldregs;
|
user_regs_struct oldregs;
|
||||||
bool regDiffSinceUpdate[numregs];
|
bool regDiffSinceUpdate[numregs];
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool update(int pid);
|
bool update(int pid);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
I386TraceChild();
|
I386TraceChild();
|
||||||
|
|
||||||
int getNumRegs()
|
int
|
||||||
|
getNumRegs()
|
||||||
{
|
{
|
||||||
return numregs;
|
return numregs;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool diffSinceUpdate(int num)
|
bool
|
||||||
|
diffSinceUpdate(int num)
|
||||||
{
|
{
|
||||||
assert(num < numregs && num >= 0);
|
assert(num < numregs && num >= 0);
|
||||||
return regDiffSinceUpdate[num];
|
return regDiffSinceUpdate[num];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getRegName(int num)
|
std::string
|
||||||
|
getRegName(int num)
|
||||||
{
|
{
|
||||||
assert(num < numregs && num >= 0);
|
assert(num < numregs && num >= 0);
|
||||||
return regNames[num];
|
return regNames[num];
|
||||||
|
@ -92,7 +95,8 @@ public:
|
||||||
int64_t getOldRegVal(int num);
|
int64_t getOldRegVal(int num);
|
||||||
uint64_t getPC() {return getRegVal(EIP);}
|
uint64_t getPC() {return getRegVal(EIP);}
|
||||||
uint64_t getSP() {return getRegVal(ESP);}
|
uint64_t getSP() {return getRegVal(ESP);}
|
||||||
std::ostream & outputStartState(std::ostream & output)
|
std::ostream &
|
||||||
|
outputStartState(std::ostream & output)
|
||||||
{
|
{
|
||||||
output << "Printing i386 initial state not yet implemented"
|
output << "Printing i386 initial state not yet implemented"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
|
@ -54,36 +54,32 @@ string SparcTraceChild::regNames[numregs] = {
|
||||||
//Miscelaneous
|
//Miscelaneous
|
||||||
"fsr", "fprs", "pc", "npc", "y", "cwp", "pstate", "asi", "ccr"};
|
"fsr", "fprs", "pc", "npc", "y", "cwp", "pstate", "asi", "ccr"};
|
||||||
|
|
||||||
bool SparcTraceChild::sendState(int socket)
|
bool
|
||||||
|
SparcTraceChild::sendState(int socket)
|
||||||
{
|
{
|
||||||
uint64_t regVal = 0;
|
uint64_t regVal = 0;
|
||||||
for(int x = 0; x <= I7; x++)
|
for (int x = 0; x <= I7; x++) {
|
||||||
{
|
|
||||||
regVal = getRegVal(x);
|
regVal = getRegVal(x);
|
||||||
if(write(socket, ®Val, sizeof(regVal)) == -1)
|
if (write(socket, ®Val, sizeof(regVal)) == -1) {
|
||||||
{
|
|
||||||
cerr << "Write failed! " << strerror(errno) << endl;
|
cerr << "Write failed! " << strerror(errno) << endl;
|
||||||
tracing = false;
|
tracing = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
regVal = getRegVal(PC);
|
regVal = getRegVal(PC);
|
||||||
if(write(socket, ®Val, sizeof(regVal)) == -1)
|
if (write(socket, ®Val, sizeof(regVal)) == -1) {
|
||||||
{
|
|
||||||
cerr << "Write failed! " << strerror(errno) << endl;
|
cerr << "Write failed! " << strerror(errno) << endl;
|
||||||
tracing = false;
|
tracing = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
regVal = getRegVal(NPC);
|
regVal = getRegVal(NPC);
|
||||||
if(write(socket, ®Val, sizeof(regVal)) == -1)
|
if (write(socket, ®Val, sizeof(regVal)) == -1) {
|
||||||
{
|
|
||||||
cerr << "Write failed! " << strerror(errno) << endl;
|
cerr << "Write failed! " << strerror(errno) << endl;
|
||||||
tracing = false;
|
tracing = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
regVal = getRegVal(CCR);
|
regVal = getRegVal(CCR);
|
||||||
if(write(socket, ®Val, sizeof(regVal)) == -1)
|
if (write(socket, ®Val, sizeof(regVal)) == -1) {
|
||||||
{
|
|
||||||
cerr << "Write failed! " << strerror(errno) << endl;
|
cerr << "Write failed! " << strerror(errno) << endl;
|
||||||
tracing = false;
|
tracing = false;
|
||||||
return false;
|
return false;
|
||||||
|
@ -91,12 +87,12 @@ bool SparcTraceChild::sendState(int socket)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t getRegs(regs & myregs, fpu & myfpu,
|
int64_t
|
||||||
uint64_t * locals, uint64_t * inputs, int num)
|
getRegs(regs & myregs, fpu & myfpu, uint64_t * locals,
|
||||||
|
uint64_t * inputs, int num)
|
||||||
{
|
{
|
||||||
assert(num < SparcTraceChild::numregs && num >= 0);
|
assert(num < SparcTraceChild::numregs && num >= 0);
|
||||||
switch(num)
|
switch (num) {
|
||||||
{
|
|
||||||
//Global registers
|
//Global registers
|
||||||
case SparcTraceChild::G0: return 0;
|
case SparcTraceChild::G0: return 0;
|
||||||
case SparcTraceChild::G1: return myregs.r_g1;
|
case SparcTraceChild::G1: return myregs.r_g1;
|
||||||
|
@ -186,45 +182,45 @@ int64_t getRegs(regs & myregs, fpu & myfpu,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SparcTraceChild::update(int pid)
|
bool
|
||||||
|
SparcTraceChild::update(int pid)
|
||||||
{
|
{
|
||||||
memcpy(&oldregs, &theregs, sizeof(regs));
|
memcpy(&oldregs, &theregs, sizeof(regs));
|
||||||
memcpy(&oldfpregs, &thefpregs, sizeof(fpu));
|
memcpy(&oldfpregs, &thefpregs, sizeof(fpu));
|
||||||
memcpy(oldLocals, locals, 8 * sizeof(uint64_t));
|
memcpy(oldLocals, locals, 8 * sizeof(uint64_t));
|
||||||
memcpy(oldInputs, inputs, 8 * sizeof(uint64_t));
|
memcpy(oldInputs, inputs, 8 * sizeof(uint64_t));
|
||||||
if(ptrace(PTRACE_GETREGS, pid, &theregs, 0) != 0)
|
if (ptrace(PTRACE_GETREGS, pid, &theregs, 0) != 0) {
|
||||||
{
|
|
||||||
cerr << "Update failed" << endl;
|
cerr << "Update failed" << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
uint64_t stackPointer = getSP();
|
uint64_t stackPointer = getSP();
|
||||||
uint64_t stackBias = 2047;
|
uint64_t stackBias = 2047;
|
||||||
bool v9 = stackPointer % 2;
|
bool v9 = stackPointer % 2;
|
||||||
for(unsigned int x = 0; x < 8; x++)
|
for (unsigned int x = 0; x < 8; x++) {
|
||||||
{
|
|
||||||
uint64_t localAddr = stackPointer +
|
uint64_t localAddr = stackPointer +
|
||||||
(v9 ? (stackBias + x * 8) : (x * 4));
|
(v9 ? (stackBias + x * 8) : (x * 4));
|
||||||
locals[x] = ptrace(PTRACE_PEEKTEXT, pid, localAddr, 0);
|
locals[x] = ptrace(PTRACE_PEEKTEXT, pid, localAddr, 0);
|
||||||
if(!v9) locals[x] >>= 32;
|
if (!v9) locals[x] >>= 32;
|
||||||
uint64_t inputAddr = stackPointer +
|
uint64_t inputAddr = stackPointer +
|
||||||
(v9 ? (stackBias + x * 8 + (8 * 8)) : (x * 4 + 8 * 4));
|
(v9 ? (stackBias + x * 8 + (8 * 8)) : (x * 4 + 8 * 4));
|
||||||
inputs[x] = ptrace(PTRACE_PEEKTEXT, pid, inputAddr, 0);
|
inputs[x] = ptrace(PTRACE_PEEKTEXT, pid, inputAddr, 0);
|
||||||
if(!v9) inputs[x] >>= 32;
|
if (!v9) inputs[x] >>= 32;
|
||||||
}
|
}
|
||||||
if(ptrace(PTRACE_GETFPREGS, pid, &thefpregs, 0) != 0)
|
if (ptrace(PTRACE_GETFPREGS, pid, &thefpregs, 0) != 0)
|
||||||
return false;
|
return false;
|
||||||
for(unsigned int x = 0; x < numregs; x++)
|
for (unsigned int x = 0; x < numregs; x++)
|
||||||
regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x));
|
regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
SparcTraceChild::SparcTraceChild()
|
SparcTraceChild::SparcTraceChild()
|
||||||
{
|
{
|
||||||
for(unsigned int x = 0; x < numregs; x++)
|
for (unsigned int x = 0; x < numregs; x++)
|
||||||
regDiffSinceUpdate[x] = false;
|
regDiffSinceUpdate[x] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SparcTraceChild::getTargets(uint32_t inst, uint64_t pc, uint64_t npc,
|
int
|
||||||
|
SparcTraceChild::getTargets(uint32_t inst, uint64_t pc, uint64_t npc,
|
||||||
uint64_t &target1, uint64_t &target2)
|
uint64_t &target1, uint64_t &target2)
|
||||||
{
|
{
|
||||||
//We can identify the instruction categories we care about using the top
|
//We can identify the instruction categories we care about using the top
|
||||||
|
@ -245,28 +241,21 @@ int SparcTraceChild::getTargets(uint32_t inst, uint64_t pc, uint64_t npc,
|
||||||
bool bcc = (cond & 0x7) &&
|
bool bcc = (cond & 0x7) &&
|
||||||
(sig == 0x1 || sig == 0x2 || sig == 0x3 || sig == 0x5 || sig == 0x6);
|
(sig == 0x1 || sig == 0x2 || sig == 0x3 || sig == 0x5 || sig == 0x6);
|
||||||
|
|
||||||
if(annul)
|
if (annul) {
|
||||||
{
|
if (bcc) {
|
||||||
if(bcc)
|
|
||||||
{
|
|
||||||
target1 = npc;
|
target1 = npc;
|
||||||
target2 = npc + 4;
|
target2 = npc + 4;
|
||||||
return 2;
|
return 2;
|
||||||
}
|
} else if(ba) {
|
||||||
else if(ba)
|
|
||||||
{
|
|
||||||
//This branches immediately to the effective address of the branch
|
//This branches immediately to the effective address of the branch
|
||||||
//which we'll have to calculate.
|
//which we'll have to calculate.
|
||||||
uint64_t disp = 0;
|
uint64_t disp = 0;
|
||||||
int64_t extender = 0;
|
int64_t extender = 0;
|
||||||
//Figure out how big the displacement field is, and grab the bits
|
//Figure out how big the displacement field is, and grab the bits
|
||||||
if(sig == 0x1 || sig == 0x5)
|
if (sig == 0x1 || sig == 0x5) {
|
||||||
{
|
|
||||||
disp = inst & ((1 << 19) - 1);
|
disp = inst & ((1 << 19) - 1);
|
||||||
extender = 1 << 18;
|
extender = 1 << 18;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
disp = inst & ((1 << 22) - 1);
|
disp = inst & ((1 << 22) - 1);
|
||||||
extender = 1 << 21;
|
extender = 1 << 21;
|
||||||
}
|
}
|
||||||
|
@ -276,21 +265,19 @@ int SparcTraceChild::getTargets(uint32_t inst, uint64_t pc, uint64_t npc,
|
||||||
//smart enough to turn this into a shift.
|
//smart enough to turn this into a shift.
|
||||||
disp *= 4;
|
disp *= 4;
|
||||||
target1 = pc + disp;
|
target1 = pc + disp;
|
||||||
}
|
} else if(bn)
|
||||||
else if(bn)
|
|
||||||
target1 = npc + 4;
|
target1 = npc + 4;
|
||||||
else
|
else
|
||||||
target1 = npc;
|
target1 = npc;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
target1 = npc;
|
target1 = npc;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SparcTraceChild::step()
|
bool
|
||||||
|
SparcTraceChild::step()
|
||||||
{
|
{
|
||||||
//Increment the count of the number of instructions executed
|
//Increment the count of the number of instructions executed
|
||||||
instructions++;
|
instructions++;
|
||||||
|
@ -345,18 +332,17 @@ bool SparcTraceChild::step()
|
||||||
uint64_t newBp1 = origBp1;
|
uint64_t newBp1 = origBp1;
|
||||||
newBp1 &= unalignedBp1 ? highMask : lowMask;
|
newBp1 &= unalignedBp1 ? highMask : lowMask;
|
||||||
newBp1 |= unalignedBp1 ? lowBreakInst : highBreakInst;
|
newBp1 |= unalignedBp1 ? lowBreakInst : highBreakInst;
|
||||||
if(ptrace(PTRACE_POKETEXT, pid, alignedBp1, newBp1) != 0)
|
if (ptrace(PTRACE_POKETEXT, pid, alignedBp1, newBp1) != 0)
|
||||||
cerr << "Poke failed" << endl;
|
cerr << "Poke failed" << endl;
|
||||||
/*
|
/*
|
||||||
* Set the second breakpoint if necessary
|
* Set the second breakpoint if necessary
|
||||||
*/
|
*/
|
||||||
if(numTargets == 2)
|
if (numTargets == 2) {
|
||||||
{
|
|
||||||
origBp2 = ptrace(PTRACE_PEEKTEXT, pid, alignedBp2, 0);
|
origBp2 = ptrace(PTRACE_PEEKTEXT, pid, alignedBp2, 0);
|
||||||
uint64_t newBp2 = origBp2;
|
uint64_t newBp2 = origBp2;
|
||||||
newBp2 &= unalignedBp2 ? highMask : lowMask;
|
newBp2 &= unalignedBp2 ? highMask : lowMask;
|
||||||
newBp2 |= unalignedBp2 ? lowBreakInst : highBreakInst;
|
newBp2 |= unalignedBp2 ? lowBreakInst : highBreakInst;
|
||||||
if(ptrace(PTRACE_POKETEXT, pid, alignedBp2, newBp2) != 0)
|
if (ptrace(PTRACE_POKETEXT, pid, alignedBp2, newBp2) != 0)
|
||||||
cerr << "Poke failed" << endl;
|
cerr << "Poke failed" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,7 +352,7 @@ bool SparcTraceChild::step()
|
||||||
//Note that the "addr" parameter is supposed to be ignored, but in at
|
//Note that the "addr" parameter is supposed to be ignored, but in at
|
||||||
//least one version of the kernel, it must be 1 or it will set what
|
//least one version of the kernel, it must be 1 or it will set what
|
||||||
//pc to continue from
|
//pc to continue from
|
||||||
if(ptrace(PTRACE_CONT, pid, 1, 0) != 0)
|
if (ptrace(PTRACE_CONT, pid, 1, 0) != 0)
|
||||||
cerr << "Cont failed" << endl;
|
cerr << "Cont failed" << endl;
|
||||||
doWait();
|
doWait();
|
||||||
|
|
||||||
|
@ -379,42 +365,42 @@ bool SparcTraceChild::step()
|
||||||
* Put back the original contents of the childs address space in the
|
* Put back the original contents of the childs address space in the
|
||||||
* reverse order.
|
* reverse order.
|
||||||
*/
|
*/
|
||||||
if(numTargets == 2)
|
if (numTargets == 2) {
|
||||||
{
|
if (ptrace(PTRACE_POKETEXT, pid, alignedBp2, origBp2) != 0)
|
||||||
if(ptrace(PTRACE_POKETEXT, pid, alignedBp2, origBp2) != 0)
|
|
||||||
cerr << "Poke failed" << endl;
|
cerr << "Poke failed" << endl;
|
||||||
}
|
}
|
||||||
if(ptrace(PTRACE_POKETEXT, pid, alignedBp1, origBp1) != 0)
|
if (ptrace(PTRACE_POKETEXT, pid, alignedBp1, origBp1) != 0)
|
||||||
cerr << "Poke failed" << endl;
|
cerr << "Poke failed" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t SparcTraceChild::getRegVal(int num)
|
int64_t
|
||||||
|
SparcTraceChild::getRegVal(int num)
|
||||||
{
|
{
|
||||||
return getRegs(theregs, thefpregs, locals, inputs, num);
|
return getRegs(theregs, thefpregs, locals, inputs, num);
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t SparcTraceChild::getOldRegVal(int num)
|
int64_t
|
||||||
|
SparcTraceChild::getOldRegVal(int num)
|
||||||
{
|
{
|
||||||
return getRegs(oldregs, oldfpregs, oldLocals, oldInputs, num);
|
return getRegs(oldregs, oldfpregs, oldLocals, oldInputs, num);
|
||||||
}
|
}
|
||||||
|
|
||||||
char * SparcTraceChild::printReg(int num)
|
char *
|
||||||
|
SparcTraceChild::printReg(int num)
|
||||||
{
|
{
|
||||||
sprintf(printBuffer, "0x%016llx", getRegVal(num));
|
sprintf(printBuffer, "0x%016llx", getRegVal(num));
|
||||||
return printBuffer;
|
return printBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
ostream & SparcTraceChild::outputStartState(ostream & os)
|
ostream &
|
||||||
|
SparcTraceChild::outputStartState(ostream & os)
|
||||||
{
|
{
|
||||||
bool v8 = false;
|
bool v8 = false;
|
||||||
uint64_t sp = getSP();
|
uint64_t sp = getSP();
|
||||||
if(sp % 2)
|
if (sp % 2) {
|
||||||
{
|
|
||||||
os << "Detected a 64 bit executable.\n";
|
os << "Detected a 64 bit executable.\n";
|
||||||
v8 = false;
|
v8 = false;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
os << "Detected a 32 bit executable.\n";
|
os << "Detected a 32 bit executable.\n";
|
||||||
v8 = true;
|
v8 = true;
|
||||||
}
|
}
|
||||||
|
@ -424,16 +410,14 @@ ostream & SparcTraceChild::outputStartState(ostream & os)
|
||||||
os << obuf;
|
os << obuf;
|
||||||
sprintf(obuf, "Initial program counter = 0x%016llx\n", pc);
|
sprintf(obuf, "Initial program counter = 0x%016llx\n", pc);
|
||||||
os << obuf;
|
os << obuf;
|
||||||
if(!v8)
|
if (!v8) {
|
||||||
{
|
|
||||||
//Take out the stack bias
|
//Take out the stack bias
|
||||||
sp += 2047;
|
sp += 2047;
|
||||||
}
|
}
|
||||||
//Output the window save area
|
//Output the window save area
|
||||||
for(unsigned int x = 0; x < 16; x++)
|
for (unsigned int x = 0; x < 16; x++) {
|
||||||
{
|
|
||||||
uint64_t regspot = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
uint64_t regspot = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||||
if(v8) regspot = regspot >> 32;
|
if (v8) regspot = regspot >> 32;
|
||||||
sprintf(obuf, "0x%016llx: Window save %d = 0x%016llx\n",
|
sprintf(obuf, "0x%016llx: Window save %d = 0x%016llx\n",
|
||||||
sp, x+1, regspot);
|
sp, x+1, regspot);
|
||||||
os << obuf;
|
os << obuf;
|
||||||
|
@ -441,17 +425,16 @@ ostream & SparcTraceChild::outputStartState(ostream & os)
|
||||||
}
|
}
|
||||||
//Output the argument count
|
//Output the argument count
|
||||||
uint64_t cargc = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
uint64_t cargc = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||||
if(v8) cargc = cargc >> 32;
|
if (v8) cargc = cargc >> 32;
|
||||||
sprintf(obuf, "0x%016llx: Argc = 0x%016llx\n", sp, cargc);
|
sprintf(obuf, "0x%016llx: Argc = 0x%016llx\n", sp, cargc);
|
||||||
os << obuf;
|
os << obuf;
|
||||||
sp += v8 ? 4 : 8;
|
sp += v8 ? 4 : 8;
|
||||||
//Output argv pointers
|
//Output argv pointers
|
||||||
int argCount = 0;
|
int argCount = 0;
|
||||||
uint64_t cargv;
|
uint64_t cargv;
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
cargv = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
cargv = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||||
if(v8) cargv = cargv >> 32;
|
if (v8) cargv = cargv >> 32;
|
||||||
sprintf(obuf, "0x%016llx: argv[%d] = 0x%016llx\n",
|
sprintf(obuf, "0x%016llx: argv[%d] = 0x%016llx\n",
|
||||||
sp, argCount++, cargv);
|
sp, argCount++, cargv);
|
||||||
os << obuf;
|
os << obuf;
|
||||||
|
@ -460,43 +443,38 @@ ostream & SparcTraceChild::outputStartState(ostream & os)
|
||||||
//Output the envp pointers
|
//Output the envp pointers
|
||||||
int envCount = 0;
|
int envCount = 0;
|
||||||
uint64_t cenvp;
|
uint64_t cenvp;
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
cenvp = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
cenvp = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||||
if(v8) cenvp = cenvp >> 32;
|
if (v8) cenvp = cenvp >> 32;
|
||||||
sprintf(obuf, "0x%016llx: envp[%d] = 0x%016llx\n",
|
sprintf(obuf, "0x%016llx: envp[%d] = 0x%016llx\n",
|
||||||
sp, envCount++, cenvp);
|
sp, envCount++, cenvp);
|
||||||
os << obuf;
|
os << obuf;
|
||||||
sp += v8 ? 4 : 8;
|
sp += v8 ? 4 : 8;
|
||||||
} while(cenvp);
|
} while (cenvp);
|
||||||
uint64_t auxType, auxVal;
|
uint64_t auxType, auxVal;
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
auxType = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
auxType = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||||
if(v8) auxType = auxType >> 32;
|
if (v8) auxType = auxType >> 32;
|
||||||
sp += (v8 ? 4 : 8);
|
sp += (v8 ? 4 : 8);
|
||||||
auxVal = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
auxVal = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||||
if(v8) auxVal = auxVal >> 32;
|
if (v8) auxVal = auxVal >> 32;
|
||||||
sp += (v8 ? 4 : 8);
|
sp += (v8 ? 4 : 8);
|
||||||
sprintf(obuf, "0x%016llx: Auxiliary vector = {0x%016llx, 0x%016llx}\n",
|
sprintf(obuf, "0x%016llx: Auxiliary vector = {0x%016llx, 0x%016llx}\n",
|
||||||
sp - 8, auxType, auxVal);
|
sp - 8, auxType, auxVal);
|
||||||
os << obuf;
|
os << obuf;
|
||||||
} while(auxType != 0 || auxVal != 0);
|
} while (auxType != 0 || auxVal != 0);
|
||||||
//Print out the argument strings, environment strings, and file name.
|
//Print out the argument strings, environment strings, and file name.
|
||||||
string current;
|
string current;
|
||||||
uint64_t buf;
|
uint64_t buf;
|
||||||
uint64_t currentStart = sp;
|
uint64_t currentStart = sp;
|
||||||
bool clearedInitialPadding = false;
|
bool clearedInitialPadding = false;
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
buf = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
buf = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||||
char * cbuf = (char *)&buf;
|
char * cbuf = (char *)&buf;
|
||||||
for(int x = 0; x < sizeof(uint32_t); x++)
|
for (int x = 0; x < sizeof(uint32_t); x++) {
|
||||||
{
|
if (cbuf[x])
|
||||||
if(cbuf[x])
|
|
||||||
current += cbuf[x];
|
current += cbuf[x];
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
sprintf(obuf, "0x%016llx: \"%s\"\n",
|
sprintf(obuf, "0x%016llx: \"%s\"\n",
|
||||||
currentStart, current.c_str());
|
currentStart, current.c_str());
|
||||||
os << obuf;
|
os << obuf;
|
||||||
|
@ -506,11 +484,12 @@ ostream & SparcTraceChild::outputStartState(ostream & os)
|
||||||
}
|
}
|
||||||
sp += (v8 ? 4 : 8);
|
sp += (v8 ? 4 : 8);
|
||||||
clearedInitialPadding = clearedInitialPadding || buf != 0;
|
clearedInitialPadding = clearedInitialPadding || buf != 0;
|
||||||
} while(!clearedInitialPadding || buf != 0);
|
} while (!clearedInitialPadding || buf != 0);
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
TraceChild * genTraceChild()
|
TraceChild *
|
||||||
|
genTraceChild()
|
||||||
{
|
{
|
||||||
return new SparcTraceChild;
|
return new SparcTraceChild;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ struct regs;
|
||||||
|
|
||||||
class SparcTraceChild : public TraceChild
|
class SparcTraceChild : public TraceChild
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum RegNum
|
enum RegNum
|
||||||
{
|
{
|
||||||
//Global registers
|
//Global registers
|
||||||
|
@ -65,7 +65,7 @@ public:
|
||||||
FSR, FPRS, PC, NPC, Y, CWP, PSTATE, ASI, CCR,
|
FSR, FPRS, PC, NPC, Y, CWP, PSTATE, ASI, CCR,
|
||||||
numregs
|
numregs
|
||||||
};
|
};
|
||||||
private:
|
private:
|
||||||
char printBuffer[256];
|
char printBuffer[256];
|
||||||
static std::string regNames[numregs];
|
static std::string regNames[numregs];
|
||||||
regs theregs;
|
regs theregs;
|
||||||
|
@ -84,26 +84,29 @@ private:
|
||||||
int getTargets(uint32_t inst, uint64_t pc, uint64_t npc,
|
int getTargets(uint32_t inst, uint64_t pc, uint64_t npc,
|
||||||
uint64_t &target1, uint64_t &target2);
|
uint64_t &target1, uint64_t &target2);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool update(int pid);
|
bool update(int pid);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SparcTraceChild();
|
SparcTraceChild();
|
||||||
|
|
||||||
bool sendState(int socket);
|
bool sendState(int socket);
|
||||||
|
|
||||||
int getNumRegs()
|
int
|
||||||
|
getNumRegs()
|
||||||
{
|
{
|
||||||
return numregs;
|
return numregs;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool diffSinceUpdate(int num)
|
bool
|
||||||
|
diffSinceUpdate(int num)
|
||||||
{
|
{
|
||||||
assert(num < numregs && num >= 0);
|
assert(num < numregs && num >= 0);
|
||||||
return regDiffSinceUpdate[num];
|
return regDiffSinceUpdate[num];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getRegName(int num)
|
std::string
|
||||||
|
getRegName(int num)
|
||||||
{
|
{
|
||||||
assert(num < numregs && num >= 0);
|
assert(num < numregs && num >= 0);
|
||||||
return regNames[num];
|
return regNames[num];
|
||||||
|
@ -115,12 +118,14 @@ public:
|
||||||
|
|
||||||
bool step();
|
bool step();
|
||||||
|
|
||||||
uint64_t getPC()
|
uint64_t
|
||||||
|
getPC()
|
||||||
{
|
{
|
||||||
return getRegVal(PC);
|
return getRegVal(PC);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t getSP()
|
uint64_t
|
||||||
|
getSP()
|
||||||
{
|
{
|
||||||
return getRegVal(O6);
|
return getRegVal(O6);
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,12 +42,13 @@ int findEndOfNestingPrinter(string, int);
|
||||||
PrinterType findSub(string, int &, int &);
|
PrinterType findSub(string, int &, int &);
|
||||||
|
|
||||||
//This is pretty easy. Just find the closing parenthesis.
|
//This is pretty easy. Just find the closing parenthesis.
|
||||||
int findEndOfRegPrinter(string config, int startPos)
|
int
|
||||||
|
findEndOfRegPrinter(string config, int startPos)
|
||||||
{
|
{
|
||||||
int pos = config.find(")", startPos);
|
int pos = config.find(")", startPos);
|
||||||
if(pos == string::npos)
|
if (pos == string::npos) {
|
||||||
{
|
cerr << "Couldn't find the closing " <<
|
||||||
cerr << "Couldn't find the closing parenthesis for a reg printer" << endl;
|
"parenthesis for a reg printer" << endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return pos;
|
return pos;
|
||||||
|
@ -55,32 +56,31 @@ int findEndOfRegPrinter(string config, int startPos)
|
||||||
|
|
||||||
//This is a little harder. We need to make sure we don't
|
//This is a little harder. We need to make sure we don't
|
||||||
//grab an ending parenthesis that belongs to the nesting printer.
|
//grab an ending parenthesis that belongs to the nesting printer.
|
||||||
int findEndOfNestingPrinter(string config, int startPos)
|
int
|
||||||
|
findEndOfNestingPrinter(string config, int startPos)
|
||||||
{
|
{
|
||||||
int length = config.length();
|
int length = config.length();
|
||||||
int pos = startPos;
|
int pos = startPos;
|
||||||
int endPos = length;
|
int endPos = length;
|
||||||
int parenPos = config.find(")", pos);
|
int parenPos = config.find(")", pos);
|
||||||
//If we didn't find an ending parenthesis at all, we're in trouble
|
//If we didn't find an ending parenthesis at all, we're in trouble
|
||||||
if(parenPos == string::npos)
|
if (parenPos == string::npos) {
|
||||||
{
|
cerr << "Couldn't find the closing " <<
|
||||||
cerr << "Couldn't find the closing parenthesis for a nesting printer on the first try" << endl;
|
"parenthesis for a nesting printer on the first try" << endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
//Keep pulling out embedded stuff until we can't any more
|
//Keep pulling out embedded stuff until we can't any more
|
||||||
//we need to make sure we aren't skipping over the parenthesis
|
//we need to make sure we aren't skipping over the parenthesis
|
||||||
//that ends -this- printer.
|
//that ends -this- printer.
|
||||||
PrinterType type = findSub(config, pos, endPos);
|
PrinterType type = findSub(config, pos, endPos);
|
||||||
if(type == PRINTER_ERROR)
|
if (type == PRINTER_ERROR)
|
||||||
return 0;
|
return 0;
|
||||||
while(type != PRINTER_NONE && endPos >= parenPos)
|
while (type != PRINTER_NONE && endPos >= parenPos) {
|
||||||
{
|
|
||||||
//Find the next closest ending parenthesis since we passed
|
//Find the next closest ending parenthesis since we passed
|
||||||
//up the last one
|
//up the last one
|
||||||
parenPos = config.find(")", endPos + 1);
|
parenPos = config.find(")", endPos + 1);
|
||||||
//If we didn't find one, we're in trouble
|
//If we didn't find one, we're in trouble
|
||||||
if(parenPos == string::npos)
|
if (parenPos == string::npos) {
|
||||||
{
|
|
||||||
cerr << "Couldn't find the closing parenthesis for a nested printer on later tries" << endl;
|
cerr << "Couldn't find the closing parenthesis for a nested printer on later tries" << endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@ int findEndOfNestingPrinter(string config, int startPos)
|
||||||
//Reset endPos so we search to the end of config
|
//Reset endPos so we search to the end of config
|
||||||
endPos = length;
|
endPos = length;
|
||||||
type = findSub(config, pos, endPos);
|
type = findSub(config, pos, endPos);
|
||||||
if(type == PRINTER_ERROR)
|
if (type == PRINTER_ERROR)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
//We ran out of embedded items, and we didn't pass up our last
|
//We ran out of embedded items, and we didn't pass up our last
|
||||||
|
@ -103,7 +103,8 @@ int findEndOfNestingPrinter(string config, int startPos)
|
||||||
//startPos and endPos are set to the beginning and end of the sub printer
|
//startPos and endPos are set to the beginning and end of the sub printer
|
||||||
//On entry, the search starts at index startPos and ends at either index
|
//On entry, the search starts at index startPos and ends at either index
|
||||||
//endPos or a closing parenthesis, whichever comes first
|
//endPos or a closing parenthesis, whichever comes first
|
||||||
PrinterType findSub(string config, int & startPos, int & endPos)
|
PrinterType
|
||||||
|
findSub(string config, int & startPos, int & endPos)
|
||||||
{
|
{
|
||||||
int length = config.length();
|
int length = config.length();
|
||||||
//Figure out where the different types of sub printers may start
|
//Figure out where the different types of sub printers may start
|
||||||
|
@ -111,28 +112,26 @@ PrinterType findSub(string config, int & startPos, int & endPos)
|
||||||
int nestingPos = config.find("~(", startPos);
|
int nestingPos = config.find("~(", startPos);
|
||||||
//If a type of printer wasn't found, say it was found too far away.
|
//If a type of printer wasn't found, say it was found too far away.
|
||||||
//This simplifies things later
|
//This simplifies things later
|
||||||
if(regPos == string::npos)
|
if (regPos == string::npos)
|
||||||
regPos = endPos;
|
regPos = endPos;
|
||||||
if(nestingPos == string::npos)
|
if (nestingPos == string::npos)
|
||||||
nestingPos = endPos;
|
nestingPos = endPos;
|
||||||
//If we find a closing paren, that marks the
|
//If we find a closing paren, that marks the
|
||||||
//end of the region we're searching.
|
//end of the region we're searching.
|
||||||
int closingPos = config.find(")", startPos);
|
int closingPos = config.find(")", startPos);
|
||||||
if(closingPos != string::npos &&
|
if (closingPos != string::npos &&
|
||||||
closingPos < regPos &&
|
closingPos < regPos &&
|
||||||
closingPos < nestingPos)
|
closingPos < nestingPos)
|
||||||
return PRINTER_NONE;
|
return PRINTER_NONE;
|
||||||
//If we didn't find anything close enough, say so.
|
//If we didn't find anything close enough, say so.
|
||||||
if(regPos >= endPos && nestingPos >= endPos)
|
if (regPos >= endPos && nestingPos >= endPos)
|
||||||
return PRINTER_NONE;
|
return PRINTER_NONE;
|
||||||
//At this point, we know that one of the options starts legally
|
//At this point, we know that one of the options starts legally
|
||||||
//We need to find which one is first and return that
|
//We need to find which one is first and return that
|
||||||
if(regPos < nestingPos)
|
if (regPos < nestingPos) {
|
||||||
{
|
|
||||||
int regEnd = findEndOfRegPrinter(config, regPos + 2);
|
int regEnd = findEndOfRegPrinter(config, regPos + 2);
|
||||||
//If we couldn't find the end...
|
//If we couldn't find the end...
|
||||||
if(!regEnd)
|
if (!regEnd) {
|
||||||
{
|
|
||||||
cerr << "Couldn't find the end of the reg printer" << endl;
|
cerr << "Couldn't find the end of the reg printer" << endl;
|
||||||
return PRINTER_ERROR;
|
return PRINTER_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -140,13 +139,10 @@ PrinterType findSub(string config, int & startPos, int & endPos)
|
||||||
startPos = regPos;
|
startPos = regPos;
|
||||||
endPos = regEnd;
|
endPos = regEnd;
|
||||||
return PRINTER_REG;
|
return PRINTER_REG;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
int nestingEnd = findEndOfNestingPrinter(config, nestingPos + 2);
|
int nestingEnd = findEndOfNestingPrinter(config, nestingPos + 2);
|
||||||
//If we couldn't find the end...
|
//If we couldn't find the end...
|
||||||
if(!nestingEnd)
|
if (!nestingEnd) {
|
||||||
{
|
|
||||||
cerr << "Couldn't find the end of the nesting printer" << endl;
|
cerr << "Couldn't find the end of the nesting printer" << endl;
|
||||||
return PRINTER_ERROR;
|
return PRINTER_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -159,7 +155,8 @@ PrinterType findSub(string config, int & startPos, int & endPos)
|
||||||
}
|
}
|
||||||
|
|
||||||
//Set up a nesting printer. This printer can contain sub printers
|
//Set up a nesting printer. This printer can contain sub printers
|
||||||
bool NestingPrinter::configure(string config)
|
bool
|
||||||
|
NestingPrinter::configure(string config)
|
||||||
{
|
{
|
||||||
//Clear out any old stuff
|
//Clear out any old stuff
|
||||||
constStrings.clear();
|
constStrings.clear();
|
||||||
|
@ -170,14 +167,13 @@ bool NestingPrinter::configure(string config)
|
||||||
int lastEndPos = -1;
|
int lastEndPos = -1;
|
||||||
//Try to find a sub printer
|
//Try to find a sub printer
|
||||||
PrinterType type = findSub(config, startPos, endPos);
|
PrinterType type = findSub(config, startPos, endPos);
|
||||||
if(type == PRINTER_ERROR)
|
if (type == PRINTER_ERROR) {
|
||||||
{
|
|
||||||
cerr << "Problem finding first sub printer" << endl;
|
cerr << "Problem finding first sub printer" << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
while(type != PRINTER_NONE)
|
while (type != PRINTER_NONE) {
|
||||||
{
|
string prefix = config.substr(lastEndPos + 1,
|
||||||
string prefix = config.substr(lastEndPos + 1, startPos - lastEndPos - 1);
|
startPos - lastEndPos - 1);
|
||||||
lastEndPos = endPos;
|
lastEndPos = endPos;
|
||||||
constStrings.push_back(prefix);
|
constStrings.push_back(prefix);
|
||||||
string subConfig, subString;
|
string subConfig, subString;
|
||||||
|
@ -185,15 +181,13 @@ bool NestingPrinter::configure(string config)
|
||||||
//Set up the register printer
|
//Set up the register printer
|
||||||
RegPrinter * regPrinter = new RegPrinter(child);
|
RegPrinter * regPrinter = new RegPrinter(child);
|
||||||
NestingPrinter * nestingPrinter = new NestingPrinter(child);
|
NestingPrinter * nestingPrinter = new NestingPrinter(child);
|
||||||
switch(type)
|
switch (type) {
|
||||||
{
|
|
||||||
//If we found a plain register printer
|
//If we found a plain register printer
|
||||||
case PRINTER_REG:
|
case PRINTER_REG:
|
||||||
numPrinters++;
|
numPrinters++;
|
||||||
//Get the register name
|
//Get the register name
|
||||||
subConfig = config.substr(startPos + 2, endPos - startPos - 2);
|
subConfig = config.substr(startPos + 2, endPos - startPos - 2);
|
||||||
if(!regPrinter->configure(subConfig))
|
if (!regPrinter->configure(subConfig)) {
|
||||||
{
|
|
||||||
delete regPrinter;
|
delete regPrinter;
|
||||||
cerr << "Error configuring reg printer" << endl;
|
cerr << "Error configuring reg printer" << endl;
|
||||||
return false;
|
return false;
|
||||||
|
@ -207,26 +201,23 @@ bool NestingPrinter::configure(string config)
|
||||||
subConfig = config.substr(startPos + 2, endPos - startPos - 2);
|
subConfig = config.substr(startPos + 2, endPos - startPos - 2);
|
||||||
lastCommaPos = string::npos;
|
lastCommaPos = string::npos;
|
||||||
commaPos = subConfig.find(",");
|
commaPos = subConfig.find(",");
|
||||||
if(commaPos == string::npos)
|
if (commaPos == string::npos)
|
||||||
return false;
|
return false;
|
||||||
childSwitchVar = child->getRegNum(subConfig.substr(0, commaPos));
|
childSwitchVar = child->getRegNum(subConfig.substr(0, commaPos));
|
||||||
if(childSwitchVar == -1)
|
if (childSwitchVar == -1) {
|
||||||
{
|
|
||||||
cerr << "Couldn't configure switching variable!" << endl;
|
cerr << "Couldn't configure switching variable!" << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//Eat up remaining arguments
|
//Eat up remaining arguments
|
||||||
while(commaPos != string::npos)
|
while (commaPos != string::npos) {
|
||||||
{
|
|
||||||
lastCommaPos = commaPos;
|
lastCommaPos = commaPos;
|
||||||
commaPos = subConfig.find(",", commaPos + 1);
|
commaPos = subConfig.find(",", commaPos + 1);
|
||||||
}
|
}
|
||||||
if(lastCommaPos != string::npos)
|
if (lastCommaPos != string::npos) {
|
||||||
{
|
subConfig = subConfig.substr(lastCommaPos + 1,
|
||||||
subConfig = subConfig.substr(lastCommaPos + 1, subConfig.length() - lastCommaPos - 1);
|
subConfig.length() - lastCommaPos - 1);
|
||||||
}
|
}
|
||||||
if(!nestingPrinter->configure(subConfig))
|
if (!nestingPrinter->configure(subConfig)) {
|
||||||
{
|
|
||||||
delete nestingPrinter;
|
delete nestingPrinter;
|
||||||
cerr << "Error configuring nesting printer" << endl;
|
cerr << "Error configuring nesting printer" << endl;
|
||||||
return false;
|
return false;
|
||||||
|
@ -242,8 +233,7 @@ bool NestingPrinter::configure(string config)
|
||||||
startPos = endPos + 1;
|
startPos = endPos + 1;
|
||||||
endPos = length;
|
endPos = length;
|
||||||
type = findSub(config, startPos, endPos);
|
type = findSub(config, startPos, endPos);
|
||||||
if(type == PRINTER_ERROR)
|
if (type == PRINTER_ERROR) {
|
||||||
{
|
|
||||||
cerr << "Unable to find subprinters on later tries" << endl;
|
cerr << "Unable to find subprinters on later tries" << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -254,12 +244,12 @@ bool NestingPrinter::configure(string config)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RegPrinter::configure(string config)
|
bool
|
||||||
|
RegPrinter::configure(string config)
|
||||||
{
|
{
|
||||||
//Figure out what our register number is based on the name we're given
|
//Figure out what our register number is based on the name we're given
|
||||||
int num = child->getRegNum(config);
|
int num = child->getRegNum(config);
|
||||||
if(num == -1)
|
if (num == -1) {
|
||||||
{
|
|
||||||
cerr << "Couldn't find register " << config << endl;
|
cerr << "Couldn't find register " << config << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -267,13 +257,12 @@ bool RegPrinter::configure(string config)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ostream & NestingPrinter::writeOut(ostream & os)
|
ostream &
|
||||||
|
NestingPrinter::writeOut(ostream & os)
|
||||||
{
|
{
|
||||||
if(switchVar == -1 || child->diffSinceUpdate(switchVar))
|
if (switchVar == -1 || child->diffSinceUpdate(switchVar)) {
|
||||||
{
|
|
||||||
int x;
|
int x;
|
||||||
for(x = 0; x < numPrinters; x++)
|
for (x = 0; x < numPrinters; x++) {
|
||||||
{
|
|
||||||
os << constStrings[x];
|
os << constStrings[x];
|
||||||
os << printers[x];
|
os << printers[x];
|
||||||
}
|
}
|
||||||
|
@ -282,7 +271,8 @@ ostream & NestingPrinter::writeOut(ostream & os)
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
ostream & RegPrinter::writeOut(ostream & os)
|
ostream &
|
||||||
|
RegPrinter::writeOut(ostream & os)
|
||||||
{
|
{
|
||||||
os << child->printReg(intRegNum);
|
os << child->printReg(intRegNum);
|
||||||
return os;
|
return os;
|
||||||
|
|
|
@ -79,12 +79,14 @@ class RegPrinter : public PrinterObject
|
||||||
PrinterObject(newChild), intRegNum(num)
|
PrinterObject(newChild), intRegNum(num)
|
||||||
{;}
|
{;}
|
||||||
|
|
||||||
void regNum(int num)
|
void
|
||||||
|
regNum(int num)
|
||||||
{
|
{
|
||||||
intRegNum = num;
|
intRegNum = num;
|
||||||
}
|
}
|
||||||
|
|
||||||
int regNum()
|
int
|
||||||
|
regNum()
|
||||||
{
|
{
|
||||||
return intRegNum;
|
return intRegNum;
|
||||||
}
|
}
|
||||||
|
@ -94,14 +96,14 @@ class RegPrinter : public PrinterObject
|
||||||
std::ostream & writeOut(std::ostream & os);
|
std::ostream & writeOut(std::ostream & os);
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline std::ostream & operator << (std::ostream & os,
|
static inline std::ostream &
|
||||||
PrinterObject & printer)
|
operator << (std::ostream & os, PrinterObject & printer)
|
||||||
{
|
{
|
||||||
return printer.writeOut(os);
|
return printer.writeOut(os);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline std::ostream & operator << (std::ostream & os,
|
static inline std::ostream &
|
||||||
PrinterPointer & printer)
|
operator << (std::ostream & os, PrinterPointer & printer)
|
||||||
{
|
{
|
||||||
return printer->writeOut(os);
|
return printer->writeOut(os);
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,18 +55,21 @@ class RefCountingPtr
|
||||||
protected:
|
protected:
|
||||||
T *data;
|
T *data;
|
||||||
|
|
||||||
void copy(T *d)
|
void
|
||||||
|
copy(T *d)
|
||||||
{
|
{
|
||||||
data = d;
|
data = d;
|
||||||
if (data)
|
if (data)
|
||||||
data->incref();
|
data->incref();
|
||||||
}
|
}
|
||||||
void del()
|
void
|
||||||
|
del()
|
||||||
{
|
{
|
||||||
if (data)
|
if (data)
|
||||||
data->decref();
|
data->decref();
|
||||||
}
|
}
|
||||||
void set(T *d)
|
void
|
||||||
|
set(T *d)
|
||||||
{
|
{
|
||||||
if (data == d)
|
if (data == d)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -36,16 +36,17 @@
|
||||||
|
|
||||||
class RegState
|
class RegState
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
virtual bool update(int pid) = 0;
|
virtual bool update(int pid) = 0;
|
||||||
public:
|
public:
|
||||||
virtual int getNumRegs() = 0;
|
virtual int getNumRegs() = 0;
|
||||||
virtual bool diffSinceUpdate(int num) = 0;
|
virtual bool diffSinceUpdate(int num) = 0;
|
||||||
virtual std::string getRegName(int num) = 0;
|
virtual std::string getRegName(int num) = 0;
|
||||||
virtual int getRegNum(std::string name)
|
virtual int
|
||||||
|
getRegNum(std::string name)
|
||||||
{
|
{
|
||||||
int numregs = getNumRegs();
|
int numregs = getNumRegs();
|
||||||
for(unsigned int x = 0; x < numregs; x++)
|
for (unsigned int x = 0; x < numregs; x++)
|
||||||
if(getRegName(x) == name)
|
if(getRegName(x) == name)
|
||||||
return x;
|
return x;
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -47,7 +47,8 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
void printUsage(const char * execName)
|
void
|
||||||
|
printUsage(const char * execName)
|
||||||
{
|
{
|
||||||
cout << execName << " <options> -- <command> <arguments>" << endl;
|
cout << execName << " <options> -- <command> <arguments>" << endl;
|
||||||
cout << "options:" << endl;
|
cout << "options:" << endl;
|
||||||
|
@ -58,7 +59,8 @@ void printUsage(const char * execName)
|
||||||
cout << " -nt don't print an instruction trace" << endl;
|
cout << " -nt don't print an instruction trace" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char * argv[], char * envp[])
|
int
|
||||||
|
main(int argc, char * argv[], char * envp[])
|
||||||
{
|
{
|
||||||
TraceChild * child = genTraceChild();
|
TraceChild * child = genTraceChild();
|
||||||
string args;
|
string args;
|
||||||
|
@ -73,87 +75,64 @@ int main(int argc, char * argv[], char * envp[])
|
||||||
printUsage(argv[0]);
|
printUsage(argv[0]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
for(int x = 1; x < argc; x++)
|
for (int x = 1; x < argc; x++) {
|
||||||
{
|
if (!strcmp(argv[x], "-h")) {
|
||||||
if(!strcmp(argv[x], "-h"))
|
|
||||||
{
|
|
||||||
printUsage(argv[0]);
|
printUsage(argv[0]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(!strcmp(argv[x], "--host"))
|
if (!strcmp(argv[x], "--host")) {
|
||||||
{
|
|
||||||
x++;
|
x++;
|
||||||
if(x >= argc)
|
if (x >= argc) {
|
||||||
{
|
|
||||||
cerr << "Incorrect usage.\n" << endl;
|
cerr << "Incorrect usage.\n" << endl;
|
||||||
printUsage(argv[0]);
|
printUsage(argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
host = argv[x];
|
host = argv[x];
|
||||||
}
|
} else if (!strcmp(argv[x], "-r")) {
|
||||||
else if(!strcmp(argv[x], "-r"))
|
|
||||||
{
|
|
||||||
cout << "Legal register names:" << endl;
|
cout << "Legal register names:" << endl;
|
||||||
int numRegs = child->getNumRegs();
|
int numRegs = child->getNumRegs();
|
||||||
for(unsigned int x = 0; x < numRegs; x++)
|
for (unsigned int x = 0; x < numRegs; x++)
|
||||||
{
|
|
||||||
cout << "\t" << child->getRegName(x) << endl;
|
cout << "\t" << child->getRegName(x) << endl;
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
} else if (!strcmp(argv[x], "-i")) {
|
||||||
else if(!strcmp(argv[x], "-i"))
|
|
||||||
{
|
|
||||||
printInitial = true;
|
printInitial = true;
|
||||||
}
|
} else if (!strcmp(argv[x], "-nt")) {
|
||||||
else if(!strcmp(argv[x], "-nt"))
|
|
||||||
{
|
|
||||||
printTrace = false;
|
printTrace = false;
|
||||||
}
|
} else if (!strcmp(argv[x], "--")) {
|
||||||
else if(!strcmp(argv[x], "--"))
|
|
||||||
{
|
|
||||||
x++;
|
x++;
|
||||||
if(x >= argc)
|
if (x >= argc) {
|
||||||
{
|
|
||||||
cerr << "Incorrect usage.\n" << endl;
|
cerr << "Incorrect usage.\n" << endl;
|
||||||
printUsage(argv[0]);
|
printUsage(argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
startProgramArgs = x;
|
startProgramArgs = x;
|
||||||
break;
|
break;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
cerr << "Incorrect usage.\n" << endl;
|
cerr << "Incorrect usage.\n" << endl;
|
||||||
printUsage(argv[0]);
|
printUsage(argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!child->startTracing(argv[startProgramArgs],
|
if (!child->startTracing(argv[startProgramArgs],
|
||||||
argv + startProgramArgs))
|
argv + startProgramArgs)) {
|
||||||
{
|
|
||||||
cerr << "Couldn't start target program" << endl;
|
cerr << "Couldn't start target program" << endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
child->step();
|
child->step();
|
||||||
if(printInitial)
|
if (printInitial)
|
||||||
{
|
|
||||||
child->outputStartState(cout);
|
child->outputStartState(cout);
|
||||||
}
|
if (printTrace) {
|
||||||
if(printTrace)
|
|
||||||
{
|
|
||||||
// Connect to m5
|
// Connect to m5
|
||||||
bool portSet = false;
|
bool portSet = false;
|
||||||
int port;
|
int port;
|
||||||
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if(sock < 0)
|
if (sock < 0) {
|
||||||
{
|
|
||||||
cerr << "Error opening socket! " << strerror(errno) << endl;
|
cerr << "Error opening socket! " << strerror(errno) << endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
struct hostent *server;
|
struct hostent *server;
|
||||||
server = gethostbyname(host.c_str());
|
server = gethostbyname(host.c_str());
|
||||||
if(!server)
|
if (!server) {
|
||||||
{
|
|
||||||
cerr << "Couldn't get host ip! " << strerror(errno) << endl;
|
cerr << "Couldn't get host ip! " << strerror(errno) << endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -164,20 +143,17 @@ int main(int argc, char * argv[], char * envp[])
|
||||||
(char *)&serv_addr.sin_addr.s_addr,
|
(char *)&serv_addr.sin_addr.s_addr,
|
||||||
server->h_length);
|
server->h_length);
|
||||||
serv_addr.sin_port = htons(8000);
|
serv_addr.sin_port = htons(8000);
|
||||||
if(connect(sock, (sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
|
if (connect(sock, (sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
|
||||||
{
|
|
||||||
cerr << "Couldn't connect to server! " << strerror(errno) << endl;
|
cerr << "Couldn't connect to server! " << strerror(errno) << endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
while(child->isTracing())
|
while (child->isTracing()) {
|
||||||
{
|
if (!child->sendState(sock))
|
||||||
if(!child->sendState(sock))
|
|
||||||
break;
|
break;
|
||||||
child->step();
|
child->step();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!child->stopTracing())
|
if (!child->stopTracing()) {
|
||||||
{
|
|
||||||
cerr << "Couldn't stop child" << endl;
|
cerr << "Couldn't stop child" << endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,44 +37,36 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
bool TraceChild::startTracing(const char * pathToFile, char * const argv[])
|
bool
|
||||||
|
TraceChild::startTracing(const char * pathToFile, char * const argv[])
|
||||||
{
|
{
|
||||||
instructions = 0;
|
instructions = 0;
|
||||||
pid = fork();
|
pid = fork();
|
||||||
if(pid == -1)
|
if (pid == -1) {
|
||||||
{
|
|
||||||
cout << "fork failed" << endl;
|
cout << "fork failed" << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
} else if (pid == 0) {
|
||||||
else if(pid == 0)
|
//We're the child. Get things ready and then exec the program to trace.
|
||||||
{
|
|
||||||
//We're the child. Get things ready and then exec the
|
|
||||||
//program to trace.
|
|
||||||
|
|
||||||
//Let our parent trace us
|
//Let our parent trace us
|
||||||
if(ptrace(PTRACE_TRACEME, 0, 0, 0) == -1)
|
if (ptrace(PTRACE_TRACEME, 0, 0, 0) == -1) {
|
||||||
{
|
cout << "Failure calling TRACEME\n" << strerror(errno) << endl;
|
||||||
cout << "Failure calling TRACEME\n";
|
|
||||||
cout << strerror(errno) << endl;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Set up an empty environment for the child...
|
//Set up an empty environment for the child... We would want to
|
||||||
//We would want to specify this somehow at some point
|
//specify this somehow at some point
|
||||||
char * env[] = {NULL};
|
char * env[] = {NULL};
|
||||||
|
|
||||||
//Start the program to trace
|
//Start the program to trace
|
||||||
execve(pathToFile, argv, env);
|
execve(pathToFile, argv, env);
|
||||||
|
|
||||||
//We should never get here, so this is an error!
|
//We should never get here, so this is an error!
|
||||||
cout << "Exec failed\n";
|
cout << "Exec failed\n" << strerror(errno) << endl;
|
||||||
cout << strerror(errno) << endl;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//From this point forward, we know we're in the parent process.
|
//From this point forward, we know we're in the parent process.
|
||||||
if(!doWait())
|
if (!doWait()) {
|
||||||
{
|
|
||||||
cout << "Didn't wait successfully" << endl;
|
cout << "Didn't wait successfully" << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -82,30 +74,30 @@ bool TraceChild::startTracing(const char * pathToFile, char * const argv[])
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TraceChild::stopTracing()
|
bool
|
||||||
|
TraceChild::stopTracing()
|
||||||
{
|
{
|
||||||
if(ptrace(PTRACE_KILL, pid, 0, 0) != 0)
|
if (ptrace(PTRACE_KILL, pid, 0, 0) != 0)
|
||||||
return false;
|
return false;
|
||||||
tracing = false;
|
tracing = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TraceChild::step()
|
bool
|
||||||
|
TraceChild::step()
|
||||||
{
|
{
|
||||||
ptraceSingleStep();
|
ptraceSingleStep();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TraceChild::ptraceSingleStep()
|
bool
|
||||||
|
TraceChild::ptraceSingleStep()
|
||||||
{
|
{
|
||||||
if(!tracing)
|
if (!tracing) {
|
||||||
{
|
|
||||||
cout << "Not tracing!" << endl;
|
cout << "Not tracing!" << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(ptrace(PTRACE_SINGLESTEP, pid, 0, 0) != 0)
|
if (ptrace(PTRACE_SINGLESTEP, pid, 0, 0) != 0) {
|
||||||
{
|
switch (errno) {
|
||||||
switch(errno)
|
|
||||||
{
|
|
||||||
case EBUSY: cout << "EBUSY" << endl; break;
|
case EBUSY: cout << "EBUSY" << endl; break;
|
||||||
case EFAULT: cout << "EFAULT" << endl; break;
|
case EFAULT: cout << "EFAULT" << endl; break;
|
||||||
case EIO: cout << "EIO" << endl; break;
|
case EIO: cout << "EIO" << endl; break;
|
||||||
|
@ -121,12 +113,12 @@ bool TraceChild::ptraceSingleStep()
|
||||||
update(pid);
|
update(pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TraceChild::doWait()
|
bool
|
||||||
|
TraceChild::doWait()
|
||||||
{
|
{
|
||||||
int wait_val;
|
int wait_val;
|
||||||
wait(&wait_val);
|
wait(&wait_val);
|
||||||
if(WIFEXITED(wait_val))
|
if (WIFEXITED(wait_val)) {
|
||||||
{
|
|
||||||
cerr << "Program exited! Exit status is "
|
cerr << "Program exited! Exit status is "
|
||||||
<< WEXITSTATUS(wait_val) << endl;
|
<< WEXITSTATUS(wait_val) << endl;
|
||||||
cerr << "Executed " << instructions
|
cerr << "Executed " << instructions
|
||||||
|
@ -134,25 +126,21 @@ bool TraceChild::doWait()
|
||||||
tracing = false;
|
tracing = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(WIFSIGNALED(wait_val))
|
if (WIFSIGNALED(wait_val)) {
|
||||||
{
|
if (WTERMSIG(wait_val))
|
||||||
if(WTERMSIG(wait_val))
|
|
||||||
cerr << "Program terminated by signal "
|
cerr << "Program terminated by signal "
|
||||||
<< WTERMSIG(wait_val) << endl;
|
<< WTERMSIG(wait_val) << endl;
|
||||||
if(WCOREDUMP(wait_val))
|
if (WCOREDUMP(wait_val))
|
||||||
cerr << "Program core dumped!" << endl;
|
cerr << "Program core dumped!" << endl;
|
||||||
tracing = false;
|
tracing = false;
|
||||||
cerr << "Executed " << instructions
|
cerr << "Executed " << instructions
|
||||||
<< " instructions." << endl;
|
<< " instructions." << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(WIFSTOPPED(wait_val) && WSTOPSIG(wait_val) != SIGTRAP)
|
if (WIFSTOPPED(wait_val) && WSTOPSIG(wait_val) != SIGTRAP) {
|
||||||
{
|
cerr << "Program stopped by signal " << WSTOPSIG(wait_val) << endl;
|
||||||
cerr << "Program stopped by signal "
|
|
||||||
<< WSTOPSIG(wait_val) << endl;
|
|
||||||
tracing = false;
|
tracing = false;
|
||||||
cerr << "Executed " << instructions
|
cerr << "Executed " << instructions << " instructions." << endl;
|
||||||
<< " instructions." << endl;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -35,30 +35,31 @@
|
||||||
|
|
||||||
class TraceChild : public RegState
|
class TraceChild : public RegState
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
int pid;
|
int pid;
|
||||||
uint64_t instructions;
|
uint64_t instructions;
|
||||||
bool tracing;
|
bool tracing;
|
||||||
public:
|
public:
|
||||||
TraceChild() : tracing(false), instructions(0)
|
TraceChild() : tracing(false), instructions(0)
|
||||||
{;}
|
{;}
|
||||||
virtual bool sendState(int socket) = 0;
|
virtual bool sendState(int socket) = 0;
|
||||||
virtual bool startTracing(const char * pathToFile,
|
virtual bool startTracing(const char * pathToFile, char * const argv[]);
|
||||||
char * const argv[]);
|
|
||||||
virtual bool stopTracing();
|
virtual bool stopTracing();
|
||||||
virtual bool step();
|
virtual bool step();
|
||||||
virtual uint64_t getPC() = 0;
|
virtual uint64_t getPC() = 0;
|
||||||
virtual uint64_t getSP() = 0;
|
virtual uint64_t getSP() = 0;
|
||||||
virtual std::ostream & outputStartState(std::ostream & os) = 0;
|
virtual std::ostream & outputStartState(std::ostream & os) = 0;
|
||||||
int getPid()
|
int
|
||||||
|
getPid()
|
||||||
{
|
{
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
bool isTracing()
|
bool
|
||||||
|
isTracing()
|
||||||
{
|
{
|
||||||
return tracing;
|
return tracing;
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
bool ptraceSingleStep();
|
bool ptraceSingleStep();
|
||||||
bool doWait();
|
bool doWait();
|
||||||
};
|
};
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
#if defined __alpha__
|
#if defined __alpha__
|
||||||
#error "Alpha architecture not implemented"
|
#error "Alpha architecture not implemented"
|
||||||
#elif defined __amd64__
|
#elif defined __amd64__
|
||||||
// #error "AMD64 architecture not implemented"
|
|
||||||
#include "arch/tracechild_amd64.cc"
|
#include "arch/tracechild_amd64.cc"
|
||||||
#elif defined __arm__
|
#elif defined __arm__
|
||||||
#include "arch/tracechild_arm.cc"
|
#include "arch/tracechild_arm.cc"
|
||||||
|
|
Loading…
Reference in a new issue