From: Daniel Jacobowitz <dan@codesourcery.com>
To: Ulrich Weigand <uweigand@de.ibm.com>
Cc: gdb-patches@sourceware.org, rearnsha@arm.com
Subject: Re: [rfa] Fix software-watchpoint failures by adding epilogue detection
Date: Wed, 22 Sep 2010 20:01:00 -0000 [thread overview]
Message-ID: <20100922193753.GA25020@caradoc.them.org> (raw)
In-Reply-To: <201009221846.o8MIklfl003240@d12av02.megacenter.de.ibm.com>
On Wed, Sep 22, 2010 at 08:46:47PM +0200, Ulrich Weigand wrote:
> Hello,
>
> I've been seeing failures in software watchpoint tests on ARM (Thumb-2),
> due to missing modeling of precise unwind states during function
> epilogues. This problem is well known from other architectures,
> and is usually fixed by skipping epilogue during sofware watchpoint
> single-stepping via the gdbarch_in_function_epilogue_p callback.
>
> However, ARM currently does not define this routine. The following
> patch adds an implementation that detects common Thumb epilogue
> sequences (ARM is missing, but could be added in an analogous way).
Hi Ulrich,
One of the patches we haven't had a chance to submit took the same
approach to solve these failures. I also did ARM mode, as well as
some additional sequences - probably those used by RealView. I've
attached it.
We have at least one other patch related to ARM testsuite failures,
specifically an ERROR (probably infinite backtrace) in gdb1250.exp.
I can extract it for you if you'd like, but I'm not sure it's in
condition to be merged.
I haven't retested this patch against HEAD, but it's in all our
builds.
--
Daniel Jacobowitz
CodeSourcery
2010-07-02 Daniel Jacobowitz <dan@codesourcery.com>
* arm-tdep.c (thumb_in_function_epilogue_p)
(arm_in_function_epilogue_p): New.
(thumb_insn_size): Move higher.
(arm_gdbarch_init): Install arm_in_function_epilogue_p as
gdbarch_in_function_epilogue_p callback.
--- /net/henry4/scratch/gcc/src/gdb-mainline/gdb/arm-tdep.c 2010-08-30 10:47:04.000000000 -0700
+++ gdb/arm-tdep.c 2010-09-13 12:32:50.000000000 -0700
@@ -1706,6 +1815,168 @@ arm_dwarf2_frame_init_reg (struct gdbarc
}
}
+/* Return the size in bytes of the complete Thumb instruction whose
+ first halfword is INST1. */
+
+static int
+thumb_insn_size (unsigned short inst1)
+{
+ if ((inst1 & 0xe000) == 0xe000 && (inst1 & 0x1800) != 0)
+ return 4;
+ else
+ return 2;
+}
+
+/* Return 1 if the stack frame has already been destroyed by the
+ function epilogue. */
+
+static int
+thumb_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+ enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
+ unsigned int inst1, inst2;
+ int found_return, found_stack_adjust;
+ CORE_ADDR func_start, func_end;
+
+ if (!find_pc_partial_function (pc, NULL, &func_start, &func_end))
+ return 0;
+
+ /* We are in the epilogue if the previous instruction was a stack
+ adjustment and the next instruction is a possible return (bx, mov
+ pc, or pop). We could have to scan backwards to find the stack
+ adjustment, or forwards to find the return, but this is a decent
+ approximation. First scan forwards. */
+
+ found_return = 0;
+ inst1 = read_memory_unsigned_integer (pc, 2, byte_order_for_code);
+
+ if ((inst1 & 0xff00) == 0xbc00 && pc + 2 < func_end)
+ /* POP (without PC). Potentially loading the return address for BX. */
+ inst1 = read_memory_unsigned_integer (pc + 2, 2, byte_order_for_code);
+
+ if ((inst1 & 0xff80) == 0x4700)
+ /* BX lr is typically used for returns. */
+ found_return = 1;
+ else if ((inst1 & 0xff00) == 0xbd00)
+ /* POP, including PC. */
+ found_return = 1;
+ else if (thumb_insn_size (inst1) == 4)
+ {
+ inst2 = read_memory_unsigned_integer (pc, 2, byte_order_for_code);
+
+ if (inst1 == 0xe8bd && (inst2 & 0x8000) == 0x8000)
+ /* POP.W, including PC. */
+ found_return = 1;
+ else if (inst1 == 0xf85d && inst2 == 0xfb04)
+ /* POP.W, only PC. */
+ found_return = 1;
+ }
+
+ if (!found_return)
+ return 0;
+
+ /* Scan backwards. This is just a heuristic, so do not worry about
+ false positives from mode changes or 16-bit vs 32-bit instructions. */
+
+ if (pc < func_start + 4)
+ return 0;
+
+ found_stack_adjust = 0;
+ inst1 = read_memory_unsigned_integer (pc - 4, 2, byte_order_for_code);
+ inst2 = read_memory_unsigned_integer (pc - 2, 2, byte_order_for_code);
+ if ((inst2 & 0xff00) == 0xbc00)
+ /* POP (without PC). */
+ found_stack_adjust = 1;
+ else if (inst1 == 0xe8bd)
+ /* POP.W (register list). */
+ found_stack_adjust = 1;
+ else if (inst1 == 0xf85d && (inst2 & 0x0fff) == 0x0b04)
+ /* POP.W (one register). */
+ found_stack_adjust = 1;
+ else if ((inst2 & 0xff00) == 0xb000)
+ /* ADD SP, imm or SUB SP, imm. */
+ found_stack_adjust = 1;
+
+ /* There are many other stack adjusting instructions which could be
+ recognized here. */
+
+ if (found_stack_adjust)
+ return 1;
+
+ return 0;
+}
+
+/* Return 1 if the stack frame has already been destroyed by the
+ function epilogue. */
+
+static int
+arm_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+ enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
+ unsigned int insn;
+ int found_return, found_stack_adjust;
+ CORE_ADDR func_start, func_end;
+
+ if (arm_pc_is_thumb (gdbarch, pc))
+ return thumb_in_function_epilogue_p (gdbarch, pc);
+
+ if (!find_pc_partial_function (pc, NULL, &func_start, &func_end))
+ return 0;
+
+ /* We are in the epilogue if the previous instruction was a stack
+ adjustment and the next instruction is a possible return (bx, mov
+ pc, or pop). We could have to scan backwards to find the stack
+ adjustment, or forwards to find the return, but this is a decent
+ approximation. First scan forwards. */
+
+ found_return = 0;
+ insn = read_memory_unsigned_integer (pc, 4, byte_order_for_code);
+ if (bits (insn, 28, 31) != INST_NV)
+ {
+ if ((insn & 0x0ffffff0) == 0x012fff10)
+ /* BX. */
+ found_return = 1;
+ else if ((insn & 0x0ffffff0) == 0x01a0f000)
+ /* MOV PC. */
+ found_return = 1;
+ else if ((insn & 0x0fff0000) == 0x08bd0000
+ && (insn & 0x0000c000) != 0)
+ /* POP (LDMIA), including PC or LR. */
+ found_return = 1;
+ }
+
+ if (!found_return)
+ return 0;
+
+ /* Scan backwards. This is just a heuristic, so do not worry about
+ false positives from mode changes. */
+
+ if (pc < func_start + 4)
+ return 0;
+
+ insn = read_memory_unsigned_integer (pc - 4, 4, byte_order_for_code);
+ if (bits (insn, 28, 31) != INST_NV)
+ {
+ if ((insn & 0x0df0f000) == 0x0080d000)
+ /* ADD SP (register or immediate). */
+ found_stack_adjust = 1;
+ else if ((insn & 0x0df0f000) == 0x0040d000)
+ /* SUB SP (register or immediate). */
+ found_stack_adjust = 1;
+ else if ((insn & 0x0ffffff0) == 0x01a0d000)
+ /* MOV SP. */
+ found_return = 1;
+ else if ((insn & 0x0fff0000) == 0x08bd0000)
+ /* POP (LDMIA). */
+ found_stack_adjust = 1;
+ }
+
+ if (found_stack_adjust)
+ return 1;
+
+ return 0;
+}
+
/* When arguments must be pushed onto the stack, they go on in reverse
order. The code below implements a FILO (stack) to do this. */
@@ -2647,18 +2918,6 @@ bitcount (unsigned long val)
return nbits;
}
-/* Return the size in bytes of the complete Thumb instruction whose
- first halfword is INST1. */
-
-static int
-thumb_insn_size (unsigned short inst1)
-{
- if ((inst1 & 0xe000) == 0xe000 && (inst1 & 0x1800) != 0)
- return 4;
- else
- return 2;
-}
-
static int
thumb_advance_itstate (unsigned int itstate)
{
@@ -6881,6 +7160,7 @@ arm_gdbarch_init (struct gdbarch_info in
/* Advance PC across function entry code. */
set_gdbarch_skip_prologue (gdbarch, arm_skip_prologue);
+ set_gdbarch_in_function_epilogue_p (gdbarch, arm_in_function_epilogue_p);
/* Skip trampolines. */
set_gdbarch_skip_trampoline_code (gdbarch, arm_skip_stub);
next prev parent reply other threads:[~2010-09-22 19:38 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-09-22 19:20 Ulrich Weigand
2010-09-22 20:01 ` Daniel Jacobowitz [this message]
2010-09-23 16:13 ` Ulrich Weigand
2010-09-24 16:11 ` Ulrich Weigand
2010-09-28 20:23 ` Daniel Jacobowitz
2010-09-28 21:47 ` Ulrich Weigand
2010-09-28 21:49 ` Daniel Jacobowitz
2010-09-29 15:24 ` Richard Earnshaw
2010-10-07 16:12 ` [rfa, v3] Fix software-watchpoint failures on ARM " Ulrich Weigand
2010-10-08 13:01 ` Richard Earnshaw
2010-10-08 13:27 ` Ulrich Weigand
2010-09-29 14:43 ` [rfa] Fix software-watchpoint failures " Yao Qi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20100922193753.GA25020@caradoc.them.org \
--to=dan@codesourcery.com \
--cc=gdb-patches@sourceware.org \
--cc=rearnsha@arm.com \
--cc=uweigand@de.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox