From: Joel Brobecker <brobecker@adacore.com>
To: gdb-patches@sourceware.org
Cc: Joel Brobecker <brobecker@adacore.com>
Subject: [RFA] DWARF frame unwinder executes one too many rows
Date: Thu, 26 Jul 2012 22:51:00 -0000 [thread overview]
Message-ID: <1343343082-15401-1-git-send-email-brobecker@adacore.com> (raw)
The problem is trying to unwind from a function where %ebp is NOT
used as the frame pointer, and the size of the frame changes over
the lifetime of that function.
For instance, trying to unwind past the GNAT runtime function
called system.tasking.rendezvous.timed_selective_wait on x86-linux,
one can get:
(gdb) bt
[...]
#3 0x0805364b in system.tasking.rendezvous.timed_selective_wait ()
#4 0xb7fe5068 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
Looking at the CFI, we find the following initial instructions...
> DW_CFA_def_cfa: %esp+4 (r4 ofs 4)
> DW_CFA_offset: %eip at cfa-4 (r8 = %eip)
... and the associated FDE:
> 00001be4 00000054 00001be8 FDE cie=00000000 pc=08053310..08053951
[...]
> DW_CFA_advance_loc: 8 to 080534ad
> DW_CFA_def_cfa_offset: 112
> DW_CFA_advance_loc2: 414 to 0805364b
> DW_CFA_def_cfa_offset: 108
[...]
The problem is that the DWARF frame unwinder executed the FDE until
the row for PC == 0x0805364b. But in reality, our program hasn't
executed the instruction at that address yet (it is the return address).
So GDB executed a little too much of the FDE, giving us the wrong
offset for the frame base, and thus the wrong address where %eip
got saved.
This patch fixes the problem by using a more correct PC as the bound
for executing the FDE.
gdb/ChangeLog:
* dwarf2-frame.c (dwarf2_frame_cache): Use
get_frame_address_in_block instead of get_frame_pc as
the bound for executing the frame's FDE.
gdb/testsuite/ChangeLog:
* gdb.ada/rdv_wait: New testcase.
Tested on x86-linux, no regression.
OK to apply?
Thanks,
--
Joel
---
gdb/dwarf2-frame.c | 5 ++-
gdb/testsuite/gdb.ada/rdv_wait.exp | 32 +++++++++++++++++++
gdb/testsuite/gdb.ada/rdv_wait/foo.adb | 53 ++++++++++++++++++++++++++++++++
gdb/testsuite/gdb.ada/rdv_wait/pck.adb | 23 ++++++++++++++
gdb/testsuite/gdb.ada/rdv_wait/pck.ads | 22 +++++++++++++
5 files changed, 133 insertions(+), 2 deletions(-)
create mode 100644 gdb/testsuite/gdb.ada/rdv_wait.exp
create mode 100644 gdb/testsuite/gdb.ada/rdv_wait/foo.adb
create mode 100644 gdb/testsuite/gdb.ada/rdv_wait/pck.adb
create mode 100644 gdb/testsuite/gdb.ada/rdv_wait/pck.ads
diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c
index 01786ef..5d614a5 100644
--- a/gdb/dwarf2-frame.c
+++ b/gdb/dwarf2-frame.c
@@ -1054,7 +1054,8 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache)
/* First decode all the insns in the CIE. */
execute_cfa_program (fde, fde->cie->initial_instructions,
- fde->cie->end, gdbarch, get_frame_pc (this_frame), fs);
+ fde->cie->end, gdbarch,
+ get_frame_address_in_block (this_frame), fs);
/* Save the initialized register set. */
fs->initial = fs->regs;
@@ -1079,7 +1080,7 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache)
/* Then decode the insns in the FDE up to our target PC. */
execute_cfa_program (fde, instr, fde->end, gdbarch,
- get_frame_pc (this_frame), fs);
+ get_frame_address_in_block (this_frame), fs);
TRY_CATCH (ex, RETURN_MASK_ERROR)
{
diff --git a/gdb/testsuite/gdb.ada/rdv_wait.exp b/gdb/testsuite/gdb.ada/rdv_wait.exp
new file mode 100644
index 0000000..67e0f1e
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/rdv_wait.exp
@@ -0,0 +1,32 @@
+# Copyright 2012 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/>.
+
+load_lib "ada.exp"
+
+standard_ada_testfile foo
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug ]] != "" } {
+ return -1
+}
+
+clean_restart ${testfile}
+
+runto "break_me"
+
+# Switch to task 2, and verify that GDB is able to unwind all the way
+# to foo.T.
+gdb_test "task 2" \
+ [join {"\\\[Switching to task 2\\\].*" \
+ ".*foo\\.t \\(.*\\).*foo\\.adb:.*"} ""]
diff --git a/gdb/testsuite/gdb.ada/rdv_wait/foo.adb b/gdb/testsuite/gdb.ada/rdv_wait/foo.adb
new file mode 100644
index 0000000..cc3c22c
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/rdv_wait/foo.adb
@@ -0,0 +1,53 @@
+-- Copyright 2012 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/>.
+
+with Pck; use Pck;
+
+procedure Foo is
+
+ task type T is
+ entry Finish;
+ end T;
+ type TA is access T;
+
+ task body T is
+ begin
+ -- Wait for up to 100 seconds for the Finish Rendez-Vous to occur.
+ select
+ accept Finish do
+ null;
+ end Finish;
+ or
+ delay 100.0;
+ end select;
+ end T;
+
+ MIT : TA;
+
+begin
+
+ -- Create a task, and give it some time to activate and then start
+ -- its execution.
+ MIT := new T;
+ delay 0.01;
+
+ -- Now, call our anchor. The task we just created should now be
+ -- blocked on a timed entry wait.
+ Break_Me;
+
+ -- Tell the task to finish before the 100 seconds are up. The test
+ -- is now finished, no need to wait :).
+ MIT.Finish;
+end Foo;
diff --git a/gdb/testsuite/gdb.ada/rdv_wait/pck.adb b/gdb/testsuite/gdb.ada/rdv_wait/pck.adb
new file mode 100644
index 0000000..e5eebdc
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/rdv_wait/pck.adb
@@ -0,0 +1,23 @@
+-- Copyright 2012 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/>.
+
+package body Pck is
+
+ procedure Break_Me is
+ begin
+ null;
+ end Break_Me;
+
+end Pck;
diff --git a/gdb/testsuite/gdb.ada/rdv_wait/pck.ads b/gdb/testsuite/gdb.ada/rdv_wait/pck.ads
new file mode 100644
index 0000000..afe98f7
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/rdv_wait/pck.ads
@@ -0,0 +1,22 @@
+-- Copyright 2012 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/>.
+
+package Pck is
+
+ procedure Break_Me;
+ -- A procedure doing nothing, but which is a convenient anchor
+ -- for inserting breakpoints.
+
+end Pck;
--
1.7.1
next reply other threads:[~2012-07-26 22:51 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-07-26 22:51 Joel Brobecker [this message]
2012-07-27 11:07 ` asmwarrior
2012-07-27 11:15 ` asmwarrior
2012-07-27 12:14 ` Joel Brobecker
2012-07-30 17:43 ` Tom Tromey
2012-08-16 15:47 ` Joel Brobecker
2012-08-04 12:30 ` Jan Kratochvil
2012-08-06 14:05 ` Tom Tromey
2012-08-06 15:06 ` Jan Kratochvil
2012-08-06 15:10 ` Tom Tromey
2012-08-06 15:19 ` Jan Kratochvil
2012-08-17 18:14 ` [patch] testsuite: Test the unwinder off-by-one [Re: [RFA] DWARF frame unwinder executes one too many rows] Jan Kratochvil
2012-08-27 16:35 ` [commit] " Jan Kratochvil
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=1343343082-15401-1-git-send-email-brobecker@adacore.com \
--to=brobecker@adacore.com \
--cc=gdb-patches@sourceware.org \
/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