[v4,4/4] gdb: Skip trampoline frames in the stack for printing or finish command.

Message ID 20230801224744.24433-5-abdul.b.ijaz@intel.com
State New
Headers
Series GDB support for DW_AT_trampoline |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_gdb_build--master-arm success Testing passed
linaro-tcwg-bot/tcwg_gdb_check--master-arm success Testing passed

Commit Message

Abdul Basit Ijaz Aug. 1, 2023, 10:47 p.m. UTC
  Before the change, GDB prints the frames indicated by the compiler with DIE
"DW_AT_trampoline" in the backtrace and finish command, but for better user
experience, all such frames can be hidden from the user.  So, after this
change, now such frames are not printed any more in the backtrace command
and also the 'finish' command skips the trampoline calls.

So far, this DIE is added to DWARF only by the IFX compiler, so
gdb.fortran/mixed-lang-stack test used to fail for this compiler because of
these extra trampoline frames in the backtrace.  After the commit, those
trampoline frames are filtered so test is updated accordingly to handle the
frame level of the filtered frames.

Backtrace output in this test before the change:

bt -frame-arguments all
'''
'''
(gdb) FAIL: gdb.fortran/mixed-lang-stack.exp: lang=auto: bt -frame-arguments all

Now, after the change:
bt -frame-arguments all
'''
'''
(gdb) PASS: gdb.fortran/mixed-lang-stack.exp: lang=auto: bt -frame-arguments all

Below is the example where IFX emits DW_at_trampoline for functions first
and second trampoline calls as following:

F90 reproducer info:
function second (x, y) result(z)
  integer, intent(in) :: x, y
  integer :: z
  z = x * y ! breakpt-backtrace
end function second

function first (num1, num2) result(total)
  integer, intent(in) :: num1, num2
  integer  :: total
  total = second (num1 + 4, num2 * 3) ! first-breakpt
  total = total + 30
end function first

Related Dwarf:

0x0000013f:   DW_TAG_subprogram
                DW_AT_low_pc    (0x0000000000404350)
                DW_AT_high_pc   (0x000000000040435f)
                DW_AT_frame_base        (DW_OP_reg6 RBP)
                DW_AT_linkage_name      ("second_.t74p.t75p")
                DW_AT_name      ("second_.t74p.t75p")
                DW_AT_trampoline        ("second_")

0x0000015a:   DW_TAG_subprogram
                DW_AT_low_pc    (0x00000000004044a0)
                DW_AT_high_pc   (0x00000000004044af)
                DW_AT_frame_base        (DW_OP_reg6 RBP)
                DW_AT_linkage_name      ("first_.t104p.t105p")
                DW_AT_name      ("first_.t104p.t105p")
                DW_AT_trampoline        ("first_")

Before this change at line with comment 'breakpt-backtrace':
(gdb) backtrace 3
(gdb) finish
Run till exit from #0  second (x=20, y=9) at test.f90:4
second_.t74p.t75p () at test.f90:10
10        total = second (num1 + 4, num2 * 3) ! first-breakpt
Value returned is $1 = 180

After the change:
(gdb) backtrace 3
(gdb) finish
Run till exit from #0  second (x=20, y=9) at test.f90:4
0x0000000000404333 in first (num1=16, num2=3) at test.f90:10
10        total = second (num1 + 4, num2 * 3) ! first-breakpt
Value returned is $1 = 180

New test func-trampoline is also added to test this in both backtrace and
finish commands for Intel(R) Fortran Compiler.

2023-08-01 Abdul Basit Ijaz <abdul.b.ijaz@intel.com>
---
 gdb/doc/gdb.texinfo                           | 35 ++++++----
 gdb/infcmd.c                                  | 13 ++++
 gdb/infrun.c                                  |  8 +--
 gdb/infrun.h                                  |  6 ++
 gdb/stack.c                                   |  8 +++
 gdb/symtab.c                                  | 12 ++++
 gdb/symtab.h                                  |  5 ++
 gdb/testsuite/gdb.fortran/func-trampoline.exp | 69 +++++++++++++++++++
 gdb/testsuite/gdb.fortran/func-trampoline.f90 | 39 +++++++++++
 .../gdb.fortran/mixed-lang-stack.exp          | 10 ++-
 10 files changed, 186 insertions(+), 19 deletions(-)
 create mode 100644 gdb/testsuite/gdb.fortran/func-trampoline.exp
 create mode 100644 gdb/testsuite/gdb.fortran/func-trampoline.f90
  

