diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 23c8895..e6cda4e 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -2665,8 +2665,8 @@ insert_bp_location (struct bp_location *bl,
 	  if ((bp_err == GENERIC_ERROR || bp_err == MEMORY_ERROR)
 	      && bl->loc_type == bp_loc_software_breakpoint
 	      && (solib_name_from_address (bl->pspace, bl->address)
-		  || userloaded_objfile_contains_address_p (bl->pspace,
-							    bl->address)))
+		  || shared_objfile_contains_address_p (bl->pspace,
+							bl->address)))
 	    {
 	      /* See also: disable_breakpoints_in_shlibs.  */
 	      bl->shlib_disabled = 1;
@@ -3805,7 +3805,7 @@ remove_breakpoint_1 (struct bp_location *bl, insertion_state_t is)
 	     whether another dynamic object might have loaded over the
 	     breakpoint's address -- the user might well let us know
 	     about it next with add-symbol-file (the whole point of
-	     OBJF_USERLOADED is letting the user manually maintain a
+	     add-symbol-file is letting the user manually maintain a
 	     list of dynamically loaded objects).  If we have the
 	     breakpoint's shadow memory, that is, this is a software
 	     breakpoint managed by GDB, check whether the breakpoint
@@ -3878,8 +3878,8 @@ remove_breakpoint_1 (struct bp_location *bl, insertion_state_t is)
 	  && (bl->loc_type == bp_loc_software_breakpoint
 	      && (bl->shlib_disabled
 		  || solib_name_from_address (bl->pspace, bl->address)
-		  || userloaded_objfile_contains_address_p (bl->pspace,
-							    bl->address))))
+		  || shared_objfile_contains_address_p (bl->pspace,
+							bl->address))))
 	val = 0;
 
       if (val)
@@ -7729,18 +7729,19 @@ disable_breakpoints_in_freed_objfile (struct objfile *objfile)
   if (objfile == NULL)
     return;
 
-  /* OBJF_USERLOADED are dynamic modules manually managed by the user
-     with add-symbol-file/remove-symbol-file.  Similarly to how
-     breakpoints in shared libraries are handled in response to
-     "nosharedlibrary", mark breakpoints in OBJF_USERLOADED modules
+  /* OBJF_SHARED|OBJF_USERLOADED objfiles are dynamic modules manually
+     managed by the user with add-symbol-file/remove-symbol-file.
+     Similarly to how breakpoints in shared libraries are handled in
+     response to "nosharedlibrary", mark breakpoints in such modules
      shlib_disabled so they end up uninserted on the next global
      location list update.  Shared libraries not loaded by the user
      aren't handled here -- they're already handled in
      disable_breakpoints_in_unloaded_shlib, called by solib.c's
      solib_unloaded observer.  We skip objfiles that are not
-     OBJF_USERLOADED (nor OBJF_SHARED) as those aren't considered
-     dynamic objects (e.g. the main objfile).  */
-  if ((objfile->flags & OBJF_USERLOADED) == 0)
+     OBJF_SHARED as those aren't considered dynamic objects (e.g. the
+     main objfile).  */
+  if ((objfile->flags & OBJF_SHARED) == 0
+      || (objfile->flags & OBJF_USERLOADED) == 0)
     return;
 
   ALL_BREAKPOINTS (b)
diff --git a/gdb/objfiles.c b/gdb/objfiles.c
index 81bbf24..a86e8bc 100644
--- a/gdb/objfiles.c
+++ b/gdb/objfiles.c
@@ -1454,14 +1454,14 @@ is_addr_in_objfile (CORE_ADDR addr, const struct objfile *objfile)
 }
 
 int
