This is the mail archive of the gdb-patches@sources.redhat.com 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]

unwind support for Linux 2.6 vsyscall DSO


In the past (during this spring and summer) there were some discussions
about the need to find unwind info in the vsyscall DSO image implicitly
loaded in processes on Linux 2.5/2.6 on some platforms.  I honestly don't
recall which mailing lists this was on.  If people are not clear on the
issues, I can try to dig up the various summaries of the details I have
posted before.  This was tabled for a while when I had other priorities
since it didn't turn out to be an issue with any kernel version used by
Red Hat production systems.

Now Linux 2.6 is getting firmed up, and it's time to revisit this.  On
Linux 2.6 kernels, backtraces from programs stopped in system calls do not
work using current glibc on x86 and AMD64 machines.  The same issue exists
on IA64 in Linux 2.6, and glibc will before long make use of the feature so
that system call backtraces need the same solutions for IA64.

My changes to export the auxv information in core dumps and /proc are now
making their way into Linux 2.6, and this gives us the tools we need to
solve the problem in gdb.

The following patches are some kludges I have tried out.  They are not fit
for inclusion, but demonstrate what needs to be done.  I hope they can
stimulate some advice on where such code should actually go.

This patch relies on the symbol_file_add_from_memory function introduced by
the patch I just posted a little earlier.  Please review that patch first
as context for what I'm doing here.  With that patch plus this one, on a Linux
2.6 kernel with the very latest patches you surely don't have quite yet, a
backtrace starting in the vsyscall entry point is unwound correctly from a
core file and when using attach.

Basically what needs to happen is a few places that should implicitly call
symbol_file_add_from_memory on the address the kernel supplied with the
AT_SYSINFO_EHDR tag on process startup.  On examining a core file, the
NT_AUXV note contains this info, and BFD makes it available as a ".auxv"
fake section.  On running or attaching to a live process, the
/proc/PID/auxv fake file provided by the target kernel contains the info.  

