[binutils-gdb] gdb/riscv: Write 4-byte nop to dummy code region before inferior calls

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

[binutils-gdb] gdb/riscv: Write 4-byte nop to dummy code region before inferior calls

gdb-buildbot
*** TEST RESULTS FOR COMMIT 01e175fe1b21950982642713513e442fc09614e6 ***

commit 01e175fe1b21950982642713513e442fc09614e6
Author:     Andrew Burgess <[hidden email]>
AuthorDate: Fri Jul 19 10:34:47 2019 +0100
Commit:     Andrew Burgess <[hidden email]>
CommitDate: Fri Jul 19 21:00:22 2019 +0100

    gdb/riscv: Write 4-byte nop to dummy code region before inferior calls
   
    When making inferior function calls GDB sets up a dummy code region on
    the stack, and places a breakpoint within that region.  If the random
    stack contents appear to be a compressed instruction then GDB  will
    place a compressed breakpoint, which can cause problems if the target
    doesn't support compressed instructions.
   
    This commit prevents this issue by writing a 4-byte nop instruction to
    the dummy region at the time the region is allocated.  With this nop
    instruction in place, when we come to insert the breakpoint then an
    uncompressed breakpoint will be used.
   
    This is similar to other targets, for example mips.
   
    gdb/ChangeLog:
   
            * riscv-tdep.c (riscv_push_dummy_code): Write a 4-byte nop
            instruction to the dummy code region.
   
    gdb/testsuite/ChangeLog:
   
            * gdb.arch/riscv-bp-infcall.c: New file.
            * gdb.arch/riscv-bp-infcall.exp: New file.

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index c5a102f315..fb08d71f39 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,8 @@
+2019-07-19  Andrew Burgess  <[hidden email]>
+
+ * riscv-tdep.c (riscv_push_dummy_code): Write a 4-byte nop
+ instruction to the dummy code region.
+
 2019-07-19  Tom Tromey  <[hidden email]>
 
  * contrib/ari/gdb_ari.sh: Mention C++11, not ISO C 90.
diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c
index 7f3a1f6cbc..e4a66f1429 100644
--- a/gdb/riscv-tdep.c
+++ b/gdb/riscv-tdep.c
@@ -1621,11 +1621,44 @@ riscv_push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp,
        struct type *value_type, CORE_ADDR *real_pc,
        CORE_ADDR *bp_addr, struct regcache *regcache)
 {
+  /* A nop instruction is 'add x0, x0, 0'.  */
+  static const gdb_byte nop_insn[] = { 0x13, 0x00, 0x00, 0x00 };
+
   /* Allocate space for a breakpoint, and keep the stack correctly
-     aligned.  */
+     aligned.  The space allocated here must be at least big enough to
+     accommodate the NOP_INSN defined above.  */
   sp -= 16;
   *bp_addr = sp;
   *real_pc = funaddr;
+
+  /* When we insert a breakpoint we select whether to use a compressed
+     breakpoint or not based on the existing contents of the memory.
+
+     If the breakpoint is being placed onto the stack as part of setting up
+     for an inferior call from GDB, then the existing stack contents may
+     randomly appear to be a compressed instruction, causing GDB to insert
+     a compressed breakpoint.  If this happens on a target that does not
+     support compressed instructions then this could cause problems.
+
+     To prevent this issue we write an uncompressed nop onto the stack at
+     the location where the breakpoint will be inserted.  In this way we
+     ensure that we always use an uncompressed breakpoint, which should
+     work on all targets.
+
+     We call TARGET_WRITE_MEMORY here so that if the write fails we don't
+     throw an exception.  Instead we ignore the error and move on.  The
+     assumption is that either GDB will error later when actually trying to
+     insert a software breakpoint, or GDB will use hardware breakpoints and
+     there will be no need to write to memory later.  */
+  int status = target_write_memory (*bp_addr, nop_insn, sizeof (nop_insn));
+
+  if (riscv_debug_breakpoints || riscv_debug_infcall)
+    fprintf_unfiltered (gdb_stdlog,
+ "Writing %lld-byte nop instruction to %s: %s\n",
+ ((unsigned long long) sizeof (nop_insn)),
+ paddress (gdbarch, *bp_addr),
+ (status == 0 ? "success" : "failed"));
+
   return sp;
 }
 
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 4d7c4a7dff..5313470150 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2019-07-19  Andrew Burgess  <[hidden email]>
+
+ * gdb.arch/riscv-bp-infcall.c: New file.
+ * gdb.arch/riscv-bp-infcall.exp: New file.
+
 2019-07-17  Andrew Burgess  <[hidden email]>
 
  PR breakpoints/24541