-userloaded_objfile_contains_address_p (struct program_space *pspace,
-				       CORE_ADDR address)
+shared_objfile_contains_address_p (struct program_space *pspace,
+				   CORE_ADDR address)
 {
   struct objfile *objfile;
 
   ALL_PSPACE_OBJFILES (pspace, objfile)
     {
-      if ((objfile->flags & OBJF_USERLOADED) != 0
+      if ((objfile->flags & OBJF_SHARED) != 0
 	  && is_addr_in_objfile (address, objfile))
 	return 1;
     }
diff --git a/gdb/objfiles.h b/gdb/objfiles.h
index 6684278..57a94e1 100644
--- a/gdb/objfiles.h
+++ b/gdb/objfiles.h
@@ -427,12 +427,9 @@ struct objfile
 #define OBJF_REORDERED	(1 << 0)	/* Functions are reordered */
 
 /* Distinguish between an objfile for a shared library and a "vanilla"
-   objfile.  (If not set, the objfile may still actually be a solib.
-   This can happen if the user created the objfile by using the
-   add-symbol-file command.  GDB doesn't in that situation actually
-   check whether the file is a solib.  Rather, the target's
-   implementation of the solib interface is responsible for setting
-   this flag when noticing solibs used by an inferior.)  */
+   objfile.  This may come from a target's implementation of the solib
+   interface, from add-symbol-file, or any other mechanism that loads
+   dynamic objects.  */
 
 #define OBJF_SHARED     (1 << 1)	/* From a shared library */
 
@@ -515,12 +512,11 @@ extern void objfiles_changed (void);
 
 extern int is_addr_in_objfile (CORE_ADDR addr, const struct objfile *objfile);
 
-/* Return true if ADDRESS maps into one of the sections of the
-   userloaded ("add-symbol-file") objfiles of PSPACE and false
-   otherwise.  */
+/* Return true if ADDRESS maps into one of the sections of a
+   OBJF_SHARED objfile of PSPACE and false otherwise.  */
 
-extern int userloaded_objfile_contains_address_p (struct program_space *pspace,
-						  CORE_ADDR address);
+extern int shared_objfile_contains_address_p (struct program_space *pspace,
+					      CORE_ADDR address);
 
 /* This operation deletes all objfile entries that represent solibs that
    weren't explicitly loaded by the user, via e.g., the add-symbol-file
diff --git a/gdb/symfile.c b/gdb/symfile.c
index 7ad4a44..5b94797 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -2262,7 +2262,7 @@ add_symbol_file_command (char *args, int from_tty)
 {
   struct gdbarch *gdbarch = get_current_arch ();
   char *filename = NULL;
-  int flags = OBJF_USERLOADED;
+  int flags = OBJF_USERLOADED | OBJF_SHARED;
   char *arg;
   int section_index = 0;
   int argcnt = 0;
@@ -2445,8 +2445,8 @@ remove_symbol_file_command (char *args, int from_tty)
 
       ALL_OBJFILES (objf)
 	{
-	  if (objf != 0
-	      && objf->flags & OBJF_USERLOADED
+	  if ((objf->flags & OBJF_USERLOADED) != 0
+	      && (objf->flags & OBJF_SHARED) != 0
 	      && objf->pspace == pspace && is_addr_in_objfile (addr, objf))
 	    break;
 	}
@@ -2464,8 +2464,8 @@ remove_symbol_file_command (char *args, int from_tty)
 
       ALL_OBJFILES (objf)
 	{
-	  if (objf != 0
-	      && objf->flags & OBJF_USERLOADED
+	  if ((objf->flags & OBJF_USERLOADED) != 0
+	      && (objf->flags & OBJF_SHARED) != 0
 	      && objf->pspace == pspace
 	      && filename_cmp (filename, objfile_name (objf)) == 0)
 	    break;
diff --git a/gdb/testsuite/gdb.base/break-main-file-remove-fail.c b/gdb/testsuite/gdb.base/break-main-file-remove-fail.c
new file mode 100644
index 0000000..8d89b6b
--- /dev/null
+++ b/gdb/testsuite/gdb.base/break-main-file-remove-fail.c
@@ -0,0 +1,46 @@
+/* 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/>.  */
+
+#include <unistd.h>
+#include <sys/mman.h>
+
+size_t pg_size;
+
+void
+start (void)
+{
+}
+
+void
+foo (void)
+{
+}
+
+int
+main (void)
+{
+  pg_size = getpagesize ();
+
+  /* This just makes sure the test fails to compile (and is therefore
+     skipped) on targets that don't have munmap.  */
+  munmap (0, 0);
+
+  start ();
+  foo ();
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/break-main-file-remove-fail.exp b/gdb/testsuite/gdb.base/break-main-file-remove-fail.exp
new file mode 100644
index 0000000..395cf97
--- /dev/null
+++ b/gdb/testsuite/gdb.base/break-main-file-remove-fail.exp
@@ -0,0 +1,106 @@
+# 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/>.  */
+
+# Test that GDB isn't silent if it fails to remove a breakpoint from
+# the main program, independently of whether the program was loaded
+# with "file PROGRAM" or directly from the command line with "gdb
+# PROGRAM".
+
+standard_testfile
+
+if {[build_executable "failed to prepare" $testfile $srcfile debug]} {
+    return -1
+}
+
+# Run the test proper.  INITIAL_LOAD determines whether the program is
+# initially loaded by the "file" command or by passing it to GDB on
+# the command line.
+proc test_remove_bp { initial_load } {
+    with_test_prefix "$initial_load" {
+	global srcdir subdir binfile
+	global gdb_prompt hex
+	global GDBFLAGS
+
+	gdb_exit
+
+	set saved_gdbflags $GDBFLAGS
+
+	# See "used to behave differently" further below.
+	if { $initial_load == "file" } {
+	    gdb_start
+	    gdb_file_cmd $binfile
+	} else {
+	    global last_loaded_file
+
+	    # gdb_file_cmd sets this.  This is what gdb_reload
+	    # implementations use as binary.
+	    set last_loaded_file $binfile
+
+	    set GDBFLAGS "$GDBFLAGS $binfile"
+	    gdb_start
+	}
+	gdb_reinitialize_dir $srcdir/$subdir
+	gdb_reload
+	set GDBFLAGS $saved_gdbflags
+
+	if ![runto start] {
+	    fail "Can't run to start"
+	    return
+	}
+
+	delete_breakpoints
+
+	# So we can easily control when are breakpoints removed.
+	gdb_test_no_output "set breakpoint always-inserted on"
+
+	set bp_addr ""
+
+	set test "break foo"
+	gdb_test_multiple $test $test {
+	    -re "Breakpoint .* at ($hex).*$gdb_prompt $" {
+		set bp_addr $expect_out(1,string)
+		pass $test
+	    }
+	}
+
+	if {$bp_addr == ""} {
+	    unsupported "can't extract foo's address"
+	    return
+	}
+
+	gdb_test "info break" "y.*$hex.*in foo at.*" \
+	    "breakpoint is set"
+
+	# Now unmap the page where the breakpoint is set.  Trying to
+	# remove the memory breakpoint afterwards should fail, and GDB
+	# should warn the user about it.
+	set pagesize [get_integer_valueof "pg_size" 0]
+	set align_addr [expr $bp_addr - $bp_addr % $pagesize]
+	set munmap [get_integer_valueof "munmap ($align_addr, $pagesize)" -1]
+
+	if {$munmap != 0} {
+	    unsupported "can't munmap foo's page"
+	    return
+	}
+
+	gdb_test "delete \$bpnum" \
+	    "warning: Error removing breakpoint .*" \
+	    "failure to remove breakpoint warns"
+    }
+}
+
+foreach initial_load { "cmdline" "file" } {
+    test_remove_bp $initial_load
+}
diff --git a/gdb/testsuite/gdb.base/break-unload-file.exp b/gdb/testsuite/gdb.base/break-unload-file.exp
index 342bcf5..20762bb 100644
--- a/gdb/testsuite/gdb.base/break-unload-file.exp
+++ b/gdb/testsuite/gdb.base/break-unload-file.exp
@@ -18,24 +18,46 @@
 
 standard_testfile
 
-if {[prepare_for_testing "failed to prepare" $testfile $srcfile debug]} {
+if {[build_executable "failed to prepare" $testfile $srcfile debug]} {
     return -1
 }
 
-if ![runto_main] then {
-    fail "Can't run to main"
-    return 0
-}
-
-# Run the test proper.  ALWAYS_INSERT determines whether
-# always-inserted mode is on/off, and BREAK_COMMAND is the break
-# command being tested.
+# Run the test proper.  INITIAL_LOAD determines whether the program is
+# initially loaded by the "file" command or by passing it to GDB on
+# the command line.  ALWAYS_INSERT determines whether always-inserted
+# mode is on/off.  BREAK_COMMAND is the break command being tested.
 #
-proc test_break { always_inserted break_command } {
-    global gdb_prompt binfile hex
+proc test_break { initial_load always_inserted break_command } {
+    global srcdir subdir binfile
+    global gdb_prompt hex
+    global GDBFLAGS
+
+    append prefix "$initial_load: "
+    append prefix "always-inserted $always_inserted: "
+    append prefix "$break_command"
+    with_test_prefix "$prefix" {
+	gdb_exit
+
+	set saved_gdbflags $GDBFLAGS
+
+	# See "used to behave differently" further below.
+	if { $initial_load == "file" } {
+	    gdb_start
+	    gdb_file_cmd $binfile
+	} else {
+	    global last_loaded_file
+
+	    # gdb_file_cmd sets this.  This is what gdb_reload
+	    # implementations use as binary.
+	    set last_loaded_file $binfile
+
+	    set GDBFLAGS "$GDBFLAGS $binfile"
+	    gdb_start
+	}
 
-    with_test_prefix "always-inserted $always_inserted: $break_command" {
-	clean_restart $binfile
+	gdb_reinitialize_dir $srcdir/$subdir
+	gdb_reload
+	set GDBFLAGS $saved_gdbflags
 
 	if ![runto_main] then {
 	    fail "Can't run to main"
@@ -88,8 +110,12 @@ proc test_break { always_inserted break_command } {
 	    }
 	}
 
-	gdb_test "info break" "y.*PENDING.*foo" \
-	    "breakpoint is pending"
+	# This test used to behave differently depending on whether
+	# the program was first loaded through "file PROGRAM" or "gdb
+	# PROGRAM".
+	set ws "\[ \t\]"
+	gdb_test "info break" "breakpoint${ws}+keep${ws}+n${ws}+$hex${ws}*" \
+	    "breakpoint is disabled"
 
 	# Now delete the breakpoint from GDB's tables, to make sure
 	# GDB doesn't reinsert it, masking the bug (with the bug, on
@@ -118,11 +144,14 @@ proc test_break { always_inserted break_command } {
     }
 }
 
-# While it doesn't trigger the original bug this is a regression test
-# for, test with breakpoint always-inserted off for extra coverage.
-foreach always_inserted { "off" "on" } {
-    test_break $always_inserted "break"
-    if {![skip_hw_breakpoint_tests]} {
-	test_break $always_inserted "hbreak"
+foreach initial_load { "cmdline" "file" } {
+    # While it doesn't trigger the original bug this is a regression
+    # test for, test with breakpoint always-inserted off for extra
+    # coverage.
+    foreach always_inserted { "off" "on" } {
+	test_break $initial_load $always_inserted "break"
+	if {![skip_hw_breakpoint_tests]} {
+	    test_break $initial_load $always_inserted "hbreak"
+	}
     }
 }
