Cleaned up the function a bit to help route out bugs.
--HG-- extra : convert_revision : db9a526bddc8634cea63b42b882f580806066db5
This commit is contained in:
parent
54c9701a25
commit
76c07ea46b
1 changed files with 83 additions and 19 deletions
|
@ -188,46 +188,110 @@ bool SparcTraceChild::step()
|
||||||
//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
|
||||||
//so that annulled branches will still stop as well.
|
//so that annulled branches will still stop as well.
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Useful constants
|
||||||
|
*/
|
||||||
const static uint64_t breakInst = 0x91d02001;
|
const static uint64_t breakInst = 0x91d02001;
|
||||||
const static uint64_t breakWord = breakInst | (breakInst << 32);
|
const static uint64_t breakWord = breakInst | (breakInst << 32);
|
||||||
const static uint64_t lowMask = (uint64_t)(0xFFFFFFFF);
|
const static uint64_t lowMask = 0xFFFFFFFFULL;
|
||||||
const static uint64_t highMask = lowMask << 32;
|
const static uint64_t highMask = lowMask << 32;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* storage for the original contents of the child process's memory
|
||||||
|
*/
|
||||||
uint64_t originalInst, originalAnnulInst;
|
uint64_t originalInst, originalAnnulInst;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get information about where the process is and is headed next.
|
||||||
|
*/
|
||||||
|
uint64_t currentPC = getRegVal(PC);
|
||||||
|
bool unalignedPC = currentPC & 7;
|
||||||
|
uint64_t alignedPC = currentPC & (~7);
|
||||||
uint64_t nextPC = getRegVal(NPC);
|
uint64_t nextPC = getRegVal(NPC);
|
||||||
bool unaligned = nextPC & 7;
|
bool unalignedNPC = nextPC & 7;
|
||||||
uint64_t alignedPC = nextPC & (~7);
|
uint64_t alignedNPC = nextPC & (~7);
|
||||||
originalInst = ptrace(PTRACE_PEEKTEXT, pid, alignedPC, 0);
|
|
||||||
if(unaligned)
|
/*
|
||||||
|
* Store the original contents of the child process's memory
|
||||||
|
*/
|
||||||
|
originalInst = ptrace(PTRACE_PEEKTEXT, pid, alignedNPC, 0);
|
||||||
|
//Save a ptrace call if we can
|
||||||
|
if(unalignedNPC)
|
||||||
{
|
{
|
||||||
originalAnnulInst = ptrace(PTRACE_PEEKTEXT, pid, alignedPC+8, 0);
|
originalAnnulInst = ptrace(PTRACE_PEEKTEXT, pid, alignedNPC+8, 0);
|
||||||
}
|
}
|
||||||
uint64_t newInst;
|
|
||||||
if(unaligned)
|
/*
|
||||||
|
* Prepare breakpointed copies of child processes memory
|
||||||
|
*/
|
||||||
|
uint64_t newInst, newAnnulInst;
|
||||||
|
//If the current instruction is in the same word as the npc
|
||||||
|
if(alignedPC == alignedNPC)
|
||||||
{
|
{
|
||||||
newInst = (originalInst & highMask) | (breakInst << 0);
|
//Make sure we only replace the other part
|
||||||
if(ptrace(PTRACE_POKETEXT, pid, alignedPC, newInst) != 0)
|
if(unalignedPC)
|
||||||
cerr << "Poke failed" << endl;
|
newInst = (originalInst & lowMask) | (breakWord & highMask);
|
||||||
newInst = (originalAnnulInst & lowMask) | (breakInst << 32);
|
else
|
||||||
if(ptrace(PTRACE_POKETEXT, pid, alignedPC+8, newInst) != 0)
|
newInst = (originalInst & highMask) | (breakWord & lowMask);
|
||||||
cerr << "Poke failed" << endl;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(ptrace(PTRACE_POKETEXT, pid, alignedPC, breakWord) != 0)
|
//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;
|
||||||
|
//Replace the next word, if necessary
|
||||||
|
if(unalignedNPC)
|
||||||
|
{
|
||||||
|
if(ptrace(PTRACE_POKETEXT, pid, alignedNPC+8, newAnnulInst) != 0)
|
||||||
cerr << "Poke failed" << endl;
|
cerr << "Poke failed" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Restart the child process
|
||||||
|
*/
|
||||||
//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, /*nextPC - 4*/ 1, 0) != 0)
|
if(ptrace(PTRACE_CONT, pid, 1, 0) != 0)
|
||||||
cerr << "Cont failed" << endl;
|
cerr << "Cont failed" << endl;
|
||||||
doWait();
|
doWait();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update our record of the child's state
|
||||||
|
*/
|
||||||
update(pid);
|
update(pid);
|
||||||
if(ptrace(PTRACE_POKETEXT, pid, alignedPC, originalInst) != 0)
|
|
||||||
|
/*
|
||||||
|
* Put back the original contents of the childs address space
|
||||||
|
*/
|
||||||
|
if(ptrace(PTRACE_POKETEXT, pid, alignedNPC, originalInst) != 0)
|
||||||
cerr << "Repoke failed" << endl;
|
cerr << "Repoke failed" << endl;
|
||||||
if(unaligned)
|
if(unalignedNPC)
|
||||||
{
|
{
|
||||||
if(ptrace(PTRACE_POKETEXT, pid, alignedPC+8, originalAnnulInst) != 0)
|
if(ptrace(PTRACE_POKETEXT, pid, alignedNPC+8, originalAnnulInst) != 0)
|
||||||
cerr << "Repoke failed" << endl;
|
cerr << "Repoke failed" << endl;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Reference in a new issue