The auxv_parse function below does the work of interpreting the auxv block
(from a core file's NT_AUXV/.auxv or from /proc/PID/auxv).  That little bit
of code is about right as it is.  The issues are when to call it.

Questions for the core file case:

1 Where should this call go in the order of operations?  

  I plopped the check in the middle of core_open because it seemed like it
  ought to come between the bfd opening and the register diddling that
  includes some calls about the grokking of the stack frame.  I don't know
  how loading a symfile interacts with that diddling.  Would it work to
  have the symbol_file_add_from_memory done after core_open?

2 Where should this support go in the target/generic code split?

  This code, and the need for it, is Linux-specific but not machine-specific.
  Linux 2.6 currently requires it on x86, IA64, and AMD64 (in both native and
  IA32 emulation versions).  The user-level support for the preloaded DSO
  image is machine-independent in the glibc implementation; no other Linux
  platform will overload the AT_SYSINFO_EHDR tag value for another purpose.
  I would like to have this implemented in gdb in a place that doesn't
  require duplication for the three existing platforms requiring the support,
  and will cover any other Linux target where kernels start using the same
  feature.  I don't see any obvious place like a common linux-tdep.c; where
  is the right place?  Should it be a different to_core_open hook that wraps
  the generic one?  Or maybe extend struct core_fns?  (But core_fns is
  redefined only in machine-specific files, and it appears inconsistently
  so--sometimes in *-nat.c and sometimes in *-tdep.c; what's the story?)

3 When and how should I unload the symbols on detaching from the core file?

  The solib symbols are cleared in core_close from what I can see.
  Is that the right spot to drop the symfile added from reading NT_AUXV?
  How do I clear it all out properly?  Do I just call free_objfile?
  Is remove_target_sections required as clear_solib does?

Similar questions for the live process case:

4 Where to make the call?

  The patch below does it in linux-nat.c's child_post_attach.  That makes
  it work for attach, but it is probably the wrong place.  I really have
  no idea where the right place to insert this is for the "run" case.  It
  needs to happen after the break-on-exec, the same time you would first
  insert breakpoints in the program.  Where is the right place to make
  that happen?  Is there one place that's right for both run and attach?

5 Same as #2, in context.

  linux-nat.c seems like it ought to be the right source file for the
  /proc parsing, or perhaps linux-proc.c; the auxv_parse function
  (renamed) should be shared between the core and live handling cases, it
  belongs in a linux-tdep sort of file logically.  

6 Same as #3, in context.

  I can't figure out where things get cleared out when a process dies or
  you detach.  Do they?  I see objfile_purge_solibs is called from
  run_command.  I think that will get the symfile I create.  Is that
  sufficient?  Do solibs get cleared on detach/attach?



Thanks,
Roland


Index: corelow.c
===================================================================
RCS file: /cvs/src/src/gdb/corelow.c,v
retrieving revision 1.30
diff -p -b -u -r1.30 corelow.c
--- corelow.c	21 Sep 2003 01:26:44 -0000	1.30
+++ corelow.c	3 Oct 2003 05:39:55 -0000
@@ -252,6 +252,63 @@ add_to_thread_list (bfd *abfd, asection 
     inferior_ptid = pid_to_ptid (thread_id);	/* Yes, make it current */
 }
 
+#include <elf/common.h>
+#include <elf/external.h>
+
+int
+auxv_parse (bfd *abfd, char *contents, bfd_size_type size, int from_tty)
+{
+  bfd_vma sysinfo_ehdr = 0;
+
+  switch (bfd_arch_bits_per_address (abfd))
+    {
+    default:
+      return 0;
+
+    case 32:
+      {
+	Elf32_External_Auxv *av;
+	for (av = (Elf32_External_Auxv *) contents;
+	     (char *) av < contents + size;
+	     ++av)
+	  {
+	    const bfd_vma type = bfd_get_32 (abfd, av->a_type);
+	    if (type == AT_NULL)
+	      break;
+	    if (type == AT_SYSINFO_EHDR)
+	      {
+		sysinfo_ehdr = bfd_get_32 (abfd, av->a_val);
+		break;
+	      }
+	  }
+	break;
+      }
+    case 64:
+      {
+	Elf64_External_Auxv *av;
+	for (av = (Elf64_External_Auxv *) contents;
+	     (char *) av < contents + size;
+	     ++av)
+	  {
+	    const bfd_vma type = bfd_get_64 (abfd, av->a_type);
+	    if (type == AT_NULL)
+	      break;
+	    if (type == AT_SYSINFO_EHDR)
+	      {
+		sysinfo_ehdr = bfd_get_64 (abfd, av->a_val);
+		break;
+	      }
+	  }
+	break;
+      }
+    }
+
+  if (sysinfo_ehdr != 0)
+    (void) symbol_file_add_from_memory (abfd, sysinfo_ehdr, from_tty);
+
+  return 1;
+}
+
 /* This routine opens and sets up the core file bfd.  */
 
 static void
@@ -264,6 +321,7 @@ core_open (char *filename, int from_tty)
   bfd *temp_bfd;
   int ontop;
   int scratch_chan;
+  asection *section;
 
   target_preopen (from_tty);
   if (!filename)
@@ -344,6 +402,22 @@ core_open (char *filename, int from_tty)
     printf_filtered ("Program terminated with signal %d, %s.\n", siggy,
 		     target_signal_to_string (target_signal_from_host (siggy)));
 
+  section = bfd_get_section_by_name (core_bfd, ".auxv");
+  if (section != NULL)
+    {
+      bfd_size_type size;
+      char *contents;
+      size = bfd_section_size (core_bfd, section);
+      contents = alloca (size);
+      if (! bfd_get_section_contents (core_bfd, section, contents,
+				      (file_ptr) 0, size))
+	warning ("Couldn't read NT_AUXV note in core file.");
+      else
+	{
+	  auxv_parse (core_bfd, contents, size, from_tty);
+	}
+    }
+
   /* Build up thread list from BFD sections. */
 
   init_thread_list ();
Index: linux-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/linux-nat.c,v
retrieving revision 1.5
diff -p -b -u -r1.5 linux-nat.c
--- linux-nat.c	17 Aug 2003 20:17:02 -0000	1.5
+++ linux-nat.c	3 Oct 2003 05:39:56 -0000
@@ -24,6 +24,7 @@
 
 #include "gdb_wait.h"
 #include <sys/ptrace.h>
+#include <fcntl.h>
 
 #include "linux-nat.h"
 
@@ -234,10 +235,30 @@ linux_enable_event_reporting (ptid_t pti
   ptrace (PTRACE_SETOPTIONS, pid, 0, options);
 }
 
+static void
+linux_add_sysinfo_symbols (int pid)
+{
+  extern bfd *exec_bfd;		/* exec.c */
+  char filename[64];
+  int fd;
+  char contents[1024];
+  int size;
+
+  sprintf (filename, "/proc/%d/auxv", pid);
+  fd = open (filename, O_RDONLY);
+  if (fd < 0)
+    return;
+  size = read (fd, contents, sizeof contents);
+  close (fd);
+
+  auxv_parse (exec_bfd, contents, size, 0);
+}
+
 void
 child_post_attach (int pid)
 {
   linux_enable_event_reporting (pid_to_ptid (pid));
+  linux_add_sysinfo_symbols (pid);
 }
 
 void


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