diff options
-rw-r--r-- | src/arch/arm/nativetrace.cc | 7 | ||||
-rw-r--r-- | util/statetrace/arch/tracechild_arm.cc | 36 |
2 files changed, 27 insertions, 16 deletions
diff --git a/src/arch/arm/nativetrace.cc b/src/arch/arm/nativetrace.cc index 7c9c70e0c..90c5e5c25 100644 --- a/src/arch/arm/nativetrace.cc +++ b/src/arch/arm/nativetrace.cc @@ -104,8 +104,13 @@ Trace::ArmNativeTrace::ThreadState::update(ThreadContext *tc) void Trace::ArmNativeTrace::check(NativeTraceRecord *record) { + ThreadContext *tc = record->getThread(); + // This area is read only on the target. It can't stop there to tell us + // what's going on, so we should skip over anything there also. + if (tc->readNextPC() > 0xffff0000) + return; nState.update(this); - mState.update(record->getThread()); + mState.update(tc); bool errorFound = false; // Regular int regs diff --git a/util/statetrace/arch/tracechild_arm.cc b/util/statetrace/arch/tracechild_arm.cc index 4687b46f0..b52c0694a 100644 --- a/util/statetrace/arch/tracechild_arm.cc +++ b/util/statetrace/arch/tracechild_arm.cc @@ -203,22 +203,28 @@ ostream & ARMTraceChild::outputStartState(ostream & os) bool ARMTraceChild::step() { + const uint32_t bkpt_inst = 0xe7f001f0; - const uint32_t bkpt_inst = 0xE1200070; - const uint32_t bkpt_mask = 0xFFF000F0; - - const uint32_t swi_inst = 0x0F0000000; - const uint32_t swi_mask = 0x0F0000000; - - uint32_t next_op = ptrace(PTRACE_PEEKDATA, pid, getPC(), 0); - if ((next_op & swi_mask) == swi_inst) { - ptrace(PTRACE_POKEDATA, pid, next_op + sizeof(uint32_t), bkpt_inst); - ptraceSingleStep(); - ptrace(PTRACE_POKEDATA, pid, next_op + sizeof(uint32_t), next_op); - } - else - { - ptraceSingleStep(); + uint32_t lr = getRegVal(14); + uint32_t pc = getPC(); + uint32_t lrOp; + + // Since ARM uses software breakpoints behind the scenes, they don't work + // in read only areas like the page of routines provided by the kernel. The + // link register generally holds the address the process wants to the + // kernel to return to after it's done, so we'll install a software + // breakpoint there. If the lr happens to point to the next instruction + // we'll leave out our breakpoint to avoid an infinite loop. This isn't a + // fool proof strategy, but it should work well in all the reasonable + // scenarios I can think of right now. + + if (pc != lr) { + lrOp = ptrace(PTRACE_PEEKDATA, pid, lr, 0); + ptrace(PTRACE_POKEDATA, pid, lr, bkpt_inst); + } + ptraceSingleStep(); + if (pc != lr) { + ptrace(PTRACE_POKEDATA, pid, lr, lrOp); } } |