diff --git a/gdb/amd64fbsd-nat.c b/gdb/amd64fbsd-nat.c
index 762b13f..ca962e1 100644
--- a/gdb/amd64fbsd-nat.c
+++ b/gdb/amd64fbsd-nat.c
@@ -140,6 +140,62 @@ amd64fbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
 }
 
 
+static int
+amd64fbsd_get_signal_trampoline (struct target_ops *ops,
+				 struct mem_range *range)
+{
+#ifdef KERN_PROC_SIGTRAMP
+  /* FreeBSD 9.2 and later provide a kern.proc.sigtramp.<pid>
+     sysctl that returns the location of the signal trampoline.  */
+  {
+    int mib[4];
+    struct kinfo_sigtramp kst;
+    size_t len;
+
+    mib[0] = CTL_KERN;
+    mib[1] = KERN_PROC;
+    mib[2] = KERN_PROC_SIGTRAMP;
+    mib[3] = ptid_get_pid (inferior_ptid);
+    len = sizeof (kst);
+    if (sysctl (mib, 4, &kst, &len, NULL, 0) == 0)
+      {
+	CORE_ADDR start_addr = (uintptr_t) kst.ksigtramp_start;
+	CORE_ADDR end_addr = (uintptr_t) kst.ksigtramp_end;
+
+	range->start = start_addr;
+	range->length = end_addr - start_addr;
+	return 1;
+      }
+  }
+#else
+  /* FreeBSD provides a kern.ps_strings sysctl that we can use to
+     locate the sigtramp.  That way we can still recognize a sigtramp
+     if its location is changed in a new kernel.  Of course this is
+     still based on the assumption that the sigtramp is placed
+     directly under the location where the program arguments and
+     environment can be found.  */
+  {
+    int mib[2];
+    long ps_strings;
+    size_t len;
+
+    mib[0] = CTL_KERN;
+    mib[1] = KERN_PS_STRINGS;
+    len = sizeof (ps_strings);
+    if (sysctl (mib, 2, &ps_strings, &len, NULL, 0) == 0)
+      {
+	CORE_ADDR start_addr = ps_strings - 32;
+	CORE_ADDR end_addr = ps_strings;
+
+	range->start = start_addr;
+	range->length = end_addr - start_addr;
+	return 1;
+      }
+  }
+#endif
+  return 0;
+}
+
 static void (*super_mourn_inferior) (struct target_ops *ops);
 
 static void
@@ -166,6 +222,8 @@ _initialize_amd64fbsd_nat (void)
   /* Add some extra features to the common *BSD/i386 target.  */
   t = amd64bsd_target ();
 
+  t->to_get_signal_trampoline = amd64fbsd_get_signal_trampoline;
+
 #ifdef HAVE_PT_GETDBREGS
 
   x86_use_watchpoints (t);
@@ -244,49 +302,4 @@ Please report this to <bug-gdb@gnu.org>."),
     }
 
   SC_RBP_OFFSET = offset;
-
-#ifdef KERN_PROC_SIGTRAMP
-  /* FreeBSD 9.2 and later provide a kern.proc.sigtramp.<pid>
-     sysctl that returns the location of the signal trampoline.
-     Note that this fetches the address for the current (gdb) process.
-     This will be correct for other 64-bit processes, but the signal
-     trampoline location is not properly set for 32-bit processes.  */
-  {
-    int mib[4];
-    struct kinfo_sigtramp kst;
-    size_t len;
-
-    mib[0] = CTL_KERN;
-    mib[1] = KERN_PROC;
-    mib[2] = KERN_PROC_SIGTRAMP;
-    mib[3] = getpid ();
-    len = sizeof (kst);
-    if (sysctl (mib, 4, &kst, &len, NULL, 0) == 0)
-      {
-	amd64fbsd_sigtramp_start_addr = (uintptr_t) kst.ksigtramp_start;
-	amd64fbsd_sigtramp_end_addr = (uintptr_t) kst.ksigtramp_end;
-      }
-  }
-#else
-  /* FreeBSD provides a kern.ps_strings sysctl that we can use to
-     locate the sigtramp.  That way we can still recognize a sigtramp
-     if its location is changed in a new kernel.  Of course this is
-     still based on the assumption that the sigtramp is placed
-     directly under the location where the program arguments and
-     environment can be found.  */
-  {
-    int mib[2];
-    long ps_strings;
-    size_t len;
-
-    mib[0] = CTL_KERN;
-    mib[1] = KERN_PS_STRINGS;
-    len = sizeof (ps_strings);
-    if (sysctl (mib, 2, &ps_strings, &len, NULL, 0) == 0)
-      {
-	amd64fbsd_sigtramp_start_addr = ps_strings - 32;
-	amd64fbsd_sigtramp_end_addr = ps_strings;
-      }
-  }
-#endif
 }
