From: Anton Blanchard <anton@samba.org>
To: gdb-patches@sourceware.org, brobecker@adacore.com,
emachado@linux.vnet.ibm.com, luis_gustavo@mentor.com,
ulrich.weigand@de.ibm.com
Subject: [PATCH 2/4] Support up to 3 conditional branches in an atomic sequence
Date: Fri, 28 Mar 2014 03:42:00 -0000 [thread overview]
Message-ID: <1395978111-30706-2-git-send-email-anton@samba.org> (raw)
In-Reply-To: <1395978111-30706-1-git-send-email-anton@samba.org>
gdb currently supports 1 conditional branch inside a ppc larx/stcx
critical region. Unfortunately there is existing code that contains more
than 1, for example in the ppc64 Linux kernel:
c00000000003ac18 <.__hash_page_4K>:
...
c00000000003ac4c: ldarx r31,0,r6
c00000000003ac50: andc. r0,r4,r31
c00000000003ac54: bne- c00000000003aee8 <htab_wrong_access>
c00000000003ac58: andi. r0,r31,2048
c00000000003ac5c: bne- c00000000003ae0c <htab_bail_ok>
c00000000003ac60: rlwinm r30,r4,30,24,24
c00000000003ac64: or r30,r30,r31
c00000000003ac68: ori r30,r30,2304
c00000000003ac6c: oris r30,r30,4096
c00000000003ac70: stdcx. r30,0,r6
If we try to single step through this we get stuck forever because
the reservation is never set when we step over the stdcx.
The following patch bumps the number to 3 conditional branches + 1
terminating branch. With this patch applied I can single step through
the offending function in the ppc64 Linux kernel.
gdb/
2014-03-28 Anton Blanchard <anton@samba.org>
* breakpoint.h (MAX_SINGLE_STEP_BREAKPOINTS): New define.
* rs6000-tdep.c (ppc_deal_with_atomic_sequence): Allow for more
than two breakpoints.
* breakpoint.c (insert_single_step_breakpoint): Likewise.
(insert_single_step_breakpoint): Likewise.
(single_step_breakpoints_inserted): Likewise.
(cancel_single_step_breakpoints): Likewise.
(detach_single_step_breakpoints): Likewise.
(single_step_breakpoint_inserted_here_p): Likewise.
---
gdb/breakpoint.c | 63 ++++++++++++++++++++++++++++---------------------------
gdb/breakpoint.h | 6 ++++--
gdb/rs6000-tdep.c | 46 ++++++++++++++++++++++------------------
3 files changed, 62 insertions(+), 53 deletions(-)
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 19af9df..b12ea94 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -15036,11 +15036,10 @@ deprecated_remove_raw_breakpoint (struct gdbarch *gdbarch, void *bp)
return ret;
}
-/* One (or perhaps two) breakpoints used for software single
- stepping. */
+/* Breakpoints used for software single stepping. */
-static void *single_step_breakpoints[2];
-static struct gdbarch *single_step_gdbarch[2];
+static void *single_step_breakpoints[MAX_SINGLE_STEP_BREAKPOINTS];
+static struct gdbarch *single_step_gdbarch[MAX_SINGLE_STEP_BREAKPOINTS];
/* Create and insert a breakpoint for software single step. */
@@ -15049,19 +15048,17 @@ insert_single_step_breakpoint (struct gdbarch *gdbarch,
struct address_space *aspace,
CORE_ADDR next_pc)
{
+ int i;
void **bpt_p;
- if (single_step_breakpoints[0] == NULL)
- {
- bpt_p = &single_step_breakpoints[0];
- single_step_gdbarch[0] = gdbarch;
- }
- else
- {
- gdb_assert (single_step_breakpoints[1] == NULL);
- bpt_p = &single_step_breakpoints[1];
- single_step_gdbarch[1] = gdbarch;
- }
+ for (i = 0; i < MAX_SINGLE_STEP_BREAKPOINTS; i++)
+ if (single_step_breakpoints[i] == NULL)
+ break;
+
+ gdb_assert (i < MAX_SINGLE_STEP_BREAKPOINTS);
+
+ bpt_p = &single_step_breakpoints[i];
+ single_step_gdbarch[i] = gdbarch;
/* NOTE drow/2006-04-11: A future improvement to this function would
be to only create the breakpoints once, and actually put them on
@@ -15082,8 +15079,13 @@ insert_single_step_breakpoint (struct gdbarch *gdbarch,
int
single_step_breakpoints_inserted (void)
{
- return (single_step_breakpoints[0] != NULL
- || single_step_breakpoints[1] != NULL);
+ int i;
+
+ for (i = 0; i < MAX_SINGLE_STEP_BREAKPOINTS; i++)
+ if (single_step_breakpoints[i] != NULL)
+ return 1;
+
+ return 0;
}
/* Remove and delete any breakpoints used for software single step. */
@@ -15091,22 +15093,21 @@ single_step_breakpoints_inserted (void)
void
remove_single_step_breakpoints (void)
{
+ int i;
+
gdb_assert (single_step_breakpoints[0] != NULL);
/* See insert_single_step_breakpoint for more about this deprecated
call. */
- deprecated_remove_raw_breakpoint (single_step_gdbarch[0],
- single_step_breakpoints[0]);
- single_step_gdbarch[0] = NULL;
- single_step_breakpoints[0] = NULL;
- if (single_step_breakpoints[1] != NULL)
- {
- deprecated_remove_raw_breakpoint (single_step_gdbarch[1],
- single_step_breakpoints[1]);
- single_step_gdbarch[1] = NULL;
- single_step_breakpoints[1] = NULL;
- }
+ for (i = 0; i < MAX_SINGLE_STEP_BREAKPOINTS; i++)
+ if (single_step_breakpoints[i] != NULL)
+ {
+ deprecated_remove_raw_breakpoint (single_step_gdbarch[i],
+ single_step_breakpoints[i]);
+ single_step_gdbarch[i] = NULL;
+ single_step_breakpoints[i] = NULL;
+ }
}
/* Delete software single step breakpoints without removing them from
@@ -15119,7 +15120,7 @@ cancel_single_step_breakpoints (void)
{
int i;
- for (i = 0; i < 2; i++)
+ for (i = 0; i < MAX_SINGLE_STEP_BREAKPOINTS; i++)
if (single_step_breakpoints[i])
{
xfree (single_step_breakpoints[i]);
@@ -15136,7 +15137,7 @@ detach_single_step_breakpoints (void)
{
int i;
- for (i = 0; i < 2; i++)
+ for (i = 0; i < MAX_SINGLE_STEP_BREAKPOINTS; i++)
if (single_step_breakpoints[i])
target_remove_breakpoint (single_step_gdbarch[i],
single_step_breakpoints[i]);
@@ -15151,7 +15152,7 @@ single_step_breakpoint_inserted_here_p (struct address_space *aspace,
{
int i;
- for (i = 0; i < 2; i++)
+ for (i = 0; i < MAX_SINGLE_STEP_BREAKPOINTS; i++)
{
struct bp_target_info *bp_tgt = single_step_breakpoints[i];
if (bp_tgt
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index d8e88fc..65d3ecb 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -1443,8 +1443,10 @@ extern void add_solib_catchpoint (char *arg, int is_load, int is_temp,
deletes all breakpoints. */
extern void delete_command (char *arg, int from_tty);
-/* Manage a software single step breakpoint (or two). Insert may be
- called twice before remove is called. */
+/* Manage software single step breakpoints. Insert may be
+ called multiple times before remove is called. */
+#define MAX_SINGLE_STEP_BREAKPOINTS 4
+
extern void insert_single_step_breakpoint (struct gdbarch *,
struct address_space *,
CORE_ADDR);
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index dbe3aa2..be14e39 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -1088,7 +1088,7 @@ ppc_deal_with_atomic_sequence (struct frame_info *frame)
struct address_space *aspace = get_frame_address_space (frame);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
CORE_ADDR pc = get_frame_pc (frame);
- CORE_ADDR breaks[2] = {-1, -1};
+ CORE_ADDR breaks[MAX_SINGLE_STEP_BREAKPOINTS];
CORE_ADDR loc = pc;
CORE_ADDR closing_insn; /* Instruction that closes the atomic sequence. */
int insn = read_memory_integer (loc, PPC_INSN_SIZE, byte_order);
@@ -1097,7 +1097,6 @@ ppc_deal_with_atomic_sequence (struct frame_info *frame)
int last_breakpoint = 0; /* Defaults to 0 (no breakpoints placed). */
const int atomic_sequence_length = 16; /* Instruction sequence length. */
int opcode; /* Branch instruction's OPcode. */
- int bc_insn_count = 0; /* Conditional branch instruction count. */
/* Assume all atomic sequences start with a lwarx/ldarx instruction. */
if ((insn & LWARX_MASK) != LWARX_INSTRUCTION
@@ -1111,24 +1110,20 @@ ppc_deal_with_atomic_sequence (struct frame_info *frame)
loc += PPC_INSN_SIZE;
insn = read_memory_integer (loc, PPC_INSN_SIZE, byte_order);
- /* Assume that there is at most one conditional branch in the atomic
- sequence. If a conditional branch is found, put a breakpoint in
- its destination address. */
if ((insn & BRANCH_MASK) == BC_INSN)
{
int immediate = ((insn & 0xfffc) ^ 0x8000) - 0x8000;
int absolute = insn & 2;
- if (bc_insn_count >= 1)
- return 0; /* More than one conditional branch found, fallback
+ if (last_breakpoint >= MAX_SINGLE_STEP_BREAKPOINTS - 1)
+ return 0; /* too many conditional branches found, fallback
to the standard single-step code. */
if (absolute)
- breaks[1] = immediate;
+ breaks[last_breakpoint] = immediate;
else
- breaks[1] = loc + immediate;
+ breaks[last_breakpoint] = loc + immediate;
- bc_insn_count++;
last_breakpoint++;
}
@@ -1147,18 +1142,29 @@ ppc_deal_with_atomic_sequence (struct frame_info *frame)
insn = read_memory_integer (loc, PPC_INSN_SIZE, byte_order);
/* Insert a breakpoint right after the end of the atomic sequence. */
- breaks[0] = loc;
+ breaks[last_breakpoint] = loc;
- /* Check for duplicated breakpoints. Check also for a breakpoint
- placed (branch instruction's destination) anywhere in sequence. */
- if (last_breakpoint
- && (breaks[1] == breaks[0]
- || (breaks[1] >= pc && breaks[1] <= closing_insn)))
- last_breakpoint = 0;
-
- /* Effectively inserts the breakpoints. */
for (index = 0; index <= last_breakpoint; index++)
- insert_single_step_breakpoint (gdbarch, aspace, breaks[index]);
+ {
+ int index2;
+ int insert_bp = 1;
+
+ /* Check for a breakpoint placed (branch instruction's destination)
+ anywhere in sequence. */
+ if (breaks[index] >= pc && breaks[index] <= closing_insn)
+ continue;
+
+ /* Check for duplicated breakpoints. */
+ for (index2 = 0; index2 < index; index2++)
+ {
+ if (breaks[index] == breaks[index2])
+ insert_bp = 0;
+ }
+
+ /* insert the breakpoint. */
+ if (insert_bp)
+ insert_single_step_breakpoint (gdbarch, aspace, breaks[index]);
+ }
return 1;
}
--
1.8.3.2
next prev parent reply other threads:[~2014-03-28 3:42 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-03-28 3:41 [PATCH 1/4] Fix ppc64 single step over atomic sequence testcase Anton Blanchard
2014-03-28 3:42 ` Anton Blanchard [this message]
2014-03-28 13:12 ` [PATCH 2/4] Support up to 3 conditional branches in an atomic sequence Joel Brobecker
2014-03-28 17:13 ` Pedro Alves
2014-03-28 17:22 ` Pedro Alves
2014-03-28 17:32 ` Joel Brobecker
2014-03-28 17:58 ` Pedro Alves
2014-03-28 18:10 ` Joel Brobecker
2014-03-28 3:42 ` [PATCH 3/4] Add multiple branches to ppc64 single step through atomic sequence testcase Anton Blanchard
2014-03-28 13:14 ` Joel Brobecker
2014-03-28 3:42 ` [PATCH 4/4] Add lbarx/stbcx., lharx/sthcx. and lqarx/stqcx. single stepping Anton Blanchard
2014-03-28 13:17 ` Joel Brobecker
2014-03-28 13:05 ` [PATCH 1/4] Fix ppc64 single step over atomic sequence testcase Joel Brobecker
2014-03-31 2:55 ` Anton Blanchard
2014-03-28 13:13 ` Ulrich Weigand
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=1395978111-30706-2-git-send-email-anton@samba.org \
--to=anton@samba.org \
--cc=brobecker@adacore.com \
--cc=emachado@linux.vnet.ibm.com \
--cc=gdb-patches@sourceware.org \
--cc=luis_gustavo@mentor.com \
--cc=ulrich.weigand@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