Comments

Eli Zaretskii Aug. 2, 2023, 11:52 a.m. UTC | #1
> From: Abdul Basit Ijaz <abdul.b.ijaz@intel.com>
> Cc: abdul.b.ijaz@intel.com,
> 	JiniSusan.George@amd.com,
> 	tom@tromey.com,
> 	eliz@gnu.org,
> 	blarsen@redhat.com
> Date: Wed,  2 Aug 2023 00:47:44 +0200
> 
> Before the change, GDB prints the frames indicated by the compiler with DIE
> "DW_AT_trampoline" in the backtrace and finish command, but for better user
> experience, all such frames can be hidden from the user.  So, after this
> change, now such frames are not printed any more in the backtrace command
> and also the 'finish' command skips the trampoline calls.

Thanks, I believe I already approved the documentation parts of this,
right?
  
Terekhov, Mikhail via Gdb-patches Aug. 2, 2023, 11:54 a.m. UTC | #2
Hi Eli,
Yes nothing change in documentation since last patch you approved. Thanks

Best Regards
Abdul Basit

-----Original Message-----
From: Eli Zaretskii <eliz@gnu.org> 
Sent: Wednesday, August 2, 2023 1:53 PM
To: Ijaz, Abdul B <abdul.b.ijaz@intel.com>
Cc: gdb-patches@sourceware.org; Ijaz, Abdul B <abdul.b.ijaz@intel.com>; JiniSusan.George@amd.com; tom@tromey.com; blarsen@redhat.com
Subject: Re: [PATCH v4 4/4] gdb: Skip trampoline frames in the stack for printing or finish command.

> From: Abdul Basit Ijaz <abdul.b.ijaz@intel.com>
> Cc: abdul.b.ijaz@intel.com,
> 	JiniSusan.George@amd.com,
> 	tom@tromey.com,
> 	eliz@gnu.org,
> 	blarsen@redhat.com
> Date: Wed,  2 Aug 2023 00:47:44 +0200
> 
> Before the change, GDB prints the frames indicated by the compiler 
> with DIE "DW_AT_trampoline" in the backtrace and finish command, but 
> for better user experience, all such frames can be hidden from the 
> user.  So, after this change, now such frames are not printed any more 
> in the backtrace command and also the 'finish' command skips the trampoline calls.

Thanks, I believe I already approved the documentation parts of this, right?
Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928
  
Tom Tromey Aug. 2, 2023, 8:41 p.m. UTC | #3
>>>>> "Abdul" == Abdul Basit Ijaz via Gdb-patches <gdb-patches@sourceware.org> writes:

Abdul> Before the change, GDB prints the frames indicated by the compiler with DIE
Abdul> "DW_AT_trampoline" in the backtrace and finish command, but for better user
Abdul> experience, all such frames can be hidden from the user.  So, after this
Abdul> change, now such frames are not printed any more in the backtrace command
Abdul> and also the 'finish' command skips the trampoline calls.

Abdul> So far, this DIE is added to DWARF only by the IFX compiler, so
Abdul> gdb.fortran/mixed-lang-stack test used to fail for this compiler because of
Abdul> these extra trampoline frames in the backtrace.  After the commit, those
Abdul> trampoline frames are filtered so test is updated accordingly to handle the
Abdul> frame level of the filtered frames.

Thanks for the patch.

I'm not totally sure how I feel about the stack trace part of this one.

On the one hand, normally I think it makes sense to elide these frames.
They aren't very interesting.

On the other hand, we have frame filters for frame elision, but then
this works in a totally different way.

If I am stopped in a frame and go "up", will I be in the trampoline
frame anyway?  And will "bt" then not print the selected frame?  But
"frame" will?

