aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite/gdb.dwarf2/dw2-step-between-different-inline-functions.c
diff options
context:
space:
mode:
authorBernd Edlinger <bernd.edlinger@hotmail.de>2024-10-15 18:14:12 +0100
committerAndrew Burgess <aburgess@redhat.com>2024-11-13 13:50:21 +0000
commit5d9887ffa2628ef93bc3cddd58e6c374b2a16ca7 (patch)
tree8e9f4171e354b94f2ca674a598531152d2920a62 /gdb/testsuite/gdb.dwarf2/dw2-step-between-different-inline-functions.c
parentb9de07a5ff74663ff39bf03632d1b2ea417bf8d5 (diff)
downloadbinutils-5d9887ffa2628ef93bc3cddd58e6c374b2a16ca7.zip
binutils-5d9887ffa2628ef93bc3cddd58e6c374b2a16ca7.tar.gz
binutils-5d9887ffa2628ef93bc3cddd58e6c374b2a16ca7.tar.bz2
gdb: stepping between inline functions with multiple ranges
I (Andrew) have split this small change from a larger patch which was posted here: https://inbox.sourceware.org/gdb-patches/AS1PR01MB9465608EBD5D62642C51C428E4922@AS1PR01MB9465.eurprd01.prod.exchangelabs.com And I have written the stand alone test for this issue. The original patch included this paragraph to explain this change (I've fixed one typo in this text replacing 'program' with 'function'): ... it may happen that the infrun machinery steps from one inline range to another inline range of the same inline function. That can look like jumping back and forth from the calling function to the inline function, while really the inline function just jumps from a hot to a cold section of the code, i.e. error handling. The important thing that happens here is that both the outer function and the inline function must both have multiple ranges. When the inferior is within the inline function and moves from one range to another it is critical that the address we stop at is the start of a range in both the outer function and the inline function. The diagram below represents how the functions are split and aligned: (A) (B) bar: |------------| |---| foo: |------------------| |--------| The inferior is stepping through 'bar' and eventually reaches point (A) at which point control passes to point (B). Currently, when the inferior stops, GDB notices that both 'foo' and 'bar' start at address (B), and so GDB uses the inline frame mechanism to skip 'bar' and tells the user that the inferior is in 'foo'. However, as we were in 'bar' before the step then it makes sense that we should be in 'bar' after the step, and this is what the patch does. There are two tests using the DWARF assembler, the first checks the above situation and ensures that GDB reports 'bar' after the step. The second test is similar, but after the step we enter a new range where a different inline function starts, something like this: (A) (B) bar: |------------| baz: |---| foo: |------------------| |--------| In this case as we step at (A) and land at (B) we leave 'bar' and expect to stop in 'foo', GDB shouldn't automatically enter 'baz' as that is a completely different inline function. And this is, indeed, what we see. Co-Authored-By: Andrew Burgess <aburgess@redhat.com>
Diffstat (limited to 'gdb/testsuite/gdb.dwarf2/dw2-step-between-different-inline-functions.c')
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-step-between-different-inline-functions.c105
1 files changed, 105 insertions, 0 deletions
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-step-between-different-inline-functions.c b/gdb/testsuite/gdb.dwarf2/dw2-step-between-different-inline-functions.c
new file mode 100644
index 0000000..5e4fe47
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-step-between-different-inline-functions.c
@@ -0,0 +1,105 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2024 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/>. */
+
+/* Used to insert labels within function foo. */
+#define LABEL(N) asm ("foo_label_" #N ": .globl foo_label_" #N)
+
+volatile int global_var = 0;
+
+/* The contents of this '#if 0' block exist so the generated debug can
+ point to these as the source lines. */
+#if 0
+
+void
+bar (void) /* bar decl line */
+{
+ /* bar line 1 */
+ /* bar line 2 */
+}
+
+void
+baz (void) /* baz decl line */
+{
+ /* baz line 1 */
+ /* baz line 2 */
+}
+
+void
+foo (void) /* foo decl line */
+{
+ /* foo line 1 */
+ /* foo line 2 */
+ /* foo line 3 */
+ /* foo line 4 */
+}
+
+#endif
+
+extern void *foo_label_6 (void);
+
+void
+foo (void)
+{
+ /* This label is used to find the start of 'foo' when generating the
+ debug information. */
+ asm ("foo_label: .globl foo_label");
+ ++global_var;
+
+ LABEL (1);
+ ++global_var;
+
+ LABEL (2);
+ ++global_var;
+
+ LABEL (3);
+ ++global_var;
+
+ /* This goto will always trigger, but we make it conditional so that the
+ compiler doesn't optimise out the code between the goto and the
+ destination.
+
+ Also 'goto *ADDR' is a GCC extension, but it is critical that the
+ destination address be a global label so that we can generate DWARF
+ that has ranges that start exactly at the destination address. */
+ if (global_var > 0)
+ goto *(&foo_label_6);
+
+ LABEL (4);
+ ++global_var;
+
+ LABEL (5);
+ ++global_var;
+
+ LABEL (6);
+ ++global_var;
+
+ LABEL (7);
+ ++global_var;
+
+ LABEL (8);
+ ++global_var;
+
+ LABEL (9);
+ ++global_var;
+}
+
+int
+main (void)
+{
+ asm ("main_label: .globl main_label");
+ foo ();
+}