diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c
index 5ae9fb3..b7ccb32 100644
--- a/gdb/arch-utils.c
+++ b/gdb/arch-utils.c
@@ -243,6 +243,14 @@ default_remote_register_number (struct gdbarch *gdbarch,
   return regno;
 }

+/* See arch-utils.h.  */
+
+CORE_ADDR
+default_vsyscall_address (struct gdbarch *gdbarch)
+{
+  return 0;
+}
+
 
 /* Functions to manipulate the endianness of the target.  */

diff --git a/gdb/arch-utils.h b/gdb/arch-utils.h
index 46d1573..fc0ce53 100644
--- a/gdb/arch-utils.h
+++ b/gdb/arch-utils.h
@@ -174,4 +174,8 @@ extern int default_return_in_first_hidden_param_p (struct gdbarch *,
 extern int default_insn_is_call (struct gdbarch *, CORE_ADDR);
 extern int default_insn_is_ret (struct gdbarch *, CORE_ADDR);
 extern int default_insn_is_jump (struct gdbarch *, CORE_ADDR);
+
+/* Do-nothing version of vsyscall_address.  Returns 0.  */
+
+extern CORE_ADDR default_vsyscall_address (struct gdbarch *);
 #endif
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index b0ee79d..68b7a3e 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -316,6 +316,7 @@ struct gdbarch
   gdbarch_insn_is_ret_ftype *insn_is_ret;
   gdbarch_insn_is_jump_ftype *insn_is_jump;
   gdbarch_auxv_parse_ftype *auxv_parse;
+  gdbarch_vsyscall_address_ftype *vsyscall_address;
 };

 /* Create a new ``struct gdbarch'' based on information provided by
@@ -408,6 +409,7 @@ gdbarch_alloc (const struct gdbarch_info *info,
   gdbarch->insn_is_call = default_insn_is_call;
   gdbarch->insn_is_ret = default_insn_is_ret;
   gdbarch->insn_is_jump = default_insn_is_jump;
+  gdbarch->vsyscall_address = default_vsyscall_address;
   /* gdbarch_alloc() */

   return gdbarch;
@@ -627,6 +629,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of insn_is_ret, invalid_p == 0 */
   /* Skip verify of insn_is_jump, invalid_p == 0 */
   /* Skip verify of auxv_parse, has predicate.  */
+  /* Skip verify of vsyscall_address, invalid_p == 0 */
   buf = ui_file_xstrdup (log, &length);
   make_cleanup (xfree, buf);
   if (length > 0)
@@ -1296,6 +1299,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
                       "gdbarch_dump: virtual_frame_pointer = <%s>\n",
                       host_address_to_string (gdbarch->virtual_frame_pointer));
   fprintf_unfiltered (file,
+                      "gdbarch_dump: vsyscall_address = <%s>\n",
+                      host_address_to_string (gdbarch->vsyscall_address));
+  fprintf_unfiltered (file,
                       "gdbarch_dump: vtable_function_descriptors = %s\n",
                       plongest (gdbarch->vtable_function_descriptors));
   fprintf_unfiltered (file,
@@ -4403,6 +4409,23 @@ set_gdbarch_auxv_parse (struct gdbarch *gdbarch,
   gdbarch->auxv_parse = auxv_parse;
 }

+CORE_ADDR
+gdbarch_vsyscall_address (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->vsyscall_address != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_vsyscall_address called\n");
+  return gdbarch->vsyscall_address (gdbarch);
+}
+
+void
+set_gdbarch_vsyscall_address (struct gdbarch *gdbarch,
+                              gdbarch_vsyscall_address_ftype vsyscall_address)
+{
+  gdbarch->vsyscall_address = vsyscall_address;
+}
+

 /* Keep a registry of per-architecture data-pointers required by GDB
    modules.  */
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index 0303b2e..8f54405 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -1317,6 +1317,10 @@ typedef int (gdbarch_auxv_parse_ftype) (struct gdbarch *gdbarch, gdb_byte **read
 extern int gdbarch_auxv_parse (struct gdbarch *gdbarch, gdb_byte **readptr, gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp);
 extern void set_gdbarch_auxv_parse (struct gdbarch *gdbarch, gdbarch_auxv_parse_ftype *auxv_parse);

+typedef CORE_ADDR (gdbarch_vsyscall_address_ftype) (struct gdbarch *gdbarch);
+extern CORE_ADDR gdbarch_vsyscall_address (struct gdbarch *gdbarch);
+extern void set_gdbarch_vsyscall_address (struct gdbarch *gdbarch, gdbarch_vsyscall_address_ftype *vsyscall_address);
+
 /* Definition for an unknown syscall, used basically in error-cases.  */
 #define UNKNOWN_SYSCALL (-1)

diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index 2a8bca8..b6f0550 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -1029,6 +1029,9 @@ m:int:insn_is_jump:CORE_ADDR addr:addr::default_insn_is_jump::0
 # Return -1 if there is insufficient buffer for a whole entry.
 # Return 1 if an entry was read into *TYPEP and *VALP.
 M:int:auxv_parse:gdb_byte **readptr, gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp:readptr, endptr, typep, valp
+
+# Return the address of the current inferior's vsyscall/vDSO.
+m:CORE_ADDR:vsyscall_address:void:::default_vsyscall_address::0
 EOF
 }

diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
index dae59c5..00f0ed5 100644
--- a/gdb/linux-tdep.c
+++ b/gdb/linux-tdep.c
@@ -1782,6 +1782,18 @@ linux_gdb_signal_to_target (struct gdbarch *gdbarch,
   return -1;
 }

+/* Implementation of the "vsyscall_address" gdbarch hook.  */
+
+static CORE_ADDR
+linux_vsyscall_address (struct gdbarch *gdbarch)
+{
+  CORE_ADDR sysinfo_ehdr;
+
+  if (target_auxv_search (&current_target, AT_SYSINFO_EHDR, &sysinfo_ehdr) > 0)
+    return sysinfo_ehdr;
+  return 0;
+}
+
 /* To be called from the various GDB_OSABI_LINUX handlers for the
    various GNU/Linux architectures and machine types.  */

@@ -1799,6 +1811,7 @@ linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 				      linux_gdb_signal_from_target);
   set_gdbarch_gdb_signal_to_target (gdbarch,
 				    linux_gdb_signal_to_target);
