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]

Re: unwind support for Linux 2.6 vsyscall DSO


Here is an alternate version of my patch, omitting the Solaris parts.  This
uses an iterator interface as you requested.  I didn't add a utility
function but duplicated the code that might be in one.  This also works
(writes a good NT_AUXV note), but the core file writing additions are now
rather clunky, and that code has to be duplicated for Solaris (or factored
out).  I prefer the first version.


Thanks,
Roland


Index: target.c
===================================================================
RCS file: /cvs/src/src/gdb/target.c,v
retrieving revision 1.55
diff -b -p -u -r1.55 target.c
--- target.c	2 Oct 2003 20:28:30 -0000	1.55
+++ target.c	7 Oct 2003 03:29:27 -0000
@@ -624,6 +624,7 @@ update_current_target (void)
       INHERIT (to_async, t);
       INHERIT (to_async_mask_value, t);
       INHERIT (to_find_memory_regions, t);
+      INHERIT (to_read_aux_vector, t);
       INHERIT (to_make_corefile_notes, t);
       INHERIT (to_get_thread_local_address, t);
       INHERIT (to_magic, t);
@@ -1500,6 +1501,13 @@ static int dummy_find_memory_regions (in
   return 0;
 }
 
+/* Error-catcher for target_read_aux_vector */
+static int dummy_read_aux_vector (int (*ignore1) (), void *ignore2)
+{
+  error ("No target.");
+  return 0;
+}
+
 /* Error-catcher for target_make_corefile_notes */
 static char * dummy_make_corefile_notes (bfd *ignore1, int *ignore2)
 {
@@ -1521,6 +1529,7 @@ init_dummy_target (void)
   dummy_target.to_pid_to_str = normal_pid_to_str;
   dummy_target.to_stratum = dummy_stratum;
   dummy_target.to_find_memory_regions = dummy_find_memory_regions;
+  dummy_target.to_read_aux_vector = dummy_read_aux_vector;
   dummy_target.to_make_corefile_notes = dummy_make_corefile_notes;
   dummy_target.to_magic = OPS_MAGIC;
 }
Index: target.h
===================================================================
RCS file: /cvs/src/src/gdb/target.h,v
retrieving revision 1.41
diff -b -p -u -r1.41 target.h
--- target.h	17 Jun 2003 20:28:13 -0000	1.41
+++ target.h	7 Oct 2003 03:29:27 -0000
@@ -322,6 +322,7 @@ struct target_ops
 					    int, int, int, 
 					    void *), 
 				   void *);
+    int (*to_read_aux_vector) (int (*) (const void *, void *), void *);
     char * (*to_make_corefile_notes) (bfd *, int *);
 
     /* Return the thread-local address at OFFSET in the
@@ -939,6 +940,14 @@ extern void (*target_new_objfile_hook) (
      (current_target.to_find_memory_regions) (FUNC, DATA)
 
 /*
+ * Function to read target startup auxilliary vector (ELF-specific).
+ * Returns a malloc'd buffer of ELF auxv data, and sets *LENP to its size.
+ */
+
+#define target_read_aux_vector(FUNC, DATA) \
+     (current_target.to_read_aux_vector) (FUNC, DATA)
+
+/*
  * Compose corefile .note section.
  */
 
