diff --git a/gdb/exec.c b/gdb/exec.c
index 6bdf9abb3e..3ff45c920c 100644
--- a/gdb/exec.c
+++ b/gdb/exec.c
@@ -82,6 +82,49 @@ struct exec_target final : public target_ops
 
 static exec_target exec_ops;
 
+/* How to handle a mismatch between the current exec file and the exec
+   file determined from target.  */
+
+static const char *const exec_file_mismatch_names[]
+  = {"reload", "warn", "off", NULL };
+enum exec_file_mismatch_mode
+  {
+    exec_file_mismatch_reload, exec_file_mismatch_warn, exec_file_mismatch_off
+  };
+static const char *exec_file_mismatch = exec_file_mismatch_names[0];
+enum exec_file_mismatch_mode exec_file_mismatch_mode = exec_file_mismatch_reload;
+
+/* Show command.  */
+static void
+show_exec_file_mismatch_command (struct ui_file *file, int from_tty,
+				 struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (gdb_stdout,
+		    _("exec-file-mismatch handling is currently \"%s\".\n"),
+		    exec_file_mismatch_names[exec_file_mismatch_mode]);
+}
+
+/* Set command.  Change the setting for range checking.  */
+static void
+set_exec_file_mismatch_command (const char *ignore,
+				int from_tty, struct cmd_list_element *c)
+{
+  for (enum exec_file_mismatch_mode mode = exec_file_mismatch_reload;
+       ;
+       mode = static_cast<enum exec_file_mismatch_mode>(1 + (int) mode))
+    {
+      if (strcmp (exec_file_mismatch, exec_file_mismatch_names[mode]) == 0)
+	{
+	  exec_file_mismatch_mode = mode;
+	  return;
+	}
+      if (mode == exec_file_mismatch_off)
+	internal_error (__FILE__, __LINE__,
+			_("Unrecognized exec-file-mismatch setting: \"%s\""),
+			exec_file_mismatch);
+    }
+}
+
 /* Whether to open exec and core files read-only or read-write.  */
 
 bool write_files = false;
@@ -191,6 +234,55 @@ try_open_exec_file (const char *exec_file_host, struct inferior *inf,
 
 /* See gdbcore.h.  */
 
+void
+validate_exec_file (int from_tty)
+{
+  if (exec_file_mismatch_mode == exec_file_mismatch_off)
+    return; /* User asked to do nothing.  */
+
+  char *current_exec_file = get_exec_file (0);
+  struct inferior *inf = current_inferior ();
+  /* Try to determine a filename from the process itself.  */
+  char *pid_exec_file = target_pid_to_exec_file (inf->pid);
+
+  if (current_exec_file == NULL || pid_exec_file == NULL)
+    return; /* We cannot validate the exec file.  */
+
+  std::string exec_file_target (pid_exec_file);
+
+  /* In case the exec file is not local, exec_file_target has to point at
+     the target file system.  */
+  if (is_target_filename (current_exec_file) && !target_filesystem_is_local ())
+    exec_file_target = TARGET_SYSROOT_PREFIX + exec_file_target;
+
+  if (strcmp (exec_file_target.c_str (), current_exec_file) != 0)
+    {
+      warning (_("Mismatch between current exec-file %s\n"
+		 "and automatically determined exec-file %s\n"
+		 "exec-file-mismatch handling is currently \"%s\""),
+	       current_exec_file, exec_file_target.c_str (),
+	       exec_file_mismatch_names[exec_file_mismatch_mode]);
+      if (exec_file_mismatch_mode == exec_file_mismatch_reload)
+	{
+	  symfile_add_flags add_flags = SYMFILE_MAINLINE;
+	  if (from_tty)
+	    add_flags |= SYMFILE_VERBOSE;
+	  try
+	    {
+	      symbol_file_add_main (exec_file_target.c_str (), add_flags);
+	      exec_file_attach (exec_file_target.c_str (), from_tty);
+	    }
+	  catch (gdb_exception_error &err)
+	    {
+	      warning (_("reloading %s %s"), exec_file_target.c_str (),
+		       err.message != NULL ? err.what () : "error");
+	    }
+	}
+    }
+}
+
+/* See gdbcore.h.  */
+
 void
 exec_file_locate_attach (int pid, int defer_bp_reset, int from_tty)
 {
@@ -1070,5 +1162,16 @@ Show writing into executable and core files."), NULL,
 			   show_write_files,
 			   &setlist, &showlist);
 
+  add_setshow_enum_cmd ("exec-file-mismatch", class_support,
+			exec_file_mismatch_names,
+			&exec_file_mismatch,
+			_("\
+Set exec-file-mismatch handling.   (reload/warn/off)"),
+			_("\
+Show exec-file-mismatch handling.  (reload/warn/off"),
+			NULL, set_exec_file_mismatch_command,
+			show_exec_file_mismatch_command,
+			&setlist, &showlist);
+
   add_target (exec_target_info, exec_target_open, filename_completer);
 }
diff --git a/gdb/gdbcore.h b/gdb/gdbcore.h
index cac91c097b..0f3c6aad95 100644
--- a/gdb/gdbcore.h
+++ b/gdb/gdbcore.h
@@ -157,6 +157,11 @@ extern void exec_file_locate_attach (int pid, int defer_bp_reset, int from_tty);
 
 extern void validate_files (void);
 
+/* Produce a warning if the current exec file does not match the exec
+   file determined from the target.  In case of mismatch, ask the user
+   if the exec file determined from target must be loaded.  */
+extern void validate_exec_file (int from_tty);
+
 /* The current default bfd target.  */
 
 extern char *gnutarget;
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 465d3a10e5..4ca092c44d 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -2563,6 +2563,9 @@ setup_inferior (int from_tty)
       reread_symbols ();
     }
 
+  /* Check for exec file mismatch, and let the user solve it.  */
+  validate_exec_file (from_tty);
+
   /* Take any necessary post-attaching actions for this platform.  */
   target_post_attach (inferior_ptid.pid ());
 
diff --git a/gdb/remote.c b/gdb/remote.c
index 5e1745db44..98346b321f 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -2380,6 +2380,9 @@ remote_target::remote_add_inferior (bool fake_pid_p, int pid, int attached,
   if (try_open_exec && get_exec_file (0) == NULL)
     exec_file_locate_attach (pid, 0, 1);
 
+  /* Check for exec file mismatch, and let the user solve it.  */
+  validate_exec_file (1);
+
   return inf;
 }
 
