This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[gdbserver] Detecting 64-bit-ness of inferior, when executable has already been deleted


With a few changes, I've gotten break-interp.exp to pass cleanly against a local
extended-remote gdbserver.  Currently, it fails badly (hundreds of FAILs/timeouts).

A problem with gdbserver the test revealed, is related to attaching to a process
after its executable has been deleted.  The symptom as seem from the gdb.log
is:

 warning: Selected architecture i386:x86-64 is not compatible with reported target architecture i386
 warning: Architecture rejected target-supplied description
 ...
 FAIL: ...

This shows up, while all the executables the test produces, are 64-bit on a 64-bit machine.

Turns out that the problem is that to figure out the architecture of the inferior,
gdbserver checks to see if the executable it is running is elf64 or elf32.  But
to do that, it tries to open the target of the /proc/PID/exe symlink, instead of
opening /proc/PID/exe directly, and that doesn't work when the original executable
file has been deleted already.

$ cp /bin/sleep ~/
$ ~/sleep 10000&
[1] 1480
$ readlink /proc/1480/exe
/home/pedro/sleep
$ rm ~/sleep
$ readlink /proc/1480/exe
/home/pedro/sleep (deleted)

And opening "/home/pedro/sleep (deleted)" of course fails.

The fix is to open/read /proc/PID/exe directly, like below.

Tested on x86_64 Fedora 16, and applied.

2012-01-27  Pedro Alves  <palves@redhat.com>

	* linux-low.c (linux_child_pid_to_exec_file): Delete.
	(elf_64_file_p): Make static.
	(linux_pid_exe_is_elf_64_file): New.
	* linux-low.h (linux_child_pid_to_exec_file, elf_64_file_p):
	Delete declarations.
	(linux_pid_exe_is_elf_64_file): Declare.
	* linux-x86-low.c (x86_arch_setup): Use
	linux_pid_exe_is_elf_64_file.
---
 gdb/gdbserver/linux-low.c     |   40 +++++++++++++---------------------------
 gdb/gdbserver/linux-low.h     |    3 +--
 gdb/gdbserver/linux-x86-low.c |    5 +----
 3 files changed, 15 insertions(+), 33 deletions(-)

diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 45aeb73..0a8b3de 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -186,32 +186,6 @@ static int linux_event_pipe[2] = { -1, -1 };
 static void send_sigstop (struct lwp_info *lwp);
 static void wait_for_sigstop (struct inferior_list_entry *entry);

-/* Accepts an integer PID; Returns a string representing a file that
-   can be opened to get info for the child process.
-   Space for the result is malloc'd, caller must free.  */
-
-char *
-linux_child_pid_to_exec_file (int pid)
-{
-  char *name1, *name2;
-
-  name1 = xmalloc (MAXPATHLEN);
-  name2 = xmalloc (MAXPATHLEN);
-  memset (name2, 0, MAXPATHLEN);
-
-  sprintf (name1, "/proc/%d/exe", pid);
-  if (readlink (name1, name2, MAXPATHLEN) > 0)
-    {
-      free (name1);
-      return name2;
-    }
-  else
-    {
-      free (name2);
-      return name1;
-    }
-}
-
 /* Return non-zero if HEADER is a 64-bit ELF file.  */

 static int
@@ -228,7 +202,7 @@ elf_64_header_p (const Elf64_Ehdr *header)
    zero if the file is not a 64-bit ELF file,
    and -1 if the file is not accessible or doesn't exist.  */

-int
+static int
 elf_64_file_p (const char *file)
 {
   Elf64_Ehdr header;
@@ -248,6 +222,18 @@ elf_64_file_p (const char *file)
   return elf_64_header_p (&header);
 }

+/* Accepts an integer PID; Returns true if the executable PID is
+   running is a 64-bit ELF file..  */
+
+int
+linux_pid_exe_is_elf_64_file (int pid)
+{
+  char file[MAXPATHLEN];
+
+  sprintf (file, "/proc/%d/exe", pid);
+  return elf_64_file_p (file);
+}
+
 static void
 delete_lwp (struct lwp_info *lwp)
 {
diff --git a/gdb/gdbserver/linux-low.h b/gdb/gdbserver/linux-low.h
index 2befc48..3ba004c 100644
--- a/gdb/gdbserver/linux-low.h
+++ b/gdb/gdbserver/linux-low.h
@@ -265,8 +265,7 @@ struct lwp_info

 extern struct inferior_list all_lwps;

-char *linux_child_pid_to_exec_file (int pid);
-int elf_64_file_p (const char *file);
+int linux_pid_exe_is_elf_64_file (int pid);

 void linux_attach_lwp (unsigned long pid);
 struct lwp_info *find_lwp_pid (ptid_t ptid);
diff --git a/gdb/gdbserver/linux-x86-low.c b/gdb/gdbserver/linux-x86-low.c
index 5e4f87a..365cd52 100644
--- a/gdb/gdbserver/linux-x86-low.c
+++ b/gdb/gdbserver/linux-x86-low.c
@@ -1106,10 +1106,7 @@ x86_arch_setup (void)
 {
 #ifdef __x86_64__
   int pid = pid_of (get_thread_lwp (current_inferior));
-  char *file = linux_child_pid_to_exec_file (pid);
-  int use_64bit = elf_64_file_p (file);
-
-  free (file);
+  int use_64bit = linux_pid_exe_is_elf_64_file (pid);

   if (use_64bit < 0)
     {


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]