Index: inftarg.c
===================================================================
RCS file: /cvs/src/src/gdb/inftarg.c,v
retrieving revision 1.18
diff -b -p -u -r1.18 inftarg.c
--- inftarg.c	21 Sep 2003 01:26:45 -0000	1.18
+++ inftarg.c	7 Oct 2003 03:29:27 -0000
@@ -628,6 +628,14 @@ inftarg_set_find_memory_regions (int (*f
   child_ops.to_find_memory_regions = func;
 }
 
+/* Take over the 'read_aux_vector' vector from inftarg.c. */
+void
+inftarg_set_read_aux_vector (int (*func) (int (*) (const void *, void *),
+					  void *))
+{
+  child_ops.to_read_aux_vector = func;
+}
+
 /* Take over the 'make_corefile_notes' vector from inftarg.c. */
 extern void 
 inftarg_set_make_corefile_notes (char * (*func) (bfd *, int *))
Index: linux-proc.c
===================================================================
RCS file: /cvs/src/src/gdb/linux-proc.c,v
retrieving revision 1.20
diff -b -p -u -r1.20 linux-proc.c
--- linux-proc.c	1 Oct 2003 20:36:56 -0000	1.20
+++ linux-proc.c	7 Oct 2003 03:29:27 -0000
@@ -161,6 +161,72 @@ linux_find_memory_regions (int (*func) (
   return 0;
 }
 
+static int
+procfs_read_aux_vector (int (*func) (const Elf_Internal_Auxv *, void *),
+			void *data)
+{
+  char pathname[MAXPATHLEN];
+  union
+  {
+    Elf32_External_Auxv av32[20];
+    Elf64_External_Auxv av64[10];
+  } buf;
+  int fd, n, ret;
+
+  sprintf (pathname, "/proc/%d/auxv", PIDGET (inferior_ptid));
+  fd = open (pathname, O_RDONLY);
+  if (fd < 0)
+    return 0;			/* XXX Call error here? */
+
+  ret = 0;
+  while (1)
+    {
+      n = read (fd, &buf, sizeof buf);
+      if (n <= 0)		/* Hit EOF or read error.  */
+	return 0;
+
+      switch (bfd_arch_bits_per_address (exec_bfd))
+	{
+	default:
+	  break;
+
+	case 32:
+	  {
+	    const Elf32_External_Auxv *av;
+	    for (av = buf.av32; (char *) av < (char *) &buf + n; ++av)
+	      {
+		Elf_Internal_Auxv elt;
+		elt.a_type = bfd_get_32 (exec_bfd, av->a_type);
+		elt.a_val = bfd_get_32 (exec_bfd, av->a_val);
+		ret = (*func) (&elt, data);
+		if (ret != 0)
+		  break;
+	      }
+	    continue;
+	  }
+	case 64:
+	  {
+	    const Elf64_External_Auxv *av;
+	    for (av = buf.av64; (char *) av < (char *) &buf + n; ++av)
+	      {
+		Elf_Internal_Auxv elt;
+		elt.a_type = bfd_get_64 (exec_bfd, av->a_type);
+		elt.a_val = bfd_get_64 (exec_bfd, av->a_val);
+		ret = (*func) (&elt, data);
+		if (ret != 0)
+		  break;
+	      }
+	    continue;
+	  }
+	}
+
+      break;
+    }
+
+  close (fd);
+  return ret;
+}
+
 /* Function: linux_do_thread_registers
  *
  * Records the thread's register state for the corefile note section.
@@ -255,6 +321,46 @@ linux_do_registers (bfd *obfd, ptid_t pt
   return note_data;
 }
 
+static int
+linux_auxv_count (const void *av, void *data)
+{
+  ++*(int *) data;
+  return 0;
+}
+
+static int
+linux_auxv_reconstruct (const void *internal, void *data)
+{
+  const Elf_Internal_Auxv *av = internal;
+  bfd_byte **ptr = data;
+
+  switch (bfd_arch_bits_per_address (exec_bfd))
+    {
+    default:
+      break;
+
+    case 32:
+      {
+	bfd_put_32 (exec_bfd, av->a_type, *ptr);
+	*ptr += 4;
+	bfd_put_32 (exec_bfd, av->a_val, *ptr);
+	*ptr += 4;
+	break;
+      }
+
+    case 64:
+      {
+	bfd_put_64 (exec_bfd, av->a_type, *ptr);
+	*ptr += 8;
+	bfd_put_64 (exec_bfd, av->a_val, *ptr);
+	*ptr += 8;
+	break;
+      }
+    }
+
+  return 0;
+}
+
 /* Function: linux_make_note_section
  *
  * Fills the "to_make_corefile_note" target vector.
@@ -271,6 +377,7 @@ linux_make_note_section (bfd *obfd, int 
   char psargs[80] = { '\0' };
   char *note_data = NULL;
   ptid_t current_ptid = inferior_ptid;
+  int auxv_len;
 
   if (get_exec_file (0))
     {
@@ -305,6 +412,19 @@ linux_make_note_section (bfd *obfd, int 
       note_data = thread_args.note_data;
     }
 
+  auxv_len = 0;
+  target_read_aux_vector (linux_auxv_count, &auxv_len);
+  if (auxv_len != 0)
+    {
+      bfd_byte *auxv, *auxvptr;
+      auxv = alloca (auxv_len * 2
+		     * (bfd_arch_bits_per_address (exec_bfd) / 8));
+      auxvptr = auxv;
+      target_read_aux_vector (linux_auxv_reconstruct, &auxvptr);
+      note_data = elfcore_write_note (obfd, note_data, note_size,
+				      "CORE", NT_AUXV, auxv, auxvptr - auxv);
+    }
+
   make_cleanup (xfree, note_data);
   return note_data;
 }
@@ -593,9 +713,11 @@ _initialize_linux_proc (void)
 {
   extern void inftarg_set_find_memory_regions ();
   extern void inftarg_set_make_corefile_notes ();
+  extern void inftarg_set_read_aux_vector ();
 
   inftarg_set_find_memory_regions (linux_find_memory_regions);
   inftarg_set_make_corefile_notes (linux_make_note_section);
+  inftarg_set_read_aux_vector (procfs_read_aux_vector);
 
   add_info ("proc", linux_info_proc_cmd,
 	    "Show /proc process information about any running process.\n\
Index: corelow.c
===================================================================
RCS file: /cvs/src/src/gdb/corelow.c,v
retrieving revision 1.30
diff -b -p -u -r1.30 corelow.c
--- corelow.c	21 Sep 2003 01:26:44 -0000	1.30
+++ corelow.c	7 Oct 2003 03:29:27 -0000
@@ -474,6 +550,69 @@ core_files_info (struct target_ops *t)
   print_section_info (t, core_bfd);
 }
 
+static int
+core_read_aux_vector (int (*func) (const void *, void *), void *data)
+{
+  sec_ptr section;
+  bfd_size_type size;
+  char *contents;
+  int ret;
+
+  section = bfd_get_section_by_name (core_bfd, ".auxv");
+  if (section == NULL)
+    return 0;
+
+  size = bfd_section_size (core_bfd, section);
+  contents = (char *) 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.");
+      return 0;
+    }
+
+  switch (bfd_arch_bits_per_address (core_bfd))
+    {
+    default:
+      return 0;
+
+    case 32:
+      {
+	Elf32_External_Auxv *av;
+	for (av = (Elf32_External_Auxv *) contents;
+	     (char *) av < contents + size;
+	     ++av)
+	  {
+	    Elf_Internal_Auxv elt;
+	    elt.a_type = bfd_get_32 (core_bfd, av->a_type);
+	    elt.a_val = bfd_get_32 (core_bfd, av->a_val);
+	    ret = (*func) (&elt, data);
+	    if (ret != 0)
+	      return ret;
+	  }
+	break;
+      }
+    case 64:
+      {
+	Elf64_External_Auxv *av;
+	for (av = (Elf64_External_Auxv *) contents;
+	     (char *) av < contents + size;
+	     ++av)
+	  {
+	    Elf_Internal_Auxv elt;
+	    elt.a_type = bfd_get_64 (core_bfd, av->a_type);
+	    elt.a_val = bfd_get_64 (core_bfd, av->a_val);
+	    ret = (*func) (&elt, data);
+	    if (ret != 0)
+	      return ret;
+	  }
+	break;
+      }
+    }
+
+  return 0;
+}
+
 /* If mourn is being called in all the right places, this could be say
    `gdb internal error' (since generic_mourn calls breakpoint_init_inferior).  */
 
@@ -520,6 +659,7 @@ init_core_ops (void)
   core_ops.to_has_memory = 1;
   core_ops.to_has_stack = 1;
   core_ops.to_has_registers = 1;
+  core_ops.to_read_aux_vector = core_read_aux_vector;
   core_ops.to_magic = OPS_MAGIC;
 }


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