diff --git a/gdb/stack.c b/gdb/stack.c
index aa0257902e1..f60258fa9f2 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -1311,6 +1311,19 @@ find_frame_funname (const frame_info_ptr
&frame, enum language *funlang,
  return funname;

       bound_minimal_symbol msymbol = lookup_minimal_symbol_by_pc (pc);
+      if (msymbol.minsym == NULL)
+ {
+  /* pc may be at function entry (get_frame_address_in_block uses
pc-1); try pc+1.  */
+  msymbol = lookup_minimal_symbol_by_pc (pc + 1);
+ }
+      else
+ {
+  /* Prefer symbol at pc+1 (resume PC) when it is exactly at function
entry.  */
+  bound_minimal_symbol at_pc_plus_one = lookup_minimal_symbol_by_pc (pc + 1);
+  if (at_pc_plus_one.minsym != NULL
+      && at_pc_plus_one.value_address () == pc + 1)
+    msymbol = at_pc_plus_one;
+ }
       if (msymbol.minsym != NULL)
  {
   funname = make_unique_xstrdup (msymbol.minsym->print_name ());
diff --git a/gdb/testsuite/gdb.base/solib-bt-trampoline-lib.S
b/gdb/testsuite/gdb.base/solib-bt-trampoline-lib.S
new file mode 100644
index 00000000000..0273e1b471d
--- /dev/null
+++ b/gdb/testsuite/gdb.base/solib-bt-trampoline-lib.S
@@ -0,0 +1,24 @@
+/* Trampoline: run_then_exit + run_then_exit_return in one object.
+   When return address is exactly at run_then_exit_return entry, GDB
+   looks up pc-1 and without the fix shows "run_then_exit" or "??".  */
+ .text
+ .globl run_then_exit
+ .type  run_then_exit,@function
+ .globl run_then_exit_return
+ .type  run_then_exit_return,@function
+ .extern exit
+run_then_exit:
+ push   %ebp
+ mov    %esp, %ebp
+ call   .Lpic
+.Lpic:
+ pop    %eax
+ add    $(run_then_exit_return - .Lpic), %eax
+ push   12(%ebp)
+ push   %eax
+ jmp    *8(%ebp)
+ .size run_then_exit, .-run_then_exit
+run_then_exit_return:
+ push   $0
+ call   exit@PLT
+ .size run_then_exit_return, .-run_then_exit_return
diff --git a/gdb/testsuite/gdb.base/solib-bt-trampoline.c
b/gdb/testsuite/gdb.base/solib-bt-trampoline.c
new file mode 100644
index 00000000000..96e150e2279
--- /dev/null
+++ b/gdb/testsuite/gdb.base/solib-bt-trampoline.c
@@ -0,0 +1,21 @@
+/* Test program for run_then_exit trampoline.  Stops in user callback so that
+   "bt" in GDB shows the trampoline return frame: frame #1 should be
+   run_then_exit_return (not "??" or "run_then_exit").  */
+
+#include <stddef.h>
+
+extern void run_then_exit (void (*fn) (void *), void *arg);
+
+static void
+inner_func (void *arg)
+{
+  (void) arg;
+  return;  /* Break here and run "bt".  */
+}
+
+int
+main (void)
+{
+  run_then_exit (inner_func, NULL);
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/solib-bt-trampoline.exp
b/gdb/testsuite/gdb.base/solib-bt-trampoline.exp
new file mode 100644
index 00000000000..18418e8f121
--- /dev/null
+++ b/gdb/testsuite/gdb.base/solib-bt-trampoline.exp
@@ -0,0 +1,74 @@
+# Copyright 2026 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 that backtrace shows the correct function name for a solib frame
+# when the resume PC is exactly at function entry (trampoline that does
+# push return-address + jmp).  Without the fix, frame #1 shows "??" or
+# the previous function (run_then_exit) instead of run_then_exit_return.
+
+require allow_shlib_tests
+require {is_any_target "i?86-*-*" "x86_64-*-*"}
+
+standard_testfile solib-bt-trampoline.c
+set libsrc ${srcdir}/${subdir}/solib-bt-trampoline-lib.S
+set libname "solib-bt-trampoline-lib"
+set libfile [standard_output_file ${libname}.so]
+
+# Shared library: assembly only, no debug info (so minimal symbols are used).
+set lib_opts [list nodebug ldflags=-nostdlib libs=-lc]
+if {![istarget "i386-*-*"]} {
+    lappend lib_opts "additional_flags=-m32"
+}
+
+if {[gdb_compile_shlib $libsrc $libfile $lib_opts] != ""} {
+    untested "failed to compile shared library (need 32-bit toolchain
on x86_64?)"
+    return -1
+}
+
+set exec_opts [list debug shlib=$libfile
"additional_flags=-fno-omit-frame-pointer"]
+if {![istarget "i386-*-*"]} {
+    lappend exec_opts "additional_flags=-m32"
+}
+
+if {[gdb_compile $srcdir/$subdir/$srcfile $binfile executable
$exec_opts] != ""} {
+    untested "failed to compile executable"
+    return -1
+}
+
+clean_restart $testfile
+gdb_load_shlib $libfile
+
+if {![runto_main]} {
+    return -1
+}
+
+gdb_breakpoint "inner_func"
+# Pattern must match to end of line (e.g. solib-bt-trampoline.c:13)
so \r\n is next.
+set location_pattern "inner_func\[^\r\n\]*|solib-bt-trampoline\[^\r\n\]*"
+gdb_test_multiple "continue" "continue to breakpoint: inner_func" {
+    -re "(?:Breakpoint|Temporary breakpoint) .* (at|in)
$location_pattern\[\r\n\]+.*$gdb_prompt $" {
+ pass $gdb_test_name
+    }
+}
+
+# Frame #1 must be run_then_exit_return (not "??" or "run_then_exit").
+gdb_test_multiple "bt" "backtrace shows run_then_exit_return in frame 1" {
+    -re "#1\[^\r\n\]*run_then_exit_return" {
+ pass $gdb_test_name
