Fixing statetrace to work with 32 bit SPARC processes, as well as rewritting it's single stepping code.
--HG-- extra : convert_revision : 69b1668a850519ab98b02c525ec41ff727eb6036
This commit is contained in:
parent
68ad153309
commit
9b72ff8290
5 changed files with 169 additions and 81 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006 The Regents of The University of Michigan
|
* Copyright (c) 2006-2007 The Regents of The University of Michigan
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -151,7 +151,6 @@ int64_t getRegs(regs & myregs, fpu & myfpu,
|
||||||
|
|
||||||
bool SparcTraceChild::update(int pid)
|
bool SparcTraceChild::update(int pid)
|
||||||
{
|
{
|
||||||
static const int stackBias = 2047;
|
|
||||||
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));
|
||||||
|
@ -161,7 +160,8 @@ bool SparcTraceChild::update(int pid)
|
||||||
cerr << "Update failed" << endl;
|
cerr << "Update failed" << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
uint64_t StackPointer = getRegVal(O6);
|
uint64_t StackPointer = getSP();
|
||||||
|
const int stackBias = (StackPointer % 1) ? 2047 : 0;
|
||||||
for(unsigned int x = 0; x < 8; x++)
|
for(unsigned int x = 0; x < 8; x++)
|
||||||
{
|
{
|
||||||
locals[x] = ptrace(PTRACE_PEEKTEXT, pid,
|
locals[x] = ptrace(PTRACE_PEEKTEXT, pid,
|
||||||
|
@ -182,8 +182,76 @@ SparcTraceChild::SparcTraceChild()
|
||||||
regDiffSinceUpdate[x] = false;
|
regDiffSinceUpdate[x] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SparcTraceChild::getTargets(uint32_t inst, uint64_t pc, uint64_t npc,
|
||||||
|
uint64_t &target1, uint64_t &target2)
|
||||||
|
{
|
||||||
|
//We can identify the instruction categories we care about using the top
|
||||||
|
//10 bits of the instruction, excluding the annul bit in the 3rd most
|
||||||
|
//significant bit position and the condition field. We'll call these
|
||||||
|
//bits the "sig" for signature.
|
||||||
|
uint32_t sig = (inst >> 22) & 0x307;
|
||||||
|
uint32_t cond = (inst >> 25) & 0xf;
|
||||||
|
bool annul = (inst & (1 << 29));
|
||||||
|
|
||||||
|
//Check if it's a ba...
|
||||||
|
bool ba = (cond == 0x8) &&
|
||||||
|
(sig == 0x1 || sig == 0x2 || sig == 0x5 || sig == 0x6);
|
||||||
|
//or a bn...
|
||||||
|
bool bn = (cond == 0x0) &&
|
||||||
|
(sig == 0x1 || sig == 0x2 || sig == 0x5 || sig == 0x6);
|
||||||
|
//or a bcc
|
||||||
|
bool bcc = (cond & 0x7) &&
|
||||||
|
(sig == 0x1 || sig == 0x2 || sig == 0x3 || sig == 0x5 || sig == 0x6);
|
||||||
|
|
||||||
|
if(annul)
|
||||||
|
{
|
||||||
|
if(bcc)
|
||||||
|
{
|
||||||
|
target1 = npc;
|
||||||
|
target2 = npc + 4;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
else if(ba)
|
||||||
|
{
|
||||||
|
//This branches immediately to the effective address of the branch
|
||||||
|
//which we'll have to calculate.
|
||||||
|
uint64_t disp = 0;
|
||||||
|
int64_t extender = 0;
|
||||||
|
//Figure out how big the displacement field is, and grab the bits
|
||||||
|
if(sig == 0x1 || sig == 0x5)
|
||||||
|
{
|
||||||
|
disp = inst & ((1 << 19) - 1);
|
||||||
|
extender = 1 << 18;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
disp = inst & ((1 << 22) - 1);
|
||||||
|
extender = 1 << 21;
|
||||||
|
}
|
||||||
|
//This does sign extension, believe it or not.
|
||||||
|
disp = (disp ^ extender) - extender;
|
||||||
|
//Multiply the displacement by 4. I'm assuming the compiler is
|
||||||
|
//smart enough to turn this into a shift.
|
||||||
|
disp *= 4;
|
||||||
|
target1 = pc + disp;
|
||||||
|
}
|
||||||
|
else if(bn)
|
||||||
|
target1 = npc + 4;
|
||||||
|
else
|
||||||
|
target1 = npc;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
target1 = npc;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool SparcTraceChild::step()
|
bool SparcTraceChild::step()
|
||||||
{
|
{
|
||||||
|
//Increment the count of the number of instructions executed
|
||||||
|
instructions++;
|
||||||
//Two important considerations are that the address of the instruction
|
//Two important considerations are that the address of the instruction
|
||||||
//being breakpointed should be word (64bit) aligned, and that both the
|
//being breakpointed should be word (64bit) aligned, and that both the
|
||||||
//next instruction and the instruction after that need to be breakpointed
|
//next instruction and the instruction after that need to be breakpointed
|
||||||
|
@ -193,6 +261,8 @@ bool SparcTraceChild::step()
|
||||||
* Useful constants
|
* Useful constants
|
||||||
*/
|
*/
|
||||||
const static uint64_t breakInst = 0x91d02001;
|
const static uint64_t breakInst = 0x91d02001;
|
||||||
|
const static uint64_t lowBreakInst = breakInst;
|
||||||
|
const static uint64_t highBreakInst = breakInst << 32;
|
||||||
const static uint64_t breakWord = breakInst | (breakInst << 32);
|
const static uint64_t breakWord = breakInst | (breakInst << 32);
|
||||||
const static uint64_t lowMask = 0xFFFFFFFFULL;
|
const static uint64_t lowMask = 0xFFFFFFFFULL;
|
||||||
const static uint64_t highMask = lowMask << 32;
|
const static uint64_t highMask = lowMask << 32;
|
||||||
|
@ -212,60 +282,39 @@ bool SparcTraceChild::step()
|
||||||
bool unalignedNPC = nextPC & 7;
|
bool unalignedNPC = nextPC & 7;
|
||||||
uint64_t alignedNPC = nextPC & (~7);
|
uint64_t alignedNPC = nextPC & (~7);
|
||||||
|
|
||||||
/*
|
//Get the current instruction
|
||||||
* Store the original contents of the child process's memory
|
uint64_t curInst = ptrace(PTRACE_PEEKTEXT, pid, alignedPC);
|
||||||
*/
|
curInst = unalignedPC ? (curInst & 0xffffffffULL) : (curInst >> 32);
|
||||||
originalInst = ptrace(PTRACE_PEEKTEXT, pid, alignedNPC, 0);
|
|
||||||
//Save a ptrace call if we can
|
uint64_t bp1, bp2;
|
||||||
if(unalignedNPC)
|
int numTargets = getTargets(curInst, currentPC, nextPC, bp1, bp2);
|
||||||
{
|
assert(numTargets == 1 || numTargets == 2);
|
||||||
originalAnnulInst = ptrace(PTRACE_PEEKTEXT, pid, alignedNPC+8, 0);
|
|
||||||
}
|
bool unalignedBp1 = bp1 & 7;
|
||||||
|
uint64_t alignedBp1 = bp1 & (~7);
|
||||||
|
bool unalignedBp2 = bp2 & 7;
|
||||||
|
uint64_t alignedBp2 = bp2 & (~7);
|
||||||
|
uint64_t origBp1, origBp2;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prepare breakpointed copies of child processes memory
|
* Set the first breakpoint
|
||||||
*/
|
*/
|
||||||
uint64_t newInst, newAnnulInst;
|
origBp1 = ptrace(PTRACE_PEEKTEXT, pid, alignedBp1, 0);
|
||||||
//If the current instruction is in the same word as the npc
|
uint64_t newBp1 = origBp1;
|
||||||
if(alignedPC == alignedNPC)
|
newBp1 &= unalignedBp1 ? highMask : lowMask;
|
||||||
{
|
newBp1 |= unalignedBp1 ? lowBreakInst : highBreakInst;
|
||||||
//Make sure we only replace the other part
|
if(ptrace(PTRACE_POKETEXT, pid, alignedBp1, newBp1) != 0)
|
||||||
if(unalignedPC)
|
|
||||||
newInst = (originalInst & lowMask) | (breakWord & highMask);
|
|
||||||
else
|
|
||||||
newInst = (originalInst & highMask) | (breakWord & lowMask);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//otherwise replace the whole thing
|
|
||||||
newInst = breakWord;
|
|
||||||
}
|
|
||||||
//If the current instruction is in the same word as the word after
|
|
||||||
//the npc
|
|
||||||
if(alignedPC == alignedNPC+8)
|
|
||||||
{
|
|
||||||
//Make sure we only replace the other part
|
|
||||||
if(unalignedPC)
|
|
||||||
newAnnulInst = (originalAnnulInst & lowMask) | (breakWord & highMask);
|
|
||||||
else
|
|
||||||
newAnnulInst = (originalAnnulInst & highMask) | (breakWord & lowMask);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//otherwise replace the whole thing
|
|
||||||
newAnnulInst = breakWord;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Stuff the breakpoint instructions into the child's address space.
|
|
||||||
*/
|
|
||||||
//Replace the word at npc
|
|
||||||
if(ptrace(PTRACE_POKETEXT, pid, alignedNPC, newInst) != 0)
|
|
||||||
cerr << "Poke failed" << endl;
|
cerr << "Poke failed" << endl;
|
||||||
//Replace the next word, if necessary
|
/*
|
||||||
if(unalignedNPC)
|
* Set the second breakpoint if necessary
|
||||||
|
*/
|
||||||
|
if(numTargets == 2)
|
||||||
{
|
{
|
||||||
if(ptrace(PTRACE_POKETEXT, pid, alignedNPC+8, newAnnulInst) != 0)
|
origBp2 = ptrace(PTRACE_PEEKTEXT, pid, alignedBp2, 0);
|
||||||
|
uint64_t newBp2 = origBp2;
|
||||||
|
newBp2 &= unalignedBp2 ? highMask : lowMask;
|
||||||
|
newBp2 |= unalignedBp2 ? lowBreakInst : highBreakInst;
|
||||||
|
if(ptrace(PTRACE_POKETEXT, pid, alignedBp2, newBp2) != 0)
|
||||||
cerr << "Poke failed" << endl;
|
cerr << "Poke failed" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,16 +334,16 @@ bool SparcTraceChild::step()
|
||||||
update(pid);
|
update(pid);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Put back the original contents of the childs address space
|
* Put back the original contents of the childs address space in the
|
||||||
|
* reverse order.
|
||||||
*/
|
*/
|
||||||
if(ptrace(PTRACE_POKETEXT, pid, alignedNPC, originalInst) != 0)
|
if(numTargets == 2)
|
||||||
cerr << "Repoke failed" << endl;
|
|
||||||
if(unalignedNPC)
|
|
||||||
{
|
{
|
||||||
if(ptrace(PTRACE_POKETEXT, pid, alignedNPC+8, originalAnnulInst) != 0)
|
if(ptrace(PTRACE_POKETEXT, pid, alignedBp2, origBp2) != 0)
|
||||||
cerr << "Repoke failed" << endl;
|
cerr << "Poke failed" << endl;
|
||||||
}
|
}
|
||||||
return true;
|
if(ptrace(PTRACE_POKETEXT, pid, alignedBp1, origBp1) != 0)
|
||||||
|
cerr << "Poke failed" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t SparcTraceChild::getRegVal(int num)
|
int64_t SparcTraceChild::getRegVal(int num)
|
||||||
|
@ -315,39 +364,56 @@ char * SparcTraceChild::printReg(int num)
|
||||||
|
|
||||||
ostream & SparcTraceChild::outputStartState(ostream & os)
|
ostream & SparcTraceChild::outputStartState(ostream & os)
|
||||||
{
|
{
|
||||||
|
bool v8 = false;
|
||||||
uint64_t sp = getSP();
|
uint64_t sp = getSP();
|
||||||
|
if(sp % 1)
|
||||||
|
{
|
||||||
|
os << "Detected a 64 bit executable.\n";
|
||||||
|
v8 = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
os << "Detected a 32 bit executable.\n";
|
||||||
|
v8 = true;
|
||||||
|
}
|
||||||
uint64_t pc = getPC();
|
uint64_t pc = getPC();
|
||||||
char obuf[1024];
|
char obuf[1024];
|
||||||
sprintf(obuf, "Initial stack pointer = 0x%016llx\n", sp);
|
sprintf(obuf, "Initial stack pointer = 0x%016llx\n", sp);
|
||||||
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;
|
||||||
//Take out the stack bias
|
if(!v8)
|
||||||
sp += 2047;
|
{
|
||||||
|
//Take out the stack bias
|
||||||
|
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;
|
||||||
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;
|
||||||
sp += 8;
|
sp += v8 ? 4 : 8;
|
||||||
}
|
}
|
||||||
//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;
|
||||||
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 += 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;
|
||||||
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;
|
||||||
sp += 8;
|
sp += v8 ? 4 : 8;
|
||||||
} while(cargv);
|
} while(cargv);
|
||||||
//Output the envp pointers
|
//Output the envp pointers
|
||||||
int envCount = 0;
|
int envCount = 0;
|
||||||
|
@ -355,20 +421,23 @@ ostream & SparcTraceChild::outputStartState(ostream & os)
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
cenvp = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
cenvp = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||||
|
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 += 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);
|
||||||
sp += 8;
|
if(v8) auxType = auxType >> 32;
|
||||||
|
sp += (v8 ? 4 : 8);
|
||||||
auxVal = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
auxVal = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||||
sp += 8;
|
if(v8) auxVal = auxVal >> 32;
|
||||||
|
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 - 16, 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.
|
||||||
|
@ -380,7 +449,7 @@ ostream & SparcTraceChild::outputStartState(ostream & os)
|
||||||
{
|
{
|
||||||
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(uint32_t); x++)
|
||||||
{
|
{
|
||||||
if(cbuf[x])
|
if(cbuf[x])
|
||||||
current += cbuf[x];
|
current += cbuf[x];
|
||||||
|
@ -393,7 +462,7 @@ ostream & SparcTraceChild::outputStartState(ostream & os)
|
||||||
currentStart = sp + x + 1;
|
currentStart = sp + x + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sp += 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;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006 The Regents of The University of Michigan
|
* Copyright (c) 2006-2007 The Regents of The University of Michigan
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -78,6 +78,12 @@ private:
|
||||||
int64_t oldInputs[8];
|
int64_t oldInputs[8];
|
||||||
bool regDiffSinceUpdate[numregs];
|
bool regDiffSinceUpdate[numregs];
|
||||||
|
|
||||||
|
//This calculates where the pc might go after the current instruction.
|
||||||
|
//while this equals npc for most instructions, it doesn't for all of
|
||||||
|
//them. The return value is the number of actual potential targets.
|
||||||
|
int getTargets(uint32_t inst, uint64_t pc, uint64_t npc,
|
||||||
|
uint64_t &target1, uint64_t &target2);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool update(int pid);
|
bool update(int pid);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006 The Regents of The University of Michigan
|
* Copyright (c) 2006-2007 The Regents of The University of Michigan
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -145,9 +145,13 @@ int main(int argc, char * argv[], char * envp[])
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(unsigned int x = startProgramArgs; x < argc; x++)
|
/*for(unsigned int x = startProgramArgs; x < argc; x++)
|
||||||
args += argv[x];
|
{
|
||||||
if(!child->startTracing(argv[startProgramArgs], args.c_str()))
|
cout << "Adding argument " << argv[x];
|
||||||
|
args += string(" ") + argv[x];
|
||||||
|
}*/
|
||||||
|
if(!child->startTracing(argv[startProgramArgs],
|
||||||
|
argv + startProgramArgs))
|
||||||
{
|
{
|
||||||
cerr << "Couldn't start target program" << endl;
|
cerr << "Couldn't start target program" << endl;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006 The Regents of The University of Michigan
|
* Copyright (c) 2006-2007 The Regents of The University of Michigan
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -36,8 +36,9 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
bool TraceChild::startTracing(const char * pathToFile, const char * arg)
|
bool TraceChild::startTracing(const char * pathToFile, char * const argv[])
|
||||||
{
|
{
|
||||||
|
instructions = 0;
|
||||||
pid = fork();
|
pid = fork();
|
||||||
if(pid == -1)
|
if(pid == -1)
|
||||||
{
|
{
|
||||||
|
@ -53,7 +54,7 @@ bool TraceChild::startTracing(const char * pathToFile, const char * arg)
|
||||||
ptrace(PTRACE_TRACEME, 0, 0, 0);
|
ptrace(PTRACE_TRACEME, 0, 0, 0);
|
||||||
|
|
||||||
//Start the program to trace
|
//Start the program to trace
|
||||||
execl(pathToFile, arg);
|
execv(pathToFile, argv);
|
||||||
|
|
||||||
//We should never get here, so this is an error!
|
//We should never get here, so this is an error!
|
||||||
return false;
|
return false;
|
||||||
|
@ -121,6 +122,8 @@ bool TraceChild::doWait()
|
||||||
{
|
{
|
||||||
cerr << "Program exited! Exit status is "
|
cerr << "Program exited! Exit status is "
|
||||||
<< WEXITSTATUS(wait_val) << endl;
|
<< WEXITSTATUS(wait_val) << endl;
|
||||||
|
cerr << "Executed " << instructions
|
||||||
|
<< " instructions." << endl;
|
||||||
tracing = false;
|
tracing = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -132,6 +135,8 @@ bool TraceChild::doWait()
|
||||||
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
|
||||||
|
<< " instructions." << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(WIFSTOPPED(wait_val) && WSTOPSIG(wait_val) != SIGTRAP)
|
if(WIFSTOPPED(wait_val) && WSTOPSIG(wait_val) != SIGTRAP)
|
||||||
|
@ -139,6 +144,8 @@ bool TraceChild::doWait()
|
||||||
cerr << "Program stopped by signal "
|
cerr << "Program stopped by signal "
|
||||||
<< WSTOPSIG(wait_val) << endl;
|
<< WSTOPSIG(wait_val) << endl;
|
||||||
tracing = false;
|
tracing = false;
|
||||||
|
cerr << "Executed " << instructions
|
||||||
|
<< " instructions." << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006 The Regents of The University of Michigan
|
* Copyright (c) 2006-2007 The Regents of The University of Michigan
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -37,11 +37,13 @@ class TraceChild : public RegState
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
int pid;
|
int pid;
|
||||||
|
uint64_t instructions;
|
||||||
bool tracing;
|
bool tracing;
|
||||||
public:
|
public:
|
||||||
TraceChild() : tracing(false)
|
TraceChild() : tracing(false), instructions(0)
|
||||||
{;}
|
{;}
|
||||||
virtual bool startTracing(const char * pathToFile, const char * arg);
|
virtual bool startTracing(const char * pathToFile,
|
||||||
|
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;
|
||||||
|
|
Loading…
Reference in a new issue