diff --git a/gdb/amd64fbsd-tdep.c b/gdb/amd64fbsd-tdep.c
index abb0cab..69cd186 100644
--- a/gdb/amd64fbsd-tdep.c
+++ b/gdb/amd64fbsd-tdep.c
@@ -87,10 +87,6 @@ static int amd64fbsd_r_reg_offset[] =
   -1				/* %gs */
 };
 
-/* Location of the signal trampoline.  */
-CORE_ADDR amd64fbsd_sigtramp_start_addr = 0x7fffffffffc0ULL;
-CORE_ADDR amd64fbsd_sigtramp_end_addr = 0x7fffffffffe0ULL;
-
 /* From <machine/signal.h>.  */
 int amd64fbsd_sc_reg_offset[] =
 {
@@ -182,6 +178,26 @@ amd64fbsd_collect_uthread (const struct regcache *regcache,
     }
 }
 
+/* Return whether THIS_FRAME corresponds to a NetBSD sigtramp
+   routine.  */
+
+static int
+amd64fbsd_sigtramp_p (struct frame_info *this_frame)
+{
+  struct mem_range range;
+  CORE_ADDR pc;
+
+  if (!target_get_signal_trampoline (&range))
+    {
+      /* Fallback to hardcoded location...  */
+      range.start = 0x7fffffffffc0ULL;
+      range.length = 0x7fffffffffe0ULL - range.start;
+    }
+
+  pc = get_frame_pc (this_frame);
+  return address_in_mem_range (pc, &range);
+}
+
 static void
 amd64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
@@ -199,8 +215,7 @@ amd64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 
   amd64_init_abi (info, gdbarch);
 
-  tdep->sigtramp_start = amd64fbsd_sigtramp_start_addr;
-  tdep->sigtramp_end = amd64fbsd_sigtramp_end_addr;
+  tdep->sigtramp_p = amd64fbsd_sigtramp_p;
   tdep->sigcontext_addr = amd64fbsd_sigcontext_addr;
   tdep->sc_reg_offset = amd64fbsd_sc_reg_offset;
   tdep->sc_num_regs = ARRAY_SIZE (amd64fbsd_sc_reg_offset);
diff --git a/gdb/target-debug.h b/gdb/target-debug.h
index 63ce12c..f114a07 100644
--- a/gdb/target-debug.h
+++ b/gdb/target-debug.h
@@ -193,4 +193,12 @@ target_debug_print_signals (unsigned char *sigs)
   fputs_unfiltered (" }", gdb_stdlog);
 }
 
+static void
+target_debug_print_struct_mem_range_p (struct mem_range *range)
+{
+  fprintf_unfiltered (gdb_stdlog, "[%s:%x]",
+		      paddress (target_gdbarch (), range->start),
+		      range->length);
+}
+
 #endif /* TARGET_DEBUG_H */
diff --git a/gdb/target-delegates.c b/gdb/target-delegates.c
index e026179..4f9cb72 100644
--- a/gdb/target-delegates.c
+++ b/gdb/target-delegates.c
@@ -3764,6 +3764,35 @@ debug_done_generating_core (struct target_ops *self)
   fputs_unfiltered (")\n", gdb_stdlog);
 }
 