+  set_gdbarch_vsyscall_address (gdbarch, linux_vsyscall_address);
 }

 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index 3deef20..af9a4ca 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -1462,10 +1462,11 @@ svr4_current_sos_direct (struct svr4_info *info)
   return head;
 }

-/* Implement the "current_sos" target_so_ops method.  */
+/* Implement the main part of the "current_sos" target_so_ops
+   method.  */

 static struct so_list *
-svr4_current_sos (void)
+svr4_current_sos_1 (void)
 {
   struct svr4_info *info = get_svr4_info ();

@@ -1478,6 +1479,42 @@ svr4_current_sos (void)
   return svr4_current_sos_direct (info);
 }

+/* Implement the "current_sos" target_so_ops method.  */
+
+static struct so_list *
+svr4_current_sos (void)
+{
+  struct so_list *so_head = svr4_current_sos_1 ();
+  struct objfile *objfile;
+  struct obj_section *osect;
+  CORE_ADDR vsyscall_addr = gdbarch_vsyscall_address (target_gdbarch ());
+
+  /* Filter out the vDSO module, if present.  Its symbol file would
+     not be found on disk.  The vDSO/vsyscall's OBJFILE is instead
+     managed by symfile-mem.c:add_vsyscall_page.  */
+  if (vsyscall_addr != 0)
+    {
+      struct so_list **sop;
+
+      sop = &so_head;
+      while (*sop != NULL)
+	{
+	  struct so_list *so = *sop;
+
+	  if (so->lm_info->l_addr_inferior == vsyscall_addr)
+	    {
+	      *sop = so->next;
+	      free_so (so);
+	      break;
+	    }
+
+	  sop = &so->next;
+	}
+    }
+
+  return so_head;
+}
+
 /* Get the address of the link_map for a given OBJFILE.  */

 CORE_ADDR
diff --git a/gdb/symfile-mem.c b/gdb/symfile-mem.c
index ef48f7d..073dec3 100644
--- a/gdb/symfile-mem.c
+++ b/gdb/symfile-mem.c
@@ -211,10 +211,9 @@ find_vdso_size (CORE_ADDR vaddr, unsigned long size,
 static void
 add_vsyscall_page (struct target_ops *target, int from_tty)
 {
-  CORE_ADDR sysinfo_ehdr;
+  CORE_ADDR sysinfo_ehdr = gdbarch_vsyscall_address (target_gdbarch ());

-  if (target_auxv_search (target, AT_SYSINFO_EHDR, &sysinfo_ehdr) > 0
-      && sysinfo_ehdr != (CORE_ADDR) 0)
+  if (sysinfo_ehdr != 0)
     {
       struct bfd *bfd;
       struct symbol_file_add_from_memory_args args;
diff --git a/gdb/testsuite/gdb.base/vdso-warning.c b/gdb/testsuite/gdb.base/vdso-warning.c
new file mode 100644
index 0000000..4b94803
--- /dev/null
+++ b/gdb/testsuite/gdb.base/vdso-warning.c
@@ -0,0 +1,22 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2014 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/>.  */
+
+int
+main (void)
+{
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/vdso-warning.exp b/gdb/testsuite/gdb.base/vdso-warning.exp
new file mode 100644
index 0000000..1f538fa
--- /dev/null
+++ b/gdb/testsuite/gdb.base/vdso-warning.exp
@@ -0,0 +1,54 @@
+# Copyright 2012-2014 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/>.
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" ${testfile} $srcfile] } {
+    return -1
+}
+
+gdb_breakpoint "main"
+
+# At least some versions of Fedora/RHEL glibc have local patches that
+# hide the vDSO.  This lines re-exposes it.  See PR libc/13097,
+# comment 2.  There's no support for passing environment variables in
+# the remote protocol, but that's OK -- if we're testing against a
+# glibc that doesn't list the vDSO without this, the test should still
+# pass.
+gdb_test_no_output "set environment LD_DEBUG=unused"
+
+gdb_run_cmd
+
+set test "stop without warning"
+gdb_test_multiple "" $test {
+    -re "Could not load shared library symbols .*\r\n$gdb_prompt $" {
+	fail $test
+    }
+    -re "\r\nBreakpoint \[0-9\]+, main .*\r\n$gdb_prompt $" {
+	pass $test
+    }
+}
+
+# Extra testing in case the warning changes and we miss updating the
+# above.
+set test "no vdso without symbols is listed"
+gdb_test_multiple "info shared" $test {
+    -re "No\[^\r\n\]+linux-(vdso|gate).*$gdb_prompt $" {
+	fail $test
+    }
+    -re "$gdb_prompt $" {
+	pass $test
+    }
+}