Abdul> +  if (skip_trampoline_functions)
Abdul> +    {
Abdul> +      for (int i = 0; i < MAX_TRAMPOLINE_CHAIN_SIZE
Abdul> +		      && (frame != nullptr)
Abdul> +		      && in_trampoline_frame (frame); ++i)
Abdul> +	frame = get_prev_frame (frame);

Formatting looks weird here.

Abdul> +++ b/gdb/stack.c
Abdul> @@ -2054,6 +2054,14 @@ backtrace_command_1 (const frame_print_options &fp_opts,
Abdul>  	{
Abdul>  	  QUIT;
 
Abdul> +	  if (in_trampoline_frame (fi))
Abdul> +	    {
Abdul> +	      /* Trampoline frames are not printed so they are not counted in
Abdul> +		 the backtrace limit.  */
Abdul> +	      count++;
Abdul> +	      continue;

I guess the frame numbers will skip as well, because the frame level is
a property of the frame, not of the loop displaying frames.

Also this approach ignores frame filters -- if one is in use, then I
think trampoline frames will show up again.  You can try this by writing
a dummy frame filter that just returns all frames as-is.

Tom
  
Tom Tromey Aug. 2, 2023, 8:42 p.m. UTC | #4
>>>>> "Abdul" == Abdul Basit Ijaz via Gdb-patches <gdb-patches@sourceware.org> writes:

Abdul> @@ -1853,6 +1853,19 @@ finish_command (const char *arg, int from_tty)
Abdul>    if (frame == 0)
Abdul>      error (_("\"finish\" not meaningful in the outermost frame."));
 
Abdul> +  if (skip_trampoline_functions)
Abdul> +    {

I forgot to ask -- I don't really know much about this either, but does
this patch properly handle reverse finish?

thanks,
Tom
  
Terekhov, Mikhail via Gdb-patches Aug. 7, 2023, 7:19 a.m. UTC | #5
Hi Tom,

Thanks for the reply.

Tom> I forgot to ask -- I don't really know much about this either, but does this patch properly handle reverse finish?
 
In V4 it did not but will add in V5 reverse-finish so here it will also be working fine. Thanks for pointing this out. 

Best Regards,
Abdul Basit

-----Original Message-----
From: Tom Tromey <tom@tromey.com> 
Sent: Wednesday, August 2, 2023 10:43 PM
To: Abdul Basit Ijaz via Gdb-patches <gdb-patches@sourceware.org>
Cc: Ijaz, Abdul B <abdul.b.ijaz@intel.com>; JiniSusan.George@amd.com; tom@tromey.com; eliz@gnu.org; blarsen@redhat.com
Subject: Re: [PATCH v4 4/4] gdb: Skip trampoline frames in the stack for printing or finish command.

>>>>> "Abdul" == Abdul Basit Ijaz via Gdb-patches <gdb-patches@sourceware.org> writes:

Abdul> @@ -1853,6 +1853,19 @@ finish_command (const char *arg, int from_tty)
Abdul>    if (frame == 0)
Abdul>      error (_("\"finish\" not meaningful in the outermost 
Abdul> frame."));
 
Abdul> +  if (skip_trampoline_functions)
Abdul> +    {

I forgot to ask -- I don't really know much about this either, but does this patch properly handle reverse finish?

thanks,
Tom
Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928
  
Terekhov, Mikhail via Gdb-patches Aug. 7, 2023, 1:28 p.m. UTC | #6
Hi Tom,

Thanks for the feedback. Added replies below:

Tom> If I am stopped in a frame and go "up", will I be in the trampoline frame anyway?  And will "bt" then not print the selected frame?  But "frame" will?

Yes in current implementation bt will not print those trampoline frames and user may see from the frame number in bt since in output  frame numbers will be missing/elided for those trampoline calls. So "up" command will still take it to trampoline call. Do we need to handle "up" call ? . One sample run from program where first function call the second function and DW_at_trampoline exist for both of them.

22        second = x * y ! second-breakpt
(gdb) bt
#0  second (x=20, y=9) at db.fortran/func-trampoline.f90:22
#2  0x0000000000405203 in first (num1=16, num2=3) at gdb.fortran/func-trampoline.f90:29
#4  0x0000000000405254 in func_trampoline () at gdb.fortran/func-trampoline.f90:35
(gdb) up
#1  0x0000000000405229 in second_.t74p.t75p () at gdb.fortran/func-trampoline.f90:30
(gdb) frame 1
#1  0x0000000000405229 in second_.t74p.t75p () at gdb.fortran/func-trampoline.f90:30
30      end function

Tom > Also this approach ignores frame filters -- if one is in use, then I think trampoline frames will show up again.  You can try this by writing a dummy frame filter that just returns all frames as-is.

Yes in case of frame filter these trampolines frames are shown up.  Do we need to cover it in this change since I think we need to handle in such case in frame filter script or something need to be handled here for this ?

Thanks & Best Regards
Abdul Basit

-----Original Message-----
From: Tom Tromey <tom@tromey.com> 
Sent: Wednesday, August 2, 2023 10:42 PM
To: Abdul Basit Ijaz via Gdb-patches <gdb-patches@sourceware.org>
Cc: Ijaz, Abdul B <abdul.b.ijaz@intel.com>; JiniSusan.George@amd.com; tom@tromey.com; eliz@gnu.org; blarsen@redhat.com
Subject: Re: [PATCH v4 4/4] gdb: Skip trampoline frames in the stack for printing or finish command.

>>>>> "Abdul" == Abdul Basit Ijaz via Gdb-patches <gdb-patches@sourceware.org> writes:

Abdul> Before the change, GDB prints the frames indicated by the 
Abdul> compiler with DIE "DW_AT_trampoline" in the backtrace and finish 
Abdul> command, but for better user experience, all such frames can be 
Abdul> hidden from the user.  So, after this change, now such frames are 
Abdul> not printed any more in the backtrace command and also the 'finish' command skips the trampoline calls.

Abdul> So far, this DIE is added to DWARF only by the IFX compiler, so 
Abdul> gdb.fortran/mixed-lang-stack test used to fail for this compiler 
Abdul> because of these extra trampoline frames in the backtrace.  After 
Abdul> the commit, those trampoline frames are filtered so test is 
Abdul> updated accordingly to handle the frame level of the filtered frames.

Thanks for the patch.

I'm not totally sure how I feel about the stack trace part of this one.

On the one hand, normally I think it makes sense to elide these frames.
They aren't very interesting.

On the other hand, we have frame filters for frame elision, but then this works in a totally different way.

If I am stopped in a frame and go "up", will I be in the trampoline frame anyway?  And will "bt" then not print the selected frame?  But "frame" will?

Abdul> +  if (skip_trampoline_functions)
Abdul> +    {
Abdul> +      for (int i = 0; i < MAX_TRAMPOLINE_CHAIN_SIZE
Abdul> +		      && (frame != nullptr)
Abdul> +		      && in_trampoline_frame (frame); ++i)
Abdul> +	frame = get_prev_frame (frame);

Formatting looks weird here.

Abdul> +++ b/gdb/stack.c
Abdul> @@ -2054,6 +2054,14 @@ backtrace_command_1 (const frame_print_options &fp_opts,
Abdul>  	{
Abdul>  	  QUIT;
 
Abdul> +	  if (in_trampoline_frame (fi))
Abdul> +	    {
Abdul> +	      /* Trampoline frames are not printed so they are not counted in
Abdul> +		 the backtrace limit.  */
Abdul> +	      count++;
Abdul> +	      continue;

I guess the frame numbers will skip as well, because the frame level is a property of the frame, not of the loop displaying frames.

Also this approach ignores frame filters -- if one is in use, then I think trampoline frames will show up again.  You can try this by writing a dummy frame filter that just returns all frames as-is.

Tom
Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928
  
Tom Tromey Aug. 10, 2023, 5:45 p.m. UTC | #7
Tom> If I am stopped in a frame and go "up", will I be in the trampoline
Tom> frame anyway?  And will "bt" then not print the selected frame?
Tom> But "frame" will?

> Yes in current implementation bt will not print those trampoline
> frames and user may see from the frame number in bt since in output
> frame numbers will be missing/elided for those trampoline calls. So
> "up" command will still take it to trampoline call. Do we need to
> handle "up" call ?

I don't think so.
It's not handled for other elision cases.

Tom
  

Patch

diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 59a93f72895..e39db2e3156 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -6401,23 +6401,34 @@  so-called @dfn{trampoline functions}, which wrap the actual function call
 (the target of the trampoline).  The compiler might mark such a trampoline in
 its debug information.  Often, such trampolines do not have any source line
 information associated with them which will lead the @code{step} command to
-behave like a @code{next} and skip the function call completely.
+behave like a @code{next} and skip the function call completely.  Similarly,
+the @code{finish} command will return to some trampoline frame entry instead
+of returning to the call site.
 
 The default is @code{set skip-trampoline-functions on} and it will cause the
-@code{step} command to treat these trampolines differently.  When issuing a
-@code{step} at the call site of a trampoline function if
-@code{skip-trampoline-functions} is set @value{GDBN} will attempt to determine
+@code{step} and the @code{finish} command to treat these trampolines
+differently.
+
+When issuing a @code{step} at the call site of a trampoline function, if
+@code{skip-trampoline-functions} is set, @value{GDBN} will attempt to determine
 the target of the trampoline and then step through the trampoline stopping at
 the target.  If the target could not be found or was not given in the debug
 info, @value{GDBN} will simply continue execution until it leaves the
-trampoline code again, even if the trampoline has no line info associated with
-it.  When returning from a target function call and stepping back into the
-trampoline, @value{GDBN} will again step through the trampoline towards the
-call site.  Additionally, even if stopped in a trampoline function with source
-line information, issuing a @code{step} will prompt @value{GDBN} to resume
-execution until leaving the trampoline region again.  The @code{stepi} command
-is not affected by the setting which is enabled by default.  Currently, only
-DWARF trampolines marked via DW_AT_trampoline are supported by this.
+trampoline code again, even if the trampoline has no line info associated
+with it.  When returning from a target function call and stepping back into
+the trampoline, @value{GDBN} will again step through the trampoline towards
+the call site.  Additionally, even if stopped in a trampoline function with
+source line information, issuing a @code{step} will prompt @value{GDBN} to
+resume execution until leaving the trampoline region again.  The @code{stepi}
+command is not affected by the setting which is enabled by default.
+
+When issuing a @code{finish} command at the target of a trampoline function, if
+@code{skip-trampoline-functions} is set, @value{GDBN} will ignore all the
+trampoline frames and will reach the first non-trampoline frame to return to
+the call site of the current function.
+
+Currently, only DWARF trampolines marked via DW_AT_trampoline are supported by
+this.
 
 @item set skip-trampoline-functions off
 Causes the @code{step} command to completely ignore any trampoline information
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 15702f84894..e64ac5dfe43 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -1853,6 +1853,19 @@  finish_command (const char *arg, int from_tty)
   if (frame == 0)
     error (_("\"finish\" not meaningful in the outermost frame."));
 
+  if (skip_trampoline_functions)
+    {
+      for (int i = 0; i < MAX_TRAMPOLINE_CHAIN_SIZE
+		      && (frame != nullptr)
+		      && in_trampoline_frame (frame); ++i)
+	frame = get_prev_frame (frame);
+
+      if (frame == nullptr)
+	error (_("\"finish\" not meaningful in the outermost non-trampoline \
+frame.  Consider running \"set skip-trampoline-functions off\", to stop in \
+trampoline frames for the \"finish\" command."));
+    }
+
   clear_proceed_status (0);
 
   tp = inferior_thread ();
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 0ef9c76d3c6..42e96556e66 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -188,7 +188,7 @@  static bool detach_fork = true;
    DW_AT_trampoline by the compiler.  If false, GDB will ignore the
    attribute.  */
 
-static bool skip_trampoline_functions = true;
+bool skip_trampoline_functions = true;
 
 bool debug_infrun = false;
 static void
@@ -10211,9 +10211,9 @@  Options are 'forward' or 'reverse'."),
 			  &skip_trampoline_functions, _("\
 Set whether gdb attempts to hide trampolines marked in the debug info."), _("\
 Show whether gdb attempts to hide trampolines marked in the debug info."), _("\
-If on, while stepping gdb will skip through functions and inlined functions\n\
-marked as trampolines by the compiler.  If off, gdb will ignore such function\n\
-trampolines."),
+If on, the step and finish commands will skip through functions and inlined\n\
+functions marked as trampolines by the compiler.  If off, gdb will ignore\n\
+such function trampolines."),
 			  nullptr, show_skip_trampoline_functions, &setlist,
 			  &showlist);
 
diff --git a/gdb/infrun.h b/gdb/infrun.h
index d4a6b7892b5..feb5f4414ec 100644
--- a/gdb/infrun.h
+++ b/gdb/infrun.h
@@ -106,6 +106,12 @@  extern bool non_stop;
    starting an inferior.  */
 extern bool disable_randomization;
 
+/* If set (default) GDB will step through functions/inlined subroutines marked
+   DW_AT_trampoline by the compiler.  If false, GDB will ignore the
+   attribute.  */
+
+extern bool skip_trampoline_functions;
+
 /* Returns a unique identifier for the current stop.  This can be used
    to tell whether a command has proceeded the inferior past the
    current location.  */
diff --git a/gdb/stack.c b/gdb/stack.c
index 002bf580634..915ac398e09 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -2054,6 +2054,14 @@  backtrace_command_1 (const frame_print_options &fp_opts,
 	{
 	  QUIT;
 
+	  if (in_trampoline_frame (fi))
+	    {
+	      /* Trampoline frames are not printed so they are not counted in
+		 the backtrace limit.  */
+	      count++;
+	      continue;
+	    }
+
 	  /* Don't use print_stack_frame; if an error() occurs it probably
 	     means further attempts to backtrace would fail (on the other
 	     hand, perhaps the code does or could be fixed to make sure
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 745fd7d5d25..f396aca78c3 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -4066,6 +4066,18 @@  in_trampoline_function (CORE_ADDR pc)
 
 /* See symtab.h.  */
 
+bool
+in_trampoline_frame (frame_info_ptr fi)
+{
+  CORE_ADDR pc;
+  if (get_frame_pc_if_available (fi, &pc))
+    return in_trampoline_function (pc);
+
+  return false;
+}
+
+/* See symtab.h.  */
+
 CORE_ADDR
 find_function_trampoline_target (CORE_ADDR pc)
 {
diff --git a/gdb/symtab.h b/gdb/symtab.h
index fc2d82e6567..f02b3840f00 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -2317,6 +2317,11 @@  extern CORE_ADDR find_solib_trampoline_target (frame_info_ptr, CORE_ADDR);
 
 extern bool in_trampoline_function (CORE_ADDR pc);
 
+/* Return whether or not the pc of current frame is within a block that belongs
+   to a function that is marked as a trampoline by the compiler.  */
+
+extern bool in_trampoline_frame (frame_info_ptr);
+
 /* Find the target of a trampoline function marked via the DW_AT_trampoline
    attribute and return its address.  Returns 0 if the pc is not contained
    in a trampoline function (inlined or not).  If DW_AT_trampoline
diff --git a/gdb/testsuite/gdb.fortran/func-trampoline.exp b/gdb/testsuite/gdb.fortran/func-trampoline.exp
new file mode 100644
index 00000000000..3bc4d1c0714
--- /dev/null
+++ b/gdb/testsuite/gdb.fortran/func-trampoline.exp
@@ -0,0 +1,69 @@ 
+# Copyright 2023 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 finish and backtrace commands for functions with trampoline
+# calls.  Also checks if trampoline frames are filtered while printing
+# stack and finish command returns to real function.
+
+require allow_fortran_tests
+
+if {![test_compiler_info {ifx-*} f90]} {
+    untested "Test is only applicable for IFX where\
+	     compiler emits trampoline DIE in Dwarf"
+    return -1
+}
+
+standard_testfile ".f90"
+load_lib fortran.exp
+
+if {[prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \
+    {debug f90}]} {
+    return -1
+}
+
+if {![fortran_runto_main]} {
+    return -1
+}
+
+set inner_loc [gdb_get_line_number "second-breakpt"]
+set middle_loc [gdb_get_line_number "first-breakpt"]
+set outer_loc [gdb_get_line_number "main-outer-loc"]
+set fill "\[^\r\n\]*"
+
+set inner_desc  "second \\(x=20, y=9\\) at ${fill}$srcfile:$inner_loc"
+set middle_desc "first \\(num1=16, num2=3\\) at ${fill}$srcfile:$middle_loc"
+set outer_desc  ".* at .*$srcfile:$outer_loc"
+
+# Set breakpoint inside the innermost function 'second'.
+gdb_breakpoint "$srcfile:$inner_loc"
+gdb_continue_to_breakpoint "innermost-body" ".*$srcfile:$inner_loc.*"
+
+# Limit the backtrace to 3 frames and ensure both frames for first
+# and second function are shown only and trampoline frames are filtered.
+gdb_test "backtrace 3" [multi_line \
+    "#$decimal.* $inner_desc" \
+    "#$decimal.* $middle_desc" \
+    "#$decimal.* $outer_desc.*"] \
+"backtrace, test trampoline frames are filtered"
+
+# Finish the function calls.  Normally we expect to see a "Value
+# returned is ..." line.
+set value_returned "(\r\nValue returned is $valnum_re = 180)"
+
+gdb_test "finish" [multi_line \
+    "Run till exit from #0 $fill second \\(x=20, y=9\\) $fill" \
+    "${fill}first \\(num1=16, num2=3\\)${fill}" \
+    "${fill}${value_returned}"] \
+    "finish the innermost frame"
diff --git a/gdb/testsuite/gdb.fortran/func-trampoline.f90 b/gdb/testsuite/gdb.fortran/func-trampoline.f90
new file mode 100644
index 00000000000..652733b44fd
--- /dev/null
+++ b/gdb/testsuite/gdb.fortran/func-trampoline.f90
@@ -0,0 +1,39 @@ 
+! Copyright 2023 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/> .
+
+! Source code for func-trampoline.exp.
+
+integer(kind=4) function second(x, y)
+  integer(kind=4), intent(in) :: x
+  integer(kind=4), intent(in) :: y
+
+  second = x * y ! second-breakpt
+end function
+
+integer(kind=4) function first(num1, num2)
+  integer(kind=4), intent(in) :: num1
+  integer(kind=4), intent(in) :: num2
+
+  first = second (num1 + 4, num2 * 3) ! first-breakpt
+end function
+
+program func_trampoline
+  integer(kind=4) :: total
+
+  total = first(16, 3) ! main-outer-loc
+
+  write(*,*)  "Result is ", total, "\n"
+  ! Expected: 180
+end program func_trampoline
diff --git a/gdb/testsuite/gdb.fortran/mixed-lang-stack.exp b/gdb/testsuite/gdb.fortran/mixed-lang-stack.exp
index 5fc36f7b95b..71a171edcf0 100644
--- a/gdb/testsuite/gdb.fortran/mixed-lang-stack.exp
+++ b/gdb/testsuite/gdb.fortran/mixed-lang-stack.exp
@@ -41,7 +41,7 @@  set have_index [exec_has_index_section $binfile]
 # value to pass to GDB's 'set language ...' command.
 proc run_tests { lang } {
     with_test_prefix "lang=${lang}" {
-	global binfile hex have_index
+	global binfile hex have_index decimal
 
 	clean_restart ${binfile}
 
@@ -63,6 +63,10 @@  proc run_tests { lang } {
 	set e_arg "\['\"\]abcdef\['\"\]"
 	set 1b_args "\[^\r\n\]+$e_arg\[^\r\n\]+"
 	set 1g_args "obj=\[^\r\n\]+"
+	# Generic decimal number is checked in regex for Frame #8 and #9 to
+	# handle filtered trampoline frames.  Since Frame#8 and Frame#10 are
+	# set to trampoline in DWARF by Intel® Fortran Compiler (ifx), they
+	# are not shown by the backtrace command.
 	set bt_stack \
 	    [multi_line \
 		 "#0\\s+breakpt \\(\\) at \[^\r\n\]+" \
@@ -73,8 +77,8 @@  proc run_tests { lang } {
 		 "#5\\s+$hex in mixed_func_1d \\(\[^\r\n\]+\\) at \[^\r\n\]+" \
 		 "#6\\s+$hex in mixed_func_1c \\(\[^\r\n\]+\\) at \[^\r\n\]+" \
 		 "#7\\s+$hex in mixed_func_1b \\($1b_args\\) at \[^\r\n\]+" \
-		 "#8\\s+$hex in mixed_func_1a \\(\\) at \[^\r\n\]+" \
-		 "#9\\s+$hex in mixed_stack_main \\(\\) at \[^\r\n\]+" ]
+		 "#$decimal\\s+$hex in mixed_func_1a \\(\\) at \[^\r\n\]+" \
+		 "#$decimal\\s+$hex in mixed_stack_main \\(\\) at \[^\r\n\]+" ]
 	set main_args "argc=1, argv=${hex}( \[^\r\n\]+)?"
 	set bt_stack_kfail \
 	    [multi_line \