+static int
+delegate_get_signal_trampoline (struct target_ops *self, struct mem_range *arg1)
+{
+  self = self->beneath;
+  return self->to_get_signal_trampoline (self, arg1);
+}
+
+static int
+tdefault_get_signal_trampoline (struct target_ops *self, struct mem_range *arg1)
+{
+  return 0;
+}
+
+static int
+debug_get_signal_trampoline (struct target_ops *self, struct mem_range *arg1)
+{
+  int result;
+  fprintf_unfiltered (gdb_stdlog, "-> %s->to_get_signal_trampoline (...)\n", debug_target.to_shortname);
+  result = debug_target.to_get_signal_trampoline (&debug_target, arg1);
+  fprintf_unfiltered (gdb_stdlog, "<- %s->to_get_signal_trampoline (", debug_target.to_shortname);
+  target_debug_print_struct_target_ops_p (&debug_target);
+  fputs_unfiltered (", ", gdb_stdlog);
+  target_debug_print_struct_mem_range_p (arg1);
+  fputs_unfiltered (") = ", gdb_stdlog);
+  target_debug_print_int (result);
+  fputs_unfiltered ("\n", gdb_stdlog);
+  return result;
+}
+
 static void
 install_delegators (struct target_ops *ops)
 {
@@ -4045,6 +4074,8 @@ install_delegators (struct target_ops *ops)
     ops->to_prepare_to_generate_core = delegate_prepare_to_generate_core;
   if (ops->to_done_generating_core == NULL)
     ops->to_done_generating_core = delegate_done_generating_core;
+  if (ops->to_get_signal_trampoline == NULL)
+    ops->to_get_signal_trampoline = delegate_get_signal_trampoline;
 }
 
 static void
@@ -4189,6 +4220,7 @@ install_dummy_methods (struct target_ops *ops)
   ops->to_decr_pc_after_break = default_target_decr_pc_after_break;
   ops->to_prepare_to_generate_core = tdefault_prepare_to_generate_core;
   ops->to_done_generating_core = tdefault_done_generating_core;
+  ops->to_get_signal_trampoline = tdefault_get_signal_trampoline;
 }
 
 static void
@@ -4333,4 +4365,5 @@ init_debug_target (struct target_ops *ops)
   ops->to_decr_pc_after_break = debug_decr_pc_after_break;
   ops->to_prepare_to_generate_core = debug_prepare_to_generate_core;
   ops->to_done_generating_core = debug_done_generating_core;
+  ops->to_get_signal_trampoline = debug_get_signal_trampoline;
 }
diff --git a/gdb/target.h b/gdb/target.h
index fb60123..e509e5e 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -1141,6 +1141,15 @@ struct target_ops
     void (*to_done_generating_core) (struct target_ops *)
       TARGET_DEFAULT_IGNORE ();
 
+    /* Return the current target's signal trampoline address range.
+       Return true on success, false if the information isn't
+       available.  This is implemented on targets that need to query
+       the kernel for this information.  Most ports we get at this
+       information through gdbarch/osabi instead.  */
+    int (*to_get_signal_trampoline) (struct target_ops *ops,
+				     struct mem_range *range)
+      TARGET_DEFAULT_RETURN (0);
+
     int to_magic;
     /* Need sub-structure for target machine related rather than comm related?
      */
@@ -2055,6 +2064,9 @@ extern int simple_verify_memory (struct target_ops* ops,
 int target_verify_memory (const gdb_byte *data,
 			  CORE_ADDR memaddr, ULONGEST size);
 
+#define target_get_signal_trampoline(range)				\
+  (*current_target.to_get_signal_trampoline) (&current_target, range)
+
 /* Routines for maintenance of the target structures...
 
    complete_target_initialization: Finalize a target_ops by filling in