diff --git a/gdb/testsuite/gdb.arch/riscv-bp-infcall.c b/gdb/testsuite/gdb.arch/riscv-bp-infcall.c
new file mode 100644
index 0000000000..9bd40af7ee
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-bp-infcall.c
@@ -0,0 +1,29 @@
+/* This file is part of GDB, the GNU debugger.
+
+   Copyright 2019 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+void
+dummy_call ()
+{
+  asm ("" ::: "memory");
+}
+
+int
+main ()
+{
+  dummy_call ();
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.arch/riscv-bp-infcall.exp b/gdb/testsuite/gdb.arch/riscv-bp-infcall.exp
new file mode 100644
index 0000000000..478032aebd
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-bp-infcall.exp
@@ -0,0 +1,56 @@
+# Copyright 2019 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test GDB for RISC-V always uses an uncompressed breakpoint when
+# setting up for an inferior call.
+
+if {![istarget "riscv*-*-*"]} {
+    verbose "Skipping ${gdb_test_file_name}."
+    return
+}
+
+standard_testfile
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile debug]} {
+    return -1
+}
+
+if ![runto_main] then {
+   fail "can't run to main"
+   return 0
+}
+
+# Figure out where the breakpoint will be placed taking account for
+# stack alignment, and allocation of the dummy code area.
+set bp_addr [get_valueof "/x" "\$sp" 0]
+set bp_addr [format 0x%x [expr ($bp_addr & ~0xf) - 0x20]]
+
+# Fill the region we know will be used as the scratch area with the
+# compressed nop instruction.  If GDB fails to overwrite this with an
+# uncompressed nop then a compressed breakpoint will be used in the
+# following inferior call.
+for {set i 0} {$i < 16} {incr i 2} {
+    gdb_test_no_output "set *((unsigned short *) (${bp_addr} + $i))=0x1" \
+ "place compressed nop in scratch area at offset $i"
+}
+
+# Make an inferior call.  GDB should write an uncompressed nop into
+# the scratch area and so force the use of an uncompressed breakpoint,
+# however, if this mechanism fails and GDB uses a compressed
+# breakpoint, and the target doesn't support compressed instructions,
+# then we would expect weird things to happen here.
+gdb_test_no_output "set debug riscv breakpoints 1"
+gdb_test "call dummy_call ()" \
+    ".*Using EBREAK for breakpoint at $bp_addr \\(instruction length 4\\).*"
Reply | Threaded
Open this post in threaded view
|

Failures on Fedora-x86_64-cc-with-index, branch master

gdb-buildbot
Buildername:
        Fedora-x86_64-cc-with-index

Worker:
        fedora-x86-64-4

Full Build URL:
        https://gdb-buildbot.osci.io/#builders/20/builds/347

Author:
        Andrew Burgess <[hidden email]>

Commit tested:
        01e175fe1b21950982642713513e442fc09614e6

Subject of commit:
        gdb/riscv: Write 4-byte nop to dummy code region before inferior calls

Testsuite logs (gdb.sum, gdb.log and others):
        https://gdb-buildbot.osci.io/results/Fedora-x86_64-cc-with-index/01/01e175fe1b21950982642713513e442fc09614e6/

*** Diff to previous build ***
==============================================
PASS -> KFAIL: gdb.threads/non-ldr-exit.exp: program exits normally
PASS -> KFAIL: gdb.threads/process-dies-while-handling-bp.exp: non_stop=on: cond_bp_target=1: inferior 1 exited
==============================================

*** Complete list of XFAILs for this builder ***

To obtain the list of XFAIL tests for this builder, go to:

        <https://gdb-buildbot.osci.io/results/Fedora-x86_64-cc-with-index/01/01e175fe1b21950982642713513e442fc09614e6//xfail.gz>

You can also see a pretty-printed version of the list, with more information
about each XFAIL, by going to:

        <https://gdb-buildbot.osci.io/results/Fedora-x86_64-cc-with-index/01/01e175fe1b21950982642713513e442fc09614e6//xfail.table.gz>

Reply | Threaded
Open this post in threaded view
|

Failures on Fedora-x86_64-m32, branch master

gdb-buildbot
In reply to this post by gdb-buildbot
Buildername:
        Fedora-x86_64-m32

Worker:
        fedora-x86-64-3

Full Build URL:
        https://gdb-buildbot.osci.io/#builders/17/builds/345

Author:
        Andrew Burgess <[hidden email]>

Commit tested:
        01e175fe1b21950982642713513e442fc09614e6

Subject of commit:
        gdb/riscv: Write 4-byte nop to dummy code region before inferior calls

Testsuite logs (gdb.sum, gdb.log and others):
        https://gdb-buildbot.osci.io/results/Fedora-x86_64-m32/01/01e175fe1b21950982642713513e442fc09614e6/

*** Diff to previous build ***
==============================================
PASS -> KFAIL: gdb.threads/process-dies-while-handling-bp.exp: non_stop=off: cond_bp_target=1: inferior 1 exited
==============================================

*** Complete list of XFAILs for this builder ***

To obtain the list of XFAIL tests for this builder, go to:

        <https://gdb-buildbot.osci.io/results/Fedora-x86_64-m32/01/01e175fe1b21950982642713513e442fc09614e6//xfail.gz>

You can also see a pretty-printed version of the list, with more information
about each XFAIL, by going to:

        <https://gdb-buildbot.osci.io/results/Fedora-x86_64-m32/01/01e175fe1b21950982642713513e442fc09614e6//xfail.table.gz>

Reply | Threaded
Open this post in threaded view
|

Failures on Fedora-x86_64-m64, branch master

gdb-buildbot
In reply to this post by gdb-buildbot
Buildername:
        Fedora-x86_64-m64

Worker:
        fedora-x86-64-4

Full Build URL:
        https://gdb-buildbot.osci.io/#builders/3/builds/370

Author:
        Andrew Burgess <[hidden email]>

Commit tested:
        01e175fe1b21950982642713513e442fc09614e6

Subject of commit:
        gdb/riscv: Write 4-byte nop to dummy code region before inferior calls

Testsuite logs (gdb.sum, gdb.log and others):
        https://gdb-buildbot.osci.io/results/Fedora-x86_64-m64/01/01e175fe1b21950982642713513e442fc09614e6/

*** Diff to previous build ***
==============================================
PASS -> KFAIL: gdb.threads/process-dies-while-handling-bp.exp: non_stop=on: cond_bp_target=1: inferior 1 exited
==============================================

*** Complete list of XFAILs for this builder ***

To obtain the list of XFAIL tests for this builder, go to:

        <https://gdb-buildbot.osci.io/results/Fedora-x86_64-m64/01/01e175fe1b21950982642713513e442fc09614e6//xfail.gz>

You can also see a pretty-printed version of the list, with more information
about each XFAIL, by going to:

        <https://gdb-buildbot.osci.io/results/Fedora-x86_64-m64/01/01e175fe1b21950982642713513e442fc09614e6//xfail.table.gz>

Reply | Threaded
Open this post in threaded view
|

Failures on Fedora-x86_64-native-gdbserver-m32, branch master

gdb-buildbot
In reply to this post by gdb-buildbot
Buildername:
        Fedora-x86_64-native-gdbserver-m32

Worker:
        fedora-x86-64-3

Full Build URL:
        https://gdb-buildbot.osci.io/#builders/24/builds/345

Author:
        Andrew Burgess <[hidden email]>

Commit tested:
        01e175fe1b21950982642713513e442fc09614e6

Subject of commit:
        gdb/riscv: Write 4-byte nop to dummy code region before inferior calls

Testsuite logs (gdb.sum, gdb.log and others):
        https://gdb-buildbot.osci.io/results/Fedora-x86_64-native-gdbserver-m32/01/01e175fe1b21950982642713513e442fc09614e6/

*** Diff to previous build ***
==============================================
PASS -> KFAIL: gdb.threads/process-dies-while-handling-bp.exp: non_stop=off: cond_bp_target=0: inferior 1 exited
==============================================

*** Complete list of XFAILs for this builder ***

To obtain the list of XFAIL tests for this builder, go to:

        <https://gdb-buildbot.osci.io/results/Fedora-x86_64-native-gdbserver-m32/01/01e175fe1b21950982642713513e442fc09614e6//xfail.gz>

You can also see a pretty-printed version of the list, with more information
about each XFAIL, by going to:

        <https://gdb-buildbot.osci.io/results/Fedora-x86_64-native-gdbserver-m32/01/01e175fe1b21950982642713513e442fc09614e6//xfail.table.gz>

Reply | Threaded
Open this post in threaded view
|

Failures on Fedora-x86_64-native-extended-gdbserver-m64, branch master

gdb-buildbot
In reply to this post by gdb-buildbot
Buildername:
        Fedora-x86_64-native-extended-gdbserver-m64

Worker:
        fedora-x86-64-2

Full Build URL:
        https://gdb-buildbot.osci.io/#builders/2/builds/347

Author:
        Andrew Burgess <[hidden email]>

Commit tested:
        01e175fe1b21950982642713513e442fc09614e6

Subject of commit:
        gdb/riscv: Write 4-byte nop to dummy code region before inferior calls

Testsuite logs (gdb.sum, gdb.log and others):
        https://gdb-buildbot.osci.io/results/Fedora-x86_64-native-extended-gdbserver-m64/01/01e175fe1b21950982642713513e442fc09614e6/

*** Diff to previous build ***
==============================================
FAIL -> UNRESOLVED: gdb.mi/mi-exec-run.exp: inferior-tty=main: mi=main: force-fail=1: run failure detected
FAIL -> UNRESOLVED: gdb.mi/mi-exec-run.exp: inferior-tty=main: mi=separate: force-fail=1: run failure detected
FAIL -> UNRESOLVED: gdb.mi/mi-exec-run.exp: inferior-tty=separate: mi=main: force-fail=1: run failure detected
FAIL -> UNRESOLVED: gdb.mi/mi-exec-run.exp: inferior-tty=separate: mi=separate: force-fail=1: run failure detected
==============================================

*** Complete list of XFAILs for this builder ***

To obtain the list of XFAIL tests for this builder, go to:

        <https://gdb-buildbot.osci.io/results/Fedora-x86_64-native-extended-gdbserver-m64/01/01e175fe1b21950982642713513e442fc09614e6//xfail.gz>

You can also see a pretty-printed version of the list, with more information
about each XFAIL, by going to:

        <https://gdb-buildbot.osci.io/results/Fedora-x86_64-native-extended-gdbserver-m64/01/01e175fe1b21950982642713513e442fc09614e6//xfail.table.gz>