Make exec-file-mismatch compare build IDs
[deliverable/binutils-gdb.git] / gdb / exec.c
index a2added5e2295ea8cc8558bbe8fdb3b2d638274f..932270a000d0585374414ce4f46e4cd1690705ab 100644 (file)
@@ -37,6 +37,7 @@
 #include "gdb_bfd.h"
 #include "gcore.h"
 #include "source.h"
+#include "build-id.h"
 
 #include <fcntl.h>
 #include "readline/tilde.h"
@@ -247,20 +248,54 @@ validate_exec_file (int from_tty)
   struct inferior *inf = current_inferior ();
   /* Try to determine a filename from the process itself.  */
   const char *pid_exec_file = target_pid_to_exec_file (inf->pid);
+  bool build_id_mismatch = false;
 
-  /* If wee cannot validate the exec file, return.  */
+  /* If we cannot validate the exec file, return.  */
   if (current_exec_file == NULL || pid_exec_file == NULL)
     return;
 
-  std::string exec_file_target (pid_exec_file);
+  /* Try validating via build-id, if available.  This is the most
+     reliable check.  */
+  const bfd_build_id *exec_file_build_id = build_id_bfd_get (exec_bfd);
+  if (exec_file_build_id != nullptr)
+    {
+      /* Prepend the target prefix, to force gdb_bfd_open to open the
+        file on the remote file system (if indeed remote).  */
+      std::string target_pid_exec_file
+       = std::string (TARGET_SYSROOT_PREFIX) + pid_exec_file;
+
+      gdb_bfd_ref_ptr abfd (gdb_bfd_open (target_pid_exec_file.c_str (),
+                                         gnutarget, -1, false));
+      if (abfd != nullptr)
+       {
+         const bfd_build_id *target_exec_file_build_id
+           = build_id_bfd_get (abfd.get ());
 
-  /* 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 (target_exec_file_build_id != nullptr)
+           {
+             if (exec_file_build_id->size == target_exec_file_build_id->size
+                 && memcmp (exec_file_build_id->data,
+                            target_exec_file_build_id->data,
+                            exec_file_build_id->size) == 0)
+               {
+                 /* Match.  */
+                 return;
+               }
+             else
+               build_id_mismatch = true;
+           }
+       }
+    }
 
-  if (exec_file_target != current_exec_file)
+  if (build_id_mismatch)
     {
+      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;
+
       warning
        (_("Mismatch between current exec-file %ps\n"
           "and automatically determined exec-file %ps\n"
@@ -1215,8 +1250,8 @@ Set exec-file-mismatch handling (ask|warn|off)."),
                        _("\
 Show exec-file-mismatch handling (ask|warn|off)."),
                        _("\
-Specifies how to handle a mismatch between the current exec-file name\n\
-loaded by GDB and the exec-file name automatically determined when attaching\n\
+Specifies how to handle a mismatch between the current exec-file\n\
+loaded by GDB and the exec-file automatically determined when attaching\n\
 to a process:\n\n\
  ask  - warn the user and ask whether to load the determined exec-file.\n\
  warn - warn the user, but do not change the exec-file.\n\
This page took 0.025903 seconds and 4 git commands to generate.