summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2009-07-29 00:14:43 -0700
committerGabe Black <gblack@eecs.umich.edu>2009-07-29 00:14:43 -0700
commit873112ea9924074212f1dd667d345850c6dce789 (patch)
tree7349e44b5e6a8faf30a49fcfce56ca59a714ddf7 /util
parent0a9eb59e6f8be32939c6a267e67943ef50b8ba83 (diff)
downloadgem5-873112ea9924074212f1dd667d345850c6dce789.tar.xz
ARM: Make sure the target process doesn't run away from statetrace.
Diffstat (limited to 'util')
-rw-r--r--util/statetrace/arch/tracechild_arm.cc36
1 files changed, 21 insertions, 15 deletions
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);
}
}