diff options
Diffstat (limited to 'util')
-rw-r--r-- | util/statetrace/arch/tracechild_sparc.cc | 102 |
1 files changed, 83 insertions, 19 deletions
diff --git a/util/statetrace/arch/tracechild_sparc.cc b/util/statetrace/arch/tracechild_sparc.cc index 1dc62412a..bad81b647 100644 --- a/util/statetrace/arch/tracechild_sparc.cc +++ b/util/statetrace/arch/tracechild_sparc.cc @@ -188,46 +188,110 @@ bool SparcTraceChild::step() //being breakpointed should be word (64bit) aligned, and that both the //next instruction and the instruction after that need to be breakpointed //so that annulled branches will still stop as well. + + /* + * Useful constants + */ const static uint64_t breakInst = 0x91d02001; 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; + + /* + * storage for the original contents of the child process's memory + */ 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); - bool unaligned = nextPC & 7; - uint64_t alignedPC = nextPC & (~7); - originalInst = ptrace(PTRACE_PEEKTEXT, pid, alignedPC, 0); - if(unaligned) + bool unalignedNPC = nextPC & 7; + uint64_t alignedNPC = nextPC & (~7); + + /* + * 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); - if(ptrace(PTRACE_POKETEXT, pid, alignedPC, newInst) != 0) - cerr << "Poke failed" << endl; - newInst = (originalAnnulInst & lowMask) | (breakInst << 32); - if(ptrace(PTRACE_POKETEXT, pid, alignedPC+8, newInst) != 0) - cerr << "Poke failed" << endl; + //Make sure we only replace the other part + 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 { - if(ptrace(PTRACE_POKETEXT, pid, alignedPC, breakWord) != 0) + //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; } + + /* + * Restart the child process + */ //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 //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; doWait(); + + /* + * Update our record of the child's state + */ 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; - 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; } return true; |